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:
parent
8d8e396ebf
commit
3368f2d2d3
12 changed files with 204 additions and 6 deletions
|
@ -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.")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -11,3 +11,9 @@ class Authorization(ext.Model):
|
||||||
# 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,
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
from .authorization import page_authorization
|
||||||
|
from .repository_authorizations import page_repository_authorizations
|
||||||
|
|
||||||
|
__all__ = ["page_authorization", "page_repository_authorizations"]
|
|
@ -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
|
|
@ -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
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue