From 922f8c7d52f7a3a44fe70ed1d2f86cebbaeeb5d4 Mon Sep 17 00:00:00 2001 From: androiddrew Date: Mon, 30 Apr 2018 12:11:34 -0400 Subject: [PATCH] Added JWT back into Project --- cookie_api/app.py | 13 +++++-- cookie_api/auth.py | 92 +++++++++++++++++++++++--------------------- cookie_api/models.py | 7 ++++ 3 files changed, 64 insertions(+), 48 deletions(-) diff --git a/cookie_api/app.py b/cookie_api/app.py index 4f5923c..7ffe2b3 100644 --- a/cookie_api/app.py +++ b/cookie_api/app.py @@ -1,11 +1,12 @@ import typing from apistar import Route, http, App -from apistar_jwt import JWT +from apistar_jwt import JWT, authentication_required, JWTUser import logbook from sqlalchemy import create_engine +from cookie_api.auth import auth_routes from cookie_api.logger import global_init from cookie_api.models import Cookie from cookie_api.schema import CookieSchema @@ -29,7 +30,8 @@ def get_cookie(session: Session, id) -> CookieSchema: return ExtJSONResponse(CookieSchema(cookie), 200) -def create_cookie(session: Session, cookie_data: CookieSchema, app: App): +@authentication_required +def create_cookie(session: Session, cookie_data: CookieSchema, app: App, user: JWTUser): cookie = Cookie(**cookie_data) session.add(cookie) session.commit() @@ -37,11 +39,13 @@ def create_cookie(session: Session, cookie_data: CookieSchema, app: App): return ExtJSONResponse(CookieSchema(cookie), 201, headers=headers) -def delete_cookie(session: Session, id: int): +@authentication_required +def delete_cookie(session: Session, id: int, user: JWTUser): cookie = session.query(Cookie).filter_by(id=id).one_or_none() if cookie is None: msg = {"error": "404 Not Found"} return http.Response(msg, status=404) + logger.debug("Deleting cookie {} {}".format(cookie.id, cookie.name)) session.delete(cookie) session.commit() @@ -62,13 +66,14 @@ app_settings = { } } -_routes = _routes # + auth_routes +_routes = _routes + auth_routes _hooks = [SQLAlchemyHook] _components = [ SQLAlchemySession(engine=engine), JWT({ + 'JWT_USER_ID': 'sub', 'JWT_SECRET': 'thisisasecret', }), ] diff --git a/cookie_api/auth.py b/cookie_api/auth.py index a219ea4..75c22b4 100644 --- a/cookie_api/auth.py +++ b/cookie_api/auth.py @@ -1,18 +1,21 @@ -""" import datetime as dt -from apistar import Component, http, Route, Include +from apistar import http, Route, Include -from apistar_jwt.token import JWT +from apistar_jwt.token import JWT, JWTUser # from apistar_mail import Message, Mail -from sqlalchemy.exc import IntegrityError, InvalidRequestError +# from sqlalchemy.exc import IntegrityError, InvalidRequestError +from sqlalchemy.orm import Session from sqlalchemy.orm.exc import NoResultFound from cookie_api.models import User -from cookie_api.schema import +from cookie_api.util import ExtJSONResponse -def login(settings: Settings, json_data: http.RequestData, session: Session): +# from cookie_api.schema import + + +def login(json_data: http.RequestData, session: Session, jwt: JWT): user_id = json_data.get('email') password = json_data.get('password') @@ -24,13 +27,11 @@ def login(settings: Settings, json_data: http.RequestData, session: Session): 'status': 'fail', 'message': 'User does not exist' } - return http.Response(error, status=400, headers={'WWW-Authenticate': 'Bearer'}) + return ExtJSONResponse(error, status=400, headers={'WWW-Authenticate': 'Bearer'}) if not user.check_password(password): error = {'error': 'Password auth failed'}, - return http.Response(error, status=401, headers={'WWW-Authenticate': 'Bearer'}) - - secret = settings['JWT'].get('SECRET') + return ExtJSONResponse(error, status=401, headers={'WWW-Authenticate': 'Bearer'}) payload = { 'exp': dt.datetime.utcnow() + dt.timedelta(days=0, minutes=60), # Expiration date of the token @@ -38,7 +39,7 @@ def login(settings: Settings, json_data: http.RequestData, session: Session): 'sub': user.id # the subject of the token } - token = JWT.encode(payload, secret=secret) + token = jwt.encode(payload) data = { 'status': 'success', @@ -46,7 +47,7 @@ def login(settings: Settings, json_data: http.RequestData, session: Session): 'auth_token': token } - return data + return ExtJSONResponse(data, 200) # TODO Add user logout @@ -55,38 +56,42 @@ def logout(): # TODO Add user registration -def register(user_rep: UserCreateSchema, session: Session, mail: Mail): - email_check = session.query(User).filter_by(email=user_rep['email']).one_or_none() - - if email_check is not None: - message = { - 'status': 'error', - 'message': 'user email address is already in use' - } - return http.Response(message, status=400) - - user = User(email=user_rep['email'], password=user_rep['password']) - - session.add(user) - session.commit() - - msg = Message("Thank you for registering please confirm your email", recipients=[user_rep['email']]) - mail.send(msg) +# def register(user_rep: UserCreateSchema, session: Session, mail: Mail): +def register(): + # email_check = session.query(User).filter_by(email=user_rep['email']).one_or_none() + # + # if email_check is not None: + # message = { + # 'status': 'error', + # 'message': 'user email address is already in use' + # } + # return http.Response(message, status=400) + # + # user = User(email=user_rep['email'], password=user_rep['password']) + # + # session.add(user) + # session.commit() + # + # msg = Message("Thank you for registering please confirm your email", recipients=[user_rep['email']]) + # mail.send(msg) + # + # headers = {} + # message = { + # 'status': 'success', + # 'message': 'Please check your inbox and confirm your email' + # } + # return http.Response(message, status=201, headers=headers) + pass - headers = {} - message = { - 'status': 'success', - 'message': 'Please check your inbox and confirm your email' - } - return http.Response(message, status=201, headers=headers) +def user_profile(user: JWTUser, session: Session): # -> UserSchema + try: + user = session.query(User).filter_by(id=user.id).one() + except NoResultFound as e: + error = {'message': str(e)} + return ExtJSONResponse(error, 400) + return ExtJSONResponse(user.to_dict()) -@annotate(authentication=[JWTAuthentication()]) -def user_profile(auth: Auth, settings: Settings, session: Session) -> UserSchema: - token = JWT(token=auth.token, settings=settings) - user_id = token.payload.get('sub') - user = session.query(User).filter_by(id=user_id).one() - return UserSchema(user) # TODO Add email confirmation def confirm(json_data: http.RequestData, session: Session): @@ -100,9 +105,8 @@ def reset(): routes = [ Route('/login', 'POST', login), - Route('/register', 'POST', register), + # Route('/register', 'POST', register), Route('/status', 'GET', user_profile) ] -auth_routes = [Include('/auth', routes)] -""" \ No newline at end of file +auth_routes = [Include('/auth', name='auth', routes=routes)] diff --git a/cookie_api/models.py b/cookie_api/models.py index 4bf2e41..52d53e0 100644 --- a/cookie_api/models.py +++ b/cookie_api/models.py @@ -65,6 +65,13 @@ class User(DBMixin, Base): def check_password(self, password): return bcrypt.checkpw(password.encode('utf-8'), self.password.encode('utf-8')) + def to_dict(self): + d = self.__dict__.copy() + if '_sa_instance_state' in d: + d.pop('_sa_instance_state') + d.pop('password') + return d + class Order(DBMixin, Base): __tablename__ = 'orders'