Make user groups

Issue #56 resolved
Marcin Kuzminski repo owner created an issue

It's cool to have user groups, and possible permissions actions on them.

Comments (6)

  1. Maciej Sawicki

    I wrote simple python script that sync ldap groups. But build in groups support would be awesome. This is the script:

    __author__ = 'Maciej Sawicki'
    
    LDAP_USERS_BASE_DN = "cn=users,cn=accounts,dc=domain,dc=com"
    LDAP_GROUPS_BASE_DN = "cn=groups,cn=accounts,dc=domain,dc=com"
    LDAP_SERVER_URL = "ldap://ldap-server.domain.com:389"
    RHODE_DB_PATH = "/var/lib/mercurial-server/rhodecode/rhodecode.db"
    LOGS_FILE_PATH = "/var/lib/mercurial-server/RhodeLdapSync/RhodeLdapSync.log"
    
    import logging
    import ldap
    import sqlite3
    import re
    
    import pprint
    
    pp = pprint.PrettyPrinter(indent=4)
    
    l = ldap.initialize(LDAP_SERVER_URL)
    
    logging.basicConfig(filename=LOGS_FILE_PATH, level=logging.DEBUG)
    logger = logging.getLogger()
    
    class Groups(object):
        def __init__(self):
            self.groups = {}
            self.users = []
            self.fetch_LDAP()
            self.con = sqlite3.connect(RHODE_DB_PATH)
            self.cur = self.con.cursor()
            self.con.execute("CREATE TABLE IF NOT EXISTS ldap_synced_groups (group_id INTEGER, UNIQUE(group_id))")
    
        def fetch_LDAP(self):
            try:
                r = l.search_s(LDAP_GROUPS_BASE_DN, ldap.SCOPE_SUBTREE, 'cn=*', ['cn', 'memberUid'])
                for dn, entry in r:
                    if entry.get('memberUid'):
                        group = {"members": entry.get('memberUid'),
                                 "group_id": None
                        }
                        self.groups[entry.get('cn')[0]] = group
    
                r = l.search_s(LDAP_USERS_BASE_DN, ldap.SCOPE_SUBTREE, 'uid=*', ['uid', 'givenName', 'sn', 'mail'])
                for dn, entry in r:
                    uid = entry.get('uid')[0]
                    name = entry.get('givenName', [uid])[0]
                    lastname = entry.get('sn', [uid])[0]
                    email = entry.get('mail', [uid + "@polidea.pl"])[0]
    
                    user = {'name': name,
                            'lastname': lastname,
                            'email': email,
                            'ldap_dn': dn,
                            'uid': uid,
                            }
    
                    self.users.append(user)
    
            except ldap.SERVER_DOWN as e:
                logger.error("can not connect to LDAP server")
            except ldap.NO_SUCH_OBJECT as e:
                logger.error("can not find object, please check if LDAP_USERS_BASE_DN is set correctly")
    
    
        def sync_group_names(self):
            con = self.con
            cur = self.cur
            for group in self.groups:
                group_id = None
                try:
                    cur.execute('insert into users_groups values(NULL,"%s",1)' % group)
                    group_id = cur.lastrowid
                    con.execute("INSERT INTO ldap_synced_groups values %i" % group_id)
                    logger.debug("added: " + group + "with id: " + str(group_id))
                except sqlite3.IntegrityError as e:
                    cur.execute('SELECT users_group_id FROM users_groups WHERE users_group_name ="%s"' % group)
                    group_id = cur.fetchone()[0]
                self.groups[group]["group_id"] = group_id
            con.commit()
    
        def sync_user(self, user):
            con = self.con
            cur = self.cur
            db_user_id = None
            try:
                cur.execute(
                    'insert into users values(NULL,"%(uid)s",NULL,1,0,"%(name)s","%(lastname)s","%(email)s", NULL,"%(ldap_dn)s",NULL)' % user)
                user_id = cur.lastrowid
                logger.debug("added: " + user["uid"] + " with id: " + str(user_id))
            except sqlite3.IntegrityError as e:
                cur.execute("SELECT user_id FROM users WHERE username = '%s'" % user["uid"])
                db_user_id = cur.fetchone()[0]
    
                if db_user_id:
                    logger.debug("skipping: " + user["uid"] + " since: " + "user already exists")
    
                else:
                    cur.execute('SELECT email FROM users WHERE email ="%s"' % user["email"])
                    email = cur.fetchone()
                    if email is not None:
                        email = email[0]
                        logger.warning("WARNING email: " + email + "is in use.")
    
                        new_email = re.sub(r'(.*)(@.*)', r'\1+' + user["uid"] + r'\2', email)
                        logger.warning("WARNING changing " + user['uid'] + "'s email to: " + new_email + ".")
                        cur.execute('insert into users values(NULL,"%s",NULL,1,0,"%s","%s","%s", NULL,"%s",NULL)' % (
                            user['uid'], user["name"],
                            user["lastname"], new_email, user["ldap_dn"]))
                        db_user_id = cur.lastrowid
    
            user["db_user_id"] = db_user_id
            con.commit()
            return user
    
        def sync_users(self):
            self.users = [self.sync_user(user) for user in self.users]
    
    
        def sync_groups(self):
            con = self.con
            cur = self.cur
            self.sync_group_names()
            self.sync_users()
            for group in self.groups:
                users_group_id = self.groups[group]["group_id"]
                members = self.groups[group]["members"]
                for member in members:
                    user = filter(lambda u: u["uid"] == member, self.users)
                    if not user:
                        logger.warning("WARNING: user: " + member + " doesn't exists, was probably deleted.")
                        continue
                    user = user[0]
                    user_id = user["db_user_id"]
                    cur.execute(
                        "SELECT users_group_member_id FROM users_groups_members WHERE users_group_id ='%s' AND user_id = '%s'" %
                        (users_group_id, user_id))
                    if not cur.fetchone():
                        con.execute("INSERT INTO users_groups_members VALUES(NULL, %d, %d)" % (users_group_id, user_id))
                    con.commit()
            con.close()
    
    
    groups = Groups()
    groups.sync_groups()
    
  2. Log in to comment