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

Add authorization creation/deletion API calls

This commit is contained in:
Lorenzo Balugani 2021-05-20 13:48:15 +02:00
parent 8d8e396ebf
commit 3368f2d2d3
12 changed files with 204 additions and 6 deletions

View file

@ -24,6 +24,20 @@ class ErrorSchema(Schema):
code = fields.String(description="Error code") code = fields.String(description="Error code")
class AuthorizationSchema(Schema):
rid = fields.Integer(description="The repository id.")
email = fields.String(description="The user's email.")
class AuthorizationParameterSchema(Schema):
rid = fields.Integer(description="The repository id.")
email = fields.String(description="The user's email.")
class CreateAuthorizationSchema(Schema):
email = fields.String(description="The user's email")
class SuccesSchema(Schema): class SuccesSchema(Schema):
result = fields.String(description="Contains a string that informs if the procedure was successful.") result = fields.String(description="Contains a string that informs if the procedure was successful.")
data = fields.String(description="The content of the response.") data = fields.String(description="The content of the response.")

View file

@ -33,6 +33,8 @@ spec.components.schema("AlertParameter", schema=AlertParameterSchema)
spec.components.schema("Alert", schema=Alert) spec.components.schema("Alert", schema=Alert)
spec.components.schema("Tweet", schema=TweetSchema) spec.components.schema("Tweet", schema=TweetSchema)
spec.components.schema("CreateAlert", schema=CreateAlert) spec.components.schema("CreateAlert", schema=CreateAlert)
spec.components.schema("CreateAuthorization", schema=CreateAuthorizationSchema)
spec.components.schema("Authorization", schema=AuthorizationSchema)
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

View file

@ -66,11 +66,21 @@ app.add_url_rule(
view_func=routes.page_repository_alerts, view_func=routes.page_repository_alerts,
methods=["GET", "POST"] methods=["GET", "POST"]
) )
app.add_url_rule(
"/api/v1/repositories/<int:rid>/authorizations/",
view_func=routes.page_repository_authorizations,
methods=["GET", "POST"],
)
app.add_url_rule( app.add_url_rule(
"/api/v1/repositories/<int:rid>/tweets/", "/api/v1/repositories/<int:rid>/tweets/",
view_func=routes.page_repository_tweets, view_func=routes.page_repository_tweets,
methods=["GET"] methods=["GET"]
) )
app.add_url_rule(
"/api/v1/authorization/<int:rid>/<string:email>",
view_func=routes.page_authorization,
methods=["DELETE"]
)
app.add_url_rule( app.add_url_rule(
"/api/v1/alert/<int:aid>", "/api/v1/alert/<int:aid>",
view_func=routes.page_alert, view_func=routes.page_alert,

View file

@ -10,4 +10,10 @@ class Authorization(ext.Model):
email = ext.Column(ext.String, ext.ForeignKey("user.email", ondelete="CASCADE"), primary_key=True) email = ext.Column(ext.String, ext.ForeignKey("user.email", ondelete="CASCADE"), primary_key=True)
# Relationships # Relationships
repository = ext.relationship("Repository", back_populates="authorizations") repository = ext.relationship("Repository", back_populates="authorizations")
user = ext.relationship("User", back_populates="authorizations") user = ext.relationship("User", back_populates="authorizations")
def to_json(self):
return {
"rid": self.rid,
"email": self.email,
}

View file

@ -25,3 +25,5 @@ ALERT_NO_LIMIT = "errorAlertNoLimit" # Missing limit entry
ALERT_NO_WINDOW = "errorAlertNoWindow" # Missing window entry ALERT_NO_WINDOW = "errorAlertNoWindow" # Missing window entry
ALERT_NO_EVALUATION = "errorAlertNoEvaluation" # Missing evalmode entry ALERT_NO_EVALUATION = "errorAlertNoEvaluation" # Missing evalmode entry
ALERT_DELETION_FAILURE = "errorAlertDeletionFailure" # Error while deleting alerts ALERT_DELETION_FAILURE = "errorAlertDeletionFailure" # Error while deleting alerts
# Authorization
AUTHORIZATION_NOT_FOUND = "errorAuthorizationNotFound" # Authorization not found

View file

@ -8,7 +8,7 @@ import functools
from flask_jwt_extended import get_jwt_identity from flask_jwt_extended import get_jwt_identity
from flask import jsonify from flask import jsonify
from re import sub from re import sub
from .errors import GENERIC_UFO from .errors import GENERIC_UFO, REPOSITORY_NOT_FOUND, USER_NOT_AUTHORIZED
__all__ = ["authenticate", "identity", "gen_password", "find_user", "admin_or_403", __all__ = ["authenticate", "identity", "gen_password", "find_user", "admin_or_403",
"repository_auth", "json_request_authorizer", "json_error", "repository_auth", "json_request_authorizer", "json_error",
@ -76,10 +76,10 @@ def repository_auth(f):
return json_error("Missing one or more parameters."), 400 return json_error("Missing one or more parameters."), 400
repository = Repository.query.filter_by(id=repository_id).first() repository = Repository.query.filter_by(id=repository_id).first()
if not repository: if not repository:
return json_error("Cant't find the repository."), 404 return json_error("Cant't find the repository.", REPOSITORY_NOT_FOUND), 404
if repository.owner_id != user.email and user.email not in [a.email for a in if repository.owner_id != user.email and user.email not in [a.email for a in
repository.authorizations] and not user.isAdmin: repository.authorizations] and not user.isAdmin:
return json_error("Stop right there, criminal scum! Nobody accesses protected data under MY watch!"), 403 return json_error("Stop right there, criminal scum! Nobody accesses protected data under MY watch!", USER_NOT_AUTHORIZED), 403
return f(*args, **kwargs) return f(*args, **kwargs)
return func return func

View file

@ -5,6 +5,8 @@ This module imports all the routes that return something to the frontend.
from .doa import page_doa from .doa import page_doa
from .users import * from .users import *
from .repository import * from .repository import *
__all__ = ["page_alert", "page_repository_alerts", "page_repository", "page_doa", __all__ = ["page_alert", "page_repository_alerts", "page_repository", "page_doa",
"page_condition", "page_repository_conditions", "page_repositories", "page_condition", "page_repository_conditions", "page_repositories",
"page_login", "page_user", "page_users"] "page_login", "page_user", "page_users", "page_authorization", "page_repository_authorizations",
"page_repository_tweets"]

View file

@ -4,6 +4,8 @@ from .repositories import page_repositories
from .conditions import * from .conditions import *
from .alerts import * from .alerts import *
from .tweets import * from .tweets import *
from .authorizations import *
__all__ = ["page_condition", "page_repository_conditions", "page_repositories", __all__ = ["page_condition", "page_repository_conditions", "page_repositories",
"page_alert", "page_repository", "page_repository_alerts", "page_repository_tweets"] "page_alert", "page_repository", "page_repository_alerts", "page_repository_tweets",
"page_authorization", "page_repository_authorizations"]

View file

@ -0,0 +1,4 @@
from .authorization import page_authorization
from .repository_authorizations import page_repository_authorizations
__all__ = ["page_authorization", "page_repository_authorizations"]

View file

@ -0,0 +1,54 @@
from flask import render_template, abort, jsonify, request
from nest_backend.database import *
from flask_jwt_extended import jwt_required, get_jwt_identity
from nest_backend.gestione import *
from flask_cors import cross_origin
from nest_backend.errors import *
@cross_origin()
@jwt_required()
def page_authorization(rid, email):
"""
---
delete:
summary: Delete an authorization.
parameters:
- in: path
schema: AuthorizationParameterSchema
security:
- jwt: []
responses:
'204':
description: The deletion was successful.
'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: Something could not be found.
content:
application/json:
schema: Error
tags:
- repository-related
"""
repository = Repository.query.filter_by(id=rid).first()
user = find_user(get_jwt_identity())
if not repository:
return json_error("Could not find the repository.", REPOSITORY_NOT_FOUND), 404
if user != repository.owner:
return json_error("You are not authorized.", USER_NOT_AUTHORIZED), 403
authorization = Authorization.query.filter_by(rid=rid, email=email).first()
if not authorization:
return json_error("Could not find the authorization", AUTHORIZATION_NOT_FOUND), 404
if request.method == "DELETE":
ext.session.delete(authorization)
ext.session.commit()
return json_success("Deleted."), 204

View file

@ -0,0 +1,101 @@
from flask import request
from flask_jwt_extended import jwt_required
from nest_backend.gestione import repository_auth, json_error, json_success, find_user, get_jwt_identity
from nest_backend.database import ext, User, Authorization, Repository
from flask_cors import cross_origin
from nest_backend.gestione import hashtag_validator
from nest_backend.errors import *
@cross_origin()
@jwt_required()
@repository_auth
def page_repository_authorizations(rid):
"""
---
get:
summary: Get a list of a repository authorizations.
parameters:
- in: path
schema: IntegerParameterSchema
security:
- jwt: []
responses:
'200':
description: List of Authorization 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 a condition and attaches it to the repository.
security:
- jwt: []
parameters:
- in: path
schema: IntegerParameterSchema
requestBody:
required: true
content:
application/json:
schema: CreateAuthorization
responses:
'201':
description: The authorization has been created successfully.
content:
application/json:
schema: Authorization
'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
"""
repository = Repository.query.filter_by(id=rid).first()
if not repository:
return json_error("Could not find repository", REPOSITORY_NOT_FOUND), 404
user = find_user(get_jwt_identity())
if user.email != repository.owner_id:
return json_error("You are not authorized.", REPOSITORY_NOT_OWNER), 403
if request.method == "GET":
try:
return json_success([a.to_json() for a in repository.authorizations])
except Exception as e:
return json_error("Unknown error:" + str(e), GENERIC_UFO), 400
if request.method == "POST":
if request.json is None:
return json_error("Missing json content.", GENERIC_NO_JSON), 400
if not request.json.get("email"):
return json_error("Missing user email.", GENERIC_MISSING_FIELDS), 400
target = User.query.filter_by(email=request.json.get('email')).first()
if not target:
return json_error("User could not be located", USER_NOT_FOUND), 400
if target == user:
return json_error("Owner cannot be a spectator", GENERIC_ALREADY_EXISTS), 406
authorization = Authorization(email=request.json.get('email'), rid=repository.id)
ext.session.add(authorization)
ext.session.commit()
return json_success(authorization.to_json()), 201

View file

@ -198,6 +198,7 @@ def page_repository(rid):
repository.evaluation_mode = evaluation_mode repository.evaluation_mode = evaluation_mode
repository.name = request.json['name'] repository.name = request.json['name']
repository.is_active = request.json['is_active'] repository.is_active = request.json['is_active']
ext.session.commit()
ids = [c['id'] for c in request.json['conditions'] if c['id']] ids = [c['id'] for c in request.json['conditions'] if c['id']]
# Delete no longer needed conditions. # Delete no longer needed conditions.
for c in repository.conditions: for c in repository.conditions: