diff --git a/swh/web/api/views/origin_save.py b/swh/web/api/views/origin_save.py --- a/swh/web/api/views/origin_save.py +++ b/swh/web/api/views/origin_save.py @@ -5,7 +5,7 @@ from swh.web.api.apidoc import api_doc, format_docstring from swh.web.api.apiurls import api_route -from swh.web.auth.utils import SWH_AMBASSADOR_PERMISSION +from swh.web.auth.utils import privileged_user_predicate from swh.web.common.origin_save import ( create_save_origin_request, get_save_origin_requests, @@ -84,12 +84,11 @@ """ if request.method == "POST": - bypass_pending_review = request.user.is_authenticated and request.user.has_perm( - SWH_AMBASSADOR_PERMISSION - ) + privileged = privileged_user_predicate(request) sor = create_save_origin_request( - visit_type, origin_url, bypass_pending_review, user_id=request.user.id + visit_type, origin_url, privileged, user_id=request.user.id ) + del sor["id"] else: sor = get_save_origin_requests(visit_type, origin_url) diff --git a/swh/web/auth/utils.py b/swh/web/auth/utils.py --- a/swh/web/auth/utils.py +++ b/swh/web/auth/utils.py @@ -70,3 +70,9 @@ The decrypted data """ return _get_fernet(password, salt).decrypt(data) + + +def privileged_user_predicate(request) -> bool: + return request.user.is_authenticated and request.user.has_perm( + SWH_AMBASSADOR_PERMISSION + ) diff --git a/swh/web/common/origin_save.py b/swh/web/common/origin_save.py --- a/swh/web/common/origin_save.py +++ b/swh/web/common/origin_save.py @@ -113,6 +113,10 @@ # TODO: do not hardcode the task name here (T1157) _visit_type_task = {"git": "load-git", "hg": "load-hg", "svn": "load-svn"} +_visit_type_task_privileged = { + "bundle": "load-archive-files", +} + # map scheduler task status to origin save status _save_task_status = { @@ -134,23 +138,34 @@ } -def get_savable_visit_types() -> List[str]: - """ - Get the list of visit types that can be performed +def get_savable_visit_types(privileged: bool = False) -> List[str]: + """Get the list of visit types that can be performed through a save request. + Args: + privileged: Flag to determine if all visit types should be returned or not. + Returns: - list: the list of saveable visit types + the list of saveable visit types + """ - return sorted(list(_visit_type_task.keys())) + task_types = [] + if privileged: + task_types = list(_visit_type_task.keys()) + list( + _visit_type_task_privileged.keys() + ) + else: + task_types = list(_visit_type_task.keys()) + return sorted(task_types) -def _check_visit_type_savable(visit_type: str) -> None: - allowed_visit_types = ", ".join(get_savable_visit_types()) + +def _check_visit_type_savable(visit_type: str, privileged: bool = False) -> None: if visit_type not in _visit_type_task: + allowed_visit_types = ", ".join(get_savable_visit_types(privileged=privileged)) raise BadInputExc( - "Visit of type %s can not be saved! " - "Allowed types are the following: %s" % (visit_type, allowed_visit_types) + f"Visit of type {visit_type} can not be saved! " + f"Allowed types are the following: {allowed_visit_types}" ) @@ -340,7 +355,7 @@ def create_save_origin_request( visit_type: str, origin_url: str, - bypass_pending_review: bool = False, + privileged: bool = False, user_id: Optional[int] = None, ) -> SaveOriginRequestInfo: """ @@ -360,6 +375,9 @@ Args: visit_type: the type of visit to perform (e.g git, hg, svn, ...) origin_url: the url of the origin to save + privileged: Whether the user has some more privilege than other (bypass + review, access to privileged other visit types) + user_id: User identifier if they are authenticated Raises: BadInputExc: the visit type or origin url is invalid or inexistent @@ -379,10 +397,10 @@ """ - _check_visit_type_savable(visit_type) + _check_visit_type_savable(visit_type, privileged) _check_origin_url_valid(origin_url) # if all checks passed so far, we can try and save the origin - save_request_status = can_save_origin(origin_url, bypass_pending_review) + save_request_status = can_save_origin(origin_url, privileged) task = None # if the origin save request is accepted, create a scheduler @@ -772,7 +790,7 @@ SAVE_TASK_RUNNING, ) - visit_types = get_savable_visit_types() + visit_types = get_savable_visit_types(privileged=True) labels_set = product(request_statuses, visit_types) diff --git a/swh/web/common/swh_templatetags.py b/swh/web/common/swh_templatetags.py --- a/swh/web/common/swh_templatetags.py +++ b/swh/web/common/swh_templatetags.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017-2019 The Software Heritage developers +# Copyright (C) 2017-2021 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information @@ -125,17 +125,18 @@ @register.filter -def visit_type_savable(visit_type): +def visit_type_savable(visit_type: str) -> bool: """Django template filter to check if a save request can be created for a given visit type. Args: - visit_type (str): the type of visit + visit_type: the type of visit Returns: If the visit type is saveable or not + """ - return visit_type in get_savable_visit_types() + return visit_type in get_savable_visit_types(privileged=True) @register.filter diff --git a/swh/web/misc/origin_save.py b/swh/web/misc/origin_save.py --- a/swh/web/misc/origin_save.py +++ b/swh/web/misc/origin_save.py @@ -9,6 +9,7 @@ from django.http import JsonResponse from django.shortcuts import render +from swh.web.auth.utils import privileged_user_predicate from swh.web.common.models import SaveOriginRequest from swh.web.common.origin_save import ( get_savable_visit_types, @@ -24,8 +25,12 @@ ) -def _visit_save_types_list(request): - visit_types = get_savable_visit_types() +def _visit_save_types_list(request) -> JsonResponse: + """Return the list of supported visit types + + """ + privileged = privileged_user_predicate(request) + visit_types = get_savable_visit_types(privileged=privileged) return JsonResponse(visit_types, safe=False)