diff --git a/uffd/role/models.py b/uffd/role/models.py index 5371d65e4bb594edbacf65ffc44281bacccdd3a9..4738ce91c5f66c3f701186f9f04ea656b38598e5 100644 --- a/uffd/role/models.py +++ b/uffd/role/models.py @@ -24,9 +24,18 @@ class RoleUser(LdapMapping, db.Model): __tablename__ = 'role-user' def update_user_groups(user): - user.groups.clear() + current_groups = set(user.groups) + groups = set() for role in user.roles: - user.groups.update(role.groups) + groups.update(role.groups) + if groups == current_groups: + return set(), set() + groups_added = groups - current_groups + groups_removed = current_groups - groups + for group in groups_removed: + user.groups.discard(group) + user.groups.update(groups_added) + return groups_added, groups_removed User.update_groups = update_user_groups diff --git a/uffd/role/views.py b/uffd/role/views.py index e915ce5a53a5d0455aab08353ce08266480abac7..86c94145743821b547b89d87dfbd4f36299a3e0b 100644 --- a/uffd/role/views.py +++ b/uffd/role/views.py @@ -1,14 +1,41 @@ +import sys + from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app +import click from uffd.navbar import register_navbar from uffd.csrf import csrf_protect from uffd.role.models import Role -from uffd.user.models import Group +from uffd.user.models import User, Group from uffd.session import get_current_user, login_required, is_valid_session from uffd.database import db from uffd.ldap import ldap bp = Blueprint("role", __name__, template_folder='templates', url_prefix='/role/') + +@bp.record +def add_cli_commands(state): + @state.app.cli.command('roles-update-all', help='Update group memberships for all users based on their roles') + @click.option('--check-only', is_flag=True) + def roles_update_all(check_only): #pylint: disable=unused-variable + consistent = True + with current_app.test_request_context(): + for user in User.query.all(): + groups_added, groups_removed = user.update_groups() + if groups_added: + consistent = False + print('Adding groups [%s] to user %s'%(', '.join([group.name for group in groups_added]), user.dn)) + if groups_removed: + consistent = False + print('Removing groups [%s] from user %s'%(', '.join([group.name for group in groups_removed]), user.dn)) + if not check_only: + ldap.session.commit() + if check_only and not consistent: + print('No changes were made because --check-only is set') + print() + print('Error: LDAP groups are not consistent with roles in database') + sys.exit(1) + @bp.before_request @login_required() def role_acl(): #pylint: disable=inconsistent-return-statements