Пример #1
0
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
Пример #3
0
    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)
Пример #4
0
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
Пример #5
0
    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)
Пример #6
0
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)
Пример #8
0
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.")
Пример #9
0
    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)
Пример #10
0
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
        )
Пример #11
0
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)
Пример #12
0
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
        )
Пример #13
0
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)
Пример #14
0
    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")
Пример #15
0
    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)
Пример #16
0
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)
Пример #17
0
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)
Пример #18
0
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)