flask-appbuilder 3.2.1rc1__py3-none-any.whl → 5.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flask_appbuilder/__init__.py +2 -3
- flask_appbuilder/_compat.py +0 -1
- flask_appbuilder/actions.py +14 -14
- flask_appbuilder/api/__init__.py +741 -527
- flask_appbuilder/api/convert.py +104 -98
- flask_appbuilder/api/manager.py +14 -8
- flask_appbuilder/api/schemas.py +12 -1
- flask_appbuilder/babel/manager.py +12 -16
- flask_appbuilder/base.py +353 -280
- flask_appbuilder/basemanager.py +1 -1
- flask_appbuilder/baseviews.py +241 -164
- flask_appbuilder/charts/jsontools.py +10 -10
- flask_appbuilder/charts/views.py +56 -60
- flask_appbuilder/cli.py +115 -70
- flask_appbuilder/const.py +52 -52
- flask_appbuilder/exceptions.py +67 -5
- flask_appbuilder/fields.py +32 -23
- flask_appbuilder/fieldwidgets.py +34 -27
- flask_appbuilder/filemanager.py +33 -45
- flask_appbuilder/filters.py +11 -13
- flask_appbuilder/forms.py +31 -35
- flask_appbuilder/hooks.py +90 -0
- flask_appbuilder/menu.py +35 -10
- flask_appbuilder/models/base.py +47 -57
- flask_appbuilder/models/decorators.py +13 -13
- flask_appbuilder/models/filters.py +42 -38
- flask_appbuilder/models/generic/__init__.py +29 -29
- flask_appbuilder/models/generic/filters.py +11 -3
- flask_appbuilder/models/generic/interface.py +1 -3
- flask_appbuilder/models/group.py +37 -39
- flask_appbuilder/models/mixins.py +22 -18
- flask_appbuilder/models/sqla/__init__.py +19 -72
- flask_appbuilder/models/sqla/base.py +24 -0
- flask_appbuilder/models/sqla/base_legacy.py +132 -0
- flask_appbuilder/models/sqla/filters.py +132 -19
- flask_appbuilder/models/sqla/interface.py +390 -276
- flask_appbuilder/security/api.py +31 -35
- flask_appbuilder/security/decorators.py +181 -83
- flask_appbuilder/security/forms.py +20 -31
- flask_appbuilder/security/manager.py +715 -489
- flask_appbuilder/security/registerviews.py +29 -112
- flask_appbuilder/security/schemas.py +43 -0
- flask_appbuilder/security/sqla/apis/__init__.py +8 -0
- flask_appbuilder/security/sqla/apis/group/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/group/api.py +227 -0
- flask_appbuilder/security/sqla/apis/group/schema.py +73 -0
- flask_appbuilder/security/sqla/apis/permission/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/permission/api.py +19 -0
- flask_appbuilder/security/sqla/apis/permission_view_menu/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/permission_view_menu/api.py +16 -0
- flask_appbuilder/security/sqla/apis/role/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/role/api.py +306 -0
- flask_appbuilder/security/sqla/apis/role/schema.py +27 -0
- flask_appbuilder/security/sqla/apis/user/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/user/api.py +292 -0
- flask_appbuilder/security/sqla/apis/user/schema.py +97 -0
- flask_appbuilder/security/sqla/apis/user/validator.py +27 -0
- flask_appbuilder/security/sqla/apis/view_menu/__init__.py +1 -0
- flask_appbuilder/security/sqla/apis/view_menu/api.py +18 -0
- flask_appbuilder/security/sqla/manager.py +421 -203
- flask_appbuilder/security/sqla/models.py +192 -57
- flask_appbuilder/security/utils.py +9 -0
- flask_appbuilder/security/views.py +232 -229
- flask_appbuilder/static/.DS_Store +0 -0
- flask_appbuilder/static/appbuilder/css/ab.css +20 -12
- flask_appbuilder/static/appbuilder/css/bootstrap-datepicker/bootstrap-datepicker3.min.css +7 -0
- flask_appbuilder/static/appbuilder/css/bootstrap.min.css.map +1 -0
- flask_appbuilder/static/appbuilder/css/flags/flags16.css +249 -245
- flask_appbuilder/static/appbuilder/css/fontawesome/all.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/brands.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/fontawesome.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/regular.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/solid.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/svg-with-js.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v4-font-face.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v4-shims.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/fontawesome/v5-font-face.min.css +6 -0
- flask_appbuilder/static/appbuilder/css/images/flags16.png +0 -0
- flask_appbuilder/static/appbuilder/css/select2/select2-bootstrap.min.css +7 -0
- flask_appbuilder/static/appbuilder/css/select2/select2.min.css +1 -0
- flask_appbuilder/static/appbuilder/css/swagger/swagger-ui.css +3 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-brands-400.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-regular-400.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-solid-900.woff2 +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.ttf +0 -0
- flask_appbuilder/static/appbuilder/css/webfonts/fa-v4compatibility.woff2 +0 -0
- flask_appbuilder/static/appbuilder/js/ab.js +33 -23
- flask_appbuilder/static/appbuilder/js/ab_filters.js +91 -84
- flask_appbuilder/static/appbuilder/js/bootstrap-datepicker/bootstrap-datepicker.min.js +8 -0
- flask_appbuilder/static/appbuilder/js/jquery-latest.js +2 -2
- flask_appbuilder/static/appbuilder/js/select2/select2.min.js +2 -0
- flask_appbuilder/static/appbuilder/js/swagger-ui-bundle.js +3 -0
- flask_appbuilder/templates/appbuilder/baselib.html +9 -3
- flask_appbuilder/templates/appbuilder/general/lib.html +60 -34
- flask_appbuilder/templates/appbuilder/general/model/edit.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/edit_cascade.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/search.html +3 -2
- flask_appbuilder/templates/appbuilder/general/model/show.html +1 -1
- flask_appbuilder/templates/appbuilder/general/model/show_cascade.html +1 -1
- flask_appbuilder/templates/appbuilder/general/security/login_db.html +7 -7
- flask_appbuilder/templates/appbuilder/general/security/login_ldap.html +5 -5
- flask_appbuilder/templates/appbuilder/general/security/login_oauth.html +24 -49
- flask_appbuilder/templates/appbuilder/general/widgets/base_list.html +2 -1
- flask_appbuilder/templates/appbuilder/general/widgets/chart.html +4 -2
- flask_appbuilder/templates/appbuilder/general/widgets/direct_chart.html +4 -3
- flask_appbuilder/templates/appbuilder/general/widgets/multiple_chart.html +3 -2
- flask_appbuilder/templates/appbuilder/general/widgets/search.html +11 -10
- flask_appbuilder/templates/appbuilder/init.html +37 -43
- flask_appbuilder/templates/appbuilder/navbar_menu.html +1 -1
- flask_appbuilder/templates/appbuilder/navbar_right.html +2 -2
- flask_appbuilder/templates/appbuilder/swagger/swagger.html +22 -19
- flask_appbuilder/translations/de/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/de/LC_MESSAGES/messages.po +305 -161
- flask_appbuilder/translations/fa/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/fa/LC_MESSAGES/messages.po +802 -0
- flask_appbuilder/translations/fr/LC_MESSAGES/messages.po +461 -319
- flask_appbuilder/translations/pt_BR/LC_MESSAGES/messages.po +650 -650
- flask_appbuilder/translations/ru/LC_MESSAGES/messages.po +1 -1
- flask_appbuilder/translations/sl/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/sl/LC_MESSAGES/messages.po +690 -0
- flask_appbuilder/translations/tr/LC_MESSAGES/messages.mo +0 -0
- flask_appbuilder/translations/tr/LC_MESSAGES/messages.po +1015 -0
- flask_appbuilder/upload.py +20 -22
- flask_appbuilder/urltools.py +39 -19
- flask_appbuilder/utils/base.py +76 -0
- flask_appbuilder/utils/legacy.py +33 -0
- flask_appbuilder/utils/limit.py +20 -0
- flask_appbuilder/validators.py +73 -14
- flask_appbuilder/views.py +75 -424
- flask_appbuilder/widgets.py +50 -51
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/METADATA +36 -76
- flask_appbuilder-5.0.2.dist-info/RECORD +240 -0
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/WHEEL +1 -1
- flask_appbuilder-5.0.2.dist-info/entry_points.txt +2 -0
- Flask_AppBuilder-3.2.1rc1.dist-info/RECORD +0 -270
- Flask_AppBuilder-3.2.1rc1.dist-info/entry_points.txt +0 -6
- flask_appbuilder/console.py +0 -426
- flask_appbuilder/models/mongoengine/__init__.py +0 -0
- flask_appbuilder/models/mongoengine/fields.py +0 -65
- flask_appbuilder/models/mongoengine/filters.py +0 -145
- flask_appbuilder/models/mongoengine/interface.py +0 -328
- flask_appbuilder/security/mongoengine/__init__.py +0 -0
- flask_appbuilder/security/mongoengine/manager.py +0 -402
- flask_appbuilder/security/mongoengine/models.py +0 -120
- flask_appbuilder/static/appbuilder/css/font-awesome.min.css +0 -4
- flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.css +0 -9
- flask_appbuilder/static/appbuilder/datepicker/bootstrap-datepicker.js +0 -28
- flask_appbuilder/static/appbuilder/fonts/FontAwesome.otf +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.eot +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.svg +0 -2671
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.ttf +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff +0 -0
- flask_appbuilder/static/appbuilder/fonts/fontawesome-webfont.woff2 +0 -0
- flask_appbuilder/static/appbuilder/img/aol.png +0 -0
- flask_appbuilder/static/appbuilder/img/flags/flags16.png +0 -0
- flask_appbuilder/static/appbuilder/img/flickr.png +0 -0
- flask_appbuilder/static/appbuilder/img/google.png +0 -0
- flask_appbuilder/static/appbuilder/img/myopenid.png +0 -0
- flask_appbuilder/static/appbuilder/img/yahoo.png +0 -0
- flask_appbuilder/static/appbuilder/js/_google_charts.js +0 -39
- flask_appbuilder/static/appbuilder/js/html5shiv.js +0 -8
- flask_appbuilder/static/appbuilder/js/respond.min.js +0 -6
- flask_appbuilder/static/appbuilder/select2/select2-spinner.gif +0 -0
- flask_appbuilder/static/appbuilder/select2/select2.css +0 -1205
- flask_appbuilder/static/appbuilder/select2/select2.js +0 -23
- flask_appbuilder/static/appbuilder/select2/select2.png +0 -0
- flask_appbuilder/static/appbuilder/select2/select2x2.png +0 -0
- flask_appbuilder/templates/appbuilder/general/security/login_oid.html +0 -129
- flask_appbuilder/templates/appbuilder/general/security/resetpassword.html +0 -29
- flask_appbuilder/tests/__init__.py +0 -0
- flask_appbuilder/tests/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_auth_ldap.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_auth_oauth.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_ldapsearch.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/_test_oauth_registration_role.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/base.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/base.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/config_api.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/config_api.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/const.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/const.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_0_fixture.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_api.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_api.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_fab_cli.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_menu.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_menu.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mongoengine.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mvc.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_mvc.cpython-37.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-36.pyc +0 -0
- flask_appbuilder/tests/__pycache__/test_sqlalchemy.cpython-37.pyc +0 -0
- flask_appbuilder/tests/_test_auth_ldap.py +0 -1045
- flask_appbuilder/tests/_test_auth_oauth.py +0 -419
- flask_appbuilder/tests/_test_ldapsearch.py +0 -135
- flask_appbuilder/tests/_test_oauth_registration_role.py +0 -59
- flask_appbuilder/tests/app.db +0 -0
- flask_appbuilder/tests/base.py +0 -90
- flask_appbuilder/tests/config_api.py +0 -21
- flask_appbuilder/tests/const.py +0 -9
- flask_appbuilder/tests/mongoengine/__init__.py +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/mongoengine/__pycache__/models.cpython-36.pyc +0 -0
- flask_appbuilder/tests/mongoengine/models.py +0 -41
- flask_appbuilder/tests/sqla/__init__.py +0 -0
- flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/__init__.cpython-37.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/models.cpython-36.pyc +0 -0
- flask_appbuilder/tests/sqla/__pycache__/models.cpython-37.pyc +0 -0
- flask_appbuilder/tests/sqla/models.py +0 -340
- flask_appbuilder/tests/test_0_fixture.py +0 -39
- flask_appbuilder/tests/test_api.py +0 -2790
- flask_appbuilder/tests/test_fab_cli.py +0 -72
- flask_appbuilder/tests/test_menu.py +0 -122
- flask_appbuilder/tests/test_mongoengine.py +0 -572
- flask_appbuilder/tests/test_mvc.py +0 -1710
- flask_appbuilder/tests/test_sqlalchemy.py +0 -24
- flask_appbuilder/translations/__pycache__/__init__.cpython-36.pyc +0 -0
- flask_appbuilder/translations/es/LC_MESSAGES/messages.po~ +0 -582
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/LICENSE +0 -0
- {Flask_AppBuilder-3.2.1rc1.dist-info → flask_appbuilder-5.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,1045 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import os
|
|
3
|
-
import unittest
|
|
4
|
-
from unittest.mock import patch
|
|
5
|
-
|
|
6
|
-
from flask import Flask
|
|
7
|
-
from flask_appbuilder import AppBuilder, SQLA
|
|
8
|
-
from flask_appbuilder.security.manager import AUTH_LDAP
|
|
9
|
-
import jinja2
|
|
10
|
-
import ldap
|
|
11
|
-
from mockldap import MockLdap
|
|
12
|
-
|
|
13
|
-
logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
|
|
14
|
-
logging.getLogger().setLevel(logging.DEBUG)
|
|
15
|
-
log = logging.getLogger(__name__)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class LDAPSearchTestCase(unittest.TestCase):
|
|
19
|
-
@classmethod
|
|
20
|
-
def setUpClass(cls):
|
|
21
|
-
cls.mockldap = MockLdap(cls.directory)
|
|
22
|
-
|
|
23
|
-
@classmethod
|
|
24
|
-
def tearDownClass(cls):
|
|
25
|
-
del cls.mockldap
|
|
26
|
-
|
|
27
|
-
def setUp(self):
|
|
28
|
-
# start MockLdap
|
|
29
|
-
self.mockldap.start()
|
|
30
|
-
self.ldapobj = self.mockldap["ldap://localhost/"]
|
|
31
|
-
|
|
32
|
-
# start Flask
|
|
33
|
-
self.app = Flask(__name__)
|
|
34
|
-
self.app.jinja_env.undefined = jinja2.StrictUndefined
|
|
35
|
-
self.app.config["SQLALCHEMY_DATABASE_URI"] = os.environ.get(
|
|
36
|
-
"SQLALCHEMY_DATABASE_URI"
|
|
37
|
-
)
|
|
38
|
-
self.app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
|
|
39
|
-
self.app.config["AUTH_TYPE"] = AUTH_LDAP
|
|
40
|
-
self.app.config["AUTH_LDAP_SERVER"] = "ldap://localhost/"
|
|
41
|
-
self.app.config["AUTH_LDAP_UID_FIELD"] = "uid"
|
|
42
|
-
self.app.config["AUTH_LDAP_FIRSTNAME_FIELD"] = "givenName"
|
|
43
|
-
self.app.config["AUTH_LDAP_LASTNAME_FIELD"] = "sn"
|
|
44
|
-
self.app.config["AUTH_LDAP_EMAIL_FIELD"] = "email"
|
|
45
|
-
|
|
46
|
-
# start Database
|
|
47
|
-
self.db = SQLA(self.app)
|
|
48
|
-
|
|
49
|
-
def tearDown(self):
|
|
50
|
-
# stop MockLdap
|
|
51
|
-
self.mockldap.stop()
|
|
52
|
-
del self.ldapobj
|
|
53
|
-
|
|
54
|
-
# stop Flask
|
|
55
|
-
self.app = None
|
|
56
|
-
|
|
57
|
-
# stop Flask-AppBuilder
|
|
58
|
-
self.appbuilder = None
|
|
59
|
-
|
|
60
|
-
# stop Database
|
|
61
|
-
self.db.session.remove()
|
|
62
|
-
self.db.drop_all()
|
|
63
|
-
self.db = None
|
|
64
|
-
|
|
65
|
-
# ----------------
|
|
66
|
-
# LDAP Directory
|
|
67
|
-
# ----------------
|
|
68
|
-
top = ("o=test", {"o": ["test"]})
|
|
69
|
-
ou_users = ("ou=users,o=test", {"ou": ["users"]})
|
|
70
|
-
ou_groups = ("ou=groups,o=test", {"ou": ["groups"]})
|
|
71
|
-
user_admin = (
|
|
72
|
-
"uid=admin,ou=users,o=test",
|
|
73
|
-
{"uid": ["admin"], "userPassword": ["admin_password"]},
|
|
74
|
-
)
|
|
75
|
-
user_alice = (
|
|
76
|
-
"uid=alice,ou=users,o=test",
|
|
77
|
-
{
|
|
78
|
-
"uid": ["alice"],
|
|
79
|
-
"userPassword": ["alice_password"],
|
|
80
|
-
"memberOf": [b"cn=staff,ou=groups,o=test"],
|
|
81
|
-
"givenName": [b"Alice"],
|
|
82
|
-
"sn": [b"Doe"],
|
|
83
|
-
"email": [b"alice@example.com"],
|
|
84
|
-
},
|
|
85
|
-
)
|
|
86
|
-
group_admins = (
|
|
87
|
-
"cn=admins,ou=groups,o=test",
|
|
88
|
-
{"cn": ["admins"], "member": [user_admin[0]]},
|
|
89
|
-
)
|
|
90
|
-
group_staff = (
|
|
91
|
-
"cn=staff,ou=groups,o=test",
|
|
92
|
-
{"cn": ["staff"], "member": [user_alice[0]]},
|
|
93
|
-
)
|
|
94
|
-
directory = dict(
|
|
95
|
-
[top, ou_users, ou_groups, user_admin, user_alice, group_admins, group_staff]
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
# ----------------
|
|
99
|
-
# LDAP Queries
|
|
100
|
-
# ----------------
|
|
101
|
-
call_initialize = ("initialize", tuple(["ldap://localhost/"]), {})
|
|
102
|
-
|
|
103
|
-
call_set_option = ("set_option", tuple([ldap.OPT_REFERRALS, 0]), {})
|
|
104
|
-
call_bind_admin = (
|
|
105
|
-
"simple_bind_s",
|
|
106
|
-
tuple(["uid=admin,ou=users,o=test", "admin_password"]),
|
|
107
|
-
{},
|
|
108
|
-
)
|
|
109
|
-
call_bind_alice = (
|
|
110
|
-
"simple_bind_s",
|
|
111
|
-
tuple(["uid=alice,ou=users,o=test", "alice_password"]),
|
|
112
|
-
{},
|
|
113
|
-
)
|
|
114
|
-
call_search_alice = (
|
|
115
|
-
"search_s",
|
|
116
|
-
tuple(["ou=users,o=test", 2, "(uid=alice)", ["givenName", "sn", "email"]]),
|
|
117
|
-
{},
|
|
118
|
-
)
|
|
119
|
-
call_search_alice_memberof = (
|
|
120
|
-
"search_s",
|
|
121
|
-
tuple(
|
|
122
|
-
[
|
|
123
|
-
"ou=users,o=test",
|
|
124
|
-
2,
|
|
125
|
-
"(uid=alice)",
|
|
126
|
-
["givenName", "sn", "email", "memberOf"],
|
|
127
|
-
]
|
|
128
|
-
),
|
|
129
|
-
{},
|
|
130
|
-
)
|
|
131
|
-
call_search_alice_filter = (
|
|
132
|
-
"search_s",
|
|
133
|
-
tuple(
|
|
134
|
-
[
|
|
135
|
-
"ou=users,o=test",
|
|
136
|
-
2,
|
|
137
|
-
"(&(memberOf=cn=staff,ou=groups,o=test)(uid=alice))",
|
|
138
|
-
["givenName", "sn", "email"],
|
|
139
|
-
]
|
|
140
|
-
),
|
|
141
|
-
{},
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
# ----------------
|
|
145
|
-
# Unit Tests
|
|
146
|
-
# ----------------
|
|
147
|
-
def test___search_ldap(self):
|
|
148
|
-
"""
|
|
149
|
-
LDAP: test `_search_ldap` method
|
|
150
|
-
"""
|
|
151
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
152
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
153
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
154
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
155
|
-
sm = self.appbuilder.sm
|
|
156
|
-
|
|
157
|
-
# prepare `con` object
|
|
158
|
-
con = ldap.initialize("ldap://localhost/")
|
|
159
|
-
sm._ldap_bind_indirect(ldap, con)
|
|
160
|
-
|
|
161
|
-
# run `_search_ldap` method
|
|
162
|
-
user_dn, user_attributes = sm._search_ldap(ldap, con, "alice")
|
|
163
|
-
|
|
164
|
-
# validate - search returned expected data
|
|
165
|
-
self.assertEqual(user_dn, self.user_alice[0])
|
|
166
|
-
self.assertEqual(user_attributes["givenName"], self.user_alice[1]["givenName"])
|
|
167
|
-
self.assertEqual(user_attributes["sn"], self.user_alice[1]["sn"])
|
|
168
|
-
self.assertEqual(user_attributes["email"], self.user_alice[1]["email"])
|
|
169
|
-
|
|
170
|
-
# validate - expected LDAP methods were called
|
|
171
|
-
self.assertEqual(
|
|
172
|
-
self.ldapobj.methods_called(with_args=True),
|
|
173
|
-
[self.call_initialize, self.call_bind_admin, self.call_search_alice],
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
def test___search_ldap_filter(self):
|
|
177
|
-
"""
|
|
178
|
-
LDAP: test `_search_ldap` method (with AUTH_LDAP_SEARCH_FILTER)
|
|
179
|
-
"""
|
|
180
|
-
# MockLdap needs non-bytes for search filters, so we patch `memberOf`
|
|
181
|
-
# to a string, only for this test
|
|
182
|
-
with patch.dict(
|
|
183
|
-
self.directory[self.user_alice[0]],
|
|
184
|
-
{
|
|
185
|
-
"memberOf": [
|
|
186
|
-
i.decode() for i in self.directory[self.user_alice[0]]["memberOf"]
|
|
187
|
-
]
|
|
188
|
-
},
|
|
189
|
-
):
|
|
190
|
-
_mockldap = MockLdap(self.directory)
|
|
191
|
-
_mockldap.start()
|
|
192
|
-
_ldapobj = _mockldap["ldap://localhost/"]
|
|
193
|
-
|
|
194
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
195
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
196
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
197
|
-
self.app.config[
|
|
198
|
-
"AUTH_LDAP_SEARCH_FILTER"
|
|
199
|
-
] = "(memberOf=cn=staff,ou=groups,o=test)"
|
|
200
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
201
|
-
sm = self.appbuilder.sm
|
|
202
|
-
|
|
203
|
-
# prepare `con` object
|
|
204
|
-
con = ldap.initialize("ldap://localhost/")
|
|
205
|
-
sm._ldap_bind_indirect(ldap, con)
|
|
206
|
-
|
|
207
|
-
# run `_search_ldap` method
|
|
208
|
-
user_dn, user_info = sm._search_ldap(ldap, con, "alice")
|
|
209
|
-
|
|
210
|
-
# validate - search returned expected data
|
|
211
|
-
self.assertEqual(user_dn, self.user_alice[0])
|
|
212
|
-
self.assertEqual(user_info["givenName"], self.user_alice[1]["givenName"])
|
|
213
|
-
self.assertEqual(user_info["sn"], self.user_alice[1]["sn"])
|
|
214
|
-
self.assertEqual(user_info["email"], self.user_alice[1]["email"])
|
|
215
|
-
|
|
216
|
-
# validate - expected LDAP methods were called
|
|
217
|
-
self.assertEqual(
|
|
218
|
-
_ldapobj.methods_called(with_args=True),
|
|
219
|
-
[
|
|
220
|
-
self.call_initialize,
|
|
221
|
-
self.call_bind_admin,
|
|
222
|
-
self.call_search_alice_filter,
|
|
223
|
-
],
|
|
224
|
-
)
|
|
225
|
-
|
|
226
|
-
def test__missing_credentials(self):
|
|
227
|
-
"""
|
|
228
|
-
LDAP: test login flow for - missing credentials
|
|
229
|
-
"""
|
|
230
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
231
|
-
sm = self.appbuilder.sm
|
|
232
|
-
|
|
233
|
-
# validate - no users are registered
|
|
234
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
235
|
-
|
|
236
|
-
# validate - login failure (missing username)
|
|
237
|
-
self.assertIsNone(sm.auth_user_ldap(None, "password"))
|
|
238
|
-
self.assertIsNone(sm.auth_user_ldap("", "password"))
|
|
239
|
-
|
|
240
|
-
# validate - login failure (missing password)
|
|
241
|
-
self.assertIsNone(sm.auth_user_ldap("username", None))
|
|
242
|
-
self.assertIsNone(sm.auth_user_ldap("username", ""))
|
|
243
|
-
|
|
244
|
-
# validate - login failure (missing username/password)
|
|
245
|
-
self.assertIsNone(sm.auth_user_ldap(None, None))
|
|
246
|
-
self.assertIsNone(sm.auth_user_ldap("", None))
|
|
247
|
-
self.assertIsNone(sm.auth_user_ldap("", ""))
|
|
248
|
-
self.assertIsNone(sm.auth_user_ldap(None, ""))
|
|
249
|
-
|
|
250
|
-
# validate - no users were created
|
|
251
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
252
|
-
|
|
253
|
-
# validate - expected LDAP methods were called
|
|
254
|
-
self.assertEquals(self.ldapobj.methods_called(with_args=True), [])
|
|
255
|
-
|
|
256
|
-
def test__inactive_user(self):
|
|
257
|
-
"""
|
|
258
|
-
LDAP: test login flow for - inactive user
|
|
259
|
-
"""
|
|
260
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
261
|
-
sm = self.appbuilder.sm
|
|
262
|
-
|
|
263
|
-
# validate - no users are registered
|
|
264
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
265
|
-
|
|
266
|
-
# register a user
|
|
267
|
-
new_user = sm.add_user(
|
|
268
|
-
username="alice",
|
|
269
|
-
first_name="Alice",
|
|
270
|
-
last_name="Doe",
|
|
271
|
-
email="alice@example.com",
|
|
272
|
-
role=[],
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
# validate - user was registered
|
|
276
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
277
|
-
|
|
278
|
-
# set user inactive
|
|
279
|
-
new_user.active = False
|
|
280
|
-
|
|
281
|
-
# attempt login
|
|
282
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
283
|
-
|
|
284
|
-
# validate - user was not allowed to log in
|
|
285
|
-
self.assertIsNone(user)
|
|
286
|
-
|
|
287
|
-
# validate - expected LDAP methods were called
|
|
288
|
-
self.assertEquals(self.ldapobj.methods_called(with_args=True), [])
|
|
289
|
-
|
|
290
|
-
def test__direct_bind__unregistered(self):
|
|
291
|
-
"""
|
|
292
|
-
LDAP: test login flow for - direct bind - unregistered user
|
|
293
|
-
"""
|
|
294
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
295
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
296
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
297
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
298
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
299
|
-
sm = self.appbuilder.sm
|
|
300
|
-
|
|
301
|
-
# validate - no users are registered
|
|
302
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
303
|
-
|
|
304
|
-
# attempt login
|
|
305
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
306
|
-
|
|
307
|
-
# validate - user was allowed to log in
|
|
308
|
-
self.assertIsInstance(user, sm.user_model)
|
|
309
|
-
|
|
310
|
-
# validate - user was registered
|
|
311
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
312
|
-
|
|
313
|
-
# validate - user was given the AUTH_USER_REGISTRATION_ROLE role
|
|
314
|
-
self.assertEqual(user.roles, [sm.find_role("Public")])
|
|
315
|
-
|
|
316
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
317
|
-
self.assertEqual(user.first_name, "Alice")
|
|
318
|
-
self.assertEqual(user.last_name, "Doe")
|
|
319
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
320
|
-
|
|
321
|
-
# validate - expected LDAP methods were called
|
|
322
|
-
self.assertEqual(
|
|
323
|
-
self.ldapobj.methods_called(with_args=True),
|
|
324
|
-
[
|
|
325
|
-
self.call_initialize,
|
|
326
|
-
self.call_set_option,
|
|
327
|
-
self.call_bind_alice,
|
|
328
|
-
self.call_search_alice,
|
|
329
|
-
],
|
|
330
|
-
)
|
|
331
|
-
|
|
332
|
-
def test__direct_bind__unregistered__no_self_register(self):
|
|
333
|
-
"""
|
|
334
|
-
LDAP: test login flow for - direct bind - unregistered user - no self-registration
|
|
335
|
-
"""
|
|
336
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
337
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
338
|
-
self.app.config["AUTH_USER_REGISTRATION"] = False
|
|
339
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
340
|
-
sm = self.appbuilder.sm
|
|
341
|
-
|
|
342
|
-
# validate - no users are registered
|
|
343
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
344
|
-
|
|
345
|
-
# attempt login
|
|
346
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
347
|
-
|
|
348
|
-
# validate - user was not allowed to log in
|
|
349
|
-
self.assertIsNone(user)
|
|
350
|
-
|
|
351
|
-
# validate - no users were registered
|
|
352
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
353
|
-
|
|
354
|
-
# validate - expected LDAP methods were called
|
|
355
|
-
self.assertEqual(self.ldapobj.methods_called(with_args=True), [])
|
|
356
|
-
|
|
357
|
-
def test__direct_bind__unregistered__no_search(self):
|
|
358
|
-
"""
|
|
359
|
-
LDAP: test login flow for - direct bind - unregistered user - no ldap search
|
|
360
|
-
"""
|
|
361
|
-
self.app.config["AUTH_LDAP_SEARCH"] = None
|
|
362
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
363
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
364
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
365
|
-
sm = self.appbuilder.sm
|
|
366
|
-
|
|
367
|
-
# validate - no users are registered
|
|
368
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
369
|
-
|
|
370
|
-
# attempt login
|
|
371
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
372
|
-
|
|
373
|
-
# validate - user was NOT allowed to log in (because registration requires search)
|
|
374
|
-
self.assertIsNone(user)
|
|
375
|
-
|
|
376
|
-
# validate - expected LDAP methods were called
|
|
377
|
-
self.assertEqual(
|
|
378
|
-
self.ldapobj.methods_called(with_args=True),
|
|
379
|
-
[self.call_initialize, self.call_set_option, self.call_bind_alice],
|
|
380
|
-
)
|
|
381
|
-
|
|
382
|
-
def test__direct_bind__registered(self):
|
|
383
|
-
"""
|
|
384
|
-
LDAP: test login flow for - direct bind - registered user
|
|
385
|
-
"""
|
|
386
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
387
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
388
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
389
|
-
sm = self.appbuilder.sm
|
|
390
|
-
|
|
391
|
-
# validate - no users are registered
|
|
392
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
393
|
-
|
|
394
|
-
# register a user
|
|
395
|
-
new_user = sm.add_user( # noqa
|
|
396
|
-
username="alice",
|
|
397
|
-
first_name="Alice",
|
|
398
|
-
last_name="Doe",
|
|
399
|
-
email="alice@example.com",
|
|
400
|
-
role=[],
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
# validate - user was registered
|
|
404
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
405
|
-
|
|
406
|
-
# attempt login
|
|
407
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
408
|
-
|
|
409
|
-
# validate - user was allowed to log in
|
|
410
|
-
self.assertIsInstance(user, sm.user_model)
|
|
411
|
-
|
|
412
|
-
# validate - expected LDAP methods were called
|
|
413
|
-
self.assertEqual(
|
|
414
|
-
self.ldapobj.methods_called(with_args=True),
|
|
415
|
-
[
|
|
416
|
-
self.call_initialize,
|
|
417
|
-
self.call_set_option,
|
|
418
|
-
self.call_bind_alice,
|
|
419
|
-
self.call_search_alice,
|
|
420
|
-
],
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
def test__direct_bind__registered__no_search(self):
|
|
424
|
-
"""
|
|
425
|
-
LDAP: test login flow for - direct bind - registered user - no ldap search
|
|
426
|
-
"""
|
|
427
|
-
self.app.config["AUTH_LDAP_SEARCH"] = None
|
|
428
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
429
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
430
|
-
sm = self.appbuilder.sm
|
|
431
|
-
|
|
432
|
-
# validate - no users are registered
|
|
433
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
434
|
-
|
|
435
|
-
# register a user
|
|
436
|
-
new_user = sm.add_user( # noqa
|
|
437
|
-
username="alice",
|
|
438
|
-
first_name="Alice",
|
|
439
|
-
last_name="Doe",
|
|
440
|
-
email="alice@example.com",
|
|
441
|
-
role=[],
|
|
442
|
-
)
|
|
443
|
-
|
|
444
|
-
# validate - user was registered
|
|
445
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
446
|
-
|
|
447
|
-
# attempt login
|
|
448
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
449
|
-
|
|
450
|
-
# validate - user was allowed to log in (because they are already registered)
|
|
451
|
-
self.assertIsInstance(user, sm.user_model)
|
|
452
|
-
|
|
453
|
-
# validate - expected LDAP methods were called
|
|
454
|
-
self.assertEqual(
|
|
455
|
-
self.ldapobj.methods_called(with_args=True),
|
|
456
|
-
[self.call_initialize, self.call_set_option, self.call_bind_alice],
|
|
457
|
-
)
|
|
458
|
-
|
|
459
|
-
def test__indirect_bind__unregistered(self):
|
|
460
|
-
"""
|
|
461
|
-
LDAP: test login flow for - indirect bind - unregistered user
|
|
462
|
-
"""
|
|
463
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
464
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
465
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
466
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
467
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
468
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
469
|
-
sm = self.appbuilder.sm
|
|
470
|
-
|
|
471
|
-
# validate - no users are registered
|
|
472
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
473
|
-
|
|
474
|
-
# attempt login
|
|
475
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
476
|
-
|
|
477
|
-
# validate - user was allowed to log in
|
|
478
|
-
self.assertIsInstance(user, sm.user_model)
|
|
479
|
-
|
|
480
|
-
# validate - user was registered
|
|
481
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
482
|
-
|
|
483
|
-
# validate - user was given the AUTH_USER_REGISTRATION_ROLE role
|
|
484
|
-
self.assertListEqual(user.roles, [sm.find_role("Public")])
|
|
485
|
-
|
|
486
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
487
|
-
self.assertEqual(user.first_name, "Alice")
|
|
488
|
-
self.assertEqual(user.last_name, "Doe")
|
|
489
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
490
|
-
|
|
491
|
-
# validate - expected LDAP methods were called
|
|
492
|
-
self.assertEqual(
|
|
493
|
-
self.ldapobj.methods_called(with_args=True),
|
|
494
|
-
[
|
|
495
|
-
self.call_initialize,
|
|
496
|
-
self.call_set_option,
|
|
497
|
-
self.call_bind_admin,
|
|
498
|
-
self.call_search_alice,
|
|
499
|
-
self.call_bind_alice,
|
|
500
|
-
],
|
|
501
|
-
)
|
|
502
|
-
|
|
503
|
-
def test__indirect_bind__unregistered__no_self_register(self):
|
|
504
|
-
"""
|
|
505
|
-
LDAP: test login flow for - indirect bind - unregistered user - no self-registration
|
|
506
|
-
""" # noqa
|
|
507
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
508
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
509
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
510
|
-
self.app.config["AUTH_USER_REGISTRATION"] = False
|
|
511
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
512
|
-
sm = self.appbuilder.sm
|
|
513
|
-
|
|
514
|
-
# validate - no users are registered
|
|
515
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
516
|
-
|
|
517
|
-
# attempt login
|
|
518
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
519
|
-
|
|
520
|
-
# validate - user was not allowed to log in
|
|
521
|
-
self.assertIsNone(user)
|
|
522
|
-
|
|
523
|
-
# validate - no users were registered
|
|
524
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
525
|
-
|
|
526
|
-
# validate - expected LDAP methods were called
|
|
527
|
-
self.assertEqual(self.ldapobj.methods_called(with_args=True), [])
|
|
528
|
-
|
|
529
|
-
def test__indirect_bind__unregistered__no_search(self):
|
|
530
|
-
"""
|
|
531
|
-
LDAP: test login flow for - indirect bind - unregistered user - no ldap search
|
|
532
|
-
"""
|
|
533
|
-
self.app.config["AUTH_LDAP_SEARCH"] = None
|
|
534
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
535
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
536
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
537
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
538
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
539
|
-
sm = self.appbuilder.sm
|
|
540
|
-
|
|
541
|
-
# validate - no users are registered
|
|
542
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
543
|
-
|
|
544
|
-
# attempt login
|
|
545
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
546
|
-
|
|
547
|
-
# validate - user was NOT allowed to log in
|
|
548
|
-
# (because indirect bind requires search)
|
|
549
|
-
self.assertIsNone(user)
|
|
550
|
-
|
|
551
|
-
# validate - expected LDAP methods were called
|
|
552
|
-
self.assertEqual(
|
|
553
|
-
self.ldapobj.methods_called(with_args=True),
|
|
554
|
-
[self.call_initialize, self.call_set_option, self.call_bind_admin],
|
|
555
|
-
)
|
|
556
|
-
|
|
557
|
-
def test__indirect_bind__registered(self):
|
|
558
|
-
"""
|
|
559
|
-
LDAP: test login flow for - indirect bind - registered user
|
|
560
|
-
"""
|
|
561
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
562
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
563
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
564
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
565
|
-
sm = self.appbuilder.sm
|
|
566
|
-
|
|
567
|
-
# validate - no users are registered
|
|
568
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
569
|
-
|
|
570
|
-
# register a user
|
|
571
|
-
new_user = sm.add_user( # noqa
|
|
572
|
-
username="alice",
|
|
573
|
-
first_name="Alice",
|
|
574
|
-
last_name="Doe",
|
|
575
|
-
email="alice@example.com",
|
|
576
|
-
role=[],
|
|
577
|
-
)
|
|
578
|
-
|
|
579
|
-
# validate - user was registered
|
|
580
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
581
|
-
|
|
582
|
-
# attempt login
|
|
583
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
584
|
-
|
|
585
|
-
# validate - user was allowed to log in
|
|
586
|
-
self.assertIsInstance(user, sm.user_model)
|
|
587
|
-
|
|
588
|
-
# validate - expected LDAP methods were called
|
|
589
|
-
self.assertEqual(
|
|
590
|
-
self.ldapobj.methods_called(with_args=True),
|
|
591
|
-
[
|
|
592
|
-
self.call_initialize,
|
|
593
|
-
self.call_set_option,
|
|
594
|
-
self.call_bind_admin,
|
|
595
|
-
self.call_search_alice,
|
|
596
|
-
self.call_bind_alice,
|
|
597
|
-
],
|
|
598
|
-
)
|
|
599
|
-
|
|
600
|
-
def test__indirect_bind__registered__no_search(self):
|
|
601
|
-
"""
|
|
602
|
-
LDAP: test login flow for - indirect bind - registered user - no ldap search
|
|
603
|
-
"""
|
|
604
|
-
self.app.config["AUTH_LDAP_SEARCH"] = None
|
|
605
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
606
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
607
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
608
|
-
sm = self.appbuilder.sm
|
|
609
|
-
|
|
610
|
-
# validate - no users are registered
|
|
611
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
612
|
-
|
|
613
|
-
# register a user
|
|
614
|
-
new_user = sm.add_user( # noqa
|
|
615
|
-
username="alice",
|
|
616
|
-
first_name="Alice",
|
|
617
|
-
last_name="Doe",
|
|
618
|
-
email="alice@example.com",
|
|
619
|
-
role=[],
|
|
620
|
-
)
|
|
621
|
-
|
|
622
|
-
# validate - user was registered
|
|
623
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
624
|
-
|
|
625
|
-
# attempt login
|
|
626
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
627
|
-
|
|
628
|
-
# validate - user was NOT allowed to log in
|
|
629
|
-
# (because indirect bind requires search)
|
|
630
|
-
self.assertIsNone(user)
|
|
631
|
-
|
|
632
|
-
# validate - expected LDAP methods were called
|
|
633
|
-
self.assertEqual(
|
|
634
|
-
self.ldapobj.methods_called(with_args=True),
|
|
635
|
-
[self.call_initialize, self.call_set_option, self.call_bind_admin],
|
|
636
|
-
)
|
|
637
|
-
|
|
638
|
-
def test__direct_bind__unregistered__single_role(self):
|
|
639
|
-
"""
|
|
640
|
-
LDAP: test login flow for - direct bind - unregistered user - single role mapping
|
|
641
|
-
"""
|
|
642
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
643
|
-
"cn=staff,ou=groups,o=test": ["User"],
|
|
644
|
-
"cn=admins,ou=groups,o=test": ["Admin"],
|
|
645
|
-
}
|
|
646
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
647
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
648
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
649
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
650
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
651
|
-
sm = self.appbuilder.sm
|
|
652
|
-
|
|
653
|
-
# add User role
|
|
654
|
-
sm.add_role("User")
|
|
655
|
-
|
|
656
|
-
# validate - no users are registered
|
|
657
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
658
|
-
|
|
659
|
-
# attempt login
|
|
660
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
661
|
-
|
|
662
|
-
# validate - user was allowed to log in
|
|
663
|
-
self.assertIsInstance(user, sm.user_model)
|
|
664
|
-
|
|
665
|
-
# validate - user was registered
|
|
666
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
667
|
-
|
|
668
|
-
# validate - user was given the correct roles
|
|
669
|
-
self.assertListEqual(user.roles, [sm.find_role("Public"), sm.find_role("User")])
|
|
670
|
-
|
|
671
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
672
|
-
self.assertEqual(user.first_name, "Alice")
|
|
673
|
-
self.assertEqual(user.last_name, "Doe")
|
|
674
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
675
|
-
|
|
676
|
-
# validate - expected LDAP methods were called
|
|
677
|
-
self.assertEqual(
|
|
678
|
-
self.ldapobj.methods_called(with_args=True),
|
|
679
|
-
[
|
|
680
|
-
self.call_initialize,
|
|
681
|
-
self.call_set_option,
|
|
682
|
-
self.call_bind_alice,
|
|
683
|
-
self.call_search_alice_memberof,
|
|
684
|
-
],
|
|
685
|
-
)
|
|
686
|
-
|
|
687
|
-
def test__direct_bind__unregistered__multi_role(self):
|
|
688
|
-
"""
|
|
689
|
-
LDAP: test login flow for - direct bind - unregistered user - multi role mapping
|
|
690
|
-
"""
|
|
691
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
692
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
693
|
-
}
|
|
694
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
695
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
696
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
697
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
698
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
699
|
-
sm = self.appbuilder.sm
|
|
700
|
-
|
|
701
|
-
# add User role
|
|
702
|
-
sm.add_role("User")
|
|
703
|
-
|
|
704
|
-
# validate - no users are registered
|
|
705
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
706
|
-
|
|
707
|
-
# attempt login
|
|
708
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
709
|
-
|
|
710
|
-
# validate - user was allowed to log in
|
|
711
|
-
self.assertIsInstance(user, sm.user_model)
|
|
712
|
-
|
|
713
|
-
# validate - user was registered
|
|
714
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
715
|
-
|
|
716
|
-
# validate - user was given the correct roles
|
|
717
|
-
self.assertListEqual(
|
|
718
|
-
user.roles,
|
|
719
|
-
[sm.find_role("Admin"), sm.find_role("Public"), sm.find_role("User")],
|
|
720
|
-
)
|
|
721
|
-
|
|
722
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
723
|
-
self.assertEqual(user.first_name, "Alice")
|
|
724
|
-
self.assertEqual(user.last_name, "Doe")
|
|
725
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
726
|
-
|
|
727
|
-
# validate - expected LDAP methods were called
|
|
728
|
-
self.assertEqual(
|
|
729
|
-
self.ldapobj.methods_called(with_args=True),
|
|
730
|
-
[
|
|
731
|
-
self.call_initialize,
|
|
732
|
-
self.call_set_option,
|
|
733
|
-
self.call_bind_alice,
|
|
734
|
-
self.call_search_alice_memberof,
|
|
735
|
-
],
|
|
736
|
-
)
|
|
737
|
-
|
|
738
|
-
def test__direct_bind__registered__multi_role__no_role_sync(self):
|
|
739
|
-
"""
|
|
740
|
-
LDAP: test login flow for - direct bind - registered user - multi role mapping - no login role-sync
|
|
741
|
-
""" # noqa
|
|
742
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
743
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
744
|
-
}
|
|
745
|
-
self.app.config["AUTH_ROLES_SYNC_AT_LOGIN"] = False
|
|
746
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
747
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
748
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
749
|
-
sm = self.appbuilder.sm
|
|
750
|
-
|
|
751
|
-
# add User role
|
|
752
|
-
sm.add_role("User")
|
|
753
|
-
|
|
754
|
-
# validate - no users are registered
|
|
755
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
756
|
-
|
|
757
|
-
# register a user
|
|
758
|
-
new_user = sm.add_user( # noqa
|
|
759
|
-
username="alice",
|
|
760
|
-
first_name="Alice",
|
|
761
|
-
last_name="Doe",
|
|
762
|
-
email="alice@example.com",
|
|
763
|
-
role=[],
|
|
764
|
-
)
|
|
765
|
-
|
|
766
|
-
# validate - user was registered
|
|
767
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
768
|
-
|
|
769
|
-
# attempt login
|
|
770
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
771
|
-
|
|
772
|
-
# validate - user was allowed to log in
|
|
773
|
-
self.assertIsInstance(user, sm.user_model)
|
|
774
|
-
|
|
775
|
-
# validate - user was given no roles
|
|
776
|
-
self.assertListEqual(user.roles, [])
|
|
777
|
-
|
|
778
|
-
# validate - expected LDAP methods were called
|
|
779
|
-
self.assertEqual(
|
|
780
|
-
self.ldapobj.methods_called(with_args=True),
|
|
781
|
-
[
|
|
782
|
-
self.call_initialize,
|
|
783
|
-
self.call_set_option,
|
|
784
|
-
self.call_bind_alice,
|
|
785
|
-
self.call_search_alice_memberof,
|
|
786
|
-
],
|
|
787
|
-
)
|
|
788
|
-
|
|
789
|
-
def test__direct_bind__registered__multi_role__with_role_sync(self):
|
|
790
|
-
"""
|
|
791
|
-
LDAP: test login flow for - direct bind - registered user - multi role mapping - with login role-sync
|
|
792
|
-
""" # noqa
|
|
793
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
794
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
795
|
-
}
|
|
796
|
-
self.app.config["AUTH_ROLES_SYNC_AT_LOGIN"] = True
|
|
797
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
798
|
-
self.app.config["AUTH_LDAP_USERNAME_FORMAT"] = "uid=%s,ou=users,o=test"
|
|
799
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
800
|
-
sm = self.appbuilder.sm
|
|
801
|
-
|
|
802
|
-
# add User role
|
|
803
|
-
sm.add_role("User")
|
|
804
|
-
|
|
805
|
-
# validate - no users are registered
|
|
806
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
807
|
-
|
|
808
|
-
# register a user
|
|
809
|
-
new_user = sm.add_user( # noqa
|
|
810
|
-
username="alice",
|
|
811
|
-
first_name="Alice",
|
|
812
|
-
last_name="Doe",
|
|
813
|
-
email="alice@example.com",
|
|
814
|
-
role=[],
|
|
815
|
-
)
|
|
816
|
-
|
|
817
|
-
# validate - user was registered
|
|
818
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
819
|
-
|
|
820
|
-
# attempt login
|
|
821
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
822
|
-
|
|
823
|
-
# validate - user was allowed to log in
|
|
824
|
-
self.assertIsInstance(user, sm.user_model)
|
|
825
|
-
|
|
826
|
-
# validate - user was given the correct roles
|
|
827
|
-
self.assertListEqual(user.roles, [sm.find_role("Admin"), sm.find_role("User")])
|
|
828
|
-
|
|
829
|
-
# validate - expected LDAP methods were called
|
|
830
|
-
self.assertEqual(
|
|
831
|
-
self.ldapobj.methods_called(with_args=True),
|
|
832
|
-
[
|
|
833
|
-
self.call_initialize,
|
|
834
|
-
self.call_set_option,
|
|
835
|
-
self.call_bind_alice,
|
|
836
|
-
self.call_search_alice_memberof,
|
|
837
|
-
],
|
|
838
|
-
)
|
|
839
|
-
|
|
840
|
-
def test__indirect_bind__unregistered__single_role(self):
|
|
841
|
-
"""
|
|
842
|
-
LDAP: test login flow for - indirect bind - unregistered user - single role mapping
|
|
843
|
-
""" # noqa
|
|
844
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {"cn=staff,ou=groups,o=test": ["User"]}
|
|
845
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
846
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
847
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
848
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
849
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
850
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
851
|
-
sm = self.appbuilder.sm
|
|
852
|
-
|
|
853
|
-
# add User role
|
|
854
|
-
sm.add_role("User")
|
|
855
|
-
|
|
856
|
-
# validate - no users are registered
|
|
857
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
858
|
-
|
|
859
|
-
# attempt login
|
|
860
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
861
|
-
|
|
862
|
-
# validate - user was allowed to log in
|
|
863
|
-
self.assertIsInstance(user, sm.user_model)
|
|
864
|
-
|
|
865
|
-
# validate - user was registered
|
|
866
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
867
|
-
|
|
868
|
-
# validate - user was given the correct roles
|
|
869
|
-
self.assertListEqual(user.roles, [sm.find_role("Public"), sm.find_role("User")])
|
|
870
|
-
|
|
871
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
872
|
-
self.assertEqual(user.first_name, "Alice")
|
|
873
|
-
self.assertEqual(user.last_name, "Doe")
|
|
874
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
875
|
-
|
|
876
|
-
# validate - expected LDAP methods were called
|
|
877
|
-
self.assertEqual(
|
|
878
|
-
self.ldapobj.methods_called(with_args=True),
|
|
879
|
-
[
|
|
880
|
-
self.call_initialize,
|
|
881
|
-
self.call_set_option,
|
|
882
|
-
self.call_bind_admin,
|
|
883
|
-
self.call_search_alice_memberof,
|
|
884
|
-
self.call_bind_alice,
|
|
885
|
-
],
|
|
886
|
-
)
|
|
887
|
-
|
|
888
|
-
def test__indirect_bind__unregistered__multi_role(self):
|
|
889
|
-
"""
|
|
890
|
-
LDAP: test login flow for - indirect bind - unregistered user - multi role mapping
|
|
891
|
-
"""
|
|
892
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
893
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
894
|
-
}
|
|
895
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
896
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
897
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
898
|
-
self.app.config["AUTH_USER_REGISTRATION"] = True
|
|
899
|
-
self.app.config["AUTH_USER_REGISTRATION_ROLE"] = "Public"
|
|
900
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
901
|
-
sm = self.appbuilder.sm
|
|
902
|
-
|
|
903
|
-
# add User role
|
|
904
|
-
sm.add_role("User")
|
|
905
|
-
|
|
906
|
-
# validate - no users are registered
|
|
907
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
908
|
-
|
|
909
|
-
# attempt login
|
|
910
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
911
|
-
|
|
912
|
-
# validate - user was allowed to log in
|
|
913
|
-
self.assertIsInstance(user, sm.user_model)
|
|
914
|
-
|
|
915
|
-
# validate - user was registered
|
|
916
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
917
|
-
|
|
918
|
-
# validate - user was given the correct roles
|
|
919
|
-
self.assertListEqual(
|
|
920
|
-
user.roles,
|
|
921
|
-
[sm.find_role("Admin"), sm.find_role("Public"), sm.find_role("User")],
|
|
922
|
-
)
|
|
923
|
-
|
|
924
|
-
# validate - user was given the correct attributes (read from LDAP)
|
|
925
|
-
self.assertEqual(user.first_name, "Alice")
|
|
926
|
-
self.assertEqual(user.last_name, "Doe")
|
|
927
|
-
self.assertEqual(user.email, "alice@example.com")
|
|
928
|
-
|
|
929
|
-
# validate - expected LDAP methods were called
|
|
930
|
-
self.assertEqual(
|
|
931
|
-
self.ldapobj.methods_called(with_args=True),
|
|
932
|
-
[
|
|
933
|
-
self.call_initialize,
|
|
934
|
-
self.call_set_option,
|
|
935
|
-
self.call_bind_admin,
|
|
936
|
-
self.call_search_alice_memberof,
|
|
937
|
-
self.call_bind_alice,
|
|
938
|
-
],
|
|
939
|
-
)
|
|
940
|
-
|
|
941
|
-
def test__indirect_bind__registered__multi_role__no_role_sync(self):
|
|
942
|
-
"""
|
|
943
|
-
LDAP: test login flow for - indirect bind - registered user - multi role mapping - no login role-sync
|
|
944
|
-
""" # noqa
|
|
945
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
946
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
947
|
-
}
|
|
948
|
-
self.app.config["AUTH_ROLES_SYNC_AT_LOGIN"] = False
|
|
949
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
950
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
951
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
952
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
953
|
-
sm = self.appbuilder.sm
|
|
954
|
-
|
|
955
|
-
# add User role
|
|
956
|
-
sm.add_role("User")
|
|
957
|
-
|
|
958
|
-
# validate - no users are registered
|
|
959
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
960
|
-
|
|
961
|
-
# register a user
|
|
962
|
-
new_user = sm.add_user( # noqa
|
|
963
|
-
username="alice",
|
|
964
|
-
first_name="Alice",
|
|
965
|
-
last_name="Doe",
|
|
966
|
-
email="alice@example.com",
|
|
967
|
-
role=[],
|
|
968
|
-
)
|
|
969
|
-
|
|
970
|
-
# validate - user was registered
|
|
971
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
972
|
-
|
|
973
|
-
# attempt login
|
|
974
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
975
|
-
|
|
976
|
-
# validate - user was allowed to log in
|
|
977
|
-
self.assertIsInstance(user, sm.user_model)
|
|
978
|
-
|
|
979
|
-
# validate - user was given no roles
|
|
980
|
-
self.assertListEqual(user.roles, [])
|
|
981
|
-
|
|
982
|
-
# validate - expected LDAP methods were called
|
|
983
|
-
self.assertEqual(
|
|
984
|
-
self.ldapobj.methods_called(with_args=True),
|
|
985
|
-
[
|
|
986
|
-
self.call_initialize,
|
|
987
|
-
self.call_set_option,
|
|
988
|
-
self.call_bind_admin,
|
|
989
|
-
self.call_search_alice_memberof,
|
|
990
|
-
self.call_bind_alice,
|
|
991
|
-
],
|
|
992
|
-
)
|
|
993
|
-
|
|
994
|
-
def test__indirect_bind__registered__multi_role__with_role_sync(self):
|
|
995
|
-
"""
|
|
996
|
-
LDAP: test login flow for - indirect bind - registered user - multi role mapping - with login role-sync
|
|
997
|
-
""" # noqa
|
|
998
|
-
self.app.config["AUTH_ROLES_MAPPING"] = {
|
|
999
|
-
"cn=staff,ou=groups,o=test": ["Admin", "User"]
|
|
1000
|
-
}
|
|
1001
|
-
self.app.config["AUTH_ROLES_SYNC_AT_LOGIN"] = True
|
|
1002
|
-
self.app.config["AUTH_LDAP_SEARCH"] = "ou=users,o=test"
|
|
1003
|
-
self.app.config["AUTH_LDAP_BIND_USER"] = "uid=admin,ou=users,o=test"
|
|
1004
|
-
self.app.config["AUTH_LDAP_BIND_PASSWORD"] = "admin_password"
|
|
1005
|
-
self.appbuilder = AppBuilder(self.app, self.db.session)
|
|
1006
|
-
sm = self.appbuilder.sm
|
|
1007
|
-
|
|
1008
|
-
# add User role
|
|
1009
|
-
sm.add_role("User")
|
|
1010
|
-
|
|
1011
|
-
# validate - no users are registered
|
|
1012
|
-
self.assertEqual(sm.get_all_users(), [])
|
|
1013
|
-
|
|
1014
|
-
# register a user
|
|
1015
|
-
new_user = sm.add_user( # noqa
|
|
1016
|
-
username="alice",
|
|
1017
|
-
first_name="Alice",
|
|
1018
|
-
last_name="Doe",
|
|
1019
|
-
email="alice@example.com",
|
|
1020
|
-
role=[],
|
|
1021
|
-
)
|
|
1022
|
-
|
|
1023
|
-
# validate - user was registered
|
|
1024
|
-
self.assertEqual(len(sm.get_all_users()), 1)
|
|
1025
|
-
|
|
1026
|
-
# attempt login
|
|
1027
|
-
user = sm.auth_user_ldap("alice", "alice_password")
|
|
1028
|
-
|
|
1029
|
-
# validate - user was allowed to log in
|
|
1030
|
-
self.assertIsInstance(user, sm.user_model)
|
|
1031
|
-
|
|
1032
|
-
# validate - user was given the correct roles
|
|
1033
|
-
self.assertListEqual(user.roles, [sm.find_role("Admin"), sm.find_role("User")])
|
|
1034
|
-
|
|
1035
|
-
# validate - expected LDAP methods were called
|
|
1036
|
-
self.assertEqual(
|
|
1037
|
-
self.ldapobj.methods_called(with_args=True),
|
|
1038
|
-
[
|
|
1039
|
-
self.call_initialize,
|
|
1040
|
-
self.call_set_option,
|
|
1041
|
-
self.call_bind_admin,
|
|
1042
|
-
self.call_search_alice_memberof,
|
|
1043
|
-
self.call_bind_alice,
|
|
1044
|
-
],
|
|
1045
|
-
)
|