Beispiel #1
0
    def put(self, organisation_id, survey_id):
        program_id = self.get_argument('programId', '')

        with model.session_scope() as session:
            org = session.query(model.Organisation).get(organisation_id)
            if not org:
                raise errors.MissingDocError("No such organisation")
            survey = (session.query(model.Survey).get((survey_id, program_id)))
            if not survey:
                raise errors.MissingDocError('No such survey')

            user_session = self.get_user_session(session)
            policy = user_session.policy.derive({
                'org':
                org,
                'survey':
                survey,
                'surveygroups':
                survey.surveygroups & org.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('survey_purchase')

            purchased_survey = (session.query(model.PurchasedSurvey).get(
                (program_id, survey_id, org.id)))

            if not purchased_survey:
                org.surveys.append(survey)
Beispiel #2
0
    def head(self, organisation_id, survey_id):
        program_id = self.get_argument('programId', '')

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

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

            user_session = self.get_user_session(session)
            policy = user_session.policy.derive({
                'org':
                org,
                'surveygroups':
                survey.surveygroups & org.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('submission_browse')

            purchased_survey = (session.query(model.PurchasedSurvey).get(
                (program_id, survey_id, organisation_id)))
            if not purchased_survey:
                raise errors.MissingDocError(
                    "This survey has not been purchased yet")

        self.finish()
Beispiel #3
0
 def get_schema(self, name):
     schema = config.SCHEMA.get(name)
     if not schema or config.is_private(name, schema):
         raise errors.MissingDocError("No such setting")
     if config.is_primitive(schema):
         raise errors.MissingDocError(
             "This service can only be used to get blob data, not "
             "text or numerical values.")
     return schema
Beispiel #4
0
    def get(self, submission_id, fmt, extension):
        if extension != 'xlsx':
            raise errors.MissingDocError("File type not supported: %s" %
                                         extension)
        if fmt not in {'tabular', 'nested'}:
            raise errors.MissingDocError("Unrecognised format: %s" % fmt)

        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")
            elif submission.deleted:
                raise errors.MissingDocError(
                    "That submission has been deleted")

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

            survey_id = submission.survey_id
            program_id = submission.program_id
            role = user_session.user.role

        output_file = 'submission_{0}_{1}.xlsx'.format(submission_id, fmt)
        base_url = ("%s://%s" % (self.request.protocol, self.request.host))

        with tempfile.TemporaryDirectory() as tmpdirname:
            output_path = os.path.join(tmpdirname, output_file)
            if fmt == 'tabular':
                yield self.export_tabular(output_path, program_id, survey_id,
                                          submission_id, role, base_url)
            else:
                yield self.export_nested(output_path, program_id, survey_id,
                                         submission_id, role, base_url)
            self.set_header('Content-Type', 'application/octet-stream')
            self.set_header('Content-Disposition', 'attachment')

            with open(output_path, 'rb') as f:
                while True:
                    data = f.read(BUF_SIZE)
                    if not data:
                        break
                    self.write(data)

        self.finish()
Beispiel #5
0
    def post(self, query_id, file_type):
        parameters = self.request_son.copy()

        with model.session_scope() as session:
            custom_query = session.query(model.CustomQuery).get(query_id)
            if not custom_query:
                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_execute')

            if not custom_query.text:
                raise errors.ModelError("Query is empty")

            conf = self.get_config(session)
            session.expunge(custom_query)

        # Overwrite stored query text if query is parameterised
        if parameters.text:
            custom_query.text = parameters.text

        yield self.export(custom_query, conf, file_type)
        self.finish()
Beispiel #6
0
    def get(self, ob_type, ids):
        if ob_type:
            self.query(ob_type, ids.split(','))
            return

        subscription_id = ids
        with model.session_scope() as session:
            subscription = (session.query(
                model.Subscription).get(subscription_id))
            if not subscription:
                raise errors.MissingDocError("No such subscription")

            user_session = self.get_user_session(session)
            policy = user_session.policy.derive({
                'user': subscription.user,
            })
            policy.verify('subscription_view')

            to_son = ToSon(
                r'/created$',
                r'/user_id$',
                r'/subscribed$',
                r'/ob_type$',
                r'/ob_refs/?.*$',
            )
            son = to_son(subscription)

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #7
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 #8
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 #9
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 #10
0
    def put(self, ob_type, subscription_id):
        if ob_type:
            raise errors.ModelError(
                "Can't provide object type when updating a subscription")

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

            subscription = (session.query(
                model.Subscription).get(subscription_id))

            if not subscription:
                raise errors.MissingDocError("No such subscription")

            subscription.subscribed = self.request_son.get('subscribed', False)

            ob = get_ob(session, subscription.ob_type, subscription.ob_refs)
            policy = user_session.policy.derive({
                'user':
                subscription.user,
                'survey':
                self.get_survey(ob),
                'submission':
                self.get_submission(ob),
            })
            policy.verify('subscription_edit')

            subscription_id = str(subscription.id)

        self.get('', subscription_id)
Beispiel #11
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 #12
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 #13
0
    def post(self, ob_type, object_ids):
        object_ids = object_ids.split(',')

        if not ob_type:
            raise errors.ModelError(
                "Object type required when creating a subscription")

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

            ob = get_ob(session, ob_type, object_ids)
            if not ob:
                raise errors.MissingDocError("No such object")

            act = Activities(session)
            subscription = act.subscribe(user_session.user, ob)
            subscription.subscribed = self.request_son.get('subscribed', False)

            policy = user_session.policy.derive({
                'user':
                subscription.user,
                'survey':
                self.get_survey(ob),
                'submission':
                self.get_submission(ob),
            })
            policy.verify('subscription_add')

            session.flush()
            subscription_id = str(subscription.id)

        self.get('', subscription_id)
Beispiel #14
0
    def get(self, attachment_id, file_name):
        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            attachment = session.query(model.Attachment).get(attachment_id)

            if not attachment:
                raise errors.MissingDocError("No such attachment")

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

            if attachment.storage == "aws":
                s3 = aws.session.client('s3', verify=False)
                object_loc = aws.S3_PATTERN.match(attachment.url)
                with tempfile.NamedTemporaryFile() as temp:
                    s3.download_file(
                        object_loc.group('bucket'),
                        object_loc.group('path'), temp.name)

                    with open(temp.name, "rb") as file:
                        blob = file.read()
            else:
                blob = attachment.blob

        self.set_header('Content-Type', 'application/octet-stream')
        self.set_header('Content-Disposition', 'attachment')
        self.write(bytes(blob))
        self.finish()
Beispiel #15
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 #16
0
    def get(self, submission_id):
        if submission_id == '':
            self.query()
            return

        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_view')

            to_son = ToSon(
                # Any
                r'/ob_type$',
                r'/id$',
                r'/title$',
                r'/name$',
                r'</description$',
                r'/approval$',
                r'/created$',
                r'/deleted$',
                r'/n_measures$',
                r'^/error$',
                r'^/survey/error$',
                r'/program/tracking_id$',
                # Nested
                r'/program$',
                r'/program/tracking_id$',
                r'/organisation$',
                r'/survey$',
                r'/survey/structure.*$',
                r'/survey/min_stats_approval$',
                r'/program/hide_aggregate$',
            )
            son = to_son(submission)
            # menu for export asset management show if asset management template exist  src/app/client/report
            # local path "src/app/client/report/" + submission.survey.title + ' Template.xlsx"
            # templateFile = "src/app/client/report/" + submission.survey.title + ' Template.xlsx'
            # local path "app/client/report/" + submission.survey.title + ' Template.xlsx" for develop
            # production path "client/report/" + submission.survey.title + ' Template.xlsx' for deploy
            templateFile = "client/report/" + submission.survey.title + ' Template.xlsx'
            if os.path.isfile(templateFile):
                son["showCreateAssetReport"] = True
        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #17
0
    def get(self, submission_id, measure_id):
        '''Get a list of versions of a response.'''
        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,
                'surveygroups':
                submission.surveygroups,
            })
            policy.verify('surveygroup_interact')
            policy.verify('response_view')

            # Current version
            versions = (session.query(model.Response).filter_by(
                submission_id=submission_id, measure_id=measure_id).all())

            # Other versions
            query = (session.query(model.ResponseHistory).filter_by(
                submission_id=submission_id, measure_id=measure_id).order_by(
                    model.ResponseHistory.version.desc()))
            query = self.paginate(query)

            versions += query.all()

            # Important! If you're going to include the comment field here,
            # make sure it is cleaned first to prevent XSS attacks.
            to_son = ToSon(
                r'/id$',
                r'/name$',
                r'/approval$',
                r'/version$',
                r'/modified$',
                # Descend
                r'/[0-9]+$',
                r'/user$',
                r'/organisation$',
                # The IDs of rnodes and responses are not part of the API
                r'!^/[0-9]+/id$',
            )
            sons = to_son(versions)

            for son, version in zip(sons, versions):
                user = session.query(model.AppUser).get(version.user_id)
                if user is not None:
                    son['user'] = to_son(user)

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(sons))
        self.finish()
Beispiel #18
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 #19
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 #20
0
    def get(self, user_id):
        '''
        Get a single user.
        '''
        if not user_id:
            self.query()
            return

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

            if user_id == 'current':
                user = user_session.user
            else:
                user = (
                    session.query(model.AppUser)
                    .options(joinedload('organisation'))
                    .options(joinedload('surveygroups'))
                    .get(user_id))
                if not user:
                    raise errors.MissingDocError("No such user")

            policy = user_session.policy.derive({
                'user': user,
                'surveygroups': user.surveygroups,
            })
            policy.verify('user_view')

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

            to_son = ToSon(
                r'/id$',
                r'/name$',
                r'/title$',
                r'/email$',
                r'/email_interval$',
                r'/role$',
                r'/deleted$',
                # Descend into nested objects
                r'/organisation$',
                r'/[0-9+]$',
                # Exclude password from response. Not really necessary because
                # 1. it's hashed and 2. it's not in the list above. But just to
                # be safe.
                r'!password',
            )
            if policy.check('surveygroup_browse'):
                to_son.add(r'^/surveygroups$')
            son = to_son(user)
        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #21
0
    def get(self, size):
        size = int(size)

        if size < 8:
            raise errors.MissingDocError("Size is too small")
        if size > 256:
            raise errors.MissingDocError("Size is too big")

        if size <= 64:
            name = 'theme_icon_sm'
        else:
            name = 'theme_icon_lg'

        with model.session_scope() as session:
            data = yield self.get_icon(session, name, size)

        self.set_header('Content-Type', 'image/png')
        self.write(data)
        self.finish()
Beispiel #22
0
    def query(self, organisation_id):
        deleted = self.get_argument('deleted', '')
        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('submission_browse')

            query = (session.query(model.Survey).join(
                model.PurchasedSurvey).filter(
                    model.PurchasedSurvey.organisation_id == organisation_id))

            if deleted:
                deleted = truthy(deleted)
                if deleted:
                    del_filter = ((model.Survey.deleted == True) |
                                  (model.Program.deleted == True))
                else:
                    del_filter = ((model.Survey.deleted == False) &
                                  (model.Program.deleted == False))
                query = query.join(model.Program).filter(del_filter)

            if not policy.check('surveygroup_interact_all'):
                query = filter_surveygroups(session, query,
                                            user_session.user.id,
                                            [model.Program],
                                            [model.program_surveygroup])

            surveys = query.all()

            to_son = ToSon(
                r'/id$',
                r'/title$',
                r'/deleted$',
                r'/n_measures$',
                r'/program/tracking_id$',
                # Descend into list
                r'/[0-9]+$',
                r'/program$')

            sons = to_son(surveys)

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(sons))
        self.finish()
