Beispiel #1
0
    def _update_state(self, program_id, editable):
        '''
        Just update the state of the program (not title etc.)
        '''
        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = session.query(model.Program).get(program_id)
            if not program:
                raise errors.MissingDocError("No such program")

            policy = user_session.policy.derive({
                'program': program,
            })

            if editable:
                program.finalised_date = None
                policy.verify('program_edit')
            else:
                policy.verify('program_edit')
                program.finalised_date = datetime.datetime.utcnow()

            act = Activities(session)
            if session.is_modified(program):
                act.record(user_session.user, program, ['state'])
            act.ensure_subscription(user_session.user, program, program,
                                    self.reason)
        self.get(program_id)
Beispiel #2
0
    def post(self, query_id):
        if query_id:
            raise errors.MethodError("Can't use POST for existing query.")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            custom_query = model.CustomQuery()
            self.update(custom_query, self.request_son)
            self.update_auto(custom_query, user_session.user)
            session.add(custom_query)

            policy = user_session.policy.derive({
                'custom_query': custom_query,
            })
            policy.verify('custom_query_add')

            session.flush()
            act = Activities(session)
            act.record(user_session.user, custom_query, ['create'])
            act.ensure_subscription(user_session.user, custom_query,
                                    custom_query, self.reason)

            query_id = str(custom_query.id)

        self.get(query_id)
