class LdapUser(ldapdb.models.Model): """ Class for representing an LDAP user entry. """ # LDAP meta-data base_dn = LDAP_BASE_DN object_classes = LDAP_OBJECT_CLASSES # inetOrgPerson first_name = CharField(db_column='givenName', verbose_name="Prime name") last_name = CharField("Final name", db_column='sn') full_name = CharField(db_column='cn') email = CharField(db_column='mail') phone = CharField(db_column='telephoneNumber', blank=True) mobile_phone = CharField(db_column='mobile', blank=True) photo = ImageField(db_column='jpegPhoto') # posixAccount uid = IntegerField(db_column='uidNumber', unique=True) group = IntegerField(db_column='gidNumber') gecos = CharField(db_column='gecos') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default='/bin/bash') username = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword') def __str__(self): return self.username def __unicode__(self): return self.full_name
class Group(BaseLdapModel): base_dn = force_text('ou=Groups,' + settings.LDAP_BASE_DN) object_classes = force_bytestrings(['posixGroup', 'sambaGroupMapping']) # posixGroup attributes name = CharField(db_column=force_text('cn'), max_length=200, primary_key=True, validators=list(name_validators)) gid = IntegerField(db_column=force_text('gidNumber'), unique=True) members = ListField(db_column=force_text('memberUid')) description = CharField(db_column=force_text('description'), max_length=500, blank=True, default='') group_type = IntegerField(db_column=force_text('sambaGroupType'), default=None) samba_sid = CharField(db_column=force_text('sambaSID'), unique=True, default='') def save(self, using=None): self.group_type = 2 self.set_next_free_value('gid', default=10000) # noinspection PyStringFormat self.samba_sid = '%s-%d' % (get_samba_sid(), self.gid) super(Group, self).save(using=using) group_of_names = list(GroupOfNames.objects.filter(name=self.name)[0:1]) if not group_of_names: group = GroupOfNames(name=self.name, members=['cn=admin,' + settings.LDAP_BASE_DN]) group.save() else: group = group_of_names[0] new_members = ['cn=admin,' + settings.LDAP_BASE_DN] + ['uid=%s,%s' % (x, User.base_dn) for x in self.members] if new_members != group.members: group.members = new_members group.save()
class LdapUser(ldapdb.models.Model): """ Class for representing an LDAP user entry. """ # LDAP meta-data base_dn = "ou=people,dc=nodomain" object_classes = ['posixAccount', 'shadowAccount', 'inetOrgPerson'] # inetOrgPerson first_name = CharField(db_column='givenName') last_name = CharField(db_column='sn') full_name = CharField(db_column='cn') email = CharField(db_column='mail') phone = CharField(db_column='telephoneNumber', blank=True) mobile_phone = CharField(db_column='mobile', blank=True) photo = ImageField(db_column='jpegPhoto') # posixAccount uid = IntegerField(db_column='uidNumber', unique=True) group = IntegerField(db_column='gidNumber') gecos = CharField(db_column='gecos') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default='/bin/bash') username = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword') date_of_birth = DateField(db_column='birthday', blank=True) latitude = FloatField(db_column='latitude', blank=True) def __str__(self): return self.username def __unicode__(self): return self.full_name
class ServiceAccount(BaseLdapModel): # description used as description for primary groups of users base_dn = 'ou=Services,' + settings.LDAP_BASE_DN object_classes = force_bytestrings(['posixAccount', 'shadowAccount', 'inetOrgPerson', 'person']) fqdn = CharField(db_column=force_text('uid'), max_length=200, primary_key=True, validators=list(name_validators)) uid_number = IntegerField(db_column=force_text('uidNumber'), default=None, unique=True) gid_number = IntegerField(db_column=force_text('gidNumber'), default=None) # forced values display_name = CharField(db_column=force_text('displayName'), max_length=200) mail = CharField(db_column=force_text('mail'), default=None) gecos = CharField(db_column=force_text('gecos'), max_length=200, default=None) cn = CharField(db_column=force_text('cn'), max_length=200, default=None, validators=list(name_validators)) sn = CharField(db_column=force_text('sn'), max_length=200, default=None, validators=list(name_validators)) # password values user_password = CharField(db_column=force_text('userPassword'), default=None) # samba_nt_password = CharField(db_column=force_text('sambaNTPassword'), default=None) def save(self, using=None): self.cn = self.fqdn self.sn = self.fqdn self.display_name = self.fqdn self.gecos = self.fqdn self.mail = '%s@%s' % (self.fqdn, settings.PENATES_DOMAIN) self.set_next_free_value('uid_number') self.gid_number = self.uid_number super(ServiceAccount, self).save(using=using) def set_password(self, password): self.user_password = password_hash(password) self.save()
class LdapUser(Model): """ Class for representing an LDAP user entry. """ class Meta: managed = False base_dn = settings.AUTH_LDAP_BASE object_classes = [ 'posixAccount', 'shadowAccount', 'inetOrgPerson', 'top', 'person', 'organizationalPerson' ] first_name = CharField(db_column='givenName') last_name = CharField(db_column='sn') full_name = CharField(db_column='cn') email = CharField(db_column='mail') username = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword') uid = IntegerField(db_column='uidNumber', unique=True) group = IntegerField(db_column='gidNumber') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default='/bin/bash') description = CharField(db_column='description') def __str__(self): return self.uid def __unicode__(self): return self.full_name
class LDAPPosixUser(LDAPModel): """ Class for representing an LDAP user entry. """ objects = LDAPPosixUserManager() # LDAP meta-data base_dn = settings.LDAP_SYNC_USER_BASE_DN object_classes = ['top', 'posixAccount', 'inetOrgPerson'] # inetOrgPerson first_name = CharField(db_column='givenName', verbose_name="Prime name") last_name = CharField("Final name", db_column='sn') common_name = CharField(db_column='cn') email = ListField(db_column='mail') # posixAccount uid = IntegerField(db_column='uidNumber', default=1000) group = IntegerField(db_column='gidNumber') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default='/bin/bash') nadine_id = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword') if hasattr(settings, 'LDAP_SYNC_USER_HOME_DIR_TEMPLATE'): HOME_DIR_TEMPLATE = settings.LDAP_SYNC_USER_HOME_DIR_TEMPLATE else: HOME_DIR_TEMPLATE = "/home/{}" def ensure_gid(self): """ If no group is set then perform a get_or_create() for default members group. """ if self.group is None: members_group, _ = LDAPPosixGroup.objects.get_or_create( name=settings.LDAP_SYNC_MEMBERS_GROUP_CN) self.group = members_group.gid def ensure_home_directory(self): """ If no home_directory is set then LDAP complains, we can auto-populate. """ if not self.home_directory: self.home_directory = self.HOME_DIR_TEMPLATE.format(self.uid) def save(self, *args, **kwargs): self.ensure_gid() self.ensure_home_directory() return super(LDAPPosixUser, self).save(*args, **kwargs) def __str__(self): return "{}:{}".format(self.nadine_id, self.common_name) def __str__(self): return self.full_name
def test_integer_field(self): where = WhereNode() where.add((Constraint("uid", "uid", IntegerField()), 'exact', 1), AND) self.assertEquals(where.as_sql(), ("(uid=1)", [])) where = WhereNode() where.add((Constraint("uid", "uid", IntegerField()), 'gte', 1), AND) self.assertEquals(where.as_sql(), ("(uid>=1)", [])) where = WhereNode() where.add((Constraint("uid", "uid", IntegerField()), 'lte', 1), AND) self.assertEquals(where.as_sql(), ("(uid<=1)", []))
class LdapUser(ldapdb.models.Model): """ Class for representing an LDAP user entry. """ # LDAP meta-data # base_dn = 'ou=tenant' + settings.APP_TENANT_ID + ',' + settings.LDAP_BASE_SEARCH_DN base_dn = settings.LDAP_BASE_SEARCH_DN object_classes = ['inetOrgPerson'] # inetOrgPerson first_name = CharField(db_column='givenName', blank=True) last_name = CharField(db_column='sn', blank=True) full_name = CharField(db_column='cn', blank=True) email = CharField(db_column='mail') phone = CharField(db_column='telephoneNumber', blank=True) mobile_phone = CharField(db_column='mobile', blank=True) nonce = CharField(db_column='employeeNumber', blank=True) status = CharField(db_column='employeeType', blank=True) create_time = CharField(db_column='createTimestamp', blank=True) # posixAccount uid = IntegerField(db_column='uidNumber', unique=True, blank=True) username = CharField(db_column='uid', primary_key=True) password = CharField(db_column='userPassword', blank=True) def __str__(self): return self.username def __unicode__(self): return self.full_name
class LdapGroup(ldapdb.models.Model): """ Class for representing an LDAP group entry. """ # LDAP meta-data base_dn = "ou=group,dc=iapp-intern,dc=de" object_classes = [ 'posixGroup', 'extensibleObject', ] # posixGroup cn = CharField(db_column='cn', primary_key=True) gidNumber = IntegerField(db_column='gidNumber', unique=True) description = CharField(db_column='description', blank=True) memberUid = ListField(db_column='memberUid') # extensibleObject owner = ListField(db_column='owner') def __str__(self): return self.cn def __unicode__(self): return self.cn
class Principal(BaseLdapModel): base_dn = 'cn=krbContainer,' + settings.LDAP_BASE_DN object_classes = force_bytestrings(['krbPrincipal', 'krbPrincipalAux', 'krbTicketPolicyAux']) name = CharField(db_column=force_text('krbPrincipalName'), primary_key=True) flags = IntegerField(db_column=force_text('krbTicketFlags'), default=None) def save(self, using=None): self.flags = 128 super(Principal, self).save(using=using)
class LdapGroup(ldapdb.models.Model): """ Class for representing an LDAP group entry. """ # LDAP meta-data base_dn = "ou=groups,dc=nodomain" object_classes = ['posixGroup'] # posixGroup attributes gid = IntegerField(db_column='gidNumber', unique=True) name = CharField(db_column='cn', max_length=200, primary_key=True) usernames = ListField(db_column='memberUid') def __str__(self): return self.name def __unicode__(self): return self.name
class LdapGroup(ldapdb.models.Model): """ Represents an LDAP posixGroup entry. """ connection_name = 'ldap' # LDAP meta-data base_dn = settings.LDAP_GROUP_DN object_classes = ['posixGroup'] # posixGroup attributes gid = IntegerField(db_column='gidNumber', unique=True) name = CharField(db_column='cn', max_length=200, primary_key=True) members = ListField(db_column='memberUid') def __str__(self): return self.name class Meta: managed = False
class LDAPPosixGroup(LDAPModel): """ Class for representing an LDAP group entry. """ objects = LDAPPosixGroupManager() # LDAP meta-data base_dn = settings.LDAP_SYNC_GROUP_BASE_DN object_classes = ['posixGroup'] # posixGroup attributes gid = IntegerField(db_column='gidNumber', default=500) name = CharField(db_column='cn', max_length=200, primary_key=True) usernames = ListField(db_column='memberUid') def __str__(self): return self.name def __str__(self): return self.name
class LdapGroup(ldapdb.models.Model): """ Represents LDAP group stored in LDAP directory, configured in settings.py """ # LDAP meta-data base_dn = "ou=Groups,dc=futurice,dc=com" # attributes gid = IntegerField(db_column='gidNumber', unique=True) name = CharField(db_column='cn', max_length=200, primary_key=True) members = ListField(db_column='uniqueMember') def __unicode__(self): return self.name @property def members_usernames(self): usernames = [] for member in self.members: # The members are given in ldap entries - we need to parse the user id from them matched = re.match(r'uid=(?P<uid>\w+?),.*', member) usernames.append(matched.group('uid')) return usernames
class GvUserPortal(ldapdb.models.Model): class Meta: managed = False base_dn = "dc=at" object_classes = ['gvUserPortal'] # RDN == Primary Key: cn is list field _only_ using a single value by convention cn = CharField(db_column='cn', max_length=250, primary_key=True) description = CharField(db_column='description', max_length=1024) gvAdminContactMail = ArrayField(CharField(db_column='gvAdminContactMail ', max_length=256),) gvAdminContactName = ArrayField(CharField(db_column='gvAdminContactName', max_length=256),) gvAdminContactTel = ArrayField(CharField(db_column='gvAdminContactTel', max_length=32),) gvDefaultParticipant = CharField(db_column='gvDefaultParticipant', max_length=32) gvMaxSecClass = IntegerField(db_column='gvMaxSecClass') gvParticipants = ListField(db_column='gvParticipants', ) gvPortalHotlineMail = ArrayField(CharField(db_column='gvPortalHotlineMail', max_length=250),) gvSupportedPvpProfile = ArrayField(CharField(db_column='gvSupportedPvpProfile', max_length=1024),) gvScope = CharField(db_column='gvScope', max_length=250) gvSource = CharField(db_column='gvSource', max_length=250) gvStatus = CharField(db_column='gvStatus', max_length=250) def __str__(self): return self.cn def __repl__(self): return self.dn def has_add_permission(self, request): return False # Allow viewing objects but not actually changing them. def has_change_permission(self, request, obj=None): return (request.method in ['GET', 'HEAD'] and super().has_change_permission(request, obj)) def has_delete_permission(self, request, obj=None): return False
def rel_db_type(self, connection): return IntegerField().db_type(connection=connection)
class Person(ldapdb.models.Model): """ A Domesday person. """ base_dn = "ou=people,dc=mozillians,dc=org" object_classes = ['inetOrgPerson', 'domesdayPerson'] uid = IntegerField(db_column='uid', max_length=256, primary_key=True) # Other fields to consider include: # timezone # lat/long (with UI to help users specify with an appropriate degree of # vagueness) cn = CharField(db_column='cn', max_length=32768) name = CharField(db_column='displayName', max_length=32768) familyName = CharField(db_column='sn', max_length=32768) nickname = CharField(db_column='domesdayNickName', max_length=32768) address = CharField(db_column='postalAddress', max_length=1024) locality = CharField(db_column='l', max_length=32768) country = CharField(db_column='co', max_length=32768) phone = CharField(db_column='telephoneNumber', max_length=32768) title = CharField(db_column='title', max_length=32768) bio = CharField(db_column='description', max_length=1024) email = CharField(db_column='mail', max_length=256) urls = ListField(db_column='labeledURI') startyear = IntegerField(db_column='domesdayStartYear', max_length=32768) tshirtsize = CharField(db_column='domesdayTShirtSize', max_length=32768) password = CharField(db_column='userPassword', max_length=128) photo = ImageField(db_column='jpegPhoto') def get_tags(self): tags = Tag.objects.filter(members__contains=self.dn) return [t.name for t in tags] def set_tags(self, tags): # Create Tag objects for each tag in the list (new ones # if necessary) and make sure the user is a member of all of them. for tag in tags: try: t = Tag.objects.get(name=tag) except Tag.DoesNotExist: t = Tag(name=tag) if not self.dn in t.members: t.members.append(self.dn) t.save() # Remove user from tags which were not specified current_tags = Tag.objects.filter(members__contains=self.dn) for ct in current_tags: if not ct.name in tags: if len(ct.members) == 1: # They are the only person left with this tag ct.delete() else: ct.members.remove(self.dn) ct.save() tags = property(get_tags, set_tags) def get_accounts(self): accts = Account.scoped("uid=%s,%s" % (self.uid, Account.base_dn)) return accts.objects.all().values() def set_accounts(self, accounts): # Create Account objects for each account in the list (new ones # if necessary). MyAccount = Account.scoped("uid=%s,%s" % (self.uid, Account.base_dn)) current_accts = MyAccount.objects.all() """ XXX FilterExceptions... for a in accounts: try: ca = MyAccount.objects.get(domain=a['domain']) ca.userid = a['userid'] except MyAccount.DoesNotExist: ca = MyAccount(domain=a['domain'], userid=a['userid']) ca.save() """ # Remove user from accounts which were not specified account_domains = [a['domain'] for a in accounts] for ca in current_accts: if not ca.domain in account_domains: ca.delete() accounts = property(get_accounts, set_accounts) def get_userid(self, domain): accts = Account.scoped("uid=%s,%s" % (self.uid, Account.base_dn)) account = accts.objects.filter(domain=domain) if account: return account[0].userid else: return None # This returns an object whose layout matches the PortableContacts schema # http://portablecontacts.net/draft-spec.html (retrieved 2011-04-19) # XXX Need to check doc more carefully and make sure it actually does in # every respect. def json_struct(self): json_struct = { "displayName": self.name, "name": { "formatted": self.name, "familyName": self.familyName, }, "nickname": self.nickname or "", "id": self.uid } if self.tags: json_struct["tags"] = [tag for tag in self.tags] if self.email: json_struct["emails"] = [{ "value": self.email, "primary": "true" }] if self.urls: json_struct["urls"] = [{ "value": u, "type": "other" } for u in self.urls] if self.phone: json_struct["phoneNumbers"] = [{ "value": self.phone }] if self.photo: json_struct["photos"] = [{ # XXX not an absolute URL, only site-relative "value": url('domesday.views.photo', pk=self.uid), "type": "thumbnail" }] if self.address or self.locality or self.country: json_struct["addresses"] = [{ "streetAddress": self.address or "", "locality": self.locality or "", "country": self.country or "", "formatted": self.address + "\n" + self.country }] if self.accounts: json_struct["accounts"] = [{ "domain": a['domain'], "userid": a['userid'] } for a in self.accounts] return json_struct def __str__(self): return self.name def __unicode__(self): return self.name def save(self, using=None): # Make sure all required fields are populated (sn and cn) if not self.familyName: self.familyName = " " if not self.cn: self.cn = self.familyName super(Person, self).save(using)
class Person(ldapdb.models.Model): """ A Domesday person. """ base_dn = "ou=people,dc=mozillians,dc=org" object_classes = ['inetOrgPerson', 'domesdayPerson'] uid = IntegerField(db_column='uid', max_length=256, primary_key=True) cn = CharField(db_column='cn', max_length=32768) givenName = CharField(db_column='givenName', max_length=32768) familyName = CharField(db_column='sn', max_length=32768) name = CharField(db_column='displayName', max_length=32768) nickname = CharField(db_column='domesdayNickName', max_length=32768) title = CharField(db_column='title', max_length=32768) address = CharField(db_column='postalAddress', max_length=1024) locality = CharField(db_column='l', max_length=32768) bio = CharField(db_column='description', max_length=1024) email = CharField(db_column='mail', max_length=256) # XXX Do we need a PasswordField type? password = CharField(db_column='userPassword', max_length=128) photo = ImageField(db_column='jpegPhoto') def get_tags(self): return Tag.objects.filter(members__contains=self.dn) def set_tags(self): pass tags = property(get_tags, set_tags) # Blog and website are stored as labeledURI fields, with the labels 'blog' # and 'website'. This means we need some mapping. labeledURIs = ListField(db_column='labeledURI') def get_uri(self, tag): test = re.compile("^(.*) " + tag + "$") results = filter(test.search, self.labeledURIs) if len(results): return test.match(results[0]).group(1) else: return "" def set_uri(self, tag, value): # Extract the old version, if present test = re.compile("^(.*) " + tag + "$") results = filter(lambda u: not test.search(u), self.labeledURIs) # Add the new one results.append(value + " " + tag) self.labeledURIs = results return self.get_uri(tag) def get_website(self): return self.get_uri("website") def set_website(self, website): return self.set_uri("website", website) website = property(get_website, set_website) def get_blog(self): return self.get_uri("blog") def set_blog(self, blog): return self.set_uri("blog", blog) blog = property(get_blog, set_blog) country = CharField(db_column='co', max_length=32768) phone = CharField(db_column='telephoneNumber', max_length=32768) tshirtsize = CharField(db_column='domesdayTShirtSize', max_length=32768) startyear = IntegerField(db_column='domesdayStartYear', max_length=32768) # XXX accounts/system IDs # This returns an object whose layout matches the PortableContacts schema # http://portablecontacts.net/draft-spec.html (retrieved 2011-04-19) # XXX Need to check doc more carefully and make sure it actually does in # every respect. def json_struct(self): json_struct = { "displayName": self.name, "name": { "formatted": self.name, "familyName": self.familyName, "givenName": self.givenName or "" }, "nickname": self.nickname or "", "id": self.uid } if self.tags: json_struct["tags"] = [tag.name for tag in self.tags] if self.email: json_struct["emails"] = [{"value": self.email, "primary": "true"}] if self.blog or self.website: json_struct["urls"] = [] if self.blog: json_struct["urls"].append({ "value": self.blog, "type": "blog" }) if self.website: json_struct["urls"].append({ "value": self.website, "type": "home" }) if self.phone: json_struct["phoneNumbers"] = [{"value": self.phone}] if self.photo: json_struct["photos"] = [{ # XXX not an absolute URL, only site-relative "value": url('domesday.views.photo', pk=self.uid), "type": "thumbnail" }] if self.address or self.locality or self.country: json_struct["addresses"] = [{ "streetAddress": self.address or "", "locality": self.locality or "", "country": self.country or "", "formatted": self.address + "\n" + self.country }] # "accounts": [ # {% for a in self.accounts %} # {% if not forlooself.first %}, {% endif %} # { # "domain": a.domain, # "userid": a.user # } # {% endfor %} #], return json_struct def __str__(self): return self.name def __unicode__(self): return self.name
class LDAPUser(ldapdb.models.Model): """ Class representing an LDAP user entry """ # LDAP metadata base_dn = settings.AUTH_LDAP_USER_BASE_DN object_classes = settings.AUTH_LDAP_USER_OBJECTCLASS # top object_class = ListField(db_column='objectClass') # person last_name = CharField(db_column='sn') full_name = CharField(db_column='cn') description = CharField(db_column='description') phone = CharField(db_column='telephoneNumber', blank=True) password = ListField(db_column='userPassword') # inetOrgPerson first_name = CharField(db_column='givenName') email = ListField(db_column='mail') username = CharField(db_column='uid', primary_key=True) # posixAccount uid = IntegerField(db_column='uidNumber', unique=True) gid = IntegerField(db_column='gidNumber') gecos = CharField(db_column='gecos') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default='/bin/bash') # ldapPublicKey ssh_key = ListField(db_column='sshPublicKey') # gentooGroup ACL = ListField(db_column='gentooACL') birthday = DateField(db_column='birthday') developer_bug = ListField(db_column='gentooDevBug') gentoo_join_date = ListField(db_column='gentooJoin') gentoo_retire_date = ListField(db_column='gentooRetire') gpg_fingerprint = ListField(db_column='gpgfingerprint') gpg_key = ListField(db_column='gpgKey') gravatar = CharField(db_column='gravatar') im = ListField(db_column='gentooIM') latitude = FloatField(db_column='lat') location = CharField(db_column='gentooLocation') longitude = FloatField(db_column='lon') mentor = ListField(db_column='gentooMentor') otp_recovery_keys = ListField(db_column='gentooOTPRecoveryKey') otp_secret = CharField(db_column='gentooOTPSecret') planet_feed = CharField(db_column='gentooPlanetFeed') universe_feed = CharField(db_column='gentooUniverseFeed') website = ListField(db_column='website') # gentooDevGroup roles = CharField(db_column='gentooRoles') alias = ListField(db_column='gentooAlias') spf = ListField(db_column='gentooSPF') # additional ACL fields based on gentooACL is_user = ACLField(db_column='gentooACL') is_developer = ACLField(db_column='gentooACL') is_foundation = ACLField(db_column='gentooACL') is_staff = ACLField(db_column='gentooACL') is_docs = ACLField(db_column='gentooACL') is_council = ACLField(db_column='gentooACL') is_trustee = ACLField(db_column='gentooACL') is_overlays = ACLField(db_column='gentooACL') is_planet = ACLField(db_column='gentooACL') is_wiki = ACLField(db_column='gentooACL') is_forums = ACLField(db_column='gentooACL') is_security = ACLField(db_column='gentooACL') is_recruiter = ACLField(db_column='gentooACL') is_undertaker = ACLField(db_column='gentooACL') is_pr = ACLField(db_column='gentooACL') is_infra = ACLField(db_column='gentooACL') is_retired = ACLField(db_column='gentooACL') def __unicode__(self): return self.username
class LdapUser(ldapdb.models.Model): """ Represents an LDAP posixAccount, inetOrgPerson, shadowAccount entry. Ref: http://www.zytrax.com/books/ldap/apa/types.html """ connection_name = 'ldap' # LDAP meta-data base_dn = settings.LDAP_USER_DN object_classes = ['inetOrgPerson', 'posixAccount', 'shadowAccount'] # inetOrgPerson first_name = CharField(db_column='givenName') last_name = CharField(db_column='sn') full_name = CharField(db_column='cn') email = CharField(db_column='mail') phone = CharField(db_column='telephoneNumber', blank=True) mobile_phone = CharField(db_column='mobile', blank=True) photo = ImageField(db_column='jpegPhoto') # posixAccount id = IntegerField(db_column='uidNumber', unique=True) # referenced in reset password form group = IntegerField(db_column='gidNumber') gecos = CharField(db_column='gecos') display_name = CharField(db_column='displayname') home_directory = CharField(db_column='homeDirectory') login_shell = CharField(db_column='loginShell', default=settings.LDAP_LOGIN_SHELL) username = CharField(db_column='uid', primary_key=True) # shadowAccount password = CharField(db_column='userPassword') shadowLastChange = IntegerField(db_column='shadowLastChange', default=settings.LDAP_SHADOW_LAST_CHANGE) shadowMin = IntegerField(db_column='shadowMin', default=settings.LDAP_SHADOW_MIN) shadowMax = IntegerField(db_column='shadowMax', default=settings.LDAP_SHADOW_MAX) shadowWarning = IntegerField(db_column='shadowWarning', default=settings.LDAP_SHADOW_WARNING) shadowInactive = IntegerField(db_column='shadowInactive') shadowExpire = IntegerField(db_column='shadowExpire', default=settings.LDAP_SHADOW_EXPIRE) shadowFlag = IntegerField(db_column='shadowFlag', default=settings.LDAP_SHADOW_FLAG) # core description = CharField(db_column='description') @staticmethod def _days_since_epoch(): return (datetime.utcnow() - datetime(1970, 1, 1)).days def set_password(self, raw_password, commit=True, prehashed=False): self.password = raw_password if prehashed else ldap_create_password( raw_password) # Update last changed password date self.shadowLastChange = LdapUser._days_since_epoch() if commit: self.save() def check_password(self, raw_password): return ldap_validate_password(raw_password, self.password) def __str__(self): return self.username class Meta: managed = False
class LdapUser(ldapdb.models.Model): """ Class for representing an LDAP user entry. """ # LDAP meta-data base_dn = "ou=people,dc=iapp-intern,dc=de" object_classes = [ 'posixAccount', 'shadowAccount', 'inetOrgPerson', 'deIappPerson', 'sambaSamAccount', ] # inetOrgPerson title = CharField(db_column='title', choices=settings.TITLES, blank=True) givenName = CharField(db_column='givenName', blank=True) sn = CharField(db_column='sn') cn = CharField(db_column='cn') mail = CharField(db_column='mail', blank=True) telephoneNumber = CharField(db_column='telephoneNumber', blank=True) facsimileTelephoneNumber = CharField(db_column='facsimileTelephoneNumber', blank=True) mobile = CharField(db_column='mobile', blank=True) employeeType = CharField(db_column='employeeType', choices=settings.EMPLOYEETYPES, blank=True) team = CharField(db_column='description', choices=settings.TEAMS, blank=True) # use django imatgefield, cause the ldap one is buggy # we use this one in the form and set the jpegPhoto in the view photo = models.ImageField(upload_to=getPhotoPath, blank=True) jpegPhoto = ImageField(db_column='jpegPhoto', blank=True) roomNumber = CharField(db_column='roomNumber', blank=True) # posixAccount uidNumber = IntegerField(db_column='uidNumber', unique=True) gidNumber = IntegerField(db_column='gidNumber', choices=settings.GROUPS) gecos = CharField(db_column='gecos') uid = CharField(db_column='uid', primary_key=True) userPassword = CharField(db_column='userPassword') homeDirectory = CharField(db_column='homeDirectory') loginShell = CharField(db_column='loginShell') # deIappPerson deIappOrder = CharField(db_column='deIappOrder', choices=settings.ORDERINGS) deIappRole = CharField(db_column='deIappRole', blank=True) deIappBirthday = CharField(db_column='deIappBirthday', blank=True) # sambaSamAccount sambaLMPassword = CharField(db_column='sambaLMPassword') sambaNTPassword = CharField(db_column='sambaNTPassword') sambaSID = CharField(db_column='sambaSID') def save(self, *args, **kwargs): """ save the model and set implicit attributes like sambaSID etc """ # userGroups is given as kwarg by the view as list of strings # we get the corresponding ldapgroups and check which are new # and which can be deleted userGroups = kwargs.pop('userGroups', []) newUserGroups = map(lambda g: get_or_none(LdapGroup, cn=g), userGroups) newUserGroups = filter(None, newUserGroups) currentUserGroups = LdapGroup.objects.filter( memberUid__contains=self.uid) deletedGroups = [ g for g in currentUserGroups if g not in newUserGroups ] for group in deletedGroups: group.memberUid.remove(self.uid) group.save() for group in newUserGroups: if self.uid not in group.memberUid: group.memberUid.append(self.uid) group.save() # implicit attributes self.cn = self.givenName + ' ' + self.sn self.sambaSID = settings.SAMBA_SID + '-' + str(self.uidNumber * 2 + 1000) self.homeDirectory = '/home/' + self.uid self.loginShell = settings.DEFAULT_SHELL # build unix timestamp from given date format (dd.mm.yyyy) if self.deIappBirthday: self.deIappBirthday = date2timestamp(self.deIappBirthday) # password is given as kwarg by the view # sha1, lm/nt hashes are build from this password and will be saved password = kwargs.pop('password', False) if password: from passlib.hash import ldap_salted_sha1 as lss from passlib.hash import lmhash from passlib.hash import nthash self.userPassword = lss.encrypt(password) self.sambaLMPassword = lmhash.encrypt(password).upper() self.sambaNTPassword = nthash.encrypt(password).upper() super(LdapUser, self).save(*args, **kwargs) def delete(self, using=None): """ Delete this entry. (move user to former-members ou) """ using = using or router.db_for_write(self.__class__, instance=self) connection = connections[using] cursor = connection._cursor() cursor.connection.rename_s( self.dn.encode(connection.charset), 'uid=' + self.uid.encode(connection.charset), newsuperior='ou=Former-Members,dc=iapp-intern,dc=de') def groups(self): # returns the groups of a ldapuser return LdapGroup.objects.filter(memberUid__contains=self.uid) def __str__(self): return self.uid def __unicode__(self): return self.cn
class User(BaseLdapModel): PRIMARY_GROUPS_DESCRIPTION = 'auto' # description used as description for primary groups of users base_dn = 'ou=Users,' + settings.LDAP_BASE_DN object_classes = force_bytestrings(['posixAccount', 'shadowAccount', 'inetOrgPerson', 'sambaSamAccount', 'person', 'AsteriskSIPUser']) name = CharField(db_column=force_text('uid'), max_length=200, primary_key=True, validators=list(name_validators)) display_name = CharField(db_column=force_text('displayName'), max_length=200) uid_number = IntegerField(db_column=force_text('uidNumber'), default=None, unique=True) gid_number = IntegerField(db_column=force_text('gidNumber'), default=None) login_shell = CharField(db_column=force_text('loginShell'), default='/bin/bash') description = CharField(db_column=force_text('description'), default='Description') jpeg_photo = ImageField(db_column=force_text('jpegPhoto'), max_length=10000000) phone = CharField(db_column=force_text('telephoneNumber'), default=None) samba_acct_flags = CharField(db_column=force_text('sambaAcctFlags'), default='[UX ]') user_smime_certificate = CharField(db_column=force_text('userSMIMECertificate'), default=None) user_certificate = CharField(db_column=force_text('userCertificate'), default=None) # forced values samba_sid = CharField(db_column=force_text('sambaSID'), default=None) primary_group_samba_sid = CharField(db_column=force_text('sambaPrimaryGroupSID'), default=None) home_directory = CharField(db_column=force_text('homeDirectory'), default=None) mail = CharField(db_column=force_text('mail'), default=None) samba_domain_name = CharField(db_column=force_text('sambaDomainName'), default=None) gecos = CharField(db_column=force_text('gecos'), max_length=200, default=None) cn = CharField(db_column=force_text('cn'), max_length=200, default=None, validators=list(name_validators)) sn = CharField(db_column=force_text('sn'), max_length=200, default=None, validators=list(name_validators)) # password values user_password = CharField(db_column=force_text('userPassword'), default=None) # samba_nt_password = CharField(db_column=force_text('sambaNTPassword'), default=None) ast_account_caller_id = CharField(db_column=force_text('AstAccountCallerID'), default=None) ast_account_context = CharField(db_column=force_text('AstAccountContext'), default='LocalSets') ast_account_DTMF_mode = CharField(db_column=force_text('AstAccountDTMFMode'), default='rfc2833') ast_account_mailbox = CharField(db_column=force_text('AstAccountMailbox'), default=None) ast_account_NAT = CharField(db_column=force_text('AstAccountNAT'), default='yes') ast_account_qualify = CharField(db_column=force_text('AstAccountQualify'), default='yes') ast_account_type = CharField(db_column=force_text('AstAccountType'), default='friend') ast_account_disallowed_codec = CharField(db_column=force_text('AstAccountDisallowedCodec'), default='all') ast_account_allowed_codec = CharField(db_column=force_text('AstAccountAllowedCodec'), default='ulaw') ast_account_music_on_hold = CharField(db_column=force_text('AstAccountMusicOnHold'), default='default') def save(self, using=None): group = self.set_gid_number() self.cn = self.name self.sn = self.name self.gecos = self.display_name self.ast_account_caller_id = self.display_name self.samba_domain_name = settings.PENATES_REALM self.mail = '%s@%s' % (self.name, settings.PENATES_DOMAIN) self.ast_account_mailbox = self.mail self.home_directory = '/home/%s' % self.name self.set_next_free_value('uid_number') self.samba_sid = '%s-%s' % (get_samba_sid(), self.uid_number) self.primary_group_samba_sid = '%s-%s' % (get_samba_sid(), self.gid_number) super(User, self).save(using=using) if group and self.name not in group.members: # noinspection PyUnresolvedReferences group.members.append(self.name) group.save() add_principal(self.principal_name) @property def principal_name(self): return '%s@%s' % (self.name, settings.PENATES_REALM) def set_gid_number(self): if self.gid_number is not None: groups = list(Group.objects.filter(gid=self.gid_number)[0:1]) else: groups = list(Group.objects.filter(name=self.name)[0:1]) if not groups: group = Group(name=self.name, gid=self.gid_number, description=self.PRIMARY_GROUPS_DESCRIPTION) group.save() else: group = groups[0] self.gid_number = group.gid return group def set_password(self, password): self.user_password = password_hash(password) self.save() change_password(self.principal_name, password) if settings.STORE_CLEARTEXT_PASSWORDS: ensure_location(self.password_filename) with codecs.open(self.password_filename, 'w', encoding='utf-8') as fd: fd.write(password) os.chmod(self.password_filename, 0o400) @property def password_filename(self): return os.path.join(settings.PKI_PATH, 'private', 'passwords', '%s.txt' % self.name) def read_password(self): if settings.STORE_CLEARTEXT_PASSWORDS: with codecs.open(self.password_filename, 'r', encoding='utf-8') as fd: return fd.read() return '' def delete(self, using=None): super(User, self).delete(using=using) delete_principal(self.principal_name) @property def user_certificate_entry(self): return CertificateEntry(self.name, organizationName=settings.PENATES_ORGANIZATION, organizationalUnitName=_('Users'), emailAddress=self.mail, localityName=settings.PENATES_LOCALITY, countryName=settings.PENATES_COUNTRY, stateOrProvinceName=settings.PENATES_STATE, altNames=[], role=USER) @property def email_certificate_entry(self): return CertificateEntry(self.name, organizationName=settings.PENATES_ORGANIZATION, organizationalUnitName=_('Users'), emailAddress=self.mail, localityName=settings.PENATES_LOCALITY, countryName=settings.PENATES_COUNTRY, stateOrProvinceName=settings.PENATES_STATE, altNames=[], role=EMAIL) @property def signature_certificate_entry(self): return CertificateEntry(self.name, organizationName=settings.PENATES_ORGANIZATION, organizationalUnitName=_('Users'), emailAddress=self.mail, localityName=settings.PENATES_LOCALITY, countryName=settings.PENATES_COUNTRY, stateOrProvinceName=settings.PENATES_STATE, altNames=[], role=SIGNATURE) @property def encipherment_certificate_entry(self): return CertificateEntry(self.name, organizationName=settings.PENATES_ORGANIZATION, organizationalUnitName=_('Users'), emailAddress=self.mail, localityName=settings.PENATES_LOCALITY, countryName=settings.PENATES_COUNTRY, stateOrProvinceName=settings.PENATES_STATE, altNames=[], role=ENCIPHERMENT)
class SambaDomain(BaseLdapModel): base_dn = settings.LDAP_BASE_DN object_classes = force_bytestrings(['sambaDomain']) rid_base = IntegerField(db_column=force_text('sambaAlgorithmicRidBase'), default=2000) sid = CharField(db_column=force_text('sambaSID')) name = CharField(db_column=force_text('sambaDomainName'), primary_key=True)