diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_create.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_create.py index 2f19bae6..eb56bb18 100755 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_create.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_create.py @@ -1,40 +1,52 @@ -# For getting objects out of the database. -from ..utilities import DbUtils +#!/usr/bin/env python3 +"""Create a prefix -# Checking that a user is in a group. -from ..utilities import UserUtils +Create a prefix to be used to classify BCOs and to determine permissions +for objects created under that prefix. The requestor must be in the group +prefix_admins to create a prefix. +""" -# Model fields -from ...models import prefixes - -# Checking prefixes import re -# Responses +from api.scripts.utilities import DbUtils +from api.scripts.utilities import UserUtils +from api.models import prefixes + from rest_framework import status from rest_framework.response import Response -def POST_api_prefixes_create( - incoming -): +def POST_api_prefixes_create(request): + """Create a prefix + + Parameters + ---------- + request: rest_framework.request.Request + Django request object. + + Returns + ------- + rest_framework.response.Response + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ + + # TODO: replace user/group looping with basic filtering + # on the model. Loops now are slower than a single + # filter call. # Instantiate any necessary imports. - db = DbUtils.DbUtils() - uu = UserUtils.UserUtils() + db_utils = DbUtils.DbUtils() + user_utils = UserUtils.UserUtils() # Define the bulk request. - bulk_request = incoming.data['POST_api_prefixes_create']['prefixes'] + bulk_request = request.data['POST_api_prefixes_create'] # Get all existing prefixes. available_prefixes = list( - prefixes.objects.all().values_list( - 'prefix', - flat = True - ) - ) + prefixes.objects.all().values_list('prefix', flat = True)) # Construct an array to return information about processing # the request. @@ -43,130 +55,92 @@ def POST_api_prefixes_create( # Since bulk_request is an array, go over each # item in the array. for creation_object in bulk_request: - - # Create a list to hold information about errors. - errors = {} - - # Standardize the prefix name. - standardized = creation_object['prefix'].upper() - - # TODO: abstract this error check to schema checker? - - # Check for each error. - - # Create a flag for if one of these checks fails. - error_check = False - - # Does the prefix follow the regex for prefixes? - if not re.match( - r"^[A-Z]{3,5}$", - standardized - ): - - error_check = True - - # Bad request because the prefix doesn't follow - # the naming rules. - errors['400_bad_request_malformed_prefix'] = db.messages( - parameters = { - 'prefix': standardized.upper() - } - )['400_bad_request_malformed_prefix'] - - # Has the prefix already been created? - if standardized in available_prefixes: - - error_check = True - - # Update the request status. - errors['409_prefix_conflict'] = db.messages( - parameters = { - 'prefix': standardized.upper() - } - )['409_prefix_conflict'] - - # Does the user exist? - if uu.check_user_exists(un = creation_object['owner_user']) is False: - - error_check = True - - # Bad request. - errors['404_user_not_found'] = db.messages( - parameters = { - 'username': creation_object['owner_user'] - } - )['404_user_not_found'] - - # Does the group exist? - if uu.check_group_exists(n = creation_object['owner_group']) is False: - - error_check = True - - # Bad request. - errors['404_group_not_found'] = db.messages( - parameters = { - 'group': creation_object['owner_group'] - } - )['404_group_not_found'] - - # Was the expiration date validly formatted and, if so, - # is it after right now? - if 'expiration_date' in creation_object: - if db.check_expiration(dt_string = creation_object['expiration_date']) is not None: + # Go over each prefix proposed. + for prfx in creation_object['prefixes']: + # Create a list to hold information about errors. + errors = {} + # Standardize the prefix name. + standardized = prfx['prefix'].upper() + # TODO: abstract this error check to schema checker? + # Check for each error. + # Create a flag for if one of these checks fails. + error_check = False + # Does the prefix follow the regex for prefixes? + if not re.match(r"^[A-Z]{3,5}$", standardized): + error_check = True + # Bad request because the prefix doesn't follow + # the naming rules. + errors['400_bad_request_malformed_prefix'] = db_utils.messages( + parameters = {'prefix': standardized.upper()} + )['400_bad_request_malformed_prefix'] + + # Has the prefix already been created? + if standardized in available_prefixes: + error_check = True + # Update the request status. + errors['409_prefix_conflict'] = db_utils.messages( + parameters = { + 'prefix': standardized.upper() + } + )['409_prefix_conflict'] + + # Does the user exist? + if user_utils.check_user_exists(un = creation_object['owner_user']) is False: error_check = True - + # Bad request. - errors['400_invalid_expiration_date'] = db.messages( - parameters = { - 'expiration_date': creation_object['expiration_date'] - } - )['400_invalid_expiration_date'] - - # Did any check fail? - if error_check is False: - # The prefix has not been created, so create it. - DbUtils.DbUtils().write_object( - p_app_label = 'api', - p_model_name = 'prefixes', - p_fields = ['created_by', 'description', 'owner_group', 'owner_user', 'prefix'], - p_data = { - 'created_by': uu.user_from_request( - request = incoming - ).username, - 'description': creation_object['description'], - 'owner_group': creation_object['owner_group'], - 'owner_user': creation_object['owner_user'], - 'prefix': standardized - } - ) - - DbUtils.DbUtils().write_object( - p_app_label = 'api', - p_model_name ='prefix_table', - p_fields = ['n_objects', 'prefix'], - p_data = { - 'n_objects': 0, - 'prefix': standardized - } - ) - - # Created the prefix. - errors['201_prefix_create'] = db.messages( - parameters = { + errors['404_user_not_found'] = db_utils.messages( + parameters = {'username': creation_object['owner_user']} + )['404_user_not_found'] + + # Does the group exist? + if user_utils.check_group_exists(n = creation_object['owner_group']) is False: + error_check = True + # Bad request. + errors['404_group_not_found'] = db_utils.messages( + parameters = {'group': creation_object['owner_group']} + )['404_group_not_found'] + + # Was the expiration date validly formatted and, if so, + # is it after right now? + if 'expiration_date' in prfx: + if db_utils.check_expiration(dt_string = prfx['expiration_date']) is not None: + error_check = True + # Bad request. + errors['400_invalid_expiration_date'] = db_utils.messages( + parameters = { + 'expiration_date': prfx['expiration_date']} + )['400_invalid_expiration_date'] + # Did any check fail? + if error_check is False: + # The prefix has not been created, so create it. + DbUtils.DbUtils().write_object( + p_app_label = 'api', + p_model_name = 'prefixes', + p_fields = ['created_by', 'description', 'owner_group', 'owner_user', 'prefix'], + p_data = { + 'created_by': user_utils.user_from_request( + request = request + ).username, + 'description': prfx['description'], + 'owner_group': creation_object['owner_group'], + 'owner_user': creation_object['owner_user'], 'prefix': standardized } - )['201_prefix_create'] - - # Append the possible "errors". - returning.append(errors) - + ) + + # Created the prefix. + errors['201_prefix_create'] = db_utils.messages( + parameters = { + 'prefix': standardized + } + )['201_prefix_create'] + + # Append the possible "errors". + returning.append(errors) + # As this view is for a bulk operation, status 200 # means that the request was successfully processed, # but NOT necessarily each item in the request. - return( - Response( - status = status.HTTP_200_OK, - data = returning - ) - ) \ No newline at end of file + return Response(status = status.HTTP_200_OK, data = returning) diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_delete.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_delete.py index 8c7ba960..80e888b7 100755 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_delete.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_delete.py @@ -1,49 +1,47 @@ -# For getting objects out of the database. -from ..utilities import DbUtils - -# Checking that a user is in a group. -from ..utilities import UserUtils - -# Model fields -from ...models import prefixes - -# Responses +#!/usr/bin/env python3 +"""Delete a prefix + +The requestor must be in the group prefix_admins to delete a prefix. +Any object created under this prefix will have its permissions "locked out." +This means that any other view which relies on object-level permissions, such +as /api/objects/drafts/read/, will not allow any requestor access to particular +objects. +""" +from api.scripts.utilities import DbUtils +from api.models import prefixes from rest_framework import status from rest_framework.response import Response +def POST_api_prefixes_delete(request): + """Deletes a prefix + Parameters + ---------- + request: rest_framework.request.Request + Django request object. + Returns + ------- + rest_framework.response.Response + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ -def POST_api_prefixes_delete( - incoming -): - - # Instantiate any necessary imports. - db = DbUtils.DbUtils() - uu = UserUtils.UserUtils() + db_utils = DbUtils.DbUtils() - # Define the bulk request. - bulk_request = incoming.data['POST_api_prefixes_delete']['prefixes'] + bulk_request = request.data['POST_api_prefixes_delete'] # Get all existing prefixes. available_prefixes = list( - prefixes.objects.all().values_list( - 'prefix', - flat=True - ) - ) - - # Construct an array to return information about processing - # the request. + prefixes.objects.all().values_list('prefix', flat=True)) + returning = [] - # Since bulk_request is an array, go over each - # item in the array. for creation_object in bulk_request: # Create a list to hold information about errors. errors = {} - + # Standardize the prefix name. standardized = creation_object.upper() @@ -51,49 +49,27 @@ def POST_api_prefixes_delete( error_check = False if standardized not in available_prefixes: - - error_check = True - + error_check = True # Update the request status. - errors['404_missing_prefix'] = db.messages( - parameters={ - 'prefix': standardized - } - )['404_missing_prefix'] - - # Did any check fail? + errors['404_missing_prefix'] = db_utils.messages(parameters={ + 'prefix': standardized})['404_missing_prefix'] + if error_check is False: - # The prefix exists, so delete it. - # No need to use DB Utils here, # just delete straight up. - # Source: https://stackoverflow.com/a/3681691 - # Django *DOESN'T* want primary keys now... - - prefixed = prefixes.objects.get( - prefix=standardized - ) + prefixed = prefixes.objects.get(prefix=standardized) prefixed.delete() - # Deleted the prefix. - errors['200_OK_prefix_delete'] = db.messages( - parameters={ - 'prefix': standardized - } - )['200_OK_prefix_delete'] - + errors['200_OK_prefix_delete'] = db_utils.messages(parameters={ + 'prefix': standardized})['200_OK_prefix_delete'] + # Append the possible "errors". - returning.append(errors) + returning.append(errors) # As this view is for a bulk operation, status 200 # means that the request was successfully processed, # but NOT necessarily each item in the request. - return ( - Response( - status=status.HTTP_200_OK, - data=returning - ) - ) + return Response(status=status.HTTP_200_OK, data=returning) diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_modify.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_modify.py index fad25832..1b615539 100755 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_modify.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_modify.py @@ -1,35 +1,40 @@ -# For getting objects out of the database. -from api.scripts.utilities import DbUtils +#!/usr/bin/env python3 +"""Modify a Prefix -# Checking that a user is in a group. -from api.scripts.utilities import UserUtils +Modify a prefix which already exists. -# Model fields +The requestor *must* be in the group prefix_admins to modify a prefix. +""" +from api.scripts.utilities import DbUtils +from api.scripts.utilities import UserUtils from api.models import prefixes - -# Responses from rest_framework import status from rest_framework.response import Response -def POST_api_prefixes_modify(incoming): - - # Instantiate any necessary imports. - db = DbUtils.DbUtils() - uu = UserUtils.UserUtils() +def POST_api_prefixes_modify(request): + """Modify a Prefix + + Parameters + ---------- + request: rest_framework.request.Request + Django request object. - # Define the bulk request. - bulk_request = incoming.data['POST_api_prefixes_modify']['prefixes'] + Returns + ------- + rest_framework.response.Response + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ + # Instantiate any necessary imports. + db_utils = DbUtils.DbUtils() + user_utils = UserUtils.UserUtils() - # Get all existing prefixes. + bulk_request = request.data['POST_api_prefixes_modify'] available_prefixes = list( - prefixes.objects.all().values_list( - 'prefix', - flat = True - ) - ) + prefixes.objects.all().values_list('prefix', flat = True)) # Construct an array to return information about processing # the request. @@ -39,93 +44,96 @@ def POST_api_prefixes_modify(incoming): # item in the array. for creation_object in bulk_request: - # Create a list to hold information about errors. - errors = {} + # Go over each prefix proposed. + for prfx in creation_object['prefixes']: - # Standardize the prefix name. - standardized = creation_object['prefix'].upper() + # Create a list to hold information about errors. + errors = {} + + # Standardize the prefix name. + standardized = prfx['prefix'].upper() - # Create a flag for if one of these checks fails. - error_check = False + # Create a flag for if one of these checks fails. + error_check = False - if standardized not in available_prefixes: + if standardized not in available_prefixes: - error_check = True + error_check = True + + # Update the request status. + # Bad request. + errors['404_missing_prefix'] = db_utils.messages( + parameters = { + 'prefix': standardized + } + )['404_missing_prefix'] - # Update the request status. - # Bad request. - errors['404_missing_prefix'] = db.messages( - parameters = { - 'prefix': standardized - } - )['404_missing_prefix'] - - # Does the user exist? - if uu.check_user_exists(un = creation_object['owner_user']) is False: - - error_check = True - - # Bad request. - errors['404_user_not_found'] = db.messages( - parameters = { - 'username': creation_object['owner_user'] - } - )['404_user_not_found'] - - # Does the group exist? - if uu.check_group_exists(n = creation_object['owner_group']) is False: - - error_check = True - - # Bad request. - errors['404_group_not_found'] = db.messages( - parameters = { - 'group': creation_object['owner_group'] - } - )['404_group_not_found'] - - # Was the expiration date validly formatted and, if so, - # is it after right now? - if 'expiration_date' in creation_object: - if db.check_expiration(dt_string = creation_object['expiration_date']) is not None: - + # Does the user exist? + if user_utils.check_user_exists(un = creation_object['owner_user']) is False: + error_check = True - - # Bad request. - errors['400_invalid_expiration_date'] = db.messages( - parameters = { - 'expiration_date': creation_object['expiration_date'] - } - )['400_invalid_expiration_date'] - - # Did any check fail? - if error_check is False: - - # The prefix has not been created, so create it. - DbUtils.DbUtils().write_object( - p_app_label = 'api', - p_model_name = 'prefixes', - p_fields = ['created_by', 'description', 'owner_group', 'owner_user', 'prefix'], - p_data = { - 'created_by': uu.user_from_request( - rq = incoming - ).username, - 'description': creation_object['description'], - 'owner_group': creation_object['owner_group'], - 'owner_user': creation_object['owner_user'], - 'prefix': standardized - } - ) - - # Created the prefix. - errors['201_prefix_modify'] = db.messages( - parameters = { - 'prefix': standardized - } - )['201_prefix_modify'] - - # Append the possible "errors". - returning.append(errors) + + # Bad request. + errors['404_user_not_found'] = db_utils.messages( + parameters = { + 'username': creation_object['owner_user'] + } + )['404_user_not_found'] + + # Does the group exist? + if user_utils.check_group_exists(n = creation_object['owner_group']) is False: + + error_check = True + + # Bad request. + errors['404_group_not_found'] = db_utils.messages( + parameters = { + 'group': creation_object['owner_group'] + } + )['404_group_not_found'] + + # Was the expiration date validly formatted and, if so, + # is it after right now? + if 'expiration_date' in prfx: + if db_utils.check_expiration(dt_string = prfx['expiration_date']) is not None: + + error_check = True + + # Bad request. + errors['400_invalid_expiration_date'] = db_utils.messages( + parameters = { + 'expiration_date': prfx['expiration_date'] + } + )['400_invalid_expiration_date'] + + # Did any check fail? + if error_check is False: + + # The prefix has not been created, so create it. + DbUtils.DbUtils().write_object( + p_app_label = 'api', + p_model_name = 'prefixes', + p_fields = ['created_by', 'description', 'owner_group', 'owner_user', 'prefix'], + p_data = { + 'created_by': user_utils.user_from_request( + request = request + ).username, + 'description': prfx['description'], + 'owner_group': creation_object['owner_group'], + 'owner_user': creation_object['owner_user'], + 'prefix': standardized + } + ) + + # Created the prefix. + errors['201_prefix_modify'] = db_utils.messages( + parameters = { + 'prefix': standardized + } + )['201_prefix_modify'] + + # Append the possible "errors". + returning.append(errors) # As this view is for a bulk operation, status 200 # means that the request was successfully processed, diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_permissions_set.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_permissions_set.py index f655906a..1cf17aaa 100755 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_permissions_set.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_permissions_set.py @@ -40,8 +40,8 @@ def POST_api_prefixes_permissions_set( prefixes.objects.all().values_list( 'prefix', flat = True - ) ) + ) # Construct an array to return information about processing # the request. @@ -51,143 +51,149 @@ def POST_api_prefixes_permissions_set( # item in the array. for creation_object in bulk_request: - # Create a list to hold information about errors. - errors = {} + # Go over each prefix proposed. + for prfx in creation_object['prefixes']: - # Standardize the prefix name. - standardized = creation_object['prefix'].upper() + # Create a list to hold information about errors. + errors = {} + + # Standardize the prefix name. + standardized = prfx.upper() - # Create a flag for if one of these checks fails. - error_check = False + # Create a flag for if one of these checks fails. + error_check = False - # Has the prefix already been created? - if standardized not in available_prefixes: + # Has the prefix already been created? + if standardized not in available_prefixes: + + error_check = True + + # Update the request status. + errors['404_missing_prefix'] = db.messages( + parameters = { + 'prefix': standardized + } + )['404_missing_prefix'] - error_check = True - - # Update the request status. - errors['404_missing_prefix'] = db.messages( - parameters = { - 'prefix': standardized - } - )['404_missing_prefix'] - - # The prefix exists, but is the requestor the owner? - if uu.check_user_owns_prefix(un = user.username, prfx = standardized) is False and user.username != 'wheel': + # The prefix exists, but is the requestor the owner? + if uu.check_user_owns_prefix(un = user.username, prfx = standardized) is False and user.username != 'wheel': - error_check = True + error_check = True - # Bad request, the user isn't the owner. - errors['403_requestor_is_not_prefix_owner'] = db.messages( - parameters = { - 'prefix': standardized - } - )['403_requestor_is_not_prefix_owner'] - - # Did any check fail? - if error_check is False: - - # Split out the permissions assignees into users and groups. - assignees = { - 'group': [], - 'username': [] - } - - if 'username' in creation_object: - assignees['username'] = creation_object['username'] + # Bad request, the user isn't the owner or wheel. + errors['403_requestor_is_not_prefix_owner'] = db.messages( + parameters = { + 'prefix': standardized + } + )['403_requestor_is_not_prefix_owner'] + + # The "expensive" work of assigning permissions is held off + # if any of the above checks fails. - if 'group' in creation_object: - assignees['group'] = creation_object['group'] + # Did any check fail? + if error_check is False: - # Go through each one. - for un in assignees['username']: + # Split out the permissions assignees into users and groups. + assignees = { + 'group': [], + 'username': [] + } + + if 'username' in creation_object: + assignees['username'] = creation_object['username'] - # Create a list to hold information about sub-errors. - sub_errors = {} - - # Create a flag for if one of these sub-checks fails. - sub_error_check = False + if 'group' in creation_object: + assignees['group'] = creation_object['group'] - # Get the user whose permissions are being assigned. - if uu.check_user_exists(un = un) is False: - - sub_error_check = True + # Go through each one. + for un in assignees['username']: - # Bad request, the user doesn't exist. - sub_errors['404_user_not_found'] = db.messages( - parameters = { - 'username': un - } - )['404_user_not_found'] - - # Was the user found? - if sub_error_check is False: - - assignee = User.objects.get(username = un) - - # Permissions are defined directly as they are - # in the POST request. - - # Assumes permissions are well-formed... + # Create a list to hold information about sub-errors. + sub_errors = {} - # Source: https://docs.djangoproject.com/en/3.2/topics/auth/default/#permissions-and-authorization - assignee.user_permissions.set([Permission.objects.get(codename = i + '_' + creation_object['prefix']) for i in creation_object['permissions']]) + # Create a flag for if one of these sub-checks fails. + sub_error_check = False + + # Get the user whose permissions are being assigned. + if uu.check_user_exists(un = un) is False: + + sub_error_check = True + + # Bad request, the user doesn't exist. + sub_errors['404_user_not_found'] = db.messages( + parameters = { + 'username': un + } + )['404_user_not_found'] + + # Was the user found? + if sub_error_check is False: + + assignee = User.objects.get(username = un) - # Permissions assigned. - sub_errors['200_OK_prefix_permissions_update'] = db.messages( - parameters = { - 'prefix': standardized - } - )['200_OK_prefix_permissions_update'] - - # Add the sub-"errors". - errors['username'] = sub_errors - - for g in assignees['group']: - - # Create a list to hold information about sub-errors. - sub_errors = {} + # Permissions are defined directly as they are + # in the POST request. - # Create a flag for if one of these sub-checks fails. - sub_error_check = False + # Assumes permissions are well-formed... - # Get the group whose permissions are being assigned. - if uu.check_group_exists(n = g) is False: + # Source: https://docs.djangoproject.com/en/3.2/topics/auth/default/#permissions-and-authorization + assignee.user_permissions.set([Permission.objects.get(codename = i + '_' + prfx) for i in creation_object['permissions']]) - sub_error_check = True + # Permissions assigned. + sub_errors['200_OK_prefix_permissions_update'] = db.messages( + parameters = { + 'prefix': standardized + } + )['200_OK_prefix_permissions_update'] - # Bad request, the group doesn't exist. - sub_errors['404_group_not_found'] = db.messages( - parameters = { - 'group': g - } - )['404_group_not_found'] + # Add the sub-"errors". + errors['username'] = sub_errors - # Was the group found? - if sub_error_check is False: - - assignee = Group.objects.get(name = g) + for g in assignees['group']: + + # Create a list to hold information about sub-errors. + sub_errors = {} + + # Create a flag for if one of these sub-checks fails. + sub_error_check = False + + # Get the group whose permissions are being assigned. + if uu.check_group_exists(n = g) is False: + + sub_error_check = True + + # Bad request, the group doesn't exist. + sub_errors['404_group_not_found'] = db.messages( + parameters = { + 'group': g + } + )['404_group_not_found'] + + # Was the group found? + if sub_error_check is False: + + assignee = Group.objects.get(name = g) - # Permissions are defined directly as they are - # in the POST request. + # Permissions are defined directly as they are + # in the POST request. - # Assumes permissions are well-formed... + # Assumes permissions are well-formed... - # Source: https://docs.djangoproject.com/en/3.2/topics/auth/default/#permissions-and-authorization - assignee.permissions.set([Permission.objects.get(codename = i + '_' + creation_object['prefix']) for i in creation_object['permissions']]) + # Source: https://docs.djangoproject.com/en/3.2/topics/auth/default/#permissions-and-authorization + assignee.permissions.set([Permission.objects.get(codename = i + '_' + prfx) for i in creation_object['permissions']]) - # Permissions assigned. - sub_errors['200_OK_prefix_permissions_update'] = db.messages( - parameters = { - 'prefix': standardized - } - )['200_OK_prefix_permissions_update'] + # Permissions assigned. + sub_errors['200_OK_prefix_permissions_update'] = db.messages( + parameters = { + 'prefix': standardized + } + )['200_OK_prefix_permissions_update'] + + # Add the sub-"errors". + errors['group'] = sub_errors - # Add the sub-"errors". - errors['group'] = sub_errors - - # Append the possible "errors". - returning.append(errors) + # Append the possible "errors". + returning.append(errors) # As this view is for a bulk operation, status 200 # means that the request was successfully processed, diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_token.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_token.py index 4d1403a6..5772b84a 100644 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_token.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_token.py @@ -1,36 +1,35 @@ -# User utilities -from ..utilities import UserUtils - -# Responses -from rest_framework import status -from rest_framework.response import Response - - +#!/usr/bin/env python3 +"""Get Prefixes for a Token +Get all available prefixes and their associated permissions for a given token. +The word 'Token' must be included in the header. +The token has already been validated, +so the user is guaranteed to exist. -def POST_api_prefixes_token( - request -): - - # Instantiate any necessary imports. - uu = UserUtils.UserUtils() - - # The token has already been validated, - # so the user is guaranteed to exist. - - # A little expensive, but use the utility - # we already have. Default will return flattened list of permissions - prefixes = uu.prefix_perms_for_user( - user_object = uu.user_from_request( - rq = request - ).username, - flatten = False - ) +A little expensive, but use the utility +we already have. Default will return flattened list of permissions. +""" +from api.scripts.utilities import UserUtils +from rest_framework import status +from rest_framework.response import Response - return( - Response( - status = status.HTTP_200_OK, - data = prefixes - ) - ) \ No newline at end of file +def POST_api_prefixes_token(request): + """Get Prefixes for a Token + + Parameters + ---------- + request: rest_framework.request.Request + Django request object. + + Returns + ------- + rest_framework.response.Response + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ + + prefixes = UserUtils.UserUtils().prefix_perms_for_user( + user_object = UserUtils.UserUtils().user_from_request( + request = request).username, flatten = False) + return Response(status = status.HTTP_200_OK, data = prefixes) diff --git a/bco_api/api/scripts/method_specific/POST_api_prefixes_token_flat.py b/bco_api/api/scripts/method_specific/POST_api_prefixes_token_flat.py index f6953754..443c4e5d 100644 --- a/bco_api/api/scripts/method_specific/POST_api_prefixes_token_flat.py +++ b/bco_api/api/scripts/method_specific/POST_api_prefixes_token_flat.py @@ -1,38 +1,34 @@ -# User utilities -from ..utilities import UserUtils +#!/usr/bin/env python3 +"""Get Prefixes for a Token, flat list -# Responses +Get all available prefixes and their associated permissions for a given token. +The word 'Token' must be included in the header. The token has already been +validated, so the user is guaranteed to exist. + +A little expensive, but use the utility we already have. Default will return +flattened list of permissions. +""" +from api.scripts.utilities import UserUtils from rest_framework import status from rest_framework.response import Response +def POST_api_prefixes_token_flat(request): + """Get Prefixes for a Token + Parameters + ---------- + request: rest_framework.request.Request + Django request object. + Returns + ------- + rest_framework.response.Response + An HttpResponse that allows its data to be rendered into + arbitrary media types. + """ -def POST_api_prefixes_token_flat( - request -): - - # Instantiate any necessary imports. - uu = UserUtils.UserUtils() - - # The token has already been validated, - # so the user is guaranteed to exist. - - # A little expensive, but use the utility - # we already have. Default will return flattened list of permissions - prefixes = uu.prefix_perms_for_user( - user_object = uu.user_from_request( - rq = request - ).username, - flatten = True - ) - - # We only need the permissions that are specific - # to the bco model. + prefixes = UserUtils.UserUtils().prefix_perms_for_user( + user_object = UserUtils.UserUtils().user_from_request( + request = request).username,flatten = True) - return( - Response( - status = status.HTTP_200_OK, - data = prefixes - ) - ) \ No newline at end of file + return Response(status = status.HTTP_200_OK, data = prefixes) diff --git a/bco_api/api/views.py b/bco_api/api/views.py index 8f0f35ab..4b9638be 100755 --- a/bco_api/api/views.py +++ b/bco_api/api/views.py @@ -604,15 +604,20 @@ class ApiObjectsDraftsPublish(APIView): permission_classes = [IsAuthenticated] POST_api_objects_drafts_publish_schema = openapi.Schema( - type=openapi.TYPE_OBJECT, - required=['draft_id', 'prefix'], - properties={ - 'prefix' : openapi.Schema(type=openapi.TYPE_STRING, description='BCO Prefix to publish with.'), - 'draft_id' : openapi.Schema(type=openapi.TYPE_STRING, description='BCO Object Draft ID.'), - 'object_id' : openapi.Schema(type=openapi.TYPE_STRING, description='BCO Object ID.'), - 'delete_draft': openapi.Schema(type=openapi.TYPE_BOOLEAN, description='Whether or not to delete the draft. False by default.'), - } - ) + type=openapi.TYPE_OBJECT, + required=['draft_id', 'prefix'], + properties={ + 'prefix': openapi.Schema(type=openapi.TYPE_STRING, + description='BCO Prefix to publish with.'), + 'draft_id': openapi.Schema(type=openapi.TYPE_STRING, + description='BCO Object Draft ID.'), + 'object_id': openapi.Schema(type=openapi.TYPE_STRING, + description='BCO Object ID.'), + 'delete_draft': openapi.Schema(type=openapi.TYPE_BOOLEAN, + description='Whether or not to delete the draft.' + ' False by default.'), + } + ) request_body = openapi.Schema( type=openapi.TYPE_OBJECT, @@ -620,10 +625,12 @@ class ApiObjectsDraftsPublish(APIView): description="Parameters that are supported when setting publishing BCOs.", required=['POST_api_objects_drafts_publish'], properties={ - 'POST_api_objects_drafts_publish': openapi.Schema(type=openapi.TYPE_ARRAY, - items=POST_api_objects_drafts_publish_schema, - description='BCO drafts to publish.'), - }) + 'POST_api_objects_drafts_publish': openapi.Schema( + type=openapi.TYPE_ARRAY, + items=POST_api_objects_drafts_publish_schema, + description='BCO drafts to publish.') + } + ) @swagger_auto_schema(request_body=request_body, responses={ 200: "BCO Publication is successful.", @@ -873,6 +880,7 @@ def get(self, request) -> Response: return POST_api_objects_published() # return POST_api_objects_token(rqst=request) + class ApiPrefixesCreate(APIView): """ Create a Prefix @@ -884,17 +892,24 @@ class ApiPrefixesCreate(APIView): ```JSON { - "POST_api_prefixes_create": { - "prefixes":[ - { - "description": "Generic testing prefix.", - "expiration_date": "2023-01-01-01-01-01", - "owner_group": "bco_publisher", - "owner_user": "anon", - "prefix": "tEsTr" - } - ] - } + "POST_api_prefixes_create": [ + { + "owner_group": "bco_publisher", + "owner_user": "anon", + "prefixes": [ + { + "description": "Just a test prefix.", + "expiration_date": "2023-01-01-01-01-01", + "prefix": "testR" + }, + { + "description": "Just another prefix.", + "expiration_date": "2023-01-01-01-01-01", + "prefix": "othER" + } + ] + } + ] } ``` """ @@ -902,33 +917,22 @@ class ApiPrefixesCreate(APIView): # Permissions - prefix admins only permission_classes = [RequestorInPrefixAdminsGroup] + # TYPE_ARRAY explanation + # Source: https://stackoverflow.com/questions/53492889/drf-yasg-doesnt-take-type-array-as-a-valid-type + + # TODO: Need to get the schema that is being sent here from FE request_body = openapi.Schema( - type=openapi.TYPE_OBJECT, - title="Prefix Creation Schema", - description="Several parameters are required to create a prefix.", - required=['owner_group', 'owner_user', 'prefix'], - properties={ - 'description': openapi.Schema(type=openapi.TYPE_STRING, - description='A description of what this prefix should' - 'represent. For example, the prefix \'GLY\' would be' - 'related to BCOs which were derived from GlyGen' - 'workflows.'), - 'expiration_date': openapi.Schema(type=openapi.TYPE_STRING, - description='The datetime at which this prefix expires in' - 'the format YYYY-MM-DD-HH-MM-SS.'), - 'owner_group': openapi.Schema(type=openapi.TYPE_STRING, - description='Which group should own the prefix. *The' - 'requestor does not have to be in owner_group to' - 'assign this.*'), - 'owner_user': openapi.Schema(type=openapi.TYPE_STRING, - description='Which user should own the prefix. *The' - 'requestor does not have to be owner_user to assign' - 'this.*'), - 'prefix': openapi.Schema(type=openapi.TYPE_STRING, - description='Any prefix which satsifies the naming' - 'standard (see link...)'), - } - ) + type=openapi.TYPE_OBJECT, + title="Prefix Creation Schema", + description="Several parameters are required to create a prefix.", + required=['owner_group', 'owner_user', 'prefix'], + properties={ + 'description': openapi.Schema(type=openapi.TYPE_STRING, description='A description of what this prefix should represent. For example, the prefix \'GLY\' would be related to BCOs which were derived from GlyGen workflows.'), + 'expiration_date': openapi.Schema(type=openapi.TYPE_STRING, description='The datetime at which this prefix expires in the format YYYY-MM-DD-HH-MM-SS.'), + 'owner_group': openapi.Schema(type=openapi.TYPE_STRING, description='Which group should own the prefix. *The requestor does not have to be in owner_group to assign this.*'), + 'owner_user': openapi.Schema(type=openapi.TYPE_STRING, description='Which user should own the prefix. *The requestor does not have to be owner_user to assign this.*'), + 'prefixes': openapi.Schema(type=openapi.TYPE_ARRAY, description='Any prefix which satsifies the naming standard (see link...)', items=openapi.Items(type=openapi.TYPE_STRING)) + }) @swagger_auto_schema(request_body=request_body, responses={ 201: "The prefix was successfully created.", @@ -956,13 +960,10 @@ class ApiPrefixesDelete(APIView): ```JSON { - "POST_api_prefixes_delete": { - "prefixes":[ - "PRFX", - "OTR", - "GLY" - ] - } + "POST_api_prefixes_delete": [ + "OTHER", + "TESTR" + ] } ``` @@ -978,8 +979,10 @@ class ApiPrefixesDelete(APIView): description="Provide a list of prefixes to delete.", required=['prefixes'], properties={ - 'prefixes': openapi.Schema(type=openapi.TYPE_STRING, - description='Any prefix in the API.'), + 'prefixes': openapi.Schema( + type=openapi.TYPE_ARRAY, + description='Any prefix in the API.', + items=openapi.Items(type=openapi.TYPE_STRING)), } ) @@ -1000,23 +1003,30 @@ class ApiPrefixesModify(APIView): -------------------- - # Modify a prefix which already exists. + Modify a prefix which already exists. The requestor *must* be in the group prefix_admins to modify a prefix. ```JSON { - "POST_api_prefixes_modify": { - "prefixes":[ - { - "description": "Here is some new description.", - "expiration_date": "2023-01-01-01-01-01", - "owner_group": "some_new_owner_group", - "owner_user": "some_new_owner_user", - "prefix": "tEsTr" - } - ] - } + "POST_api_prefixes_modify": [ + { + "owner_group": "bco_drafter", + "owner_user": "wheel", + "prefixes": [ + { + "description": "Just another description here.", + "expiration_date": "2025-01-01-01-01-01", + "prefix": "testR" + }, + { + "description": "Just another prefix description here as well.", + "expiration_date": "2025-01-01-01-01-01", + "prefix": "othER" + } + ] + } + ] } ``` @@ -1024,21 +1034,62 @@ class ApiPrefixesModify(APIView): # Permissions - prefix admins only permission_classes = [RequestorInPrefixAdminsGroup] + prefixes_object_schema = openapi.Schema( + type=openapi.TYPE_OBJECT, + required=[], + properties={ + 'description': openapi.Schema( + type=openapi.TYPE_STRING, + description='A description of what this prefix should' + ' represent. For example, the prefix \'GLY\' would be ' + 'related to BCOs which were derived from GlyGen workflows.' + ), + 'expiration_date': openapi.Schema( + type=openapi.TYPE_STRING, + description='The datetime at which this prefix expires in the' + ' format YYYY-MM-DD-HH-MM-SS.'), + 'prefix': openapi.Schema( + type=openapi.TYPE_STRING, + description='Any prefix which satsifies the naming standard') + } + + + ) + POST_api_prefixes_modify_schema = openapi.Schema( + type=openapi.TYPE_OBJECT, + required=[], + properties={ + 'owner_group': openapi.Schema( + type=openapi.TYPE_STRING, + description='Which group should own the prefix. *The' + ' requestor does not have to be in the owner group to' + ' assign this.*'), + 'owner_user': openapi.Schema( + type=openapi.TYPE_STRING, + description='Which user should own the prefix. *The requestor' + ' does not have to be owner_user but owner_user must be in' + ' owner_group*.'), + 'prefixes': openapi.Schema( + type=openapi.TYPE_ARRAY, + items=prefixes_object_schema, + description='Any prefix which satsifies the naming standard') + } + ) # TODO: Need to get the schema that is being sent here from FE request_body = openapi.Schema( - type=openapi.TYPE_OBJECT, - title="Prefix Modification Schema", - description="Several parameters are required to modify a prefix.", - required=['prefix'], - properties={ - 'description': openapi.Schema(type=openapi.TYPE_STRING, description='A description of what this prefix should represent. For example, the prefix \'GLY\' would be related to BCOs which were derived from GlyGen workflows.'), - 'expiration_date': openapi.Schema(type=openapi.TYPE_STRING, description='The datetime at which this prefix expires in the format YYYY-MM-DD-HH-MM-SS.'), - 'owner_group': openapi.Schema(type=openapi.TYPE_STRING, description='Which group should own the prefix. *The requestor does not have to be in the owner group to assign this.*'), - 'owner_user': openapi.Schema(type=openapi.TYPE_STRING, description='Which user should own the prefix. *The requestor does not have to be owner_user but owner_user must be in owner_group*.'), - 'prefix': openapi.Schema(type=openapi.TYPE_STRING, description='Any prefix which satsifies the naming standard (see link...)'), - }) - + type=openapi.TYPE_OBJECT, + title="Prefix Modification Schema", + description="Several parameters are required to modify a prefix.", + required=['POST_api_prefixes_modify'], + properties={ + 'POST_api_prefixes_modify': openapi.Schema( + type=openapi.TYPE_ARRAY, + items=POST_api_prefixes_modify_schema, + description='' + ) + }) # TODO: ADD LINK FOR PREFIX DOCUMENTATION + @swagger_auto_schema(request_body=request_body, responses={ 200: "The prefix was successfully modified.", 400: "Bad request because owner_user and/or owner_group do not exist.", @@ -1067,15 +1118,19 @@ class ApiPrefixesPermissionsSet(APIView): "group": [ "bco_drafter" ], + "mode": "add", "permissions": [ "change", "delete", "view" ], - "prefix": "BCO", + "prefixes": [ + "testR", + "BCO" + ], "username": [ "some_user" - ], + ] } ] } @@ -1094,6 +1149,7 @@ class ApiPrefixesPermissionsSet(APIView): required=['permissions', 'prefix'], properties={ 'group': openapi.Schema(type=openapi.TYPE_STRING, description='Which group the permission is being assigned to.'), + 'mode': openapi.Schema(type=openapi.TYPE_STRING, description='Whether to \'add\' (append), \'remove\' (subtract), or define the \'full_set\' of permissions.'), 'permissions': openapi.Schema(type=openapi.TYPE_STRING, description='Which permissions to assign.'), 'prefix': openapi.Schema(type=openapi.TYPE_STRING, description='Which prefix to assign the permissions to.'), 'username': openapi.Schema(type=openapi.TYPE_STRING, description='Which user the permission is being assigned to.'), @@ -1110,12 +1166,11 @@ def post(self, request) -> Response: class ApiPrefixesToken(APIView): """ - Get Prefixes for a Token + Get list of prefixes -------------------- - # Get all available prefixes and their associated permissions for a given token. - + Get all available prefixes and their associated permissions for a given token. The word 'Token' must be included in the header. For example: 'Token 627626823549f787c3ec763ff687169206626149'. @@ -1138,16 +1193,12 @@ def post(self, request) -> Response: class ApiPrefixesTokenFlat(APIView): """ - Get Prefixes for a Token in Flat Format + Get a flat list of prefixes -------------------- - # Get all available prefixes and their associated permissions for a given token in flat format. - - # TODO: What does this do? Appears to flatten the prefixes (not sure what for) - # Answer (Chris, 1/22): These may be easier for a requestor to parse rapidly on a web page. - - The word 'Token' must be included in the header. + Get all available prefixes and their associated permissions for a given + token in flat format. The word 'Token' must be included in the header. For example: 'Token 627626823549f787c3ec763ff687169206626149'. """