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

💥 Create test framework

This commit is contained in:
Stefano Pigozzi 2021-05-07 19:46:14 +02:00
parent d7e55e556d
commit 008efa1c24
Signed by untrusted user who does not match committer: steffo
GPG key ID: 6965406171929D01
37 changed files with 324 additions and 192 deletions

View file

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Backend: Run tests" type="tests" factoryName="py.test">
<module name="backend" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="FLASK_CONFIG" value="../config.py" />
</envs>
<option name="SDK_HOME" value="$USER_HOME$/.cache/pypoetry/virtualenvs/nest-backend-3ypGnHKr-py3.9/bin/python" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/code/backend" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="_new_keywords" value="&quot;&quot;" />
<option name="_new_parameters" value="&quot;&quot;" />
<option name="_new_additionalArguments" value="&quot;&quot;" />
<option name="_new_target" value="&quot;nest_backend&quot;" />
<option name="_new_targetType" value="&quot;PYTHON&quot;" />
<method v="2" />
</configuration>
</component>

View file

@ -1,22 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Backend: [Make your own run config!]" type="PythonConfigurationType" factoryName="Python" editBeforeRun="true">
<module name="frontend" />
<configuration default="false" name="Backend: Start server" type="PythonConfigurationType" factoryName="Python">
<module name="backend" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
<env name="FLASK_CONFIG" value="../config.py" />
</envs>
<option name="SDK_HOME" value="C:\Users\giova\AppData\Local\pypoetry\Cache\virtualenvs\nest-backend-gZK59SuL-py3.9\Scripts\python.exe" />
<option name="WORKING_DIRECTORY" value="" />
<option name="IS_MODULE_SDK" value="false" />
<option name="SDK_HOME" value="$USER_HOME$/.cache/pypoetry/virtualenvs/nest-backend-3ypGnHKr-py3.9/bin/python" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/code/backend" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="" />
<option name="SCRIPT_NAME" value="nest_backend" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="MODULE_MODE" value="true" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />

View file

@ -1,3 +1,8 @@
# Flask config
config.py
configtest.py
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]

View file

@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/nest_backend" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/nest_backend/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/old_unittest_tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/docs/_build" />
</content>
<orderEntry type="jdk" jdkName="Poetry (backend)" jdkType="Python SDK" />

View file

