From 69228f21caf50493060fb91a426e34fffc0dfd09 Mon Sep 17 00:00:00 2001
From: Eli Ribble <eli@authentise.com>
Date: Tue, 3 May 2016 19:28:56 -0600
Subject: [PATCH] Add API for creating new users

---
 tests/api/test_user.py | 15 +++++++++++++++
 vanth/api/user.py      | 23 +++++++++++++++++++++++
 vanth/platform/user.py | 22 ++++++++++++++++++++++
 vanth/server.py        |  2 ++
 vanth/tables.py        | 17 ++++++++++++++---
 5 files changed, 76 insertions(+), 3 deletions(-)
 create mode 100644 tests/api/test_user.py
 create mode 100644 vanth/api/user.py
 create mode 100644 vanth/platform/user.py

diff --git a/tests/api/test_user.py b/tests/api/test_user.py
new file mode 100644
index 0000000..2c4706f
--- /dev/null
+++ b/tests/api/test_user.py
@@ -0,0 +1,15 @@
+import json
+
+import pytest
+
+
+@pytest.mark.usefixtures('db')
+def test_post(client):
+    data = {
+        'name'      : 'Blue Stahli',
+        'password'  : 'metamorphosis',
+        'username'  : 'BlueStahli',
+    }
+    response = client.post('/user/', data=json.dumps(data))
+    assert response.status_code == 204
+    assert response.headers['Location']
diff --git a/vanth/api/user.py b/vanth/api/user.py
new file mode 100644
index 0000000..9a6064e
--- /dev/null
+++ b/vanth/api/user.py
@@ -0,0 +1,23 @@
+import sepiida.endpoints
+import sepiida.fields
+
+import vanth.platform.user
+
+
+class User(sepiida.endpoints.APIEndpoint):
+    ENDPOINT = '/user/'
+    SIGNATURE = sepiida.fields.JSONObject(s={
+        'name'      : sepiida.fields.String(),
+        'password'  : sepiida.fields.String(),
+        'username'  : sepiida.fields.String(),
+    })
+
+    @staticmethod
+    def post(payload):
+        uri = vanth.platform.user.create(payload['name'], payload['username'], payload['password'])
+
+        return None, 204, {'Location': uri}
+
+    @staticmethod
+    def get(uuid): # pylint: disable=unused-argument
+        return {}
diff --git a/vanth/platform/user.py b/vanth/platform/user.py
new file mode 100644
index 0000000..55dbcff
--- /dev/null
+++ b/vanth/platform/user.py
@@ -0,0 +1,22 @@
+import uuid
+
+import chryso.connection
+import passlib.apps
+import sepiida.routing
+
+import vanth.tables
+
+
+def create(name, username, password):
+    engine = chryso.connection.get()
+
+    _uuid = uuid.uuid4()
+    statement = vanth.tables.User.insert().values( #pylint: disable=no-value-for-parameter
+        name            = name,
+        password        = passlib.apps.custom_app_context.encrypt(password),
+        username        = username,
+        uuid            = str(_uuid),
+    )
+    engine.execute(statement)
+
+    return sepiida.routing.uri('user', _uuid)
diff --git a/vanth/server.py b/vanth/server.py
index 9da9866..d695785 100644
--- a/vanth/server.py
+++ b/vanth/server.py
@@ -6,6 +6,7 @@ import flask_uuid
 import sepiida.endpoints
 
 import vanth.api.about
+import vanth.api.user
 import vanth.user
 
 
@@ -50,5 +51,6 @@ def create_app(config):
     app.route('/logout/', methods=['POST'])(logout)
 
     sepiida.endpoints.add_resource(app, vanth.api.about.About, endpoint='about')
+    sepiida.endpoints.add_resource(app, vanth.api.user.User, endpoint='user')
 
     return app
diff --git a/vanth/tables.py b/vanth/tables.py
index a394669..9d6bbe5 100644
--- a/vanth/tables.py
+++ b/vanth/tables.py
@@ -1,10 +1,21 @@
-from sqlalchemy import Boolean, Column, Date, DateTime, Float, ForeignKey, Integer, MetaData, String, Table, func
-from sqlalchemy.dialects.postgresql import UUID, ENUM
-from sqlalchemy.dialects import postgres
 import chryso.constants
+from sqlalchemy import (Column, Date, DateTime, Float, ForeignKey, Integer,
+                        MetaData, String, Table, func)
+from sqlalchemy.dialects.postgresql import UUID
 
 metadata = MetaData(naming_convention=chryso.constants.CONVENTION)
 
+User = Table('users', metadata,
+    Column('uuid',          UUID(), primary_key=True),
+    Column('username',      String(255), nullable=False),
+    Column('name',          String(255), nullable=False),
+    Column('company',       String(255), nullable=True),
+    Column('password',      String(128), nullable=False),
+    Column('created_at',    DateTime,    nullable=False, server_default=func.now()),
+    Column('updated_at',    DateTime,    nullable=False, server_default=func.now(), onupdate=func.now()),
+    Column('deleted_at',    DateTime,    nullable=True),
+)
+
 CreditCard = Table('credit_card', metadata,
     Column('uuid',              UUID(as_uuid=True),         primary_key=True),
     Column('brand',             String(20),     nullable=False), # The brand of the card, like 'visa'