1
Fork 0
mirror of https://github.com/pds-nest/nest.git synced 2024-11-22 04:54:18 +00:00

Breaking changes!

All the urls have been changed, and several have been regrouped. Please check the docstrings.
This commit is contained in:
Lorenzo Balugani 2021-04-29 21:59:05 +02:00
parent 7b320f01c3
commit 925ff9a9fa
16 changed files with 207 additions and 193 deletions

View file

@ -20,13 +20,12 @@ reverse_proxy_app = werkzeug.middleware.proxy_fix.ProxyFix(app=app, x_for=1, x_p
# Routes setup
app.add_url_rule("/doa", view_func=page_doa, methods=["GET", "POST"])
app.add_url_rule("/api/login", view_func=page_login, methods=["POST"])
app.add_url_rule("/api/user/create", view_func=page_user_create, methods=["POST"])
app.add_url_rule("/api/user/remove", view_func=page_user_delete, methods=["POST"])
app.add_url_rule("/api/repository/list", view_func=page_repository_list, methods=["GET"])
app.add_url_rule("/api/repository/create", view_func=page_repository_create, methods=["POST"])
app.add_url_rule("/api/repository/edit", view_func=page_repository_edit, methods=["PUT"])
app.add_url_rule("/api/repository/add_condition", view_func=page_repository_add_condition, methods=["POST"])
app.add_url_rule("/api/v1/login", view_func=page_login, methods=["POST"])
app.add_url_rule("/api/v1/users", view_func=page_users, methods=["GET", "POST"])
app.add_url_rule("/api/v1/users/<string:email>", view_func=page_user, methods=["GET", "PATCH", "DELETE"])
app.add_url_rule("/api/v1/repositories/", view_func=page_repositories, methods=["GET", "POST"])
app.add_url_rule("/api/v1/repositories/<int:rid>", view_func=page_repository, methods=["GET", "PATCH", "DELETE"])
app.add_url_rule("/api/v1/repositories/<int:rid>/conditions", view_func=page_repository_conditions, methods=["GET", "POST"])
app.register_error_handler(Exception, error_handler)

View file

@ -74,7 +74,7 @@ def repository_auth(f):
repository = Repository.query.filter_by(id=repository_id)
if not repository:
return json_error("Cant't find the repository."), 404
if repository.owner_id != user.email:
if repository.owner_id != user.email and user.email not in [a.email for a in repository.authorizations]:
return json_error("Stop right there, criminal scum! Nobody accesses protected data under MY watch!"), 403
return f(*args, **kwargs)
return func

View file

@ -1,4 +1,3 @@
from .repository_add_condition import page_repository_add_condition
from .repository_edit import page_repository_edit
from .repository_create import page_repository_create
from .repository_list import page_repository_list
from .repository_conditions import page_repository_conditions
from .repository import page_repository
from .repositories import page_repositories

View file

@ -0,0 +1,38 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
import datetime
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_repositories():
"""
Repositories:
+ GET: [onlyActive], [onlyDead] -> Gets the list of all the user-related repos.
+ POST: name -> Creates a new repository and returns it
"""
user = find_user(get_jwt_identity())
if request.method == "GET":
owner = Repository.query.filter_by(owner_id=user.email)
spectator = Authorization.query.filter_by(email=user.email).join(Repository)
if request.json.get("onlyActive"):
owner = owner.filter_by(isActive=True)
spectator = spectator.filter(Repository.isActive == True)
elif request.json.get("onlyDead"):
owner = owner.filter_by(isActive=False)
spectator = spectator.filter(Repository.isActive == False)
owner = owner.all()
spectator = spectator.all()
return json_success({"owner": [r.to_json() for r in owner],
"spectator": [r.repository.to_json() for r in spectator]})
elif request.method == "POST":
name = request.json.get("name")
if not name:
return json_error("Missing one or more parameters"), 400
repository = Repository(name=name, owner_id=user.email)
Base.session.add(repository)
Base.session.commit()
return json_success(repository.to_json()), 200

View file

@ -0,0 +1,40 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
import datetime
@cross_origin()
@jwt_required()
@repository_auth
def page_repository(rid):
"""
Repository <rid>:
+ GET: Gets info about the specified repository.
+ PATCH: [name], [close], [open] -> Updates certain aspects of the repository.
+ DELETE: deletes the specified repository.
"""
user = find_user(get_jwt_identity())
repository = Repository.query.filter_by(id=request.json['id']).first()
if request.method == "GET":
return json_success(repository.to_json()), 200
elif request.method == "PATCH":
if repository.owner_id != user.email:
return json_error("You are not the owner of this repository."), 403
if 'name' in request.json:
repository.name = request.json['name']
if 'close' in request.json and not repository.end and repository.isActive:
repository.end = datetime.datetime.now()
repository.isActive = False
if 'open' in request.json and not repository.isActive and not repository.end:
repository.isActive = True
Base.session.commit()
return json_success(repository.to_json()), 200
elif request.method == "DELETE":
if repository.owner_id != user.email:
return json_error("You are not the owner of this repository."), 403
Base.session.delete(repository)
Base.session.commit()
return json_success("Success"), 200

View file

@ -1,34 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
@repository_auth
def page_repository_add_condition():
"""
API call that allows to add conditions to a repository.
:parameter id: Repository ID
:parameter type: The type of the condition. It can either be an 'hashtag', a 'location' or 'time'
:parameter content: The content of the condition (#PdS2021, Roma, 18:00)
:returns: a JSON string that tells whether or not the procedure was a success.
"""
type = request.json.get("type")
if not type or type not in dir(ConditionType):
return json_error("Could not understand the type of the condition."), 400
content = request.json.get("content")
if not content:
return json_error("Could not find the content"), 400
condition = Condition.query.filter(Condition.content.ilike(str(content))).filter_by(type=ConditionType.__getattr__(str(type)).value).first()
if not condition:
condition = Condition(content=content, type=ConditionType.__getattr__(str(type)).value)
Base.session.add(condition)
repository = Repository.query.filter_by(request.json.get("id"))
if Uses.query.filter_by(cid=condition.id, rid=repository.id):
return json_error("This condition is already connected to the repository."), 406
Base.session.add(Uses(cid=condition.id, rid=repository.id))
Base.session.commit()
return json_success("Operation done with success."), 200

View file

@ -0,0 +1,39 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
@repository_auth
def page_repository_conditions(rid):
"""
Repository/Condition:
+ GET: Returns the conditions of the specified repo.
+ POST: type, content -> Adds a condition and returns it.
"""
repository = Repository.query.filter_by(rid=rid).first()
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([u.condition.to_json() for u in repository.uses])
if request.method == "POST":
type = request.json.get("type")
if not type or type not in dir(ConditionType):
return json_error("Could not understand the type of the condition."), 400
content = request.json.get("content")
if not content:
return json_error("Could not find the content"), 400
condition = Condition.query.filter(Condition.content.ilike(str(content))).filter_by(type=ConditionType.__getattr__(str(type)).value).first()
if not condition:
condition = Condition(content=content, type=ConditionType.__getattr__(str(type)).value)
Base.session.add(condition)
repository = Repository.query.filter_by(request.json.get("id"))
if Uses.query.filter_by(cid=condition.id, rid=repository.id):
return json_error("This condition is already connected to the repository."), 406
Base.session.add(Uses(cid=condition.id, rid=repository.id))
Base.session.commit()
return json_success(condition.to_json()), 200

View file

@ -1,25 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
import datetime
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_repository_create():
"""
API call that allows an user to create a new repository.
:parameter name: The name of the repository.
:returns: If the user is logged in and has provided the repository name, a JSON string is returned containing
the return status of the operation and the repository in json format.
"""
user = find_user(get_jwt_identity())
name = request.json.get("name")
if not name:
return json_error("Missing one or more parameters"), 400
repository = Repository(name=name, owner_id=user.email)
Base.session.add(repository)
Base.session.commit()
return json_success(repository.to_json()), 200

View file

@ -1,28 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
import datetime
@cross_origin()
@jwt_required()
@repository_auth
def page_repository_edit():
"""
This API call allows to edit a repository.
:parameter name: If present, it changes the repository name.
:parameter close: If present, it closes the repository.
:returns: A JSON formatted string that either contains an error or the updated representation of the repository.
"""
repository = Repository.query.filter_by(id=request.json['id'])
if 'name' in request.json:
repository.name = request.json['name']
if 'close' in request.json and not repository.end and repository.isActive:
repository.end = datetime.datetime.now()
repository.isActive = False
if 'open' in request.json and not repository.isActive and not repository.end:
repository.isActive = True
Base.session.commit()
return json_success(repository.to_json())

View file

@ -1,32 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_repository_list():
"""
API call that returns the list of repositories.
:parameter onlyActive: if present, only active repos are provided
:parameter onlyDead: if present, only dead repos are provided
:returns: a JSON-formatted string that contains under the "content" field the list of repositories that belong to
the user ("owner") and a list of repositories that he can spectate ("spectator").
"""
user = find_user(get_jwt_identity())
owner = Repository.query.filter_by(owner_id=user.email)
spectator = Authorization.query.filter_by(email=user.email).join(Repository)
if request.args.get("onlyActive"):
owner = owner.filter_by(isActive=True)
spectator = spectator.filter(Repository.isActive == True)
elif request.args.get("onlyDead"):
owner = owner.filter_by(isActive=False)
spectator = spectator.filter(Repository.isActive == False)
owner = owner.all()
spectator = spectator.all()
return json_success({"owner": [r.to_json() for r in owner],
"spectator": [r.repository.to_json() for r in spectator]})

View file

@ -1,3 +1,3 @@
from .user_create import page_user_create
from .users import page_users
from .login import page_login
from .user_delete import page_user_delete
from .user import page_user

View file

@ -9,12 +9,8 @@ from datetime import timedelta, datetime
@cross_origin()
def page_login():
"""
The API call that allows to log-in. It requires:
:parameter email: The user's email
:parameter password: The users's password
:returns: Json-formatted data. If the login is successful, it will contain the access_token and the users data.
The access_token must be included in the Authorization header, using the format Bearer <token>.
Login:
+ POST: email, password -> Sends a response containing the JWT token
"""
email = request.json.get("email", None)
password = request.json.get("password", None)

View file

@ -0,0 +1,47 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_user(email):
"""
User <email>:
+ GET: gets info about the specified user.
+ PATCH: password, username -> Updates data about the user, returns the updated user.
+ DELETE: deletes the specified user.
"""
user = find_user(get_jwt_identity())
if request.method == "GET":
if not email == user.email and not user.isAdmin:
return json_error("Thou art not authorized."), 403
target = find_user(email).to_json()
if not target:
json_error("Could not locate the user."), 404
return json_success(target.to_json())
elif request.method == "DELETE":
if not user.isAdmin:
return json_error("User is not admin."), 403
deluser = request.json.get('email')
target = find_user(deluser)
if not target:
return json_error("User not found."), 404
if user == target:
return json_error("The user cant delete himself. Its a sin."), 406
Base.session.delete(target)
Base.session.commit()
return json_success("The user has been deleted.")
elif request.method == "PATCH":
if not email == user.email and not user.isAdmin:
return json_error("Thou art not authorized."), 403
target = find_user(email)
if not target:
json_error("Could not locate the user."), 404
if request.json.get("username"):
target.username = request.json.get("username")
if request.json.get("password"):
target.password = gen_password(request.json.get("password"))
Base.session.commit()

View file

@ -1,26 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_user_create():
"""
The API call that allows to create new users. It requires:
:parameter email: The user's email
:parameter password: The users's password
:parameter username: The users's username
:return: Json-formatted data. If something goes wrong, it returns a
{'result':'failure', 'content':'something blew up'}, else it returns {'result':'success', 'content':newUser.to_json().
"""
user = find_user(get_jwt_identity())
if not user.isAdmin:
return json_error("User is not admin. Thou are not authorized."), 403
new_user = User(email=request.json.get("email"), password=gen_password(request.json.get("password")),
username=request.json.get("username"))
Base.session.add(new_user)
Base.session.commit()
return json_success(new_user.to_json())

View file

@ -1,28 +0,0 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_user_delete():
"""
API call that allows an user to be deleted from NEST.
:parameter email: The email of the user that needs to be removed.
:return: JSON-formatted data. If the user has the privilege, the target user exists and differs from the current
user, the target gets deleted and a json containing the field "result":"success" is returned.
"""
user = find_user(get_jwt_identity())
if not user.isAdmin:
return json_error("User is not admin."), 403
deluser=request.json.get('email')
target = find_user(deluser)
if not target:
return json_error("User not found."), 404
if user == target:
return json_error("The user cant delete himself. Its a sin."), 406
Base.session.delete(target)
Base.session.commit()
return json_success("The user has been deleted.")

View file

@ -0,0 +1,29 @@
from flask import render_template, abort, jsonify, request
from ...database import *
from flask_jwt_extended import jwt_required
from ...gestione import *
from flask_cors import cross_origin
@cross_origin()
@jwt_required()
def page_users():
"""
Users:
+ GET: gets info about all the users of the platform. Requires the user to be admin.
+ POST: email, password, username -> Creates a new user and returns it. Requires the user to be admin.
"""
user = find_user(get_jwt_identity())
if request.method == "GET":
if not user.isAdmin:
return json_error("User is not admin. Thou art not authorized"), 403
users = User.query.all()
return json_success([user.to_json() for user in users])
if request.method == "POST":
if not user.isAdmin:
return json_error("User is not admin. Thou art not authorized."), 403
new_user = User(email=request.json.get("email"), password=gen_password(request.json.get("password")),
username=request.json.get("username"))
Base.session.add(new_user)
Base.session.commit()
return json_success(new_user.to_json())