diff --git a/tests/unit/admin/views/test_projects.py b/tests/unit/admin/views/test_projects.py index 1e3cfe0ff56a..349fd87d0a4d 100644 --- a/tests/unit/admin/views/test_projects.py +++ b/tests/unit/admin/views/test_projects.py @@ -354,21 +354,21 @@ def test_sets_limitwith_integer(self, db_request): flash=pretend.call_recorder(lambda *a, **kw: None), ) db_request.matchdict["project_name"] = project.normalized_name - db_request.POST["upload_limit"] = "12345" + db_request.POST["upload_limit"] = "90" views.set_upload_limit(project, db_request) assert db_request.session.flash.calls == [ pretend.call( - "Successfully set the upload limit on 'foo' to 12345", + "Successfully set the upload limit on 'foo'.", queue="success"), ] - assert project.upload_limit == 12345 + assert project.upload_limit == 90 * views.ONE_MB def test_sets_limit_with_none(self, db_request): project = ProjectFactory.create(name="foo") - project.upload_limit = 12345 + project.upload_limit = 90 * views.ONE_MB db_request.route_path = pretend.call_recorder( lambda *a, **kw: "/admin/projects/") @@ -381,13 +381,13 @@ def test_sets_limit_with_none(self, db_request): assert db_request.session.flash.calls == [ pretend.call( - "Successfully set the upload limit on 'foo' to None", + "Successfully set the upload limit on 'foo'.", queue="success"), ] assert project.upload_limit is None - def test_sets_limit_with_bad_value(self, db_request): + def test_sets_limit_with_non_integer(self, db_request): project = ProjectFactory.create(name="foo") db_request.matchdict["project_name"] = project.normalized_name @@ -395,3 +395,12 @@ def test_sets_limit_with_bad_value(self, db_request): with pytest.raises(HTTPBadRequest): views.set_upload_limit(project, db_request) + + def test_sets_limit_with_less_than_minimum(self, db_request): + project = ProjectFactory.create(name="foo") + + db_request.matchdict["project_name"] = project.normalized_name + db_request.POST["upload_limit"] = "20" + + with pytest.raises(HTTPBadRequest): + views.set_upload_limit(project, db_request) diff --git a/warehouse/admin/templates/admin/projects/detail.html b/warehouse/admin/templates/admin/projects/detail.html index 4c7cea25c1c7..8f798e33743f 100644 --- a/warehouse/admin/templates/admin/projects/detail.html +++ b/warehouse/admin/templates/admin/projects/detail.html @@ -54,7 +54,13 @@

{{ project.name }}

Upload limit - {{ project.upload_limit }} + + {% if project.upload_limit %} + {{ project.upload_limit|filesizeformat(binary=True) }} + {% else %} + Default ({{ MAX_FILESIZE|filesizeformat(binary=True) }}) + {% endif %} + @@ -159,8 +165,13 @@

Set upload limit

- - + + {% if project.upload_limit %} + {% set upload_limit_value = project.upload_limit / ONE_MB %} + {% else %} + {% set upload_limit_value = '' %} + {% endif %} +
diff --git a/warehouse/admin/views/projects.py b/warehouse/admin/views/projects.py index c0a54dbb8be7..d5bfc3be91e1 100644 --- a/warehouse/admin/views/projects.py +++ b/warehouse/admin/views/projects.py @@ -24,6 +24,9 @@ from warehouse.accounts.models import User from warehouse.packaging.models import Project, Release, Role, JournalEntry from warehouse.utils.paginate import paginate_url_factory +from warehouse.forklift.legacy import MAX_FILESIZE + +ONE_MB = 1024 * 1024 # bytes @view_config( @@ -101,7 +104,13 @@ def project_detail(project, request): ) ] - return {"project": project, "maintainers": maintainers, "journal": journal} + return { + "project": project, + "maintainers": maintainers, + "journal": journal, + "ONE_MB": ONE_MB, + "MAX_FILESIZE": MAX_FILESIZE + } @view_config( @@ -218,18 +227,27 @@ def set_upload_limit(project, request): # If the upload limit is an empty string or othrwise falsy, just set the # limit to None, indicating the default limit. if not upload_limit: - project.upload_limit = None + upload_limit = None else: try: - project.upload_limit = int(upload_limit) + upload_limit = int(upload_limit) except ValueError: raise HTTPBadRequest( - f"Invalid value for upload_limit: {upload_limit}, " + f"Invalid value for upload limit: {upload_limit}, " f"must be integer or empty string.") + # The form is in MB, but the database field is in bytes. + upload_limit *= ONE_MB + + if upload_limit < MAX_FILESIZE: + raise HTTPBadRequest( + f"Upload limit can not be less than the default limit of " + f"{MAX_FILESIZE / ONE_MB}MB.") + + project.upload_limit = upload_limit + request.session.flash( - f"Successfully set the upload limit on {project.name!r} to " - f"{project.upload_limit!r}", + f"Successfully set the upload limit on {project.name!r}.", queue="success", )