def authenticate(func, *args, **kwargs): print("\n\n\n\n####### request.headers ### [START]") print(request.headers) print("####### request.headers ### [END]\n\n\n") claims: Dict = get_claims() if SUB not in claims: UnauthorizedException( message="No valid user found.", code=MESSAGE_CODE_USER_NOT_FOUND ) if ROLE_CLAIM not in claims or claims.get(ROLE_CLAIM) == []: UnauthorizedException( message="No valid user role found.", code=MESSAGE_CODE_USER_NOT_AUTHORIZED ) user_name = claims.get(SUB) connexion.context[USER_NAME] = user_name connexion.context[USER_ROLES] = [role.replace(ROLE_PREFIX, "") for role in claims.get(ROLE_CLAIM) if role.startswith(ROLE_PREFIX)] return func(*args, **kwargs)
def get_claims() -> Dict[str, Dict]: """ Gets all user role related claims from all the claims in token_info. Decoded JWT information are set to connexion.context['token_info'] by the security decorators in connexion. :return: dict of claim id to claim value. """ if 'token_info' not in connexion.context.keys(): UnauthorizedException("No claims found.") claims: dict = connexion.context['token_info'] filtered_claims = {} filtered_claim_keys = [ ROLE_CLAIM_PREFIX + ADMIN_ROLE, ROLE_CLAIM_PREFIX + DATA_EDITOR_ROLE, ROLE_CLAIM_PREFIX + POLLING_DIVISION_REPORT_VIEWER_ROLE, ROLE_CLAIM_PREFIX + POLLING_DIVISION_REPORT_GENERATOR_ROLE, ROLE_CLAIM_PREFIX + ELECTORAL_DISTRICT_REPORT_VIEWER_ROLE, ROLE_CLAIM_PREFIX + ELECTORAL_DISTRICT_REPORT_GENERATOR_ROLE, ROLE_CLAIM_PREFIX + NATIONAL_REPORT_VIEWER_ROLE, ROLE_CLAIM_PREFIX + NATIONAL_REPORT_GENERATOR_ROLE, ROLE_CLAIM_PREFIX + EC_LEADERSHIP_ROLE, SUB ] for role_claim_key in filtered_claim_keys: if role_claim_key in claims.keys(): filtered_claims[role_claim_key] = claims.get(role_claim_key) return filtered_claims
def authorize_workflow_action(self, workflow_action, content=None): from auth import has_role_based_access if not has_role_based_access(election=self.tallySheet.election, tally_sheet_code=self.tallySheet.tallySheetCode, access_type=workflow_action.actionType): UnauthorizedException(message="Not allowed to %s" % (workflow_action.actionName), code=MESSAGE_CODE_WORKFLOW_ACTION_NOT_AUTHORIZED) if workflow_action.actionType == WORKFLOW_ACTION_TYPE_REQUEST_CHANGES and workflow_action.toStatus in [ WORKFLOW_STATUS_TYPE_CHANGES_REQUESTED]: from orm.entities import TallySheet from orm.entities.TallySheet import TallySheetTallySheetModel extended_election = self.tallySheet.election.get_extended_election() verified_parent_tally_sheets = db.session.query( TallySheet.Model.tallySheetId ).filter( TallySheetTallySheetModel.childTallySheetId == self.tallySheet.tallySheetId, TallySheet.Model.tallySheetId == TallySheetTallySheetModel.parentTallySheetId, WorkflowInstance.Model.workflowInstanceId == TallySheet.Model.workflowInstanceId, WorkflowInstance.Model.status.in_( extended_election.tally_sheet_verified_statuses_list() ) ).all() if len(verified_parent_tally_sheets) > 0: raise MethodNotAllowedException( message="Cannot request changes since the data from this report has been already aggregated in verified summary reports.", code=MESSAGE_CODE_TALLY_SHEET_CANNOT_BE_UNLOCKED_WHILE_HAVING_VERIFIED_PARENT_SUMMARY_SHEETS)
def get_by_id(tallySheetId, tallySheetCode=None): # Filter by authorized areas user_access_area_ids: Set[int] = get_user_access_area_ids() query_args = [TallySheetModel] query_filters = [ TallySheetModel.tallySheetId == tallySheetId, TallySheetModel.areaId.in_(user_access_area_ids), Template.Model.templateId == Model.templateId ] query_group_by = [Model.tallySheetId] if tallySheetCode is not None: query_filters.append(Template.Model.templateName == tallySheetCode) tally_sheet = db.session.query(*query_args).filter( *query_filters).group_by(*query_group_by).one_or_none() # Validate the authorization if tally_sheet is not None and not has_role_based_access( election=tally_sheet.election, tally_sheet_code=tally_sheet.tallySheetCode, access_type=WORKFLOW_ACTION_TYPE_VIEW): raise UnauthorizedException( message="Not authorized to view tally sheet. (tallySheetId=%d)" % tallySheetId, code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_VIEW) return tally_sheet
def authorize_workflow_action(self, workflow_action, content=None): from auth import has_role_based_access if not has_role_based_access(self.tallySheet, workflow_action.actionType): UnauthorizedException( message="Not allowed to %s" % (workflow_action.actionName), code=MESSAGE_CODE_WORKFLOW_ACTION_NOT_AUTHORIZED)
def authenticate(func, *args, **kwargs): claims: Dict = get_claims() if SUB not in claims: UnauthorizedException("No valid user found.") else: user_name = claims.get(SUB) connexion.context[USER_NAME] = user_name return func(*args, **kwargs)
def get_jwt_token(): if JWT_TOKEN_HEADER_KEY not in request.headers: raise UnauthorizedException(message="No authorization header found.", code=MESSAGE_CODE_USER_NOT_AUTHENTICATED) print("######### request.headers.get(JWT_TOKEN_HEADER_KEY) ###### ", request.headers.get(JWT_TOKEN_HEADER_KEY)) return request.headers.get(JWT_TOKEN_HEADER_KEY)
def decode_token(token): try: token = jwt.decode(token, key=JWT_SECRET, options={ "verify_signature": False, "verify_exp": False }) return token except Exception as e: raise UnauthorizedException("Invalid authorization token.")
def on_before_workflow_action(self, workflow_action, tally_sheet_version): if workflow_action.actionType in [WORKFLOW_ACTION_TYPE_VERIFY]: if tally_sheet_version.createdBy == get_user_name(): raise UnauthorizedException("You cannot verify the data last edited by yourself.", code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_VERIFY) if workflow_action.actionType in [WORKFLOW_ACTION_TYPE_SAVE, WORKFLOW_ACTION_TYPE_EDIT]: # To ignore the completion check pass else: return super(ExtendedTallySheetDataEntry, self).on_before_workflow_action( workflow_action=workflow_action, tally_sheet_version=tally_sheet_version)
def decode_token(token): try: token = jwt.decode( token, key=JWT_SECRET, options={"verify_signature": False, "verify_exp": False} ) return token except Exception as e: raise UnauthorizedException( message="Invalid authorization token.", code=MESSAGE_CODE_USER_NOT_AUTHENTICATED )
def authenticate(func, *args, **kwargs): print("\n\n\n\n####### request.headers ### [START]") print(request.headers) print("####### request.headers ### [END]\n\n\n") claims: Dict = get_claims() if SUB not in claims: UnauthorizedException("No valid user found.") else: user_name = claims.get(SUB) connexion.context[USER_NAME] = user_name return func(*args, **kwargs)
def decode_token(token): try: token = jwt.decode( token, key=JWT_SECRET, options={"verify_signature": False, "verify_exp": False} ) return token except Exception as e: raise UnauthorizedException( message="Invalid authorization token.", code=MESSAGE_CODE_INVALID_AUTHORIZATION_TOKEN )
def authorize(func, required_roles=None, *args, **kwargs): if required_roles is None: return func(*args, **kwargs) if 'token_info' not in connexion.context.keys(): UnauthorizedException("No claims found.") claims: Dict = get_role_claims() claim_found = False for role in required_roles: claim = CLAIM_PREFIX + role if claim not in claims.keys(): continue claim_found = True if not claim_found: UnauthorizedException("No matching claim found.") else: return func(*args, **kwargs)
def token_validator(self, obj): if HTTP_AUTH not in obj: raise TokenException("Token is not provided") auth_key = obj[HTTP_AUTH] try: self.username = Token.objects.get(key=auth_key).user.username user_obj = User.objects.get(username=self.username) except: raise TokenException("Invalid Token") if not user_obj.is_superuser: raise UnauthorizedException("Unauthorised access")
def create(cls, tallySheetId): tally_sheet = TallySheet.get_by_id(tallySheetId=tallySheetId) if tally_sheet is None: raise NotFoundException( message="Tally sheet not found. (tallySheetId=%d)" % tallySheetId, code=MESSAGE_CODE_TALLY_SHEET_NOT_FOUND ) # Validate the authorization if not has_role_based_access(tally_sheet=tally_sheet, access_type=WORKFLOW_ACTION_TYPE_SAVE): raise UnauthorizedException( message="Not authorized to edit tally sheet. (tallySheetId=%d)" % tallySheetId, code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_EDIT ) return TallySheetVersionModel(tallySheetId=tallySheetId)
def authorize(func, required_roles=None, *args, **kwargs): from orm.entities import Area from orm.enums import AreaTypeEnum if required_roles is None: return func(*args, **kwargs) claims: Dict = get_claims() claim_found = False user_access_area_ids = [] for role in required_roles: claim = ROLE_CLAIM_PREFIX + role if claim not in claims.keys(): continue claim_found = True user_access_area_ids.extend( [x.get(AREA_ID) for x in claims.get(claim)]) if role is NATIONAL_REPORT_VIEWER_ROLE or role is NATIONAL_REPORT_GENERATOR_ROLE: areas = db.session.query(Area.Model.areaId).filter( Area.Model.areaType == AreaTypeEnum.Country).all() user_access_area_ids.extend([area.areaId for area in areas]) elif role is EC_LEADERSHIP_ROLE: areas = db.session.query(Area.Model.areaId).filter( Area.Model.areaType == AreaTypeEnum.ElectionCommission).all() user_access_area_ids.extend([area.areaId for area in areas]) if not claim_found: UnauthorizedException("No matching claim found.") else: connexion.context[USER_ACCESS_AREA_IDS] = set(user_access_area_ids) return func(*args, **kwargs)
def authorize(func, required_roles=None, *args, **kwargs): from orm.enums import AreaTypeEnum if required_roles is None: return func(*args, **kwargs) claims: Dict = get_claims() claim_found = False user_access_area_ids = [] for role in required_roles: claim = AREA_CLAIM_PREFIX + role if claim not in claims.keys(): continue if not has_role(role): continue claim_found = True claim_area_ids = [x.get(AREA_ID) for x in claims.get(claim)] if role is DATA_EDITOR_ROLE: # To list, view, submit and lock data entry tally sheets. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.CountingCentre, voteTypes=[ VOTE_TYPES.Postal, VOTE_TYPES.NonPostal, VOTE_TYPES.Quarantine, VOTE_TYPES.Displaced ]) ]) elif role is POLLING_DIVISION_REPORT_VIEWER_ROLE: # To list and view polling division wise reports. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.PollingDivision) ]) elif role is POLLING_DIVISION_REPORT_VERIFIER_ROLE: # To list, view and lock polling division wise reports. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.PollingDivision) ]) # To list, view and unlock counting wise reports. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.CountingCentre, voteTypes=[VOTE_TYPES.NonPostal]) ]) elif role is ELECTORAL_DISTRICT_REPORT_VIEWER_ROLE: # To list, view and lock PRE-30-ED and PRE-30-PV. user_access_area_ids.extend(claim_area_ids) elif role is ELECTORAL_DISTRICT_REPORT_VERIFIER_ROLE: # To list, view and lock PRE-30-ED and PRE-30-PV. user_access_area_ids.extend(claim_area_ids) # To list, view and unlock polling division reports. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.PollingDivision) ]) # To list, view and unlock postal vote counting wise reports. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.CountingCentre, voteTypes=[ VOTE_TYPES.Postal, VOTE_TYPES.Quarantine, VOTE_TYPES.Displaced ]) ]) elif role is NATIONAL_REPORT_VIEWER_ROLE: # To list, view and lock All Island Reports. user_access_area_ids.extend(claim_area_ids) elif role is NATIONAL_REPORT_VERIFIER_ROLE: # To list, view and lock All Island Reports. user_access_area_ids.extend(claim_area_ids) # To list, view and unlock PR-30-PV and PRE-30-ED. user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.ElectoralDistrict) ]) elif role is EC_LEADERSHIP_ROLE: for country_id in claim_area_ids: # To list, view and unlock All Island Reports user_access_area_ids.extend(claim_area_ids) user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.ElectoralDistrict) ]) user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.PollingDivision) ]) user_access_area_ids.extend([ area.areaId for area in _get_role_area_ids( parentAreaIds=claim_area_ids, areaType=AreaTypeEnum.CountingCentre) ]) if not claim_found: UnauthorizedException(message="No matching claim found.", code=MESSAGE_CODE_NO_MATCHING_CLAIM_FOUND) else: connexion.context[USER_ACCESS_AREA_IDS] = set(user_access_area_ids) return func(*args, **kwargs)
def get_jwt_token(): if JWT_TOKEN_HEADER_KEY not in request.headers: raise UnauthorizedException("No authorization header found.") return request.headers.get(JWT_TOKEN_HEADER_KEY)
def authorize(func, required_roles=None, *args, **kwargs): global_area_map = init_global_area_map() if required_roles is None: return func(*args, **kwargs) claims: Dict = get_claims() claim_found = False user_access_area_ids = [] for role in required_roles: claim = AREA_CLAIM_PREFIX + role if claim not in claims.keys(): continue if not has_role(role): continue claim_found = True claim_area_ids = [x.get(AREA_ID) for x in claims.get(claim)] if role is DATA_EDITOR_ROLE: for electoral_district_id in claim_area_ids: # To list, view, submit and lock postal data entry tally sheets. if electoral_district_id in global_area_map[ ElectoralDistricts][CountingCentres][Postal]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][CountingCentres] [Postal][electoral_district_id]) # To list, view, submit and lock non postal data entry tally sheets. if electoral_district_id in global_area_map[ ElectoralDistricts][CountingCentres][NonPostal]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][CountingCentres] [NonPostal][electoral_district_id]) elif role is POLLING_DIVISION_REPORT_VIEWER_ROLE: for electoral_district_id in claim_area_ids: # To list, view and lock PRE-30-PD. if electoral_district_id in global_area_map[ ElectoralDistricts][PollingDivisions]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][PollingDivisions] [electoral_district_id]) elif role is POLLING_DIVISION_REPORT_VERIFIER_ROLE: for electoral_district_id in claim_area_ids: # To list, view and lock PRE-30-PD. if electoral_district_id in global_area_map[ ElectoralDistricts][PollingDivisions]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][PollingDivisions] [electoral_district_id]) # To list, view and unlock non postal data entry tally sheets. if electoral_district_id in global_area_map[ ElectoralDistricts][CountingCentres][NonPostal]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][CountingCentres] [NonPostal][electoral_district_id]) elif role is ELECTORAL_DISTRICT_REPORT_VIEWER_ROLE: # To list, view and lock PRE-30-ED and PRE-30-PV. user_access_area_ids.extend(claim_area_ids) elif role is ELECTORAL_DISTRICT_REPORT_VERIFIER_ROLE: # To list, view and lock PRE-30-ED and PRE-30-PV. user_access_area_ids.extend(claim_area_ids) for electoral_district_id in claim_area_ids: # To list, view and unlock PR-30-PD. if electoral_district_id in global_area_map[ ElectoralDistricts][PollingDivisions]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][PollingDivisions] [electoral_district_id]) # To list, view and unlock postal data entry tally sheets. if electoral_district_id in global_area_map[ ElectoralDistricts][CountingCentres][Postal]: user_access_area_ids.extend( global_area_map[ElectoralDistricts][CountingCentres] [Postal][electoral_district_id]) elif role is NATIONAL_REPORT_VIEWER_ROLE: for electoral_district_id in claim_area_ids: # To list, view and lock All Island Reports user_access_area_ids.extend(claim_area_ids) elif role is NATIONAL_REPORT_VERIFIER_ROLE: for country_id in claim_area_ids: # To list, view and lock All Island Reports user_access_area_ids.extend(claim_area_ids) # To list, view and unlock PR-30-PV and PRE-30-ED. if country_id in global_area_map[Countries][ ElectoralDistricts]: user_access_area_ids.extend( global_area_map[Countries][ElectoralDistricts] [country_id]) elif role is EC_LEADERSHIP_ROLE: for country_id in claim_area_ids: # To list, view and unlock All Island Reports user_access_area_ids.extend(claim_area_ids) if country_id in global_area_map[Countries][ ElectoralDistricts]: user_access_area_ids.extend( global_area_map[Countries][ElectoralDistricts] [country_id]) if country_id in global_area_map[Countries][PollingDivisions]: user_access_area_ids.extend(global_area_map[Countries] [PollingDivisions][country_id]) if country_id in global_area_map[Countries][CountingCentres][ Postal]: user_access_area_ids.extend( global_area_map[Countries][CountingCentres][Postal] [country_id]) if country_id in global_area_map[Countries][CountingCentres][ NonPostal]: user_access_area_ids.extend( global_area_map[Countries][CountingCentres][NonPostal] [country_id]) if not claim_found: UnauthorizedException(message="No matching claim found.", code=MESSAGE_CODE_USER_NOT_AUTHORIZED) else: connexion.context[USER_ACCESS_AREA_IDS] = set(user_access_area_ids) return func(*args, **kwargs)