Skip to content

Instantly share code, notes, and snippets.

@SakiiR
Last active November 13, 2017 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SakiiR/02d3a211336c622b53e060cf1f134bc5 to your computer and use it in GitHub Desktop.
Save SakiiR/02d3a211336c622b53e060cf1f134bc5 to your computer and use it in GitHub Desktop.
Démonstration DFA

Demo DFA BACK

Dépot Dev / Prod

  • Un dépot prévu pour le déploiement de toutes les applications (FRONT, DSL et BACK)
  • Fichier de configuration pour tout les dépots (config.py pour les dépots back)

Docker compose production

version: '3'
services:
    dfa_back_api_server:
        build: './dfa-back-api-server'
        ports:
            - '1337:1337'
    dfa_back_worker:
        build: './dfa-back-worker'
        # ports:
        #   - '4243:4243'
    mongo:
        image: 'mongo'
        # ports:
        #   - '27017:27017'
    rabbitmq:
        image: 'rabbitmq'
        # ports:
        #   - '5672:5672'

Fichier de configuration API

from dfa_api.resources.datasource.config import datasource_schema
from dfa_api.resources.model.config import model_schema
from dfa_api.resources.project.config import project_schema
from dfa_api.resources.result.config import result_schema
from dfa_api.resources.rule.config import rule_schema
from dfa_api.token import MyTokenAuth
import os


API_PORT = 1337
API_HOST = '0.0.0.0'


MONGO_HOST = 'localhost'
if os.environ.get('MONGO_HOST'):
    MONGO_HOST = os.environ.get('MONGO_HOST')

MONGO_PORT = 27017
if os.environ.get('MONGO_PORT'):
    MONGO_PORT = int(os.environ.get('MONGO_PORT'))

MONGO_USERNAME = ''
MONGO_PASSWORD = ''
MONGO_DBNAME = 'dfa'

WORKER_BASE_URL = "http://localhost:4243"
WORKER_TOKEN = "random_token"

MONGO_URII = "mongodb://{host}:{port}/{dbname}".format(host=MONGO_HOST, port=MONGO_PORT, dbname=MONGO_DBNAME)

TOKEN_CHARSET = ("abcdefghijklmnopqrstuvwxyz"
                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                 "0123456789")

TOKEN_LENGTH = 64

SUPERADMIN_EMAIL = 'admin'
SUPERADMIN_PASSWORD = 'password'

# App config
X_DOMAINS = '*'

X_HEADERS = [
    'Authorization',
    'If-Match',
    'Access-Control-Expose-Headers',
    'Content-Type',
    'Pragma',
    'Cache-Control'
]

X_EXPOSE_HEADERS = [
    'Origin',
    'X-Requested-With',
    'Content-Type',
    'Accept'
]

SOFT_DELETE = True

PAGINATION_LIMIT = 500

MONGO_QUERY_BLACKLIST = ['$where']

RESOURCE_METHODS = ['GET', 'POST', 'DELETE']
ITEM_METHODS = ['GET', 'PATCH', 'DELETE']


# Eve-Rights
ACCOUNT_RESOURCE = "user"
RESOURCE_BLACKLIST = []
ACL_FIELDS_READ = "w_reads"
ACL_FIELDS_WRITE = "w_writes"
RESTRICTED_RESOURCES = ['project']

DOMAIN = {
    'project': {
        'item_title': 'project',
        'authentication': MyTokenAuth(),
        'schema': {
            'w_reads': { 'type': 'list', 'default': [], 'schema': { 'type': 'objectid', 'data_relation': { 'resource': ACCOUNT_RESOURCE, 'field': '_id', }, } },
            'w_writes': { 'type': 'list', 'default': [], 'schema': { 'type': 'objectid', 'data_relation': { 'resource': ACCOUNT_RESOURCE, 'field': '_id', }, } },
            'name': {
                'type': 'string',
                'required': True,
                'minlength': 1,
                'maxlength': 50,
            },
            'description': {
                'type': 'string',
                'minlength': 1,
                'maxlength': 256,
            }
        },
        'description': "L'api projet permet de créer, éditer, chercher et supprimer un projet"
    },
    'datasource': {
        'item_title': 'datasource',
        'authentication': MyTokenAuth(),
        'schema': datasource_schema,
        'description': "L'api datasource permet de créer, éditer, chercher et supprimer un source de donnée"
    },
    'rule': {
        'item_title': 'rule',
        'authentication': MyTokenAuth(),
        'schema': rule_schema,
        'description': "L'api rule permet de créer, éditer, chercher et supprimer un règle"
    },
    'model': {
        'item_title': 'model',
        'authentication': MyTokenAuth(),
        'schema': model_schema,
        'description': "L'api model permet de créer, éditer, chercher et supprimer un modèle"
    },
    'result': {
        'item_title': 'result',
        'authentication': MyTokenAuth(),
        'schema': result_schema,
        'description': "L'api result permet de créer, éditer, chercher et supprimer un résultat d'éxecution de règle"
    },
    'user': {
        'description': "Utilisateur de l'application",
        'authentication': MyTokenAuth(),
        'schema': {
            'email': {
                'type': 'string',
                'minlength': 1,
                'maxlength': 10
            },
            'password': {
                'type': 'string',
            },
            'token': {
                'type': 'string',
            }
        }
    }
}

Root endpoint

http 'http://localhost:1337/'
HTTP/1.0 200 OK
Content-Length: 257
Content-Type: application/json
Date: Mon, 13 Nov 2017 19:49:53 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3

{
    "_links": {
        "child": [
            {
                "href": "project",
                "title": "project"
            },
            {
                "href": "datasource",
                "title": "datasource"
            },
            {
                "href": "rule",
                "title": "rule"
            },
            {
                "href": "model",
                "title": "model"
            },
            {
                "href": "result",
                "title": "result"
            },
            {
                "href": "user",
                "title": "user"
            }
        ]
    }
}

Authorization Failed

http 'http://localhost:1337/project'
HTTP/1.0 401 UNAUTHORIZED
Content-Length: 91
Content-Type: application/json
Date: Mon, 13 Nov 2017 19:51:58 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3
WWW-Authenticate: Basic realm="eve"

{
    "_error": {
        "code": 401,
        "message": "Please provide proper credentials"
    },
    "_status": "ERR"
}

Authentication

Comptes

admin:password
erwan:123456

Success

  • Récupération d'un token valide ( Sans expiration )
  • Information utilisateurs retournées
  • Token unique par compte (pas de connexions simultanées)
http POST 'http://localhost:1337/login' 'email=admin' 'password=password'
HTTP/1.0 200 OK
Content-Length: 405
Content-Type: application/json
Date: Mon, 13 Nov 2017 19:53:58 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3

{
    "message": "successfully logged in",
    "success": true,
    "user": {
        "_created": "Mon, 13 Nov 2017 20:49:45 GMT",
        "_deleted": false,
        "_etag": "bc4919c6adf7168088eaea06e27a5b23f0f9f9da",
        "_id": "5a09f759caef344d41a4ca02",
        "_updated": "Mon, 13 Nov 2017 20:49:45 GMT",
        "email": "admin",
        "token": "T0mHM5ZCwYCBB9G8DcrJVvq2HxcDhNdKdFOxWagZZzUSuVZHKgsh5OJ2wAp0aXUD"
    }
}

Failure

  • Le message ne diffère pas enfonction du champ invalide
  • Booléen success passé à false
http POST 'http://localhost:1337/login' 'email=admin' 'password=bad_password'
HTTP/1.0 401 UNAUTHORIZED
Content-Length: 70
Content-Type: application/json
Date: Mon, 13 Nov 2017 19:55:23 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3

{
    "message": "Failed: bad email or password",
    "success": false
}

Authorization success

  • Token valide envoyé dans le header HTTP Authorization
  • SCRUD générique pour toutes les ressources (à présenter par Yohan)
  • Listing des compte avec un compte superadmin
