Skip to content

Commit 730f33f

Browse files
committed
Merge branch 'main' into feat-group-mark-revoked
2 parents 0817bcc + 4136c84 commit 730f33f

20 files changed

+1860
-1250
lines changed

Access/accessrequest_helper.py

Lines changed: 247 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
import logging
33
import time
44
from . import helpers as helper
5+
from Access import notifications
56

67
from BrowserStackAutomation.settings import DECLINE_REASONS
78
from Access.models import UserAccessMapping, User, GroupV2, AccessV2
89
import datetime
910
import json
1011
from django.db import transaction
12+
from Access.background_task_manager import background_task
1113

1214
logger = logging.getLogger(__name__)
1315

@@ -19,6 +21,7 @@
1921
"title": "{access_tag}: Duplicate Request not submitted",
2022
"msg": "Access already granted or request in pending state. {access_label}",
2123
}
24+
REQUEST_PROCESS_MSG = "The Request ({request_id}) is now being processed"
2225
REQUEST_ERR_MSG = {
2326
"error_msg": "Invalid Request",
2427
"msg": "Please Contact Admin",
@@ -27,43 +30,10 @@
2730
"error_msg": "The submitted form is empty. Tried direct access to reqeust access page",
2831
"msg": "Error Occured while submitting your Request. Please contact the Admin",
2932
}
30-
3133
REQUEST_ACCESS_AUTO_APPROVED_MSG = {
3234
"title": "{request_id} Request Approved",
3335
"msg": "Once granted you will receive the update",
3436
}
35-
36-
REQUEST_DB_ERR_MSG = {
37-
"error_msg": "Error Saving Request",
38-
"msg": "Please Contact Admin",
39-
}
40-
REQUEST_IDENTITY_NOT_SETUP_ERR_MSG = {
41-
"error_msg": "Identity not setup",
42-
"msg": "User Identity for module {access_tag} not setup by the user",
43-
}
44-
45-
REQUEST_SUCCESS_MSG = {
46-
"title": "{request_id} Request Submitted",
47-
"msg": "Once approved you will receive the update. {access_label}",
48-
}
49-
REQUEST_DUPLICATE_ERR_MSG = {
50-
"title": "{access_tag}: Duplicate Request not submitted",
51-
"msg": "Access already granted or request in pending state. {access_label}",
52-
}
53-
REQUEST_ERR_MSG = {
54-
"error_msg": "Invalid Request",
55-
"msg": "Please Contact Admin",
56-
}
57-
REQUEST_EMPTY_FORM_ERR_MSG = {
58-
"error_msg": "The submitted form is empty. Tried direct access to reqeust access page",
59-
"msg": "Error Occured while submitting your Request. Please contact the Admin",
60-
}
61-
62-
REQUEST_ACCESS_AUTO_APPROVED_MSG = {
63-
"title": "{request_id} Request Approved",
64-
"msg": "Once granted you will receive the update",
65-
}
66-
6737
REQUEST_DB_ERR_MSG = {
6838
"error_msg": "Error Saving Request",
6939
"msg": "Please Contact Admin",
@@ -72,6 +42,12 @@
7242
"error_msg": "Identity not setup",
7343
"msg": "User Identity for module {access_tag} not setup by the user",
7444
}
45+
USER_REQUEST_IN_PROCESS_ERR_MSG = "The Request ({request_id}) has already been processed. \
46+
Please check Access History for more information"
47+
USER_REQUEST_PERMISSION_DENIED_ERR_MSG = "Permission Denied!"
48+
USER_REQUEST_DECLINE_MSG = "Declined Request {request_id} - Reason: {decline_reason}"
49+
USER_REQUEST_SECONDARY_PENDING_MSG = "The Request ({request_id}) is approved by {approved_by} \
50+
Pending on secondary approver"
7551

7652

7753
def requestAccessGet(request):
@@ -117,6 +93,30 @@ def requestAccessGet(request):
11793
return context
11894

11995

96+
def validate_approver_permissions(access_mapping, access_type, request, request_id):
97+
json_response = {}
98+
99+
access_label = access_mapping.access.access_label
100+
try:
101+
permissions = _get_approver_permissions(access_type, access_label)
102+
except Exception as e:
103+
return process_error_response(e)
104+
105+
approver_permissions = permissions["approver_permissions"]
106+
if "2" in approver_permissions and access_mapping.is_secondary_pending():
107+
if not request.user.user.has_permission(approver_permissions["2"]):
108+
logger.debug(USER_REQUEST_PERMISSION_DENIED_ERR_MSG)
109+
json_response["error"] = USER_REQUEST_PERMISSION_DENIED_ERR_MSG
110+
return json_response
111+
elif access_mapping.is_pending():
112+
if not request.user.user.has_permission(approver_permissions["1"]):
113+
logger.debug(USER_REQUEST_PERMISSION_DENIED_ERR_MSG)
114+
json_response["error"] = USER_REQUEST_PERMISSION_DENIED_ERR_MSG
115+
return json_response
116+
117+
return json_response
118+
119+
120120
def getGrantFailedRequests(request):
121121
try:
122122
failures = UserAccessMapping.objects.filter(
@@ -134,7 +134,7 @@ def getGrantFailedRequests(request):
134134
context = {"failures": failures, "heading": "Grant Failures"}
135135
return context
136136
except Exception as e:
137-
return process_error_response(request, e)
137+
return process_error_response(e)
138138

139139

140140
def get_pending_revoke_failures(request):
@@ -178,7 +178,39 @@ def getPendingRequests(request):
178178

179179
return context
180180
except Exception as e:
181-
return process_error_response(request, e)
181+
return process_error_response(e)
182+
183+
184+
def get_decline_access_request(request, access_type, request_id):
185+
logger.info("Decline Access Request call initiated")
186+
try:
187+
context = {"response": {}}
188+
reason = request.GET["reason"]
189+
request_ids = []
190+
return_ids = []
191+
if access_type.endswith("-club"):
192+
for value in [request_id]:
193+
return_ids.append(value)
194+
current_ids = list(
195+
UserAccessMapping.get_pending_access_mapping(request_id=value)
196+
)
197+
request_ids.extend(current_ids)
198+
access_type = access_type.rsplit("-", 1)[0]
199+
else:
200+
request_ids = [request_id]
201+
for current_request_id in request_ids:
202+
response = decline_individual_access(
203+
request, access_type, current_request_id, reason
204+
)
205+
if "error" in response:
206+
response["success"] = False
207+
else:
208+
response["success"] = True
209+
context["response"][current_request_id] = response
210+
context["returnIds"] = return_ids
211+
return context
212+
except Exception as e:
213+
return process_error_response(e)
182214

183215

184216
def get_pending_accesses_from_modules(access_user):
@@ -191,7 +223,6 @@ def get_pending_accesses_from_modules(access_user):
191223
access_module,
192224
) in helpers.get_available_access_modules().items():
193225
access_module_start_time = time.time()
194-
195226
try:
196227
pending_accesses = access_module.get_pending_accesses(access_user)
197228
except Exception as e:
@@ -282,7 +313,7 @@ def process_group_requests(group_pending_requests, group_requests):
282313
group_requests[club_id]["accessData"].append(accessData)
283314

284315

285-
def process_error_response(request, e):
316+
def process_error_response(e):
286317
logger.debug("Error in request not found OR Invalid request type")
287318
logger.exception(e)
288319
json_response = {}
@@ -398,7 +429,6 @@ def _create_access(auth_user, access_label, access_type, request_id, access_reas
398429
}
399430

400431
try:
401-
402432
access = _create_access_mapping(
403433
access=access,
404434
user_identity=user_identity,
@@ -475,3 +505,182 @@ def validate_access_labels(access_labels_json, access_type):
475505
)
476506
)
477507
return access_labels
508+
509+
510+
def _get_approver_permissions(access_type, access_label=None):
511+
json_response = {}
512+
513+
access_module = helper.get_available_access_module_from_tag(access_type)
514+
approver_permissions = []
515+
approver_permissions = access_module.fetch_approver_permissions(access_label)
516+
517+
json_response["approver_permissions"] = approver_permissions
518+
if len(json_response) == 0:
519+
raise Exception("Approver Permissions not found for module %s " % access_module)
520+
return json_response
521+
522+
523+
def is_request_valid(request_id, access_mapping):
524+
if access_mapping.is_already_processed():
525+
logger.warning(
526+
USER_REQUEST_IN_PROCESS_ERR_MSG.format(
527+
request_id=request_id,
528+
)
529+
)
530+
return False
531+
532+
return True
533+
534+
535+
def accept_user_access_requests(request, access_type, request_id):
536+
json_response = {}
537+
access_mapping = UserAccessMapping.get_access_request(request_id)
538+
if not is_request_valid(request_id, access_mapping):
539+
json_response["error"] = USER_REQUEST_IN_PROCESS_ERR_MSG.format(
540+
request_id=request_id,
541+
)
542+
return json_response
543+
544+
requester = access_mapping.user_identity.user.email
545+
if request.user.username == requester:
546+
json_response["error"] = USER_REQUEST_PERMISSION_DENIED_ERR_MSG
547+
return json_response
548+
549+
access_label = access_mapping.access.access_label
550+
551+
try:
552+
permissions = _get_approver_permissions(access_type, access_label)
553+
approver_permissions = permissions["approver_permissions"]
554+
if not helper.check_user_permissions(
555+
request.user, list(approver_permissions.values())
556+
):
557+
logger.debug(USER_REQUEST_PERMISSION_DENIED_ERR_MSG)
558+
json_response["error"] = USER_REQUEST_PERMISSION_DENIED_ERR_MSG
559+
return json_response
560+
561+
is_primary_approver = (
562+
access_mapping.is_pending()
563+
and request.user.user.has_permission(approver_permissions["1"])
564+
)
565+
is_secondary_approver = (
566+
access_mapping.is_secondary_pending()
567+
and request.user.user.has_permission(approver_permissions["2"])
568+
)
569+
570+
if not (is_primary_approver or is_secondary_approver):
571+
logger.debug(USER_REQUEST_PERMISSION_DENIED_ERR_MSG)
572+
json_response["error"] = USER_REQUEST_PERMISSION_DENIED_ERR_MSG
573+
return json_response
574+
if is_primary_approver and "2" in approver_permissions:
575+
access_mapping.approver_1 = request.user.user
576+
access_mapping.update_access_status("SecondaryPending")
577+
json_response["msg"] = USER_REQUEST_SECONDARY_PENDING_MSG.format(
578+
request_id=request_id, approved_by=request.user.username
579+
)
580+
logger.debug(
581+
USER_REQUEST_SECONDARY_PENDING_MSG.format(
582+
request_id=request_id, approved_by=request.user.username
583+
)
584+
)
585+
else:
586+
json_response = run_accept_request_task(
587+
is_primary_approver,
588+
access_mapping,
589+
request,
590+
request_id,
591+
access_type,
592+
access_label,
593+
)
594+
except Exception as e:
595+
return process_error_response(e)
596+
597+
return json_response
598+
599+
600+
def run_accept_request_task(
601+
is_primary_approver, access_mapping, request, request_id, access_type, access_label
602+
):
603+
json_response = {}
604+
json_response["status"] = []
605+
if is_primary_approver:
606+
access_mapping.approver_1 = request.user.user
607+
else:
608+
access_mapping.approver_2 = request.user.user
609+
json_response["msg"] = REQUEST_PROCESS_MSG.format(request_id=request_id)
610+
611+
with transaction.atomic():
612+
try:
613+
access_mapping.update_access_status("Processing")
614+
615+
background_task(
616+
"run_accept_request",
617+
json.dumps({"request_id": request_id, "access_type": access_type}),
618+
)
619+
except Exception as e:
620+
logger.exception(e)
621+
raise Exception(
622+
"Error in accepting the request - {request_id}. Please try again.".format(
623+
request_id=request_id
624+
)
625+
)
626+
627+
json_response["status"].append(
628+
{
629+
"title": REQUEST_SUCCESS_MSG["title"].format(request_id=request_id),
630+
"msg": REQUEST_SUCCESS_MSG["msg"].format(
631+
access_label=json.dumps(access_label)
632+
),
633+
}
634+
)
635+
636+
return json_response
637+
638+
639+
def decline_individual_access(request, access_type, request_id, reason):
640+
json_response = {}
641+
access_mapping = UserAccessMapping.get_access_request(request_id)
642+
if not is_request_valid(request_id, access_mapping):
643+
json_response["error"] = USER_REQUEST_IN_PROCESS_ERR_MSG.format(
644+
request_id=request_id,
645+
)
646+
return json_response
647+
648+
json_response = validate_approver_permissions(
649+
access_mapping, access_type, request, request_id
650+
)
651+
if "error" in json_response:
652+
return json_response
653+
654+
with transaction.atomic():
655+
access_mapping.decline_access(reason)
656+
if hasattr(access_mapping, "approver_1"):
657+
access_mapping.decline_reason = reason
658+
if access_mapping.approver_1 is not None:
659+
access_mapping.approver_2 = request.user.user
660+
else:
661+
access_mapping.approver_1 = request.user.user
662+
else:
663+
access_mapping.reason = reason
664+
access_mapping.approver = request.user.username
665+
666+
access_mapping.save()
667+
668+
access_module = helper.get_available_access_module_from_tag(access_type)
669+
access_labels = [access_mapping.access.access_label]
670+
description = access_module.combine_labels_desc(access_labels)
671+
notifications.send_mail_for_request_decline(
672+
request, description, request_id, reason, access_type
673+
)
674+
675+
logger.debug(
676+
USER_REQUEST_DECLINE_MSG.format(
677+
request_id=request_id,
678+
decline_reason=reason,
679+
)
680+
)
681+
json_response = {}
682+
json_response["msg"] = USER_REQUEST_DECLINE_MSG.format(
683+
request_id=request_id,
684+
decline_reason=reason,
685+
)
686+
return json_response

0 commit comments

Comments
 (0)