@ -1,57 +1,23 @@
"""
This is the runner for the server.
"""
import werkzeug.middleware.proxy_fix
from .routes import *
import os
import sys
from .gestione import *
from flask_cors import CORS
from flask_jwt_extended import *
from .app import app
from .api_spec import spec
from .swagger import swagger_ui_blueprint, SWAGGER_URL
Base.init_app(app=app)
jwt = JWTManager(app)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
reverse_proxy_app = werkzeug.middleware.proxy_fix.ProxyFix(app=app, x_for=1, x_proto=0, x_host=1, x_port=0, x_prefix=0)
# Routes setup
app.add_url_rule("/doa", view_func=page_doa, methods=["GET", "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", "PUT"])
app.add_url_rule("/api/v1/repositories/<int:rid>/conditions", view_func=page_repository_conditions,
methods=["GET", "POST"])
app.add_url_rule("/api/v1/conditions/<int:cid>", view_func=page_condition, methods=["GET", "PATCH", "DELETE"])
app.register_error_handler(Exception, error_handler)
app.register_blueprint(swagger_ui_blueprint, url_prefix=SWAGGER_URL)
from .app import app, extension_sqlalchemy
with app.test_request_context():
print(" * Getting docs ready...")
for fn_name in app.view_functions:
if fn_name == 'static':
continue
view_fn = app.view_functions[fn_name]
spec.path(view=view_fn)
print(" * Docs have been compiled on http://127.0.0.1:5000/docs")
print(" * Swagger docs will be available at http://127.0.0.1:5000/docs")
@app.route("/docs/swagger.json")
def create_swagger_doc():
return jsonify(spec.to_dict())
if __name__ == "__main__":
with app.app_context():
Base.create_all(app=app)
with app.app_context():
print(" * Creating database tables...")
extension_sqlalchemy.create_all(app=app)
if not User.query.filter_by(isAdmin=True).all():
Base.session.add(
print(" * Creating default admin account...")
extension_sqlalchemy.session.add(
User(email="admin@admin.com", password=gen_password("password"), username="admin", isAdmin=True))
Base.session.commit()
app.run(debug=__debug__)
extension_sqlalchemy.session.commit()
print(" * Created! Username: admin | Password: password")
app.run(debug=__debug__)

View file

@ -1,16 +1,101 @@
from flask import Flask
import os
from flask_cors import CORS as FlaskCORS
from flask_jwt_extended import JWTManager as FlaskJWTManager
from flask_sqlalchemy import SQLAlchemy as FlaskSQLAlchemy
from werkzeug.middleware.proxy_fix import ProxyFix as MiddlewareProxyFix
from . import database, routes, gestione, swagger
from .api_spec import spec
# --- MAIN APP ---
app = Flask(__name__)
if os.getenv('COOKIE_SECRET'):
app.secret_key = os.getenv('COOKIE_SECRET')
else:
app.secret_key = "testing"
if os.getenv("JWT_SECRET_KEY"):
app.config["JWT_SECRET_KEY"] = os.getenv("JWT_SECRET_KEY")
else:
app.config["JWT_SECRET_KEY"] = "testing"
if os.getenv("DATABASE_URI"):
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URI')
else:
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:password@localhost:5432/PdSDev'
# --- APP CONFIG
app.config.from_envvar("FLASK_CONFIG")
# --- EXTENSIONS ---
app.config['CORS_HEADERS'] = 'Content-Type'
extension_cors = FlaskCORS(app=app)
extension_jwt = FlaskJWTManager(app=app)
extension_sqlalchemy = database.ext
extension_sqlalchemy.init_app(app=app)
# --- API ROUTES ---
app.add_url_rule(
"/doa",
view_func=routes.page_doa,
methods=["GET", "POST"],
)
app.add_url_rule(
"/api/v1/login",
view_func=routes.page_login,
methods=["POST"],
)
app.add_url_rule(
"/api/v1/users/",
view_func=routes.page_users,
methods=["GET", "POST"],
)
app.add_url_rule(
"/api/v1/users/<string:email>",
view_func=routes.page_user,
methods=["GET", "PATCH", "DELETE"],
)
app.add_url_rule(
"/api/v1/repositories/",
view_func=routes.page_repositories,
methods=["GET", "POST"],
)
app.add_url_rule(
"/api/v1/repositories/<int:rid>",
view_func=routes.page_repository,
methods=["GET", "PATCH", "DELETE", "PUT"],
)
app.add_url_rule(
"/api/v1/repositories/<int:rid>/conditions",
view_func=routes.page_repository_conditions,
methods=["GET", "POST"],
)
app.add_url_rule(
"/api/v1/conditions/<int:cid>",
view_func=routes.page_condition,
methods=["GET", "PATCH", "DELETE"],
)
# --- SWAGGER DOCS ---
app.register_blueprint(
swagger.swagger_ui_blueprint,
url_prefix=swagger.SWAGGER_URL
)
with app.test_request_context():
for fn_name in app.view_functions:
if fn_name == 'static':
continue
view_fn = app.view_functions[fn_name]
spec.path(view=view_fn)
app.add_url_rule(
"/docs/swagger.json",
view_func=lambda: gestione.jsonify(spec.to_dict()),
methods=["GET"],
)
# --- ERROR HANDLER ---
app.register_error_handler(
Exception,
gestione.error_handler
)
# --- REVERSE PROXY ---
if not __debug__:
app = MiddlewareProxyFix(app=app, x_for=1, x_proto=0, x_host=1, x_port=0, x_prefix=0)

View file

@ -3,4 +3,4 @@ This module imports all the tables and the declarative base
"""
from .tables import *
from .base import Base
from .base import ext

View file

@ -1,7 +1,3 @@
"""
This module creates the declarative base
"""
import flask_sqlalchemy
from sqlalchemy.orm import backref
Base = flask_sqlalchemy.SQLAlchemy()
ext = flask_sqlalchemy.SQLAlchemy()

View file

@ -2,18 +2,18 @@
This module defines the Alert database class.
"""
from ..base import Base
from ..base import ext
class Alert(Base.Model):
class Alert(ext.Model):
__tablename__ = "alert"
id = Base.Column(Base.Integer, primary_key=True)
name = Base.Column(Base.String, nullable=False)
limit = Base.Column(Base.Integer, nullable=False)
window_size = Base.Column(Base.Integer, nullable=False)
id = ext.Column(ext.Integer, primary_key=True)
name = ext.Column(ext.String, nullable=False)
limit = ext.Column(ext.Integer, nullable=False)
window_size = ext.Column(ext.Integer, nullable=False)
# Foreign Keys
repository_id = Base.Column(Base.Integer, Base.ForeignKey("repository.id", ondelete="CASCADE"), nullable=False)
repository_id = ext.Column(ext.Integer, ext.ForeignKey("repository.id", ondelete="CASCADE"), nullable=False)
# Relationships
repository = Base.relationship("Repository", back_populates="alerts")
notifications = Base.relationship("Notification", back_populates="alert", cascade="all, delete")
operations = Base.relationship("BoolOperation", back_populates="alert", cascade="all, delete")
repository = ext.relationship("Repository", back_populates="alerts")
notifications = ext.relationship("Notification", back_populates="alert", cascade="all, delete")
operations = ext.relationship("BoolOperation", back_populates="alert", cascade="all, delete")

View file

@ -2,12 +2,12 @@
This module defines the Authorization database class.
"""
from ..base import Base
from ..base import ext
class Authorization(Base.Model):
rid = Base.Column(Base.Integer, Base.ForeignKey("repository.id", ondelete="CASCADE"), primary_key=True)
email = Base.Column(Base.String, Base.ForeignKey("user.email", ondelete="CASCADE"), primary_key=True)
class Authorization(ext.Model):
rid = ext.Column(ext.Integer, ext.ForeignKey("repository.id", ondelete="CASCADE"), primary_key=True)
email = ext.Column(ext.String, ext.ForeignKey("user.email", ondelete="CASCADE"), primary_key=True)
# Relationships
repository = Base.relationship("Repository", back_populates="authorizations")
user = Base.relationship("User", back_populates="authorizations")
repository = ext.relationship("Repository", back_populates="authorizations")
user = ext.relationship("User", back_populates="authorizations")

View file

@ -2,24 +2,25 @@
This module defines the BoolOperation database class.
"""
from ..base import Base, backref
from ..base import ext
from .Enums import OperationType
from sqlalchemy.orm import backref
class BoolOperation(Base.Model):
class BoolOperation(ext.Model):
__tablename__ = "bool_operation"
id = Base.Column(Base.Integer, primary_key=True)
operation = Base.Column(Base.Enum(OperationType), nullable=False)
isRoot = Base.Column(Base.Boolean, default=False, nullable=False)
id = ext.Column(ext.Integer, primary_key=True)
operation = ext.Column(ext.Enum(OperationType), nullable=False)
isRoot = ext.Column(ext.Boolean, default=False, nullable=False)
# Foreign Keys
condition_id = Base.Column(Base.Integer, Base.ForeignKey("condition.id"))
node_1_id = Base.Column(Base.Integer, Base.ForeignKey("bool_operation.id"))
node_2_id = Base.Column(Base.Integer, Base.ForeignKey("bool_operation.id"))
alert_id = Base.Column(Base.Integer, Base.ForeignKey("alert.id"))
condition_id = ext.Column(ext.Integer, ext.ForeignKey("condition.id"))
node_1_id = ext.Column(ext.Integer, ext.ForeignKey("bool_operation.id"))
node_2_id = ext.Column(ext.Integer, ext.ForeignKey("bool_operation.id"))
alert_id = ext.Column(ext.Integer, ext.ForeignKey("alert.id"))
# Relationships
condition = Base.relationship("Condition", back_populates="operations")
node_1 = Base.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_1_id==bool_operation.c.id"),
condition = ext.relationship("Condition", back_populates="operations")
node_1 = ext.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_1_id==bool_operation.c.id"),
remote_side="BoolOperation.id", backref=backref("father_1", uselist=False))
node_2 = Base.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_2_id==bool_operation.c.id"),
node_2 = ext.relationship("BoolOperation", primaryjoin=("bool_operation.c.node_2_id==bool_operation.c.id"),
remote_side="BoolOperation.id", backref=backref("father_2", uselist=False))
alert = Base.relationship("Alert", back_populates="operations")
alert = ext.relationship("Alert", back_populates="operations")