Beispiel #3
0
    def delete(self, response_type_id):
        '''Delete'''

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            response_type = (session.query(model.ResponseType).get(
                (response_type_id, program_id)))
            if not response_type:
                raise errors.MissingDocError("No such response type")

            policy = user_session.policy.derive({
                'program':
                response_type.program,
                'surveygroups':
                response_type.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_type_del')

            session.delete(response_type)
            # No need for survey update: delete will fail if any measures are
            # using this RT

            act = Activities(session)
            act.record(user_session.user, response_type, ['delete'])
            act.ensure_subscription(user_session.user, response_type,
                                    response_type.program, self.reason)

        self.set_header("Content-Type", "text/plain")
        self.finish()
Beispiel #4
0
    def delete(self, organisation_id):
        if not organisation_id:
            raise errors.MethodError("Organisation ID required")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.MissingDocError("No such organisation")

            policy = user_session.policy.derive({
                'org':
                org,
                'surveygroups':
                org.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('org_del')

            act = Activities(session)
            if not org.deleted:
                act.record(user_session.user, org, ['delete'])
            act.ensure_subscription(user_session.user, org, org, self.reason)

            org.deleted = True

        self.finish()
Beispiel #5
0
    def delete(self, user_id):
        if not user_id:
            raise errors.MethodError("User ID required")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            user = session.query(model.AppUser).get(user_id)
            if not user:
                raise errors.MissingDocError("No such user")

            policy = user_session.policy.derive({
                'org': user.organisation,
                'user': user,
                'surveygroups': user.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('user_del')

            act = Activities(session)
            if not user.deleted:
                act.record(user_session.user, user, ['delete'])
            act.ensure_subscription(
                user_session.user, user, user.organisation, self.reason)

            user.deleted = True

        self.finish()
Beispiel #6
0
    def delete(self, program_id):
        '''
        Delete an existing program.
        '''
        if not program_id:
            raise errors.MethodError("Program ID required")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = session.query(model.Program).get(program_id)
            if not program:
                raise errors.MissingDocError("No such program")

            policy = user_session.policy.derive({
                'program':
                program,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('program_del')

            act = Activities(session)
            if not program.deleted:
                act.record(user_session.user, program, ['delete'])
            act.ensure_subscription(user_session.user, program, program,
                                    self.reason)

            program.deleted = True

        self.finish()
Beispiel #7
0
    def delete(self, submission_id):
        if submission_id == '':
            raise errors.MethodError("Submission ID required")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            submission = (session.query(model.Submission).get(submission_id))
            if not submission:
                raise errors.MissingDocError("No such submission")

            policy = user_session.policy.derive({
                'org':
                submission.organisation,
                'surveygroups':
                submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_del')

            act = Activities(session)
            if not submission.deleted:
                act.record(user_session.user, submission, ['delete'])
            act.ensure_subscription(user_session.user, submission,
                                    submission.organisation, self.reason)

            submission.deleted = True

        self.finish()
Beispiel #8
0
    def put(self, response_type_id):
        '''Update existing'''

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            response_type = (session.query(model.ResponseType).get(
                (response_type_id, program_id)))
            if not response_type:
                raise errors.MissingDocError("No such response type")

            policy = user_session.policy.derive({
                'program':
                response_type.program,
                'surveygroups':
                response_type.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_type_edit')

            if 'name' in self.request_son:
                rt_by_name = (session.query(model.ResponseType).filter(
                    model.ResponseType.program_id == program_id).filter(
                        model.ResponseType.name ==
                        self.request_son.name).first())
                if rt_by_name and rt_by_name != response_type:
                    raise errors.ModelError(
                        "'" + self.request_son.name +
                        "' as a response type of that name already exists")

            try:
                self._update(response_type, self.request_son)
            except ResponseTypeError as e:
                raise errors.ModelError(str(e))
            except voluptuous.error.Error as e:
                raise errors.ModelError(str(e))
            except Exception as e:
                raise errors.ModelError(str(e))

            verbs = []
            # Check if modified now to avoid problems with autoflush later
            if session.is_modified(response_type):
                verbs.append('update')
                calculator = Calculator.structural()
                for measure in response_type.measures:
                    for qnode_measure in measure.qnode_measures:
                        calculator.mark_measure_dirty(qnode_measure)
                calculator.execute()

            act = Activities(session)
            act.record(user_session.user, response_type, verbs)
            act.ensure_subscription(user_session.user, response_type,
                                    response_type.program, self.reason)

        self.get(response_type_id)
Beispiel #9
0
    def put(self, survey_id):
        '''Update existing.'''
        if not survey_id:
            raise errors.MethodError("Survey ID required")

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            survey = (session.query(model.Survey).options(
                joinedload('program')).options(
                    joinedload('program.surveygroups')).get(
                        (survey_id, program_id)))
            if not survey:
                raise errors.MissingDocError("No such survey")

            ## set only last level indexing_form 1 if no value, remove other level indexing_form
            levels = len(self.request_son.structure.levels)

            for i, l in enumerate(self.request_son.structure.levels):
                if i + 1 != levels and l.indexing_from:
                    del l.indexing_from
                if i + 1 == levels and (
                    (not l.indexing_from and l.indexing_from != 0) or
                    (not isinstance(l.indexing_from, Number))
                        or l.indexing_from < 0):
                    l.indexing_from = 1

            self._update(survey, self.request_son)

            policy = user_session.policy.derive({
                'program':
                survey.program,
                'survey':
                survey,
                'surveygroups':
                survey.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('survey_edit')

            verbs = []
            if session.is_modified(survey):
                verbs.append('update')

            if survey.deleted:
                survey.deleted = False
                verbs.append('undelete')

            act = Activities(session)
            act.record(user_session.user, survey, verbs)
            act.ensure_subscription(user_session.user, survey, survey.program,
                                    self.reason)

        self.get(survey_id)
Beispiel #10
0
    def post(self, user_id):
        '''
        Create a new user.
        '''
        if user_id:
            raise errors.MethodError("Can't use POST for existing users.")

        try:
            user_input_schema(self.request_son)
        except voluptuous.error.Invalid as e:
            raise errors.ModelError.from_voluptuous(e)

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = (
                session.query(model.Organisation)
                .get(self.request_son['organisation']['id']))
            if not org:
                raise errors.ModelError("No such organisation")

            user = model.AppUser(organisation=org)

            try:
                assign_surveygroups(user_session, user, self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'org': user.organisation,
                'user': user,
                'target': self.request_son,
                'surveygroups': user.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('user_add')
            policy.verify('user_change_role')
            self.check_password(self.request_son.password)

            self._update(user, self.request_son, session)
            session.add(user)

            # Need to flush so object has an ID to record action against.
            session.flush()

            act = Activities(session)
            act.record(user_session.user, user, ['create'])
            act.ensure_subscription(
                user_session.user, user, user.organisation, self.reason)
            act.subscribe(user, user.organisation)
            self.reason("New user subscribed to organisation")

            user_id = user.id
        self.get(user_id)
Beispiel #11
0
    def post(self, response_type_id):
        '''Create new'''
        if response_type_id:
            raise errors.ModelError("Can't specify ID when creating")

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = session.query(model.Program).get(program_id)
            if not program:
                raise errors.MissingDocError("No such program")

            policy = user_session.policy.derive({
                'program':
                program,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_type_add')

            rt_by_name = (session.query(model.ResponseType).filter(
                model.ResponseType.program_id == program_id).filter(
                    model.ResponseType.name == self.request_son.name).first())
            if rt_by_name:
                raise errors.ModelError(
                    "'" + self.request_son.name +
                    "' as a response type of that name already exists")

            response_type = model.ResponseType(program=program)
            session.add(response_type)
            try:
                self._update(response_type, self.request_son)
            except ResponseTypeError as e:
                raise errors.ModelError(str(e))
            except voluptuous.error.Error as e:
                raise errors.ModelError(str(e))

            try:
                session.flush()
            except sqlalchemy.exc.IntegrityError as e:
                raise errors.ModelError.from_sa(e)

            response_type_id = str(response_type.id)
            # No need for survey update: RT is not being used yet

            act = Activities(session)
            act.record(user_session.user, response_type, ['create'])
            act.ensure_subscription(user_session.user, response_type,
                                    response_type.program, self.reason)
        self.get(response_type_id)
Beispiel #12
0
    def post(self, survey_id):
        '''Create new.'''
        if survey_id:
            raise errors.MethodError("Can't use POST for existing object")

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = (session.query(model.Program).options(
                joinedload('surveygroups')).get(program_id))
            if not program:
                raise errors.ModelError("No such program")

            ## set only last level indexing_form 1 if no value, remove other level indexing_form
            levels = len(self.request_son.structure.levels)

            for i, l in enumerate(self.request_son.structure.levels):
                if i + 1 != levels and l.indexing_from:
                    del l.indexing_from
                if i + 1 == levels and (
                    (not l.indexing_from and l.indexing_from != 0) or
                    (not isinstance(l.indexing_from, Number))
                        or l.indexing_from < 0):
                    l.indexing_from = 1

            survey = model.Survey(program=program)
            self._update(survey, self.request_son)
            session.add(survey)

            # Need to flush so object has an ID to record action against.
            session.flush()

            policy = user_session.policy.derive({
                'program':
                program,
                'survey':
                survey,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('survey_add')

            act = Activities(session)
            act.record(user_session.user, survey, ['create'])
            act.ensure_subscription(user_session.user, survey, survey.program,
                                    self.reason)

            survey_id = str(survey.id)

        self.get(survey_id)
Beispiel #13
0
    def put(self, organisation_id):
        '''
        Update an existing organisation.
        '''
        if not organisation_id:
            raise errors.MethodError(
                "Can't use PUT for new organisations (no ID).")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.MissingDocError("No such organisation")

            try:
                groups_changed = assign_surveygroups(user_session, org,
                                                     self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'org':
                org,
                'surveygroups':
                org.surveygroups,
            })
            policy.verify('org_edit')

            # Check that user shares a common surveygroup with this org.
            # Admins need permission to edit orgs outside their surveygroups
            # though.
            if not policy.check('admin'):
                policy.verify('surveygroup_interact')

            old_locations = list(org.locations)
            self._update(org, self.request_son)

            verbs = []
            if (session.is_modified(org) or org.locations != old_locations
                    or groups_changed or session.is_modified(org.meta)):
                verbs.append('update')

            if org.deleted:
                org.deleted = False
                verbs.append('undelete')

            act = Activities(session)
            act.record(user_session.user, org, verbs)
            act.ensure_subscription(user_session.user, org, org, self.reason)

        self.get(organisation_id)
Beispiel #14
0
    def delete(self, qnode_id):
        '''Delete existing.'''

        if not qnode_id:
            raise errors.MethodError("Question node ID required")

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            qnode = (
                session.query(model.QuestionNode)
                .options(joinedload('program'))
                .options(joinedload('program.surveygroups'))
                .get((qnode_id, program_id)))
            if not qnode:
                raise errors.MissingDocError("No such question node")
            log.debug("deleting: %s", qnode)

            program = qnode.program
            survey = qnode.survey
            parent = qnode.parent

            policy = user_session.policy.derive({
                'program': program,
                'survey': survey,
                'surveygroups': program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_del')

            act = Activities(session)
            if not qnode.deleted:
                act.record(user_session.user, qnode, ['delete'])
            act.ensure_subscription(
                user_session.user, qnode, qnode.program, self.reason)

            qnode.deleted = True

            calculator = Calculator.structural()
            if parent:
                parent.children.reorder()
                calculator.mark_qnode_dirty(parent)
            else:
                survey.qnodes.reorder()
                calculator.mark_survey_dirty(survey)
            calculator.execute()

        self.finish()
Beispiel #15
0
    def put(self, query_id):
        if not query_id:
            raise errors.MethodError("Can't use PUT for new query.")

        with model.session_scope(version=True) as session:
            custom_query = session.query(model.CustomQuery).get(query_id)
            if custom_query is None:
                raise errors.MissingDocError("No such query")

            user_session = self.get_user_session(session)
            policy = user_session.policy.derive({
                'custom_query': custom_query,
            })
            policy.verify('custom_query_edit')

            self.check_concurrent_write(custom_query)
            if not self.should_save_new_version(custom_query,
                                                user_session.user):
                custom_query.version_on_update = False

            self.update(custom_query, self.request_son)

            verbs = []
            if session.is_modified(custom_query):
                verbs.append('update')
                self.update_auto(custom_query, user_session.user)
            else:
                custom_query.version_on_update = False

            if custom_query.deleted:
                custom_query.deleted = False
                verbs.append('undelete')

            session.flush()
            act = Activities(session)
            act.record(user_session.user, custom_query, verbs)
            act.ensure_subscription(user_session.user, custom_query,
                                    custom_query, self.reason)

            query_id = str(custom_query.id)

        self.get(query_id)
Beispiel #16
0
    def post(self, organisation_id):
        '''
        Create a new organisation.
        '''
        if organisation_id:
            raise errors.MethodError(
                "Can't use POST for existing organisation.")

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = model.Organisation()

            try:
                assign_surveygroups(user_session, org, self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            self._update(org, self.request_son)
            session.add(org)

            # Need to flush so object has an ID to record action against.
            session.flush()

            policy = user_session.policy.derive({
                'org':
                org,
                'surveygroups':
                org.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('org_add')

            act = Activities(session)
            act.record(user_session.user, org, ['create'])
            act.ensure_subscription(user_session.user, org, org, self.reason)

            organisation_id = str(org.id)
        self.get(organisation_id)
Beispiel #17
0
    def delete(self, survey_id):
        if not survey_id:
            raise errors.MethodError("Survey ID required")

        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            survey = (session.query(model.Survey).options(
                joinedload('program')).options(
                    joinedload('program.surveygroups')).get(
                        (survey_id, program_id)))
            if not survey:
                raise errors.MissingDocError("No such survey")

            policy = user_session.policy.derive({
                'program':
                survey.program,
                'survey':
                survey,
                'surveygroups':
                survey.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('survey_del')

            act = Activities(session)
            if not survey.deleted:
                act.record(user_session.user, survey, ['delete'])
            act.ensure_subscription(user_session.user, survey, survey.program,
                                    self.reason)

            survey.deleted = True

        self.finish()
Beispiel #18
0
    def delete(self, query_id):
        if not query_id:
            raise errors.MethodError("Query ID required")

        with model.session_scope(version=False) as session:
            custom_query = session.query(model.CustomQuery).get(query_id)
            if custom_query is None:
                raise errors.MissingDocError("No such query")

            user_session = self.get_user_session(session)
            policy = user_session.policy.derive({
                'custom_query': custom_query,
            })
            policy.verify('custom_query_del')

            act = Activities(session)
            if not custom_query.deleted:
                act.record(user_session.user, custom_query, ['delete'])
            act.ensure_subscription(user_session.user, custom_query,
                                    custom_query, self.reason)

            custom_query.deleted = True

        self.get(query_id)
Beispiel #19
0
    def post(self, program_id):
        '''
        Create a new program.
        '''
        if program_id:
            raise errors.MethodError("Can't use POST for existing program.")

        duplicate_id = self.get_argument('duplicateId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = model.Program()
            self._update(program, self.request_son)
            session.add(program)

            try:
                assign_surveygroups(user_session, program, self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'program':
                program,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('program_add')

            # Need to flush so object has an ID to record action against.
            session.flush()

            act = Activities(session)

            if duplicate_id:
                source_program = (session.query(
                    model.Program).get(duplicate_id))
                if not source_program:
                    raise errors.MissingDocError(
                        "Source program does not exist")

                policy = user_session.policy.derive({
                    'program':
                    source_program,
                    'surveygroups':
                    source_program.surveygroups,
                })
                policy.verify('surveygroup_interact')
                policy.verify('program_view')

                yield self.duplicate_structure(source_program, program,
                                               session)
                source_program.finalised_date = datetime.datetime.utcnow()
                act.record(user_session.user, source_program, ['state'])

            act.record(user_session.user, program, ['create'])
            act.ensure_subscription(user_session.user, program, program,
                                    self.reason)

            program_id = program.id

        self.get(program_id)
Beispiel #20
0
    def put(self, submission_id):
        '''Update existing.'''
        if submission_id == '':
            raise errors.MethodError("Submission ID required")

        approval = self.get_argument('approval', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            submission = session.query(model.Submission).get(submission_id)
            if not submission:
                raise errors.MissingDocError("No such submission")

            policy = user_session.policy.derive({
                'org':
                submission.organisation,
                'approval':
                approval,
                'surveygroups':
                submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_edit')

            current_level = 0
            verbs = []
            if approval:
                self.check_approval_down_one(session, submission, approval)
                current_level = APPROVAL_STATES.index(submission.approval)
                if approval != submission.approval:
                    verbs.append('state')
                submission.approval = approval
            self._update(submission, self.request_son)
            if session.is_modified(submission):
                verbs.append('update')

            # update measures approval state, when save edited submission no approval, so here should not
            if approval != '':
                approval_level = APPROVAL_STATES.index(approval)
                if 'state' in verbs and approval_level > current_level:
                    approval_level = approval_level - 1
                    responses = (session.query(model.Response).filter(
                        model.Response.submission_id == submission.id,
                        model.Response.approval ==
                        APPROVAL_STATES[approval_level]))
                    for response in responses:
                        # update = updater(response, error_factory=errors.ModelError)
                        # update('title', son)
                        response.approval = approval
                        try:
                            calculator = Calculator.scoring(submission)
                            calculator.mark_measure_dirty(
                                response.qnode_measure)
                            calculator.execute()
                        except ResponseTypeError as e:
                            raise errors.ModelError(str(e))

                        act = Activities(session)
                        act.record(user_session.user, response, verbs)
                        act.ensure_subscription(user_session.user, response,
                                                response.submission,
                                                self.reason)

            if submission.deleted:
                submission.deleted = False
                verbs.append('undelete')

            act = Activities(session)
            act.record(user_session.user, submission, verbs)
            act.ensure_subscription(user_session.user, submission,
                                    submission.organisation, self.reason)

        self.get(submission_id)
Beispiel #21
0
    def post(self, submission_id):
        '''Create new.'''
        if submission_id:
            raise errors.MethodError("Can't use POST for existing object")

        program_id = self.get_argument('programId', '')
        if not program_id:
            raise errors.ModelError("Program ID is required")

        survey_id = self.get_argument('surveyId', '')
        if not survey_id:
            raise errors.ModelError("Survey ID is required")

        organisation_id = self.get_argument('organisationId', '')
        if not organisation_id:
            raise errors.ModelError("Organisation ID is required")

        # Source submission ID
        duplicate_id = self.get_argument('duplicateId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.ModelError("No such organisation")

            survey = session.query(model.Survey).get((survey_id, program_id))
            if not survey:
                raise errors.ModelError("No such survey")

            if duplicate_id:
                source_submission = (session.query(
                    model.Submission).get(duplicate_id))
                if not source_submission:
                    raise errors.MissingDocError(
                        "Source submission (for duplication) not found")
                if source_submission.organisation != org:
                    raise errors.ModelError(
                        "Can't duplicate a submission across two "
                        "organisations: '%s' and '%s'" %
                        (source_submission.organisation.name, org.name))
            else:
                source_submission = None

            submission = model.Submission(program=survey.program,
                                          survey=survey,
                                          organisation=org,
                                          approval='draft')
            self._update(submission, self.request_son)
            session.add(submission)

            surveygroups = submission.surveygroups
            if source_submission:
                surveygroups &= source_submission.surveygroups

            policy = user_session.policy.derive({
                'org': org,
                'survey': survey,
                'surveygroups': surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_add')

            session.flush()
            submission_id = str(submission.id)

            if source_submission:
                yield SubmissionHandler.executor.submit(
                    self.duplicate, submission, source_submission, session)

            act = Activities(session)
            act.record(user_session.user, submission, ['create'])
            act.ensure_subscription(user_session.user, submission,
                                    submission.organisation, self.reason)

        self.get(submission_id)
Beispiel #22
0
    def put(self, submission_id, qnode_id):
        '''Save (create or update).'''

        approval = self.get_argument('approval', '')
        relevance = self.get_argument('relevance', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            submission = (
                session.query(model.Submission)
                .get(submission_id))
            if not submission:
                raise errors.MissingDocError("No such submission")

            policy = user_session.policy.derive({
                'org': submission.organisation,
                'submission': submission,
                'approval': approval,
                'index': APPROVAL_STATES.index,
                'surveygroups': submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('rnode_edit')

            rnode = (
                session.query(model.ResponseNode)
                .get((submission_id, qnode_id)))

            verbs = []

            if not rnode:
                qnode = (
                    session.query(model.QuestionNode)
                    .get((qnode_id, submission.program.id)))
                if qnode is None:
                    raise errors.MissingDocError("No such question node")
                rnode = model.ResponseNode.from_qnode(
                    qnode, submission, create=True)

            importance = self.request_son.get('importance')
            if importance is not None:
                if int(importance) <= 0:
                    self.request_son['importance'] = None
                elif int(importance) > 5:
                    self.request_son['importance'] = 5
            urgency = self.request_son.get('urgency')
            if urgency is not None:
                if int(urgency) <= 0:
                    self.request_son['urgency'] = None
                elif int(urgency) > 5:
                    self.request_son['urgency'] = 5
            self._update(rnode, self.request_son)
            if session.is_modified(rnode):
                verbs.append('update')
            session.flush()

            if approval:
                policy.verify('submission_response_approval')
                yield self.set_approval(
                    session, rnode, approval, user_session)
                verbs.append('state')
            if relevance:
                yield self.set_relevance(
                    session, rnode, relevance, user_session)
                verbs.append('update')

            try:
                calculator = Calculator.scoring(submission)
                calculator.mark_qnode_dirty(rnode.qnode)
                calculator.execute()
            except ResponseTypeError as e:
                raise errors.ModelError(str(e))

            act = Activities(session)
            act.record(user_session.user, rnode, verbs)
            act.ensure_subscription(
                user_session.user, rnode, rnode.submission,
                self.reason)

        self.get(submission_id, qnode_id)
Beispiel #23
0
    def put(self, submission_id, measure_id):
        '''Save (create or update).'''

        with model.session_scope(version=True) as session:
            user_session = self.get_user_session(session)

            submission = (session.query(model.Submission).get(submission_id))
            if not submission:
                raise errors.MissingDocError("No such submission")

            response = (session.query(model.Response).get(
                (submission_id, measure_id)))

            verbs = []
            if response is None:
                program_id = submission.program_id
                survey_id = submission.survey_id
                qnode_measure = (session.query(model.QnodeMeasure).get(
                    (program_id, survey_id, measure_id)))
                if qnode_measure is None:
                    raise errors.MissingDocError("No such measure")
                response = model.Response(qnode_measure=qnode_measure,
                                          submission=submission,
                                          approval='draft')
                session.add(response)
                verbs.append('create')
            else:
                same_user = response.user.id == user_session.user.id
                td = datetime.datetime.utcnow() - response.modified
                hours_since_update = td.total_seconds() / 60 / 60

                if same_user and hours_since_update < 8:
                    response.version_on_update = False

                modified = self.request_son.get("latest_modified", 0)
                # Convert to int to avoid string conversion errors during
                # JSON marshalling.
                if int(modified) < int(response.modified.timestamp()):
                    raise errors.ModelError(
                        "This response has changed since you loaded the"
                        " page. Please copy or remember your changes and"
                        " refresh the page.")
                verbs.append('update')

            if self.request_son['approval'] != response.approval:
                verbs.append('state')

            self._update(response, self.request_son, user_session.user)
            if not session.is_modified(response) and 'update' in verbs:
                verbs.remove('update')

            policy = user_session.policy.derive({
                'org':
                submission.organisation,
                'submission':
                submission,
                'approval':
                response.approval,
                'index':
                APPROVAL_STATES.index,
                'surveygroups':
                submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_edit')

            session.flush()

            # Prevent creating a second version during following operations
            response.version_on_update = False

            try:
                calculator = Calculator.scoring(submission)
                calculator.mark_measure_dirty(response.qnode_measure)
                calculator.execute()
            except ResponseTypeError as e:
                raise errors.ModelError(str(e))

            act = Activities(session)
            act.record(user_session.user, response, verbs)
            act.ensure_subscription(user_session.user, response,
                                    response.submission, self.reason)

        self.get(submission_id, measure_id)
Beispiel #24
0
    def put(self, user_id):
        '''
        Update an existing user.
        '''
        if not user_id:
            raise errors.MethodError("Can't use PUT for new users (no ID).")

        try:
            user_input_schema(self.request_son)
        except voluptuous.error.Invalid as e:
            raise errors.ModelError.from_voluptuous(e)

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            user = session.query(model.AppUser).get(user_id)
            if not user:
                raise errors.MissingDocError("No such user")

            try:
                groups_changed = assign_surveygroups(
                    user_session, user, self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'org': user.organisation,
                'user': user,
                'target': self.request_son,
                'surveygroups': user.surveygroups,
            })
            policy.verify('user_edit')

            # Check that user shares a common surveygroup with the requesting
            # user.
            # Allow admins to edit users outside their surveygroups though.
            if not policy.check('admin'):
                policy.verify('surveygroup_interact')

            if self.request_son.role and self.request_son.role != user.role:
                policy.verify('user_change_role')

            if ('deleted' in self.request_son and
                    self.request_son['deleted'] != user.deleted):
                policy.verify('user_enable')

            if self.request_son.get('password'):
                self.check_password(self.request_son.password)

            verbs = []
            oid = self.request_son.organisation.id
            if oid != str(user.organisation_id):
                policy.verify('user_change_org')
                verbs.append('relation')

            self._update(user, self.request_son, session)

            act = Activities(session)
            if session.is_modified(user) or groups_changed:
                verbs.append('update')

            if user.deleted:
                user.deleted = False
                verbs.append('undelete')

            session.flush()
            if len(verbs) > 0:
                act.record(user_session.user, user, verbs)
                act.ensure_subscription(
                    user_session.user, user, user.organisation, self.reason)
                if not act.has_subscription(user, user):
                    act.subscribe(user, user.organisation)
                    self.reason("User subscribed to organisation")

        self.get(user_id)
Beispiel #25
0
    def post(self, qnode_id):
        '''Create new.'''

        if qnode_id:
            raise errors.MethodError("Can't use POST for existing object")

        program_id = self.get_argument('programId', '')
        survey_id = self.get_argument('surveyId', '')
        parent_id = self.get_argument('parentId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = (
                session.query(model.Program)
                .options(joinedload('surveygroups'))
                .get(program_id))
            if not program:
                raise errors.ModelError("No such program")

            qnode = model.QuestionNode(program=program)
            self._update(session, qnode, self.request_son)
            log.debug("new: %s", qnode)

            if survey_id:
                survey = (
                    session.query(model.Survey)
                    .get((survey_id, program_id)))
                if not survey:
                    raise errors.ModelError("No such survey")
            else:
                survey = None
            log.debug("survey: %s", survey)

            if parent_id:
                parent = (
                    session.query(model.QuestionNode)
                    .get((parent_id, program_id)))
                if not parent:
                    raise errors.ModelError("Parent does not exist")
                if not survey:
                    survey = parent.survey
                elif parent.survey != survey:
                    raise errors.ModelError(
                        "Parent does not belong to that survey")
            else:
                parent = None

            qnode.survey = survey

            if parent:
                log.debug("Appending to parent")
                parent.children.append(qnode)
                parent.children.reorder()
                log.debug("committing: %s", parent.children)
            elif survey:
                log.debug("Appending to survey")
                survey.qnodes.append(qnode)
                survey.qnodes.reorder()
                log.debug("committing: %s", survey.qnodes)
            else:
                raise errors.ModelError("Parent or survey ID required")

            # Need to flush so object has an ID to record action against.
            session.flush()

            policy = user_session.policy.derive({
                'program': qnode.program,
                'survey': qnode.survey,
                'surveygroups': qnode.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_add')

            calculator = Calculator.structural()
            calculator.mark_qnode_dirty(qnode)
            calculator.execute()

            qnode_id = str(qnode.id)

            act = Activities(session)
            act.record(user_session.user, qnode, ['create'])
            act.ensure_subscription(
                user_session.user, qnode, qnode.program, self.reason)

        self.get(qnode_id)
Beispiel #26
0
    def put(self, qnode_id):
        '''Update existing.'''

        if not qnode_id:
            self.ordering()
            return

        program_id = self.get_argument('programId', '')
        parent_id = self.get_argument('parentId', '')

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            qnode = (
                session.query(model.QuestionNode)
                .options(joinedload('program'))
                .options(joinedload('program.surveygroups'))
                .get((qnode_id, program_id)))
            if not qnode:
                raise errors.MissingDocError("No such question node")

            policy = user_session.policy.derive({
                'program': qnode.program,
                'survey': qnode.survey,
                'surveygroups': qnode.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_edit')

            self._update(session, qnode, self.request_son)

            verbs = []
            if session.is_modified(qnode):
                verbs.append('update')

            calculator = Calculator.structural()
            if parent_id and str(qnode.parent_id) != parent_id:
                # Change parent
                old_parent = qnode.parent
                new_parent = (
                    session.query(model.QuestionNode)
                    .get((parent_id, program_id)))
                if new_parent.survey != qnode.survey:
                    raise errors.ModelError("Can't move to different survey")
                if not new_parent:
                    raise errors.ModelError("No such question node")
                old_parent.children.remove(qnode)
                old_parent.children.reorder()
                new_parent.children.append(qnode)
                new_parent.children.reorder()
                calculator.mark_qnode_dirty(old_parent)
                calculator.mark_qnode_dirty(qnode)
                self.reason("Moved from %s to %s" % (
                    old_parent.title, new_parent.title))
                verbs.append('relation')

            if qnode.deleted:
                # Get a reference to the collection before changing the
                # deleted flag - otherwise, if a query is needed to
                # instantiate the collection, it will seem as if the object
                # is already in the collection and insert will not work as
                # expected.
                if qnode.parent:
                    collection = qnode.parent.children
                else:
                    collection = qnode.survey.qnodes
                qnode.deleted = False
                collection.insert(qnode.seq, qnode)
                collection.reorder()
                calculator.mark_qnode_dirty(qnode)
                verbs.append('undelete')

            calculator.execute()

            act = Activities(session)
            act.record(user_session.user, qnode, verbs)
            act.ensure_subscription(
                user_session.user, qnode, qnode.program, self.reason)

        self.get(qnode_id)
Beispiel #27
0
    def ordering(self):
        '''Change the order of all children in a parent's collection.'''

        program_id = self.get_argument('programId', '')
        survey_id = self.get_argument('surveyId', '')
        parent_id = self.get_argument('parentId', '')
        root = self.get_argument('root', None)

        #if parent_id and root is None:
        if parent_id is None and root is None: 
            raise errors.ModelError(
                "Parent ID required, or specify 'root=' for root nodes")
        if root is not None and parent_id:
            raise errors.ModelError(
                "Can't specify both 'root=' and parent ID")
            if not survey_id:
                raise errors.ModelError(
                    "Survey ID is required for operating on root nodes")

        son = json_decode(self.request.body)

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            act = Activities(session)
            if parent_id:
                parent = (
                    session.query(model.QuestionNode)
                    .get((parent_id, program_id)))
                if not parent:
                    raise errors.MissingDocError(
                        "Parent question node does not exist")
                survey = parent.survey
                if survey_id and survey_id != str(survey.id):
                    raise errors.MissingDocError(
                        "Parent does not belong to that survey")
                log.debug("Reordering children of: %s", parent)
                reorder(parent.children, son)
                act.record(user_session.user, parent, ['reorder_children'])
                act.ensure_subscription(
                    user_session.user, parent, parent.program, self.reason)

            elif root is not None:
                survey = (
                    session.query(model.Survey)
                    .get((survey_id, program_id)))
                if not survey:
                    raise errors.MissingDocError("No such survey")
                log.debug("Reordering children of: %s", survey)
                reorder(survey.qnodes, son)
                act.record(
                    user_session.user, survey, ['reorder_children'])
                act.ensure_subscription(
                    user_session.user, survey, survey.program, self.reason)

            else:
                raise errors.ModelError(
                    "Survey or parent ID required")

            policy = user_session.policy.derive({
                'program': survey.program,
                'survey': survey,
                'surveygroups': survey.program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('qnode_edit')

        self.query()
Beispiel #28
0
    def put(self, program_id):
        '''
        Update an existing program.
        '''
        if program_id == '':
            raise errors.MethodError("Can't use PUT for new program (no ID).")

        editable = self.get_argument('editable', '')
        if editable != '':
            self._update_state(program_id, truthy(editable))
            return

        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            program = session.query(model.Program).get(program_id)
            if not program:
                raise errors.MissingDocError("No such program")

            try:
                groups_changed = assign_surveygroups(user_session, program,
                                                     self.request_son)
            except ValueError as e:
                raise errors.ModelError(str(e))

            policy = user_session.policy.derive({
                'program':
                program,
                'surveygroups':
                program.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('program_edit')

            if not program.is_editable:
                raise errors.MethodError("This program is closed for editing")

            calculator = Calculator.structural()
            if self.request_son['has_quality'] != program.has_quality:
                # Recalculate stats for surveys. This will trigger the
                # recalculation of the submissions in the recalculation
                # daemon.
                for survey in program.surveys:
                    calculator.mark_survey_dirty(survey)

            self._update(program, self.request_son)

            calculator.execute()

            verbs = []
            if session.is_modified(program) or groups_changed:
                verbs.append('update')

            if program.deleted:
                program.deleted = False
                verbs.append('undelete')

            act = Activities(session)
            act.record(user_session.user, program, verbs)
            act.ensure_subscription(user_session.user, program, program,
                                    self.reason)
        self.get(program_id)