From a342af50445c5f625ef5b0b4f008c636bebbf213 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Fri, 24 Apr 2020 05:37:16 +0100 Subject: [PATCH 01/22] Projeto iniciado. --- FlaskAPI/__init__.py | 24 ++++++ FlaskAPI/app.py | 15 ++-- FlaskAPI/models.py | 161 ++++++++++++++++++++++++++++++++++++++ FlaskAPI/requirements.txt | 22 ++++++ FlaskAPI/settings.py | 21 +++++ FlaskAPI/views.py | 56 +++++++++++++ Frontend/Frontend/urls.py | 2 +- 7 files changed, 291 insertions(+), 10 deletions(-) create mode 100644 FlaskAPI/__init__.py create mode 100644 FlaskAPI/models.py create mode 100644 FlaskAPI/requirements.txt create mode 100644 FlaskAPI/settings.py create mode 100644 FlaskAPI/views.py diff --git a/FlaskAPI/__init__.py b/FlaskAPI/__init__.py new file mode 100644 index 0000000..c7d6913 --- /dev/null +++ b/FlaskAPI/__init__.py @@ -0,0 +1,24 @@ +from flask import Flask, Response +from flask_swagger_ui import get_swaggerui_blueprint + + +class MyResponse(Response): + default_mimetype = 'application/xml' + + +# http://flask.pocoo.org/docs/0.10/patterns/appfactories/ +def create_app(config_filename): + app = Flask(__name__) + app.config.from_object(config_filename) + app.config['SQLALCHEMY_TRACK_MODIFICATONS'] = False + app.response_class = MyResponse + + from models import db + db.init_app(app) + + # Blueprints + from views import users_bp + app.register_blueprint(users_bp) + + + return app \ No newline at end of file diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index 4b059ec..7d38579 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -1,12 +1,9 @@ -from flask import Flask - -app = Flask(__name__) - - -@app.route('/') -def hello_world(): - return 'Hello World!' +from __init__ import create_app +app = create_app('settings') if __name__ == '__main__': - app.run() + + app.run(host=app.config['HOST'], + port=app.config['PORT'], + debug=app.config['DEBUG']) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py new file mode 100644 index 0000000..da00d88 --- /dev/null +++ b/FlaskAPI/models.py @@ -0,0 +1,161 @@ +from flask_sqlalchemy import SQLAlchemy +from marshmallow import validate +from marshmallow_jsonapi import Schema, fields +from flask_marshmallow import Marshmallow + +db = SQLAlchemy() +ma = Marshmallow() + +class CRUD: + def add(self, resource): + db.session.add(resource) + return db.session.commit() + + def update(self): + return db.session.commit() + + def delete(self, resource): + db.session.delete(resource) + return db.session.commit() + + +class Role (db.Model, CRUD): + + __tablename__ = 'Role' + id = db.Column(db.Integer, primary_key=True) + role_name = db.Column(db.String(20)) + + def __init__(self, role_name): + self.role_name = role_name + + +class Profile(db.Model, CRUD): + + __tablename__ = 'Profile' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + email = db.Column(db.String(200), nullable=False, unique=True) + num_testes = db.Column(db.INTEGER) + register_date = db.Column(db.TIMESTAMP, nullable=False) + picture = db.Column(db.LargeBinary) + last_login = db.Column(db.TIMESTAMP) + role = db.Column(db.Integer, db.ForeignKey('Role.id')) + + def __init__(self, id, name, email, num_testes, register_date, picture, last_login, role): + self.id = id + self.name = name + self.email = email + self.num_testes = num_testes + self.register_date = register_date + self.picture = picture + self.last_login = last_login + self.role = role + + +class Template(db.Model, CRUD): + + __tablename__ = 'Template' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80)) + protocol = db.Column(db.String(50)) + duration = db.Column(db.BIGINT) + profile = db.Column(db.Integer, db.ForeignKey('Profile.id')) + + def __init__(self, id, name, protocol, duration, profile): + self.id = id + self.name = name + self.protocol = protocol + self.duration = duration + self.profile = profile + + +class Experience(db.Model, CRUD): + + __tablename__ = 'Experience' + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(100)) + begin_date = db.Column(db.TIMESTAMP, nullable=False) + end_date = db.Column(db.TIMESTAMP, nullable=False) + num_test = db.Column(db.Integer) + register_date = db.Column(db.TIMESTAMP, nullable=False) + status = db.Column(db.String(20), nullable=False) + profile = db.Column(db.Integer, db.ForeignKey('Profile.id')) + template = db.Column(db.Integer, db.ForeignKey('Template.id')) + + def __init__(self, id, name, begin_date, end_date, num_test, register_date, status, profile, template): + self.id = id + self.name = name + self.begin_date = begin_date + self.end_date = end_date + self.num_test = num_test + self.register_date = register_date + self.status = status + self.profile = profile + self.template = template + + +class APU(db.Model, CRUD): + + __tablename__ = 'APU' + number = db.Column(db.Integer, primary_key=True) + + def __init__(self, number): + self.number = number + + +class APUConfig(db.Model, CRUD): + + __tablename__ = 'APUConfig' + id = db.Column(db.Integer, primary_key=True) + + +class APUConfig_Template(db.Model, CRUD): + + __tablename__ = 'APUConfig_Template' + id_nonexistent = db.Column(db.Integer, primary_key=True) + apu = db.Column(db.Integer, db.ForeignKey('APU.number')) + apu_config = db.Column(db.Integer, db.ForeignKey('APUConfig.id')) + template = db.Column(db.Integer, db.ForeignKey('Template.id')) + + def __init__(self, apu, apu_config, template): + self.apu = apu + self.apu_config = apu_config + self.template = template + + +class RoleSchema(ma.Schema): + class Meta: + fields = ('id', 'role_name') + + +class ProfileSchema(ma.Schema): + class Meta: + fields = ('id', 'name', 'email', 'num_testes', 'register_date', 'picture', 'last_login', 'role') + + +class TemplateSchema(ma.Schema): + class Meta: + fields = ('Template', 'id', 'name', 'protocol', 'duration', 'profile') + + +class ExperienceSchema(ma.Schema): + class Meta: + fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template') + + +class APUSchema(ma.Schema): + class Meta: + fields = ('number',) + + +class APUConfigSchema(ma.Schema): + class Meta: + fields = ('id',) + + +class APUConfig_TemplateSchema(ma.Schema): + class Meta: + fields = ('apu', 'apu_config', 'template') + + + diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt new file mode 100644 index 0000000..c8ce1b1 --- /dev/null +++ b/FlaskAPI/requirements.txt @@ -0,0 +1,22 @@ +alembic==1.4.2 +aniso8601==8.0.0 +Flask==1.1.2 +Flask-Migrate==2.5.3 +Flask-RESTful==0.3.8 +Flask-Script==2.0.6 +Flask-SQLAlchemy==2.4.1 +flask-marshmallow==0.11.0 +marshmallow-sqlalchemy==0.22.3 +itsdangerous== 1.1.0 +Jinja2==2.11.2 +Mako==1.1.2 +MarkupSafe==1.1.1 +marshmallow==3.5.1 +marshmallow-jsonapi==0.23.1 +psycopg2==2.8.5 +python-dateutil==2.8.1 +python-editor==1.0.4 +pytz==2019.3 +six==1.14.0 +SQLAlchemy==1.3.16 +Werkzeug==1.0.1 diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py new file mode 100644 index 0000000..a0620e0 --- /dev/null +++ b/FlaskAPI/settings.py @@ -0,0 +1,21 @@ +# DATABASE SETTINGS +import os + +pg_db_username = os.environ.get('db_username') +pg_db_password = os.environ.get('db_password') +pg_db_name = os.environ.get('db_name') +pg_db_hostname = os.environ.get('db_hostname') + + +DEBUG = True +PORT = 5000 +HOST = "127.0.0.1" +SQLALCHEMY_ECHO = True +SQLALCHEMY_TRACK_MODIFICATIONS = True +SECRET_KEY = "SOME SECRET" +# PostgreSQL +SQLALCHEMY_DATABASE_URI = "postgresql://{DB_USER}:{DB_PASS}@{DB_ADDR}/{DB_NAME}".format(DB_USER=pg_db_username, + DB_PASS=pg_db_password, + DB_ADDR=pg_db_hostname, + DB_NAME=pg_db_name) +print(SQLALCHEMY_DATABASE_URI) \ No newline at end of file diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py new file mode 100644 index 0000000..4642dbf --- /dev/null +++ b/FlaskAPI/views.py @@ -0,0 +1,56 @@ +from models import * +from flask import Blueprint, request, jsonify, make_response +from flask_restful import Api, Resource + +from sqlalchemy.exc import SQLAlchemyError +from marshmallow import ValidationError + +users_bp = Blueprint('users', __name__) +api = Api(users_bp) + +role_schema = RoleSchema() +profile_schema = ProfileSchema(many=True) +template_schema = TemplateSchema(many=True) +experience_schema = ExperienceSchema(many=True) +apu_schema = APUSchema(many=True) +apuconfig_schema = APUConfigSchema(many=True) +apuconfig_template_schema = APUConfig_TemplateSchema(many=True) + + +class ProfileList(Resource): + def get(self): + users_query = Profile.query.all() + results = profile_schema.dump(users_query, many=True).data + return results + + def post(self): + raw_dict = request.get_json(force=True) + try: + profile_schema.validate(raw_dict) + d_profile = raw_dict['data']['attributes'] + profile = Profile(d_profile['name'], d_profile['email'], d_profile['num_testes'], d_profile['register_date'], d_profile['picture'], d_profile['last_login'], d_profile['role']) + profile.add(profile) + query = profile_schema.query.get(profile.id) + results = profile_schema.dump(query).data + return results, 201 + + except ValidationError as err: + resp = jsonify({"error": err.messages}) + resp.status_code = 403 + return resp + + except SQLAlchemyError as e: + db.session.rollback() + resp = jsonify({"error": str(e)}) + resp.status_code = 403 + return resp + +class RoleList(Resource): + def get(self): + role_query = Role.query.all() + results = profile_schema.dump(role_query, many=True).data + return results + + +api.add_resource(ProfileList, '/users') +api.add_resource(RoleList, '/roles') \ No newline at end of file diff --git a/Frontend/Frontend/urls.py b/Frontend/Frontend/urls.py index 48dd38e..2d6bdd3 100644 --- a/Frontend/Frontend/urls.py +++ b/Frontend/Frontend/urls.py @@ -22,5 +22,5 @@ path('admin/', admin.site.urls), path('', views.home, name='home'), path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), - path('logout', auth_views.LogoutView.as_view(next_page='/'), name='logout'), + path('logout/', auth_views.LogoutView.as_view(next_page='/'), name='logout'), ] From 3573c12e9bfbc183a4445258109717bdd207eef5 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Fri, 24 Apr 2020 17:53:17 +0100 Subject: [PATCH 02/22] user and role base paths defined, adding jwt support to users --- FlaskAPI/.cert | 0 FlaskAPI/.gitignore | 3 ++- FlaskAPI/__init__.py | 24 --------------------- FlaskAPI/app.py | 37 ++++++++++++++++++++++++++++++-- FlaskAPI/models.py | 44 +++++++++++++++++++-------------------- FlaskAPI/requirements.txt | 3 +++ FlaskAPI/settings.py | 18 ++++++++++++++-- FlaskAPI/views.py | 18 +++++++++++----- 8 files changed, 91 insertions(+), 56 deletions(-) create mode 100644 FlaskAPI/.cert delete mode 100644 FlaskAPI/__init__.py diff --git a/FlaskAPI/.cert b/FlaskAPI/.cert new file mode 100644 index 0000000..e69de29 diff --git a/FlaskAPI/.gitignore b/FlaskAPI/.gitignore index b3cac3e..d03277b 100644 --- a/FlaskAPI/.gitignore +++ b/FlaskAPI/.gitignore @@ -1,3 +1,4 @@ .env venv/ -.idea/ \ No newline at end of file +.idea/ +.cert \ No newline at end of file diff --git a/FlaskAPI/__init__.py b/FlaskAPI/__init__.py deleted file mode 100644 index c7d6913..0000000 --- a/FlaskAPI/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from flask import Flask, Response -from flask_swagger_ui import get_swaggerui_blueprint - - -class MyResponse(Response): - default_mimetype = 'application/xml' - - -# http://flask.pocoo.org/docs/0.10/patterns/appfactories/ -def create_app(config_filename): - app = Flask(__name__) - app.config.from_object(config_filename) - app.config['SQLALCHEMY_TRACK_MODIFICATONS'] = False - app.response_class = MyResponse - - from models import db - db.init_app(app) - - # Blueprints - from views import users_bp - app.register_blueprint(users_bp) - - - return app \ No newline at end of file diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index 7d38579..172e44f 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -1,9 +1,42 @@ -from __init__ import create_app +from flask_jwt_extended import JWTManager + +from models import db + +from flask import Flask, Response + + +class MyResponse(Response): + default_mimetype = 'application/xml' + +# http://flask.pocoo.org/docs/0.10/patterns/appfactories/ +def create_app(config_filename): + app = Flask(__name__) + app.config.from_object(config_filename) + app.config['SQLALCHEMY_TRACK_MODIFICATONS'] = False + app.response_class = MyResponse + +# from models import db +# db.init_app(app) + + # Blueprints + from views import users_bp + app.register_blueprint(users_bp) + return app + + + + app = create_app('settings') +db.init_app(app) +jwt = JWTManager(app) + +@app.before_first_request +def create_database(): + db.create_all() if __name__ == '__main__': app.run(host=app.config['HOST'], port=app.config['PORT'], - debug=app.config['DEBUG']) + debug=app.config['DEBUG']) \ No newline at end of file diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index da00d88..f9d5b4f 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -2,9 +2,9 @@ from marshmallow import validate from marshmallow_jsonapi import Schema, fields from flask_marshmallow import Marshmallow +from marshmallow import Schema, fields, ValidationError, pre_load db = SQLAlchemy() -ma = Marshmallow() class CRUD: def add(self, resource): @@ -21,7 +21,7 @@ def delete(self, resource): class Role (db.Model, CRUD): - __tablename__ = 'Role' + __tablename__ = 'role' id = db.Column(db.Integer, primary_key=True) role_name = db.Column(db.String(20)) @@ -31,7 +31,7 @@ def __init__(self, role_name): class Profile(db.Model, CRUD): - __tablename__ = 'Profile' + __tablename__ = 'profile' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) email = db.Column(db.String(200), nullable=False, unique=True) @@ -39,7 +39,7 @@ class Profile(db.Model, CRUD): register_date = db.Column(db.TIMESTAMP, nullable=False) picture = db.Column(db.LargeBinary) last_login = db.Column(db.TIMESTAMP) - role = db.Column(db.Integer, db.ForeignKey('Role.id')) + role = db.Column(db.Integer, db.ForeignKey('role.id')) def __init__(self, id, name, email, num_testes, register_date, picture, last_login, role): self.id = id @@ -54,12 +54,12 @@ def __init__(self, id, name, email, num_testes, register_date, picture, last_log class Template(db.Model, CRUD): - __tablename__ = 'Template' + __tablename__ = 'template' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) protocol = db.Column(db.String(50)) duration = db.Column(db.BIGINT) - profile = db.Column(db.Integer, db.ForeignKey('Profile.id')) + profile = db.Column(db.Integer, db.ForeignKey('profile.id')) def __init__(self, id, name, protocol, duration, profile): self.id = id @@ -71,7 +71,7 @@ def __init__(self, id, name, protocol, duration, profile): class Experience(db.Model, CRUD): - __tablename__ = 'Experience' + __tablename__ = 'experience' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) begin_date = db.Column(db.TIMESTAMP, nullable=False) @@ -79,8 +79,8 @@ class Experience(db.Model, CRUD): num_test = db.Column(db.Integer) register_date = db.Column(db.TIMESTAMP, nullable=False) status = db.Column(db.String(20), nullable=False) - profile = db.Column(db.Integer, db.ForeignKey('Profile.id')) - template = db.Column(db.Integer, db.ForeignKey('Template.id')) + profile = db.Column(db.Integer, db.ForeignKey('profile.id')) + template = db.Column(db.Integer, db.ForeignKey('template.id')) def __init__(self, id, name, begin_date, end_date, num_test, register_date, status, profile, template): self.id = id @@ -96,7 +96,7 @@ def __init__(self, id, name, begin_date, end_date, num_test, register_date, stat class APU(db.Model, CRUD): - __tablename__ = 'APU' + __tablename__ = 'apu' number = db.Column(db.Integer, primary_key=True) def __init__(self, number): @@ -105,17 +105,17 @@ def __init__(self, number): class APUConfig(db.Model, CRUD): - __tablename__ = 'APUConfig' + __tablename__ = 'apuconfig' id = db.Column(db.Integer, primary_key=True) class APUConfig_Template(db.Model, CRUD): - __tablename__ = 'APUConfig_Template' + __tablename__ = 'apuconfig_template' id_nonexistent = db.Column(db.Integer, primary_key=True) - apu = db.Column(db.Integer, db.ForeignKey('APU.number')) - apu_config = db.Column(db.Integer, db.ForeignKey('APUConfig.id')) - template = db.Column(db.Integer, db.ForeignKey('Template.id')) + apu = db.Column(db.Integer, db.ForeignKey('apu.number')) + apu_config = db.Column(db.Integer, db.ForeignKey('apuconfig.id')) + template = db.Column(db.Integer, db.ForeignKey('template.id')) def __init__(self, apu, apu_config, template): self.apu = apu @@ -123,37 +123,37 @@ def __init__(self, apu, apu_config, template): self.template = template -class RoleSchema(ma.Schema): +class RoleSchema(Schema): class Meta: fields = ('id', 'role_name') -class ProfileSchema(ma.Schema): +class ProfileSchema(Schema): class Meta: fields = ('id', 'name', 'email', 'num_testes', 'register_date', 'picture', 'last_login', 'role') -class TemplateSchema(ma.Schema): +class TemplateSchema(Schema): class Meta: fields = ('Template', 'id', 'name', 'protocol', 'duration', 'profile') -class ExperienceSchema(ma.Schema): +class ExperienceSchema(Schema): class Meta: fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template') -class APUSchema(ma.Schema): +class APUSchema(Schema): class Meta: fields = ('number',) -class APUConfigSchema(ma.Schema): +class APUConfigSchema(Schema): class Meta: fields = ('id',) -class APUConfig_TemplateSchema(ma.Schema): +class APUConfig_TemplateSchema(Schema): class Meta: fields = ('apu', 'apu_config', 'template') diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index c8ce1b1..01418d5 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -6,6 +6,7 @@ Flask-RESTful==0.3.8 Flask-Script==2.0.6 Flask-SQLAlchemy==2.4.1 flask-marshmallow==0.11.0 +flask-jwt-extended marshmallow-sqlalchemy==0.22.3 itsdangerous== 1.1.0 Jinja2==2.11.2 @@ -20,3 +21,5 @@ pytz==2019.3 six==1.14.0 SQLAlchemy==1.3.16 Werkzeug==1.0.1 +Search Results +Web results diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index a0620e0..7ec86f7 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -1,6 +1,7 @@ -# DATABASE SETTINGS import os +# DATABASE SETTINGS + pg_db_username = os.environ.get('db_username') pg_db_password = os.environ.get('db_password') pg_db_name = os.environ.get('db_name') @@ -18,4 +19,17 @@ DB_PASS=pg_db_password, DB_ADDR=pg_db_hostname, DB_NAME=pg_db_name) -print(SQLALCHEMY_DATABASE_URI) \ No newline at end of file + + + + +# JWT Decode Algorithm + +jwt_cert = os.environ.get('cert') + + +JWT_DECODE_ALGORITHMS = 'RS256' +# JWT Decode CERT +JWT_SECRET_KEY = jwt_cert +# JWT Identifier +JWT_IDENTITY_CLAIM = 'email' \ No newline at end of file diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 4642dbf..b208b97 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -1,3 +1,5 @@ +from flask_jwt_extended import jwt_required, get_raw_jwt + from models import * from flask import Blueprint, request, jsonify, make_response from flask_restful import Api, Resource @@ -16,13 +18,18 @@ apuconfig_schema = APUConfigSchema(many=True) apuconfig_template_schema = APUConfig_TemplateSchema(many=True) - class ProfileList(Resource): + @jwt_required def get(self): + header = request.headers + print(1, header) + print(2, get_raw_jwt()) + print(3, get_raw_jwt()['jti']) users_query = Profile.query.all() - results = profile_schema.dump(users_query, many=True).data + results = profile_schema.dump(users_query, many=True) return results + @jwt_required def post(self): raw_dict = request.get_json(force=True) try: @@ -48,9 +55,10 @@ def post(self): class RoleList(Resource): def get(self): role_query = Role.query.all() - results = profile_schema.dump(role_query, many=True).data + print("ROLE QUERYY ", role_query) + results = profile_schema.dump(role_query, many=True) return results -api.add_resource(ProfileList, '/users') -api.add_resource(RoleList, '/roles') \ No newline at end of file +api.add_resource(ProfileList, '/user') +api.add_resource(RoleList, '/role') \ No newline at end of file From 70c032e1d5587697c80e1295c236fe2ec339cff0 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sat, 25 Apr 2020 04:23:35 +0100 Subject: [PATCH 03/22] added extra CRUD to users, and base get for experience, jwt token not working cause certificate is invalid --- FlaskAPI/app.py | 4 +- FlaskAPI/models.py | 2 +- FlaskAPI/settings.py | 9 ++-- FlaskAPI/views.py | 119 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 108 insertions(+), 26 deletions(-) diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index 172e44f..b3d553e 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -19,8 +19,8 @@ def create_app(config_filename): # db.init_app(app) # Blueprints - from views import users_bp - app.register_blueprint(users_bp) + from views import schema_blueprint + app.register_blueprint(schema_blueprint) return app diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index f9d5b4f..fd6f9f5 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -25,7 +25,7 @@ class Role (db.Model, CRUD): id = db.Column(db.Integer, primary_key=True) role_name = db.Column(db.String(20)) - def __init__(self, role_name): + def __init__(self, id, role_name): self.role_name = role_name diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 7ec86f7..0fc15d5 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -1,4 +1,5 @@ import os +from Crypto.PublicKey import RSA # DATABASE SETTINGS @@ -25,11 +26,11 @@ # JWT Decode Algorithm -jwt_cert = os.environ.get('cert') +with open('.cert', mode='rb') as jwt_cert: + JWT_SECRET_KEY = jwt_cert.read() - -JWT_DECODE_ALGORITHMS = 'RS256' +JWT_DECODE_ALGORITHMS = ['RS256'] # JWT Decode CERT -JWT_SECRET_KEY = jwt_cert + # JWT Identifier JWT_IDENTITY_CLAIM = 'email' \ No newline at end of file diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index b208b97..58e3e90 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -1,4 +1,4 @@ -from flask_jwt_extended import jwt_required, get_raw_jwt +from flask_jwt_extended import jwt_required, get_raw_jwt, get_jti from models import * from flask import Blueprint, request, jsonify, make_response @@ -7,29 +7,40 @@ from sqlalchemy.exc import SQLAlchemyError from marshmallow import ValidationError -users_bp = Blueprint('users', __name__) -api = Api(users_bp) +schema_blueprint = Blueprint('amazing', __name__) +api = Api(schema_blueprint) role_schema = RoleSchema() -profile_schema = ProfileSchema(many=True) -template_schema = TemplateSchema(many=True) -experience_schema = ExperienceSchema(many=True) -apu_schema = APUSchema(many=True) -apuconfig_schema = APUConfigSchema(many=True) -apuconfig_template_schema = APUConfig_TemplateSchema(many=True) - -class ProfileList(Resource): - @jwt_required +profile_schema = ProfileSchema() +template_schema = TemplateSchema() +experience_schema = ExperienceSchema() +apu_schema = APUSchema() +apuconfig_schema = APUConfigSchema() +apuconfig_template_schema = APUConfig_TemplateSchema() + + +def retrieve_id(email): + # email = get_raw_jwt()['jti'] + users_query = Profile.query.filter_by(email=email) + results = profile_schema.dump(users_query, many=True) + if results: + return results[0]['id'] + return + +email = 'j.brito@ua.pt' + +class ProfileSingle(Resource): + + #@jwt_required def get(self): header = request.headers - print(1, header) - print(2, get_raw_jwt()) - print(3, get_raw_jwt()['jti']) - users_query = Profile.query.all() + #email = get_raw_jwt()['jti'] + + users_query = Profile.query.filter_by(email=email) results = profile_schema.dump(users_query, many=True) return results - @jwt_required + #@jwt_required def post(self): raw_dict = request.get_json(force=True) try: @@ -52,6 +63,65 @@ def post(self): resp.status_code = 403 return resp + def put(self): + # email = get_raw_jwt()['jti'] + user_id = retrieve_id(email) + + if not user_id: + resp = jsonify({"error": 'Non-existent user'}) + resp.status_code = 403 + return resp + + raw_dict = request.get_json(force=True) + try: + profile = profile_schema.query.get(user_id) + profile_schema.validate(raw_dict) + d_profile = raw_dict['data']['attributes'] + + profile['name'], profile['email'], profile['num_testes'], profile['register_date'], profile['picture'], profile['last_login'], profile['role'] = d_profile['name'], d_profile['email'], d_profile['num_testes'], d_profile['register_date'], d_profile['picture'], d_profile['last_login'], d_profile['role'] + + profile.update(profile) + results = profile + return results, 201 + + except ValidationError as err: + resp = jsonify({"error": err.messages}) + resp.status_code = 403 + return resp + + except SQLAlchemyError as e: + db.session.rollback() + resp = jsonify({"error": str(e)}) + resp.status_code = 403 + return resp + + def delete(self): + #email = get_raw_jwt()['jti'] + user_id = retrieve_id(email) + + if not user_id: + resp = jsonify({"error": 'Non-existent user'}) + resp.status_code = 403 + return resp + + try: + profile = profile_schema.query.get(user_id) + + profile.delete(profile) + results = {profile} + return results, 200 + + except ValidationError as err: + resp = jsonify({"error": err.messages}) + resp.status_code = 403 + return resp + + except SQLAlchemyError as e: + db.session.rollback() + resp = jsonify({"error": str(e)}) + resp.status_code = 403 + return resp + class RoleList(Resource): def get(self): role_query = Role.query.all() @@ -59,6 +129,17 @@ def get(self): results = profile_schema.dump(role_query, many=True) return results +class ExperienceList(Resource): + + def get(self): + #email = get_raw_jwt()['jti'] + user_id = retrieve_id(email) + experiences = Experience.query.filter_by(profile=user_id) + results = experience_schema.dump(experiences, many=True) + return results + + -api.add_resource(ProfileList, '/user') -api.add_resource(RoleList, '/role') \ No newline at end of file +api.add_resource(ProfileSingle, '/user') +api.add_resource(RoleList, '/role') +api.add_resource(ExperienceList, '/experience') \ No newline at end of file From 34e773ad455808a55ecb2aaf7a35db4bf3bda891 Mon Sep 17 00:00:00 2001 From: Rui Coelho Date: Sat, 25 Apr 2020 16:51:21 +0100 Subject: [PATCH 04/22] update --- FlaskAPI/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 835 bytes FlaskAPI/__pycache__/app.cpython-37.pyc | Bin 0 -> 852 bytes FlaskAPI/__pycache__/settings.cpython-37.pyc | Bin 0 -> 785 bytes FlaskAPI/app.py | 55 +++++++------------ FlaskAPI/requirements.txt | 31 +++-------- FlaskAPI/settings.py | 49 +++++------------ 6 files changed, 43 insertions(+), 92 deletions(-) create mode 100644 FlaskAPI/__pycache__/__init__.cpython-37.pyc create mode 100644 FlaskAPI/__pycache__/app.cpython-37.pyc create mode 100644 FlaskAPI/__pycache__/settings.cpython-37.pyc diff --git a/FlaskAPI/__pycache__/__init__.cpython-37.pyc b/FlaskAPI/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6ec7abf6efbaf4f90b4801984c9395a3f4db7fe9 GIT binary patch literal 835 zcmYjP&2H2%5cW@!hV7QF%7GIPkP95RAXK4lx3sL<-9lRqSSze->|LdGHoXb%Z0f*T|PNvh#3HeBjFR{dRHKBn;jT)}SsNcoQ;8Su-8}uCm#Xb^b6WO4_Jai-ofT@pzqUr-z@(7yWmiUjlz=ym_}fZyaUD LG1J3c+6(^y@#D;% literal 0 HcmV?d00001 diff --git a/FlaskAPI/__pycache__/app.cpython-37.pyc b/FlaskAPI/__pycache__/app.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68fd0504e93f4e25e0e3c2130cb0f7892ea11c2f GIT binary patch literal 852 zcmYLHO>fgM7><*sP22Qi*#|q0V|UmjBsic6QQEQ<)(*8r(@cdG)$dAHCoXo%Sg+&C zg*y_HxbR0f@DqIH#9!D6JJmEtdGh#qU)%5d#4jq9lBLJDcR$~Mw=L_hncNLmljr)C ze>6~wB4))1qu9oF>|iI(;T$r$&D=PT^BH$oA@;Br7jZG0=U6E&<8sDb=HrUacUcuz z^*7IIaUIu@1qjxz5e{f!iXgaHr`~}D<%|^%ELzG~S!;O+s81`j8lec$+E*KIfCqtI z>qGEklh$t#6zLibzF5~tt6Q)}*Jrl)t)mZaEM0{=v>F@#bU#)jr`(q;lrvQj@Noe$ zRW$(#1wm4X=PXP?6)q%CqVuZ;Qn}X2VA!x#>DB3|7bf8pgz_&gQ(_iJ0%(@g8I1ax zlo<~xp*)4;6Ltr~M~|Q2O}&t`JFSy;hcu55PX^u5QE!N=Mjm!rgU*P&?wlzX;xJ-3 zFmkuu>5sajGtxS4c6&>Ee-{_Hh^A2@720heTofSrLQFv3qWy{K>TV!STKbha4HW6F z?f%j~0>=2xDHn`B{AG!%j@`rUUhC=jtpp**ViEDlxD9fa^7**g3zyyg;W%@v`KCJ# z=kvY!l`4NQ+mTDN-Ih5^Um(kJL|vou2+@rsgfzC5dv1IdCM+BSrYK>q7cONXGT}ms zyb*$xV4Q`|+CK_Z6im8jqMn2_jgqMpMKg7D8ZM@M21&HkKg8xzQi6$U)`H?*qa+1$;HmTy#I+I$oJy#PZv47%QuvB0|-C^WP>^= zS}+!14(6dB5ft&TPZ!|gGwM`Is^oN8(q&H7lBzjffh(s5FcZ0}{mB1A?$GR65V_zH zM2Qz3ROgCk9|xK_E7L0%SOg}$WT>K1!1akoRkE-!IKl2~cY zsO-YuE&Wx$cO+P5B!~>7am=X86mxDd%voT9dHY^jz%%{S+%!j&(%8Z#J~f8Yo;AQx zvtpa3nqp7e_;wrv9X@RN?PR<*;G8n!c-~uDoHS9Dkz22G>s{-lh~q(k^OPNSQ_>&E zp;qT7#}1U_!-A}L_0*X-Aq=M0U@aQ^eQK%JfIg-t`rP2iaobgPlGdZ}WGW{oa@P#c z4`9;kYbwD=M5GUvCeUR!cuKj>CL)E@F=k?Hrd~%dS{|u-Pt*{HmRL7FgeNlT z^z@O;wf8X9KMh|QHWFIz1=FlCCflF+bqD}OHy;FU6I)6~wFN%9T zv!EBlS-f9G^BM0!KZ&+8Msd%Q+MkJm3w=hHX3$HLRk(n!wx_K2W)p#Z;JwX@guoZM MJx6O;6~+Iq-{wl+g#Z8m literal 0 HcmV?d00001 diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index b3d553e..2baf932 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -1,42 +1,29 @@ -from flask_jwt_extended import JWTManager +from flask import Flask, request, render_template, jsonify +from flask_cors import CORS +from flask_jwt_extended import JWTManager, jwt_required +from settings import CERT -from models import db +import jwt as tokenizer +import os +from dotenv import load_dotenv -from flask import Flask, Response +app = Flask(__name__) +# JWT Decode Algorithm +app.config['JWT_DECODE_ALGORITHMS'] = ['RS256'] +# JWT Decode CERT +app.config['JWT_SECRET_KEY'] = CERT +# JWT Identifier +app.config['JWT_IDENTITY_CLAIM'] = 'email' -class MyResponse(Response): - default_mimetype = 'application/xml' - -# http://flask.pocoo.org/docs/0.10/patterns/appfactories/ -def create_app(config_filename): - app = Flask(__name__) - app.config.from_object(config_filename) - app.config['SQLALCHEMY_TRACK_MODIFICATONS'] = False - app.response_class = MyResponse - -# from models import db -# db.init_app(app) - - # Blueprints - from views import schema_blueprint - app.register_blueprint(schema_blueprint) - return app - - - - - -app = create_app('settings') -db.init_app(app) +cors = CORS(app, resources={r"/*": {"origins": "*"}}) jwt = JWTManager(app) -@app.before_first_request -def create_database(): - db.create_all() +@app.route('/') +@jwt_required +def hello_world(): + return 'Hello World!' -if __name__ == '__main__': - app.run(host=app.config['HOST'], - port=app.config['PORT'], - debug=app.config['DEBUG']) \ No newline at end of file +if __name__ == '__main__': + app.run() diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index 01418d5..6dcb744 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -1,25 +1,8 @@ -alembic==1.4.2 -aniso8601==8.0.0 -Flask==1.1.2 -Flask-Migrate==2.5.3 -Flask-RESTful==0.3.8 -Flask-Script==2.0.6 -Flask-SQLAlchemy==2.4.1 -flask-marshmallow==0.11.0 +Flask +Flask-Cors flask-jwt-extended -marshmallow-sqlalchemy==0.22.3 -itsdangerous== 1.1.0 -Jinja2==2.11.2 -Mako==1.1.2 -MarkupSafe==1.1.1 -marshmallow==3.5.1 -marshmallow-jsonapi==0.23.1 -psycopg2==2.8.5 -python-dateutil==2.8.1 -python-editor==1.0.4 -pytz==2019.3 -six==1.14.0 -SQLAlchemy==1.3.16 -Werkzeug==1.0.1 -Search Results -Web results +python-dotenv +eventlet +gunicorn +pyjwt[crypto] +Flask-API \ No newline at end of file diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 0fc15d5..6a8534c 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -1,36 +1,17 @@ +from dotenv import load_dotenv import os -from Crypto.PublicKey import RSA -# DATABASE SETTINGS - -pg_db_username = os.environ.get('db_username') -pg_db_password = os.environ.get('db_password') -pg_db_name = os.environ.get('db_name') -pg_db_hostname = os.environ.get('db_hostname') - - -DEBUG = True -PORT = 5000 -HOST = "127.0.0.1" -SQLALCHEMY_ECHO = True -SQLALCHEMY_TRACK_MODIFICATIONS = True -SECRET_KEY = "SOME SECRET" -# PostgreSQL -SQLALCHEMY_DATABASE_URI = "postgresql://{DB_USER}:{DB_PASS}@{DB_ADDR}/{DB_NAME}".format(DB_USER=pg_db_username, - DB_PASS=pg_db_password, - DB_ADDR=pg_db_hostname, - DB_NAME=pg_db_name) - - - - -# JWT Decode Algorithm - -with open('.cert', mode='rb') as jwt_cert: - JWT_SECRET_KEY = jwt_cert.read() - -JWT_DECODE_ALGORITHMS = ['RS256'] -# JWT Decode CERT - -# JWT Identifier -JWT_IDENTITY_CLAIM = 'email' \ No newline at end of file +load_dotenv() +HOST = os.getenv('DB_HOST') +NAME = os.getenv('DB_NAME') +PASS = os.getenv('DB_PASS') +USER = os.getenv('DB_USER') +CERT = b'-----BEGIN PUBLIC KEY-----\n' \ + b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlc6LMgsz5b2m2Q3M/ps2\n' \ + b'XRKIuBRdwOUrY532F9OmkYrrdPsVpDpWTjRsc3Srrc9hUCIWNMQa++Cjq4yMFTHl\n' \ + b'D3Yn8x1kHJnO+DWw7sIJvg1+8PxZWZnslXUHjFRuuxUNUH5wxy5z/C1T6aMqIO93\n' \ + b'tXJty1q2nzVdW9GON0AI0oPHhSdPJalbxC7mo1ExZRa5SoYiBv8xe7ER4e1Neb3K\n' \ + b'sUF+Rfny1t79PQJC6uk0FwnloEQVj5yYvmwAv8HTda0mhFY0GdYqNk5+ks0D3hGg\n' \ + b'3D7FspI98MOX1lUatEJDq6/xE0JlK111uh24i7aZaZD5Bn3dqZl83zK4PdexXE/z\n' \ + b'JwIDAQAB\n' \ + b'-----END PUBLIC KEY-----' \ No newline at end of file From af352a53afbd6669e2a26dad1fed00762341183b Mon Sep 17 00:00:00 2001 From: Rui Coelho Date: Sat, 25 Apr 2020 16:52:17 +0100 Subject: [PATCH 05/22] token --- FlaskAPI/app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index 2baf932..7311d38 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -22,6 +22,7 @@ @app.route('/') @jwt_required def hello_world(): + token = request.headers["Authorization"].split()[1] # Split Bearer from token return 'Hello World!' From 5c03b074912367fecf511bfcc850b9591d02d83e Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sun, 26 Apr 2020 16:04:05 +0100 Subject: [PATCH 06/22] Users, Profile, Experiences returns working --- FlaskAPI/app.py | 31 ++--- FlaskAPI/models.py | 55 +++++---- FlaskAPI/settings.py | 50 +++++++- FlaskAPI/views.py | 277 ++++++++++++++++++++++++++++++++----------- 4 files changed, 299 insertions(+), 114 deletions(-) diff --git a/FlaskAPI/app.py b/FlaskAPI/app.py index 7311d38..c9894a4 100644 --- a/FlaskAPI/app.py +++ b/FlaskAPI/app.py @@ -1,6 +1,9 @@ from flask import Flask, request, render_template, jsonify from flask_cors import CORS -from flask_jwt_extended import JWTManager, jwt_required +from flask_jwt_extended import JWTManager, jwt_required, get_raw_jwt +from views import schema_blueprint +from views import db + from settings import CERT import jwt as tokenizer @@ -8,23 +11,23 @@ from dotenv import load_dotenv app = Flask(__name__) - -# JWT Decode Algorithm -app.config['JWT_DECODE_ALGORITHMS'] = ['RS256'] -# JWT Decode CERT -app.config['JWT_SECRET_KEY'] = CERT -# JWT Identifier -app.config['JWT_IDENTITY_CLAIM'] = 'email' +app.config.from_object('settings') cors = CORS(app, resources={r"/*": {"origins": "*"}}) jwt = JWTManager(app) +app.config.update(JWT=jwt) + +app.register_blueprint(schema_blueprint) + +db.init_app(app) + -@app.route('/') -@jwt_required -def hello_world(): - token = request.headers["Authorization"].split()[1] # Split Bearer from token - return 'Hello World!' +@app.before_first_request +def create_database(): + db.create_all() if __name__ == '__main__': - app.run() + app.run(host=app.config['HOST'], + port=app.config['PORT'], + debug=app.config['DEBUG']) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index fd6f9f5..119d782 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -5,7 +5,7 @@ from marshmallow import Schema, fields, ValidationError, pre_load db = SQLAlchemy() - +session = None class CRUD: def add(self, resource): db.session.add(resource) @@ -25,7 +25,7 @@ class Role (db.Model, CRUD): id = db.Column(db.Integer, primary_key=True) role_name = db.Column(db.String(20)) - def __init__(self, id, role_name): + def __init__(self, role_name): self.role_name = role_name @@ -35,14 +35,13 @@ class Profile(db.Model, CRUD): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) email = db.Column(db.String(200), nullable=False, unique=True) - num_testes = db.Column(db.INTEGER) + num_testes = db.Column(db.INTEGER, nullable=True) register_date = db.Column(db.TIMESTAMP, nullable=False) - picture = db.Column(db.LargeBinary) - last_login = db.Column(db.TIMESTAMP) + picture = db.Column(db.LargeBinary, nullable=True) + last_login = db.Column(db.TIMESTAMP, nullable=True) role = db.Column(db.Integer, db.ForeignKey('role.id')) - def __init__(self, id, name, email, num_testes, register_date, picture, last_login, role): - self.id = id + def __init__(self, name, email, register_date, role, num_testes=None, picture=None, last_login=None): self.name = name self.email = email self.num_testes = num_testes @@ -57,14 +56,12 @@ class Template(db.Model, CRUD): __tablename__ = 'template' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80)) - protocol = db.Column(db.String(50)) duration = db.Column(db.BIGINT) profile = db.Column(db.Integer, db.ForeignKey('profile.id')) - def __init__(self, id, name, protocol, duration, profile): + def __init__(self, id, name, duration, profile): self.id = id self.name = name - self.protocol = protocol self.duration = duration self.profile = profile @@ -73,17 +70,16 @@ class Experience(db.Model, CRUD): __tablename__ = 'experience' id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(100)) + name = db.Column(db.String(100), nullable=False) begin_date = db.Column(db.TIMESTAMP, nullable=False) end_date = db.Column(db.TIMESTAMP, nullable=False) - num_test = db.Column(db.Integer) + num_test = db.Column(db.Integer, nullable=False) register_date = db.Column(db.TIMESTAMP, nullable=False) status = db.Column(db.String(20), nullable=False) profile = db.Column(db.Integer, db.ForeignKey('profile.id')) template = db.Column(db.Integer, db.ForeignKey('template.id')) - def __init__(self, id, name, begin_date, end_date, num_test, register_date, status, profile, template): - self.id = id + def __init__(self, name, begin_date, end_date, num_test, register_date, status, profile, template): self.name = name self.begin_date = begin_date self.end_date = end_date @@ -97,28 +93,35 @@ def __init__(self, id, name, begin_date, end_date, num_test, register_date, stat class APU(db.Model, CRUD): __tablename__ = 'apu' - number = db.Column(db.Integer, primary_key=True) + id = db.Column(db.Integer, primary_key=True) - def __init__(self, number): - self.number = number + def __init__(self, id): + self.id = id class APUConfig(db.Model, CRUD): __tablename__ = 'apuconfig' id = db.Column(db.Integer, primary_key=True) + apu = db.Column(db.Integer, db.ForeignKey('apuconfig.id')) + ip = db.Column(db.String(40)) + protocol = db.Column(db.String(50)) + base_template = db.Column(db.Integer) + def __init__(self, apu, ip, protocol, base_template): + self.apu = apu + self.ip = ip + self.protocol = protocol + base_template = base_template class APUConfig_Template(db.Model, CRUD): __tablename__ = 'apuconfig_template' id_nonexistent = db.Column(db.Integer, primary_key=True) - apu = db.Column(db.Integer, db.ForeignKey('apu.number')) apu_config = db.Column(db.Integer, db.ForeignKey('apuconfig.id')) template = db.Column(db.Integer, db.ForeignKey('template.id')) - def __init__(self, apu, apu_config, template): - self.apu = apu + def __init__(self, apu_config, template): self.apu_config = apu_config self.template = template @@ -135,7 +138,7 @@ class Meta: class TemplateSchema(Schema): class Meta: - fields = ('Template', 'id', 'name', 'protocol', 'duration', 'profile') + fields = ('Template', 'id', 'name', 'duration', 'profile') class ExperienceSchema(Schema): @@ -145,17 +148,21 @@ class Meta: class APUSchema(Schema): class Meta: - fields = ('number',) + fields = ('id',) class APUConfigSchema(Schema): class Meta: - fields = ('id',) + fields = ('id', 'apu', 'ip', 'protocol', 'base_template') class APUConfig_TemplateSchema(Schema): class Meta: - fields = ('apu', 'apu_config', 'template') + fields = ('apu_config', 'template') + +class ExperienceAPUConfig_TemplateSchema(Schema): + class Meta: + fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template') diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 6a8534c..600cad4 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -1,11 +1,37 @@ from dotenv import load_dotenv import os -load_dotenv() -HOST = os.getenv('DB_HOST') -NAME = os.getenv('DB_NAME') -PASS = os.getenv('DB_PASS') -USER = os.getenv('DB_USER') +pg_db_hostname = os.getenv('DB_HOST') +pg_db_name = os.getenv('DB_NAME') +pg_db_password = os.getenv('DB_PASS') +pg_db_username = os.getenv('DB_USER') + +DEBUG = True +PORT = 5001 +HOST = "127.0.0.1" +SQLALCHEMY_ECHO = True +SQLALCHEMY_TRACK_MODIFICATIONS = True +SECRET_KEY = "SOME SECRET" +# PostgreSQL +SQLALCHEMY_DATABASE_URI = "postgresql://{DB_USER}:{DB_PASS}@{DB_ADDR}/{DB_NAME}".format(DB_USER=pg_db_username, + DB_PASS=pg_db_password, + DB_ADDR=pg_db_hostname, + DB_NAME=pg_db_name) + + +SQLALCHEMY_TRACK_MODIFICATONS = False +"""" +CERT = b-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv +vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc +aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy +tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0 +e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb +V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9 +MwIDAQAB +-----END PUBLIC KEY----- +""" + CERT = b'-----BEGIN PUBLIC KEY-----\n' \ b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlc6LMgsz5b2m2Q3M/ps2\n' \ b'XRKIuBRdwOUrY532F9OmkYrrdPsVpDpWTjRsc3Srrc9hUCIWNMQa++Cjq4yMFTHl\n' \ @@ -14,4 +40,16 @@ b'sUF+Rfny1t79PQJC6uk0FwnloEQVj5yYvmwAv8HTda0mhFY0GdYqNk5+ks0D3hGg\n' \ b'3D7FspI98MOX1lUatEJDq6/xE0JlK111uh24i7aZaZD5Bn3dqZl83zK4PdexXE/z\n' \ b'JwIDAQAB\n' \ - b'-----END PUBLIC KEY-----' \ No newline at end of file + b'-----END PUBLIC KEY-----' +""" + +# JWT Decode Algorithm +JWT_SECRET_KEY = CERT + +JWT_DECODE_ALGORITHMS = ['RS256'] +# JWT Decode CERT + +# JWT Identifier +JWT_IDENTITY_CLAIM = 'email' + + diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 58e3e90..1dd74e7 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -1,15 +1,19 @@ from flask_jwt_extended import jwt_required, get_raw_jwt, get_jti - +from _datetime import datetime, timedelta from models import * from flask import Blueprint, request, jsonify, make_response -from flask_restful import Api, Resource +from flask_restful import Api, Resource, reqparse +from flask_api import status from sqlalchemy.exc import SQLAlchemyError from marshmallow import ValidationError +# COnfig Files schema_blueprint = Blueprint('amazing', __name__) api = Api(schema_blueprint) +# Schema Config + role_schema = RoleSchema() profile_schema = ProfileSchema() template_schema = TemplateSchema() @@ -18,128 +22,261 @@ apuconfig_schema = APUConfigSchema() apuconfig_template_schema = APUConfig_TemplateSchema() +# Parse definition +parser = reqparse.RequestParser() +# users +parser.add_argument('typeID') +parser.add_argument('email') -def retrieve_id(email): - # email = get_raw_jwt()['jti'] - users_query = Profile.query.filter_by(email=email) - results = profile_schema.dump(users_query, many=True) - if results: - return results[0]['id'] - return +# Users and Experience +parser.add_argument('content') -email = 'j.brito@ua.pt' +# Experience +parser.add_argument('userID') +parser.add_argument('date') +parser.add_argument('begin_date') +parser.add_argument('end_date') +parser.add_argument('status') -class ProfileSingle(Resource): - #@jwt_required - def get(self): - header = request.headers - #email = get_raw_jwt()['jti'] +# BASE Functions - users_query = Profile.query.filter_by(email=email) - results = profile_schema.dump(users_query, many=True) +def get_user_by_email(email): + users_query = db.session().query(Profile).filter(Profile.email == email).one() + results = profile_schema.dump(users_query) + print(results) + if results: + return results + return + + +class UserView(Resource): + @jwt_required + def get(self, *filters): + parse_data = parser.parse_args() + raw_data = get_raw_jwt() + if not raw_data['isAdmin']: + results = jsonify() + results.status_code = status.HTTP_401_UNAUTHORIZED + return results + users_query = db.session().query(Profile) + + if parse_data['typeID']: + users_query = users_query.filter(Profile.role == parse_data['typeID']) + if parse_data['email']: + users_query = users_query.filter(Profile.email == parse_data['email']) + if parse_data['content']: + users_query = users_query.filter(Profile.name.contains(parse_data['content'])) + + results = profile_schema.dump(users_query.all(), many=True) return results - #@jwt_required + @jwt_required def post(self): + if not get_raw_jwt()['isAdmin']: + results = jsonify() + results.status_code = status.HTTP_401_UNAUTHORIZED + return results raw_dict = request.get_json(force=True) try: - profile_schema.validate(raw_dict) - d_profile = raw_dict['data']['attributes'] - profile = Profile(d_profile['name'], d_profile['email'], d_profile['num_testes'], d_profile['register_date'], d_profile['picture'], d_profile['last_login'], d_profile['role']) + message = raw_dict['message'] + profile = Profile(name=message['name'], email=message['email'], role=message['role'], num_testes=0, + register_date=datetime.datetime.now()) profile.add(profile) - query = profile_schema.query.get(profile.id) - results = profile_schema.dump(query).data + results = profile_schema.dump(profile) return results, 201 except ValidationError as err: resp = jsonify({"error": err.messages}) - resp.status_code = 403 + resp.status_code = status.HTTP_403_FORBIDDEN return resp except SQLAlchemyError as e: db.session.rollback() resp = jsonify({"error": str(e)}) - resp.status_code = 403 + resp.status_code = status.HTTP_400_BAD_REQUEST return resp - def put(self): - # email = get_raw_jwt()['jti'] - user_id = retrieve_id(email) - if not user_id: +class UserInfoView(Resource): + @jwt_required + def get(self, id): + if not get_raw_jwt()['isAdmin']: + results = jsonify() + results.status_code = status.HTTP_401_UNAUTHORIZED + return results + user_query = db.session.query(Profile).query.get_or_404(id) + user = profile_schema.dump(user_query) + return user + + @jwt_required + def put(self, id): + jwt_data = get_raw_jwt() + if not jwt_data['isAdmin']: + results = jsonify() + results.status_code = status.HTTP_401_UNAUTHORIZED + return results + + raw_dict = request.get_json(force=True) + users_schema = db.session.query(Profile).query.get_or_404(id) + user = profile_schema.dump(users_schema) + if not user: resp = jsonify({"error": 'Non-existent user'}) resp.status_code = 403 return resp - - raw_dict = request.get_json(force=True) try: - profile = profile_schema.query.get(user_id) - profile_schema.validate(raw_dict) - d_profile = raw_dict['data']['attributes'] + message = raw_dict['data']['message'] + user['role'] = message['role'] + return user, status.HTTP_200_OK - profile['name'], profile['email'], profile['num_testes'], profile['register_date'], profile['picture'], profile['last_login'], profile['role'] = d_profile['name'], d_profile['email'], d_profile['num_testes'], d_profile['register_date'], d_profile['picture'], d_profile['last_login'], d_profile['role'] - - profile.update(profile) - results = profile - return results, 201 - - except ValidationError as err: - resp = jsonify({"error": err.messages}) - resp.status_code = 403 - return resp except SQLAlchemyError as e: db.session.rollback() resp = jsonify({"error": str(e)}) - resp.status_code = 403 + resp.status_code = status.HTTP_401_UNAUTHORIZED return resp - def delete(self): - #email = get_raw_jwt()['jti'] - user_id = retrieve_id(email) + +""" + @jwt_required + def delete(self, id): + email = get_raw_jwt()['jti'] + user_id = get_email_by_id(email)['id'] if not user_id: resp = jsonify({"error": 'Non-existent user'}) resp.status_code = 403 return resp + user = Profile.query.get_or_404(user_id) try: - profile = profile_schema.query.get(user_id) - - profile.delete(profile) - results = {profile} - return results, 200 - - except ValidationError as err: - resp = jsonify({"error": err.messages}) - resp.status_code = 403 - return resp + delete = user.delete(user) + response = make_response() + response.status_code = 204 + return response except SQLAlchemyError as e: db.session.rollback() resp = jsonify({"error": str(e)}) - resp.status_code = 403 + resp.status_code = status.HTTP_401_UNAUTHORIZED return resp -class RoleList(Resource): +""" + + +class ProfileView(Resource): + @jwt_required + def get(self): + email = get_raw_jwt()['email'] + users_query = db.session(Profile).query.filter_by(email=email) + results = profile_schema.dump(users_query, many=True) + return results + + +class RoleView(Resource): def get(self): - role_query = Role.query.all() - print("ROLE QUERYY ", role_query) + role_query = db.session.query(Role).all() results = profile_schema.dump(role_query, many=True) return results -class ExperienceList(Resource): +class ExperienceView(Resource): + @jwt_required def get(self): - #email = get_raw_jwt()['jti'] - user_id = retrieve_id(email) - experiences = Experience.query.filter_by(profile=user_id) - results = experience_schema.dump(experiences, many=True) + parse_data = parser.parse_args() + raw_data = get_raw_jwt() + experiences_query = db.session.query(Experience) + # Apply filters + if raw_data['isAdmin']: + if parse_data['userID']: + experiences_query = experiences_query.filter(Experience.profile == parse_data['userID']) + else: + email = parse_data['email'] + user_id = get_user_by_email(email)['id'] + experiences_query = experiences_query.filter(Experience.profile == user_id) + + if parse_data['date']: + date = datetime.strptime(parse_data['date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.begin_date >= date >= Experience.end_date) + else: + if parse_data['begin_date']: + date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.begin_date >= date) + if parse_data['end_date']: + date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.end_date <= date) + if parse_data['status']: + experiences_query = experiences_query.filter(Experience.status == parse_data['status']) + + results = experience_schema.dump(experiences_query.all(), many=True) return results + @jwt_required + def post(self): + raw_data = get_raw_jwt() + email = raw_data['email'] + print("here") + user_id = get_user_by_email(email)['id'] + print("there") + print(request) + raw_dict = request.get_json(force=True) + print(raw_dict) + try: + message = raw_dict['message'] + print(message) + begin_date = datetime.strptime(message['begin_date'], "%Y-%m-%d %H:%M:%S") + template = db.session.query(Template).get(message['template']) + print(template.duration) + total_duration = message['num_test'] * (template.duration + 60) # 1 min for test setup + + print(begin_date) + print(template) + print(total_duration) + + experience = Experience(name=message['name'], + begin_date=begin_date, + num_test=message['num_test'], + end_date=begin_date + timedelta(0, total_duration), + status='SCHEDULED', + profile=user_id, + template=message['template'], + register_date=datetime.now()) + + print(experience) + experience.add(experience) + + return experience_schema.dump(experience), status.HTTP_201_CREATED + + except ValidationError as err: + resp = jsonify({"error": err.messages}) + resp.status_code = status.HTTP_403_FORBIDDEN + return resp + except SQLAlchemyError as e: + db.session.rollback() + resp = jsonify({"error": str(e)}) + resp.status_code = status.HTTP_400_BAD_REQUEST + return resp + +class ExperienceInfoView(Resource): + + @jwt_required + def get(self, id): + claims = get_raw_jwt() + user_id = get_user_by_email(claims['email']) + query = db.session.query(Experience, Template).filter(Experience.id==id).filter(Experience.template == Template.id).one() + experience = experience_schema.dump(query[0]) + template = template_schema.dump(query[1]) + if not claims['isAdmin'] and experience.profile != user_id: + results = jsonify() + results.status_code = status.HTTP_401_UNAUTHORIZED + results = make_response({"experience": experience, "template": template}) + results.status_code = status.HTTP_200_OK + return results -api.add_resource(ProfileSingle, '/user') -api.add_resource(RoleList, '/role') -api.add_resource(ExperienceList, '/experience') \ No newline at end of file +api.add_resource(UserView, '/user') +api.add_resource(UserInfoView, '/user/') +api.add_resource(RoleView, '/role') +api.add_resource(ProfileView, '/profile') +api.add_resource(ExperienceView, '/experience') +api.add_resource(ExperienceInfoView, '/experience/') From 0008fb05e8755641170c0600de3231b2aa621e01 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sun, 26 Apr 2020 16:08:48 +0100 Subject: [PATCH 07/22] fixed commented line --- FlaskAPI/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 600cad4..2aca29f 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -41,7 +41,7 @@ b'3D7FspI98MOX1lUatEJDq6/xE0JlK111uh24i7aZaZD5Bn3dqZl83zK4PdexXE/z\n' \ b'JwIDAQAB\n' \ b'-----END PUBLIC KEY-----' -""" + # JWT Decode Algorithm JWT_SECRET_KEY = CERT From f7915f4f4ddf8dfc7618c806cb94438af41a2199 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sun, 26 Apr 2020 17:42:34 +0100 Subject: [PATCH 08/22] Profile and user PUT back online --- FlaskAPI/views.py | 55 ++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 1dd74e7..953cf68 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -44,12 +44,18 @@ def get_user_by_email(email): users_query = db.session().query(Profile).filter(Profile.email == email).one() results = profile_schema.dump(users_query) - print(results) if results: return results return +class RoleView(Resource): + def get(self): + role_query = db.session.query(Role).all() + results = profile_schema.dump(role_query, many=True) + return results + + class UserView(Resource): @jwt_required def get(self, *filters): @@ -118,24 +124,13 @@ def put(self, id): return results raw_dict = request.get_json(force=True) - users_schema = db.session.query(Profile).query.get_or_404(id) - user = profile_schema.dump(users_schema) - if not user: - resp = jsonify({"error": 'Non-existent user'}) - resp.status_code = 403 - return resp - try: - message = raw_dict['data']['message'] - user['role'] = message['role'] - return user, status.HTTP_200_OK - - - except SQLAlchemyError as e: - db.session.rollback() - resp = jsonify({"error": str(e)}) - resp.status_code = status.HTTP_401_UNAUTHORIZED - return resp + message = raw_dict['message'] + profile = db.session.query(Profile).get(id) + profile.name = message['name'] + profile.email = email=message['email'] + profile.role = message['role'] + return profile """ @jwt_required @@ -172,12 +167,15 @@ def get(self): results = profile_schema.dump(users_query, many=True) return results + def put(self): + email = get_raw_jwt()['email'] -class RoleView(Resource): - def get(self): - role_query = db.session.query(Role).all() - results = profile_schema.dump(role_query, many=True) - return results + user = users_query = db.session().query(Profile).filter(Profile.email == email).one() + message = request.get_json(force=True)['message'] + user.picture = message['picture'] + user.name = message['name'] + user.update(user) + return profile_schema.dump(user) class ExperienceView(Resource): @@ -215,24 +213,14 @@ def get(self): def post(self): raw_data = get_raw_jwt() email = raw_data['email'] - print("here") user_id = get_user_by_email(email)['id'] - print("there") - print(request) raw_dict = request.get_json(force=True) - print(raw_dict) try: message = raw_dict['message'] - print(message) begin_date = datetime.strptime(message['begin_date'], "%Y-%m-%d %H:%M:%S") template = db.session.query(Template).get(message['template']) - print(template.duration) total_duration = message['num_test'] * (template.duration + 60) # 1 min for test setup - print(begin_date) - print(template) - print(total_duration) - experience = Experience(name=message['name'], begin_date=begin_date, num_test=message['num_test'], @@ -242,7 +230,6 @@ def post(self): template=message['template'], register_date=datetime.now()) - print(experience) experience.add(experience) return experience_schema.dump(experience), status.HTTP_201_CREATED From 58f718678b267c4cadf8013cf277578706659af2 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sun, 26 Apr 2020 18:06:05 +0100 Subject: [PATCH 09/22] Update requirements --- FlaskAPI/requirements.txt | 31 +++++++++++++++++++++++-------- FlaskAPI/settings.py | 7 ++++--- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index 6dcb744..e38470e 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -1,8 +1,23 @@ -Flask -Flask-Cors -flask-jwt-extended -python-dotenv -eventlet -gunicorn -pyjwt[crypto] -Flask-API \ No newline at end of file +alembic==1.4.2 +aniso8601==8.0.0 +Flask==1.1.2 +Flask-Migrate==2.5.3 +Flask-RESTful==0.3.8 +Flask-Script==2.0.6 +Flask-SQLAlchemy==2.4.1 +flask-marshmallow==0.11.0 +flask-jwt-extended== 3.24.1 +marshmallow-sqlalchemy==0.22.3 +itsdangerous== 1.1.0 +Jinja2==2.11.2 +Mako==1.1.2 +MarkupSafe==1.1.1 +marshmallow==3.5.1 +marshmallow-jsonapi==0.23.1 +psycopg2==2.8.5 +python-dateutil==2.8.1 +python-editor==1.0.4 +pytz==2019.3 +six==1.14.0 +SQLAlchemy==1.3.16 +Werkzeug==1.0.1 \ No newline at end of file diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 2aca29f..114953c 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -7,7 +7,7 @@ pg_db_username = os.getenv('DB_USER') DEBUG = True -PORT = 5001 +PORT = 5000 HOST = "127.0.0.1" SQLALCHEMY_ECHO = True SQLALCHEMY_TRACK_MODIFICATIONS = True @@ -20,7 +20,7 @@ SQLALCHEMY_TRACK_MODIFICATONS = False -"""" +""" CERT = b-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc @@ -32,6 +32,7 @@ -----END PUBLIC KEY----- """ + CERT = b'-----BEGIN PUBLIC KEY-----\n' \ b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlc6LMgsz5b2m2Q3M/ps2\n' \ b'XRKIuBRdwOUrY532F9OmkYrrdPsVpDpWTjRsc3Srrc9hUCIWNMQa++Cjq4yMFTHl\n' \ @@ -42,7 +43,7 @@ b'JwIDAQAB\n' \ b'-----END PUBLIC KEY-----' - +#""" # JWT Decode Algorithm JWT_SECRET_KEY = CERT From 40356c54ca4bffa5edc4e1f8790746e9d037b8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o?= Date: Sun, 26 Apr 2020 19:19:42 +0100 Subject: [PATCH 10/22] Presentation Ready --- FlaskAPI/__pycache__/models.cpython-36.pyc | Bin 0 -> 7442 bytes FlaskAPI/__pycache__/settings.cpython-36.pyc | Bin 0 -> 1237 bytes FlaskAPI/__pycache__/views.cpython-36.pyc | Bin 0 -> 7102 bytes FlaskAPI/app.py | 25 ++++++++++++++++ FlaskAPI/requirements.txt | 29 ++++++++++++++----- FlaskAPI/settings.py | 2 +- FlaskAPI/views.py | 2 ++ 7 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 FlaskAPI/__pycache__/models.cpython-36.pyc create mode 100644 FlaskAPI/__pycache__/settings.cpython-36.pyc create mode 100644 FlaskAPI/__pycache__/views.cpython-36.pyc diff --git a/FlaskAPI/__pycache__/models.cpython-36.pyc b/FlaskAPI/__pycache__/models.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68964566ce7e21c3fc6d23c73eba2c710ae29235 GIT binary patch literal 7442 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 CwJcl! literal 0 HcmV?d00001 diff --git a/FlaskAPI/__pycache__/settings.cpython-36.pyc b/FlaskAPI/__pycache__/settings.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5469bde516b5587dfef72a1051d40701fa1b8ffe GIT binary patch literal 1237 zcmZ9L$!_CD5Qa&bl5Kh$&tx#C1U|+PG884tk_JICO|m6X5=n`RW%XeQ+Rf3%MIt3@ z2@C|tC6_!#4nf``FOWNP%qg#sQ%E`qjOjubzUrS{ETF5(CnwCWzyJK`*LQgHG_#^wimR@(%6f@bOPHI>RUE1wKXR&N+IC&qgGAgJ|5Jl}VQ`4V3UeaMMDJP^8m(`H!;a(Co zqTfh@_$pmIY)Z;S&*Zz3aM6Lo?2wTqiI=88;YYK@cs6O)*F_%mVFLhF0R0+Bbz#&= z7y|eHx+{;OUFELimHK6woku0+R_jPBUc+nE42P9+sZm$G*)R-oFS?nF^MNtdqWiKQ zhWGWcDM$lF?%RceFkM`2<%ZF68L>R{Ya4FXYWr$I9IUI6)P5Log<5Ze2FQ=xTeCH7 zXsgx6RLoXoz1dcFtiT!9w!DzkdYM_?wwGIOQSx^;cu;SuN)brKpw}AfxYxGbyNyuw z0uFAFW>@rJIN={^8>b4jD~D5@yK;w#%tk@`=x@1YwchKuh3nO<*jW2+0Q)!7%69nR zt-(XBWnjDLjT^&a6Au^4tWuaoMX@|?j+nAoZA5daUX#^Z&Nb~NY>SI)b_0uTx5IJV zYFxUSRBdD^?2c)#B@y%i&t#7R74g$|igTJ?s$9o8$FnEy zCpXvQB=n5?;4=pIP)cA{M2ZjcOjwP$2)Q|*VNUEa8%u^#^Sfo)?fL7$BIrgTLyD>K4ERo-c9_GHJU70 zAlo}hX|fI1j%J`Iv5~V}CSvqh($ literal 0 HcmV?d00001 diff --git a/FlaskAPI/__pycache__/views.cpython-36.pyc b/FlaskAPI/__pycache__/views.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a506396f0948131c901ae5992b125c213e7df425 GIT binary patch literal 7102 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 XpY4_#Hyd{v') +def node_info(nodeID): + r = requests.get('192.168.1.141') + if r.status_code == 200: + msg = {'msg': 'Erro 200'} + return msg + return jsonify(r.json()) + +@app.route('/node/') +def nodeInfo(nodeID): + return jsonify( + {'id': 1, 'placas': 2, 'ips': ['192.168.1.141', '192.168.1.03'], + 'mac': ['00:0a:95:9d:68:16', '00:0a:95:9d:68:17'], + 'state': 0 + } + ) + + if __name__ == '__main__': app.run(host=app.config['HOST'], diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index 6dcb744..c704e33 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -1,8 +1,23 @@ -Flask -Flask-Cors +alembic==1.4.2 +aniso8601==8.0.0 +Flask==1.1.2 +Flask-Migrate==2.5.3 +Flask-RESTful==0.3.8 +Flask-Script==2.0.6 +Flask-SQLAlchemy==2.4.1 +flask-marshmallow==0.11.0 flask-jwt-extended -python-dotenv -eventlet -gunicorn -pyjwt[crypto] -Flask-API \ No newline at end of file +marshmallow-sqlalchemy==0.22.3 +itsdangerous== 1.1.0 +Jinja2==2.11.2 +Mako==1.1.2 +MarkupSafe==1.1.1 +marshmallow==3.5.1 +marshmallow-jsonapi==0.23.1 +psycopg2==2.8.5 +python-dateutil==2.8.1 +python-editor==1.0.4 +pytz==2019.3 +six==1.14.0 +SQLAlchemy==1.3.16 +Werkzeug==1.0.1 \ No newline at end of file diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 2aca29f..a210634 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -7,7 +7,7 @@ pg_db_username = os.getenv('DB_USER') DEBUG = True -PORT = 5001 +PORT = 5000 HOST = "127.0.0.1" SQLALCHEMY_ECHO = True SQLALCHEMY_TRACK_MODIFICATIONS = True diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 1dd74e7..908ba27 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -55,6 +55,7 @@ class UserView(Resource): def get(self, *filters): parse_data = parser.parse_args() raw_data = get_raw_jwt() + print("RAW ", raw_data) if not raw_data['isAdmin']: results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED @@ -69,6 +70,7 @@ def get(self, *filters): users_query = users_query.filter(Profile.name.contains(parse_data['content'])) results = profile_schema.dump(users_query.all(), many=True) + print("RESULTS ", results) return results @jwt_required From 1ab8f3df6b96881c46d316b32430c3996ac09650 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Sun, 26 Apr 2020 22:47:14 +0100 Subject: [PATCH 11/22] Updated picture data type --- FlaskAPI/models.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 119d782..73ad2e6 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -37,7 +37,7 @@ class Profile(db.Model, CRUD): email = db.Column(db.String(200), nullable=False, unique=True) num_testes = db.Column(db.INTEGER, nullable=True) register_date = db.Column(db.TIMESTAMP, nullable=False) - picture = db.Column(db.LargeBinary, nullable=True) + picture = db.Column(db.String(10485760), nullable=True) last_login = db.Column(db.TIMESTAMP, nullable=True) role = db.Column(db.Integer, db.ForeignKey('role.id')) @@ -50,6 +50,9 @@ def __init__(self, name, email, register_date, role, num_testes=None, picture=N self.last_login = last_login self.role = role + def __repr__(self): + return + class Template(db.Model, CRUD): @@ -133,7 +136,7 @@ class Meta: class ProfileSchema(Schema): class Meta: - fields = ('id', 'name', 'email', 'num_testes', 'register_date', 'picture', 'last_login', 'role') + fields = ('id', 'name', 'email', 'num_test', 'register_date', 'picture', 'last_login', 'role') class TemplateSchema(Schema): From 735df73945531321a88b591cebcc52f05525a3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o?= Date: Sun, 26 Apr 2020 23:42:02 +0100 Subject: [PATCH 12/22] =?UTF-8?q?Sou=20bu=C3=A9=20fixe=20-=20Commits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FlaskAPI/requirements.txt | 9 +++++++- FlaskAPI/views.py | 43 +++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index e38470e..cf3ed1c 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -20,4 +20,11 @@ python-editor==1.0.4 pytz==2019.3 six==1.14.0 SQLAlchemy==1.3.16 -Werkzeug==1.0.1 \ No newline at end of file +Werkzeug==1.0.1 +Flask-Cors +python-dotenv +eventlet +gunicorn +pyjwt[crypto] +flask_api +requests \ No newline at end of file diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index e6fe3dd..61588db 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -5,6 +5,10 @@ from flask_restful import Api, Resource, reqparse from flask_api import status +from base64 import b64encode + +import ast + from sqlalchemy.exc import SQLAlchemyError from marshmallow import ValidationError @@ -87,11 +91,12 @@ def post(self): return results raw_dict = request.get_json(force=True) try: - message = raw_dict['message'] + message = raw_dict profile = Profile(name=message['name'], email=message['email'], role=message['role'], num_testes=0, - register_date=datetime.datetime.now()) + register_date=datetime.now()) profile.add(profile) results = profile_schema.dump(profile) + print("\n\n\n", results) return results, 201 except ValidationError as err: @@ -100,6 +105,7 @@ def post(self): return resp except SQLAlchemyError as e: + print("\n\n\n E", e) db.session.rollback() resp = jsonify({"error": str(e)}) resp.status_code = status.HTTP_400_BAD_REQUEST @@ -113,26 +119,29 @@ def get(self, id): results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results - user_query = db.session.query(Profile).query.get_or_404(id) + user_query = db.session.query(Profile).get_or_404(id) user = profile_schema.dump(user_query) return user @jwt_required def put(self, id): jwt_data = get_raw_jwt() + print("\n\n\nAQUI", jwt_data, "\n\n\n") if not jwt_data['isAdmin']: results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results raw_dict = request.get_json(force=True) - message = raw_dict['message'] + print("\n\n\nAQUI", raw_dict, "\n\n\n") + message = raw_dict['role'] profile = db.session.query(Profile).get(id) - profile.name = message['name'] - profile.email = email=message['email'] - profile.role = message['role'] - return profile + # profile.name = message['name'] + # profile.email = email=message['email'] + profile.role = message + db.session.commit() + return profile_schema.dump(profile) """ @jwt_required @@ -165,18 +174,26 @@ class ProfileView(Resource): @jwt_required def get(self): email = get_raw_jwt()['email'] - users_query = db.session(Profile).query.filter_by(email=email) - results = profile_schema.dump(users_query, many=True) + users_query = db.session.query(Profile).filter(Profile.email==email).one() + results = profile_schema.dump(users_query) return results + @jwt_required def put(self): email = get_raw_jwt()['email'] user = users_query = db.session().query(Profile).filter(Profile.email == email).one() - message = request.get_json(force=True)['message'] - user.picture = message['picture'] + message = request.get_json(force=True) + # message = request.data.decode("utf-8") + # message = ast.literal_eval(message) + print("\n\n\nMESSAGE", message) + if message['pic']: + # msg = bytes(message['pic'], 'utf-8') + # msg = b64encode(msg) + user.picture = message['pic'] user.name = message['name'] - user.update(user) + # user.update(user) + db.session.commit() return profile_schema.dump(user) From 6b7395049af3fbffa0eaa2313c17ac54c0519885 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 01:53:33 +0100 Subject: [PATCH 13/22] Author added to Experience returns, Startins to change the schema to serializer. --- FlaskAPI/models.py | 39 ++++++++++++++++++++++++++++++++--- FlaskAPI/requirements.txt | 3 ++- FlaskAPI/views.py | 43 ++++++++++++++++++++++++--------------- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 73ad2e6..2d7d820 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -28,6 +28,13 @@ class Role (db.Model, CRUD): def __init__(self, role_name): self.role_name = role_name + @property + def serializable(self): + return { + 'id': self.id, + 'role_name': self.role_name, + } + class Profile(db.Model, CRUD): @@ -51,7 +58,20 @@ def __init__(self, name, email, register_date, role, num_testes=None, picture=N self.role = role def __repr__(self): - return + return '') -api.add_resource(RoleView, '/role') -api.add_resource(ProfileView, '/profile') -api.add_resource(ExperienceView, '/experience') -api.add_resource(ExperienceInfoView, '/experience/') +api.add_resource(UserView, '/user', '/user/') +api.add_resource(UserInfoView, '/user/', '/user//') +api.add_resource(RoleView, '/role', '/role/') +api.add_resource(ProfileView, '/profile', '/profile/') +api.add_resource(ExperienceView, '/experience', '/experience/') +api.add_resource(ExperienceInfoView, '/experience/', '/experience//') + From f9afb6d4a53bd34738976798d61933c63e4f9655 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 02:29:52 +0100 Subject: [PATCH 14/22] Fix num_test --- FlaskAPI/models.py | 41 ++++++++++++++++++++++++++++++++++++----- FlaskAPI/settings.py | 8 ++++---- FlaskAPI/views.py | 16 +++------------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 2d7d820..e7199aa 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -42,16 +42,16 @@ class Profile(db.Model, CRUD): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) email = db.Column(db.String(200), nullable=False, unique=True) - num_testes = db.Column(db.INTEGER, nullable=True) + num_test = db.Column(db.INTEGER, nullable=True) register_date = db.Column(db.TIMESTAMP, nullable=False) picture = db.Column(db.String(10485760), nullable=True) last_login = db.Column(db.TIMESTAMP, nullable=True) role = db.Column(db.Integer, db.ForeignKey('role.id')) - def __init__(self, name, email, register_date, role, num_testes=None, picture=None, last_login=None): + def __init__(self, name, email, register_date, role, num_test=None, picture=None, last_login=None): self.name = name self.email = email - self.num_testes = num_testes + self.num_test = num_test self.register_date = register_date self.picture = picture self.last_login = last_login @@ -66,7 +66,7 @@ def serializable(self): "id": self.id, "name": self.name, "email": self.email, - "num_testes": self.num_testes, + "num_test": self.num_test, "register_date": self.register_date, "picture": self.picture, "last_login": self.last_login, @@ -88,6 +88,15 @@ def __init__(self, id, name, duration, profile): self.duration = duration self.profile = profile + @property + def serializable(self): + return { + "id": self.id, + "name": self.name, + "duration": self.duration, + "profile": self.profile + } + class Experience(db.Model, CRUD): @@ -134,6 +143,12 @@ class APU(db.Model, CRUD): def __init__(self, id): self.id = id + @property + def serializable(self): + return { + "id":self.id + } + class APUConfig(db.Model, CRUD): @@ -148,7 +163,16 @@ def __init__(self, apu, ip, protocol, base_template): self.apu = apu self.ip = ip self.protocol = protocol - base_template = base_template + self.base_template = base_template + + def serializable(self): + return { + "id": self.id, + "apu": self.apu, + "ip": self.ip, + "protocol": self.protocol, + "base_template": self.base_template + } class APUConfig_Template(db.Model, CRUD): @@ -161,6 +185,13 @@ def __init__(self, apu_config, template): self.apu_config = apu_config self.template = template + @property + def serializable(self): + return { + "apu_config": self.apu_config, + "template": self.template + } + class RoleSchema(Schema): class Meta: diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index 114953c..e5f0c74 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -20,8 +20,8 @@ SQLALCHEMY_TRACK_MODIFICATONS = False -""" -CERT = b-----BEGIN PUBLIC KEY----- + +CERT = b"""-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy @@ -32,7 +32,7 @@ -----END PUBLIC KEY----- """ - +""" CERT = b'-----BEGIN PUBLIC KEY-----\n' \ b'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlc6LMgsz5b2m2Q3M/ps2\n' \ b'XRKIuBRdwOUrY532F9OmkYrrdPsVpDpWTjRsc3Srrc9hUCIWNMQa++Cjq4yMFTHl\n' \ @@ -43,7 +43,7 @@ b'JwIDAQAB\n' \ b'-----END PUBLIC KEY-----' -#""" +""" # JWT Decode Algorithm JWT_SECRET_KEY = CERT diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 56e52b7..770d5e1 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -19,15 +19,6 @@ schema_blueprint = Blueprint('amazing', __name__) api = Api(schema_blueprint) -# Schema Config - -role_schema = RoleSchema() -profile_schema = ProfileSchema() -template_schema = TemplateSchema() -experience_schema = ExperienceSchema() -apu_schema = APUSchema() -apuconfig_schema = APUConfigSchema() -apuconfig_template_schema = APUConfig_TemplateSchema() # Parse definition parser = reqparse.RequestParser() @@ -50,7 +41,7 @@ def get_user_by_email(email): users_query = db.session().query(Profile).filter(Profile.email == email).one() - results = profile_schema.dump(users_query) + results = jsonify(users_query.seriable) if results: return results return @@ -59,7 +50,7 @@ def get_user_by_email(email): class RoleView(Resource): def get(self): role_query = db.session.query(Role).all() - results = profile_schema.dump(role_query, many=True) + results = jsonify([role.serializable for role in role_query.all()]) return results @@ -95,7 +86,7 @@ def post(self): raw_dict = request.get_json(force=True) try: message = raw_dict - profile = Profile(name=message['name'], email=message['email'], role=message['role'], num_testes=0, + profile = Profile(name=message['name'], email=message['email'], role=message['role'], num_test=0, register_date=datetime.now()) profile.add(profile) results = profile_schema.dump(profile) @@ -233,7 +224,6 @@ def get(self): for experience, profile in q: experience = experience.serializable profile = profile.serializable - print(experience, profile) experience['author'] = profile['name'] response.append(experience) return jsonify(response) From 46110cdfddb255462bed91acf46e0796e633c5c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o?= Date: Mon, 27 Apr 2020 03:35:45 +0100 Subject: [PATCH 15/22] Working --- FlaskAPI/__pycache__/models.cpython-36.pyc | Bin 7442 -> 7556 bytes FlaskAPI/__pycache__/settings.cpython-36.pyc | Bin 1237 -> 1241 bytes FlaskAPI/__pycache__/views.cpython-36.pyc | Bin 7102 -> 7267 bytes FlaskAPI/app.py | 29 +++++++++---------- FlaskAPI/models.py | 2 +- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/FlaskAPI/__pycache__/models.cpython-36.pyc b/FlaskAPI/__pycache__/models.cpython-36.pyc index 68964566ce7e21c3fc6d23c73eba2c710ae29235..644f2c9a380aa6e3d864c9c9474e2aec3e5458ab 100644 GIT binary patch delta 1440 zcmcIjOH31C5Z-@jYu^w0eh{HVuxeV~QC_iv1yl-ZObCe-WY>sD+x*2uIp_g6XcWca z00)SX1mnpV^sb2)4L1{SVvIL0#=9}j>=xV@8c(*F@BjDv=AW6J`S(%lT$`=YW;6d{ z8zax$g76iR0q=|GqF9?uT**zziR|@kZYt3&7bd53`9yvqljm|l&Q2#Tjg3#rS!wg5 zXe?tdVbER!D`pP_4J~~}$u!F(Q8L^YhaIx+svgZ&e0CO}4Y;}_^DLVchs!0WWR+}l zY}hT?CC8jF?2#Ul+zxLd zp6X17%Xyy3G?SNzAg~$dAkST%xF*L{5#H|`fo5YBi^FGY;6N08D$xo)1f!^9PUc}g zL|V~Avx!GxOc#U=;}6yZ%cclR!Yk95r3nx4dV*?L)K`QXaC;1`U`0?PIhhqB@CG`+ z$<0fwt`W7EiQ94E2MLZ6&@tXhaG0Qtpqii&R!x3(0n*m-SRD~1-PJ+fywaJcG268$|zdFfS}YV@^-~%z`o5oAnpiSI#A+Cf)jAgQNuXgbPR@+ z9Ew!+N2gsEHK3vsw>UYWKySCxN@}E4aJ!k7_n!J)g8Iv+>8c8~)=X+|9566}G5729ms`P!xFTfXH3SN6N10@Hk z&Rxl5(iHFy|K03MC9$+X8&75pK7vc zu8S*;{DwwL!}svRka9KX+vD_^arz`UU1FYswMdku@qYT@L!>4c^f){Lj|tK0)NB5_ E-|A%$DSb zR79Vepe9z)XuKH0&66fxO#BNx_>p+iv!0B;*)6y+Z9JLH{C4N}d-LARdvA83>t?5| zO%UvJFP|KlU9~;u!qLdd>|`pEnaN})BmJq|>FMlLWGWp=PA1Q#GZW(z>FKrioVAQR zgY)J_5FKs^@*PpP%BlP{E+MAOrz|*x!rW7s^Z2e%ZS!QFOL$d5b*Rn-l8{vU0h8>4 z`+U#JXP%VHW$}1iu7pvS4Aa&oA>kNG(uq`WI+LVlA#V-AK|u=Dn@pxU961TW%9)8s zB;rHVABkK0X>}654OJS3hvijdCv3JSb)p#-?e*0ysC6(G&J7nLaT1B6E%3`4So>nX zMVebtlWo+6FS>=nHU`@n>|oHypp!wEL8}&OKfH1tmm`cQY2IvDGb98p?KqD?MyMt2 zEIK?D7RfQ_aE(=Vp)!Ue$0KM*A3H|_?Kg|F_BO=*C&&km!To=DrXs0jJPv6fL>gSt<7oMXI&3l1GcY!`M zm|^bh26vdvJ{YNZD_mp>#}q;p2-WzA0;7W86GQ5PL5rbvC*-~FJPNXx4T@nEh&5*6 zl0h5LR{fAhTUb?T9RsagdIR7zE?a0(4LO>a-VurK65b z{?;}&bPv^H>DY_>T{!Gl;A0@=)$5N`T;^z@8P*e;FX3Sb`3JBZP(ZAn|8EI>Ts*pG u82J^0HVny{rCO~u*d3(ox>0sDC~IiS`jZZTBUq3B9WTU!4a5g$g8tvd>iBg4 diff --git a/FlaskAPI/__pycache__/settings.cpython-36.pyc b/FlaskAPI/__pycache__/settings.cpython-36.pyc index 5469bde516b5587dfef72a1051d40701fa1b8ffe..c22bfe5aad66ada5c67b9d2ebcec2dbed180871e 100644 GIT binary patch delta 70 zcmcc0d6SdVn3tD}@ygP;`x`j}S=62NGxBp&_47*e@^kfFQj4=o@(c6}GUE%1Qj1gb aO7xQwle1IvQYP231hVt7@USqku>b&9s1}C+ delta 66 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 XpY4_#Hyd{v') -def node_info(nodeID): - r = requests.get('192.168.1.141') - if r.status_code == 200: - msg = {'msg': 'Erro 200'} - return msg - return jsonify(r.json()) - @app.route('/node/') -def nodeInfo(nodeID): - return jsonify( - {'id': 1, 'placas': 2, 'ips': ['192.168.1.141', '192.168.1.03'], - 'mac': ['00:0a:95:9d:68:16', '00:0a:95:9d:68:17'], - 'state': 0 - } - ) +def node_info(nodeID): + if nodeID=='1': + r = requests.get('http://192.168.1.141:5000/testi') + if r.status_code != 200: + msg = {'msg': 'Erro 200'} + return msg + return jsonify(r.json()) + + if nodeID=='2': + r = requests.get('http://192.168.1.142:5000/testi') + if r.status_code != 200: + msg = {'msg': 'Erro 200'} + return msg + return jsonify(r.json()) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 73ad2e6..f66bae7 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -136,7 +136,7 @@ class Meta: class ProfileSchema(Schema): class Meta: - fields = ('id', 'name', 'email', 'num_test', 'register_date', 'picture', 'last_login', 'role') + fields = ('id', 'name', 'email', 'num_testes', 'register_date', 'picture', 'last_login', 'role') class TemplateSchema(Schema): From 39a89d592ea4cb7e975b69cabd3e759914626a1e Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 03:41:40 +0100 Subject: [PATCH 16/22] Finished to clean Schemas --- FlaskAPI/models.py | 13 +++---- FlaskAPI/views.py | 89 ++++++++++++++++++++-------------------------- 2 files changed, 46 insertions(+), 56 deletions(-) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 6fbe709..1909fbd 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -67,7 +67,7 @@ def serializable(self): "name": self.name, "email": self.email, "num_test": self.num_test, - "register_date": self.register_date, + "register_date": self.register_date.strftime("%Y-%m-%d %H:%M:%S"), "picture": self.picture, "last_login": self.last_login, "role": self.role @@ -118,7 +118,7 @@ def __init__(self, name, begin_date, end_date, num_test, register_date, status, self.num_test = num_test self.register_date = register_date self.status = status - self.profile = profile.serializable + self.profile = profile self.template = template @property @@ -126,10 +126,10 @@ def serializable(self): return { "id": self.id, "name": self.name, - "begin_date": self.begin_date, - "end_date": self.end_date, + "begin_date": self.begin_date.strftime("%Y-%m-%d %H:%M:%S"), + "end_date": self.end_date.strftime("%Y-%m-%d %H:%M:%S"), "num_test": self.num_test, - "register_date": self.register_date, + "register_date": self.register_date.strftime("%Y-%m-%d %H:%M:%S"), "status": self.status, "profile": self.profile, "template": self.template @@ -210,7 +210,8 @@ class Meta: class ExperienceSchema(Schema): class Meta: - fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template', 'name', 'email', 'num_test', 'register_date', 'picture', 'last_login', 'role') + fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template', + 'name', 'email', 'num_test', 'register_date', 'picture', 'last_login', 'role') class APUSchema(Schema): diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 770d5e1..e8247b0 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -41,29 +41,28 @@ def get_user_by_email(email): users_query = db.session().query(Profile).filter(Profile.email == email).one() - results = jsonify(users_query.seriable) - if results: - return results - return + return users_query.serializable + class RoleView(Resource): def get(self): role_query = db.session.query(Role).all() - results = jsonify([role.serializable for role in role_query.all()]) + results = jsonify([role.serializable for role in role_query]) return results class UserView(Resource): @jwt_required - def get(self, *filters): + def get(self): parse_data = parser.parse_args() - raw_data = get_raw_jwt() - print("RAW ", raw_data) - if not raw_data['isAdmin']: + print(parse_data) + jwt_data = get_raw_jwt() + if not jwt_data['isAdmin']: results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results + users_query = db.session().query(Profile) if parse_data['typeID']: @@ -73,8 +72,7 @@ def get(self, *filters): if parse_data['content']: users_query = users_query.filter(Profile.name.contains(parse_data['content'])) q = users_query.all() - #results = profile_schema.dump(q, many=True) - #print("RESULTS ", results) + print(q) return jsonify([result.serializable for result in q]) @jwt_required @@ -83,15 +81,13 @@ def post(self): results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results - raw_dict = request.get_json(force=True) + raw_data = request.get_json(force=True) try: - message = raw_dict + message = raw_data profile = Profile(name=message['name'], email=message['email'], role=message['role'], num_test=0, register_date=datetime.now()) profile.add(profile) - results = profile_schema.dump(profile) - print("\n\n\n", results) - return results, 201 + return profile.serializable, status.HTTP_201_CREATED except ValidationError as err: resp = jsonify({"error": err.messages}) @@ -99,7 +95,6 @@ def post(self): return resp except SQLAlchemyError as e: - print("\n\n\n E", e) db.session.rollback() resp = jsonify({"error": str(e)}) resp.status_code = status.HTTP_400_BAD_REQUEST @@ -113,29 +108,25 @@ def get(self, id): results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results - user_query = db.session.query(Profile).get_or_404(id) - user = profile_schema.dump(user_query) + user_query = db.session.query(Profile).get(id) + user = jsonify(user_query.serializable) return user @jwt_required def put(self, id): jwt_data = get_raw_jwt() - print("\n\n\nAQUI", jwt_data, "\n\n\n") if not jwt_data['isAdmin']: results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED return results - raw_dict = request.get_json(force=True) - print("\n\n\nAQUI", raw_dict, "\n\n\n") - message = raw_dict['role'] + raw_data = request.get_json(force=True) + message = raw_data['role'] profile = db.session.query(Profile).get(id) - # profile.name = message['name'] - # profile.email = email=message['email'] profile.role = message db.session.commit() - return profile_schema.dump(profile) + return jsonify(profile.serializable) """ @jwt_required @@ -169,35 +160,33 @@ class ProfileView(Resource): def get(self): email = get_raw_jwt()['email'] users_query = db.session.query(Profile).filter(Profile.email==email).one() - results = profile_schema.dump(users_query) - return results + results = users_query.serializable + return jsonify(results) @jwt_required def put(self): email = get_raw_jwt()['email'] user = users_query = db.session().query(Profile).filter(Profile.email == email).one() - message = request.get_json(force=True) - # message = request.data.decode("utf-8") - # message = ast.literal_eval(message) - print("\n\n\nMESSAGE", message) - if message['pic']: - # msg = bytes(message['pic'], 'utf-8') + raw_data = request.get_json(force=True) + + if raw_data['pic']: + # msg = bytes(raw_data['pic'], 'utf-8') # msg = b64encode(msg) - user.picture = message['pic'] - user.name = message['name'] + user.picture = raw_data['pic'] + user.name = raw_data['name'] # user.update(user) db.session.commit() - return profile_schema.dump(user) + return user.serializable class ExperienceView(Resource): @jwt_required def get(self): parse_data = parser.parse_args() - raw_data = get_raw_jwt() + jwt_data = get_raw_jwt() experiences_query = db.session.query(Experience, Profile) # Apply filters - if raw_data['isAdmin']: + if jwt_data['isAdmin']: if parse_data['userID']: experiences_query = experiences_query.filter(Experience.profile == parse_data['userID']) else: @@ -230,12 +219,12 @@ def get(self): @jwt_required def post(self): - raw_data = get_raw_jwt() - email = raw_data['email'] + jwt_data = get_raw_jwt() + email = jwt_data['email'] user_id = get_user_by_email(email)['id'] - raw_dict = request.get_json(force=True) + raw_data = request.get_json(force=True) try: - message = raw_dict['message'] + message = raw_data['message'] begin_date = datetime.strptime(message['begin_date'], "%Y-%m-%d %H:%M:%S") template = db.session.query(Template).get(message['template']) total_duration = message['num_test'] * (template.duration + 60) # 1 min for test setup @@ -250,8 +239,8 @@ def post(self): register_date=datetime.now()) experience.add(experience) - - return experience_schema.dump(experience), status.HTTP_201_CREATED + print(experience) + return experience.serializable, status.HTTP_201_CREATED except ValidationError as err: resp = jsonify({"error": err.messages}) @@ -268,12 +257,12 @@ class ExperienceInfoView(Resource): @jwt_required def get(self, id): - claims = get_raw_jwt() - user_id = get_user_by_email(claims['email']) + jwt_data = get_raw_jwt() + user_id = get_user_by_email(jwt_data['email'])['id'] query = db.session.query(Experience, Template).filter(Experience.id==id).filter(Experience.template == Template.id).one() - experience = experience_schema.dump(query[0]) - template = template_schema.dump(query[1]) - if not claims['isAdmin'] and experience.profile != user_id: + experience = query[0].serializable + template = query[1].serializable + if not jwt_data['isAdmin'] and experience.profile != user_id: results = jsonify() results.status_code = status.HTTP_401_UNAUTHORIZED results = make_response({"experience": experience, "template": template}) From 2d30d0717491bfe043aba95e3beb91c02f86eac0 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 12:19:28 +0100 Subject: [PATCH 17/22] Removed unesed libraries and imports --- FlaskAPI/models.py | 48 +-------------------------------------- FlaskAPI/requirements.txt | 34 +++++++-------------------- FlaskAPI/settings.py | 1 - FlaskAPI/views.py | 11 +-------- 4 files changed, 10 insertions(+), 84 deletions(-) diff --git a/FlaskAPI/models.py b/FlaskAPI/models.py index 1909fbd..45a651a 100644 --- a/FlaskAPI/models.py +++ b/FlaskAPI/models.py @@ -1,8 +1,5 @@ from flask_sqlalchemy import SQLAlchemy -from marshmallow import validate -from marshmallow_jsonapi import Schema, fields -from flask_marshmallow import Marshmallow -from marshmallow import Schema, fields, ValidationError, pre_load +from marshmallow import Schema db = SQLAlchemy() session = None @@ -191,46 +188,3 @@ def serializable(self): "apu_config": self.apu_config, "template": self.template } - - -class RoleSchema(Schema): - class Meta: - fields = ('id', 'role_name') - - -class ProfileSchema(Schema): - class Meta: - fields = ('id', 'name', 'email', 'num_testes', 'register_date', 'picture', 'last_login', 'role') - - -class TemplateSchema(Schema): - class Meta: - fields = ('Template', 'id', 'name', 'duration', 'profile') - - -class ExperienceSchema(Schema): - class Meta: - fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template', - 'name', 'email', 'num_test', 'register_date', 'picture', 'last_login', 'role') - - -class APUSchema(Schema): - class Meta: - fields = ('id',) - - -class APUConfigSchema(Schema): - class Meta: - fields = ('id', 'apu', 'ip', 'protocol', 'base_template') - - -class APUConfig_TemplateSchema(Schema): - class Meta: - fields = ('apu_config', 'template') - -class ExperienceAPUConfig_TemplateSchema(Schema): - class Meta: - fields = ('id', 'name', 'begin_date', 'end_date', 'num_test', 'register_date', 'status', 'profile', 'template') - - - diff --git a/FlaskAPI/requirements.txt b/FlaskAPI/requirements.txt index 52c5e07..612e60f 100644 --- a/FlaskAPI/requirements.txt +++ b/FlaskAPI/requirements.txt @@ -1,31 +1,13 @@ -alembic==1.4.2 -aniso8601==8.0.0 Flask==1.1.2 -Flask-Migrate==2.5.3 Flask-RESTful==0.3.8 -Flask-Script==2.0.6 -Flask-SQLAlchemy==2.4.1 -flask-marshmallow==0.11.0 flask-jwt-extended== 3.24.1 -marshmallow-sqlalchemy==0.22.3 -itsdangerous== 1.1.0 -Jinja2==2.11.2 -Mako==1.1.2 -MarkupSafe==1.1.1 +flask_api==2.0 marshmallow==3.5.1 -marshmallow-jsonapi==0.23.1 -psycopg2==2.8.5 -python-dateutil==2.8.1 -python-editor==1.0.4 -pytz==2019.3 -six==1.14.0 SQLAlchemy==1.3.16 -Werkzeug==1.0.1 -Flask-Cors -python-dotenv -eventlet -gunicorn -pyjwt[crypto] -flask_api -requests -PyJWT==1.6.1 \ No newline at end of file +Flask-Cors==3.0.8 +python-dotenv==0.13.0 +pyjwt[crypto]==1.7.1 +requests==2.23.0 +Flask-SQLAlchemy==2.4.1 +psycopg2==2.8.5 +PyJWT==1.7.1 \ No newline at end of file diff --git a/FlaskAPI/settings.py b/FlaskAPI/settings.py index e5f0c74..a571fbb 100644 --- a/FlaskAPI/settings.py +++ b/FlaskAPI/settings.py @@ -1,4 +1,3 @@ -from dotenv import load_dotenv import os pg_db_hostname = os.getenv('DB_HOST') diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index e8247b0..c13b448 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -1,17 +1,11 @@ from flask_jwt_extended import jwt_required, get_raw_jwt, get_jti from _datetime import datetime, timedelta -import json -from sqlalchemy.ext.declarative import DeclarativeMeta from models import * from flask import Blueprint, request, jsonify, make_response from flask_restful import Api, Resource, reqparse from flask_api import status -from base64 import b64encode - -import ast - from sqlalchemy.exc import SQLAlchemyError from marshmallow import ValidationError @@ -56,7 +50,6 @@ class UserView(Resource): @jwt_required def get(self): parse_data = parser.parse_args() - print(parse_data) jwt_data = get_raw_jwt() if not jwt_data['isAdmin']: results = jsonify() @@ -72,7 +65,6 @@ def get(self): if parse_data['content']: users_query = users_query.filter(Profile.name.contains(parse_data['content'])) q = users_query.all() - print(q) return jsonify([result.serializable for result in q]) @jwt_required @@ -126,7 +118,7 @@ def put(self, id): profile.role = message db.session.commit() - return jsonify(profile.serializable) + return profile.serializable """ @jwt_required @@ -239,7 +231,6 @@ def post(self): register_date=datetime.now()) experience.add(experience) - print(experience) return experience.serializable, status.HTTP_201_CREATED except ValidationError as err: From 4bc2d0a7039095b0d1c066636f34545de64f054d Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 13:44:37 +0100 Subject: [PATCH 18/22] Experience current added, small fix needed --- FlaskAPI/views.py | 50 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index c13b448..5193f17 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -9,7 +9,7 @@ from sqlalchemy.exc import SQLAlchemyError from marshmallow import ValidationError -# COnfig Files +# Config Files schema_blueprint = Blueprint('amazing', __name__) api = Api(schema_blueprint) @@ -162,11 +162,8 @@ def put(self): raw_data = request.get_json(force=True) if raw_data['pic']: - # msg = bytes(raw_data['pic'], 'utf-8') - # msg = b64encode(msg) user.picture = raw_data['pic'] user.name = raw_data['name'] - # user.update(user) db.session.commit() return user.serializable @@ -187,14 +184,14 @@ def get(self): experiences_query = experiences_query.filter(Experience.profile == user_id) if parse_data['date']: - date = datetime.strptime(parse_data['date'], "%Y-%m-%d").date() + date = datetime.strptime(parse_data['date'], "%Y-%m-%d %H:%M:%H").date() experiences_query = experiences_query.filter(Experience.begin_date >= date >= Experience.end_date) else: if parse_data['begin_date']: - date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d").date() + date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d %H:%M:%H").date() experiences_query = experiences_query.filter(Experience.begin_date >= date) if parse_data['end_date']: - date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d").date() + date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d %H:%M:%H").date() experiences_query = experiences_query.filter(Experience.end_date <= date) if parse_data['status']: experiences_query = experiences_query.filter(Experience.status == parse_data['status']) @@ -216,7 +213,7 @@ def post(self): user_id = get_user_by_email(email)['id'] raw_data = request.get_json(force=True) try: - message = raw_data['message'] + message = raw_data begin_date = datetime.strptime(message['begin_date'], "%Y-%m-%d %H:%M:%S") template = db.session.query(Template).get(message['template']) total_duration = message['num_test'] * (template.duration + 60) # 1 min for test setup @@ -260,10 +257,45 @@ def get(self, id): results.status_code = status.HTTP_200_OK return results +class ExperienceScheduleView(Resource): + def get(self): + + date_now = datetime.now() + #date_now = datetime.strptime("2020-06-30", "%Y-%m-%d").date() + print() + experience_schedule_query = db.session.query(Experience, Profile) \ + .filter(Experience.end_date >= date_now) \ + .filter(Experience.profile == Profile.id) \ + .order_by(Experience.begin_date.asc()) \ + .limit(2) \ + .all() + calendar = {'current_experience': None, 'next_experience': None} + print(experience_schedule_query) + print(len(experience_schedule_query)) + if len(experience_schedule_query) == 2: + calendar['current_experience'] = self.format_experience_calendar(experience_schedule_query[0]) + calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[1]) + + elif len(experience_schedule_query) == 1: + if datetime.strptime(experience_schedule_query[0][0].serializable['begin_date'], "%Y-%m-%d %H:%M:%S").date() < date_now: + calendar['current_experience'] = self.format_experience_calendar(experience_schedule_query[0]) + else: + calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[0]) + return calendar + + @staticmethod + def format_experience_calendar(experince_calendar_fragment): + experience = experince_calendar_fragment[0].serializable + profile = experince_calendar_fragment[1].serializable + experience['author'] = profile['name'] + experience['email'] = profile['email'] + return experience + + api.add_resource(UserView, '/user', '/user/') api.add_resource(UserInfoView, '/user/', '/user//') api.add_resource(RoleView, '/role', '/role/') api.add_resource(ProfileView, '/profile', '/profile/') api.add_resource(ExperienceView, '/experience', '/experience/') api.add_resource(ExperienceInfoView, '/experience/', '/experience//') - +api.add_resource(ExperienceScheduleView, '/experience/now', '/experience/now/') From 48b51fdc1560319147c02f5dec846af555868dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o?= Date: Mon, 27 Apr 2020 13:46:29 +0100 Subject: [PATCH 19/22] Views Settings --- FlaskAPI/__pycache__/models.cpython-36.pyc | Bin 7556 -> 9121 bytes FlaskAPI/__pycache__/settings.cpython-36.pyc | Bin 1241 -> 1241 bytes FlaskAPI/__pycache__/views.cpython-36.pyc | Bin 7267 -> 7418 bytes FlaskAPI/settings.py | 15 ++------------- FlaskAPI/views.py | 4 +++- 5 files changed, 5 insertions(+), 14 deletions(-) diff --git a/FlaskAPI/__pycache__/models.cpython-36.pyc b/FlaskAPI/__pycache__/models.cpython-36.pyc index 644f2c9a380aa6e3d864c9c9474e2aec3e5458ab..4e9ab10a80a89ffeb7aee8d716ea5fc3357bcff2 100644 GIT binary patch literal 9121 zcmbVS&2t<_6`z@%ot>TCl~&S9R{Rymu^cueQbG7CR|v8l*)fS0$9AYfB#f_>QC=L`HxpCmY0jhul9N@wn;1H@n{{RP0{C+(z(Ne!W^6Pl~p{{8{6M9$c>8`FbZ*+}b&dsTO zu50%4ZoX%^mZHsWp=Z0c%IDE;T-PhQ#h&9jy5{Nonp+ZVIy;iq7_-@^lCPt7{Wib2ouv=%) z-;i=31A9k$&F-Kj8g0%K{S0K*@%WdJc$%vV%{7EBjK`Xr6FFhxZHm0G@Xm_@__PD_ z`knXQY_lhSeDk@E$6rD+)VB3)V^7})dQ?8Quc4pbsGETy?gs_m^L_9Y3iL+z?Pmr*p+SXmzu0%wEtaQdwjR;Zm!+vw)}@zZ{J$$4TRVAS9c!CGRASp9_6FyWqo9G39FdD4Y;cx z-+a_E*f?B9#ClG$OqQ5bkkoZK!#r6GlR4x9Yj=mbVwJB1q>oB!s<8Y-LQ7^2EUd^I zdLai!$iZyPf#QX1$ORGgrs)6%$J+Z4|ZGKutteZ z&PU^=mYPgdL@giRLSpN-Y3C&A35-$d>v;S(kt7&%bDp`K$72aYVJ&(qrT63m8no}I4>l^ioqyXe16WU`?X*P%K zI#w%%5Lnj--Q8Y4DBS7~y$7CDOu)emWvBl@F(bKBx{bk(Cx?&Zd5)LBJ;A^!RB#@j z1KWnFSM{m^9I$)>2XTz~EozR617ZN!D8|?*?CU5qg#A&@b;hM7&}>y6)0J_rnYdRG zy}~xLahs5?j%f?;IpF|#hC46jMOjoH>+XV>5wq}pHE&T=#oS{J7+ex1XmKGZ+?Io_ z4q#Y-keC4y<#Slu!EGcr=)C*8-7ZCc@CTGY)i2=%C(-YGuJ^3Hg$1OcF>a z*F)62hQ}xHHQh@6jjCgTWt$A$gfbbzSLmV1z-+MY?c9D&8P4eZ>$^bvl?&hd{wo(Y zxVSJ&GhhxO#@ZUlUTY{5*42WtO$%l%y&c(XzK%H~vre%YR!&$p-J4>Qa)>NDViRxp zGy(609MrQ7_1^w$ybRx5wcoB zacaxJ_J?w7*y(vG#Y|tevgNOE#Z;aKM-u)y>OHDOYD)VRaNlUuPaX0tlI|!BP#2hc zfr(nrMdso~!Ot}AZQR_rqtFu+@7>zmxO?yF=Iszy@j?UV#z1v(*D#M`?H7RT;w_AWw0@F#{L9up-rdBAK$T8 zpim~f0{wxZd_XSp0cL`hz!tl*HN>7vuApZ<9~yUpyDyCj3^bJ~W4oHcz?9NV>s4U*X3X6f#-qiUyEJ|q^||9?H?XeV zx(Vb;C7{n^s!&P_luyUw7tnZmHN&#|Y!JJcK%g@+=eGo~XnMsySt zt#N%NLhchWGK{Q@qfv}xOswL(#+W#lLU~mno~k(Mh!Rk~;MG*TWOQ5Atdg=H!EeRYsb$yAE zQ{ie8{EWzR1?@aM6Oo5;CyYHc+Pov#D%qreC$!Wiw->Jz(E#Pf5cVM;52P74jFZo@L=oCgqLCNtU6khgCfLmebC?PJaCIpZ(C&}C6CH+5xnEUr@-O? zZLiJ1%OBsdRw$Hdelqfhro4()IFs(E1K)7a9(04s{g&_H*bwejqD=!E$_*wrnA~KN zaRm4o$|pAs^YN0hVZ<8*<=q$y(%ubuY;U$r>>Tn6R$xUTHiMO?RZZVR{DRC9y&6uh z;ooQ}VRsUa)g!}Exe~?XMGSpdXbP-Tx3kyK<0p7jsED?+bSPzRAXuA?*KeWbgm`7J zx5wL8U{!5jOI|tNzE;ND*F=%cXs6}Q$B2vpla1ENz@7uQ{PAtzQTivE(twRXY6K2u zX@<5SRXEOt;rJGMsDdmc{u-6zdoTpqGqGA@=Ck2QmJ~bmS`i#m7dSGW6kasRPY2m= zVm`1@9X+4H$0W{Xj({_FrX!mDLErn3hx-0dD#*p$93^_a1-5=g*2+jCpdn(Jk~M8S z@sA=|$K%sNBaq=PTiq551N%YT7{fx%z~Om3ysVxWfjU+rP{+{-!W{R@k7kp8tDD}i z71}wk$#7+s5I7|8jv%?>Qg_}d6oGjIL!%xdK-QJ zp6XBfgo2ojqh^LUo@L~Mrw%@WHt=!w2KaKU0f8Zuof@egBc_ zPx^$yTaMQsZ+$YPNF}dx!U<3%A^P03Q9^OXdk+Tem^dcd{>AxEh_*ZE`$?)l=@Sa< zV&d4QEqY?)BBomB)DxmB!5(?K4DyH~kN~t?<7bB*za*_8za3&%+{ zk~~Ao0uyeik`L$Vo3xwX|6Kp4e&F(cQRTw}sruiErU?nNY{s-)|dbX$_< zCkZLZ#bjB0V80%IPJe^$*?$E|8TY<8xarG=h12Csr8ZZ)TwAWK)Mk+`RP*Z3QmOfW DNeWGR delta 2353 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 Date: Mon, 27 Apr 2020 14:11:11 +0100 Subject: [PATCH 20/22] Experience/now working to return correct value --- FlaskAPI/views.py | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 5193f17..fbfb1cb 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -32,13 +32,11 @@ # BASE Functions - def get_user_by_email(email): users_query = db.session().query(Profile).filter(Profile.email == email).one() return users_query.serializable - class RoleView(Resource): def get(self): role_query = db.session.query(Role).all() @@ -184,15 +182,16 @@ def get(self): experiences_query = experiences_query.filter(Experience.profile == user_id) if parse_data['date']: - date = datetime.strptime(parse_data['date'], "%Y-%m-%d %H:%M:%H").date() - experiences_query = experiences_query.filter(Experience.begin_date >= date >= Experience.end_date) + date = datetime.strptime(parse_data['date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.begin_date >= date).filter(date >= Experience.end_date) + print("\n\n\n\n, experiences_query", experiences_query) else: if parse_data['begin_date']: - date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d %H:%M:%H").date() - experiences_query = experiences_query.filter(Experience.begin_date >= date) + date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.begin_date.date() >= date) if parse_data['end_date']: - date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d %H:%M:%H").date() - experiences_query = experiences_query.filter(Experience.end_date <= date) + date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d").date() + experiences_query = experiences_query.filter(Experience.end_date <= date.date()) if parse_data['status']: experiences_query = experiences_query.filter(Experience.status == parse_data['status']) if parse_data['content']: @@ -241,6 +240,7 @@ def post(self): resp.status_code = status.HTTP_400_BAD_REQUEST return resp + class ExperienceInfoView(Resource): @jwt_required @@ -257,27 +257,30 @@ def get(self, id): results.status_code = status.HTTP_200_OK return results + class ExperienceScheduleView(Resource): def get(self): date_now = datetime.now() - #date_now = datetime.strptime("2020-06-30", "%Y-%m-%d").date() - print() - experience_schedule_query = db.session.query(Experience, Profile) \ - .filter(Experience.end_date >= date_now) \ - .filter(Experience.profile == Profile.id) \ - .order_by(Experience.begin_date.asc()) \ - .limit(2) \ + experience_schedule_query = db.session.query(Experience, Profile)\ + .filter(Experience.end_date >= date_now)\ + .filter(Experience.profile == Profile.id)\ + .order_by(Experience.begin_date.asc())\ + .limit(2)\ .all() calendar = {'current_experience': None, 'next_experience': None} - print(experience_schedule_query) - print(len(experience_schedule_query)) + if len(experience_schedule_query) == 2: - calendar['current_experience'] = self.format_experience_calendar(experience_schedule_query[0]) - calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[1]) + if datetime.strptime(experience_schedule_query[0][0].serializable['begin_date'], + "%Y-%m-%d %H:%M:%S") < date_now: + calendar['current_experience'] = self.format_experience_calendar(experience_schedule_query[0]) + calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[1]) + else: + calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[0]) elif len(experience_schedule_query) == 1: - if datetime.strptime(experience_schedule_query[0][0].serializable['begin_date'], "%Y-%m-%d %H:%M:%S").date() < date_now: + if datetime.strptime(experience_schedule_query[0][0].serializable['begin_date'], + "%Y-%m-%d %H:%M:%S") < date_now: calendar['current_experience'] = self.format_experience_calendar(experience_schedule_query[0]) else: calendar['next_experience'] = self.format_experience_calendar(experience_schedule_query[0]) From 1d6de83b79e6afbee169c136030b5a4a4a973a8c Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Mon, 27 Apr 2020 14:55:07 +0100 Subject: [PATCH 21/22] Fixed Experience search filters --- FlaskAPI/views.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/FlaskAPI/views.py b/FlaskAPI/views.py index 5e4090c..f0ef71e 100644 --- a/FlaskAPI/views.py +++ b/FlaskAPI/views.py @@ -33,7 +33,6 @@ # BASE Functions def get_user_by_email(email): - print("\n\n\nEMAIL", email) users_query = db.session().query(Profile).filter(Profile.email == email).one() return users_query.serializable @@ -172,8 +171,7 @@ class ExperienceView(Resource): def get(self): parse_data = parser.parse_args() jwt_data = get_raw_jwt() - print("\n\n\n JWT ", jwt_data) - experiences_query = db.session.query(Experience, Profile) + experiences_query = db.session.query(Experience, Profile).filter(Experience.profile == Profile.id) # Apply filters if jwt_data['isAdmin']: if parse_data['userID']: @@ -184,21 +182,22 @@ def get(self): experiences_query = experiences_query.filter(Experience.profile == user_id) if parse_data['date']: - date = datetime.strptime(parse_data['date'], "%Y-%m-%d").date() - experiences_query = experiences_query.filter(Experience.begin_date >= date).filter(date >= Experience.end_date) - print("\n\n\n\n, experiences_query", experiences_query) + date_start = datetime.strptime(parse_data['date'], "%Y-%m-%d").date() + date_finish = date_start + timedelta(days=1) + experiences_query = experiences_query.filter(Experience.begin_date >= date_start).filter( date_finish >= Experience.end_date) + else: if parse_data['begin_date']: date = datetime.strptime(parse_data['begin_date'], "%Y-%m-%d").date() - experiences_query = experiences_query.filter(Experience.begin_date.date() >= date) + experiences_query = experiences_query.filter(Experience.begin_date >= date) if parse_data['end_date']: date = datetime.strptime(parse_data['end_date'], "%Y-%m-%d").date() - experiences_query = experiences_query.filter(Experience.end_date <= date.date()) + experiences_query = experiences_query.filter(Experience.end_date <= date) if parse_data['status']: experiences_query = experiences_query.filter(Experience.status == parse_data['status']) if parse_data['content']: experiences_query = experiences_query.filter(Experience.name.contains(parse_data['content'])) - q = experiences_query.join(Profile).filter(Experience.profile == Profile.id).all() + q = experiences_query.all() response = [] for experience, profile in q: experience = experience.serializable From 0c1f6b4b2b69a1012bf1271c5b450ba62ce2eb45 Mon Sep 17 00:00:00 2001 From: Rui Coelho Date: Tue, 28 Apr 2020 15:15:06 +0100 Subject: [PATCH 22/22] checkout frontend --- Frontend/Frontend/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Frontend/Frontend/urls.py b/Frontend/Frontend/urls.py index 2d6bdd3..48dd38e 100644 --- a/Frontend/Frontend/urls.py +++ b/Frontend/Frontend/urls.py @@ -22,5 +22,5 @@ path('admin/', admin.site.urls), path('', views.home, name='home'), path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), - path('logout/', auth_views.LogoutView.as_view(next_page='/'), name='logout'), + path('logout', auth_views.LogoutView.as_view(next_page='/'), name='logout'), ]