Exemplo n.º 1
0
 def get_owner_property(self, id_or_entity):
     owner_props = {
         'Team': 'owned_teams',
         'Organization': 'owned_organizations',
     }
     kind = SqlModel.get_kind(id_or_entity)
     return getattr(self, owner_props[kind])if kind in owner_props else None
Exemplo n.º 2
0
    def resolve_id_mismatch(klass, user, new_id):
        """Change all references to user's id to a new id.

        N.B. this is obviously brittle; when the relationship schema changes,
        this will also have to change.
        """
        # The auth server has a different id for this user; defer to it.

        teams = Team.get(captain_id=user.uid)
        for t in teams:
            t.captain_id = new_id
        Team.put_multi(teams)

        classrooms = Classroom.get(contact_id=user.uid)
        for c in classrooms:
            c.contact_id = new_id
        Classroom.put_multi(classrooms)

        params = {'uid': new_id, 'short_uid': SqlModel.convert_uid(new_id)}
        with mysql_connection.connect() as sql:
            sql.update_row(klass.table, 'uid', user.uid, **params)

        for k, v in params.items():
            setattr(user, k, v)

        return user
Exemplo n.º 3
0
 def __call__(self):
     # Calling code may have pulled the entity for us already, no sense
     # in doing it again; on the other hand, merely an id may be
     # sufficient, depending on the kind, so only run this code if its
     # called.
     if self._entity is None:
         self._entity = SqlModel.kind_to_class(kind).get_by_id(self.uid)
     return self._entity
Exemplo n.º 4
0
 def __init__(self, id_or_entity):
     if isinstance(id_or_entity, basestring):
         self.uid = str(id_or_entity)
         self._entity = None
     else:
         self.uid = id_or_entity.uid
         self._entity = id_or_entity
     self.kind = SqlModel.get_kind(self.uid)
Exemplo n.º 5
0
    def report_link(self, report):
        parent_kind = SqlModel.get_url_kind(report.parent_id)
        short_id = SqlModel.convert_uid(report.parent_id)

        if report.gcs_path:
            platform = 'triton'
            prefix = ''
            view_path = '/api/{parent_kind}/{id}/reports/{filename}'.format(
                parent_kind=parent_kind,
                id=short_id,
                filename=report.filename,
            )
        elif report.dataset_id:
            platform = 'neptune'
            prefix = '{protocol}://{domain}'.format(
                protocol='http' if util.is_localhost() else 'https',
                domain=('localhost:8888' if util.is_localhost() else
                        os.environ['NEPTUNE_DOMAIN']),
            )
            view_path = '/datasets/{ds_id}/{template}/{filename}'.format(
                ds_id=SqlModel.convert_uid(report.dataset_id),  # short form
                template=report.template,
                filename=report.filename,
            )

        # Permit report clients to query some data about participation.
        parent_path = '/api/{parent_kind}/{id}'.format(parent_kind=parent_kind,
                                                       id=short_id)
        data_path = '/api/{parent_kind}/{id}/report_data'.format(
            parent_kind=parent_kind, id=short_id)

        link_jwt = jwt_helper.encode(
            {
                'allowed_endpoints': [
                    self.get_endpoint_str(platform=platform, path=view_path),
                    self.get_endpoint_str(platform='triton', path=parent_path),
                    self.get_endpoint_str(platform='triton', path=data_path),
                ]
            },
            expiration_minutes=(30 * 24 * 60),  # thirty days
        )

        return util.set_query_parameters(prefix + view_path, token=link_jwt)
