add some group management

This commit is contained in:
Franzi 2021-12-21 09:27:25 +01:00
parent 602127cbdc
commit 026fbf3c58
Signed by: kunsi
GPG key ID: 12E3D2136B818350
6 changed files with 157 additions and 21 deletions

View file

@ -2,9 +2,17 @@ from json import load
from os import environ from os import environ
from flask import Flask, flash, redirect, request, session, url_for from flask import Flask, flash, redirect, request, session, url_for
from ldap3 import ALL_ATTRIBUTES
from ldap3.core.exceptions import LDAPException from ldap3.core.exceptions import LDAPException
from .helpers.ldap import login_required, try_auth, get_user, template, update_user from .helpers.flask import template
from .helpers.ldap import (
admin_required,
get_user,
login_required,
try_auth,
update_user,
)
app = Flask(__name__) app = Flask(__name__)
app.secret_key = environ.get("FLASK_SECRET_KEY", default="test") app.secret_key = environ.get("FLASK_SECRET_KEY", default="test")
@ -66,7 +74,7 @@ def selfservice(ldap):
request.form["givenName"], request.form["givenName"],
request.form["sn"], request.form["sn"],
), ),
"mail": request.form["mail"] "mail": request.form["mail"],
}, },
) )
flash("data updated") flash("data updated")
@ -82,3 +90,44 @@ def selfservice(ldap):
flash(e) flash(e)
return template(ldap, "selfservice.html") return template(ldap, "selfservice.html")
@app.route("/groups", methods=["GET"])
@login_required
def groups(ldap):
ldap.search(
APP_CONFIG["ldap"]["group_base"],
"(objectclass=groupOfNames)",
attributes=ALL_ATTRIBUTES,
)
return template(
ldap,
"groups/list.html",
groups=ldap.entries,
)
@app.route("/groups/<ou>", methods=["GET", "POST"])
@admin_required
def group_edit(ldap, ou):
if request.method == "POST":
if request.form.get("remove"):
flash(
f"did not remove {request.form['remove']} because not yet implemented"
)
return redirect(url_for("group_edit", ou=ou))
ldap.search(
APP_CONFIG["ldap"]["user_base"],
APP_CONFIG["template"]["group_members"].format(ou),
attributes=ALL_ATTRIBUTES,
)
return template(
ldap,
"groups/members.html",
members=ldap.entries,
ou=ou,
)

View file

@ -0,0 +1,38 @@
from functools import wraps
from json import load
from os import environ
from flask import redirect, render_template, session, url_for
from .ldap import get_user
with open(environ["APP_CONFIG"]) as f:
APP_CONFIG = load(f)
def template(ldap, name, **kwargs):
user = None
is_admin = False
if ldap:
user = get_user(ldap, session["username"])
ldap.search(
APP_CONFIG["ldap"]["user_base"],
APP_CONFIG["template"]["group_admin"].format(user["uid"]),
attributes=["uid"],
)
if len(ldap.entries) == 1:
is_admin = True
return render_template(
name,
APP_CONFIG=APP_CONFIG,
CURRENT_USER=user,
USER_IS_ADMIN=is_admin,
**kwargs,
)
class UserNotFoundException(Exception):
pass

View file

@ -2,9 +2,8 @@ from functools import wraps
from json import load from json import load
from os import environ from os import environ
from flask import redirect, session, url_for, render_template from flask import redirect, session, url_for
from ldap3 import ALL, Connection, Server from ldap3 import ALL, ALL_ATTRIBUTES, MODIFY_REPLACE, Connection, Server
from ldap3 import ALL_ATTRIBUTES, MODIFY_REPLACE
from ldap3.core.exceptions import LDAPException from ldap3.core.exceptions import LDAPException
with open(environ["APP_CONFIG"]) as f: with open(environ["APP_CONFIG"]) as f:
@ -21,7 +20,7 @@ def login_required(func):
): ):
ldap = connect() ldap = connect()
return func(ldap, *args, **kwargs) return func(ldap, **kwargs)
else: else:
return redirect(url_for("login")) return redirect(url_for("login"))
else: else:
@ -41,7 +40,16 @@ def admin_required(func):
): ):
ldap = connect() ldap = connect()
return func(ldap, *args, **kwargs) ldap.search(
APP_CONFIG["ldap"]["user_base"],
APP_CONFIG["template"]["group_admin"].format(session["username"]),
attributes=["uid"],
)
if len(ldap.entries) == 1:
return func(ldap, **kwargs)
else:
return redirect(url_for("selfservice"))
else: else:
return redirect(url_for("login")) return redirect(url_for("login"))
else: else:
@ -89,6 +97,7 @@ def get_user(ldap, username):
else: else:
raise UserNotFoundException(username) raise UserNotFoundException(username)
def update_user(ldap, username, settings): def update_user(ldap, username, settings):
attrs = {} attrs = {}
for attr, value in settings.items(): for attr, value in settings.items():
@ -100,18 +109,5 @@ def update_user(ldap, username, settings):
) )
def template(ldap, name, **kwargs):
user = None
if ldap:
user = get_user(ldap, session["username"])
return render_template(
name,
APP_CONFIG=APP_CONFIG,
CURRENT_USER=user,
**kwargs,
)
class UserNotFoundException(Exception): class UserNotFoundException(Exception):
pass pass

View file

@ -0,0 +1,26 @@
{% extends "layout/default.html" %}
{% block title %}groups{% endblock %}
{% block content %}
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th scope="col">group name</th>
<th scope="col">group description</th>
<th scope="col">member count</th>
</tr>
</thead>
<tbody>
{% for group in groups|sort %}
<tr>
{% if USER_IS_ADMIN %}
<th scope="row"><a href="{{ url_for("group_edit", ou=group["ou"]) }}">{{ group["ou"] }}</a></th>
{% else %}
<th scope="row">{{ group["ou"] }}</th>
{% endif %}
<td>{{ group["description"] }}</td>
<td>{{ group["member"]|length }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -0,0 +1,27 @@
{% extends "layout/default.html" %}
{% block title %}group {{ ou }}{% endblock %}
{% block content %}
<table class="table table-hover align-middle">
<thead class="table-light">
<tr>
<th scope="col">uid</th>
<th scope="col">cn</th>
<th scope="col">remove</th>
</tr>
</thead>
<tbody>
{% for member in members|sort %}
<tr>
<th scope="row">{{ member["uid"] }}</th>
<td>{{ member["cn"] }}</td>
<td>
<form action="{{ url_for("group_edit", ou=ou) }}" method="post">
<input type="hidden" name="remove" value="{{ member["uid"] }}">
<input type="submit" value="remove" class="btn btn-danger">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -23,7 +23,7 @@
<a class="nav-link" href="{{ url_for("selfservice") }}">self service</a> <a class="nav-link" href="{{ url_for("selfservice") }}">self service</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#">groups</a> <a class="nav-link" href="{{ url_for("groups") }}">groups</a>
</li> </li>
</ul> </ul>
<span class="navbar-text navbar-right">Signed in as <em>{{ CURRENT_USER["uid"] }}</em> - <a href="{{ url_for("logout") }}">logout</a></span> <span class="navbar-text navbar-right">Signed in as <em>{{ CURRENT_USER["uid"] }}</em> - <a href="{{ url_for("logout") }}">logout</a></span>