Skip to content

Commit da5dc63

Browse files
Jon Wayne Parrottdstufft
Jon Wayne Parrott
authored andcommitted
Add ability for admins to set the upload limit on projects (#2470)
1 parent 5b057cf commit da5dc63

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

tests/unit/admin/views/test_projects.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,56 @@ def test_non_normalized_name(self, db_request):
342342
)
343343
with pytest.raises(HTTPMovedPermanently):
344344
views.journals_list(project, db_request)
345+
346+
347+
class TestProjectSetLimit:
348+
def test_sets_limitwith_integer(self, db_request):
349+
project = ProjectFactory.create(name="foo")
350+
351+
db_request.route_path = pretend.call_recorder(
352+
lambda *a, **kw: "/admin/projects/")
353+
db_request.session = pretend.stub(
354+
flash=pretend.call_recorder(lambda *a, **kw: None),
355+
)
356+
db_request.matchdict["project_name"] = project.normalized_name
357+
db_request.POST["upload_limit"] = "12345"
358+
359+
views.set_upload_limit(project, db_request)
360+
361+
assert db_request.session.flash.calls == [
362+
pretend.call(
363+
"Successfully set the upload limit on 'foo' to 12345",
364+
queue="success"),
365+
]
366+
367+
assert project.upload_limit == 12345
368+
369+
def test_sets_limit_with_none(self, db_request):
370+
project = ProjectFactory.create(name="foo")
371+
project.upload_limit = 12345
372+
373+
db_request.route_path = pretend.call_recorder(
374+
lambda *a, **kw: "/admin/projects/")
375+
db_request.session = pretend.stub(
376+
flash=pretend.call_recorder(lambda *a, **kw: None),
377+
)
378+
db_request.matchdict["project_name"] = project.normalized_name
379+
380+
views.set_upload_limit(project, db_request)
381+
382+
assert db_request.session.flash.calls == [
383+
pretend.call(
384+
"Successfully set the upload limit on 'foo' to None",
385+
queue="success"),
386+
]
387+
388+
assert project.upload_limit is None
389+
390+
def test_sets_limit_with_bad_value(self, db_request):
391+
project = ProjectFactory.create(name="foo")
392+
393+
db_request.matchdict["project_name"] = project.normalized_name
394+
db_request.POST["upload_limit"] = "meep"
395+
396+
with pytest.raises(HTTPBadRequest):
397+
views.set_upload_limit(project, db_request)

warehouse/admin/routes.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ def includeme(config):
5757
traverse="/{project_name}",
5858
domain=warehouse,
5959
)
60+
config.add_route(
61+
"admin.project.set_upload_limit",
62+
"/admin/projects/{project_name}/set_upload_limit/",
63+
factory="warehouse.packaging.models:ProjectFactory",
64+
traverse="/{project_name}",
65+
domain=warehouse,
66+
)
6067

6168
# Journal related Admin pages
6269
config.add_route(

warehouse/admin/templates/admin/projects/detail.html

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@
4646
<div class="box box-primary">
4747
<div class="box-body box-profile">
4848
<h3 class="project-name text-center">{{ project.name }}</h3>
49+
<div class="box-body box-attributes">
50+
<table class="table table-hover">
51+
<tr>
52+
<th>Attribute</th>
53+
<th>Value</th>
54+
</tr>
55+
<tr>
56+
<td>Upload limit</td>
57+
<td>{{ project.upload_limit }}</td>
58+
</tr>
59+
</table>
60+
</div>
4961
<div class="box-body box-maintainers">
5062
<table class="table table-hover">
5163
<tr>
@@ -108,6 +120,7 @@ <h3 class="project-name text-center">{{ project.name }}</h3>
108120
</div>
109121
</div>
110122
</div>
123+
<!-- Blacklist form -->
111124
<div class="box box-secondary collapsed-box">
112125
<div class="box-header with-border">
113126
<h3 class="box-title">Blacklist Project</h3>
@@ -132,4 +145,30 @@ <h3 class="box-title">Blacklist Project</h3>
132145
</div>
133146
</form>
134147
</div>
148+
149+
<!-- Upload limit form -->
150+
<div class="box box-secondary collapsed-box">
151+
<div class="box-header with-border">
152+
<h3 class="box-title">Set upload limit</h3>
153+
<div class="box-tools">
154+
<button class="btn btn-box-tool" data-widget="collapse" data-toggle="tooltip" title="Expand"><i class="fa fa-plus"></i></button>
155+
</div>
156+
</div>
157+
158+
<form method="POST" action="{{ request.route_path('admin.project.set_upload_limit', project_name=project.normalized_name) }}">
159+
<input name="csrf_token" type="hidden" value="{{ request.session.get_csrf_token() }}">
160+
<div class="box-body">
161+
<div class="form-group col-sm-12">
162+
<label for="uploadLimit">Upload limit (in bytes)</label>
163+
<input type="text" name="upload_limit" class="form-control" id="uploadLimit" rows="3" value="{{ project.upload_limit | default('', True)}}">
164+
</div>
165+
</div>
166+
167+
<div class="box-footer">
168+
<div class="pull-right">
169+
<button type="submit" class="btn btn-primary">Submit</button>
170+
</div>
171+
</div>
172+
</form>
173+
</div>
135174
{% endblock %}

warehouse/admin/views/projects.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from pyramid.httpexceptions import (
1717
HTTPBadRequest,
1818
HTTPMovedPermanently,
19+
HTTPSeeOther,
1920
)
2021
from pyramid.view import view_config
2122
from sqlalchemy import or_
@@ -201,3 +202,37 @@ def journals_list(project, request):
201202
)
202203

203204
return {"journals": journals, "project": project, "query": q}
205+
206+
207+
@view_config(
208+
route_name="admin.project.set_upload_limit",
209+
permission="admin",
210+
request_method="POST",
211+
uses_session=True,
212+
require_methods=False,
213+
)
214+
def set_upload_limit(project, request):
215+
upload_limit = request.POST.get("upload_limit", "")
216+
217+
# Update the project's upload limit.
218+
# If the upload limit is an empty string or othrwise falsy, just set the
219+
# limit to None, indicating the default limit.
220+
if not upload_limit:
221+
project.upload_limit = None
222+
else:
223+
try:
224+
project.upload_limit = int(upload_limit)
225+
except ValueError:
226+
raise HTTPBadRequest(
227+
f"Invalid value for upload_limit: {upload_limit}, "
228+
f"must be integer or empty string.")
229+
230+
request.session.flash(
231+
f"Successfully set the upload limit on {project.name!r} to "
232+
f"{project.upload_limit!r}",
233+
queue="success",
234+
)
235+
236+
return HTTPSeeOther(
237+
request.route_path(
238+
'admin.project.detail', project_name=project.normalized_name))

0 commit comments

Comments
 (0)