diff --git a/backend/app/api/loginAPI.py b/backend/app/api/loginAPI.py index c07702d..b5bfa1e 100644 --- a/backend/app/api/loginAPI.py +++ b/backend/app/api/loginAPI.py @@ -1,6 +1,6 @@ from flask import session -from flask.ext.restful.reqparse import RequestParser from flask_restful import Resource +from flask_restful.reqparse import RequestParser from app.model import * @@ -20,14 +20,24 @@ class LoginAPI(Resource): if userInfo is not None: 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 - if query.count() == 1: - session['user'] = query.select().execute().first() + if user is not None: + session['user'] = user.id return {'AUTH_RESULT': 'OK'}, 200 else: return {'AUTH_RESULT': 'NOT_ALLOWED'}, 403 else: return {'AUTH_RESULT': 'AUTHENTICATION_FAILED'}, 401 + def delete(self): + session['user'] = None + return {'AUTH_RESULT': 'OK'}, 200 + 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 diff --git a/backend/app/utils.py b/backend/app/utils.py index 64e6eda..eb16e2e 100644 --- a/backend/app/utils.py +++ b/backend/app/utils.py @@ -2,6 +2,9 @@ import random import string from hashlib import sha512 +from flask import json +from sqlalchemy.ext.declarative import DeclarativeMeta + SIMPLE_CHARS = string.ascii_letters + string.digits @@ -13,3 +16,38 @@ def get_random_hash(length=64): hash = sha512() hash.update(get_random_string()) 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 diff --git a/backend/manage.py b/backend/manage.py index 82c0eb5..a4ca31a 100644 --- a/backend/manage.py +++ b/backend/manage.py @@ -25,7 +25,7 @@ else: Config.configure_app(config="prod") core = importlib.import_module("app.core") -model = importlib.import_module("backend.app.model") +model = importlib.import_module("app.model") manager = Manager(core.app) manager.add_option("-d", "--debug", @@ -75,7 +75,6 @@ manager.add_command('checkdb', CheckDB()) class RunTests(Command): """Seed the db """ def run(self): - Config.configure_app(config="test") test_loader = unittest.defaultTestLoader test_runner = unittest.TextTestRunner() test_suite = test_loader.discover('tests') diff --git a/backend/tests/api/__init__.py b/backend/tests/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/api/example_test_someapi.py b/backend/tests/api/example_test_someapi.py index 12c3594..8f7aa85 100644 --- a/backend/tests/api/example_test_someapi.py +++ b/backend/tests/api/example_test_someapi.py @@ -1,7 +1,8 @@ +import unittest + from flask import json -from backend.app.core import app -import unittest +from app.core import app class AuthTestCase(unittest.TestCase): diff --git a/backend/tests/api/test_loginAPI.py b/backend/tests/api/test_loginAPI.py new file mode 100644 index 0000000..84b0ded --- /dev/null +++ b/backend/tests/api/test_loginAPI.py @@ -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() diff --git a/backend/tests/tools/__init__.py b/backend/tests/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/tools/pdfjinja/__init__.py b/backend/tests/tools/pdfjinja/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tox.ini b/backend/tox.ini index cdb5ede..0ab37a0 100644 --- a/backend/tox.ini +++ b/backend/tox.ini @@ -7,7 +7,7 @@ skipsdist = True [testenv] 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 xml coverage html