示例#1
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)