mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-26 06: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:
parent
7b320f01c3
commit
925ff9a9fa
16 changed files with 207 additions and 193 deletions
|
@ -20,13 +20,12 @@ reverse_proxy_app = werkzeug.middleware.proxy_fix.ProxyFix(app=app, x_for=1, x_p
|
||||||
# Routes setup
|
# Routes setup
|
||||||
|
|
||||||
app.add_url_rule("/doa", view_func=page_doa, methods=["GET", "POST"])
|
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/v1/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/v1/users", view_func=page_users, methods=["GET", "POST"])
|
||||||
app.add_url_rule("/api/user/remove", view_func=page_user_delete, methods=["POST"])
|
app.add_url_rule("/api/v1/users/<string:email>", view_func=page_user, methods=["GET", "PATCH", "DELETE"])
|
||||||
app.add_url_rule("/api/repository/list", view_func=page_repository_list, methods=["GET"])
|
app.add_url_rule("/api/v1/repositories/", view_func=page_repositories, methods=["GET", "POST"])
|
||||||
app.add_url_rule("/api/repository/create", view_func=page_repository_create, methods=["POST"])
|
app.add_url_rule("/api/v1/repositories/<int:rid>", view_func=page_repository, methods=["GET", "PATCH", "DELETE"])
|
||||||
app.add_url_rule("/api/repository/edit", view_func=page_repository_edit, methods=["PUT"])
|
app.add_url_rule("/api/v1/repositories/<int:rid>/conditions", view_func=page_repository_conditions, methods=["GET", "POST"])
|
||||||
app.add_url_rule("/api/repository/add_condition", view_func=page_repository_add_condition, methods=["POST"])
|
|
||||||
|
|
||||||
app.register_error_handler(Exception, error_handler)
|
app.register_error_handler(Exception, error_handler)
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ def repository_auth(f):
|
||||||
repository = Repository.query.filter_by(id=repository_id)
|
repository = Repository.query.filter_by(id=repository_id)
|
||||||
if not repository:
|
if not repository:
|
||||||
return json_error("Cant't find the repository."), 404
|
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 json_error("Stop right there, criminal scum! Nobody accesses protected data under MY watch!"), 403
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
return func
|
return func
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from .repository_add_condition import page_repository_add_condition
|
from .repository_conditions import page_repository_conditions
|
||||||
from .repository_edit import page_repository_edit
|
from .repository import page_repository
|
||||||
from .repository_create import page_repository_create
|
from .repositories import page_repositories
|
||||||
from .repository_list import page_repository_list
|
|
38
code/backend/nest_backend/routes/repository/repositories.py
Normal file
38
code/backend/nest_backend/routes/repository/repositories.py
Normal 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
|
40
code/backend/nest_backend/routes/repository/repository.py
Normal file
40
code/backend/nest_backend/routes/repository/repository.py
Normal 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
|
|
@ -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
|
|
|
@ -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
|
|
@ -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
|
|
|
@ -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())
|
|
|
@ -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]})
|
|
|
@ -1,3 +1,3 @@
|
||||||
from .user_create import page_user_create
|
from .users import page_users
|
||||||
from .login import page_login
|
from .login import page_login
|
||||||
from .user_delete import page_user_delete
|
from .user import page_user
|
|
@ -9,12 +9,8 @@ from datetime import timedelta, datetime
|
||||||
@cross_origin()
|
@cross_origin()
|
||||||
def page_login():
|
def page_login():
|
||||||
"""
|
"""
|
||||||
The API call that allows to log-in. It requires:
|
Login:
|
||||||
:parameter email: The user's email
|
+ POST: email, password -> Sends a response containing the JWT token
|
||||||
: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>.
|
|
||||||
"""
|
"""
|
||||||
email = request.json.get("email", None)
|
email = request.json.get("email", None)
|
||||||
password = request.json.get("password", None)
|
password = request.json.get("password", None)
|
||||||
|
|
47
code/backend/nest_backend/routes/users/user.py
Normal file
47
code/backend/nest_backend/routes/users/user.py
Normal 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()
|
|
@ -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())
|
|
|
@ -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.")
|
|
29
code/backend/nest_backend/routes/users/users.py
Normal file
29
code/backend/nest_backend/routes/users/users.py
Normal 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())
|
Loading…
Reference in a new issue