From a81d14b4f83f6307c366dd75b4cbc1de5ae866b8 Mon Sep 17 00:00:00 2001
From: Luka <luka@init.hr>
Date: Thu, 28 Oct 2021 14:09:10 +0000
Subject: [PATCH] feat(Users): Implemented Kratos CRUD

---
 api/users.py                | 38 -------------------------
 app.py                      | 13 ++++-----
 {api => areas}/__init__.py  |  0
 areas/apps/__init__.py      |  1 +
 {api => areas/apps}/apps.py |  2 +-
 areas/auth/__init__.py      |  1 +
 {api => areas/auth}/auth.py |  2 +-
 areas/users/__init__.py     |  1 +
 areas/users/users.py        | 57 +++++++++++++++++++++++++++++++++++++
 helpers/kratos_api.py       | 32 +++++++++++++++++++++
 10 files changed, 99 insertions(+), 48 deletions(-)
 delete mode 100644 api/users.py
 rename {api => areas}/__init__.py (100%)
 create mode 100644 areas/apps/__init__.py
 rename {api => areas/apps}/apps.py (98%)
 create mode 100644 areas/auth/__init__.py
 rename {api => areas/auth}/auth.py (95%)
 create mode 100644 areas/users/__init__.py
 create mode 100644 areas/users/users.py
 create mode 100644 helpers/kratos_api.py

diff --git a/api/users.py b/api/users.py
deleted file mode 100644
index b96a03f6..00000000
--- a/api/users.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from flask import jsonify
-from flask_jwt_extended import jwt_required
-from flask_cors import cross_origin
-
-from . import api_v1
-
-
-USER_DATA = [
-  {"id": 1, "email": "john@doe.com", "name": "John Doe", "status": "active", "last_login": "2021-08-03T07:40:51+00:00"}
-]
-
-
-@api_v1.route('/users', methods=['GET'])
-@jwt_required()
-@cross_origin()
-def get_users():
-    return jsonify(USER_DATA)
-
-
-@api_v1.route('/users', methods=['POST'])
-@jwt_required()
-@cross_origin()
-def post_user():
-    return jsonify(USER_DATA), 201
-
-
-@api_v1.route('/users/<int:id>', methods=['PUT'])
-@jwt_required()
-@cross_origin()
-def put_user(id):
-    return jsonify(USER_DATA)
-
-
-@api_v1.route('/users/<int:id>', methods=['DELETE'])
-@jwt_required()
-@cross_origin()
-def delete_user(id):
-    return jsonify(USER_DATA)
diff --git a/app.py b/app.py
index bbf66e12..2c7d1cfa 100644
--- a/app.py
+++ b/app.py
@@ -1,12 +1,14 @@
 from flask import Flask, jsonify
 from flask_jwt_extended import JWTManager
 from flask_cors import CORS
-import requests
 
+from areas import api_v1
+# There imports are required
+from areas import users
+from areas import apps
+from areas import auth
 from config import *
 
-from api import api_v1, auth, users, apps
-
 app = Flask(__name__)
 cors = CORS(app)
 app.config['SECRET_KEY'] = SECRET_KEY
@@ -26,8 +28,3 @@ def expired_token_callback(*args):
 @app.route('/')
 def index():
     return 'Open App Stack API v1.0'
-
-@app.route('/hello')
-def hello():
-    requests.get('{}/health/ready'.format(KRATOS_URL))
-    return 'Open App Stack API v1.0'
diff --git a/api/__init__.py b/areas/__init__.py
similarity index 100%
rename from api/__init__.py
rename to areas/__init__.py
diff --git a/areas/apps/__init__.py b/areas/apps/__init__.py
new file mode 100644
index 00000000..2dbf1c6c
--- /dev/null
+++ b/areas/apps/__init__.py
@@ -0,0 +1 @@
+from .apps import *
\ No newline at end of file
diff --git a/api/apps.py b/areas/apps/apps.py
similarity index 98%
rename from api/apps.py
rename to areas/apps/apps.py
index af9bcd6e..edfc8521 100644
--- a/api/apps.py
+++ b/areas/apps/apps.py
@@ -2,7 +2,7 @@ from flask import jsonify
 from flask_jwt_extended import jwt_required
 from flask_cors import cross_origin
 
