Skip to content
Snippets Groups Projects
Verified Commit f74081ae authored by nd's avatar nd
Browse files

added support to edit user

parent 8f76104f
No related branches found
No related tags found
No related merge requests found
......@@ -3,3 +3,7 @@ LDAP_BASE_GROUPS="ou=groups,dc=example,dc=com"
LDAP_SERVICE_BIND_DN=""
LDAP_SERVICE_BIND_PASSWORD=""
LDAP_SERVICE_URL="ldapi:///"
LDAP_USER_OBJECTCLASSES=["vmailUser", "top", "inetOrgPerson", "organizationalPerson", "person", "posixAccount"]
LDAP_USER_GID=20001
LDAP_USER_MIN_UID=10000
LDAP_USER_MAX_UID=18999
......@@ -26,7 +26,6 @@ class Group():
@classmethod
def from_ldap_dn(cls, dn):
conn = ldap.service_conn()
print(dn)
conn.search(dn, '(objectClass=groupOfUniqueNames)')
if not len(conn.entries) == 1:
return None
......
from .ldap import bp as ldap_bp
from .ldap import service_conn, user_conn, escape_filter_chars
from .ldap import service_conn, user_conn, escape_filter_chars, uid_to_dn, loginname_to_dn, get_next_uid
bp = [ldap_bp]
......@@ -20,3 +20,31 @@ def service_conn():
def user_conn():
pass
def uid_to_dn(uid):
conn = service_conn()
conn.search(current_app.config["LDAP_BASE_USER"], '(&(objectclass=person)(uidNumber={}))'.format(escape_filter_chars(uid)))
if not len(conn.entries) == 1:
return None
else:
return conn.entries[0].entry_dn
def loginname_to_dn(loginname):
return 'uid={},{}'.format(escape_filter_chars(loginname), current_app.config["LDAP_BASE_USER"])
def get_next_uid():
conn = service_conn()
conn.search(current_app.config["LDAP_BASE_USER"], '(objectclass=person)')
max_uid = current_app.config["LDAP_USER_MIN_UID"]
for i in conn.entries:
# skip out of range entries
if i['uidNumber'].value > current_app.config["LDAP_USER_MAX_UID"]:
continue
if i['uidNumber'].value < current_app.config["LDAP_USER_MIN_UID"]:
continue
max_uid = max(i['uidNumber'].value, max_uid)
next_uid = max_uid + 1
if uid_to_dn(next_uid):
raise Exception('No free uid found')
else:
return next_uid
import string
from ldap3 import MODIFY_REPLACE, HASHED_SALTED_SHA512
from flask import current_app
from uffd import ldap
class User():
......@@ -6,6 +10,7 @@ class User():
loginname = None
displayname = None
mail = None
newpassword = None
def __init__(self, uid=None, loginname='', displayname='', mail='', groups=None):
self.uid = uid
......@@ -14,7 +19,7 @@ class User():
self.mail = mail
if isinstance(groups, str):
groups = [groups]
self.groups_ldap = groups
self.groups_ldap = groups or []
self._groups = None
@classmethod
......@@ -36,7 +41,35 @@ class User():
return User.from_ldap(conn.entries[0])
def to_ldap(self, new):
pass
conn = ldap.service_conn()
if new:
attributes= {
'uidNumber': ldap.get_next_uid(),
'gidNumber': current_app.config['LDAP_USER_GID'],
'homeDirectory': '/home/'+self.loginname,
'sn': ' ',
# same as for update
'givenName': self.displayname,
'displayName': self.displayname,
'cn': self.displayname,
'mail': self.mail,
}
dn = ldap.loginname_to_dn(self.loginname)
result = conn.add(dn, current_app.config['LDAP_USER_OBJECTCLASSES'], attributes)
else:
attributes = {
'givenName': [(MODIFY_REPLACE, [self.displayname])],
'displayName': [(MODIFY_REPLACE, [self.displayname])],
'cn': [(MODIFY_REPLACE, [self.displayname])],
'mail': [(MODIFY_REPLACE, [self.mail])],
}
dn = ldap.uid_to_dn(self.uid)
result = conn.modify(dn, attributes)
if result:
if self.newpassword:
print(self.newpassword)
conn.extend.standard.modify_password(user=dn, old_password=None, new_password=self.newpassword, hash_algorithm=HASHED_SALTED_SHA512)
return result
def get_groups(self):
from uffd.group.models import Group
......@@ -66,4 +99,4 @@ class User():
return True
def set_password(self, value):
raise Exception('TODO: user want to change passwords')
self.newpassword = value
{% extends 'base.html' %}
{% block body %}
<form action="{{ url_for(".user_update", id_=user.uid) }}" method="POST">
<form action="{{ url_for(".user_update", uid=user.uid) }}" method="POST">
<div class="align-self-center">
<div class="form-group col">
<label for="user-uid">uid</label>
......
......@@ -8,7 +8,7 @@
<tr>
<th scope="col">uid</th>
<th scope="col">login name</th>
<th scope="col">given name</th>
<th scope="col">display name</th>
<th scope="col">
<a type="button" class="btn btn-primary" href="{{ url_for(".user_show") }}">
<i class="fa fa-plus" aria-hidden="true"></i> New
......@@ -28,7 +28,7 @@
</a>
</td>
<td>
{{ user.givenname }}
{{ user.displayname }}
</td>
<td>
<a href="{{ url_for(".user_show", uid=user.uid) }}" class="btn btn-primary">
......
......@@ -23,16 +23,18 @@ def user_list():
def user_show(uid=None):
if not uid:
user = User()
ldif = '<none yet>'
else:
conn = service_conn()
conn.search(current_app.config["LDAP_BASE_USER"], '(&(objectclass=person)(uidNumber={}))'.format((escape_filter_chars(uid))))
assert len(conn.entries) == 1
user = User.from_ldap(conn.entries[0])
return render_template('user.html', user=user, user_ldif=conn.entries[0].entry_to_ldif())
ldif = conn.entries[0].entry_to_ldif()
return render_template('user.html', user=user, user_ldif=ldif)
@bp.route("/<int:uid>/update", methods=['POST'])
@bp.route("/new", methods=['POST'])
def user_update(uid=None):
def user_update(uid=False):
conn = service_conn()
if uid:
conn.search(current_app.config["LDAP_BASE_USER"], '(&(objectclass=person)(uidNumber={}))'.format((escape_filter_chars(uid))))
......@@ -51,7 +53,7 @@ def user_update(uid=None):
new_password = request.form.get('password')
if new_password:
user.set_password(new_password)
if user.to_ldap(conn, new=bool(uid)):
if user.to_ldap(new=(not uid)):
flash('User updated')
else:
flash('Error updating user: {}'.format(conn.result['message']))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment