예제 #1
0
class LdapUser(ldapdb.models.Model):
    class Meta:
        managed = False

    rdn_keys = ['username']

    # inetOrgPerson
    first_name = ldap_fields.CharField(db_column='givenName')
    last_name = ldap_fields.CharField(db_column='sn')
    full_name = ldap_fields.CharField(db_column='cn')
    email = ldap_fields.CharField(db_column='mail')
    # posixAccount
    username = ldap_fields.CharField(db_column='uid')
    # ldap specific
    modified_date = ldap_fields.DateTimeField(db_column='modifytimestamp',blank=True)

    def __str__(self):
        return self.username

    def __str__(self):
        return self.full_name

    def save(self,*args,**kwargs):
        force_insert = kwargs.pop('force_insert',None)
        super(LdapUser,self).save(*args,**kwargs)

    class Meta:
        abstract=True
예제 #2
0
파일: models.py 프로젝트: bd808/striker
class Maintainer(ldapdb.models.Model):
    """A tool maintainer."""
    base_dn = settings.TOOLS_MAINTAINER_BASE_DN
    object_classes = ['posixAccount']

    username = fields.CharField(db_column='uid', primary_key=True)
    full_name = fields.CharField(db_column='cn')

    def __str__(self):
        return self.username
예제 #3
0
class LdapMultiPKRoom(ldapdb.models.Model):
    """
    Class for representing a room, using a composite primary key.
    """
    # LDAP meta-data
    base_dn = "ou=rooms,dc=example,dc=org"
    object_classes = ['room']

    # room attributes
    name = fields.CharField(db_column='cn', max_length=200, primary_key=True)
    number = fields.CharField(db_column='roomNumber', max_length=10, primary_key=True)
    phone = fields.CharField(db_column='telephoneNumber', max_length=20, blank=True, null=True)

    def __str__(self):
        return "%s (%s)" % (self.name, self.number)
예제 #4
0
class FakeModel(models.Model):
    class Meta:
        abstract = True

    base_dn = 'ou=test,dc=example,dc=org'
    object_classes = ['inetOrgPerson']
    name = fields.CharField(db_column='cn')
예제 #5
0
파일: models.py 프로젝트: bd808/striker
class Tool(ldapdb.models.Model):
    """A tool is a specially named LDAP group."""
    base_dn = settings.TOOLS_TOOL_BASE_DN
    object_classes = ['posixGroup', 'groupOfNames']

    objects = ToolManager()

    group_name = fields.CharField(db_column='cn',
                                  max_length=200,
                                  primary_key=True)
    gid = fields.IntegerField(db_column='gidNumber', unique=True)
    maintainer_ids = fields.ListField(db_column='member')

    @property
    def name(self):
        return self.group_name[6:]

    @name.setter
    def name(self, value):
        self.group_name = 'tools.{0!s}'.format(value)

    def maintainers(self):
        # OMG, this is horrible. You can't search LDAP by dn.
        return Maintainer.objects.filter(
            username__in=(dn.split(',')[0].split('=')[1]
                          for dn in self.maintainer_ids))

    def __str__(self):
        return self.name
예제 #6
0
class CuLdapUser(LdapUser):
    class Meta:
        managed = False

    base_dn = settings.LDAPCONFS['culdap']['people_dn']
    object_classes = []
    uid = ldap_fields.IntegerField(db_column='uidNumber', unique=True)
    # Used for automatic determination of role and affiliation.
    edu_affiliation = ldap_fields.ListField(db_column='eduPersonAffiliation')
    edu_primary_affiliation = ldap_fields.CharField(db_column='eduPersonPrimaryAffiliation')
    cu_primary_major = ldap_fields.CharField(db_column='cuEduPersonPrimaryMajor1')
    cu_home_department = ldap_fields.CharField(db_column='cuEduPersonHomeDepartment')

    @sensitive_variables('pwd')
    def authenticate(self,pwd):
        authed = ldap_utils.authenticate(self.dn,pwd,'culdap')
        logger = logging.getLogger('accounts')
        logger.info('CU user {} auth attempt: {}'.format(self.username, authed))
        return authed
