diff --git a/models/__init__.py b/cookie_api/__init__.py similarity index 100% rename from models/__init__.py rename to cookie_api/__init__.py diff --git a/app.py b/cookie_api/app.py similarity index 85% rename from app.py rename to cookie_api/app.py index 1f6ef5a..0a432bd 100644 --- a/app.py +++ b/cookie_api/app.py @@ -1,20 +1,13 @@ -import json - -from apistar import Include, Route, annotate, http -from apistar.interfaces import Router - +from apistar import Include, Route, http, Command 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 models.schema import Base, Cookie -import render - +from apistar.interfaces import Router -def welcome(name=None): - if name is None: - return {'message': 'Welcome to API Star!'} - return {'message': 'Welcome to API Star, %s!' % name} +from render import JSONRenderer +from commands import commands +from models.schema import Base, Cookie def get_cookies(session: Session): @@ -41,6 +34,7 @@ def get_cookie(session: Session, id): return cookie.to_dict() +# @annotate(authentication=[JWTAuthentication()]) def create_cookie(session: Session, json_data: http.RequestData, route: Router): cookie = Cookie(name=json_data['name'], recipe_url=json_data['recipe_url'], @@ -54,7 +48,6 @@ def create_cookie(session: Session, json_data: http.RequestData, route: Router): routes = [ - Route('/', 'GET', welcome), Route('/cookies', 'GET', get_cookies), Route('/cookies', 'POST', create_cookie), Route('/cookies/{id}', 'GET', get_cookie), @@ -67,12 +60,18 @@ settings = { 'URL': 'postgresql://:@localhost/apistar', 'METADATA': Base.metadata }, - 'RENDERERS': [render.JSONRenderer()] + 'RENDERERS': [JSONRenderer()], + 'JWT': { + 'SECRET': 'thisisasecret' + }, + 'BCRYPT_LOG_ROUNDS': 13 } +commands = sqlalchemy_backend.commands + commands + app = App(routes=routes, settings=settings, - commands=sqlalchemy_backend.commands, + commands=commands, components=sqlalchemy_backend.components ) diff --git a/cookie_api/commands.py b/cookie_api/commands.py new file mode 100644 index 0000000..b834c67 --- /dev/null +++ b/cookie_api/commands.py @@ -0,0 +1,15 @@ +from apistar import Command +from apistar.backends.sqlalchemy_backend import Session + +from models.schema import User + +def create_user(session: Session, email, password): + user = User(email, password) + session.add(user) + session.commit() + print('User added') + + +commands = [ + Command('create_user', create_user) +] \ No newline at end of file diff --git a/cookie_api/models/__init__.py b/cookie_api/models/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models/schema.py b/cookie_api/models/schema.py similarity index 82% rename from models/schema.py rename to cookie_api/models/schema.py index ffc13b9..2d4a338 100644 --- a/models/schema.py +++ b/cookie_api/models/schema.py @@ -1,3 +1,4 @@ +import bcrypt from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, DateTime, Boolean, Numeric from sqlalchemy.orm import relationship, backref @@ -5,10 +6,12 @@ from sqlalchemy.sql import expression from sqlalchemy.ext.compiler import compiles from sqlalchemy.types import DateTime as DateTimeType + # can be moved to models util? class utcnow(expression.FunctionElement): type = DateTimeType() + # Can be moved to the models util? @compiles(utcnow, 'postgresql') def pg_utcnow(element, compiler, **kw): @@ -18,9 +21,8 @@ def pg_utcnow(element, compiler, **kw): Base = declarative_base() - class DBMixin: - id = Column(Integer, primary_key=True) + id = Column(Integer, primary_key=True, autoincrement=True) created_date = Column(DateTime, server_default=utcnow()) modified_date = Column(DateTime, server_default=utcnow(), onupdate=utcnow()) @@ -47,10 +49,14 @@ class Cookie(Base, DBMixin): class User(DBMixin, Base): __tablename__ = 'users' - username = Column(String(255), nullable=False, unique=True) - email_address = Column(String(255), nullable=False) - phone = Column(String(20), nullable=False) + email = Column(String(255), nullable=False, unique=True) password = Column(String(255)) + admin = Column(Boolean, nullable=False, default=False) + + def __init__(self, email, password, admin=False): + self.email = email + self.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(13)).decode() + self.admin = admin class Order(DBMixin, Base): @@ -72,4 +78,3 @@ class LineItem(DBMixin, Base): order = relationship('Order', backref=backref('line_items')) cookie = relationship('Cookie', uselist=False) - diff --git a/models/util.py b/cookie_api/models/util.py similarity index 100% rename from models/util.py rename to cookie_api/models/util.py diff --git a/render.py b/cookie_api/render.py similarity index 97% rename from render.py rename to cookie_api/render.py index 1e105d5..b751716 100644 --- a/render.py +++ b/cookie_api/render.py @@ -1,8 +1,9 @@ import json +from models.util import alchemyencoder + from apistar import http from apistar.renderers import Renderer -from models.util import alchemyencoder class JSONRenderer(Renderer): diff --git a/requirements.txt b/requirements.txt index 6aef029..e41aac6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ apistar==0.3.6 +apistar-jwt==0.1.2 certifi==2017.7.27.1 chardet==3.0.4 coreapi==2.3.1 @@ -7,7 +8,9 @@ idna==2.6 itypes==1.1.0 Jinja2==2.9.6 MarkupSafe==1.0 +psycopg2==2.7.3.1 py==1.4.34 +PyJWT==1.5.3 pytest==3.2.2 requests==2.18.4 SQLAlchemy==1.1.14 diff --git a/tests.py b/tests.py index 5c73bcc..a944f6c 100644 --- a/tests.py +++ b/tests.py @@ -1,6 +1,7 @@ -from apistar.test import TestClient from app import welcome +from apistar.test import TestClient + def test_welcome(): """