http 'http://localhost:1337/user' 'Authorization: T0mHM5ZCwYCBB9G8DcrJVvq2HxcDhNdKdFOxWagZZzUSuVZHKgsh5OJ2wAp0aXUD'
HTTP/1.0 200 OK
Content-Length: 618
Content-Type: application/json
Date: Mon, 13 Nov 2017 20:11:41 GMT
Last-Modified: Mon, 13 Nov 2017 20:49:45 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3
X-Total-Count: 1

{
    "_items": [
        {
            "_created": "Mon, 13 Nov 2017 20:49:45 GMT",
            "_deleted": false,
            "_etag": "bc4919c6adf7168088eaea06e27a5b23f0f9f9da",
            "_id": "5a09f759caef344d41a4ca02",
            "_links": {
                "self": {
                    "href": "user/5a09f759caef344d41a4ca02",
                    "title": "User"
                }
            },
            "_updated": "Mon, 13 Nov 2017 20:49:45 GMT",
            "email": "admin",
            "password": "pbkdf2:sha1:1000$WjYyMqK4$0d3e4368ba78337fa3c277c62d2b9157f214a9a8",
            "token": "T0mHM5ZCwYCBB9G8DcrJVvq2HxcDhNdKdFOxWagZZzUSuVZHKgsh5OJ2wAp0aXUD"
        }
    ],
    "_links": {
        "parent": {
            "href": "/",
            "title": "home"
        },
        "self": {
            "href": "user",
            "title": "user"
        }
    },
    "_meta": {
        "max_results": 25,
        "page": 1,
        "total": 1
    }
}

Creating account

Generating password

In [1]: from werkzeug.security import check_password_hash, generate_password_hash

In [2]: encrypted = generate_password_hash("123456")

In [3]: check_password_hash(encrypted, "123456")
Out[3]: True

In [4]: check_password_hash(encrypted, "123")
Out[4]: False

In [5]: print(encrypted)
pbkdf2:sha1:1000$JXhUHrs7$77f2d255d5bd934c943c94b8874d82162411e92f

Requesting API

