import csv import argparse import gitlab from mimetypes import guess_type DEFAULT_REPOS = ['solutions', 'exercises'] BASEDN = 'ou=people,dc=tu-bs,dc=de' gl = gitlab.Gitlab.from_config() gl.auth() def group_name(longname): """Use the group number (located at start of group name)""" if longname in ['keine Teilnahme an den Übungen', 'keiner Funktion oder Gruppe zugeordnet', 'Gruppe']: return None else: return longname.split(' ')[0] def parse_groups_csv(csvfile, encoding='utf-8'): """Reads the names of the groups from CSV file and yields the group names """ with open(csvfile, 'r', encoding=encoding) as lines: """ Get distinct values from first column (groups)""" reader = csv.reader(lines, delimiter=';', quotechar='"') zipped = list(zip(*reader)) for groupname in set(zipped[0]): short_name = group_name(groupname) """Discard groups that are None""" if short_name: yield(short_name) def parse_users_csv(csvfile, encoding='utf-8'): """Reads user information from a CSV file and yields id and group""" with open(csvfile, 'r', encoding=encoding) as lines: reader = csv.DictReader(lines, delimiter=';', quotechar='"') for line in reader: user = object() user.id = line['Nutzernamen'] user.email = line['E-Mail'] user.name = line['Vorname'] + ' ' + line['Nachname'] user.group = group_name(line['Gruppe']) def create_student(user_id, email, tutorial): """Create user and add to tutorial group and workgroup based on preferred Abgabepartner User will later be updated with password from LDAP https://gitlab.com/gitlab-org/gitlab-ee/issues/699 """ pass def create_abgabegruppe(tutorial): """Create a Abgabegruppe""" pass def create_tutorial(course, group): """Creates a group via Gitlab API""" # this is the short path, not the full path path = group.replace(' ', '_').lower() try: subgroup = gl.groups.create({'name': group, 'path': path, 'parent_id': course.id}) return subgroup except gitlab.exceptions.GitlabHttpError as e: print(e) def create_course(course_name): courses = gl.groups.list(search=course_name) course = None if len(courses) == 0: path = course_name.replace(' ', '_').lower() course = gl.groups.create({'name': course_name, 'path': path}) else: course = courses[0] return course def create_course_project(name, course): try: gl.projects.create({ 'name': name, 'namespace_id': course.id, 'visibility': 'internal' }) except gitlab.exceptions.GitlabHttpError as e: print(e) def setup_user_project(user, base, course): """Create user projects as forks from course/solutions in namespace of course and add user as developer (NOT master) user should not be able to modify protected TAG or force-push on protected branch users can later invite other users into their projects""" fork = course.projects.list(name=user) if len(fork) == 0: fork = base.forks.create({ 'name': user.id, 'namespace': base.namspace, 'visibility': 'private' }) fork.members.create({ 'user_id': user.id, 'access_level': gitlab.DEVELOPER_ACCESS }) return fork def create_dummy_ldap_user(user): """Creates a dummy user for users that do not exist in gitlab but in LDAP and have not logged in yet""" users = gl.users.list(search=user) if len(users) == 0: dummy = gl.users.create({ 'email': user.email, 'username': user.name, 'name': user.id, 'provider': 'main', 'skip_confirmation': true, 'extern_uid': 'uid=%s,%s' % (user.id, basedn), 'password': secrets.token_urlsafe(nbytes=32) }) return dummy else: return users[0] if __name__ == '__main__': parser = argparse.ArgumentParser(description='Import groups and users from data source') parser.add_argument('course', type=str, nargs=1, help='name of the course') parser.add_argument('source', type=str, nargs=1, help='data source') parser.add_argument('--encoding', type=str, nargs=1, help='encoding of source') args = parser.parse_args() type, _ = guess_type(args.source[0]) course = args.course[0] course = create_course(course) for repo in DEFAULT_REPOS: course_project = create_course_project(repo, course) users = None if type == 'text/csv': # TODO get functions from API and add hiwis to admins users = parse_users_csv(args.source[0], args.encoding[0]) elif type == None: print('MIME type not recognized') for user in users: create_dummy_user_ldap(user) setup_user_project(user, course) """TODO - add users (LDAP) with custom attribute for group, matrikelnummer + if user exists set custom attributes - create search for custom attribute (-> checkout repos for group) """