예제 #1
0
    def set_locked_version(self, tallySheetVersion: TallySheetVersion):
        if tallySheetVersion is None:
            if not has_role_based_access(self, ACCESS_TYPE_UNLOCK):
                raise ForbiddenException(
                    message="User not authorized to unlock the tally sheet.",
                    code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_UNLOCK)

            self.submission.set_locked_version(submissionVersion=None)
        else:
            if self.template.is_submit_allowed():
                if self.submittedVersionId is None:
                    raise ForbiddenException(
                        message=
                        "Data entry tally sheet cannot be locked before submitting",
                        code=MESSAGE_CODE_TALLY_SHEET_CANNOT_LOCK_BEFORE_SUBMIT
                    )
                elif self.submittedStamp.createdBy == get_user_name():
                    raise ForbiddenException(
                        message=
                        "Data entry tally sheet submitted user is not allowed to lock/unlock.",
                        code=
                        MESSAGE_CODE_TALLY_SHEET_SAME_USER_CANNOT_SAVE_AND_SUBMIT
                    )

            if not has_role_based_access(self, ACCESS_TYPE_LOCK):
                raise ForbiddenException(
                    message="User is not authorized to lock the tally sheet.",
                    code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_LOCK)

            self.submission.set_locked_version(
                submissionVersion=tallySheetVersion.submissionVersion)

        self.update_status_report()
예제 #2
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
예제 #3
0
    def get_tally_sheet_workflow_instance_actions(self, workflow_instance):
        tally_sheet_workflow_instance_actions = db.session.query(
            WorkflowActionModel.workflowActionId,
            WorkflowActionModel.actionName, WorkflowActionModel.actionType,
            WorkflowActionModel.fromStatus,
            WorkflowActionModel.toStatus).filter(
                WorkflowActionModel.workflowId ==
                workflow_instance.workflowId).order_by(
                    WorkflowActionModel.workflowActionId).all()

        processed_tally_sheet_workflow_instance_actions = []
        for tally_sheet_workflow_instance_action in tally_sheet_workflow_instance_actions:
            processed_tally_sheet_workflow_instance_actions.append({
                "workflowActionId":
                tally_sheet_workflow_instance_action.workflowActionId,
                "actionName":
                tally_sheet_workflow_instance_action.actionName,
                "actionType":
                tally_sheet_workflow_instance_action.actionType,
                "fromStatus":
                tally_sheet_workflow_instance_action.fromStatus,
                "toStatus":
                tally_sheet_workflow_instance_action.toStatus,
                "allowed":
                tally_sheet_workflow_instance_action.fromStatus ==
                workflow_instance.status,
                "authorized":
                has_role_based_access(
                    tally_sheet=self,
                    access_type=tally_sheet_workflow_instance_action.actionType
                )
            })

        return processed_tally_sheet_workflow_instance_actions
예제 #4
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)
예제 #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 get_all(electionId=None,
            areaId=None,
            tallySheetCode=None,
            voteType=None,
            partyId=None,
            limit=None,
            offset=None):
    # Filter by authorized areas
    user_access_area_ids: Set[int] = get_user_access_area_ids()

    query_args = [Model]
    query_filters = [
        Submission.Model.areaId.in_(user_access_area_ids),
        Template.Model.templateId == Model.templateId,
        Submission.Model.submissionId == Model.tallySheetId,
        Election.Model.electionId == Submission.Model.electionId
    ]
    query_group_by = [Model.tallySheetId]

    if areaId is not None:
        query_filters.append(Submission.Model.areaId == areaId)

    if electionId is not None:
        election = Election.get_by_id(electionId=electionId)
        query_filters.append(
            Election.Model.electionId.in_(
                election.get_this_and_below_election_ids()))

    if tallySheetCode is not None:
        query_filters.append(Template.Model.templateName == tallySheetCode)

    if voteType is not None:
        query_filters.append(Election.Model.voteType == voteType)

    if partyId is not None:
        query_filters += [
            MetaData.Model.metaId == Model.metaId,
            MetaData.Model.metaDataKey == "partyId",
            MetaData.Model.metaDataValue == partyId
        ]

    tally_sheet_list = db.session.query(*query_args).filter(
        *query_filters).group_by(*query_group_by).order_by(Model.tallySheetId)

    tally_sheet_list = get_paginated_query(query=tally_sheet_list,
                                           limit=limit,
                                           offset=offset)

    authorized_tally_sheet_list = []
    for tally_sheet in tally_sheet_list:
        if has_role_based_access(election=tally_sheet.submission.election,
                                 tally_sheet_code=tally_sheet.tallySheetCode,
                                 access_type=WORKFLOW_ACTION_TYPE_VIEW):
            authorized_tally_sheet_list.append(tally_sheet)

    return authorized_tally_sheet_list
예제 #7
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)
예제 #8
0
    def _get_allowed_workflow_actions(self, workflow_action_type):
        workflow_actions = db.session.query(WorkflowActionModel).filter(
            WorkflowActionModel.fromStatus == WorkflowInstance.Model.status,
            WorkflowInstance.Model.workflowInstanceId ==
            self.tallySheet.workflowInstanceId,
            Workflow.Model.workflowId == WorkflowInstance.Model.workflowId,
            WorkflowActionModel.workflowId ==
            WorkflowInstance.Model.workflowId,
            WorkflowActionModel.actionType == workflow_action_type).all()

        authorized_workflow_actions = []
        for workflow_action in workflow_actions:
            if has_role_based_access(tally_sheet=self.tallySheet,
                                     access_type=workflow_action.actionType):
                authorized_workflow_actions.append(workflow_action)

        return authorized_workflow_actions
예제 #9
0
def get_all(electionId=None, areaId=None, tallySheetCode=None, voteType=None):
    # Filter by authorized areas
    user_access_area_ids: Set[int] = get_user_access_area_ids()

    query_args = [Model]
    query_filters = [
        Submission.Model.areaId.in_(user_access_area_ids),
        Template.Model.templateId == Model.templateId,
        Submission.Model.submissionId == Model.tallySheetId,
        Election.Model.electionId == Submission.Model.electionId
    ]
    query_group_by = [Model.tallySheetId]

    if areaId is not None:
        query_filters.append(Submission.Model.areaId == areaId)

    if electionId is not None:
        election = Election.get_by_id(electionId=electionId)
        query_filters.append(
            Election.Model.electionId.in_(
                election.get_this_and_below_election_ids()))

    if tallySheetCode is not None:
        query_filters.append(Template.Model.templateName == tallySheetCode)

    if voteType is not None:
        query_filters.append(Election.Model.voteType == voteType)

    tally_sheet_list = db.session.query(*query_args).filter(
        *query_filters).group_by(*query_group_by)

    authorized_tally_sheet_list = []
    for tally_sheet in tally_sheet_list:
        if has_role_based_access(tally_sheet=tally_sheet,
                                 access_type=WORKFLOW_ACTION_TYPE_VIEW):
            authorized_tally_sheet_list.append(tally_sheet)

    return authorized_tally_sheet_list
def _append_latest_workflow_instance_to_cached_tally_sheets(
        cached_tally_sheets):
    cached_tally_sheet_ids = [
        cached_tally_sheet["tallySheetId"]
        for cached_tally_sheet in cached_tally_sheets
    ]

    tally_sheet_workflow_instances = WorkflowInstance.Model.query.filter(
        WorkflowInstance.Model.workflowInstanceId ==
        TallySheet.Model.workflowInstanceId,
        TallySheet.Model.tallySheetId.in_(cached_tally_sheet_ids)).all()
    tally_sheet_workflow_instances_map = {
        tally_sheet_workflow_instance.workflowInstanceId:
        tally_sheet_workflow_instance
        for tally_sheet_workflow_instance in tally_sheet_workflow_instances
    }

    tally_sheet_elections = db.session.query(
        Election.Model.electionId, Election.Model.electionTemplateName,
        Election.Model.voteType).filter(
            Election.Model.electionId == Submission.Model.electionId,
            Submission.Model.submissionId.in_(cached_tally_sheet_ids)).all()
    tally_sheet_elections_map = {
        tally_sheet_election.electionId: tally_sheet_election
        for tally_sheet_election in tally_sheet_elections
    }

    for tally_sheet_index in range(len(cached_tally_sheet_ids)):
        cached_tally_sheet = cached_tally_sheets[tally_sheet_index]
        tally_sheet_workflow_instance_id = cached_tally_sheet[
            "workflowInstanceId"]

        workflow_instance = tally_sheet_workflow_instances_map[
            tally_sheet_workflow_instance_id]
        workflow_actions = workflow_instance.workflow.actions

        # Convert the actions list to a list of dictionary objects due to following issue
        # https://github.com/ECLK/results-tabulation/issues/708
        workflow_action_dict_list = []
        for workflow_action in workflow_actions:
            workflow_action_dict_list.append({
                "workflowActionId":
                workflow_action.workflowActionId,
                "actionName":
                workflow_action.actionName,
                "actionType":
                workflow_action.actionType,
                "fromStatus":
                workflow_action.fromStatus,
                "toStatus":
                workflow_action.toStatus,
                "allowed":
                workflow_action.fromStatus == workflow_instance.status,
                "authorized":
                has_role_based_access(
                    election=tally_sheet_elections_map[
                        cached_tally_sheet["electionId"]],
                    tally_sheet_code=cached_tally_sheet["tallySheetCode"],
                    access_type=workflow_action.actionType)
            })

        setattr(workflow_instance, "actions", workflow_action_dict_list)
        cached_tally_sheet["workflowInstance"] = WorkflowInstanceSchema().dump(
            workflow_instance).data

    return cached_tally_sheets