def get(self, parent_type, rel_id, filename): # Always require a jwt that specifies this path/report. This allows # shareable, expiring links. if not self.get_current_user().super_admin: params = self.get_params({'token': str}) token = params.get('token', None) payload, error = jwt_helper.decode(token) if error == jwt_helper.EXPIRED: return self.http_forbidden("This link has expired.") elif not payload or error: return self.http_bad_request("Missing or invalid token.") allowed_endpoints = payload.get('allowed_endpoints', []) if self.get_endpoint_str() not in allowed_endpoints: return self.http_forbidden("Token does not allow endpoint.") if parent_type == 'organizations': parent_id = Organization.get_long_uid(rel_id), elif parent_type == 'teams': parent_id = Team.get_long_uid(rel_id), elif parent_type == 'classrooms': parent_id = Classroom.get_long_uid(rel_id), else: raise Exception("Unrecognized parent type: {}".format(parent_type)) results = Report.get(parent_id=parent_id, filename=filename) if len(results) == 0: return self.http_not_found() report = results[0] # We intentionally don't check permissions or ownership any further # here, because reports are shared by link, and we already checked for # a jwt in the query string. self.response.headers.update({ 'Content-Disposition': 'inline; filename={}'.format(report.filename), # Unicode not allowed in headers. 'Content-Type': str(report.content_type), }) try: with gcs.open(report.gcs_path, 'r') as gcs_file: self.response.write(gcs_file.read()) except gcs.NotFoundError: logging.error("Couldn't find a gcs file for report {}".format( report.to_dict())) self.http_not_found()