Add API for retrieving user info
This commit is contained in:
parent
8f69c33de1
commit
c79d89c0b7
|
@ -18,6 +18,8 @@ ldap:
|
||||||
password: phi
|
password: phi
|
||||||
|
|
||||||
base_dn: dc=unit,dc=macaomilano,dc=org
|
base_dn: dc=unit,dc=macaomilano,dc=org
|
||||||
|
attribute_id: uid
|
||||||
|
attribute_mail: mail
|
||||||
|
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
|
@ -44,5 +46,5 @@ logging:
|
||||||
level: DEBUG
|
level: DEBUG
|
||||||
handlers: [console, file]
|
handlers: [console, file]
|
||||||
ldap3:
|
ldap3:
|
||||||
level: DEBUG
|
level: WARNING
|
||||||
handlers: [console, file]
|
handlers: [console, file]
|
||||||
|
|
|
@ -32,7 +32,7 @@ populate:
|
||||||
|
|
||||||
.PHONY: inspect
|
.PHONY: inspect
|
||||||
inspect:
|
inspect:
|
||||||
ldapsearch -ZZ -h 127.0.0.1 \
|
ldapsearch -ZZ -H ldap://127.0.0.1 \
|
||||||
-x -D "cn=root,dc=unit,dc=macaomilano,dc=org" -w root \
|
-x -D "cn=root,dc=unit,dc=macaomilano,dc=org" -w root \
|
||||||
-b "dc=unit,dc=macaomilano,dc=org" \
|
-b "dc=unit,dc=macaomilano,dc=org" \
|
||||||
'(objectclass=*)'
|
'(objectclass=*)'
|
||||||
|
|
|
@ -1,12 +1,23 @@
|
||||||
from aiohttp.web import json_response
|
from aiohttp.web import json_response, View
|
||||||
|
from aiohttp.web import HTTPNotFound, HTTPUnprocessableEntity
|
||||||
|
|
||||||
|
from phi.logging import get_logger
|
||||||
|
from phi.ldap.user import get_user_by_uid
|
||||||
|
from phi.api.utils import serialize
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def status(request):
|
class User(View):
|
||||||
response = {
|
async def get(self):
|
||||||
'ldap': {
|
uid = self.request.match_info.get('uid', None)
|
||||||
'connected': not request.app['ldap_client'].connection.closed,
|
if uid is None:
|
||||||
'bound': request.app['ldap_client'].connection.bound
|
return HTTPUnprocessableEntity()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json_response(response)
|
client = self.request.app['ldap_client']
|
||||||
|
user = get_user_by_uid(client, uid)
|
||||||
|
|
||||||
|
if not user:
|
||||||
|
return HTTPNotFound()
|
||||||
|
|
||||||
|
return json_response(serialize(user))
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from aiohttp.web import get
|
from aiohttp.web import route
|
||||||
|
|
||||||
from phi.api.rest import status
|
from phi.api.rest import User
|
||||||
|
|
||||||
|
|
||||||
api_routes = [
|
api_routes = [
|
||||||
get('/status', status)
|
route('*', '/user/{uid}', User)
|
||||||
]
|
]
|
||||||
|
|
6
src/phi/api/utils.py
Normal file
6
src/phi/api/utils.py
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def serialize(d):
|
||||||
|
return {k: (v.isoformat() if isinstance(v, datetime) else v)
|
||||||
|
for k, v in d.items()}
|
|
@ -10,7 +10,6 @@ def setup_app(config):
|
||||||
app = web.Application(loop=loop)
|
app = web.Application(loop=loop)
|
||||||
app['config'] = config
|
app['config'] = config
|
||||||
|
|
||||||
|
|
||||||
api = api_app(config)
|
api = api_app(config)
|
||||||
app.add_subapp('/api', api)
|
app.add_subapp('/api', api)
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,39 @@
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from ldap3.utils.log import set_library_log_detail_level, BASIC
|
from ldap3.utils.log import set_library_log_detail_level, PROTOCOL
|
||||||
|
|
||||||
from phi.logging import get_logger
|
from phi.logging import get_logger
|
||||||
from phi.ldap.connection import make_connection
|
from phi.ldap.connection import make_connection
|
||||||
from phi.ldap.connection import open_connection, close_connection
|
from phi.ldap.connection import open_connection, close_connection
|
||||||
|
|
||||||
log = get_logger(__name__)
|
log = get_logger(__name__)
|
||||||
set_library_log_detail_level(BASIC)
|
set_library_log_detail_level(PROTOCOL)
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
def __init__(self, host=None, port=389,
|
def __init__(self,
|
||||||
encryption=None, ciphers=None, validate=False,
|
host=None, port=389,
|
||||||
ca_certs=None, username=None, password=None,
|
encryption=None, ciphers=None, validate=False, ca_certs=None,
|
||||||
base_dn=None):
|
username=None, password=None,
|
||||||
|
base_dn=None,
|
||||||
|
attribute_id='uid', attribute_mail='mail'):
|
||||||
log.info("Initializing LDAP Client.")
|
log.info("Initializing LDAP Client.")
|
||||||
|
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
|
|
||||||
self.encryption = encryption
|
self.encryption = encryption
|
||||||
self.ciphers = ciphers
|
self.ciphers = ciphers
|
||||||
self.validate = validate
|
self.validate = validate
|
||||||
self.ca_certs = ca_certs
|
self.ca_certs = ca_certs
|
||||||
|
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
|
|
||||||
self.base_dn = base_dn
|
self.base_dn = base_dn
|
||||||
|
|
||||||
|
self.attribute_id = attribute_id
|
||||||
|
self.attribute_mail = attribute_mail
|
||||||
|
|
||||||
self.connection_lock = Lock()
|
self.connection_lock = Lock()
|
||||||
self.connection = make_connection(host=self.host, port=self.port,
|
self.connection = make_connection(host=self.host, port=self.port,
|
||||||
encryption=self.encryption,
|
encryption=self.encryption,
|
||||||
|
@ -41,7 +50,8 @@ class Client:
|
||||||
self.connection_lock.release()
|
self.connection_lock.release()
|
||||||
else:
|
else:
|
||||||
self.connection_lock.release()
|
self.connection_lock.release()
|
||||||
raise Exception("Trying to open a connection, but it is already open.")
|
raise Exception("Trying to open a connection, "
|
||||||
|
"but it is already open.")
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.connection_lock.acquire()
|
self.connection_lock.acquire()
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
def inspect(client):
|
|
||||||
id = client.connection.search(client.base_dn,
|
|
||||||
'(objectclass=*)')
|
|
||||||
response, result = client.connection.get_response(id)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
def whoami(client):
|
|
||||||
response = client.connection.extend.standard.who_am_i()
|
|
||||||
return response
|
|
36
src/phi/ldap/entry.py
Normal file
36
src/phi/ldap/entry.py
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES
|
||||||
|
|
||||||
|
from phi.logging import get_logger
|
||||||
|
|
||||||
|
log = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_entry_by_uid(client, uid):
|
||||||
|
log.info("Searching entry with identifier: {}".format(uid))
|
||||||
|
|
||||||
|
filter_ = "({}={})".format(client.attribute_id, uid)
|
||||||
|
log.debug("Search filter: {}".format(filter_))
|
||||||
|
|
||||||
|
response_id = client.connection.search(
|
||||||
|
client.base_dn, filter_,
|
||||||
|
search_scope='SUBTREE',
|
||||||
|
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES]
|
||||||
|
)
|
||||||
|
|
||||||
|
response, result, request = client.connection.get_response(
|
||||||
|
response_id, get_request=True
|
||||||
|
)
|
||||||
|
|
||||||
|
log.debug("Request: {}".format(request))
|
||||||
|
log.debug("Response: {}".format(response))
|
||||||
|
log.debug("Result: {}".format(result))
|
||||||
|
|
||||||
|
if not response:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if response[1:]:
|
||||||
|
log.erorr("Looking for exactly one result but server gave {}. "
|
||||||
|
"Taking the first and ignoring the rest."
|
||||||
|
.format(len(response)))
|
||||||
|
|
||||||
|
return response[0]
|
26
src/phi/ldap/user.py
Normal file
26
src/phi/ldap/user.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from phi.ldap.entry import get_entry_by_uid
|
||||||
|
from phi.ldap.utils import flatten_attributes
|
||||||
|
|
||||||
|
|
||||||
|
def user_attributes_mapping(client):
|
||||||
|
return {
|
||||||
|
client.attribute_id: 'uid',
|
||||||
|
client.attribute_mail: 'mail',
|
||||||
|
'createTimestamp': 'created_at',
|
||||||
|
'modifyTimestamp': 'modified_at'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_by_uid(client, uid):
|
||||||
|
entry = get_entry_by_uid(client, uid)
|
||||||
|
|
||||||
|
if not entry:
|
||||||
|
return None
|
||||||
|
|
||||||
|
mapping = user_attributes_mapping(client)
|
||||||
|
|
||||||
|
user = {mapping[k]: v
|
||||||
|
for k, v in entry['attributes'].items()
|
||||||
|
if k in mapping.keys()}
|
||||||
|
|
||||||
|
return flatten_attributes(user)
|
3
src/phi/ldap/utils.py
Normal file
3
src/phi/ldap/utils.py
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
def flatten_attributes(d):
|
||||||
|
return {k: (v[0] if isinstance(v, list) else v)
|
||||||
|
for k, v in d.items()}
|
Loading…
Reference in New Issue
Block a user