TG-35 : Structure TU + TU LoginAPI
This commit is contained in:
parent
c96d6ad0f8
commit
1b6d51516d
@ -1,6 +1,6 @@
|
|||||||
from flask import session
|
from flask import session
|
||||||
from flask.ext.restful.reqparse import RequestParser
|
|
||||||
from flask_restful import Resource
|
from flask_restful import Resource
|
||||||
|
from flask_restful.reqparse import RequestParser
|
||||||
|
|
||||||
from app.model import *
|
from app.model import *
|
||||||
|
|
||||||
@ -20,14 +20,24 @@ class LoginAPI(Resource):
|
|||||||
|
|
||||||
if userInfo is not None:
|
if userInfo is not None:
|
||||||
query = USER.select(USER.c.login == userInfo["login"])
|
query = USER.select(USER.c.login == userInfo["login"])
|
||||||
|
res = query.execute()
|
||||||
|
user = res.first()
|
||||||
# TODO : check si le user fait partie d'un group actif
|
# TODO : check si le user fait partie d'un group actif
|
||||||
if query.count() == 1:
|
if user is not None:
|
||||||
session['user'] = query.select().execute().first()
|
session['user'] = user.id
|
||||||
return {'AUTH_RESULT': 'OK'}, 200
|
return {'AUTH_RESULT': 'OK'}, 200
|
||||||
else:
|
else:
|
||||||
return {'AUTH_RESULT': 'NOT_ALLOWED'}, 403
|
return {'AUTH_RESULT': 'NOT_ALLOWED'}, 403
|
||||||
else:
|
else:
|
||||||
return {'AUTH_RESULT': 'AUTHENTICATION_FAILED'}, 401
|
return {'AUTH_RESULT': 'AUTHENTICATION_FAILED'}, 401
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
session['user'] = None
|
||||||
|
return {'AUTH_RESULT': 'OK'}, 200
|
||||||
|
|
||||||
def getUserInfoFromCAS(self, login, password):
|
def getUserInfoFromCAS(self, login, password):
|
||||||
pass
|
# TODO : A implémenter
|
||||||
|
if (login == "admin" or login == "toto") and password == login:
|
||||||
|
return {"login": login}
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
@ -2,6 +2,9 @@ import random
|
|||||||
import string
|
import string
|
||||||
from hashlib import sha512
|
from hashlib import sha512
|
||||||
|
|
||||||
|
from flask import json
|
||||||
|
from sqlalchemy.ext.declarative import DeclarativeMeta
|
||||||
|
|
||||||
SIMPLE_CHARS = string.ascii_letters + string.digits
|
SIMPLE_CHARS = string.ascii_letters + string.digits
|
||||||
|
|
||||||
|
|
||||||
@ -13,3 +16,38 @@ def get_random_hash(length=64):
|
|||||||
hash = sha512()
|
hash = sha512()
|
||||||
hash.update(get_random_string())
|
hash.update(get_random_string())
|
||||||
return hash.hexdigest()[:length]
|
return hash.hexdigest()[:length]
|
||||||
|
|
||||||
|
|
||||||
|
def new_alchemy_encoder(revisit_self=False, fields_to_expand=[]):
|
||||||
|
_visited_objs = []
|
||||||
|
|
||||||
|
class AlchemyEncoder(json.JSONEncoder):
|
||||||
|
def default(self, obj):
|
||||||
|
if isinstance(obj.__class__, DeclarativeMeta):
|
||||||
|
# don't re-visit self
|
||||||
|
if revisit_self:
|
||||||
|
if obj in _visited_objs:
|
||||||
|
return None
|
||||||
|
_visited_objs.append(obj)
|
||||||
|
|
||||||
|
# go through each field in this SQLalchemy class
|
||||||
|
fields = {}
|
||||||
|
for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
|
||||||
|
val = obj.__getattribute__(field)
|
||||||
|
|
||||||
|
# is this field another SQLalchemy object, or a list of SQLalchemy objects?
|
||||||
|
if isinstance(val.__class__, DeclarativeMeta) or (
|
||||||
|
isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
|
||||||
|
# unless we're expanding this field, stop here
|
||||||
|
if field not in fields_to_expand:
|
||||||
|
# not expanding this field: set it to None and continue
|
||||||
|
fields[field] = None
|
||||||
|
continue
|
||||||
|
|
||||||
|
fields[field] = val
|
||||||
|
# a json-encodable dict
|
||||||
|
return fields
|
||||||
|
|
||||||
|
return json.JSONEncoder.default(self, obj)
|
||||||
|
|
||||||
|
return AlchemyEncoder
|
||||||
|
@ -25,7 +25,7 @@ else:
|
|||||||
Config.configure_app(config="prod")
|
Config.configure_app(config="prod")
|
||||||
|
|
||||||
core = importlib.import_module("app.core")
|
core = importlib.import_module("app.core")
|
||||||
model = importlib.import_module("backend.app.model")
|
model = importlib.import_module("app.model")
|
||||||
|
|
||||||
manager = Manager(core.app)
|
manager = Manager(core.app)
|
||||||
manager.add_option("-d", "--debug",
|
manager.add_option("-d", "--debug",
|
||||||
@ -75,7 +75,6 @@ manager.add_command('checkdb', CheckDB())
|
|||||||
class RunTests(Command):
|
class RunTests(Command):
|
||||||
"""Seed the db """
|
"""Seed the db """
|
||||||
def run(self):
|
def run(self):
|
||||||
Config.configure_app(config="test")
|
|
||||||
test_loader = unittest.defaultTestLoader
|
test_loader = unittest.defaultTestLoader
|
||||||
test_runner = unittest.TextTestRunner()
|
test_runner = unittest.TextTestRunner()
|
||||||
test_suite = test_loader.discover('tests')
|
test_suite = test_loader.discover('tests')
|
||||||
|
0
backend/tests/api/__init__.py
Normal file
0
backend/tests/api/__init__.py
Normal file
@ -1,7 +1,8 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
from flask import json
|
from flask import json
|
||||||
|
|
||||||
from backend.app.core import app
|
from app.core import app
|
||||||
import unittest
|
|
||||||
|
|
||||||
|
|
||||||
class AuthTestCase(unittest.TestCase):
|
class AuthTestCase(unittest.TestCase):
|
||||||
|
54
backend/tests/api/test_loginAPI.py
Normal file
54
backend/tests/api/test_loginAPI.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from flask import json
|
||||||
|
|
||||||
|
from app.core import app
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTestCase(unittest.TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.app = app.test_client()
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def login(self, email, password):
|
||||||
|
return self.app.post('/api/login',
|
||||||
|
data=json.dumps(
|
||||||
|
dict(
|
||||||
|
login=email,
|
||||||
|
password=password
|
||||||
|
)
|
||||||
|
), content_type='application/json')
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
return self.app.delete('/api/login')
|
||||||
|
|
||||||
|
def test_login_logout(self):
|
||||||
|
rv = self.login('admin', 'admin')
|
||||||
|
self.assertEqual(rv.status_code, 200, 'Login as admin Failed')
|
||||||
|
|
||||||
|
rv = self.logout()
|
||||||
|
self.assertEqual(rv.status_code, 200, 'Logout Failed')
|
||||||
|
|
||||||
|
rv = self.login('adminx', 'admin')
|
||||||
|
self.assertEqual(rv.status_code, 401, 'Authentication from CAS has not failed for the invalid user xadmin !')
|
||||||
|
|
||||||
|
rv = self.login('admin', 'adminx')
|
||||||
|
self.assertEqual(rv.status_code, 401,
|
||||||
|
'Authentication from CAS has not failed for the invalid password xadmin !')
|
||||||
|
|
||||||
|
rv = self.login('toto', 'toto')
|
||||||
|
self.assertEqual(rv.status_code, 403, 'Authentication shouldn\'t be allowed for user toto !')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
0
backend/tests/tools/__init__.py
Normal file
0
backend/tests/tools/__init__.py
Normal file
0
backend/tests/tools/pdfjinja/__init__.py
Normal file
0
backend/tests/tools/pdfjinja/__init__.py
Normal file
@ -7,7 +7,7 @@ skipsdist = True
|
|||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
commands=
|
commands=
|
||||||
coverage run --source app/api app/tools --omit app/api/*/model.py manage.py runtests
|
coverage run --source app/api,app/tools manage.py -t runtests
|
||||||
coverage report -m
|
coverage report -m
|
||||||
coverage xml
|
coverage xml
|
||||||
coverage html
|
coverage html
|
||||||
|
Reference in New Issue
Block a user