1010from django .http import JsonResponse
1111from django .http .response import HttpResponse , HttpResponseBadRequest
1212from django .template .response import TemplateResponse
13- from django .core .exceptions import ObjectDoesNotExist
13+ from django .core .exceptions import ObjectDoesNotExist , PermissionDenied
1414from django .utils .decorators import method_decorator
1515from django .views .decorators .csrf import csrf_exempt
1616from django .views .decorators .debug import sensitive_post_parameters
1717from apps .dot_ext .constants import TOKEN_ENDPOINT_V3_KEY
18+ from oauthlib .oauth2 .rfc6749 .errors import AccessDeniedError as AccessDeniedTokenCustomError
1819from oauth2_provider .exceptions import OAuthToolkitError
1920from oauth2_provider .views .base import app_authorized
2021from oauth2_provider .models import get_refresh_token_model , get_access_token_model
@@ -79,50 +80,8 @@ def _wrapped(request, *args, **kwargs):
7980 return _wrapped
8081
8182
82- def check_v3_endpoint_access (view_func ):
83- @wraps (view_func )
84- def _wrapped (request , * args , ** kwargs ):
85- # 4250-TODO how do we not call this so many times?
86- path_info = request .__dict__ .get ('path_info' )
87- version = get_api_version_number_from_url (path_info )
88- if version != Versions .V3 :
89- return view_func (request , * args , ** kwargs )
90-
91- flag = get_waffle_flag_model ().get ('v3_early_adopter' )
92- req_meta = request .META
93- url_query = parse_qs (req_meta .get ('QUERY_STRING' ))
94- client_id = url_query .get ('client_id' , [None ])
95- try :
96- if client_id [0 ]:
97- application = get_application_model ().objects .get (client_id = client_id [0 ])
98- else :
99- url_query = parse_qs (request ._body .decode ('utf-8' ))
100- refresh_token_from_request = url_query .get ('refresh_token' , [None ])
101- refresh_token = get_refresh_token_model ().objects .get (token = refresh_token_from_request [0 ])
102- application = get_application_model ().objects .get (id = refresh_token .application_id )
103-
104- application_user = get_user_model ().objects .get (id = application .user_id )
105-
106- if flag .id is not None and flag .is_active_for_user (application_user ):
107- return view_func (request , * args , ** kwargs )
108- else :
109- return JsonResponse (
110- {'status_code' : 403 , 'message' : settings .APPLICATION_DOES_NOT_HAVE_V3_ENABLED_YET .format (application .name )},
111- status = 403 ,
112- )
113- except ObjectDoesNotExist :
114- # 4250-TODO Do we need this?
115- return JsonResponse (
116- {'status_code' : 500 , 'message' : 'Error retrieving data' },
117- status = 500 ,
118- )
119-
120- return _wrapped
121-
122-
12383@method_decorator (csrf_exempt , name = "dispatch" )
12484@method_decorator (require_post_state_decorator , name = "dispatch" )
125- @method_decorator (check_v3_endpoint_access , name = "dispatch" )
12685class AuthorizationView (DotAuthorizationView ):
12786 """
12887 Override the base authorization view from dot to
@@ -274,6 +233,27 @@ def get(self, request, *args, **kwargs):
274233 kwargs ['code_challenge_method' ] = request .GET .get ('code_challenge_method' , None )
275234 return super ().get (request , * args , ** kwargs )
276235
236+ def validate_v3_authorization_request (self ):
237+ flag = get_waffle_flag_model ().get ('v3_early_adopter' )
238+ req_meta = self .request .META
239+ url_query = parse_qs (req_meta .get ('QUERY_STRING' ))
240+ client_id = url_query .get ('client_id' , [None ])
241+ try :
242+ application = get_application_model ().objects .get (client_id = client_id [0 ])
243+ application_user = get_user_model ().objects .get (id = application .user_id )
244+ if flag .id is not None and flag .is_active_for_user (application_user ):
245+ return
246+ else :
247+ raise AccessDeniedTokenCustomError (
248+ description = settings .APPLICATION_DOES_NOT_HAVE_V3_ENABLED_YET .format (application .name )
249+ )
250+ except ObjectDoesNotExist :
251+ # 4250-TODO Do we need this?
252+ return JsonResponse (
253+ {'status_code' : 500 , 'message' : 'Error retrieving data' },
254+ status = 500 ,
255+ )
256+
277257 def form_valid (self , form ):
278258 client_id = form .cleaned_data ["client_id" ]
279259 application = get_application_model ().objects .get (client_id = client_id )
@@ -312,6 +292,12 @@ def form_valid(self, form):
312292 refresh_token_delete_cnt = 0
313293
314294 try :
295+ path_info = self .request .__dict__ .get ('path_info' )
296+ version = get_api_version_number_from_url (path_info )
297+ # If it is not version 3, we don't need to check anything, just return
298+ if version == Versions .V3 :
299+ self .validate_v3_authorization_request ()
300+
315301 if not scopes :
316302 # Since the create_authorization_response will re-inject scopes even when none are
317303 # valid, we want to pre-emptively treat this as an error case
@@ -441,7 +427,6 @@ def dispatch(self, request, uuid, *args, **kwargs):
441427 return result
442428
443429
444- # @method_decorator(check_v3_endpoint_access, name="dispatch")
445430@method_decorator (csrf_exempt , name = "dispatch" )
446431class TokenView (DotTokenView ):
447432
@@ -461,13 +446,47 @@ def validate_token_endpoint_request_body(self, request):
461446 description = f"Invalid parameters in request: { invalid_parameters } "
462447 )
463448
449+ def validate_v3_token_call (self , request ) -> None :
450+ flag = get_waffle_flag_model ().get ('v3_early_adopter' )
451+ req_meta = request .META
452+ url_query = parse_qs (req_meta .get ('QUERY_STRING' ))
453+ try :
454+ url_query = parse_qs (request ._body .decode ('utf-8' ))
455+ refresh_token_from_request = url_query .get ('refresh_token' , [None ])
456+ refresh_token = get_refresh_token_model ().objects .get (token = refresh_token_from_request [0 ])
457+ application = get_application_model ().objects .get (id = refresh_token .application_id )
458+ application_user = get_user_model ().objects .get (id = application .user_id )
459+
460+ if flag .id is not None and flag .is_active_for_user (application_user ):
461+ return
462+ else :
463+ raise PermissionDenied (
464+ settings .APPLICATION_DOES_NOT_HAVE_V3_ENABLED_YET .format (application .name )
465+ )
466+ except ObjectDoesNotExist :
467+ # 4250-TODO Do we need this?
468+ return JsonResponse (
469+ {'status_code' : 500 , 'message' : 'Error retrieving data' },
470+ status = 500 ,
471+ )
472+
464473 @method_decorator (sensitive_post_parameters ("password" ))
465474 def post (self , request , * args , ** kwargs ):
475+ path_info = self .request .__dict__ .get ('path_info' )
476+ version = get_api_version_number_from_url (path_info )
477+ # If it is not version 3, we don't need to check anything, just return
466478 try :
479+ if version == Versions .V3 :
480+ self .validate_v3_token_call (request )
467481 self .validate_token_endpoint_request_body (request )
468482 app = validate_app_is_active (request )
469483 except (InvalidClientError , InvalidGrantError , InvalidRequestError ) as error :
470484 return json_response_from_oauth2_error (error )
485+ except PermissionDenied as e :
486+ return JsonResponse (
487+ {'status_code' : 403 , 'message' : str (e )},
488+ status = 403 ,
489+ )
471490
472491 url , headers , body , status = self .create_token_response (request )
473492
0 commit comments