예제 #7
0
파일: ldap.py 프로젝트: swipswaps/borg-hive
class RepositoryLdapUser(ldapdb.models.Model):
    """
    Class for representing a repository user in LDAP
    """

    # pylint: disable=W0222

    # LDAP meta-data
    base_dn = settings.BORGHIVE['LDAP_USER_BASEDN']
    object_classes = ['organizationalPerson', 'posixAccount', 'shadowAccount']

    last_modified = fields.DateTimeField(db_column='modifyTimestamp')

    # posixAccount
    uid = fields.IntegerField(db_column='uidNumber', unique=True)
    group = fields.IntegerField(db_column='gidNumber')
    gecos = fields.CharField(db_column='gecos', default='Borghive Repo User')
    home = fields.CharField(db_column='homeDirectory',
                            default=settings.BORGHIVE['REPO_PATH'])
    shell = fields.CharField(db_column='loginShell', default='/bin/bash')
    username = fields.CharField(db_column='uid', primary_key=True)
    sn = fields.CharField(db_column='sn', default='')
    cn = fields.CharField(db_column='cn', default='')

    def save(self, *args, **kwargs):
        self.home = os.path.join(settings.BORGHIVE['REPO_PATH'], self.username)
        self.sn = self.username
        self.cn = self.username
        super().save(*args, **kwargs)

    def __str__(self):
        return 'RepositoryLdapUser: {0.dn}: uid={0.uid} gid={0.group}'.format(
            self)
예제 #8
0
class AbstractGroup(ldapdb.models.Model):
    class Meta:
        abstract = True

    object_classes = ['posixGroup']
    gid = fields.IntegerField(db_column='gidNumber', unique=True)
    name = fields.CharField(db_column='cn', max_length=200, primary_key=True)
    usernames = fields.ListField(db_column='memberUid')

    def __str__(self):
        return self.name

    def __unicode__(self):
        return self.name
예제 #9
0
class LdapGroup(ldapdb.models.Model):
    """
    Class for representing an LDAP group entry.
    """

    class Meta:
        verbose_name = "LDAP group"
        verbose_name_plural = "LDAP groups"

    # LDAP meta-data
    base_dn = settings.REG_GROUP_BASE_DN
    object_classes = settings.REG_GROUP_OBJECT_CLASSES

    # LDAP group attributes
    cn = ldapdb_fields.CharField(db_column="cn", max_length=200, primary_key=True)
    description = ldapdb_fields.CharField(db_column="description", max_length=200)
    members = ldapdb_fields.ListField(db_column="member")

    def __str__(self):
        return self.cn

    def __unicode__(self):
        return self.cn
예제 #10
0
class LdapGroup(ldapdb.models.Model):
    """
    Class for representing an LDAP group entry.
    """
    # LDAP meta-data
    base_dn = "ou=groups,dc=example,dc=org"
    object_classes = ['posixGroup']

    # posixGroup attributes
    gid = fields.IntegerField(db_column='gidNumber', unique=True)
    name = fields.CharField(db_column='cn', max_length=200, primary_key=True)
    usernames = fields.ListField(db_column='memberUid')

    def __str__(self):
        return self.name

    def __unicode__(self):
        return self.name
