test_upload.py 7.85 KB
Newer Older
1
#   test_upload.py — functional tests for package upload
2
#
3
4
#   This file is part of debexpo -
#   https://salsa.debian.org/mentors.debian.net-team/debexpo
5
#
Jonny Lamb's avatar
Jonny Lamb committed
6
#   Copyright © 2008 Jonny Lamb <jonny@debian.org>
7
#   Copyright © 2010 Jan Dittberner <jandd@debian.org>
8
#   Copyright © 2019 Baptiste Beauplat <lyknode@cilg.org>
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#
#   Permission is hereby granted, free of charge, to any person
#   obtaining a copy of this software and associated documentation
#   files (the "Software"), to deal in the Software without
#   restriction, including without limitation the rights to use,
#   copy, modify, merge, publish, distribute, sublicense, and/or sell
#   copies of the Software, and to permit persons to whom the
#   Software is furnished to do so, subject to the following
#   conditions:
#
#   The above copyright notice and this permission notice shall be
#   included in all copies or substantial portions of the Software.
#
#   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
#   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
#   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
#   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
#   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
#   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
#   OTHER DEALINGS IN THE SOFTWARE.

31
32
33
from logging import getLogger
import os
from tempfile import TemporaryDirectory
34

35
36
from django.conf import settings
from django.urls import reverse
37

38
from tests import TestController
39

40
log = getLogger(__name__)
Jonny Lamb's avatar
Jonny Lamb committed
41

42

Jonny Lamb's avatar
Jonny Lamb committed
43
44
class TestUploadController(TestController):

45
    _UNSIGNED_CHANGES_CONTENT = """
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
Format: 1.8
Date: Tue, 12 Mar 2019 17:31:31 +0100
Source: vitetris
Binary: vitetris vitetris-dbgsym
Architecture: source amd64
Version: 0.58.0-1
Distribution: unstable
Urgency: medium
Maintainer: Baptiste BEAUPLAT <lyknode@cilg.org>
Changed-By: Baptiste BEAUPLAT <lyknode@cilg.org>
Description:
 vitetris   - Virtual terminal *tris clone
Changes:
 vitetris (0.58.0-1) unstable; urgency=medium
 .
   * New upstream version 0.58.0
Checksums-Sha1:
63
 4a756ca07e9487f482465a99e8286abc86ba4dc7 1261 vitetris_0.58.0-1.dsc
64
Checksums-Sha256:
65
 d1b2a59fbea7e20077af9f91b27e95e865061b270be03ff539ab3b73587882e8 1261 vitetris_0.58.0-1.dsc
66
Files:
67
68
69
70
71
72
73
74
75
76
77
78
 98bf7d8c15784f0a3d63204441e1e2aa 1261 games optional vitetris_0.58.0-1.dsc
"""  # noqa: E501
    _CHANGES_CONTENT = f"""
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
{_UNSIGNED_CHANGES_CONTENT}-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQRVkwbu4cjBst0cc7HENHgc6HHz3wUCXfjpNAAKCRDENHgc6HHz
3yJ9AQC0U9bahPO/TH/4ULdsnBd0ECHCG6wJmvBBrrEsfxHjhwD9GlqAs6pTyoYZ
fC0rs1ly7CQ7ZQN441ZE3csnK69gzwc=
=1nnA
-----END PGP SIGNATURE-----
79
80
81
82
83
84
85
86
87
88
89
"""
    _CHANGES_CONTENT_SUBKEY = f"""
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
{_UNSIGNED_CHANGES_CONTENT}-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQSzz3sz+AdjONtPqA6HkZKDEXU71wUCXgkR1wAKCRCHkZKDEXU7
19RiAQDcC+i0jXdCo2+dY1QTtBY3072BhBD3uq5dT9XPaqYvOAEA8Pk7FdZReoLw
C7NQGzfRMFLSPxIHVzhHvJUo6vNZ+AA=
=FCEl
-----END PGP SIGNATURE-----
90
91
"""

92
    def setUp(self):
93
94
95
96
        self._setup_example_user(gpg=True)
        self.spool = TemporaryDirectory()
        self.old_spool = getattr(settings, 'UPLOAD_SPOOL', None)
        settings.UPLOAD_SPOOL = self.spool.name
97

98
    def tearDown(self):
99
        self._remove_example_user()
100
        settings.UPLOAD_SPOOL = self.old_spool
101

102
103
    def testGetRequest(self):
        """
104
105
        Tests whether requests where method != PUT are rejected with error code
        405.
106
        """