Beispiel #23
0
    def query(self, submission_id):
        '''Get a list.'''
        qnode_id = self.get_argument('qnodeId', '')
        if not qnode_id:
            raise errors.ModelError("qnode ID required")

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

            submission = (session.query(model.Submission).options(
                joinedload('organisation')).filter_by(
                    id=submission_id).first())

            if not submission:
                raise errors.MissingDocError("No such submission")

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

            rnode = (session.query(model.ResponseNode).get(
                (submission_id, qnode_id)))
            if not rnode:
                responses = []
            else:
                responses = rnode.responses

            to_son = ToSon(
                # Fields to match from any visited object
                r'/id$',
                r'/score$',
                r'/approval$',
                r'/modified$',
                r'/not_relevant$',
                r'^/[0-9]+/error$',
                # Descend into nested objects
                r'/[0-9]+$',
                r'/measure$',
            )
            if user_session.user.role == 'clerk':
                to_son.exclude(r'/score$')
            sons = to_son(responses)

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(sons))
        self.finish()
Beispiel #24
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 #25
0
    def put(self, activity_id):
        with model.session_scope() as session:
            user_session = self.get_user_session(session)

            activity = (session.query(model.Activity).get(activity_id))
            if not activity:
                raise errors.MissingDocError("No such activity")

            if 'surveygroups' in self.request_son:
                try:
                    assign_surveygroups(user_session, activity,
                                        self.request_son)
                except ValueError as e:
                    raise errors.ModelError(str(e))

            if activity.ob_type == 'organisation':
                org = get_ob(activity.ob_type, activity.ob_ids)
                policy = user_session.policy.derive({
                    'activity':
                    activity,
                    'org':
                    org,
                    'surveygroups':
                    org.surveygroups,
                })
            elif not activity.ob_type:
                policy = user_session.policy.derive({
                    'activity':
                    activity,
                    'surveygroups':
                    activity.surveygroups,
                })
            else:
                raise errors.ModelError("That activity can't be modified")

            policy.verify('surveygroup_interact')

            if 'sticky' in self.request_son:
                if self.request_son.sticky != activity.sticky:
                    policy.verify('post_pin')
                    activity.sticky = self.request_son.sticky

            if 'message' in self.request_son:
                if self.request_son.message != activity.message:
                    policy.verify('post_edit')
                    activity.message = self.request_son.message

            son = ActivityHandler.TO_SON(activity)

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #26
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 #27
0
    def get(self, query_id):
        if not query_id:
            self.query()
            return

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

        with model.session_scope() 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_view')

            old_version = self.get_version(session, custom_query, version)

            to_son = ToSon(
                r'/id$',
                r'/deleted$',
                r'/modified$',
                r'/latest_modified$',
                r'/user$',
                r'/title$',
                r'</description$',
                r'/name$',
                r'/text$',
                r'/version$',
            )

            if not old_version:
                son = to_son(custom_query)
            else:
                son = to_son(old_version)
                user = session.query(model.AppUser).get(old_version.user_id)
                if user:
                    son.user = to_son(user)

            # Always include the mtime of the most recent version. This is used
            # to avoid edit conflicts.
            dummy_relations = {
                'latest_modified': custom_query.modified,
            }
            son.update(to_son(dummy_relations))

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #28
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 #29
0
    def get(self, program_id):
        '''
        Get a single program.
        '''
        if program_id == "":
            self.query()
            return

        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.MissingDocError("No such program")

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

            to_son = ToSon(
                r'/ob_type$',
                r'/id$',
                r'/tracking_id$',
                r'/title$',
                r'</description$',
                r'/created$',
                r'/deleted$',
                r'/is_editable$',
                r'^/error$',
                r'/has_quality$',
                r'/hide_aggregate$',
                r'/[0-9+]$',
            )
            if policy.check('surveygroup_browse'):
                to_son.add(r'^/surveygroups$')
            if not policy.check('author'):
                to_son.exclude(
                    r'/response_types.*score$',
                    r'/response_types.*formula$',
                )
            son = to_son(program)
        self.set_header("Content-Type", "application/json")
        self.write(json_encode(son))
        self.finish()
Beispiel #30
0
    def get(self, program_id):
        '''
        Get a list of programs that share the same lineage.
        '''
        if program_id == '':
            raise errors.MethodError("Program ID is 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_view')

            query = (session.query(model.Program).filter(
                model.Program.tracking_id == program.tracking_id).order_by(
                    model.Program.created))

            if not policy.check('surveygroup_interact_all'):
                query = filter_surveygroups(session, query,
                                            user_session.user.id, [],
                                            [model.program_surveygroup])

            deleted = self.get_argument('deleted', '')
            if deleted != '':
                deleted = truthy(deleted)
                query = query.filter(model.Program.deleted == deleted)

            to_son = ToSon(
                r'/id$',
                r'/title$',
                r'/is_editable$',
                r'/deleted$',
                # Descend
                r'/[0-9]+$',
            )
            sons = to_son(query.all())

        self.set_header("Content-Type", "application/json")
        self.write(json_encode(sons))
        self.finish()