class RCLdapUser(ldapdb.models.Model):
    """
    Class for representing an LDAP user entry.
    """
    rdn_keys = ['username']

    # LDAP meta-data
    base_dn = 'ou=users,dc=example,dc=org'
    object_classes = ['posixAccount', 'inetOrgPerson']
    last_modified = fields.DateTimeField(db_column='modifyTimestamp')

    organization = fields.CharField(max_length=128,blank=False,null=False)

    # inetOrgPerson
    first_name = fields.CharField(db_column='givenName', verbose_name="Prime name")
    last_name = fields.CharField("Final name", db_column='sn')
    full_name = fields.CharField(db_column='cn')
    email = fields.CharField(db_column='mail')

    # posixAccount
    uid = fields.IntegerField(db_column='uidNumber', unique=True)
    group = fields.IntegerField(db_column='gidNumber')
    gecos = fields.CharField(db_column='gecos')
    home_directory = fields.CharField(db_column='homeDirectory')
    login_shell = fields.CharField(db_column='loginShell', default='/bin/bash')
    username = fields.CharField(db_column='uid')

    @property
    def organization(self):
        return self.org

    def __str__(self):
        return self.username

    def __unicode__(self):
        return self.full_name
예제 #12
0
파일: models.py 프로젝트: michigg/lama
class LdapUser(Model):
    """
    Class for representing an LDAP user entry.
    """
    # LDAP meta-data
    ROOT_DN = os.environ.get('LDAP_USER_ENTRY', 'dc=test,dc=de')
    base_dn = ROOT_DN
    object_classes = ['inetOrgPerson']
    # last_modified = ldap_fields.DateTimeField(db_column='modifyTimestamp', blank=True)

    # inetOrgPerson
    username = ldap_fields.CharField(db_column='uid', primary_key=True)
    display_name = ldap_fields.CharField(db_column='displayName', blank=True)
    password = ldap_fields.CharField(db_column='userPassword')
    first_name = ldap_fields.CharField(db_column='cn', blank=True)
    last_name = ldap_fields.CharField(db_column='sn', blank=True)
    email = ldap_fields.CharField(db_column='mail')
    phone = ldap_fields.CharField(db_column='telephoneNumber', blank=True)
    mobile_phone = ldap_fields.CharField(db_column='mobile', blank=True)
    photo = ldap_fields.ImageField(db_column='photo')
    last_login = ldap_fields.DateTimeField(db_column='authTimestamp',
                                           blank=True)

    # photo = ldap_fields.ImageField(db_column='jpegPhoto')

    def __str__(self):
        return self.username

    def __unicode__(self):
        return self.full_name

    @staticmethod
    def create_with_django_user_creation_and_welcome_mail(
            realm, protocol, domain, username, email):
        ldap_user, user = LdapUser.create_with_django_user(
            realm, username, email)
        send_welcome_mail(domain, email, protocol, realm, user)
        return ldap_user

    @staticmethod
    def create_with_django_user(realm, username, email, password=None):
        if not LdapUser.is_user_duplicate(username):
            LdapUser.base_dn = f'ou=people, {realm.ldap_base_dn}'
            # TODO: rewrite
            if password:
                ldap_user = LdapUser.objects.create(username=username,
                                                    email=email,
                                                    first_name=" ",
                                                    last_name=" ",
                                                    password=password)
            else:
                ldap_user = LdapUser.objects.create(username=username,
                                                    email=email,
                                                    first_name=" ",
                                                    last_name=" ")
            if password:
                user, _ = User.objects.get_or_create(username=username,
                                                     email=email,
                                                     password=password)
            else:
                user, _ = User.objects.get_or_create(username=username,
                                                     email=email)
            return ldap_user, user
        else:
            raise ALREADY_EXISTS('User already exists')

    @staticmethod
    def get_extended_user(ldap_user):
        wrapper = {'user': ldap_user}
        try:
            wrapper['deleted_user'] = DeletedUser.objects.get(
                ldap_dn=ldap_user.dn)
        except ObjectDoesNotExist:
            wrapper['deleted_user'] = {}
        try:
            django_user = User.objects.get(username=ldap_user.username)
            wrapper['active'] = True if django_user.last_login else False
        except ObjectDoesNotExist:
            wrapper['active'] = False
        return wrapper

    @staticmethod
    def password_reset(user, raw_password):
        LdapUser.base_dn = LdapUser.ROOT_DN
        ldap_user = LdapUser.objects.get(username=user.username)
        ldap_user.password = raw_password
        LdapUser.base_dn = re.compile('(uid=[a-zA-Z0-9_-]*),(.*)').match(
            ldap_user.dn).group(2)
        ldap_user.save()

    @staticmethod
    def get_users_by_dn(realm, users):
        LdapGroup.base_dn = f'ou=groups,{realm.ldap_base_dn}'
        # logger.debug(users)
        users = [
            re.compile('uid=([a-zA-Z0-9_-]*),(ou=[a-zA-Z_]*),(.*)').match(
                user).group(1) for user in users
        ]
        query = Q(username=users.pop())
        for user in users:
            query = query | Q(username=user)
        LdapUser.base_dn = LdapUser.ROOT_DN
        return LdapUser.objects.filter(query)

    @staticmethod
    def is_user_duplicate(username: str):
        LdapUser.base_dn = LdapUser.ROOT_DN
        try:
            LdapUser.objects.get(username=username)
            return True
        except (NO_SUCH_OBJECT, ObjectDoesNotExist) as err:
            return False

    @staticmethod
    def is_active_user(ldap_user):
        try:
            django_user = User.objects.get(username=ldap_user.username)
            return django_user.last_login
        except ObjectDoesNotExist:
            return False

    @staticmethod
    def get_user_active_marked(ldap_users):
        user_wrappers = []
        for user in ldap_users:
            if LdapUser.is_active_user(user):
                user_wrappers.append({'user': user, 'active': True})
            else:
                user_wrappers.append({'user': user, 'active': False})
        return user_wrappers

    def get_users_realm_base_dn(self):
        return re.compile('(uid=[a-zA-Z0-9_-]*),(ou=[a-zA-Z_-]*),(.*)').match(
            self.dn).group(3)

    @staticmethod
    def get_user(username: str, realm: Realm = None):
        LdapUser.base_dn = f'ou=people, {realm.ldap_base_dn}' if realm else LdapUser.ROOT_DN
        try:
            return LdapUser.objects.get(username=username)
        except Exception as e:
            return None

    @staticmethod
    def get_user_by_dn(dn: str, realm: Realm = None):
        LdapUser.base_dn = f'ou=people, {realm.ldap_base_dn}' if realm else LdapUser.ROOT_DN
        try:
            return LdapUser.objects.get(dn=dn)
        except Exception as e:
            return None

    @staticmethod
    def get_users(realm: Realm = None):
        LdapUser.base_dn = f'ou=people, {realm.ldap_base_dn}' if realm else LdapUser.ROOT_DN
        try:
            return LdapUser.objects.all()
        except Exception as e:
            return None

    @staticmethod
    def get_inactive_users(realm: Realm = None):
        LdapUser.base_dn = realm.ldap_base_dn if realm else LdapUser.ROOT_DN
        last_semester = datetime.now() - timedelta(days=182)
        return (LdapUser.objects.filter(last_login__lte=last_semester)
                | LdapUser.objects.exclude(last_login__lte=datetime.now() +
                                           timedelta(days=1)))

    def get_django_user(self):
        try:
            return User.objects.get(username=self.username)
        except ObjectDoesNotExist:
            return None

    def get_deletable(self):
        try:
            return DeletedUser.objects.get(ldap_dn=self.dn)
        except ObjectDoesNotExist:
            return None

    def delete_complete(self):
        django_user = self.get_django_user()
        deletable_user = self.get_deletable()
        LdapGroup.remove_user_from_groups(self.dn)
        self.delete()
        if django_user:
            django_user.delete()
        if deletable_user:
            deletable_user.delete()

    @staticmethod
    def set_root_dn(realm):
        LdapUser.base_dn = f'ou=people,{realm.ldap_base_dn}'
예제 #13
0
 def test_char_field_max_length(self):
     self.assertEqual(fields.CharField(max_length=42).max_length, 42)
예제 #14
0
class LdapUser(ldapdb.models.Model):
    """
    Class for representing an LDAP user entry.
    """
    # LDAP meta-data
    base_dn = "ou=people,dc=example,dc=org"
    object_classes = ['posixAccount', 'shadowAccount', 'inetOrgPerson']
    last_modified = fields.DateTimeField(db_column='modifyTimestamp')

    # inetOrgPerson
    first_name = fields.CharField(db_column='givenName', verbose_name="Prime name")
    last_name = fields.CharField("Final name", db_column='sn')
    full_name = fields.CharField(db_column='cn')
    email = fields.CharField(db_column='mail')
    phone = fields.CharField(db_column='telephoneNumber', blank=True)
    mobile_phone = fields.CharField(db_column='mobile', blank=True)
    photo = fields.ImageField(db_column='jpegPhoto')

    # posixAccount
    uid = fields.IntegerField(db_column='uidNumber', unique=True)
    group = fields.IntegerField(db_column='gidNumber')
    gecos = fields.CharField(db_column='gecos')
    home_directory = fields.CharField(db_column='homeDirectory')
    login_shell = fields.CharField(db_column='loginShell', default='/bin/bash')
    username = fields.CharField(db_column='uid', primary_key=True)
    password = fields.CharField(db_column='userPassword')

    # shadowAccount
    last_password_change = fields.TimestampField(db_column='shadowLastChange')

    def __str__(self):
        return self.username

    def __unicode__(self):
        return self.full_name