POST /user HTTP/1.1
Accept: application/json, */*
Accept-Encoding: gzip, deflate
Authorization: T0mHM5ZCwYCBB9G8DcrJVvq2HxcDhNdKdFOxWagZZzUSuVZHKgsh5OJ2wAp0aXUD
Connection: keep-alive
Content-Length: 121
Content-Type: application/json
Host: localhost:1337
User-Agent: HTTPie/0.9.9

{
    "email": "erwan.dupard@dataforall.fr",
    "password": "pbkdf2:sha1:1000$JXhUHrs7$77f2d255d5bd934c943c94b8874d82162411e92f"
}
HTTP/1.0 201 CREATED
Content-Length: 294
Content-Type: application/json
Date: Mon, 13 Nov 2017 20:20:58 GMT
Location: http://localhost:1337/user/5a09feaacaef345d4cf22ab2
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3

{
    "_created": "Mon, 13 Nov 2017 20:20:58 GMT",
    "_deleted": false,
    "_etag": "a2f0e7884405ef8d7bb36480a1f8a061ffb72f0e",
    "_id": "5a09feaacaef345d4cf22ab2",
    "_links": {
        "self": {
            "href": "user/5a09feaacaef345d4cf22ab2",
            "title": "User"
        }
    },
    "_status": "OK",
    "_updated": "Mon, 13 Nov 2017 20:20:58 GMT"
}
http 'http://localhost:1337/user' 'Authorization: T0mHM5ZCwYCBB9G8DcrJVvq2HxcDhNdKdFOxWagZZzUSuVZHKgsh5OJ2wAp0aXUD'
HTTP/1.0 200 OK
Content-Type: application/json
Date: Mon, 13 Nov 2017 20:25:41 GMT
Last-Modified: Mon, 13 Nov 2017 21:20:07 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3
X-Total-Count: 3

{
    "_items": [
        {
            "_created": "Mon, 13 Nov 2017 21:20:07 GMT",
            "_deleted": false,
            "_etag": "bc4919c6adf7168088eaea06e27a5b23f0f9f9da",
            "_id": "5a09fe77caef345d4cf22ab1",
            "_links": {
                "self": {
                    "href": "user/5a09fe77caef345d4cf22ab1",
                    "title": "User"
                }
            },
            "_updated": "Mon, 13 Nov 2017 21:20:07 GMT",
            "email": "admin",
            "password": "pbkdf2:sha1:1000$aW0gmm6n$d56eea980e127d20a16c78a82a9893b7c847560c",
            "token": "XM1aNzK1DbNfciCmrU3cIhHBC71VP2iEVlj6RfVevXw31IejuQy3LadPTfoxULBA"
        },
        {
            "_created": "Mon, 13 Nov 2017 20:23:16 GMT",
            "_deleted": false,
            "_etag": "55606f1539b2f46f2ab3de77a91e857271fa4db4",
            "_id": "5a09ff34caef345d4cf22ab3",
            "_links": {
                "self": {
                    "href": "user/5a09ff34caef345d4cf22ab3",
                    "title": "User"
                }
            },
            "_updated": "Mon, 13 Nov 2017 20:23:16 GMT",
            "email": "erwan.dupard@dataforall.fr",
            "password": "pbkdf2:sha1:1000$JXhUHrs7$77f2d255d5bd934c943c94b8874d82162411e92f"
        }
    ],
    "_links": {
        "parent": {
            "href": "/",
            "title": "home"
        },
        "self": {
            "href": "user",
            "title": "user"
        }
    },
    "_meta": {
        "max_results": 25,
        "page": 1,
        "total": 3
    }
}

ACL

  • Configuration des token dans des variables d'environnement
set -gx TOKEN_ERWAN "Z7qRhhe05dmycWVyiaAyoULrFUlqJ9DjfsRVSVP4lEd3GdqNJys8d5WVBDxRTH68"
set -gx TOKEN_ADMIN "yl0dq6oPz1hmEHm7gpvmUH7zxHNijckmKu5UhavUq7TjGejVuJH1JwXsMP43I3Yw"
  • Creation d'un projet en tant qu'admin et en tant que erwan
http POST 'http://localhost:1337/project' "Authorization: $TOKEN_ADMIN" 'name=project_admin' 'description=projet de admin'
http POST 'http://localhost:1337/project' "Authorization: $TOKEN_ERWAN" 'name=project_erwan' 'description=projet de erwan'
  • Listing des projets en tant qu'admin
HTTP/1.0 200 OK
Content-Length: 595
Content-Type: application/json
Date: Mon, 13 Nov 2017 20:45:35 GMT
Last-Modified: Mon, 13 Nov 2017 20:44:04 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3
X-Total-Count: 1

{
    "_items": [
        {
            "_created": "Mon, 13 Nov 2017 20:44:04 GMT",
            "_deleted": false,
            "_etag": "78b21e48a39be1f9753134875be24758db491e80",
            "_id": "5a0a0414caef345d4cf22ab4",
            "_links": {
                "self": {
                    "href": "project/5a0a0414caef345d4cf22ab4",
                    "title": "project"
                }
            },
            "_updated": "Mon, 13 Nov 2017 20:44:04 GMT",
            "description": "projet de admin",
            "name": "project_admin",
            "w_reads": [
                "5a09fe77caef345d4cf22ab1"
            ],
            "w_writes": [
                "5a09fe77caef345d4cf22ab1"
            ]
        }
    ],
    "_links": {
        "parent": {
            "href": "/",
            "title": "home"
        },
        "self": {
            "href": "project",
            "title": "project"
        }
    },
    "_meta": {
        "max_results": 25,
        "page": 1,
        "total": 1
    }
}
  • Listing des projets en tant qu'erwan
HTTP/1.0 200 OK
Content-Length: 170
Content-Type: application/json
Date: Mon, 13 Nov 2017 20:46:39 GMT
Server: Eve/0.7.4 Werkzeug/0.11.15 Python/3.6.3
X-Total-Count: 0

{
    "_items": [],
    "_links": {
        "parent": {
            "href": "/",
            "title": "home"
        },
        "self": {
            "href": "project",
            "title": "project"
        }
    },
    "_meta": {
        "max_results": 25,
        "page": 1,
        "total": 0
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment