From 809f5c17c4bbfbebe9d6de969ef34ba9592984c9 Mon Sep 17 00:00:00 2001 From: nd <git@notandy.de> Date: Sun, 23 Aug 2020 16:48:02 +0200 Subject: [PATCH] added user csv import --- uffd/user/templates/user_list.html | 38 ++++++++++++++++- uffd/user/views_user.py | 67 +++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/uffd/user/templates/user_list.html b/uffd/user/templates/user_list.html index 8bd88a19..85da86db 100644 --- a/uffd/user/templates/user_list.html +++ b/uffd/user/templates/user_list.html @@ -14,6 +14,9 @@ <a type="button" class="btn btn-primary" href="{{ url_for("user.show") }}"> <i class="fa fa-plus" aria-hidden="true"></i> New </a> + <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#csvimport"> + <i class="fa fa-file-csv" aria-hidden="true"></i> CSV import + </button> </p> </th> </tr> @@ -44,5 +47,38 @@ </tbody> </table> </div> -</dev> +</div> + +<div class="modal fade" id="csvimport" tabindex="-1" role="dialog" aria-hidden="true"> + <form action="{{ url_for("user.csvimport") }}" method="POST"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h5 class="modal-title" id="exampleModalLabel">Import a csv formated list of users</h5> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> + <div class="modal-body"> + <p> + The format should be "loginname,mailaddres,groupid1;groupid2;". + Neither setting the display name, nor setting roles or passwords is supported (yet). + Example: + </p> + <pre> +testuser1,foobar@example.com +testuser5,foobsdfar@example.com +testuser5,foobadfar@example.com +testuser2,foobaadsfr@example.com + </pre> + <textarea rows="10" class="form-control" name="csv"></textarea> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> + <button type="submit" class="btn btn-primary">Import</button> + </div> + </div> + </div> + </form> +</div> {% endblock %} diff --git a/uffd/user/views_user.py b/uffd/user/views_user.py index c8afb560..755929b6 100644 --- a/uffd/user/views_user.py +++ b/uffd/user/views_user.py @@ -1,3 +1,6 @@ +import csv +import io + from flask import Blueprint, render_template, request, url_for, redirect, flash, current_app from uffd.navbar import register_navbar @@ -81,19 +84,19 @@ def update(uid=False): role.add_member(user) elif user.dn in role_member_dns: role.del_member(user) - usergroups = set() - for role in Role.get_for_user(user).all(): - usergroups.update(role.group_dns()) - user.replace_group_dns(usergroups) if user.to_ldap(new=is_newuser): if is_newuser: send_passwordreset(user.loginname) flash('User created. We sent the user a password reset link by mail') - session.commit() else: flash('User updated') - session.commit() + + usergroups = set() + for role in Role.get_for_user(user).all(): + usergroups.update(role.group_dns()) + user.replace_group_dns(usergroups) + session.commit() else: flash('Error updating user: {}'.format(conn.result['message'])) session.rollback() @@ -120,3 +123,55 @@ def delete(uid): flash('Could not delete user: {}'.format(conn.result['message'])) session.rollback() return redirect(url_for('user.index')) + +@bp.route("/csv", methods=['POST']) +@csrf_protect(blueprint=bp) +def csvimport(): + csvdata = request.values.get('csv') + if not csvdata: + flash('No data for csv import!') + return redirect(url_for('user.index')) + + roles = Role.query.all() + usersadded = 0 + with io.StringIO(initial_value=csvdata) as csvfile: + csvreader = csv.reader(csvfile) + for row in csvreader: + if not len(row) == 3: + flash("invalid line, ignored : {}".format(row)) + continue + newuser = User() + if not newuser.set_loginname(row[0]) or not newuser.set_displayname(row[0]): + flash("invalid login name, skipped : {}".format(row)) + continue + if not newuser.set_mail(row[1]): + flash("invalid mail address, skipped : {}".format(row)) + continue + session = db.session + + for role in roles: + role_member_dns = role.member_dns() + if (str(role.id) in row[2].split(';')) or role.name in current_app.config["ROLES_BASEROLES"]: + if newuser.dn in role_member_dns: + continue + role.add_member(newuser) + + result = newuser.to_ldap(new=True) + print(result) + if result: + send_passwordreset(newuser.loginname) + + usergroups = set() + for role in Role.get_for_user(newuser).all(): + usergroups.update(role.group_dns()) + newuser.replace_group_dns(usergroups) + + session.commit() + usersadded += 1 + else: + flash('Error adding user {}'.format(row[0])) + session.rollback() + continue + + flash('Added {} new users'.format(usersadded)) + return redirect(url_for('user.index')) -- GitLab