예제 #15
0
class RcLdapUser(LdapUser):
    class Meta:
        verbose_name = 'LDAP user'
        verbose_name_plural = 'LDAP users'
        managed = False

    def __init__(self,*args,**kwargs):
        super(RcLdapUser,self).__init__(*args,**kwargs)
        rdn = self.dn.lower().replace(self.base_dn.lower(), '')
        rdn_list = rdn.split(',')
        self.org = ''
        if len(rdn_list) > 1:
            ou = self.base_dn.lower().split(',')[0]
            __, org = ou.split('=')
            self.org = org
            self.base_dn = self.base_dn.lower()

    objects = RcLdapUserManager()

    base_dn = str(settings.LDAPCONFS['rcldap']['people_dn'])
    object_classes = list(map(str, ['top','person','inetorgperson','posixaccount','curcPerson','shadowAccount']))
    expires = ldap_fields.IntegerField(db_column='shadowExpire',blank=True,null=True)
    uid = ldap_fields.IntegerField(db_column='uidNumber',null=True,blank=True)
    gid = ldap_fields.IntegerField(db_column='gidNumber',null=True,blank=True)
    gecos = ldap_fields.CharField(db_column='gecos',default='')
    home_directory = ldap_fields.CharField(db_column='homeDirectory')
    login_shell = ldap_fields.CharField(db_column='loginShell', default='/bin/bash')
    #curcPerson attributes
    role = ldap_fields.ListField(db_column='curcRole',blank=True,null=True)
    affiliation = ldap_fields.ListField(db_column='curcAffiliation',blank=True,null=True)

    @property
    def organization(self):
        return self.org

    @property
    def effective_uid(self):
        suffixed_username = ldap_utils.get_suffixed_username(self.username,self.organization)
        return suffixed_username

    def _set_base_dn(self,org):
        if org in list(map(str, list(settings.ORGANIZATION_INFO.keys()))):
            ou = 'ou={}'.format(org)
            self.org = org
            if ou not in self.base_dn.lower():
                self.base_dn = ','.join([ou,self.base_dn])
        else:
            raise ValueError('Invalid organization specified: {}'.format(org))

    def save(self,*args,**kwargs):
        org = str(kwargs.pop('organization', None))
        if not org:
            raise ValueError('No organization specified.')
        self._set_base_dn(org)

        # If no UID/GID specified, auto-assign
        logger = logging.getLogger('accounts')
        if (self.uid == None) and (self.gid == None):
            id_tracker = IdTracker.objects.get(category='posix')
            uid = id_tracker.get_next_id()
            self.uid = uid
            self.gid = uid
            logger.info('Auto-assigning UID and GID to user: {}, {}'.format(uid, self.effective_uid))
        elif self.uid == None:
            self.uid = self.gid
            logger.info('Auto-assigning UID to user: {}, {}'.format(self.gid, self.effective_uid))
        elif self.gid == None:
            self.gid = self.uid
            logger.info('Auto-assigning GID to user: {}, {}'.format(self.uid, self.effective_uid))

        super(RcLdapUser,self).save(*args,**kwargs)