-from . import api_v1
+from areas import api_v1
 
 CONFIG_DATA = [
     {
diff --git a/areas/auth/__init__.py b/areas/auth/__init__.py
new file mode 100644
index 00000000..d7c8ad39
--- /dev/null
+++ b/areas/auth/__init__.py
@@ -0,0 +1 @@
+from .auth import *
\ No newline at end of file
diff --git a/api/auth.py b/areas/auth/auth.py
similarity index 95%
rename from api/auth.py
rename to areas/auth/auth.py
index fb4cdd9d..af89132c 100644
--- a/api/auth.py
+++ b/areas/auth/auth.py
@@ -2,7 +2,7 @@ from flask import request, jsonify
 from flask_jwt_extended import create_access_token
 from flask_cors import cross_origin
 
-from . import api_v1
+from areas import api_v1
 
 USERNAME = 'admin'
 PASSWORD = 'admin'
diff --git a/areas/users/__init__.py b/areas/users/__init__.py
new file mode 100644
index 00000000..642b0709
--- /dev/null
+++ b/areas/users/__init__.py
@@ -0,0 +1 @@
+from .users import *
\ No newline at end of file
diff --git a/areas/users/users.py b/areas/users/users.py
new file mode 100644
index 00000000..7ad285ca
--- /dev/null
+++ b/areas/users/users.py
@@ -0,0 +1,57 @@
+from flask import jsonify, request
+from flask_jwt_extended import jwt_required
+from flask_cors import cross_origin
+
+from areas import api_v1
+from helpers.kratos_api import KratosApi
+
+
+@api_v1.route('/users', methods=['GET'])
+@jwt_required()
+@cross_origin()
+def get_users():
+    res = KratosApi.get('/identities')
+    return jsonify(res.json())
+
+@api_v1.route('/users/<string:id>', methods=['GET'])
+@jwt_required()
+@cross_origin()
+def get_user(id):
+    res = KratosApi.get('/identities/{}'.format(id))
+    return jsonify(res.json())
+
+
+@api_v1.route('/users', methods=['POST'])
+@jwt_required()
+@cross_origin()
+def post_user():
+    data = request.get_json()
+    kratos_data = {
+        "schema_id": "default",
+        "traits": data
+    }
+    res = KratosApi.post('/identities', kratos_data)
+    return jsonify(res.json()), res.status_code
+
+
+@api_v1.route('/users/<string:id>', methods=['PUT'])
+@jwt_required()
+@cross_origin()
+def put_user(id):
+    data = request.get_json()
+    kratos_data = {
+        "schema_id": "default",
+        "traits": data
+    }
+    res = KratosApi.put('/identities/{}'.format(id), kratos_data)
+    return jsonify(res.json()), res.status_code
+
+
+@api_v1.route('/users/<string:id>', methods=['DELETE'])
+@jwt_required()
+@cross_origin()
+def delete_user(id):
+    res = KratosApi.delete('/identities/{}'.format(id))
+    if (res.status_code == 204):
+        return jsonify(), res.status_code
+    return jsonify(res.json()), res.status_code
diff --git a/helpers/kratos_api.py b/helpers/kratos_api.py
new file mode 100644
index 00000000..5a25b311
--- /dev/null
+++ b/helpers/kratos_api.py
@@ -0,0 +1,32 @@
+import requests
+
+from config import *
+
+class KratosApi():
+    @staticmethod
+    def get(url):
+        try:
+            return requests.get('{}{}'.format(KRATOS_URL, url))
+        except:
+            return "Failed to contact Kratos"
+
+    @staticmethod
+    def post(url, data):
+        try:
+            return requests.post('{}{}'.format(KRATOS_URL, url), json=data)
+        except:
+            return "Failed to contact Kratos"
+
+    @staticmethod
+    def put(url, data):
+        try:
+            return requests.put('{}{}'.format(KRATOS_URL, url), json=data)
+        except:
+            return "Failed to contact Kratos"
+
+    @staticmethod
+    def delete(url):
+        try:
+            return requests.delete('{}{}'.format(KRATOS_URL, url))
+        except:
+            return "Failed to contact Kratos"
\ No newline at end of file
-- 
GitLab