diff --git a/.gitignore b/.gitignore index cf6a489..cbf8643 100644 --- a/.gitignore +++ b/.gitignore @@ -61,5 +61,5 @@ coverage.xml # Sphinx documentation docs/_build/ -# PyBuilder -target/ \ No newline at end of file +# Redis +/dump.rdb diff --git a/cookie_api/app.py b/cookie_api/app.py index c4f79bb..4129148 100644 --- a/cookie_api/app.py +++ b/cookie_api/app.py @@ -3,12 +3,21 @@ from apistar.backends import sqlalchemy_backend from apistar.backends.sqlalchemy_backend import Session from apistar.frameworks.wsgi import WSGIApp as App from apistar.handlers import docs_urls, static_urls -from apistar.interfaces import Router +from apistar.interfaces import Router, Injector from cookie_api.render import JSONRenderer from cookie_api.commands import commands from cookie_api.models.schema import Base, Cookie +from .auth import auth_routes, auth_components + + +def get_state(injector: Injector): + state = injector.state + d = dict() + for k, v in state.items(): + d[k] = str(v) + return d def get_cookies(session: Session): cookies = session.query(Cookie).all() @@ -48,6 +57,7 @@ def create_cookie(session: Session, json_data: http.RequestData, route: Router): routes = [ + Route('/state', 'GET', get_state), Route('/cookies', 'GET', get_cookies), Route('/cookies', 'POST', create_cookie), Route('/cookies/{id}', 'GET', get_cookie), @@ -68,10 +78,10 @@ settings = { commands = sqlalchemy_backend.commands + commands -app = App(routes=routes, +app = App(routes=routes + auth_routes, settings=settings, commands=commands, - components=sqlalchemy_backend.components + components=sqlalchemy_backend.components + auth_components ) if __name__ == "__main__": diff --git a/cookie_api/auth.py b/cookie_api/auth.py new file mode 100644 index 0000000..ec9846c --- /dev/null +++ b/cookie_api/auth.py @@ -0,0 +1,55 @@ +import datetime as dt +import json +from apistar import Component, Settings, http, Route, Include +from apistar.backends.sqlalchemy_backend import Session +from apistar_jwt.authentication import get_jwt +from apistar_jwt.token import JWT + +from .models.schema import User + +# /auth/register +# /auth/login +# /auth/logout +# /auth/user + +auth_components = [ + Component(JWT, init=get_jwt) +] + + +def login(settings: Settings, json_data: http.RequestData, session: Session): + user_id = json_data.get('email') + password = json_data.get('password') + + user = session.query(User).filter_by(email=user_id).one() + 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') + + payload = { + 'exp': dt.datetime.utcnow() + dt.timedelta(days=0, seconds=5), + 'iat': dt.datetime.utcnow(), + 'sub': user.id + } + + token = JWT.encode(payload, secret=SECRET) + + data = { + 'status': 'success', + 'message': 'Successfully logged in.', + 'auth_token': token + } + + headers = { + 'Authorization': 'Bearer {}'.format(token) + } + return http.Response(data, status=200, headers=headers) + + +routes = [ + Route('/login', 'POST', login) +] + +auth_routes = [Include('/auth', routes)] \ No newline at end of file diff --git a/cookie_api/models/schema.py b/cookie_api/models/schema.py index ec14f22..4085400 100644 --- a/cookie_api/models/schema.py +++ b/cookie_api/models/schema.py @@ -9,7 +9,7 @@ from sqlalchemy.ext.compiler import compiles from sqlalchemy.types import DateTime as DateTimeType cfg = ConfigParser() -cfg.read('config.ini') +cfg.read('/Users/Drewbednar/PycharmProjects/apistar_tut/config.ini') BCRYPT_LOG_ROUNDS = cfg.get('user', 'BCRYPT_LOG_ROUNDS') @@ -62,9 +62,12 @@ class User(DBMixin, Base): def __init__(self, email, password, admin=False): self.email = email - self.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(BCRYPT_LOG_ROUNDS)).decode() + self.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(11)).decode() self.admin = admin + def check_password(self, password): + return bcrypt.checkpw(password.encode('utf-8'), self.password.encode('utf-8')) + class Order(DBMixin, Base): __tablename__ = 'orders' diff --git a/requirements.txt b/requirements.txt index 1a7951e..4d650d1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ apistar==0.3.9 -apistar-jwt==0.2.0 +apistar-jwt==0.2.1 bcrypt==3.1.4 certifi==2017.7.27.1 cffi==1.11.2 @@ -11,6 +11,7 @@ idna==2.6 itypes==1.1.0 Jinja2==2.9.6 MarkupSafe==1.0 +psycopg2==2.7.3.1 py==1.4.34 pycparser==2.18 PyJWT==1.5.3