From 5f41066be272c2c0a6198daec0b92d15b3911d20 Mon Sep 17 00:00:00 2001
From: Benjamin Bertrand <benjamin.bertrand@esss.se>
Date: Wed, 19 Jul 2017 09:27:23 +0200
Subject: [PATCH] Add API blueprint

---
 app/api/__init__.py |  0
 app/api/items.py    | 54 +++++++++++++++++++++++++++++++++++++++++++++
 app/extensions.py   |  2 ++
 app/factory.py      |  5 ++++-
 environment.yml     |  2 ++
 5 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 app/api/__init__.py
 create mode 100644 app/api/items.py

diff --git a/app/api/__init__.py b/app/api/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/app/api/items.py b/app/api/items.py
new file mode 100644
index 0000000..ea9b8a6
--- /dev/null
+++ b/app/api/items.py
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+"""
+app.api.items
+~~~~~~~~~~~~~
+
+This module implements the items API.
+
+:copyright: (c) 2017 European Spallation Source ERIC
+:license: BSD 2-Clause, see LICENSE for more details.
+
+"""
+from flask import (current_app, Blueprint, jsonify, request)
+from flask_jwt_extended import create_access_token, jwt_required
+from flask_ldap3_login import AuthenticationResponseStatus
+from ..extensions import ldap_manager, db
+from ..models import User
+
+bp = Blueprint('api', __name__)
+
+
+@bp.route('/login', methods=['POST'])
+def login():
+    try:
+        username = request.get_json()['username']
+        password = request.get_json()['password']
+    except (TypeError, KeyError):
+        return jsonify({'msg': 'Bad Request'}), 400
+    response = ldap_manager.authenticate(username, password)
+    if response.status == AuthenticationResponseStatus.success:
+        current_app.logger.debug(f'{username} successfully logged in')
+        user = User.query.filter_by(username=username).first()
+        if user is None:
+            # LDAP user not in database yet - create it
+            user = User(username, name=response.user_info['cn'], email=response.user_info['mail'])
+            db.session.add(user)
+            db.session.commit()
+        payload = {'access_token': create_access_token(identity=user.id)}
+        return jsonify(payload), 200
+    return jsonify({'msg': 'Invalid credentials'}), 401
+
+
+@bp.route('/items')
+@jwt_required
+def get_items():
+    sql = """SELECT item.id, item.name, vendor.name, model.name, location.name, status.name
+            FROM item
+            INNER JOIN vendor ON vendor.id = item.vendor_id
+            INNER JOIN model ON model.id = item.model_id
+            INNER JOIN location ON location.id = item.location_id
+            INNER JOIN status ON status.id = item.status_id
+            """
+    result = db.engine.execute(sql)
+    data = [[item for item in row] for row in result]
+    return jsonify(data=data)
diff --git a/app/extensions.py b/app/extensions.py
index 4c2c1a9..87da52a 100644
--- a/app/extensions.py
+++ b/app/extensions.py
@@ -17,6 +17,7 @@ from flask_migrate import Migrate
 from flask_bootstrap import Bootstrap
 from flask_admin import Admin
 from flask_mail import Mail
+from flask_jwt_extended import JWTManager
 
 
 convention = {
@@ -36,3 +37,4 @@ ldap_manager = LDAP3LoginManager()
 bootstrap = Bootstrap()
 admin = Admin(template_mode='bootstrap3')
 mail = Mail()
+jwt = JWTManager()
diff --git a/app/factory.py b/app/factory.py
index b1b2977..941db72 100644
--- a/app/factory.py
+++ b/app/factory.py
@@ -13,10 +13,11 @@ import sqlalchemy as sa
 from flask import Flask
 from flask_admin.contrib.sqla import ModelView
 from . import settings
-from .extensions import db, migrate, login_manager, ldap_manager, bootstrap, admin, mail
+from .extensions import db, migrate, login_manager, ldap_manager, bootstrap, admin, mail, jwt
 from .models import User, Role, Action, Vendor, Model, Location, Status, Item
 from .main.views import bp as main
 from .users.views import bp as users
+from .api.items import bp as api
 from .defaults import defaults
 
 
@@ -84,6 +85,7 @@ def create_app():
     login_manager.login_view = 'users.login'
     ldap_manager.init_app(app)
     mail.init_app(app)
+    jwt.init_app(app)
 
     admin.init_app(app)
     admin.add_view(ModelView(Role, db.session))
@@ -97,6 +99,7 @@ def create_app():
 
     app.register_blueprint(main)
     app.register_blueprint(users)
+    app.register_blueprint(api, url_prefix='/api')
 
     register_cli(app)
 
diff --git a/environment.yml b/environment.yml
index 2cd6683..20d4c15 100644
--- a/environment.yml
+++ b/environment.yml
@@ -48,10 +48,12 @@ dependencies:
   - dominate==2.3.1
   - flask-admin==1.5.0
   - flask-bootstrap==3.3.7.1
+  - flask-jwt-extended==3.1.1
   - flask-ldap3-login==0.9.13
   - flask-mail==0.9.1
   - flask-migrate==2.0.4
   - flask-script==2.0.5
   - ldap3==2.2.4
   - pyasn1==0.2.3
+  - pyjwt==1.4.2
   - visitor==0.1.3
-- 
GitLab