Example #1
0
def joined_cohort(user, project_cohort):
    """Notify program and super admins."""
    # This always happens along with creating a program.
    pc = project_cohort
    program_admins = User.get(owned_programs=pc.program_label)
    super_admins = User.get(user_type='super_admin')
    organization = Organization.get_by_id(pc.organization_id)
    program_config = Program.get_config(pc.program_label)
    cohort_name = program_config['cohorts'][pc.cohort_label]['name']

    notes = []
    for admin in program_admins + super_admins:
        note = Notification.create(
            parent=admin,
            context_id=pc.uid,
            subject=u"{org} joined a cohort".format(org=organization.name),
            body=(
                u"{org} joined {cohort} in {program}. The organization is "
                "currently {status}."
            ).format(
                org=organization.name, cohort=cohort_name,
                program=program_config['name'], status=organization.status,
            ),
            link='/organizations/{}'.format(organization.short_uid),
            autodismiss=True,
        )
        notes.append(note)
    ndb.put_multi(notes)
Example #2
0
    def post(self, project_id, slug):
        """A project has been identified as new. Send them a welcome."""
        project = Project.get_by_id(project_id)
        program = Program.get_config(project.program_label)
        org = Organization.get_by_id(project.organization_id)

        # The Org liaison is preferred, but is not guaranteed to be set (users
        # choose their org liaison explicitly as one of the org tasks). Default
        # to the Project liaison, which is set on creation in
        # add_program.controller.js@joinProgram
        org_liaison = User.get_by_id(org.liaison_id)
        project_liaison = User.get_by_id(project.liaison_id)
        liaison = org_liaison or project_liaison

        email = Email.create(
            to_address=liaison.email,
            mandrill_template=slug,
            mandrill_template_content={
                'program_name': program['name'],
                'organization_name': org.name,
                'liaison_name': liaison.name,
                'join_date': util.datelike_to_iso_string(project.created),
            },
        )
        email.put()
Example #3
0
 def test_delete_other_forbidden(self):
     user, org_dict = self.test_create()
     other = User.create(name='other', email='*****@*****.**')
     other.put()
     response = self.testapp.delete('/api/organizations/{}'.format(
         org_dict['uid']),
                                    headers=self.login_headers(other),
                                    status=403)
     self.assertIsNotNone(Organization.get_by_id(org_dict['uid']))
Example #4
0
 def test_delete(self):
     """Owners can delete their orgs."""
     user, org_dict = self.test_create()
     response = self.testapp.delete('/api/organizations/{}'.format(
         org_dict['uid']),
                                    headers=self.login_headers(user),
                                    status=204)
     self.assertIsNone(Organization.get_by_id(org_dict['uid']))
     return response, user, org_dict
Example #5
0
 def test_organization_name_update(self):
     """Updating an organization name should update associated project"""
     org_name_1 = 'Foo College'
     org_name_2 = 'Bar College'
     organization = Organization.create(name=org_name_1)
     organization.put()
     project = Project.create(program_label='demo-program',
                              organization_id=organization.uid)
     project.put()
     organization = Organization.get_by_id(organization.uid)
     organization.name = org_name_2
     organization.put()
     project_dict = project.get_by_id(project.uid).to_client_dict()
     self.assertEqual(project_dict['organization_name'], organization.name)
Example #6
0
    def get(self, template, context_id):
        # Attempt to treat id as as project cohort (it might be a program, or
        # invalid).
        project_cohort = ProjectCohort.get_by_id(context_id)

        def todt(s):
            return datetime.datetime.strptime(s, config.iso_date_format)

        if project_cohort:
            # This is a "real" set of instructions with data filled in.
            organization = Organization.get_by_id(
                project_cohort.organization_id)
            liaison = User.get_by_id(organization.liaison_id)
            program = Program.get_config(project_cohort.program_label)
            cohort = program['cohorts'][project_cohort.cohort_label]
            participation_open_date = todt(cohort['open_date'])
            # See notes in program config for why we take a day off for display.
            participation_close_date = (todt(cohort['close_date']) -
                                        datetime.timedelta(1))
        else:
            # This is a generic example version of the document.
            try:
                program = Program.get_config(context_id)
            except ImportError:
                return self.http_not_found()
            organization = None
            liaison = None
            project_cohort = None
            cohort = None
            participation_open_date = None
            participation_close_date = None

        if template == 'custom_portal_technical_guide':
            # This template doesn't vary by program.
            template_filename = '{}.html'.format(template)
        else:
            template_filename = '{}_{}.html'.format(program['label'], template)

        self.write(
            template_filename,
            organization=organization,
            liaison=liaison,
            program_name=program['name'],
            cohort_name=cohort['name'] if cohort else '',
            program_description=program['description'],
            project_cohort=project_cohort,
            participation_open_date=participation_open_date,
            participation_close_date=participation_close_date,
        )
Example #7
0
    def get_organization_reports(self, organization_id):
        user = self.get_current_user()
        org = Organization.get_by_id(organization_id)

        if not org:
            return self.http_not_found()

        if not owns(user, org):
            return self.http_forbidden("Only org admins can list reports.")

        # Limit access to preview reports, super admin only.
        show_preview_reports = True if user.super_admin else False
        all_reports = Report.get_for_organization(org.uid,
                                                  show_preview_reports)

        # Add a custom link for users to access each report.
        self.write([
            dict(r.to_client_dict(), link=self.report_link(r))
            for r in all_reports
        ])
Example #8
0
    def test_create(self):
        """Anyone can create an org."""
        org_name = 'Org Foo'
        user = User.create(name='foo', email='*****@*****.**')
        user.put()
        response = self.testapp.post_json(
            '/api/organizations',
            {
                'name': org_name,
                'program_id': self.program.uid
            },
            headers=self.login_headers(user),
        )
        response_dict = json.loads(response.body)
        self.assertEqual(response_dict['name'], org_name)

        fetched_org = Organization.get_by_id(response_dict['uid'])
        self.assertIsNotNone(fetched_org)

        # Remove user's cookie so we can use the test app as other people.
        self.testapp.reset()
        return user, response_dict
Example #9
0
def downloaded_identifiers(user, project_cohort_id):
    supers = User.get(user_type='super_admin')
    notes = []

    project_cohort = ProjectCohort.get_by_id(project_cohort_id)
    organization = Organization.get_by_id(project_cohort.organization_id)
    program = Program.get_config(project_cohort.program_label)
    cohort_name = program['cohorts'][project_cohort.cohort_label]['name']

    for sup in supers:
        note = Notification.create(
            parent=sup,
            context_id=project_cohort_id,
            subject="IDs Downloaded",
            body=u"{} ({}) downloaded IDs for {}: {} {}.".format(
                user.name, user.email, organization.name, program['name'],
                cohort_name),
            link='/dashboard/{}'.format(project_cohort.short_uid),
            autodismiss=True,
        )
        notes.append(note)
    ndb.put_multi(notes)
    def get(self, org_id):
        user = self.get_current_user()
        org = Organization.get_by_id(org_id)

        if not org:
            return self.http_not_found()

        if not owns(user, org):
            return self.http_forbidden()

        teams = Team.query_by_organization(org_id)
        team_ids = [t.uid for t in teams]
        classrooms = Classroom.query_by_teams(team_ids)
        cycles = Cycle.query_by_teams(team_ids)
        responses = Response.get_for_teams(user, team_ids)
        users = User.query_by_team(team_ids)

        self.write({
            'classrooms': [e.to_client_dict() for e in classrooms],
            'cycles': [e.to_client_dict() for e in cycles],
            'teams': [e.to_client_dict() for e in teams],
            'responses': [e.to_client_dict() for e in responses],
            'users': [e.to_client_dict() for e in users],
        })
Example #11
0
    def post(self):
        """Save references to reports, and perhaps the report file itself.

        Has two modes: accept a file, in which case the file is saved to GCS, or
        a dataset id. In both cases a Report is inserted referencing the
        file/dataset.

        Either `team_id` or `classroom_id` must be provided. If team_id, then
        the report's classroom_id is empty (these are "team-level" reports). If
        classroom_id, the corresponding team_id is looked up (these are
        "classroom-level" reports).
        """

        # Allow RServe to call this endpoint, then fall back on regular auth.
        user, error = self.authenticate_rserve()
        if not user:
            user = self.get_current_user()
            error = ''

        # Replaces function of `requires_auth = True`.
        if user.user_type == 'public':
            return self.http_unauthorized()

        if not user.super_admin:
            return self.http_forbidden()

        org_id = self.get_param('organization_id', str, None)
        team_id = self.get_param('team_id', str, None)
        classroom_id = self.get_param('classroom_id', str, None)
        params = self.get_params({
            'dataset_id': str,
            'filename': unicode,
            'issue_date': str,
            'notes': unicode,
            'preview': bool,
            'template': str,
        })

        # Lookup related objects.
        classroom = None
        if classroom_id:
            classroom = Classroom.get_by_id(classroom_id)
            if not classroom:
                return self.http_bad_request(
                    "Classroom not found: {}".format(classroom_id))
            team_id = classroom.team_id

        team = None
        if team_id:
            # May be set for team reports, or via lookup for class reports.
            team = Team.get_by_id(team_id)
            if not team:
                return self.http_bad_request(
                    "Team not found: {}".format(team_id))

        org = None
        if org_id:
            org = Organization.get_by_id(org_id)
            if not org:
                return self.http_bad_request(
                    "Organization not found: {}".format(org_id))

        content_type = self.request.headers['Content-Type']
        is_form = 'multipart/form-data' in content_type
        is_json = 'application/json' in content_type

        if is_form:
            report = self.save_file(
                params['filename'],
                self.request.POST['file'],
                org_id,
                team_id,
                classroom_id,
            )
        elif is_json:
            kwargs = {
                'classroom_id': classroom_id,
                'dataset_id': params['dataset_id'],
                'filename': params['filename'],
                'issue_date': params.get('issue_date', None),
                'notes': params.get('notes', None),
                'organization_id': org_id,
                'team_id': team_id,
                'template': params['template'],
            }

            # Some params we may want to avoid including at all, so that if
            # they're absent they'll take the default value defined in the db.
            if params.get('preview', None) is not None:
                kwargs['preview'] = params['preview']

            report = Report.create(**kwargs)
        else:
            return self.http_bad_request(
                "Only supported content types are 1) multipart/form-data for "
                "uploading files and 2) application/json for datasets. Got {}".
                format(self.request.headers['Content-Type']))

        saved_report = Report.put_for_index(report, 'parent-file')

        self.write(saved_report)