107
        response = self.client.get(reverse('upload', args=['testname.dsc']))
108

109
        self.assertEqual(response.status_code, 405)
110

111
112
    def testExtensionNotAllowed(self):
        """
113
114
        Tests whether uploads of an unknown file extensions are rejected with
        error code 403.
115
        """
116
        response = self.client.put(reverse('upload', args=['testname.unknown']))
117

118
        self.assertEqual(response.status_code, 403)
119
120
121

    def testSuccessfulUpload(self):
        """
122
123
        Tests whether uploads with sane file extensions and authorization are
        successful.
124
        """
125
126
        response = self.client.put(reverse('upload', args=['testfile2.dsc']),
                                   data='contents')
127

128
        self.assertEqual(response.status_code, 200)
129

130
131
132
        self.assertTrue(
            os.path.isfile(
                os.path.join(
133
134
                    settings.UPLOAD_SPOOL,
                    'incoming',
135
136
                    'testfile2.dsc')))

137
138
139
140
141
142
        with open(
            os.path.join(
                settings.UPLOAD_SPOOL,
                'incoming',
                'testfile2.dsc')) as fd:
            self.assertEqual(fd.read(), 'contents')
143

144
145
146
147
        if os.path.isfile(os.path.join(settings.UPLOAD_SPOOL,
                                       'incoming', 'testfile2.dsc')):
            os.remove(os.path.join(settings.UPLOAD_SPOOL,
                                   'incoming', 'testfile2.dsc'))
148

149
    def testDuplicatedUpload(self, with_subkey=False):
150
151
152
        """
        Tests whether a re-uploads of the same file failed with error code 403.
        """
153

154
155
156
157
158
        # Malicous changes does not break upload
        response = self.client.put(reverse(
            'upload',
            args=['plop.changes']),
            data='contents')
159

160
        self.assertEqual(response.status_code, 200)
161

162
163
164
165
166
167
        # Invalid changes does not break upload
        response = self.client.put(reverse(
            'upload',
            args=['plop.changes']),
            data=self._UNSIGNED_CHANGES_CONTENT.replace('Source: vitetris\n',
                                                        ''))
168

169
        self.assertEqual(response.status_code, 200)
170

171
172
173
174
175
        # First upload allowed
        response = self.client.put(reverse(
            'upload',
            args=['vitetris_0.58.0-1.dsc']),
            data='contents')
176

177
        self.assertEqual(response.status_code, 200)
178

179
180
181
182
183
        # Second upload allowed
        response = self.client.put(reverse(
            'upload',
            args=['vitetris_0.58.0-1.dsc']),
            data='contents')
184

185
        self.assertEqual(response.status_code, 200)
186

187
188
189
190
191
        if with_subkey:
            data = self._CHANGES_CONTENT_SUBKEY
        else:
            data = self._CHANGES_CONTENT

192
193
194
195
        # Upload a file not referenced allowed
        response = self.client.put(reverse(
            'upload',
            args=['testfile.changes']),
196
            data=data)
197

198
        self.assertEqual(response.status_code, 200)
199

200
201
202
203
        # Second upload denined (.changes)
        response = self.client.put(reverse(
            'upload',
            args=['testfile.changes']),
204
            data=data)
205

206
        self.assertEqual(response.status_code, 403)
207

208
209
210
211
212
        # Second upload denined (others)
        response = self.client.put(reverse(
            'upload',
            args=['vitetris_0.58.0-1.dsc']),
            data='contents')
213

214
        self.assertEqual(response.status_code, 403)
215

216
217
218
219
220
221
222
223
        # Next upload allowed
        response = self.client.put(reverse(
            'upload',
            args=['vitetris_0.58.0-2.dsc']),
            data='contents')

        self.assertEqual(response.status_code, 200)

224
225
226
227
228
229
        for filename in (os.path.join(settings.UPLOAD_SPOOL,
                                      'incoming', 'vitetris_0.58.0-1.dsc'),
                         os.path.join(settings.UPLOAD_SPOOL,
                                      'incoming', 'testfile.changes')):
            if os.path.isfile(filename):
                os.remove(filename)
230

231
232
233
        if not with_subkey:
            self.testDuplicatedUpload(True)

234
235
236
237
    def testUploadNonwritableQueue(self):
        """
        Tests whether an uploads with an nonwritable queue fails.
        """
238
        settings.UPLOAD_SPOOL = '/proc/sys'
239

240
241
242
243
        response = self.client.put(reverse(
            'upload',
            args=['testfile.dsc']),
            data='contents')
244

245
        self.assertEqual(response.status_code, 500)