Exemplo n.º 6
0
    def post(self):
        # Anyone is allowed to post responses.
        params = self.get_params(Response.property_types())
        user = self.get_current_user()

        if 'user_id' not in params:
            params['user_id'] = user.uid

        required_params = ('team_id', 'parent_id', 'module_label')
        for k in required_params:
            if not params.get(k, None):
                return self.http_bad_request("{} required.".format(k))

        # Validate the parent, if it's a cycle.
        parent_id = params.get('parent_id', None)
        parent_kind = SqlModel.get_kind(parent_id)
        if parent_kind == 'Cycle':
            cycle = SqlModel.kind_to_class(parent_kind).get_by_id(parent_id)
            if not cycle or not owns(user, parent_id):
                return self.http_forbidden("Must own the parent to respond.")
        # ...else this is a step label, so allow any truthy string.

        # Permission to create varies by type/level.
        params['type'] = params.get('type', Response.USER_LEVEL_SYMBOL)
        if params['type'] == Response.TEAM_LEVEL_SYMBOL:
            if not owns(user, params['team_id']):
                return self.http_forbidden("Must own the team to respond.")
        elif not owns(user, params['user_id']):
            return self.http_forbidden("May not create responses for others.")

        try:
            new_entity = Response.insert_or_conflict(params)
        except ResponseIndexConflict:
            return self.http_conflict(
                "Response for this type-user-team-parent-module combination "
                "exists. Send a request like `PUT /api/responses/:id`.")
        except JsonTextValueLengthError:
            return self.http_payload_too_large("Value too long.")
        except JsonTextDictLengthError:
            return self.http_payload_too_large("Body has too many keys.")
        self.write(new_entity)
Exemplo n.º 7
0
 def test_completion_ids_exclude_testing(self):
     """Don't count testing pd as that participant being done."""
     pid = self.test_create_portal_pd(testing=True)
     participant = Participant.create(
         id=SqlModel.convert_uid(pid),
         name='Pascal',
         organization_id='Organization_PERTS',
     )
     participant.put()
     results = ParticipantData.completion_ids(
         project_cohort_id='ProjectCohort_12345678')
     self.assertEqual(results, [])
Exemplo n.º 8
0
    def associated_organization_ids(self, depth=0, pending_network=None):
        """Traverse all network-to-network relationships to associated orgs.

        Returns a flat and unique list of org ids.
        """
        # While we support network-to-network, this recursive function could
        # generate many inefficient db calls if we get carried away.
        if depth >= 4:
            raise InvalidNetworkAssociation(
                "Too much depth in network associations: {}"
                .format(self.uid)
            )

        org_ids = set()
        for assc_id in self.association_ids:
            kind = SqlModel.get_kind(assc_id)
            if kind == 'Network':

                # Note! This function is often run as a before_put check that
                # the associations are valid. This means we have to consider
                # the as-of-yet-unsaved "root" network (the `pending_network`)
                # and not any version of it we might fetch from the db in order
                # to catch the introduction of circular references.

                if pending_network and assc_id == pending_network.uid:
                    child_network = pending_network
                else:
                    child_network = Network.get_by_id(assc_id)

                if child_network:
                    child_org_ids = child_network.associated_organization_ids(
                        depth=depth + 1,
                        pending_network=pending_network,
                    )
                    org_ids.update(child_org_ids)
                else:
                    # No exception here because we don't want Networks to
                    # become unusable if an associated thing gets deleted.
                    # @todo: consider having this actually remove the
                    # association ids from the list.
                    logging.warning(
                        "Bad reference in {}: association {} doesn't exist."
                        .format(self.uid, assc_id)
                    )
            elif kind == 'Organization':
                org_ids.add(assc_id)
            else:
                raise InvalidNetworkAssociation(
                    "Invalid association kind: {}".format(kind))

        return org_ids
Exemplo n.º 9
0
 def test_completion_ids(self):
     pid = self.test_create_portal_pd()
     participant = Participant.create(
         id=SqlModel.convert_uid(pid),
         name='Pascal',
         organization_id='Organization_PERTS',
     )
     participant.put()
     results = ParticipantData.completion_ids(
         project_cohort_id='ProjectCohort_12345678')
     expected = [
         {
             'module': 1,
             'percent_progress': '100',
             'token': 'Pascal'
         },
         {
             'module': 2,
             'percent_progress': '33',
             'token': 'Pascal'
         },
     ]
     self.assertEqual(results, expected)