1
Fork 0
mirror of https://github.com/pds-nest/nest.git synced 2024-11-25 14:34:19 +00:00

Add alert creation

This commit is contained in:
Lorenzo Balugani 2021-05-07 19:15:14 +02:00
parent 112c40a372
commit 2d00b9102f
10 changed files with 351 additions and 4 deletions

View file

@ -26,6 +26,8 @@ app.add_url_rule("/api/v1/repositories/", view_func=page_repositories, methods=[
app.add_url_rule("/api/v1/repositories/<int:rid>", view_func=page_repository, methods=["GET", "PATCH", "DELETE", "PUT"]) app.add_url_rule("/api/v1/repositories/<int:rid>", view_func=page_repository, methods=["GET", "PATCH", "DELETE", "PUT"])
app.add_url_rule("/api/v1/repositories/<int:rid>/conditions", view_func=page_repository_conditions, app.add_url_rule("/api/v1/repositories/<int:rid>/conditions", view_func=page_repository_conditions,
methods=["GET", "POST"]) methods=["GET", "POST"])
app.add_url_rule("/api/v1/repositories/<int:rid>/alerts", view_func=page_repository_alerts,
methods=["GET", "POST"])
app.add_url_rule("/api/v1/conditions/<int:cid>", view_func=page_condition, methods=["GET", "PATCH", "DELETE"]) app.add_url_rule("/api/v1/conditions/<int:cid>", view_func=page_condition, methods=["GET", "PATCH", "DELETE"])
app.register_error_handler(Exception, error_handler) app.register_error_handler(Exception, error_handler)

View file

@ -75,5 +75,38 @@ class CreateCondition(Schema):
content = fields.String(description="The condition content. Meaning may change according to type.") content = fields.String(description="The condition content. Meaning may change according to type.")
class CreateAlert(Schema):
name = fields.String(description="The name of the alert.")
limit = fields.Integer(description="The number of tweets in a time window.")
window_size = fields.Integer(description="The size of the time window.")
class Operations(Schema):
id = fields.Integer(description="The operation id.")
operation = fields.Integer(description="The type of the operation.")
is_root = fields.Boolean(description="If true, the operation is the root of the operation tree.")
node_1 = fields.Nested('self')
node_2 = fields.Nested('self')
condition = fields.Nested(ConditionSchema)
alert_id = fields.Integer(description="The id of the related alert.")
class Notification(Schema):
id = fields.Integer(description="The notification id.")
ora = fields.DateTime(description="Muda muda muda.")
repository_id = fields.Integer(description="The id of the related repository.")
class Alert(Schema):
id = fields.Integer(description="The alert id.")
name = fields.String(description="The name of the alert.")
limit = fields.Integer(description="The number of tweets in a time window.")
window_size = fields.Integer(description="The size of the time window.")
repository_id = fields.Integer(description="The id of the related repository.")
operations = fields.Nested(Operations, many=True)
root_operation = fields.Nested(Operations, many=False)
notifications = fields.Nested(Notification, many=True)
class ConditionParameterSchema(Schema): class ConditionParameterSchema(Schema):
cid = fields.Integer(description="The condition id.") cid = fields.Integer(description="The condition id.")

View file

@ -29,6 +29,8 @@ spec.components.schema("RepositoryUpdate", schema=RepositoryUpdate)
spec.components.schema("CreateRepository", schema=CreateRepository) spec.components.schema("CreateRepository", schema=CreateRepository)
spec.components.schema("CreateCondition", schema=CreateCondition) spec.components.schema("CreateCondition", schema=CreateCondition)
spec.components.schema("ConditionParameter", schema=ConditionParameterSchema) spec.components.schema("ConditionParameter", schema=ConditionParameterSchema)
spec.components.schema("Alert", schema=Alert)
spec.components.schema("CreateAlert", schema=CreateAlert)
spec.components.security_scheme("jwt", {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}) spec.components.security_scheme("jwt", {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"})
# add swagger tags that are used for endpoint annotation # add swagger tags that are used for endpoint annotation
@ -42,6 +44,9 @@ tags = [
{'name': 'condition-related', {'name': 'condition-related',
'description': 'Condition related calls of the API.' 'description': 'Condition related calls of the API.'
}, },
{'name': 'alert-related',
'description': 'Alert related calls of the API.'
},
{'name': 'admin-only', {'name': 'admin-only',
'description': 'Admin only calls of the API.' 'description': 'Admin only calls of the API.'
}, },

View file

@ -16,4 +16,17 @@ class Alert(Base.Model):
# Relationships # Relationships
repository = Base.relationship("Repository", back_populates="alerts") repository = Base.relationship("Repository", back_populates="alerts")
notifications = Base.relationship("Notification", back_populates="alert", cascade="all, delete") notifications = Base.relationship("Notification", back_populates="alert", cascade="all, delete")
operations = Base.relationship("BoolOperation", back_populates="alert", cascade="all, delete") operations = Base.relationship("BoolOperation", back_populates="alert", cascade="all, delete")
def to_json(self):
return {
'id': self.id,
'name': self.name,
'window_size': self.window_size,
'limit': self.limit,
'repository_id': self.repository_id,
'notifications': [notification.to_json() for notification in self.notifications],
'operations': [operation.to_json() for operation in self.operations],
'root_operation': [operation.to_json() for operation in self.operations if operation.is_root == True][
0] if self.operations else None
}

View file

@ -10,7 +10,7 @@ class BoolOperation(Base.Model):
__tablename__ = "bool_operation" __tablename__ = "bool_operation"
id = Base.Column(Base.Integer, primary_key=True) id = Base.Column(Base.Integer, primary_key=True)
operation = Base.Column(Base.Enum(OperationType), nullable=False) operation = Base.Column(Base.Enum(OperationType), nullable=False)
isRoot = Base.Column(Base.Boolean, default=False, nullable=False) is_root = Base.Column(Base.Boolean, default=False, nullable=False)
# Foreign Keys # Foreign Keys
condition_id = Base.Column(Base.Integer, Base.ForeignKey("condition.id")) condition_id = Base.Column(Base.Integer, Base.ForeignKey("condition.id"))
node_1_id = Base.Column(Base.Integer, Base.ForeignKey("bool_operation.id")) node_1_id = Base.Column(Base.Integer, Base.ForeignKey("bool_operation.id"))
@ -23,3 +23,13 @@ class BoolOperation(Base.Model):
node_2 = Base.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_2_id==bool_operation.c.id"), node_2 = Base.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_2_id==bool_operation.c.id"),
remote_side="BoolOperation.id", backref=backref("father_2", uselist=False)) remote_side="BoolOperation.id", backref=backref("father_2", uselist=False))
alert = Base.relationship("Alert", back_populates="operations") alert = Base.relationship("Alert", back_populates="operations")
def to_json(self):
return {"id": self.id,
"operation": self.operation,
"is_root": self.is_root,
"alert_id": self.alert_id,
"condition": self.condition.to_json() if self.condition else None,
"node_1": self.node_1.to_json() if self.node_1 else None,
"node_2": self.node_2.to_json() if self.node_2 else None
}

View file

@ -11,4 +11,11 @@ class Notification(Base.Model):
# Foreign Key # Foreign Key
alert_id = Base.Column(Base.Integer, Base.ForeignKey("alert.id"), nullable=False) alert_id = Base.Column(Base.Integer, Base.ForeignKey("alert.id"), nullable=False)
# Relationships # Relationships
alert = Base.relationship("Alert", back_populates="notifications") alert = Base.relationship("Alert", back_populates="notifications")
def to_json(self):
return {
"id": self.id,
"ora": self.ora.isoformat(),
"alert_id": self.alert_id
}

View file

@ -1,4 +1,5 @@
from .conditions import page_repository_conditions from .conditions import page_repository_conditions
from .repository import page_repository from .repository import page_repository
from .repositories import page_repositories from .repositories import page_repositories
from .conditions import * from .conditions import *
from .alerts import *

View file

@ -0,0 +1 @@
from .repository_alerts import page_repository_alerts

View file

@ -0,0 +1,183 @@
from flask import render_template, abort, jsonify, request
from nest_backend.database import *
from flask_jwt_extended import jwt_required
from nest_backend.gestione import *
from flask_cors import cross_origin
import datetime
@cross_origin()
@jwt_required()
@repository_auth
def page_repository(aid):
"""
---
get:
summary: Get details about a repository.
parameters:
- in: path
schema: IntegerParameterSchema
security:
- jwt: []
responses:
'200':
description: The details about the requested schema. The schema is incapsulated in Success.
content:
application/json:
schema: Repository
'404':
description: Could not find the requested repository.
content:
application/json:
schema: Error
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
tags:
- repository-related
delete:
summary: Deletes a repository.
parameters:
- in: path
schema: IntegerParameterSchema
security:
- jwt: []
responses:
'200':
description: The repository has been deleted successfully.
'404':
description: Could not find the requested repository.
content:
application/json:
schema: Error
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
'500':
description: Could not delete the repository.
content:
application/json:
schema: Error
tags:
- repository-related
patch:
summary: Updates a repository.
security:
- jwt: []
requestBody:
required: true
content:
application/json:
schema: RepositoryUpdate
parameters:
- in: path
schema: IntegerParameterSchema
responses:
'200':
description: The repository has been updated successfully.
content:
application/json:
schema: Repository
'404':
description: Could not find the requested repository.
content:
application/json:
schema: Error
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
tags:
- repository-related
put:
summary: Overwrites a repository.
security:
- jwt: []
requestBody:
required: true
content:
application/json:
schema: Repository
parameters:
- in: path
schema: IntegerParameterSchema
responses:
'200':
description: The repository has been updated successfully.
content:
application/json:
schema: Repository
'404':
description: Could not find the requested repository.
content:
application/json:
schema: Error
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
'400':
description: The request was malformed.
content:
application/json:
schema: Error
tags:
- repository-related
"""
user = find_user(get_jwt_identity())
alert = Alert.query.filter_by(id=aid).first()
if not alert:
return json_error("Could not find alert."), 404
if alert.repository not in [a.repository for a in user.authorizations] + user.owner_of:
json_error("You are not authorized to proceed."), 403
if request.method == "GET":
return json_success(alert.to_json()), 200
if alert.repository not in user.owner_of:
json_error("You are not authorized to proceed."), 403
if request.method == "PATCH":
if 'name' in request.json:
alert.name = request.json['name']
if 'limit' in request.json:
alert.limit = request.json['limit']
if 'window_size' in request.json:
alert.window_size = request.json['window_size']
Base.session.commit()
return json_success(alert.to_json()), 200
elif request.method == "DELETE":
try:
Base.session.delete(alert)
Base.session.commit()
except Exception:
return json_error("Something went wrong while deleting alert."), 500
return json_success("Deletion completed."), 200
elif request.method == "PUT":
pass

View file

@ -0,0 +1,92 @@
from flask import render_template, abort, jsonify, request
from nest_backend.database import *
from flask_jwt_extended import jwt_required
from nest_backend.gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
@repository_auth
def page_repository_alerts(rid):
"""
---
get:
summary: Get a list of a repository alerts.
parameters:
- in: path
schema: IntegerParameterSchema
security:
- jwt: []
responses:
'200':
description: List of Alert schemas, incapsulated in Success.
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'404':
description: The repository could not be found.
content:
application/json:
schema: Error
tags:
- repository-related
post:
summary: Creates an alert and attaches it to the repository.
security:
- jwt: []
requestBody:
required: true
content:
application/json:
schema: CreateAlert
responses:
'200':
description: The alert has been created successfully.
content:
application/json:
schema: Alert
'403':
description: The user is not authorized.
content:
application/json:
schema: Error
'401':
description: The user is not logged in.
content:
application/json:
schema: Error
tags:
- alert-related
"""
repository = Repository.query.filter_by(id=rid).first()
if not repository:
return json_error("Could not find repository"), 404
user = find_user(get_jwt_identity())
if user.email != repository.owner_id:
return json_error("You are not authorized."), 403
if request.method == "GET":
return json_success([alert.to_json() for alert in repository.alerts])
if request.method == "POST":
if 'name' not in request.json:
json_error("Missing name."), 400
if 'limit' not in request.json:
json_error('Missing limit'), 400
if 'window_size' not in request.json:
json_error('Missing window size'), 400
alert = Alert(name=request.json['name'], limit=request.json['limit'], window_size=request.json['window_size'],
repository_id=rid)
Base.session.add(alert)
Base.session.commit()
return json_success(alert.to_json()), 200