mirror of
https://github.com/pds-nest/nest.git
synced 2024-11-25 14:34:19 +00:00
User removal, repository creation, CORS
This commit is contained in:
parent
bfdf01555e
commit
c7ec25b811
12 changed files with 96 additions and 11 deletions
|
@ -8,6 +8,7 @@ from .routes import *
|
||||||
from .database import Base, tables
|
from .database import Base, tables
|
||||||
import psycopg2
|
import psycopg2
|
||||||
from .gestione import *
|
from .gestione import *
|
||||||
|
from flask_cors import CORS
|
||||||
from flask_jwt_extended import *
|
from flask_jwt_extended import *
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -25,6 +26,8 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password@localhos
|
||||||
Base.app = app
|
Base.app = app
|
||||||
Base.init_app(app)
|
Base.init_app(app)
|
||||||
jwt = JWTManager(app)
|
jwt = JWTManager(app)
|
||||||
|
cors = CORS(app)
|
||||||
|
app.config['CORS_HEADERS'] = 'Content-Type'
|
||||||
# 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"])
|
||||||
|
|
|
@ -10,7 +10,7 @@ class Repository(Base.Model):
|
||||||
id = Base.Column(Base.Integer, primary_key=True)
|
id = Base.Column(Base.Integer, primary_key=True)
|
||||||
name = Base.Column(Base.String, nullable=False)
|
name = Base.Column(Base.String, nullable=False)
|
||||||
start = Base.Column(Base.DateTime, nullable=False)
|
start = Base.Column(Base.DateTime, nullable=False)
|
||||||
end = Base.Column(Base.DateTime, nullable=False)
|
end = Base.Column(Base.DateTime, nullable=True)
|
||||||
# Foreign Keys
|
# Foreign Keys
|
||||||
owner_id = Base.Column(Base.String, Base.ForeignKey("user.email"), nullable=False)
|
owner_id = Base.Column(Base.String, Base.ForeignKey("user.email"), nullable=False)
|
||||||
# Relationships
|
# Relationships
|
||||||
|
@ -19,3 +19,6 @@ class Repository(Base.Model):
|
||||||
tweets = Base.relationship("Composed", back_populates="repository")
|
tweets = Base.relationship("Composed", back_populates="repository")
|
||||||
alerts = Base.relationship("Alert", back_populates="repository")
|
alerts = Base.relationship("Alert", back_populates="repository")
|
||||||
uses = Base.relationship("Uses", back_populates="repository")
|
uses = Base.relationship("Uses", back_populates="repository")
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return {"id": self.id, "name": self.name, "start": self.start.isoformat(), "owner": self.owner.to_json()}
|
||||||
|
|
|
@ -14,3 +14,6 @@ class User(Base.Model):
|
||||||
# Relationships
|
# Relationships
|
||||||
owner_of = Base.relationship("Repository", back_populates="owner")
|
owner_of = Base.relationship("Repository", back_populates="owner")
|
||||||
authorizations = Base.relationship("Authorization", back_populates="user")
|
authorizations = Base.relationship("Authorization", back_populates="user")
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return {'email': self.email, 'username': self.username, 'isAdmin': self.isAdmin}
|
||||||
|
|
0
code/backend/nest_backend/routes/repository/__init__.py
Normal file
0
code/backend/nest_backend/routes/repository/__init__.py
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
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.
|
||||||
|
:form name: The name of the repository.
|
||||||
|
:returns: If the user is logged in and
|
||||||
|
"""
|
||||||
|
user = find_user(get_jwt_identity())
|
||||||
|
name = request.json.get("name")
|
||||||
|
if not name:
|
||||||
|
return jsonify({"result": "failure", "msg": "Missing one or more parameters"}), 40
|
||||||
|
repository = Repository(name=name, start=datetime.datetime.now(), owner_id=user.email)
|
||||||
|
Base.session.add(repository)
|
||||||
|
Base.session.commit()
|
||||||
|
return jsonify({"result":"success", "content":repository.to_json()}), 200
|
|
@ -1,2 +1,3 @@
|
||||||
from .user_create import page_user_create
|
from .user_create import page_user_create
|
||||||
from .login import page_login
|
from .login import page_login
|
||||||
|
from .user_delete import page_user_delete
|
|
@ -2,14 +2,16 @@ from flask import render_template, abort, jsonify, request
|
||||||
from ...database import *
|
from ...database import *
|
||||||
from ...gestione import *
|
from ...gestione import *
|
||||||
from flask_jwt_extended import create_access_token
|
from flask_jwt_extended import create_access_token
|
||||||
|
from flask_cors import cross_origin
|
||||||
|
|
||||||
|
|
||||||
|
@cross_origin()
|
||||||
def page_login():
|
def page_login():
|
||||||
"""
|
"""
|
||||||
The API call that allows to log-in. It requires:
|
The API call that allows to log-in. It requires:
|
||||||
:form email: The user's email
|
:form email: The user's email
|
||||||
:form password: The users's password
|
:form password: The users's password
|
||||||
:return: Json-formatted data. If the login is successful, it will contain the access_token.
|
:return: 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>.
|
The access_token must be included in the Authorization header, using the format Bearer <token>.
|
||||||
"""
|
"""
|
||||||
|
@ -17,5 +19,6 @@ def page_login():
|
||||||
password = request.json.get("password", None)
|
password = request.json.get("password", None)
|
||||||
if authenticate(email, password):
|
if authenticate(email, password):
|
||||||
access_token = create_access_token(identity=email)
|
access_token = create_access_token(identity=email)
|
||||||
return jsonify({"result": "success", "access_token": access_token}), 201
|
user = find_user(email)
|
||||||
|
return jsonify({"result": "success", "access_token": access_token, 'user': user.to_json()}), 201
|
||||||
return jsonify({"result": "failure", "msg": "Bad username or password."}), 401
|
return jsonify({"result": "failure", "msg": "Bad username or password."}), 401
|
||||||
|
|
|
@ -2,7 +2,10 @@ from flask import render_template, abort, jsonify, request
|
||||||
from ...database import *
|
from ...database import *
|
||||||
from flask_jwt_extended import jwt_required
|
from flask_jwt_extended import jwt_required
|
||||||
from ...gestione import *
|
from ...gestione import *
|
||||||
|
from flask_cors import cross_origin
|
||||||
|
|
||||||
|
|
||||||
|
@cross_origin()
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def page_user_create():
|
def page_user_create():
|
||||||
"""
|
"""
|
||||||
|
@ -11,12 +14,13 @@ def page_user_create():
|
||||||
:form password: The users's password
|
:form password: The users's password
|
||||||
:form username: The users's username
|
:form username: The users's username
|
||||||
:return: Json-formatted data. If something goes wrong, it returns a
|
: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()}.
|
{'result':'failure', 'content':'something blew up'}, else it returns {'result':'success', 'content':newUser.to_json().
|
||||||
"""
|
"""
|
||||||
user = find_user(get_jwt_identity())
|
user = find_user(get_jwt_identity())
|
||||||
if not user.isAdmin:
|
if not user.isAdmin:
|
||||||
abort(403)
|
abort(403)
|
||||||
nUser = User(email=request.json.get("email"), password=gen_password(request.json.get("password")), username=request.json.get("username"))
|
nUser = User(email=request.json.get("email"), password=gen_password(request.json.get("password")),
|
||||||
|
username=request.json.get("username"))
|
||||||
Base.session.add(nUser)
|
Base.session.add(nUser)
|
||||||
Base.session.commit()
|
Base.session.commit()
|
||||||
return jsonify({"result":"success", "content":"something"})
|
return jsonify({"result": "success", "content": user.to_json()})
|
||||||
|
|
27
code/backend/nest_backend/routes/users/user_delete.py
Normal file
27
code/backend/nest_backend/routes/users/user_delete.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
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.
|
||||||
|
:form 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 jsonify({"result": "failure", "msg": "User is not admin."}), 403
|
||||||
|
target = find_user(request.json.get('email'))
|
||||||
|
if not target:
|
||||||
|
return jsonify({"result": "failure", "msg": "User not found."}), 404
|
||||||
|
if user == target:
|
||||||
|
return jsonify({"result": "failure", "msg": "The user cant delete himself. Its a sin."}), 406
|
||||||
|
Base.session.remove(target)
|
||||||
|
Base.session.commit()
|
||||||
|
return jsonify({"result": "success", "content":"The user has been deleted."})
|
18
code/backend/poetry.lock
generated
18
code/backend/poetry.lock
generated
|
@ -52,6 +52,18 @@ dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxco
|
||||||
docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
|
docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
|
||||||
dotenv = ["python-dotenv"]
|
dotenv = ["python-dotenv"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flask-cors"
|
||||||
|
version = "3.0.10"
|
||||||
|
description = "A Flask extension adding a decorator for CORS support"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
Flask = ">=0.9"
|
||||||
|
Six = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flask-jwt-extended"
|
name = "flask-jwt-extended"
|
||||||
version = "4.1.0"
|
version = "4.1.0"
|
||||||
|
@ -205,7 +217,7 @@ watchdog = ["watchdog"]
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.8.5"
|
python-versions = "^3.8.5"
|
||||||
content-hash = "6bc937df83a15e8774d6ab63f19f5b6b3780730d935678c81259f53ee7cd8ebc"
|
content-hash = "8269162351f5e7827601a662d25048bbc0f58503fa4d251334c45b29feac5e5c"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
bcrypt = [
|
bcrypt = [
|
||||||
|
@ -264,6 +276,10 @@ flask = [
|
||||||
{file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"},
|
{file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"},
|
||||||
{file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
|
{file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
|
||||||
]
|
]
|
||||||
|
flask-cors = [
|
||||||
|
{file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"},
|
||||||
|
{file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"},
|
||||||
|
]
|
||||||
flask-jwt-extended = [
|
flask-jwt-extended = [
|
||||||
{file = "Flask-JWT-Extended-4.1.0.tar.gz", hash = "sha256:77ca23f23e80480ea42b9c1d9b0fca214e08db7192583e782c2421416b4a4655"},
|
{file = "Flask-JWT-Extended-4.1.0.tar.gz", hash = "sha256:77ca23f23e80480ea42b9c1d9b0fca214e08db7192583e782c2421416b4a4655"},
|
||||||
{file = "Flask_JWT_Extended-4.1.0-py2.py3-none-any.whl", hash = "sha256:f952f4ebd449182431c6755acfb7cbb52b8034df7a9f9ef95eb51ccfc1e235b0"},
|
{file = "Flask_JWT_Extended-4.1.0-py2.py3-none-any.whl", hash = "sha256:f952f4ebd449182431c6755acfb7cbb52b8034df7a9f9ef95eb51ccfc1e235b0"},
|
||||||
|
|
|
@ -11,6 +11,7 @@ Flask = "^1.1.2"
|
||||||
Flask-SQLAlchemy = "^2.5.1"
|
Flask-SQLAlchemy = "^2.5.1"
|
||||||
bcrypt = "^3.2.0"
|
bcrypt = "^3.2.0"
|
||||||
Flask-JWT-Extended = "^4.1.0"
|
Flask-JWT-Extended = "^4.1.0"
|
||||||
|
Flask-Cors = "^3.0.10"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue