def create(): require(request.authz.logged_in) data = parse_request(CollectionCreateSchema) role = Role.by_id(request.authz.id) sync = get_flag('sync') collection = create_collection(data, role=role, sync=sync) return CollectionSerializer.jsonify(collection)
def ingest_upload(collection_id): require(request.authz.can(collection_id, request.authz.WRITE)) sync = get_flag('sync') meta, foreign_id = _load_metadata() parent_id = _load_parent(collection_id, meta) upload_dir = mkdtemp(prefix='aleph.upload.') try: path = None content_hash = None for storage in request.files.values(): path = safe_filename(storage.filename, default='upload') path = os.path.join(upload_dir, path) storage.save(path) content_hash = checksum(path) document = Document.by_keys(collection_id=collection_id, parent_id=parent_id, foreign_id=foreign_id, content_hash=content_hash) document.update(meta) document.schema = Document.SCHEMA if content_hash is None: document.schema = Document.SCHEMA_FOLDER ingest_document(document, path, role_id=request.authz.id, content_hash=content_hash) finally: shutil.rmtree(upload_dir) if document.collection.casefile: # Make sure collection counts are always accurate. update_document(document, sync=sync) return jsonify({ 'status': 'ok', 'id': stringify(document.id) }, status=201)
def triples(collection_id): require(request.authz.can_stream()) log.debug("Stream triples [%r] begins... (coll: %s)", request.authz, collection_id) collection = get_db_collection(collection_id, request.authz.READ) record_audit(Audit.ACT_COLLECTION, id=collection_id) return Response(export_collection(collection), mimetype='text/plain')
def create(): require(not request.authz.in_maintenance, settings.PASSWORD_LOGIN) data = parse_request(RoleCreateSchema) try: email = Role.SIGNATURE.loads(data.get('code'), max_age=Role.SIGNATURE_MAX_AGE) except BadSignature: return jsonify({ 'status': 'error', 'message': gettext('Invalid code') }, status=400) role = Role.by_email(email) if role is not None: return jsonify({ 'status': 'error', 'message': gettext('Email is already registered') }, status=409) role = Role.load_or_create( foreign_id='password:{}'.format(email), type=Role.USER, name=data.get('name') or email, email=email ) role.set_password(data.get('password')) db.session.add(role) db.session.commit() update_role(role) # Let the serializer return more info about this user request.authz.id = role.id tag_request(role_id=role.id) return RoleSerializer.jsonify(role, status=201)
def create(): require(request.authz.session_write) data = parse_request(AlertSchema) alert = Alert.create(data, request.authz.id) db.session.commit() tag_request(alert_id=alert.id) return AlertSerializer.jsonify(alert)
def index(): require(request.authz.logged_in) role = Role.by_id(request.authz.id) query = Notification.by_channels(get_role_channels(role), since=role.notified_at, exclude_actor_id=role.id) result = DatabaseQueryResult(request, query) return NotificationSerializer.jsonify_result(result)
def update(id): role = obj_or_404(Role.by_id(id)) require(request.authz.session_write) require(check_editable(role, request.authz)) data = parse_request(RoleSchema) role.update(data) db.session.add(role) db.session.commit() update_role(role) return RoleSerializer.jsonify(role)
def export(format): require(request.authz.logged_in) parser = SearchQueryParser(request.args, request.authz) parser.limit = EXPORT_MAX tag_request(query=parser.text, prefix=parser.prefix) result = EntitiesQuery.handle(request, parser=parser) stream = export_entities(request, result, format) response = Response(stream, mimetype='application/zip') disposition = 'attachment; filename={}'.format('Query_export.zip') response.headers['Content-Disposition'] = disposition return response
def bulk(collection_id): collection = get_db_collection(collection_id, request.authz.WRITE) require(request.authz.can_bulk_import()) merge = get_flag('merge', default=False) # This will disable certain security measures in order to allow bulk # loading of document data. unsafe = get_flag('unsafe', default=False) unsafe = unsafe and request.authz.is_admin entities = ensure_list(request.get_json(force=True)) bulk_write(collection, entities, merge=merge, unsafe=unsafe) refresh_collection(id) return ('', 204)
def suggest(): require(request.authz.logged_in) parser = QueryParser(request.args, request.authz, limit=10) if parser.prefix is None or len(parser.prefix) < 3: # Do not return 400 because it's a routine event. return jsonify({ 'status': 'error', 'message': gettext('prefix filter is too short'), 'results': [], 'total': 0 }) # this only returns users, not groups q = Role.by_prefix(parser.prefix, exclude=parser.exclude) result = DatabaseQueryResult(request, q, parser=parser) return RoleSerializer.jsonify_result(result)
def update(id): """Change user settings. --- post: summary: Change user settings description: > Update a role to change its display name, or to define a new login password. Users can only update roles they have write access to, i.e. their own. parameters: - in: path name: id required: true description: role ID schema: type: integer requestBody: content: application/json: schema: $ref: '#/components/schemas/RoleUpdate' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Role' tags: - Role """ role = obj_or_404(Role.by_id(id)) require(request.authz.can_write_role(role.id)) data = parse_request("RoleUpdate") # When changing passwords, check the old password first. # cf. https://github.com/alephdata/aleph/issues/718 if data.get("password"): current_password = data.get("current_password") if not role.check_password(current_password): raise BadRequest(gettext("Incorrect password.")) role.update(data) db.session.add(role) db.session.commit() update_role(role) return RoleSerializer.jsonify(role)
def update(entity_id): """ --- post: summary: Update an entity description: > Update the entity with id `entity_id`. This only applies to entities which are backed by a database row, i.e. not any entities resulting from a mapping or bulk load. parameters: - in: path name: entity_id required: true schema: type: string format: entity_id requestBody: content: application/json: schema: $ref: '#/components/schemas/EntityUpdate' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Entity' tags: - Entity """ data = parse_request("EntityUpdate") try: entity = get_index_entity(entity_id, request.authz.WRITE) require(check_write_entity(entity, request.authz)) collection = get_db_collection(entity.get("collection_id"), request.authz.WRITE) except NotFound: collection = get_nested_collection(data, request.authz.WRITE) tag_request(collection_id=collection.id) data["id"] = entity_id if get_flag("validate", default=False): validate_entity(data) sync = get_flag("sync", default=True) entity_id = upsert_entity(data, collection, authz=request.authz, sync=sync) db.session.commit() return view(entity_id)
def update(id): role = obj_or_404(Role.by_id(id)) require(request.authz.can_write_role(role.id)) data = parse_request(RoleSchema) # When changing passwords, check the old password first. # cf. https://github.com/alephdata/aleph/issues/718 if data.get('password'): current_password = data.get('current_password') if not role.check_password(current_password): raise BadRequest(gettext('Incorrect password.')) role.update(data) db.session.add(role) db.session.commit() update_role(role) return RoleSerializer.jsonify(role)
def suggest(): """ --- get: summary: Suggest users matching a search prefix description: >- For a given `prefix`, suggest matching user accounts. For security reasons, the prefix must be more than three characters long. parameters: - in: query name: prefix required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object allOf: - $ref: '#/components/schemas/QueryResponse' properties: results: type: array items: $ref: '#/components/schemas/Role' tags: - Role """ require(request.authz.logged_in) parser = QueryParser(request.args, request.authz, limit=10) if parser.prefix is None or len(parser.prefix) < 3: # Do not return 400 because it's a routine event. return jsonify({ 'status': 'error', 'message': gettext('prefix filter is too short'), 'results': [], 'total': 0 }) # this only returns users, not groups q = Role.by_prefix(parser.prefix, exclude=parser.exclude) result = DatabaseQueryResult(request, q, parser=parser) return RoleSerializer.jsonify_result(result)
def mapping_process(collection_id): collection = get_db_collection(collection_id, request.authz.WRITE) require(request.authz.can_bulk_import()) # TODO: we need to look into possible abuse of mapping load path for local # path access on the machine running the mapping. Until then, this action # must be restricted to admins: require(request.authz.is_admin) if not request.is_json: raise BadRequest() data = request.get_json().get(collection.foreign_id) for query in keys_values(data, 'queries', 'query'): try: model.make_mapping(query) bulk_load_query.apply_async([collection.id, query], priority=6) except InvalidMapping as invalid: raise BadRequest(invalid) return ('', 204)
def create(): """Create a user role. --- post: summary: Create a user account description: > Create a user role by supplying the required account details. requestBody: content: application/json: schema: $ref: '#/components/schemas/RoleCreate' responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Role' tags: - Role """ require(settings.PASSWORD_LOGIN) require(not request.authz.in_maintenance) data = parse_request('RoleCreate') try: email = Role.SIGNATURE.loads(data.get('code'), max_age=Role.SIGNATURE_MAX_AGE) except BadSignature: return jsonify({ 'status': 'error', 'message': gettext('Invalid code') }, status=400) role = Role.by_email(email) if role is not None: return jsonify({ 'status': 'error', 'message': gettext('Email is already registered') }, status=409) role = create_user(email, data.get('name'), data.get('password')) # Let the serializer return more info about this user request.authz = Authz.from_role(role) tag_request(role_id=role.id) return RoleSerializer.jsonify(role, status=201)
def entities(collection_id=None): require(request.authz.can_stream()) log.debug("Stream entities [%r] begins... (coll: %s)", request.authz, collection_id) schemata = ensure_list(request.args.getlist('schema')) excludes = ['text', 'roles', 'fingerprints'] includes = ensure_list(request.args.getlist('include')) includes = [f for f in includes if f not in excludes] if collection_id is not None: get_db_collection(collection_id, request.authz.READ) record_audit(Audit.ACT_COLLECTION, id=collection_id) entities = iter_entities(authz=request.authz, collection_id=collection_id, schemata=schemata, excludes=excludes, includes=includes) return stream_ijson(entities)
def mapping_process(id): collection = get_db_collection(id, request.authz.WRITE) require(request.authz.can_bulk_import()) # TODO: we need to look into possible abuse of mapping load path for local # path access on the machine running the mapping. Until then, this action # must be restricted to admins: require(request.authz.is_admin) if not request.is_json: raise BadRequest() data = request.get_json().get(collection.foreign_id) for query in keys_values(data, 'queries', 'query'): try: model.make_mapping(query) bulk_load_query.apply_async([collection.id, query], priority=6) except InvalidMapping as invalid: raise BadRequest(invalid) return ('', 204)
def index(collection_id): """ --- get: summary: Fetch cross-reference results description: >- Fetch cross-reference matches for entities in the collection with id `collection_id` parameters: - in: path name: collection_id required: true schema: type: integer responses: '200': description: OK content: application/json: schema: type: object allOf: - $ref: '#/components/schemas/QueryResponse' properties: results: type: array items: $ref: '#/components/schemas/XrefResponse' tags: - Xref - Collection """ get_index_collection(collection_id) result = XrefQuery.handle(request, collection_id=collection_id) context_id = result.parser.getint('context_id', request.authz.id) if context_id is not None: require(request.authz.can_read_role(context_id)) pairs = [] for xref in result.results: pairs.append((xref.get('entity_id'), xref.get('match_id'))) decisions = Linkage.decisions(pairs, context_id) for xref in result.results: key = (xref.get('entity_id'), xref.get('match_id')) xref['decision'] = decisions.get(key) return XrefSerializer.jsonify_result(result)
def status(): require(request.authz.logged_in) status = get_active_collection_status() active_collections = status.pop('datasets', []) active_foreign_ids = set(active_collections.keys()) collections = request.authz.collections(request.authz.READ) serializer = CollectionSerializer(reference=True) results = [] for fid in sorted(active_foreign_ids): collection = Collection.by_foreign_id(fid) if collection is None: continue if collection.id in collections: result = active_collections[fid] result['collection'] = serializer.serialize(collection.to_dict()) result['id'] = fid results.append(result) return jsonify({'results': results, 'total': len(results)})
def status(): require(request.authz.logged_in) status = get_active_collection_status() active_collections = status.pop('datasets') active_foreign_ids = set(active_collections.keys()) collections = request.authz.collections(request.authz.READ) results = [] for fid in active_foreign_ids: collection = Collection.by_foreign_id(fid) if collection is None: continue if collection.id in collections: result = active_collections[fid] result['collection'] = collection.to_dict() result['id'] = fid results.append(result) status['results'] = results return jsonify(status)
def retrieve(): """Downloads a binary blob from the blob storage archive. --- get: summary: Download a blob from the archive parameters: - description: Authorization token for an archive blob in: query name: claim schema: type: string description: A signed JWT with the object hash. responses: '200': description: OK content: '*/*': {} '404': description: Object does not exist. tags: - Archive """ claim = request.args.get("claim") role_id, content_hash, file_name, mime_type = archive_claim(claim) require(request.authz.id == role_id) tag_request(content_hash=content_hash, file_name=file_name) url = archive.generate_url(content_hash, file_name=file_name, mime_type=mime_type) if url is not None: return redirect(url) try: local_path = archive.load_file(content_hash) if local_path is None: return Response(status=404) return send_file( str(local_path), as_attachment=True, conditional=True, attachment_filename=file_name, mimetype=mime_type, ) finally: archive.cleanup_file(content_hash)
def password_login(): """Provides email and password authentication. --- post: summary: Log in as a user description: Create a session token using a username and password. requestBody: content: application/json: schema: $ref: '#/components/schemas/Login' responses: '200': description: OK content: application/json: schema: type: object properties: status: type: string token: type: string tags: - Role """ require(settings.PASSWORD_LOGIN) data = parse_request("Login") role = Role.by_email(data.get("email")) if role is None or not role.has_password: raise BadRequest(gettext("Invalid user or password.")) if not role.check_password(data.get("password")): raise BadRequest(gettext("Invalid user or password.")) if role.is_blocked: raise Unauthorized(gettext("Your account is blocked.")) role.touch() db.session.commit() update_role(role) authz = Authz.from_role(role) request.authz = authz return jsonify({"status": "ok", "token": authz.to_token(role=role)})
def entities(collection_id=None): """ --- get: summary: Stream collection entities. description: > Stream a JSON form of each entity in the given collection, or throughout the entire database. parameters: - description: The collection ID. in: path name: collection_id required: true schema: minimum: 1 type: integer responses: '200': description: OK content: application/x-ndjson: schema: type: array items: $ref: '#/components/schemas/Entity' tags: - Entity """ log.debug("Stream entities [%r] begins... (coll: %s)", request.authz, collection_id) schemata = ensure_list(request.args.getlist("schema")) includes = ensure_list(request.args.getlist("include")) includes = includes or PROXY_INCLUDES if collection_id is not None: get_db_collection(collection_id, request.authz.WRITE) else: require(request.authz.is_admin) entities = iter_entities( authz=request.authz, collection_id=collection_id, schemata=schemata, includes=includes, ) return stream_ijson(entities)
def oauth_init(): """Init OAuth auth flow. --- get: summary: Start OAuth authentication description: Initiate a forward to the OAuth server. responses: '302': description: Redirect tags: - Role """ require(settings.OAUTH) url = url_for(".oauth_callback") state = oauth.provider.create_authorization_url(url) state["next_url"] = request.args.get("next", request.referrer) state["redirect_uri"] = url cache.set_complex(_oauth_session(state.get("state")), state, expires=3600) return redirect(state["url"])
def entities(collection_id=None): """ --- get: summary: Stream collection entities. description: > Stream a JSON form of each entity in the given collection, or throughout the entire database. parameters: - description: The collection ID. in: path name: collection_id required: true schema: minimum: 1 type: integer responses: '200': description: OK content: application/x-ndjson: schema: type: array items: $ref: '#/components/schemas/Entity' tags: - Entity """ require(request.authz.can_stream()) log.debug("Stream entities [%r] begins... (coll: %s)", request.authz, collection_id) schemata = ensure_list(request.args.getlist('schema')) excludes = ['text', 'fingerprints'] includes = ensure_list(request.args.getlist('include')) includes = [f for f in includes if f not in excludes] if collection_id is not None: get_db_collection(collection_id, request.authz.READ) entities = iter_entities(authz=request.authz, collection_id=collection_id, schemata=schemata, excludes=excludes, includes=includes) return stream_ijson(entities)
def oauth_callback(): require(settings.OAUTH) err = Unauthorized(gettext("Authentication has failed.")) state = cache.get_complex(_oauth_session(request.args.get("state"))) if state is None: raise err try: oauth.provider.framework.set_session_data(request, "state", state.get("state")) uri = state.get("redirect_uri") oauth_token = oauth.provider.authorize_access_token(redirect_uri=uri) except AuthlibBaseError as err: log.warning("Failed OAuth: %r", err) raise err if oauth_token is None or isinstance(oauth_token, AuthlibBaseError): log.warning("Failed OAuth: %r", oauth_token) raise err role = handle_oauth(oauth.provider, oauth_token) if role is None: raise err # Determine session duration based on OAuth settings expire = oauth_token.get("expires_in", Authz.EXPIRE) expire = oauth_token.get("refresh_expires_in", expire) db.session.commit() update_role(role) log.debug("Logged in: %r", role) request.authz = Authz.from_role(role, expire=expire) token = request.authz.to_token() # Store id_token to generate logout URL later id_token = oauth_token.get("id_token") if id_token is not None: cache.set(_token_session(token), id_token, expires=expire) next_path = get_url_path(state.get("next_url")) next_url = ui_url("oauth", next=next_path) next_url = "%s#token=%s" % (next_url, token) session.clear() return redirect(next_url)
def oauth_callback(): require(settings.OAUTH) token = oauth.provider.authorize_access_token() if token is None or isinstance(token, AuthlibBaseError): log.warning("Failed OAuth: %r", token) raise Unauthorized(gettext("Authentication has failed.")) role = handle_oauth(oauth.provider, token) if role is None: log.error("No OAuth handler was installed.") raise Unauthorized(gettext("Authentication has failed.")) db.session.commit() update_role(role) log.info("Logged in: %r", role) request.authz = Authz.from_role(role) token = request.authz.to_token(role=role) token = token.decode('utf-8') next_path = get_url_path(request.args.get('state')) next_url = ui_url(settings.OAUTH_UI_CALLBACK, next=next_path) next_url = '%s#token=%s' % (next_url, token) return redirect(next_url)
def retrieve(): claim = request.args.get('claim') role_id, content_hash, file_name, mime_type = archive_claim(claim) require(request.authz.id == role_id) tag_request(content_hash=content_hash, file_name=file_name) url = archive.generate_url(content_hash, file_name=file_name, mime_type=mime_type) if url is not None: return redirect(url) try: local_path = archive.load_file(content_hash) if local_path is None: return Response(status=404) return send_file(str(local_path), as_attachment=True, conditional=True, attachment_filename=file_name, mimetype=mime_type) finally: archive.cleanup_file(content_hash)
def view(profile_id): """ --- get: summary: Retrieve a profile description: >- Get a profile with constituent items and the merged pseudo entity. responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/Profile' tags: - Profile """ profile = obj_or_404(get_profile(profile_id, authz=request.authz)) require(request.authz.can(profile.get("collection_id"), request.authz.READ)) return ProfileSerializer.jsonify(profile)
def export(): """ --- post: summary: Download the results of a search description: >- Downloads all the results of a search as a zip archive; upto a max of 10,000 results. The returned file will contain an Excel document with structured data as well as the binary files from all matching documents. Supports the same query parameters as the search API. responses: '202': description: Accepted tags: - Entity """ require(request.authz.logged_in) parser = SearchQueryParser(request.args, request.authz) parser.limit = MAX_PAGE tag_request(query=parser.text, prefix=parser.prefix) result = EntitiesQuery.handle(request, parser=parser) label = "Search results for query: %s" % parser.text export = create_export( operation=OP_EXPORT_SEARCH_RESULTS, role_id=request.authz.id, label=label, file_path=None, expires_after=Export.DEFAULT_EXPIRATION, collection=None, mime_type=ZIP, ) job_id = get_session_id() payload = { "export_id": export.id, "result": result.to_dict(), } queue_task(None, OP_EXPORT_SEARCH_RESULTS, job_id=job_id, payload=payload) return ("", 202)
def retrieve(): claim = request.args.get('claim') role_id, content_hash, file_name, mime_type = archive_claim(claim) require(request.authz.id == role_id) record_audit(Audit.ACT_ARCHIVE, content_hash=content_hash) tag_request(content_hash=content_hash, file_name=file_name) url = archive.generate_url(content_hash, file_name=file_name, mime_type=mime_type) if url is not None: return redirect(url) try: local_path = archive.load_file(content_hash) if local_path is None: return Response(status=404) return send_file(local_path, as_attachment=True, conditional=True, attachment_filename=file_name, mimetype=mime_type) finally: archive.cleanup_file(content_hash)
def status(): """ --- get: summary: Get an overview of collections being processed description: > List collections being processed currently and pending task counts responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/SystemStatusResponse' tags: - System """ require(request.authz.logged_in) request.rate_limit = None status = get_active_collection_status() active_collections = status.pop('datasets', []) active_foreign_ids = set(active_collections.keys()) collections = request.authz.collections(request.authz.READ) serializer = CollectionSerializer(reference=True) results = [] for fid in sorted(active_foreign_ids): collection = Collection.by_foreign_id(fid) if collection is None: continue if collection.id in collections: result = active_collections[fid] result['collection'] = serializer.serialize(collection.to_dict()) result['id'] = fid results.append(result) return jsonify({ 'results': results, 'total': len(results) })
def create_code(): """Send a account creation token to an email address. --- post: summary: Begin account registration description: > Begin validating a user email by sending a token to the address which can then be used to create an account. requestBody: content: application/json: schema: $ref: '#/components/schemas/RoleCodeCreate' responses: '200': description: OK content: application/json: schema: type: object properties: status: type: string token: type: string tags: - Role """ require(settings.PASSWORD_LOGIN) require(not request.authz.in_maintenance) data = parse_request("RoleCodeCreate") challenge_role(data) return jsonify({ "status": "ok", "message": gettext("To proceed, please check your email.") })
def tags(profile_id): """ --- get: summary: Get profile tags description: >- Get tags for the profile with id `profile_id`. parameters: - in: path name: profile_id required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object allOf: - $ref: '#/components/schemas/QueryResponse' properties: results: type: array items: $ref: '#/components/schemas/EntityTag' tags: - Profile """ profile = obj_or_404(get_profile(profile_id, authz=request.authz)) require(request.authz.can(profile.get("collection_id"), request.authz.READ)) tag_request(collection_id=profile.get("collection_id")) results = entity_tags(profile["merged"], request.authz) return jsonify({"status": "ok", "total": len(results), "results": results})
def status(): """ --- get: summary: Get an overview of collections and exports being processed description: > List collections being processed currently and pending task counts responses: '200': description: OK content: application/json: schema: $ref: '#/components/schemas/SystemStatusResponse' tags: - System """ require(request.authz.logged_in) request.rate_limit = None status = get_active_dataset_status() datasets = status.pop("datasets", {}) collections = (get_dataset_collection_id(d) for d in datasets.keys()) collections = (c for c in collections if c is not None) collections = Collection.all_by_ids(collections, deleted=True).all() collections = {c.id: c for c in collections} serializer = CollectionSerializer(reference=True) results = [] for dataset, status in sorted(datasets.items()): collection_id = get_dataset_collection_id(dataset) if not request.authz.can(collection_id, request.authz.READ): continue collection = collections.get(collection_id) if collection is not None: status["collection"] = serializer.serialize(collection.to_dict()) results.append(status) return jsonify({"results": results, "total": len(results)})
def delete(): """Delete the query logs for a particular search term. --- delete: summary: Clear query log description: Delete the query logs for a particular search term parameters: - in: query name: query schema: type: string responses: '204': description: No Content tags: - Query Log """ require(request.authz.logged_in) query = request.args.get('query') if not query: return ('', 404) QueryLog.delete_query(request.authz.id, query) db.session.commit() return ('', 204)
def index(): require(request.authz.logged_in) parser = QueryParser(request.args, request.authz) q = QueryLog.query_log(role_id=request.authz.id) result = DatabaseQueryResult(request, q, parser=parser) return QueryLogSerializer.jsonify_result(result)
def view(alert_id): require(request.authz.logged_in) alert = obj_or_404(Alert.by_id(alert_id, role_id=request.authz.id)) return AlertSerializer.jsonify(alert)
def delete(alert_id): require(request.authz.session_write) alert = obj_or_404(Alert.by_id(alert_id, role_id=request.authz.id)) alert.delete() db.session.commit() return ('', 204)
def view(id): role = obj_or_404(Role.by_id(id)) require(check_editable(role, request.authz)) return RoleSerializer.jsonify(role)
def mark_read(): require(request.authz.logged_in) role = Role.by_id(request.authz.id) role.notified_at = datetime.utcnow() db.session.commit() return jsonify({'status': 'ok'}, status=202)
def index(): require(request.authz.logged_in) query = Alert.by_role(request.authz.role) result = DatabaseQueryResult(request, query, schema=AlertSchema) return jsonify(result)
def create(): require(request.authz.session_write) data = parse_request(schema=AlertSchema) alert = Alert.create(data, request.authz.role) db.session.commit() return view(alert.id)
def view(id): require(request.authz.logged_in) alert = obj_or_404(Alert.by_id(id, role=request.authz.role)) return jsonify(alert, schema=AlertSchema)
def delete(id): require(request.authz.session_write) alert = obj_or_404(Alert.by_id(id, role=request.authz.role)) alert.delete() db.session.commit() return jsonify({'status': 'ok'})
def index(): require(request.authz.logged_in) query = Alert.by_role_id(request.authz.id) result = DatabaseQueryResult(request, query) return AlertSerializer.jsonify_result(result)