Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Kontr 2.0
Portal API Backend
Commits
363af840
Unverified
Commit
363af840
authored
Sep 18, 2018
by
Peter Stanko
Browse files
Extract uco from LDAP using ldap3 instead of python-ldap
parent
8f0da640
Pipeline
#13208
passed with stage
in 13 minutes and 1 second
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Pipfile
View file @
363af840
...
...
@@ -22,11 +22,11 @@ python-gitlab = "*"
psycopg2-binary
=
"*"
flask-restplus
=
"*"
celery
=
{
extras
=
[
"auth"
,
"yaml"
,
"msgpack"
,
"redis"
]}
python-ldap
=
"*"
mockredispy
=
"*"
python-slugify
=
"*"
coloredlogs
=
"*"
worker-api
=
{
editable
=
true
,
git
=
"https://gitlab.fi.muni.cz/grp-kontr2/worker-api.git"
,
ref
=
'master'
}
"ldap3"
=
"*"
[dev-packages]
pylint
=
"*"
...
...
README.adoc
View file @
363af840
...
...
@@ -105,6 +105,7 @@ Here are some important variables:
- `EMAIL_PORT` - Port on which the mail server is running
- `EMAIL_DEFAULT_FROM` - From who the emails are
- `PORTAL_DATA_WORKER_DOMAIN` - Domain where default worker will be running (default: `localhost`) This one is mostly for the template
- `LDAP_URL` - LDAP url, required only if you need LDAP support
For more take a look at the config files.
...
...
portal/config.py
View file @
363af840
...
...
@@ -38,6 +38,7 @@ class Config(object):
EMAIL_BACKEND
=
'tests.utils.email_backend.EmailBackend'
PORTAL_LOG_CONFIG
=
False
PORTAL_DATA_WORKER_DOMAIN
=
os
.
getenv
(
'PORTAL_DATA_WORKER_DOMAIN'
,
'localhost'
)
LDAP_URL
=
os
.
getenv
(
'LDAP_URL'
,
None
)
class
DevelopmentConfig
(
Config
):
...
...
portal/service/users.py
View file @
363af840
...
...
@@ -2,7 +2,7 @@
Users service
"""
from
typing
import
List
from
typing
import
List
,
Optional
from
portal
import
ldap_wrapper
,
logger
from
portal.database.models
import
Course
,
Group
,
Project
,
Review
,
Role
,
Submission
,
User
...
...
@@ -33,20 +33,30 @@ class UserLdapService:
def
user
(
self
):
return
self
.
service
.
user
def
extract_uco
(
self
)
->
int
:
def
extract_uco
(
self
)
->
Optional
[
int
]
:
"""Get uco from the ldap
Returns(int): User's uco
"""
username
=
self
.
user
.
username
user_dict
=
self
.
ldap
.
search_dict
(
f
"uid=
{
username
}
,ou=People"
)
log
.
debug
(
f
"[LDAP] User (
{
username
}
):
{
user_dict
}
"
)
if
not
user_dict
:
return
0
desc
=
user_dict
[
0
][
'description'
]
uco
=
[
u
.
decode
(
'utf-8'
)
for
u
in
desc
if
u
.
decode
(
'utf-8'
).
startswith
(
'UCO='
)]
if
not
uco
:
return
0
return
int
(
uco
[
0
][
4
:])
user_entity
=
self
.
ldap
.
search
(
f
"uid=
{
username
}
,ou=People"
)
log
.
debug
(
f
"[LDAP] User (
{
username
}
):
{
user_entity
}
"
)
if
not
user_entity
:
return
None
desc
=
user_entity
.
description
uco
=
self
.
_parse_uco_from_desc
(
desc
)
log
.
debug
(
f
"[LDAP] User's UCO (
{
username
}
):
{
uco
}
"
)
return
uco
def
_parse_uco_from_desc
(
self
,
desc
):
values
:
List
[
str
]
=
desc
.
values
uco_entry
=
None
for
item
in
values
:
if
item
.
startswith
(
'UCO='
):
uco_entry
=
item
if
not
uco_entry
:
return
None
uco
=
int
(
uco_entry
[
len
(
'UCO='
):])
return
uco
class
UserService
:
...
...
@@ -73,10 +83,17 @@ class UserService:
def
_set_user_data
(
self
,
data
:
dict
,
full
:
bool
=
False
)
->
User
:
if
(
data
.
get
(
"is_admin"
)
is
not
None
)
and
full
:
self
.
user
.
is_admin
=
data
[
'is_admin'
]
if
self
.
ldap
.
is_enabled
:
data
[
'uco'
]
=
self
.
ldap
.
extract_uco
()
self
.
__update_uco_using_ldap
(
data
)
return
general
.
update_entity
(
self
.
user
,
data
,
allowed
=
[
'name'
,
'email'
,
'uco'
])
def
__update_uco_using_ldap
(
self
,
data
):
if
self
.
ldap
.
is_enabled
:
uco
=
self
.
ldap
.
extract_uco
()
if
uco
:
data
[
'uco'
]
=
uco
else
:
log
.
warning
(
f
'[LDAP] Cannot extract UCO for user:
{
self
.
user
.
log_name
}
'
)
def
create_user
(
self
,
**
data
):
"""Creates a new user
...
...
portal/tools/ldap_client.py
View file @
363af840
"""
LDAP integration module
"""
import
ldap3
from
flask
import
Flask
import
ldap
from
ldap.ldapobject
import
LDAPObject
import
logging
from
portal
import
logger
...
...
@@ -15,6 +13,7 @@ class LDAPWrapper(object):
def
__init__
(
self
,
app
:
Flask
=
None
):
self
.
flask_app
=
None
self
.
_ldap_client
=
None
self
.
_ldap_server
=
None
self
.
_selector_base
=
',dc=fi,dc=muni,dc=cz'
if
app
:
self
.
init_app
(
app
)
...
...
@@ -49,22 +48,24 @@ class LDAPWrapper(object):
return
self
.
_selector_base
@
property
def
ldap
(
self
)
->
LDAPObject
:
def
ldap
(
self
)
->
ldap3
.
Server
:
"""LDAP object instance
Returns(LDAPObject): LDAP Object instance
"""
if
not
self
.
_ldap_client
and
self
.
is_enabled
:
self
.
_ldap_client
=
ldap
.
initialize
(
self
.
ldap_url
,
bytes_mode
=
False
)
return
self
.
_ldap_client
if
not
self
.
_ldap_server
and
self
.
is_enabled
:
self
.
_ldap_server
=
ldap3
.
Server
(
self
.
ldap_url
,
get_info
=
ldap3
.
ALL
)
return
self
.
_ldap_server
@
property
def
ldap_connection
(
self
):
connection
=
None
if
self
.
ldap
is
not
None
:
connection
=
ldap3
.
Connection
(
self
.
ldap
,
auto_bind
=
True
)
return
connection
def
search
(
self
,
selector
:
str
):
selector
=
selector
+
self
.
selector_base
result
=
self
.
ldap
.
search_s
(
selector
,
ldap
.
SCOPE_SUBTREE
,
"objectclass=*"
)
self
.
ldap_connection
.
search
(
selector
,
'(objectclass=*)'
,
attributes
=
ldap3
.
ALL_ATTRIBUTES
)
result
=
self
.
ldap_connection
.
entries
[
0
]
log
.
debug
(
f
"[LDAP] Search (
{
selector
}
):
{
result
}
"
)
return
result
def
search_dict
(
self
,
*
args
,
**
kwargs
):
l_res
=
self
.
search
(
*
args
,
**
kwargs
)
if
not
l_res
:
return
None
return
[
rec
[
1
]
for
rec
in
l_res
]
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment