From 440ae44515c53cd030b9c95333f0589c878740d0 Mon Sep 17 00:00:00 2001 From: loorely Date: Sat, 15 Jun 2019 15:05:01 -0400 Subject: [PATCH 01/13] integration with raspberry pi --- aper/views.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aper/views.py b/aper/views.py index d8d2388..3678475 100644 --- a/aper/views.py +++ b/aper/views.py @@ -4,6 +4,8 @@ from .models import User from .db import db_session import datetime +from gpiozero import LED +from time import sleep @app.route('/') @@ -24,6 +26,11 @@ def users(): def open_gate(): allowed_users = User.allowed_users() if current_user in allowed_users: + controller=LED(17) + controller.on() + sleep(2) + controller.off() + sleep(2) return 'Open Sesame' else: return 'You cannot park inside today', 403 From 22a7a02104788e9d75a642a2d57f8c16b17147a3 Mon Sep 17 00:00:00 2001 From: Gabriela Gaona Date: Sat, 15 Jun 2019 15:08:10 -0400 Subject: [PATCH 02/13] Updated readme --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index 650d21c..d4c66c5 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,19 @@ Be sure to set the following parameters in the file you just created: - GOOGLE_CLIENT_ID: what you just got from google - SQLALCHEMY_DATABASE_URI: URI to your database +Install pipenv by following this tuto: https://pypi.org/project/pipenv/ + +Create database with sqlite command: +``` +$ sqlite3 test.db +>> .databases +``` +.databases should list the existing databases like this: +`` +main: /home/raspberry/porton/test.db +`` + + Having done that, we can install the app: ``` From b7429f87356d59c1071216f4562f78ffb05506f9 Mon Sep 17 00:00:00 2001 From: Gabriela Gaona Date: Sat, 15 Jun 2019 15:17:50 -0400 Subject: [PATCH 03/13] adding Rele connection --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d4c66c5..3b23ca9 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,6 @@ $ sqlite3 test.db main: /home/raspberry/porton/test.db `` - Having done that, we can install the app: ``` @@ -47,3 +46,8 @@ export FLASK_APP=aper flask db upgrade python run.py ``` + +## RaspberryPI connection +Pin 1 —> +3V -> Rele DC+ +Pin 9 —> GND -> Rele DC- +Pin 11 —> GPIO 17 -> Rele IN From bf8ff8c7fbd8367c35a56d452cd1b3419ab7d0d0 Mon Sep 17 00:00:00 2001 From: Verna Ojeda Date: Sat, 15 Jun 2019 15:37:54 -0400 Subject: [PATCH 04/13] Update users. Avatar added. --- aper/auth.py | 13 ++++++++----- aper/models.py | 9 ++++++--- aper/views.py | 12 +++++++++++- migrations/versions/26a6b4da8b01_.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 9 deletions(-) create mode 100644 migrations/versions/26a6b4da8b01_.py diff --git a/aper/auth.py b/aper/auth.py index 1e8678b..68b4b35 100644 --- a/aper/auth.py +++ b/aper/auth.py @@ -28,10 +28,10 @@ def load_user(request): try: # Specify the CLIENT_ID of the app that accesses the backend: - #idinfo = id_token.verify_oauth2_token(token, requests.Request(), - # app.config['GOOGLE_CLIENT_ID']) + idinfo = id_token.verify_oauth2_token(token, requests.Request(), + app.config['GOOGLE_CLIENT_ID']) - idinfo = json.loads(dummy_info) + # idinfo = json.loads(dummy_info) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) @@ -48,11 +48,14 @@ def load_user(request): # raise ValueError('Wrong hosted domain.') # ID token is valid. Get the user's Google Account ID from the decoded token. + # print(idinfo) user = User.query.filter(User.email == idinfo['email']).first() if not user: - user = User(idinfo['name'], idinfo['email']) + user = User(idinfo['name'], idinfo['email'], idinfo['picture']) db_session.add(user) - db_session.commit() + else: + user.avatar = idinfo['picture'] + db_session.commit() return user except ValueError: # Invalid token diff --git a/aper/models.py b/aper/models.py index 75800e3..c65f3f7 100644 --- a/aper/models.py +++ b/aper/models.py @@ -15,13 +15,15 @@ class User(UserMixin, Base): name = Column(String(100)) order = Column(Integer, nullable=False) absent_on = Column(Date) + avatar = Column(String(100)) - def __init__(self, name, email): + def __init__(self, name, email, avatar): self.email = email self.name = name max_order = db_session.query(func.max(User.order)).scalar() self.order = max_order + 1 if max_order else 1 self.absent_on = None + self.avatar = avatar def serialize(self): """Return object data in serializeable format""" @@ -30,7 +32,8 @@ def serialize(self): 'name': self.name, 'email': self.email, 'order': self.order, - 'absent_on': self.absent_on + 'absent_on': self.absent_on, + 'avatar': self.avatar } @classmethod @@ -44,4 +47,4 @@ def __repr__(self): return ''.format(self.name, self.email) def __eq__(self, value): - return self.id == value.id and self.name == value.name and self.order == value.order and self.absent_on == value.absent_on + return self.id == value.id and self.name == value.name and self.order == value.order and self.absent_on == value.absent_on and self.avatar == value.avatar diff --git a/aper/views.py b/aper/views.py index d8d2388..735f18a 100644 --- a/aper/views.py +++ b/aper/views.py @@ -32,10 +32,20 @@ def open_gate(): @app.route('/users', methods=['PUT']) @login_required def update_user(): + print(current_user) current_user.order = request.form.get('order', current_user.order) - d = request.form.get('absent_on', current_user.absent_on) if d: current_user.absent_on = datetime.datetime.strptime(d, '%Y-%m-%d') db_session.commit() return 'User updated' + +@app.route('/users', methods=['POST']) +@login_required +def update_users(): + arr = request.form.get('ids').split(',') + for id, index in enumerate(arr, start = 1): + user = User.query.get(id) + user.order = index + db_session.commit() + return 'Users updated' diff --git a/migrations/versions/26a6b4da8b01_.py b/migrations/versions/26a6b4da8b01_.py new file mode 100644 index 0000000..7ead151 --- /dev/null +++ b/migrations/versions/26a6b4da8b01_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: 26a6b4da8b01 +Revises: b502b6a81347 +Create Date: 2019-06-15 13:27:53.745935 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '26a6b4da8b01' +down_revision = 'b502b6a81347' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('users', sa.Column('avatar', sa.String(length=100), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('users', 'avatar') + # ### end Alembic commands ### From 3b4c3b7f1e12ef91d33918bc56cebb0e4dc08b1d Mon Sep 17 00:00:00 2001 From: vanecanhete Date: Sat, 15 Jun 2019 16:59:20 -0400 Subject: [PATCH 05/13] CORS: hacer pip install flask_cors --- aper/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/aper/__init__.py b/aper/__init__.py index c0573f6..15f4258 100644 --- a/aper/__init__.py +++ b/aper/__init__.py @@ -1,11 +1,14 @@ from flask import Flask from flask_login import LoginManager +from flask_cors import CORS app = Flask(__name__, instance_relative_config=True) app.config.from_object('config') app.config.from_pyfile('config.py', silent=True) +CORS(app) + login_manager = LoginManager() login_manager.init_app(app) From cb5d5425a6e7ac39e2a0f8104a98a69503670afc Mon Sep 17 00:00:00 2001 From: vanecanhete Date: Sat, 15 Jun 2019 17:14:04 -0400 Subject: [PATCH 06/13] Autenticacion de google activada --- aper/auth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/aper/auth.py b/aper/auth.py index 1e8678b..fecf0b1 100644 --- a/aper/auth.py +++ b/aper/auth.py @@ -28,10 +28,10 @@ def load_user(request): try: # Specify the CLIENT_ID of the app that accesses the backend: - #idinfo = id_token.verify_oauth2_token(token, requests.Request(), - # app.config['GOOGLE_CLIENT_ID']) + idinfo = id_token.verify_oauth2_token(token, requests.Request(), + app.config['GOOGLE_CLIENT_ID']) - idinfo = json.loads(dummy_info) + #idinfo = json.loads(dummy_info) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) @@ -56,4 +56,4 @@ def load_user(request): return user except ValueError: # Invalid token - return None \ No newline at end of file + return None From a5aa9c7477adb35e74d51ad927eadc12960e6932 Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Fri, 16 Aug 2019 19:28:19 -0400 Subject: [PATCH 07/13] added role column --- migrations/versions/9756024d98f4_.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 migrations/versions/9756024d98f4_.py diff --git a/migrations/versions/9756024d98f4_.py b/migrations/versions/9756024d98f4_.py new file mode 100644 index 0000000..5a0a234 --- /dev/null +++ b/migrations/versions/9756024d98f4_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: 9756024d98f4 +Revises: 26a6b4da8b01 +Create Date: 2019-08-16 14:01:42.659328 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '9756024d98f4' +down_revision = '26a6b4da8b01' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('users', sa.Column('role', sa.String(length=100), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('users', 'role') + # ### end Alembic commands ### From 2510656060c9b6783a438a3ba61bb2e67061aeff Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Mon, 19 Aug 2019 12:38:04 -0400 Subject: [PATCH 08/13] logic for absent --- Pipfile | 2 ++ Pipfile.lock | 73 +++++++++++++++++++++++++++++++----------------- aper/__init__.py | 1 - aper/auth.py | 10 ++++--- aper/models.py | 7 +++-- aper/views.py | 26 ++++++++--------- 6 files changed, 73 insertions(+), 46 deletions(-) diff --git a/Pipfile b/Pipfile index 67faeb2..356fc13 100644 --- a/Pipfile +++ b/Pipfile @@ -10,6 +10,8 @@ google-auth = "*" flask-sqlalchemy = "*" requests = "*" flask-migrate = "*" +gpiozero = "*" +flask-cors = "*" [dev-packages] yapf = "*" diff --git a/Pipfile.lock b/Pipfile.lock index df215f2..24b390f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "826c4eb5a798e68e5b69da8c0fde56d03208addefe65fb568fe118714a003819" + "sha256": "6c4b2fdc432b62907064797a14baedcd816e5644bc3084db3d3f2d3e670b6f4b" }, "pipfile-spec": 6, "requires": { @@ -18,9 +18,9 @@ "default": { "alembic": { "hashes": [ - "sha256:828dcaa922155a2b7166c4f36ec45268944e4055c86499bd14319b4c8c0094b7" + "sha256:cdb7d98bd5cbf65acd38d70b1c05573c432e6473a82f955cdea541b5c153b0cc" ], - "version": "==1.0.10" + "version": "==1.0.11" }, "cachetools": { "hashes": [ @@ -31,10 +31,10 @@ }, "certifi": { "hashes": [ - "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5", - "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae" + "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", + "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" ], - "version": "==2019.3.9" + "version": "==2019.6.16" }, "chardet": { "hashes": [ @@ -50,13 +50,28 @@ ], "version": "==7.0" }, + "colorzero": { + "hashes": [ + "sha256:acba47119b5d8555680d3cda9afe6ccc5481385ccc3c00084dd973f7aa184599", + "sha256:e3c36d15b293de2b2f77ff54a5bd243fffac941ed0a5332d0697a6612a26a0a3" + ], + "version": "==1.1" + }, "flask": { "hashes": [ - "sha256:ad7c6d841e64296b962296c2c2dabc6543752985727af86a975072dea984b6f3", - "sha256:e7d32475d1de5facaa55e3958bc4ec66d3762076b074296aa50ef8fdc5b9df61" + "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", + "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" ], "index": "pypi", - "version": "==1.0.3" + "version": "==1.1.1" + }, + "flask-cors": { + "hashes": [ + "sha256:72170423eb4612f0847318afff8c247b38bd516b7737adfc10d1c2cdbb382d16", + "sha256:f4d97201660e6bbcff2d89d082b5b6d31abee04b1b3003ee073a6fd25ad1d69a" + ], + "index": "pypi", + "version": "==3.0.8" }, "flask-login": { "hashes": [ @@ -89,6 +104,14 @@ "index": "pypi", "version": "==1.6.3" }, + "gpiozero": { + "hashes": [ + "sha256:101044038e71cec8be2fa841d4cea9e50e7962e9fb0287f465298b59e3f06594", + "sha256:ae1a8dc4e6e793ffd8f900968f3290d218052c46347fa0c0503c65fabe422e4d" + ], + "index": "pypi", + "version": "==1.5.1" + }, "idna": { "hashes": [ "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", @@ -112,9 +135,9 @@ }, "mako": { "hashes": [ - "sha256:0cfa65de3a835e87eeca6ac856b3013aade55f49e32515f65d999f91a2324162" + "sha256:a36919599a9b7dc5d86a7a8988f23a9a3a3d083070023bab23d64f7f1d1e0a4b" ], - "version": "==1.0.12" + "version": "==1.1.0" }, "markupsafe": { "hashes": [ @@ -151,17 +174,17 @@ }, "pyasn1": { "hashes": [ - "sha256:da2420fe13a9452d8ae97a0e478adde1dee153b11ba832a95b223a2ba01c10f7", - "sha256:da6b43a8c9ae93bc80e2739efb38cc776ba74a886e3e9318d65fe81a8b8a2c6e" + "sha256:3bb81821d47b17146049e7574ab4bf1e315eb7aead30efe5d6a9ca422c9710be", + "sha256:b773d5c9196ffbc3a1e13bdf909d446cad80a039aa3340bcad72f395b76ebc86" ], - "version": "==0.4.5" + "version": "==0.4.6" }, "pyasn1-modules": { "hashes": [ - "sha256:ef721f68f7951fab9b0404d42590f479e30d9005daccb1699b0a51bb4177db96", - "sha256:f309b6c94724aeaf7ca583feb1cc70430e10d7551de5e36edfc1ae6909bcfb3c" + "sha256:43c17a83c155229839cc5c6b868e8d0c6041dba149789b6d6e28801c64821722", + "sha256:e30199a9d221f1b26c885ff3d87fd08694dbbe18ed0e8e405a2a7126d30ce4c0" ], - "version": "==0.2.5" + "version": "==0.2.6" }, "python-dateutil": { "hashes": [ @@ -202,9 +225,9 @@ }, "sqlalchemy": { "hashes": [ - "sha256:c7fef198b43ef31dfd783d094fd5ee435ce8717592e6784c45ba337254998017" + "sha256:217e7fc52199a05851eee9b6a0883190743c4fb9c8ac4313ccfceaffd852b0ff" ], - "version": "==1.3.4" + "version": "==1.3.6" }, "urllib3": { "hashes": [ @@ -215,20 +238,20 @@ }, "werkzeug": { "hashes": [ - "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", - "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6" + "sha256:87ae4e5b5366da2347eb3116c0e6c681a0e939a33b2805e2c0cbd282664932c4", + "sha256:a13b74dd3c45f758d4ebdb224be8f1ab8ef58b3c0ffc1783a8c7d9f4f50227e6" ], - "version": "==0.15.4" + "version": "==0.15.5" } }, "develop": { "yapf": { "hashes": [ - "sha256:34f6f80c446dcb2c44bd644c4037a2024b6645e293a4c9c4521983dd0bb247a1", - "sha256:613deba14233623ff3432d9d5032631b5f600be97b39f66932cbe67648bfa8ea" + "sha256:02ace10a00fa2e36c7ebd1df2ead91dbfbd7989686dc4ccbdc549e95d19f5780", + "sha256:6f94b6a176a7c114cfa6bad86d40f259bbe0f10cf2fa7f2f4b3596fc5802a41b" ], "index": "pypi", - "version": "==0.27.0" + "version": "==0.28.0" } } } diff --git a/aper/__init__.py b/aper/__init__.py index 15f4258..dacb73d 100644 --- a/aper/__init__.py +++ b/aper/__init__.py @@ -22,6 +22,5 @@ def shutdown_session(exception=None): db_session.remove() - import aper.auth import aper.views diff --git a/aper/auth.py b/aper/auth.py index 95a11b9..f08fd1d 100644 --- a/aper/auth.py +++ b/aper/auth.py @@ -3,7 +3,7 @@ from .db import db_session from google.oauth2 import id_token from google.auth.transport import requests -import json + @login_manager.request_loader @@ -28,6 +28,7 @@ def load_user(request): try: # Specify the CLIENT_ID of the app that accesses the backend: + idinfo = id_token.verify_oauth2_token(token, requests.Request(), app.config['GOOGLE_CLIENT_ID']) @@ -37,19 +38,20 @@ def load_user(request): # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]: # raise ValueError('Could not verify audience.') - if idinfo['iss'] not in [ 'accounts.google.com', 'https://accounts.google.com' ]: raise ValueError('Wrong issuer.') - # If auth request is from a G Suite domain: # if idinfo['hd'] != GSUITE_DOMAIN_NAME: # raise ValueError('Wrong hosted domain.') # ID token is valid. Get the user's Google Account ID from the decoded token. - # print(idinfo) + user = User.query.filter(User.email == idinfo['email']).first() + + print(user) + if not user: user = User(idinfo['name'], idinfo['email'], idinfo['picture']) db_session.add(user) diff --git a/aper/models.py b/aper/models.py index c65f3f7..8af908c 100644 --- a/aper/models.py +++ b/aper/models.py @@ -16,6 +16,7 @@ class User(UserMixin, Base): order = Column(Integer, nullable=False) absent_on = Column(Date) avatar = Column(String(100)) + role = Column(String(100)) def __init__(self, name, email, avatar): self.email = email @@ -24,6 +25,7 @@ def __init__(self, name, email, avatar): self.order = max_order + 1 if max_order else 1 self.absent_on = None self.avatar = avatar + self.role = None def serialize(self): """Return object data in serializeable format""" @@ -33,7 +35,8 @@ def serialize(self): 'email': self.email, 'order': self.order, 'absent_on': self.absent_on, - 'avatar': self.avatar + 'avatar': self.avatar, + 'role': self.role, } @classmethod @@ -47,4 +50,4 @@ def __repr__(self): return ''.format(self.name, self.email) def __eq__(self, value): - return self.id == value.id and self.name == value.name and self.order == value.order and self.absent_on == value.absent_on and self.avatar == value.avatar + return self.id == value.id and self.name == value.name and self.order == value.order and self.absent_on == value.absent_on and self.avatar == value.avatar and self.role == value.role diff --git a/aper/views.py b/aper/views.py index 555a1d3..41d38a2 100644 --- a/aper/views.py +++ b/aper/views.py @@ -3,7 +3,7 @@ from flask import jsonify, request from .models import User from .db import db_session -import datetime +from datetime import date from gpiozero import LED from time import sleep @@ -26,26 +26,24 @@ def users(): def open_gate(): allowed_users = User.allowed_users() if current_user in allowed_users: - controller=LED(17) - controller.on() - sleep(2) - controller.off() - sleep(2) - return 'Open Sesame' + # controller=LED(17) + # controller.on() + # sleep(2) + # controller.off() + # sleep(2) + return 'Abriendo portón...' else: - return 'You cannot park inside today', 403 + return 'No podés estacionar adentro hoy :(', 403 -@app.route('/users', methods=['PUT']) +@app.route('/not_using', methods=['POST']) @login_required def update_user(): print(current_user) - current_user.order = request.form.get('order', current_user.order) - d = request.form.get('absent_on', current_user.absent_on) - if d: - current_user.absent_on = datetime.datetime.strptime(d, '%Y-%m-%d') + current_user.absent_on = date.today() db_session.commit() - return 'User updated' + return 'OK' + @app.route('/users', methods=['POST']) @login_required From 3a153a8af5552f47487ddbab96f50d77d88195ad Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Mon, 19 Aug 2019 19:34:24 -0400 Subject: [PATCH 09/13] Added feautures new get of current users absent_on functionality messages for opengate --- aper/views.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aper/views.py b/aper/views.py index 41d38a2..599c46e 100644 --- a/aper/views.py +++ b/aper/views.py @@ -8,10 +8,10 @@ from time import sleep -@app.route('/') +@app.route('/current_user', methods=['GET']) @login_required -def index(): - return 'Hello {}!'.format(current_user.name) +def get_current_user(): + return jsonify(current_user.serialize()) @app.route('/users', methods=['GET']) @@ -38,11 +38,11 @@ def open_gate(): @app.route('/not_using', methods=['POST']) @login_required -def update_user(): +def not_using(): print(current_user) current_user.absent_on = date.today() db_session.commit() - return 'OK' + return 'Registramos que no vas a usar tu lugar hoy' @app.route('/users', methods=['POST']) From 4a2e35df4a73583cf6cd0ae4d21d2e67ae9d14fb Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Wed, 21 Aug 2019 18:57:36 -0400 Subject: [PATCH 10/13] /not_usign improved --- aper/views.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/aper/views.py b/aper/views.py index 599c46e..3046a42 100644 --- a/aper/views.py +++ b/aper/views.py @@ -4,6 +4,7 @@ from .models import User from .db import db_session from datetime import date +import datetime from gpiozero import LED from time import sleep @@ -40,10 +41,14 @@ def open_gate(): @login_required def not_using(): print(current_user) - current_user.absent_on = date.today() - db_session.commit() - return 'Registramos que no vas a usar tu lugar hoy' - + if current_user.absent_on != datetime.date.today(): + current_user.absent_on = date.today() + db_session.commit() + return 'Registramos que no vas a usar tu lugar hoy' + else: + current_user.absent_on = None + db_session.commit() + return 'Vas a usar tu lugar hoy' @app.route('/users', methods=['POST']) @login_required From 6637dff17e8751aa66f66c33002a433a7833c1f0 Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Thu, 22 Aug 2019 11:28:26 -0400 Subject: [PATCH 11/13] the backend returns if the user is absent on that day or not so the timezone is consistent --- aper/views.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/aper/views.py b/aper/views.py index 3046a42..496e85d 100644 --- a/aper/views.py +++ b/aper/views.py @@ -50,6 +50,7 @@ def not_using(): db_session.commit() return 'Vas a usar tu lugar hoy' + @app.route('/users', methods=['POST']) @login_required def update_users(): @@ -59,3 +60,12 @@ def update_users(): user.order = index db_session.commit() return 'Users updated' + + +@app.route('/absent', methods=['GET']) +@login_required +def isabsent(): + if current_user.absent_on == datetime.date.today(): + return 'yes' + else: + return 'no' From ec268bb7fe5a0ef2a7a4d48a71a72cee12a9df77 Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Thu, 22 Aug 2019 19:37:39 -0400 Subject: [PATCH 12/13] Validating every request according on role --- aper/auth.py | 16 +++++++++-- aper/views.py | 79 +++++++++++++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/aper/auth.py b/aper/auth.py index f08fd1d..2c5557a 100644 --- a/aper/auth.py +++ b/aper/auth.py @@ -48,9 +48,21 @@ def load_user(request): # ID token is valid. Get the user's Google Account ID from the decoded token. - user = User.query.filter(User.email == idinfo['email']).first() + # whitelist = app.config['USERS'] + # + # if idinfo['email'] in whitelist: + # user = User.query.filter(User.email == idinfo['email']).first() + # if not user: + # newuser = User(idinfo['name'], idinfo['email'], idinfo['picture']) + # db_session.add(newuser) + # else: + # return user + # else: + # return None + # except ValueError: + # return None - print(user) + user = User.query.filter(User.email == idinfo['email']).first() if not user: user = User(idinfo['name'], idinfo['email'], idinfo['picture']) diff --git a/aper/views.py b/aper/views.py index 496e85d..651af77 100644 --- a/aper/views.py +++ b/aper/views.py @@ -18,49 +18,74 @@ def get_current_user(): @app.route('/users', methods=['GET']) @login_required def users(): - users = [u.serialize() for u in User.query.all()] - return jsonify(users) + if current_user.role != 'ADMIN': + return 'UNAUTHORIZED', 401 + else: + users = [u.serialize() for u in User.query.all()] + return jsonify(users) @app.route('/open_gate', methods=['GET']) @login_required def open_gate(): - allowed_users = User.allowed_users() - if current_user in allowed_users: - # controller=LED(17) - # controller.on() - # sleep(2) - # controller.off() - # sleep(2) - return 'Abriendo portón...' + if (current_user.role != 'ADMIN' and current_user.role != 'USER'): + return 'UNAUTHORIZED', 401 else: - return 'No podés estacionar adentro hoy :(', 403 + allowed_users = User.allowed_users() + if current_user in allowed_users: + # controller=LED(17) + # controller.on() + # sleep(2) + # controller.off() + # sleep(2) + return 'Abriendo portón...' + else: + return 'No podés estacionar adentro hoy :(', 403 @app.route('/not_using', methods=['POST']) @login_required def not_using(): - print(current_user) - if current_user.absent_on != datetime.date.today(): - current_user.absent_on = date.today() - db_session.commit() - return 'Registramos que no vas a usar tu lugar hoy' + if (current_user.role != 'ADMIN' and current_user.role != 'USER'): + return 'UNAUTHORIZED', 401 else: - current_user.absent_on = None - db_session.commit() - return 'Vas a usar tu lugar hoy' + print(current_user) + if current_user.absent_on != datetime.date.today(): + current_user.absent_on = date.today() + db_session.commit() + return 'Registramos que no vas a usar tu lugar hoy' + else: + current_user.absent_on = None + db_session.commit() + return 'Vas a usar tu lugar hoy' -@app.route('/users', methods=['POST']) +@app.route('/users_order', methods=['POST']) @login_required -def update_users(): - arr = request.form.get('ids').split(',') - for id, index in enumerate(arr, start = 1): - user = User.query.get(id) - user.order = index - db_session.commit() - return 'Users updated' +def change_order(): + if current_user.role != 'ADMIN': + return 'UNAUTHORIZED', 401 + else: + arr = request.form.get('ids').split(',') + for id, index in enumerate(arr, start = 1): + user = User.query.get(id) + user.order = index + db_session.commit() + return 'Users updated' +@app.route('/users_roles', methods=['POST']) +@login_required +def change_roles(): + if current_user.role != 'ADMIN': + return 'UNAUTHORIZED', 401 + else: + arr = request.form.get('ids').split(',') + print(arr) + for id, index in enumerate(arr, start = 1): + user = User.query.get(id) + user.role = index + db_session.commit() + return 'Users updated' @app.route('/absent', methods=['GET']) @login_required From 330f02d8015fa0821290cbebde64b34a208861b0 Mon Sep 17 00:00:00 2001 From: Diego Aguilera Date: Thu, 22 Aug 2019 19:53:54 -0400 Subject: [PATCH 13/13] Every new user is guest and has no permissions until is promoted to user --- aper/auth.py | 2 +- aper/models.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/aper/auth.py b/aper/auth.py index 2c5557a..08ee86b 100644 --- a/aper/auth.py +++ b/aper/auth.py @@ -65,7 +65,7 @@ def load_user(request): user = User.query.filter(User.email == idinfo['email']).first() if not user: - user = User(idinfo['name'], idinfo['email'], idinfo['picture']) + user = User(idinfo['name'], idinfo['email'], idinfo['picture'], "GUEST") db_session.add(user) else: user.avatar = idinfo['picture'] diff --git a/aper/models.py b/aper/models.py index 8af908c..632bc2a 100644 --- a/aper/models.py +++ b/aper/models.py @@ -18,14 +18,14 @@ class User(UserMixin, Base): avatar = Column(String(100)) role = Column(String(100)) - def __init__(self, name, email, avatar): + def __init__(self, name, email, avatar, role): self.email = email self.name = name max_order = db_session.query(func.max(User.order)).scalar() self.order = max_order + 1 if max_order else 1 self.absent_on = None self.avatar = avatar - self.role = None + self.role = role def serialize(self): """Return object data in serializeable format"""