View file

@ -2,13 +2,13 @@
This module defines the Composed database class.
"""
from ..base import Base
from ..base import ext
class Composed(Base.Model):
class Composed(ext.Model):
__tablename__ = "composed"
rid = Base.Column(Base.Integer, Base.ForeignKey("repository.id"), primary_key=True)
snowflake = Base.Column(Base.String, Base.ForeignKey("tweet.snowflake"), primary_key=True)
rid = ext.Column(ext.Integer, ext.ForeignKey("repository.id"), primary_key=True)
snowflake = ext.Column(ext.String, ext.ForeignKey("tweet.snowflake"), primary_key=True)
# Relationships
repository = Base.relationship("Repository", back_populates="tweets")
tweet = Base.relationship("Tweet", back_populates="repositories")
repository = ext.relationship("Repository", back_populates="tweets")
tweet = ext.relationship("Tweet", back_populates="repositories")

View file

@ -2,21 +2,21 @@
This module defines the Condition database class.
"""
from ..base import Base
from ..base import ext
from .Enums import ConditionType
class Condition(Base.Model):
class Condition(ext.Model):
__tablename__ = "condition"
id = Base.Column(Base.Integer, primary_key=True)
type = Base.Column(Base.Enum(ConditionType), nullable=False)
content = Base.Column(Base.String, nullable=False)
id = ext.Column(ext.Integer, primary_key=True)
type = ext.Column(ext.Enum(ConditionType), nullable=False)
content = ext.Column(ext.String, nullable=False)
# FK
repository_id = Base.Column(Base.Integer, Base.ForeignKey("repository.id", ondelete="CASCADE"))
repository_id = ext.Column(ext.Integer, ext.ForeignKey("repository.id", ondelete="CASCADE"))
# Relationships
repository = Base.relationship("Repository", back_populates="conditions", cascade="all, delete")
tweets = Base.relationship("Contains", back_populates="condition")
operations = Base.relationship("BoolOperation", back_populates="condition")
repository = ext.relationship("Repository", back_populates="conditions", cascade="all, delete")
tweets = ext.relationship("Contains", back_populates="condition")
operations = ext.relationship("BoolOperation", back_populates="condition")
def to_json(self):
return {

View file

@ -2,13 +2,13 @@
This module defines the Contains database class.
"""
from ..base import Base
from ..base import ext
class Contains(Base.Model):
class Contains(ext.Model):
__tablename__ = "contains"
cid = Base.Column(Base.Integer, Base.ForeignKey("condition.id"), primary_key=True)
snowflake = Base.Column(Base.String, Base.ForeignKey("tweet.snowflake"), primary_key=True)
cid = ext.Column(ext.Integer, ext.ForeignKey("condition.id"), primary_key=True)
snowflake = ext.Column(ext.String, ext.ForeignKey("tweet.snowflake"), primary_key=True)
# Relationships
condition = Base.relationship("Condition", back_populates="tweets")
tweet = Base.relationship("Tweet", back_populates="conditions")
condition = ext.relationship("Condition", back_populates="tweets")
tweet = ext.relationship("Tweet", back_populates="conditions")

View file

@ -2,13 +2,14 @@
This module defines the Notification database class.
"""
from ..base import Base
from ..base import ext
class Notification(Base.Model):
class Notification(ext.Model):
__tablename__ = "notification"
id = Base.Column(Base.Integer, primary_key=True)
ora = Base.Column(Base.DateTime, nullable=False)
id = ext.Column(ext.Integer, primary_key=True)
ora = ext.Column(ext.DateTime, nullable=False)
# Foreign Key
alert_id = Base.Column(Base.Integer, Base.ForeignKey("alert.id"), nullable=False)
alert_id = ext.Column(ext.Integer, ext.ForeignKey("alert.id"), nullable=False)
# Relationships
alert = Base.relationship("Alert", back_populates="notifications")
alert = ext.relationship("Alert", back_populates="notifications")

View file

@ -2,30 +2,30 @@
This module defines the :class:`.Repository` database class.
"""
from ..base import Base
from ..base import ext
from .Enums import ConditionMode
class Repository(Base.Model):
class Repository(ext.Model):
__tablename__ = "repository"
# Columns
id = Base.Column(Base.Integer, primary_key=True)
name = Base.Column(Base.String, nullable=False)
start = Base.Column(Base.DateTime, nullable=True)
end = Base.Column(Base.DateTime, nullable=True)
is_active = Base.Column(Base.Boolean, nullable=False, default=False)
evaluation_mode = Base.Column(Base.Enum(ConditionMode), default=ConditionMode.all_or.value)
id = ext.Column(ext.Integer, primary_key=True)
name = ext.Column(ext.String, nullable=False)
start = ext.Column(ext.DateTime, nullable=True)
end = ext.Column(ext.DateTime, nullable=True)
is_active = ext.Column(ext.Boolean, nullable=False, default=False)
evaluation_mode = ext.Column(ext.Enum(ConditionMode), default=ConditionMode.all_or.value)
# Foreign Keys
owner_id = Base.Column(Base.String, Base.ForeignKey("user.email", ondelete="CASCADE"), nullable=False)
owner_id = ext.Column(ext.String, ext.ForeignKey("user.email", ondelete="CASCADE"), nullable=False)
# Relationships
owner = Base.relationship("User", back_populates="owner_of")
authorizations = Base.relationship("Authorization", back_populates="repository", cascade="all, delete")
tweets = Base.relationship("Composed", back_populates="repository", cascade="all, delete")
alerts = Base.relationship("Alert", back_populates="repository", cascade="all, delete")
conditions = Base.relationship("Condition", back_populates="repository")
owner = ext.relationship("User", back_populates="owner_of")
authorizations = ext.relationship("Authorization", back_populates="repository", cascade="all, delete")
tweets = ext.relationship("Composed", back_populates="repository", cascade="all, delete")
alerts = ext.relationship("Alert", back_populates="repository", cascade="all, delete")
conditions = ext.relationship("Condition", back_populates="repository")
def to_json(self):
return {

View file

@ -2,15 +2,15 @@
This module defines the Tweet database class.
"""
from ..base import Base
from ..base import ext
class Tweet(Base.Model):
class Tweet(ext.Model):
__tablename__ = "tweet"
snowflake = Base.Column(Base.String, primary_key=True)
content = Base.Column(Base.String)
location = Base.Column(Base.String) # Todo: see if a dedicated class for locations is needed. This is likely.
poster = Base.Column(Base.String) # Todo: see if a dedicated class for posters is needed.
snowflake = ext.Column(ext.String, primary_key=True)
content = ext.Column(ext.String)
location = ext.Column(ext.String) # Todo: see if a dedicated class for locations is needed. This is likely.
poster = ext.Column(ext.String) # Todo: see if a dedicated class for posters is needed.
# Relationships
repositories = Base.relationship("Composed", back_populates="tweet", cascade="all, delete")
conditions = Base.relationship("Contains", back_populates="tweet", cascade="all, delete")
repositories = ext.relationship("Composed", back_populates="tweet", cascade="all, delete")
conditions = ext.relationship("Contains", back_populates="tweet", cascade="all, delete")

View file

@ -2,18 +2,18 @@
This module defines the User database class.
"""
from ..base import Base
from ..base import ext
class User(Base.Model):
class User(ext.Model):
__tablename__ = "user"
email = Base.Column(Base.String, primary_key=True)
username = Base.Column(Base.String, nullable=False)
password = Base.Column(Base.LargeBinary, nullable=False)
isAdmin = Base.Column(Base.Boolean, default=False)
email = ext.Column(ext.String, primary_key=True)
username = ext.Column(ext.String, nullable=False)
password = ext.Column(ext.LargeBinary, nullable=False)
isAdmin = ext.Column(ext.Boolean, default=False)
# Relationships
owner_of = Base.relationship("Repository", back_populates="owner", cascade="all, delete")
authorizations = Base.relationship("Authorization", back_populates="user", cascade="all, delete")
owner_of = ext.relationship("Repository", back_populates="owner", cascade="all, delete")
authorizations = ext.relationship("Authorization", back_populates="user", cascade="all, delete")
def to_json(self):
return {'email': self.email, 'username': self.username, 'isAdmin': self.isAdmin}

View file

@ -9,7 +9,7 @@ from .database import *
import bcrypt
import functools
from flask_jwt_extended import get_jwt_identity
from flask import request, jsonify
from flask import jsonify
def authenticate(username, password):

View file

@ -123,9 +123,9 @@ def page_condition(cid):
if content := request.json.get("content"):
condition.content = content
Base.session.commit()
ext.session.commit()
return json_success(condition.to_json()), 200
if request.method == "DELETE":
Base.session.delete(condition)
Base.session.commit()
ext.session.delete(condition)
ext.session.commit()
return json_success("Deleted."), 200

View file

@ -1,7 +1,8 @@
from flask import render_template, abort, jsonify, request
from nest_backend.database import *
from flask import request
from flask_jwt_extended import jwt_required
from nest_backend.gestione import *
from nest_backend.gestione import repository_auth, json_error, json_success, ConditionType, Condition, Repository, \
find_user, get_jwt_identity
from nest_backend.database import ext as extension_sqlalchemy
from flask_cors import cross_origin
@ -91,7 +92,7 @@ def page_repository_conditions(rid):
return json_error("Missing `content` parameter."), 400
condition = Condition(content=content, type=type_, repository_id=rid)
Base.session.add(condition)
Base.session.commit()
extension_sqlalchemy.session.add(condition)
extension_sqlalchemy.session.commit()
return json_success(condition.to_json()), 200

View file

@ -77,6 +77,6 @@ def page_repositories():
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()
ext.session.add(repository)
ext.session.commit()
return json_success(repository.to_json()), 200

View file

@ -174,16 +174,16 @@ def page_repository(rid):
except KeyError:
return json_error("Unknown `type` specified."), 400
repository.evaluation_mode = evaluation_mode
Base.session.commit()
ext.session.commit()
return json_success(repository.to_json()), 200
elif request.method == "DELETE":
if repository.owner_id != user.email and not user.isAdmin:
return json_error("You are not the owner of this repository."), 403
try:
Base.session.delete(repository)
Base.session.commit()
ext.session.delete(repository)
ext.session.commit()
except Exception as e:
Base.session.rollback()
ext.session.rollback()
return json_error("Cant delete repository because of dependencies."), 500
return json_success("Success"), 200
elif request.method == "PUT":
@ -200,8 +200,8 @@ def page_repository(rid):
# Delete no longer needed conditions.
for c in repository.conditions:
if c.id not in ids:
Base.session.delete(c)
Base.session.commit()
ext.session.delete(c)
ext.session.commit()
# Create brand new conditions
for c in request.json['conditions']:
if not c['id']:
@ -210,6 +210,6 @@ def page_repository(rid):
type_ = ConditionType(type_)
except KeyError:
return json_error("Unknown `type` specified."), 400
Base.session.add(Condition(type=type_, content=c['content'], repository_id=rid))
Base.session.commit()
ext.session.add(Condition(type=type_, content=c['content'], repository_id=rid))
ext.session.commit()
return json_success(repository.to_json()), 200

View file

@ -127,11 +127,11 @@ def page_user(email):
return json_error("User is not admin."), 403
if user == target:
return json_error("The user cant delete himself. Its a sin."), 406
Base.session.delete(target)
ext.session.delete(target)
try:
Base.session.commit()
ext.session.commit()
except Exception:
Base.session.rollback()
ext.session.rollback()
return json_error("Could not delete the user."), 500
return json_success("The user has been deleted.")
elif request.method == "PATCH":
@ -142,5 +142,5 @@ def page_user(email):
target.username = request.json.get("username")
if request.json.get("password"):
target.password = gen_password(request.json.get("password"))
Base.session.commit()
ext.session.commit()
return json_success(target.to_json())

View file

@ -68,6 +68,6 @@ def page_users():
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()
ext.session.add(new_user)
ext.session.commit()
return json_success(new_user.to_json())

View file

@ -2,8 +2,7 @@
from flask_swagger_ui import get_swaggerui_blueprint
SWAGGER_URL = '/docs/'
# FIXME: this will break if the website root isn't /, use url_for() instead!
SWAGGER_URL = '/docs'
API_URL = "/docs/swagger.json"
# Call factory function to create our blueprint

View file

@ -0,0 +1,7 @@
"""
Pytest configuration file.
Import global fixtures here.
"""
from fixtures.flask_client import flask_client

View file

@ -0,0 +1,37 @@
import pytest
import uuid
from nest_backend.app import app
from nest_backend.gestione import gen_password
from nest_backend.database import ext
from nest_backend.database.tables import User
@pytest.fixture(scope="package", autouse=True)
def flask_client():
# Enter testing mode
app.config["TESTING"] = True
# Get environment variables
app.config.from_envvar("FLASK_CONFIG")
# Initialize database
with app.app_context():
# Use unique db schemas for each test session
uniq_schema = f"test_{uuid.uuid4()}"
ext.engine.execute(f"""CREATE SCHEMA "{uniq_schema}";""")
for table in ext.Model.metadata.tables.values():
table.schema = uniq_schema
ext.create_all(app=app)
if not User.query.filter_by(isAdmin=True).all():
ext.session.add(
User(email="admin@admin.com", password=gen_password("password"), username="admin", isAdmin=True))
ext.session.commit()
# Prepare test client
with app.test_client(use_cookies=False) as client:
yield client
# Teardown schema
with app.app_context():
ext.engine.execute(f"""DROP SCHEMA "{uniq_schema}" CASCADE;""")

View file

@ -0,0 +1,9 @@
import pytest
from flask.testing import Client
from nest_backend.test.fixtures import flask_client
# noinspection PyShadowingNames
def test_doa(flask_client: Client):
response = flask_client.get("/doa")
assert b"If you see this, the server is fine." in response.data

View file

@ -7,7 +7,7 @@ from nltk.corpus import stopwords
Base.init_app(app=app)
ext.init_app(app=app)
def authenticate():
c_k = "GEhtSyP9e98mzFeiOCSW0lvQX"
@ -81,5 +81,5 @@ if __name__ == "__main__":
search_repo_conditions()
#print(stopwords.words('italian'))
with app.app_context():
Base.create_all(app=app)
ext.create_all(app=app)
#start_exploring()