예제 #16
0
파일: models.py 프로젝트: michigg/lama
class LdapGroup(Model):
    """
    Class for representing an LDAP group entry.
    """
    # LDAP meta-data
    ROOT_DN = os.environ.get('LDAP_USER_ENTRY', 'dc=test,dc=de')
    base_dn = ROOT_DN
    object_classes = ['groupOfNames']

    name = ldap_fields.CharField(db_column='cn',
                                 max_length=200,
                                 primary_key=True)
    description = ldap_fields.CharField(db_column='description',
                                        max_length=1024)
    members = ldap_fields.ListField(db_column='member')

    @staticmethod
    def get_user_groups(realm: Realm, ldap_user: LdapUser):
        LdapUser.base_dn = f'ou=people,{realm.ldap_base_dn}'
        LdapGroup.base_dn = LdapGroup.ROOT_DN
        return LdapGroup.objects.filter(members=ldap_user.dn)

    @staticmethod
    def add_user_to_groups(ldap_user: LdapUser, ldap_groups: List):
        for ldap_group in ldap_groups:
            ldap_group.members.append(ldap_user.dn)
            ldap_group.save()

    @staticmethod
    def remove_user_from_groups(ldap_user_dn, user_groups=None):
        if not user_groups:
            LdapGroup.base_dn = LdapGroup.ROOT_DN
            user_groups = LdapGroup.objects.filter(
                members__contains=ldap_user_dn)
        for group in user_groups:
            LdapGroup.base_dn = re.compile(
                'cn=([a-zA-Z0-9_-]*),(ou=[a-zA-Z_]*.*)').match(
                    group.dn).group(2)
            group.members.remove(ldap_user_dn)
            group.save()

    def get_django_group(self):
        django_group, _ = Group.objects.get_or_create(name=self.name)
        return django_group

    @staticmethod
    def get_group(group_name: str, realm: Realm = None):
        LdapGroup.base_dn = f'ou=groups,{realm.ldap_base_dn}' if realm else LdapGroup.ROOT_DN
        try:
            return LdapGroup.objects.get(name=group_name)
        except Exception as e:
            logger.error(e)
            return None

    @staticmethod
    def get_groups(realm: Realm = None):
        LdapGroup.base_dn = f'ou=groups,{realm.ldap_base_dn}' if realm else LdapGroup.ROOT_DN
        try:
            return LdapGroup.objects.all()
        except Exception as e:
            logger.error(e)
            return None

    @staticmethod
    def set_root_dn(realm):
        LdapGroup.base_dn = f'ou=groups,{realm.ldap_base_dn}'

    def __str__(self):
        return self.name

    def __unicode__(self):
        return self.name
예제 #17
0
class LdapPerson(ldapdb.models.Model):
    """
    Class for representing an LDAP person entry.
    """

    class Meta:
        verbose_name = "LDAP person"
        verbose_name_plural = "LDAP people"

    # LDAP meta-data
    base_dn = settings.REG_PERSON_BASE_DN
    object_classes = settings.REG_PERSON_OBJECT_CLASSES

    # Minimal attributes
    uid = ldapdb_fields.CharField(db_column="uid", max_length=200, primary_key=True)
    cn = ldapdb_fields.CharField(db_column="cn", max_length=200)
    sn = ldapdb_fields.CharField(db_column="sn", max_length=200)
    mail = ldapdb_fields.CharField(db_column="mail", max_length=200)

    def __str__(self):
        return self.uid

    def __unicode__(self):
        return self.uid

    def change_password(self, raw_password, using=None):
        # dig into the ldapdb primitives
        using = using or router.db_for_write(self.__class__, instance=self)
        connection = connections[using]
        cursor = connection._cursor()

        # call pyldap_orm password modification
        cursor.connection.extop_s(PasswordModify(self.dn, raw_password))

    def check_password(self, raw_password, using=None):
        using = using or router.db_for_write(self.__class__, instance=self)
        conn_params = connections[using].get_connection_params()

        # This is copy-pasta from django-ldapdb/ldapdb/backends/ldap/base.py
        connection = ldap.ldapobject.ReconnectLDAPObject(
            uri=conn_params["uri"],
            retry_max=conn_params["retry_max"],
            retry_delay=conn_params["retry_delay"],
            bytes_mode=False,
        )
        options = conn_params["options"]
        for opt, value in options.items():
            if opt == "query_timeout":
                connection.timeout = int(value)
            elif opt == "page_size":
                self.page_size = int(value)
            else:
                connection.set_option(opt, value)
        if conn_params["tls"]:
            connection.start_tls_s()

        # After setting up the connection, we try to authenticate
        try:
            connection.simple_bind_s(self.dn, raw_password)
        except ldap.INVALID_CREDENTIALS:
            return False

        return True
예제 #18
0
class RcLdapGroup(ldapdb.models.Model):
    class Meta:
        verbose_name = 'LDAP group'
        verbose_name_plural = 'LDAP groups'
        managed = False

    def __init__(self,*args,**kwargs):
        super(RcLdapGroup,self).__init__(*args,**kwargs)

        rdn = self.dn.lower().replace(self.base_dn.lower(), '')
        rdn_list = rdn.split(',')
        self.org = ''
        if len(rdn_list) > 1:
            ou = self.base_dn.lower().split(',')[0]
            __, org = ou.split('=')
            self.org = org
            self.base_dn = self.base_dn.lower()

    objects = RcLdapGroupManager()

    rdn_keys = ['name']
    base_dn =  settings.LDAPCONFS['rcldap']['group_dn']
    object_classes = ['top','posixGroup']
    # posixGroup attributes
    # gid = ldap_fields.IntegerField(db_column='gidNumber', unique=True)
    gid = ldap_fields.IntegerField(db_column='gidNumber',null=True,blank=True)
    name = ldap_fields.CharField(db_column='cn', max_length=200)
    members = ldap_fields.ListField(db_column='memberUid',blank=True,null=True)

    def __str__(self):
        return self.name

    def __str__(self):
        return self.name

    @property
    def organization(self):
        return self.org

    @property
    def effective_cn(self):
        suffixed_name = ldap_utils.get_suffixed_username(self.name,self.organization)
        return suffixed_name

    def _set_base_dn(self,org):
        if org in list(settings.ORGANIZATION_INFO.keys()):
            ou = 'ou={}'.format(org)
            self.org = org
            if ou not in self.base_dn.lower():
                self.base_dn = ','.join([ou,self.base_dn])
        else:
            raise ValueError('Invalid organization specified: {}'.format(org))

    def save(self,*args,**kwargs):
        org = kwargs.pop('organization', None)
        if not org:
            raise ValueError('No organization specified.')
        self._set_base_dn(org)
        force_insert = kwargs.pop('force_insert',None)

        # If no GID specified, auto-assign
        if self.gid == None:
            id_tracker = IdTracker.objects.get(category='posix')
            gid = id_tracker.get_next_id()
            self.gid = gid
            logger = logging.getLogger('accounts')
            logger.info('Auto-assigned GID to group: {}, {}'.format(gid, self.name))

        super(RcLdapGroup,self).save(*args,**kwargs)