def profile(self, domain, mail, accountType='user'): self.mail = web.safestr(mail) self.domain = self.mail.split('@', 1)[-1] if self.domain != domain: return web.seeother('/domains?msg=PERMISSION_DENIED') self.filter = '(&(objectClass=mailUser)(mail=%s))' % (self.mail,) if accountType == 'catchall': self.filter = '(&(objectClass=mailUser)(mail=@%s))' % (self.mail,) else: if not self.mail.endswith('@' + self.domain): return web.seeother('/domains?msg=PERMISSION_DENIED') if attrs.RDN_USER == 'mail': self.searchdn = ldaputils.convKeywordToDN(self.mail, accountType=accountType) self.scope = ldap.SCOPE_BASE else: self.searchdn = attrs.DN_BETWEEN_USER_AND_DOMAIN + ldaputils.convKeywordToDN(self.domain, accountType='domain') self.scope = ldap.SCOPE_SUBTREE try: self.user_profile = self.conn.search_s( self.searchdn, self.scope, self.filter, attrs.USER_ATTRS_ALL, ) return (True, self.user_profile) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def profile(self, domain, mail, accountType='user'): self.mail = web.safestr(mail) self.domain = self.mail.split('@', 1)[-1] if self.domain != domain: return web.seeother('/domains?msg=PERMISSION_DENIED') self.filter = '(&(objectClass=mailUser)(mail=%s))' % (self.mail, ) if accountType == 'catchall': self.filter = '(&(objectClass=mailUser)(mail=@%s))' % (self.mail, ) else: if not self.mail.endswith('@' + self.domain): return web.seeother('/domains?msg=PERMISSION_DENIED') if attrs.RDN_USER == 'mail': self.searchdn = ldaputils.convKeywordToDN(self.mail, accountType=accountType) self.scope = ldap.SCOPE_BASE else: self.searchdn = attrs.DN_BETWEEN_USER_AND_DOMAIN + ldaputils.convKeywordToDN( self.domain, accountType='domain') self.scope = ldap.SCOPE_SUBTREE try: self.user_profile = self.conn.search_s( self.searchdn, self.scope, self.filter, attrs.USER_ATTRS_ALL, ) return (True, self.user_profile) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def deleteSingleUserFromGroups(self, mail): self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') # Get domain name of this account. self.domain = self.mail.split('@')[-1] # Get dn of mail user and domain. self.dnUser = ldaputils.convKeywordToDN(self.mail, accountType='user') self.dnDomain = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: # Get accounts which contains destination email. objsHasUser = self.conn.search_s( self.dnDomain, ldap.SCOPE_SUBTREE, self.getFilterOfDeleteUserFromGroups(self.mail), ['dn'], ) if len(objsHasUser) >= 1: connutils = connUtils.Utils() for obj in objsHasUser: if obj[0].endswith(attrs.DN_BETWEEN_ALIAS_AND_DOMAIN + self.dnDomain) or \ obj[0].endswith(attrs.DN_BETWEEN_USER_AND_DOMAIN + self.dnDomain): # Remove address from alias and user. connutils.addOrDelAttrValue( dn=obj[0], attr='mailForwardingAddress', value=self.mail, action='delete', ) elif obj[0].endswith('ou=Externals,' + self.domaindn): # Remove address from external member list. connutils.addOrDelAttrValue( dn=obj[0], attr='mail', value=self.mail, action='delete', ) else: pass else: pass return (True, ) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def deleteSingleUserFromGroups(self, mail): self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') # Get domain name of this account. self.domain = self.mail.split('@')[-1] # Get dn of mail user and domain. self.dnUser = ldaputils.convKeywordToDN(self.mail, accountType='user') self.dnDomain = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: # Get accounts which contains destination email. objsHasUser = self.conn.search_s( self.dnDomain, ldap.SCOPE_SUBTREE, self.getFilterOfDeleteUserFromGroups(self.mail), ['dn'], ) if len(objsHasUser) >= 1: connutils = connUtils.Utils() for obj in objsHasUser: if obj[0].endswith(attrs.DN_BETWEEN_ALIAS_AND_DOMAIN + self.dnDomain) or \ obj[0].endswith(attrs.DN_BETWEEN_USER_AND_DOMAIN + self.dnDomain): # Remove address from alias and user. connutils.addOrDelAttrValue( dn=obj[0], attr='mailForwardingAddress', value=self.mail, action='delete', ) elif obj[0].endswith('ou=Externals,' + self.domaindn): # Remove address from external member list. connutils.addOrDelAttrValue( dn=obj[0], attr='mail', value=self.mail, action='delete', ) else: pass else: pass return (True,) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def deleteSingleUser( self, mail, deleteFromGroups=True, ): self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') # Get domain name of this account. self.domain = self.mail.split('@')[-1] # Get dn of mail user and domain. self.dnUser = ldaputils.convKeywordToDN(self.mail, accountType='user') # Delete user object. try: #deltree.DelTree(self.conn, self.dnUser, ldap.SCOPE_SUBTREE) self.conn.delete_s(self.dnUser) if deleteFromGroups: self.deleteSingleUserFromGroups(self.mail) # Log delete action. web.logger( msg="Delete user: %s." % (self.mail), domain=self.domain, event='delete', ) return (True, ) except ldap.LDAPError, e: return (False, ldaputils.getExceptionDesc(e))
def getDomainDefaultUserQuota(self, domain, domainAccountSetting=None,): # Return 0 as unlimited. self.domain = web.safestr(domain) self.dn = ldaputils.convKeywordToDN(self.domain, accountType='domain') if domainAccountSetting is not None: if 'defaultQuota' in domainAccountSetting.keys(): return int(domainAccountSetting['defaultQuota']) else: return 0 else: try: result = self.conn.search_s( self.dn, ldap.SCOPE_BASE, '(domainName=%s)' % self.domain, ['domainName', 'accountSetting'], ) settings = ldaputils.getAccountSettingFromLdapQueryResult(result, key='domainName',) if 'defaultQuota' in settings[self.domain].keys(): return int(settings[self.domain]['defaultQuota']) else: return 0 except Exception, e: return 0
def listAccounts(self, domain): self.domain = domain self.domainDN = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: # Use '(!([email protected]))' to hide catch-all account. self.users = self.conn.search_s( attrs.DN_BETWEEN_USER_AND_DOMAIN + self.domainDN, ldap.SCOPE_SUBTREE, '(&(objectClass=mailUser)(!(mail=@%s)))' % self.domain, attrs.USER_SEARCH_ATTRS, ) connutils = connUtils.Utils() connutils.updateAttrSingleValue(self.domainDN, 'domainCurrentUserNumber', len(self.users)) return (True, self.users) except ldap.NO_SUCH_OBJECT: #self.conn.add_s( # attrs.DN_BETWEEN_USER_AND_DOMAIN + self.domainDN, # iredldif.ldif_group(attrs.GROUP_USERS), # ) return (False, 'NO_SUCH_OBJECT') except ldap.SIZELIMIT_EXCEEDED: return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def enableOrDisableAccount( self, mails, action, attr='accountStatus', ): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') result = {} connutils = connUtils.Utils() for mail in mails: self.mail = web.safestr(mail).strip().lower() if not iredutils.isEmail(self.mail): continue self.domain = self.mail.split('@')[-1] self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: connutils.enableOrDisableAccount( domain=self.domain, account=self.mail, dn=self.dn, action=web.safestr(action).strip().lower(), accountTypeInLogger='admin', ) except ldap.LDAPError, e: result[self.mail] = str(e)
def delete(self, domain, mails=[]): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') self.domain = web.safestr(domain) self.mails = [str(v) for v in mails if iredutils.isEmail(v) and str(v).endswith('@'+self.domain)] self.domaindn = ldaputils.convKeywordToDN(self.domain, accountType='domain') if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') result = {} for mail in self.mails: self.mail = web.safestr(mail) try: # Delete user object (ldap.SCOPE_BASE). self.deleteSingleUser(self.mail,) # Delete user object and whole sub-tree. # Get dn of mail user and domain. """ self.userdn = ldaputils.convKeywordToDN(self.mail, accountType='user') deltree.DelTree(self.conn, self.userdn, ldap.SCOPE_SUBTREE) # Log delete action. web.logger( msg="Delete user: %s." % (self.mail), domain=self.mail.split('@')[1], event='delete', ) """ except ldap.LDAPError, e: result[self.mail] = ldaputils.getExceptionDesc(e)
def deleteSingleUser(self, mail, deleteFromGroups=True,): self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') # Get domain name of this account. self.domain = self.mail.split('@')[-1] # Get dn of mail user and domain. self.dnUser = ldaputils.convKeywordToDN(self.mail, accountType='user') # Delete user object. try: #deltree.DelTree(self.conn, self.dnUser, ldap.SCOPE_SUBTREE) self.conn.delete_s(self.dnUser) if deleteFromGroups: self.deleteSingleUserFromGroups(self.mail) # Log delete action. web.logger( msg="Delete user: %s." % (self.mail), domain=self.domain, event='delete', ) return (True,) except ldap.LDAPError, e: return (False, ldaputils.getExceptionDesc(e))
def add(self, data): # msg: {key: value} msg = {} self.domain = web.safestr(data.get('domainName', '')).strip().lower() # Check domain name. if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') # Check whether domain name already exist (domainName, domainAliasName). connutils = connUtils.Utils() if connutils.isDomainExists(self.domain): return (False, 'ALREADY_EXISTS') self.dn = ldaputils.convKeywordToDN(self.domain, accountType='domain') self.cn = data.get('cn', None) ldif = iredldif.ldif_maildomain(domain=self.domain, cn=self.cn,) # Add domain dn. try: result = self.conn.add_s(self.dn, ldif) web.logger(msg="Create domain: %s." % (self.domain), domain=self.domain, event='create',) except ldap.ALREADY_EXISTS: msg[self.domain] = 'ALREADY_EXISTS' except ldap.LDAPError, e: msg[self.domain] = str(e)
def enableOrDisableAccount(self, domain, mails, action, attr='accountStatus',): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') self.mails = [str(v) for v in mails if iredutils.isEmail(v) and str(v).endswith('@'+str(domain)) ] result = {} connutils = connUtils.Utils() for mail in self.mails: self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): continue self.domain = self.mail.split('@')[-1] self.dn = ldaputils.convKeywordToDN(self.mail, accountType='user') try: connutils.enableOrDisableAccount( domain=self.domain, account=self.mail, dn=self.dn, action=web.safestr(action).strip().lower(), accountTypeInLogger='user', ) except ldap.LDAPError, e: result[self.mail] = str(e)
def getNumberOfCurrentAccountsUnderDomain(self, domain, accountType='user', filter=None): # accountType in ['user', 'list', 'alias',] self.domain = web.safestr(domain) self.domaindn = ldaputils.convKeywordToDN(self.domain, accountType='domain') if filter is not None: self.searchdn = self.domaindn self.filter = filter else: if accountType == 'user': self.searchdn = attrs.DN_BETWEEN_USER_AND_DOMAIN + self.domaindn self.filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % self.domain elif accountType == 'maillist': self.searchdn = attrs.DN_BETWEEN_MAILLIST_AND_DOMAIN + self.domaindn self.filter = '(objectClass=mailList)' else: self.searchdn = self.domaindn self.filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % self.domain try: result = self.conn.search_s( self.searchdn, ldap.SCOPE_SUBTREE, self.filter, ['dn',], ) return (True, len(result)) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def getSizelimitFromAccountLists(self, accountList, sizelimit=50, curPage=1, domain=None, accountType=None,): # Return a dict which contains: # - totalAccounts: number of total accounts # - accountList: list of accounts used to display in current page # - totalPages: number of total pages show be showed in account list page. # - totalQuota: number of domain quota size. Only available when accountType=='user'. # Initial a dict to set default values. result = { 'totalAccounts': 0, # Integer 'accountList': [], # List 'totalPages': 0, # Integer 'totalQuota': 0, # Integer 'currentQuota': {}, # Dict } # Get total accounts. totalAccounts = len(accountList) result['totalAccounts'] = totalAccounts # Get number of actual pages. if totalAccounts % sizelimit == 0: totalPages = totalAccounts / sizelimit else: totalPages = (totalAccounts / sizelimit) + 1 result['totalPages'] = totalPages if curPage >= totalPages: curPage = totalPages # Sort accounts in place. if isinstance(accountList, types.ListType): accountList.sort() else: pass # Get total domain mailbox quota. if accountType == 'user': counter = 0 for i in accountList: quota = i[1].get('mailQuota', ['0'])[0] if quota.isdigit(): result['totalQuota'] += int(quota) counter += 1 # Update number of current domain quota size in LDAP (@attrs.ATTR_DOMAIN_CURRENT_QUOTA_SIZE). if domain is not None: # Update number of current domain quota size in LDAP. try: dnDomain = ldaputils.convKeywordToDN(domain, accountType='domain') self.updateAttrSingleValue( dn=dnDomain, attr=attrs.ATTR_DOMAIN_CURRENT_QUOTA_SIZE, value=str(result['totalQuota']), ) except Exception, e: pass
def POST(self): # Get username, password. i = web.input(_unicode=False) username = web.safestr(i.get('username', '').strip()) password = i.get('password', '').strip() save_pass = web.safestr(i.get('save_pass', 'no').strip()) if not iredutils.isEmail(username): return web.seeother('/login?msg=INVALID_USERNAME') if len(password) == 0: return web.seeother('/login?msg=EMPTY_PASSWORD') # Convert username to ldap dn. userdn = ldaputils.convKeywordToDN(username, accountType='admin') # Return True if auth success, otherwise return error msg. self.auth_result = auth.Auth(cfg.ldap.get('uri', 'ldap://127.0.0.1/'), userdn, password,) if self.auth_result is True: session['username'] = username session['logged'] = True # Read preferred language from db. adminLib = adminlib.Admin() #session['lang'] = adminLib.getPreferredLanguage(userdn) or cfg.general.get('lang', 'en_US') adminProfile = adminLib.profile(username) if adminProfile[0] is True: cn = adminProfile[1][0][1].get('cn', [None])[0] lang = adminProfile[1][0][1].get('preferredLanguage', [cfg.general.get('lang', 'en_US')])[0] session['cn'] = cn session['lang'] = lang else: pass web.config.session_parameters['cookie_name'] = 'iRedAdmin' # Session expire when client ip was changed. web.config.session_parameters['ignore_change_ip'] = False # Don't ignore session expiration. web.config.session_parameters['ignore_expiry'] = False if save_pass == 'yes': # Session timeout (in seconds). web.config.session_parameters['timeout'] = 86400 # 24 hours else: # Expire session when browser closed. web.config.session_parameters['timeout'] = 600 # 10 minutes web.logger(msg="Login success", event='login',) return web.seeother('/dashboard/checknew') else: session['failedTimes'] += 1 web.logger(msg="Login failed.", admin=username, event='login', loglevel='error',) return web.seeother('/login?msg=%s' % self.auth_result)
def getDomainAdmins(self, domain): domain = web.safestr(domain) dn = ldaputils.convKeywordToDN(domain, accountType='domain') try: self.domainAdmins = self.conn.search_s( dn, ldap.SCOPE_BASE, '(&(objectClass=mailDomain)(domainName=%s))' % domain, ['domainAdmin'], ) return self.domainAdmins except Exception, e: return str(e)
def update(self, profile_type, domain, data): self.profile_type = web.safestr(profile_type) self.domain = web.safestr(domain) self.domaindn = ldaputils.convKeywordToDN(self.domain, accountType='domain') connutils = connUtils.Utils() self.accountSetting = [] mod_attrs = [] # Allow normal admin to update profiles. if self.profile_type == 'general': cn = data.get('cn', None) mod_attrs += ldaputils.getSingleModAttr(attr='cn', value=cn, default=self.domain) else: pass # Allow global admin to update profiles. if session.get('domainGlobalAdmin') is True: if self.profile_type == 'general': # Get accountStatus. if 'accountStatus' in data.keys(): accountStatus = 'active' else: accountStatus = 'disabled' mod_attrs += [ (ldap.MOD_REPLACE, 'accountStatus', accountStatus) ] else: pass else: pass try: dn = ldaputils.convKeywordToDN(self.domain, accountType='domain') self.conn.modify_s(dn, mod_attrs) return (True,) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def add(self, data): self.cn = data.get('cn') self.mail = web.safestr(data.get('mail')).strip().lower() if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') self.domainGlobalAdmin = web.safestr( data.get('domainGlobalAdmin', 'no')) if self.domainGlobalAdmin not in [ 'yes', 'no', ]: self.domainGlobalAdmin = 'no' self.preferredLanguage = web.safestr( data.get('preferredLanguage', 'en_US')) # Check password. self.newpw = web.safestr(data.get('newpw')) self.confirmpw = web.safestr(data.get('confirmpw')) result = iredutils.verifyNewPasswords(self.newpw, self.confirmpw) if result[0] is True: self.passwd = ldaputils.generatePasswd(result[1]) else: return result ldif = iredldif.ldif_mailadmin( mail=self.mail, passwd=self.passwd, cn=self.cn, preferredLanguage=self.preferredLanguage, domainGlobalAdmin=self.domainGlobalAdmin, ) self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: self.conn.add_s(self.dn, ldif) web.logger( msg="Create admin: %s." % (self.mail), event='create', ) return (True, ) except ldap.ALREADY_EXISTS: return (False, 'ALREADY_EXISTS') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def profile(self, mail): self.mail = web.safestr(mail) self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: self.admin_profile = self.conn.search_s( self.dn, ldap.SCOPE_BASE, '(&(objectClass=mailAdmin)(mail=%s))' % self.mail, attrs.ADMIN_ATTRS_ALL, ) return (True, self.admin_profile) except ldap.NO_SUCH_OBJECT: return (False, 'NO_SUCH_OBJECT') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def getDnWithKeyword(self, value, accountType='user'): self.keyword = web.safestr(value) if accountType == 'user': if attrs.RDN_USER == 'mail': if not iredutils.isEmail(self.keyword): return False return ldaputils.convKeywordToDN(self.keyword, accountType='user') else: self.domain = self.keyword.split('@', 1)[-1] self.dnOfDomain = ldaputils.convKeywordToDN(self.domain, accountType='domain',) try: result = self.conn.search_s( attrs.DN_BETWEEN_USER_AND_DOMAIN + self.dnOfDomain, ldap.SCOPE_SUBTREE, '(&(objectClass=mailUser)(mail=%s))' % (self.keyword), ) if len(result) == 1: self.dn = result[0][0] return self.dn else: return False except Exception, e: return False
def isDomainAdmin(self, domain, admin=session.get('username'),): dn = ldaputils.convKeywordToDN(domain, accountType='domain') try: result = self.conn.search_s( dn, ldap.SCOPE_BASE, "(&(%s=%s)(domainAdmin=%s))" % (attrs.RDN_DOMAIN, domain, admin), ['dn', 'domainAdmin'], ) if len(result) >= 1: return True else: return False except Exception, e: return False
def delete(self, mails): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') result = {} for mail in mails: self.mail = web.safestr(mail) dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: deltree.DelTree( self.conn, dn, ldap.SCOPE_SUBTREE ) web.logger(msg="Delete admin: %s." % (self.mail,), event='delete',) except ldap.LDAPError, e: result[self.mail] = str(e)
def delete(self, domains=[]): if not isinstance(domains, types.ListType): return (False, 'INVALID_DOMAIN_NAME') msg = {} for domain in domains: if not iredutils.isDomain(domain): continue dn = ldaputils.convKeywordToDN(web.safestr(domain), accountType='domain') try: deltree.DelTree(self.conn, dn, ldap.SCOPE_SUBTREE) web.logger(msg="Delete domain: %s." % (domain), domain=domain, event='delete',) except ldap.LDAPError, e: msg[domain] = str(e)
def delete(self, mails): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') result = {} for mail in mails: self.mail = web.safestr(mail) dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: deltree.DelTree(self.conn, dn, ldap.SCOPE_SUBTREE) web.logger( msg="Delete admin: %s." % (self.mail, ), event='delete', ) except ldap.LDAPError, e: result[self.mail] = str(e)
def profile(self, domain): self.domain = web.safestr(domain) self.dn = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: self.domain_profile = self.conn.search_s( self.dn, ldap.SCOPE_BASE, '(&(objectClass=mailDomain)(domainName=%s))' % self.domain, attrs.DOMAIN_ATTRS_ALL, ) if len(self.domain_profile) == 1: return (True, self.domain_profile) else: return (False, 'NO_SUCH_DOMAIN') except ldap.NO_SUCH_OBJECT: return (False, 'NO_SUCH_OBJECT') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def isDomainAdmin( self, domain, admin=session.get('username'), ): dn = ldaputils.convKeywordToDN(domain, accountType='domain') try: result = self.conn.search_s( dn, ldap.SCOPE_BASE, "(&(%s=%s)(domainAdmin=%s))" % (attrs.RDN_DOMAIN, domain, admin), ['dn', 'domainAdmin'], ) if len(result) >= 1: return True else: return False except Exception, e: return False
def enableOrDisableAccount(self, domains, action, attr='accountStatus',): if domains is None or len(domains) == 0: return (False, 'NO_DOMAIN_SELECTED') result = {} connutils = connUtils.Utils() for domain in domains: self.domain = web.safestr(domain) self.dn = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: connutils.enableOrDisableAccount( domain=self.domain, account=self.domain, dn=self.dn, action=web.safestr(action).strip().lower(), accountTypeInLogger='domain', ) except ldap.LDAPError, e: result[self.domain] = str(e)
def add(self, data): self.cn = data.get('cn') self.mail = web.safestr(data.get('mail')).strip().lower() if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') self.domainGlobalAdmin = web.safestr(data.get('domainGlobalAdmin', 'no')) if self.domainGlobalAdmin not in ['yes', 'no',]: self.domainGlobalAdmin = 'no' self.preferredLanguage = web.safestr(data.get('preferredLanguage', 'en_US')) # Check password. self.newpw = web.safestr(data.get('newpw')) self.confirmpw = web.safestr(data.get('confirmpw')) result = iredutils.verifyNewPasswords(self.newpw, self.confirmpw) if result[0] is True: self.passwd = ldaputils.generatePasswd(result[1]) else: return result ldif = iredldif.ldif_mailadmin( mail=self.mail, passwd=self.passwd, cn=self.cn, preferredLanguage=self.preferredLanguage, domainGlobalAdmin=self.domainGlobalAdmin, ) self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') try: self.conn.add_s(self.dn, ldif) web.logger(msg="Create admin: %s." % (self.mail), event='create',) return (True,) except ldap.ALREADY_EXISTS: return (False, 'ALREADY_EXISTS') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def getAvailableDomainNames(self, domain): '''Get list of domainName and domainAliasName by quering domainName. >>> getAvailableDomainNames(domain='example.com') (True, ['example.com', 'aliasdomain01.com', 'aliasdomain02.com', ...]) ''' self.domain = web.safestr(domain).strip().lower() if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') self.dnOfDomain = ldaputils.convKeywordToDN(self.domain, accountType='domain') try: result = self.conn.search_s( self.dnOfDomain, ldap.SCOPE_BASE, '(&(objectClass=mailDomain)(domainName=%s))' % self.domain, ['domainName', 'domainAliasName'], ) return (True, result[0][1].get('domainName', []) + result[0][1].get('domainAliasName', [])) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def delete(self, domain, mails=[]): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') self.domain = web.safestr(domain) self.mails = [ str(v) for v in mails if iredutils.isEmail(v) and str(v).endswith('@' + self.domain) ] self.domaindn = ldaputils.convKeywordToDN(self.domain, accountType='domain') if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') result = {} for mail in self.mails: self.mail = web.safestr(mail) try: # Delete user object (ldap.SCOPE_BASE). self.deleteSingleUser(self.mail, ) # Delete user object and whole sub-tree. # Get dn of mail user and domain. """ self.userdn = ldaputils.convKeywordToDN(self.mail, accountType='user') deltree.DelTree(self.conn, self.userdn, ldap.SCOPE_SUBTREE) # Log delete action. web.logger( msg="Delete user: %s." % (self.mail), domain=self.mail.split('@')[1], event='delete', ) """ except ldap.LDAPError, e: result[self.mail] = ldaputils.getExceptionDesc(e)
def getDomainCurrentQuotaSizeFromLDAP(self, domain): self.domain = web.safestr(domain).strip().lower() if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') self.domainDN = ldaputils.convKeywordToDN(self.domain, accountType='domain') # Initial @domainCurrentQuotaSize self.domainCurrentQuotaSize = 0 try: # Use '(!([email protected]))' to hide catch-all account. self.users = self.conn.search_s( attrs.DN_BETWEEN_USER_AND_DOMAIN + self.domainDN, ldap.SCOPE_SUBTREE, '(&(objectClass=mailUser)(!(mail=@%s)))' % self.domain, attrs.USER_SEARCH_ATTRS, ) # Update @domainCurrentUserNumber self.updateAttrSingleValue(self.domainDN, 'domainCurrentUserNumber', len(self.users)) for i in self.users: quota = i[1].get('mailQuota', ['0'])[0] if quota.isdigit(): self.domainCurrentQuotaSize += int(quota) return (True, self.domainCurrentQuotaSize) except ldap.NO_SUCH_OBJECT: #self.conn.add_s( # attrs.DN_BETWEEN_USER_AND_DOMAIN + self.domainDN, # iredldif.ldif_group(attrs.GROUP_USERS), # ) return (False, 'NO_SUCH_OBJECT') except ldap.SIZELIMIT_EXCEEDED: return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def update(self, profile_type, mail, data): self.profile_type = web.safestr(profile_type) self.mail = web.safestr(mail) if session.get('domainGlobalAdmin' ) is not True and session.get('username') != self.mail: # Don't allow to view/update other admins' profile. return (False, 'PERMISSION_DENIED') self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') mod_attrs = [] if self.profile_type == 'general': # Get preferredLanguage. self.lang = web.safestr(data.get('preferredLanguage', 'en_US')) mod_attrs += [(ldap.MOD_REPLACE, 'preferredLanguage', self.lang)] # Get cn. cn = data.get('cn', None) mod_attrs += ldaputils.getSingleModAttr( attr='cn', value=cn, default=self.mail.split('@')[0], ) # Get accountStatus. if 'accountStatus' in data.keys(): accountStatus = 'active' else: accountStatus = 'disabled' mod_attrs += [(ldap.MOD_REPLACE, 'accountStatus', accountStatus)] try: # Modify profiles. self.conn.modify_s(self.dn, mod_attrs) if session.get('username') == self.mail: session['lang'] = self.lang except ldap.LDAPError, e: return (False, ldaputils.getExceptionDesc(e)) ######################### # Managed domains # if session.get('domainGlobalAdmin') is not True: return (False, 'PERMISSION_DENIED') # Get domains under control. result = self.getManagedDomains(mail=self.mail, attrs=[ 'domainName', ]) if result[0] is True: self.managedDomains = [] for d in result[1]: if 'domainName' in d[1].keys(): self.managedDomains += d[1].get('domainName') else: return result # Get domains from web form. self.newmd = [ web.safestr(v) for v in data.get('domainName', []) if iredutils.isDomain(v) ] # Compare two lists, get domain list which need to remove or add domain admins. self.domainsRemoveAdmins = [ str(v) for v in self.managedDomains if v not in self.newmd and iredutils.isDomain(v) ] self.domainsAddAdmins = [ str(v) for v in self.newmd if v not in self.managedDomains and iredutils.isDomain(v) ] connutils = connUtils.Utils() for i in self.domainsRemoveAdmins: result = connutils.addOrDelAttrValue( dn=ldaputils.convKeywordToDN(i, accountType='domain'), attr='domainAdmin', value=self.mail, action='delete', ) if result[0] is False: return result for i in self.domainsAddAdmins: result = connutils.addOrDelAttrValue( dn=ldaputils.convKeywordToDN(i, accountType='domain'), attr='domainAdmin', value=self.mail, action='add', ) if result[0] is False: return result return (True, )
def add(self, domain, data): # Get domain name, username, cn. self.domain = web.safestr(data.get('domainName')).strip().lower() self.username = web.safestr(data.get('username')).strip().lower() self.mail = self.username + '@' + self.domain self.groups = data.get('groups', []) if not iredutils.isDomain(self.domain) or not iredutils.isEmail(self.mail): return (False, 'MISSING_DOMAIN_OR_USERNAME') # Check account existing. connutils = connUtils.Utils() if connutils.isAccountExists(domain=self.domain, filter='(mail=%s)' % self.mail): return (False, 'ALREADY_EXISTS') # Get @domainAccountSetting. domainLib = domainlib.Domain() result_domain_profile = domainLib.profile(self.domain) # Initial parameters. domainAccountSetting = {} self.aliasDomains = [] if result_domain_profile[0] is True: domainProfile = result_domain_profile[1] domainAccountSetting = ldaputils.getAccountSettingFromLdapQueryResult(domainProfile, key='domainName').get(self.domain, {}) self.aliasDomains = domainProfile[0][1].get('domainAliasName', []) # Check password. self.newpw = web.safestr(data.get('newpw')) self.confirmpw = web.safestr(data.get('confirmpw')) result = iredutils.verifyNewPasswords(self.newpw, self.confirmpw, min_passwd_length=domainAccountSetting.get('minPasswordLength', '0'), max_passwd_length=domainAccountSetting.get('maxPasswordLength', '0'), ) if result[0] is True: self.passwd = ldaputils.generatePasswd(result[1]) else: return result # Get display name. self.cn = data.get('cn') # Get user quota. Unit is MB. # 0 or empty is not allowed if domain quota is set, set to # @defaultUserQuota or @domainSpareQuotaSize # Initial final mailbox quota. self.quota = 0 # Get mail quota from web form. defaultUserQuota = domainLib.getDomainDefaultUserQuota(self.domain, domainAccountSetting) self.mailQuota = str(data.get('mailQuota')).strip() if self.mailQuota.isdigit(): self.mailQuota = int(self.mailQuota) else: self.mailQuota = defaultUserQuota # 0 means unlimited. domainQuotaSize, domainQuotaUnit = domainAccountSetting.get('domainQuota', '0:GB').split(':') if int(domainQuotaSize) == 0: # Unlimited. self.quota = self.mailQuota else: # Get domain quota, convert to MB. if domainQuotaUnit == 'TB': domainQuota = int(domainQuotaSize) * 1024 * 1024 # TB elif domainQuotaUnit == 'GB': domainQuota = int(domainQuotaSize) * 1024 # GB else: domainQuota = int(domainQuotaSize) # MB # TODO Query whole domain and calculate current quota size, not read from domain profile. #domainCurrentQuotaSize = int(domainProfile[0][1].get('domainCurrentQuotaSize', ['0'])[0]) / (1024*1024) result = connutils.getDomainCurrentQuotaSizeFromLDAP(domain=self.domain) if result[0] is True: domainCurrentQuotaSize = result[1] else: domainCurrentQuotaSize = 0 # Spare quota. domainSpareQuotaSize = domainQuota - domainCurrentQuotaSize/(1024*1024) if domainSpareQuotaSize <= 0: return (False, 'EXCEEDED_DOMAIN_QUOTA_SIZE') # Get FINAL mailbox quota. if self.mailQuota == 0: self.quota = domainSpareQuotaSize else: if domainSpareQuotaSize > self.mailQuota: self.quota = self.mailQuota else: self.quota = domainSpareQuotaSize # Get default groups. self.groups = [ web.safestr(v) for v in domainAccountSetting.get('defaultList', '').split(',') if iredutils.isEmail(v) ] self.defaultStorageBaseDirectory = domainAccountSetting.get('defaultStorageBaseDirectory', None) # Get default mail list which set in domain accountSetting. ldif = iredldif.ldif_mailuser( domain=self.domain, aliasDomains=self.aliasDomains, username=self.username, cn=self.cn, passwd=self.passwd, quota=self.quota, groups=self.groups, storageBaseDirectory=self.defaultStorageBaseDirectory, ) if attrs.RDN_USER == 'mail': self.dn = ldaputils.convKeywordToDN(self.mail, accountType='user') elif attrs.RDN_USER == 'cn': self.dn = 'cn=' + self.cn + ',' + attrs.DN_BETWEEN_USER_AND_DOMAIN + \ ldaputils.convKeywordToDN(self.domain, accountType='domain') elif attrs.RDN_USER == 'uid': self.dn = 'uid=' + self.username + ',' + attrs.DN_BETWEEN_USER_AND_DOMAIN + \ ldaputils.convKeywordToDN(self.domain, accountType='domain') else: return (False, 'UNSUPPORTED_USER_RDN') try: self.conn.add_s(ldap.filter.escape_filter_chars(self.dn), ldif,) web.logger(msg="Create user: %s." % (self.mail), domain=self.domain, event='create',) return (True,) except ldap.ALREADY_EXISTS: return (False, 'ALREADY_EXISTS') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def update(self, profile_type, mail, data): self.profile_type = web.safestr(profile_type) self.mail = web.safestr(mail) if session.get('domainGlobalAdmin') is not True and session.get('username') != self.mail: # Don't allow to view/update other admins' profile. return (False, 'PERMISSION_DENIED') self.dn = ldaputils.convKeywordToDN(self.mail, accountType='admin') mod_attrs = [] if self.profile_type == 'general': # Get preferredLanguage. self.lang = web.safestr(data.get('preferredLanguage', 'en_US')) mod_attrs += [(ldap.MOD_REPLACE, 'preferredLanguage', self.lang)] # Get cn. cn = data.get('cn', None) mod_attrs += ldaputils.getSingleModAttr(attr='cn', value=cn, default=self.mail.split('@')[0],) # Get accountStatus. if 'accountStatus' in data.keys(): accountStatus = 'active' else: accountStatus = 'disabled' mod_attrs += [ (ldap.MOD_REPLACE, 'accountStatus', accountStatus) ] try: # Modify profiles. self.conn.modify_s(self.dn, mod_attrs) if session.get('username') == self.mail: session['lang'] = self.lang except ldap.LDAPError, e: return (False, ldaputils.getExceptionDesc(e)) ######################### # Managed domains # if session.get('domainGlobalAdmin') is not True: return (False, 'PERMISSION_DENIED') # Get domains under control. result = self.getManagedDomains(mail=self.mail, attrs=['domainName',]) if result[0] is True: self.managedDomains = [] for d in result[1]: if 'domainName' in d[1].keys(): self.managedDomains += d[1].get('domainName') else: return result # Get domains from web form. self.newmd = [web.safestr(v) for v in data.get('domainName', []) if iredutils.isDomain(v)] # Compare two lists, get domain list which need to remove or add domain admins. self.domainsRemoveAdmins = [str(v) for v in self.managedDomains if v not in self.newmd and iredutils.isDomain(v) ] self.domainsAddAdmins = [str(v) for v in self.newmd if v not in self.managedDomains and iredutils.isDomain(v) ] connutils = connUtils.Utils() for i in self.domainsRemoveAdmins: result = connutils.addOrDelAttrValue( dn=ldaputils.convKeywordToDN(i, accountType='domain'), attr='domainAdmin', value=self.mail, action='delete', ) if result[0] is False: return result for i in self.domainsAddAdmins: result = connutils.addOrDelAttrValue( dn=ldaputils.convKeywordToDN(i, accountType='domain'), attr='domainAdmin', value=self.mail, action='add', ) if result[0] is False: return result return (True,)
def add(self, domain, data): # Get domain name, username, cn. self.domain = web.safestr(data.get('domainName')).strip().lower() self.username = web.safestr(data.get('username')).strip().lower() self.mail = self.username + '@' + self.domain self.groups = data.get('groups', []) if not iredutils.isDomain(self.domain) or not iredutils.isEmail( self.mail): return (False, 'MISSING_DOMAIN_OR_USERNAME') # Check account existing. connutils = connUtils.Utils() if connutils.isAccountExists(domain=self.domain, filter='(mail=%s)' % self.mail): return (False, 'ALREADY_EXISTS') # Get @domainAccountSetting. domainLib = domainlib.Domain() result_domain_profile = domainLib.profile(self.domain) # Initial parameters. domainAccountSetting = {} self.aliasDomains = [] if result_domain_profile[0] is True: domainProfile = result_domain_profile[1] domainAccountSetting = ldaputils.getAccountSettingFromLdapQueryResult( domainProfile, key='domainName').get(self.domain, {}) self.aliasDomains = domainProfile[0][1].get('domainAliasName', []) # Check password. self.newpw = web.safestr(data.get('newpw')) self.confirmpw = web.safestr(data.get('confirmpw')) result = iredutils.verifyNewPasswords( self.newpw, self.confirmpw, min_passwd_length=domainAccountSetting.get('minPasswordLength', '0'), max_passwd_length=domainAccountSetting.get('maxPasswordLength', '0'), ) if result[0] is True: self.passwd = ldaputils.generatePasswd(result[1]) else: return result # Get display name. self.cn = data.get('cn') # Get user quota. Unit is MB. # 0 or empty is not allowed if domain quota is set, set to # @defaultUserQuota or @domainSpareQuotaSize # Initial final mailbox quota. self.quota = 0 # Get mail quota from web form. defaultUserQuota = domainLib.getDomainDefaultUserQuota( self.domain, domainAccountSetting) self.mailQuota = str(data.get('mailQuota')).strip() if self.mailQuota.isdigit(): self.mailQuota = int(self.mailQuota) else: self.mailQuota = defaultUserQuota # 0 means unlimited. domainQuotaSize, domainQuotaUnit = domainAccountSetting.get( 'domainQuota', '0:GB').split(':') if int(domainQuotaSize) == 0: # Unlimited. self.quota = self.mailQuota else: # Get domain quota, convert to MB. if domainQuotaUnit == 'TB': domainQuota = int(domainQuotaSize) * 1024 * 1024 # TB elif domainQuotaUnit == 'GB': domainQuota = int(domainQuotaSize) * 1024 # GB else: domainQuota = int(domainQuotaSize) # MB # TODO Query whole domain and calculate current quota size, not read from domain profile. #domainCurrentQuotaSize = int(domainProfile[0][1].get('domainCurrentQuotaSize', ['0'])[0]) / (1024*1024) result = connutils.getDomainCurrentQuotaSizeFromLDAP( domain=self.domain) if result[0] is True: domainCurrentQuotaSize = result[1] else: domainCurrentQuotaSize = 0 # Spare quota. domainSpareQuotaSize = domainQuota - domainCurrentQuotaSize / ( 1024 * 1024) if domainSpareQuotaSize <= 0: return (False, 'EXCEEDED_DOMAIN_QUOTA_SIZE') # Get FINAL mailbox quota. if self.mailQuota == 0: self.quota = domainSpareQuotaSize else: if domainSpareQuotaSize > self.mailQuota: self.quota = self.mailQuota else: self.quota = domainSpareQuotaSize # Get default groups. self.groups = [ web.safestr(v) for v in domainAccountSetting.get('defaultList', '').split(',') if iredutils.isEmail(v) ] self.defaultStorageBaseDirectory = domainAccountSetting.get( 'defaultStorageBaseDirectory', None) # Get default mail list which set in domain accountSetting. ldif = iredldif.ldif_mailuser( domain=self.domain, aliasDomains=self.aliasDomains, username=self.username, cn=self.cn, passwd=self.passwd, quota=self.quota, groups=self.groups, storageBaseDirectory=self.defaultStorageBaseDirectory, ) if attrs.RDN_USER == 'mail': self.dn = ldaputils.convKeywordToDN(self.mail, accountType='user') elif attrs.RDN_USER == 'cn': self.dn = 'cn=' + self.cn + ',' + attrs.DN_BETWEEN_USER_AND_DOMAIN + \ ldaputils.convKeywordToDN(self.domain, accountType='domain') elif attrs.RDN_USER == 'uid': self.dn = 'uid=' + self.username + ',' + attrs.DN_BETWEEN_USER_AND_DOMAIN + \ ldaputils.convKeywordToDN(self.domain, accountType='domain') else: return (False, 'UNSUPPORTED_USER_RDN') try: self.conn.add_s( ldap.filter.escape_filter_chars(self.dn), ldif, ) web.logger( msg="Create user: %s." % (self.mail), domain=self.domain, event='create', ) return (True, ) except ldap.ALREADY_EXISTS: return (False, 'ALREADY_EXISTS') except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def POST(self): # Get username, password. i = web.input(_unicode=False) username = web.safestr(i.get('username', '').strip()) password = i.get('password', '').strip() save_pass = web.safestr(i.get('save_pass', 'no').strip()) if not iredutils.isEmail(username): return web.seeother('/login?msg=INVALID_USERNAME') if len(password) == 0: return web.seeother('/login?msg=EMPTY_PASSWORD') # Convert username to ldap dn. userdn = ldaputils.convKeywordToDN(username, accountType='admin') # Return True if auth success, otherwise return error msg. self.auth_result = auth.Auth( cfg.ldap.get('uri', 'ldap://127.0.0.1/'), userdn, password, ) if self.auth_result is True: session['username'] = username session['logged'] = True # Read preferred language from db. adminLib = adminlib.Admin() #session['lang'] = adminLib.getPreferredLanguage(userdn) or cfg.general.get('lang', 'en_US') adminProfile = adminLib.profile(username) if adminProfile[0] is True: cn = adminProfile[1][0][1].get('cn', [None])[0] lang = adminProfile[1][0][1].get( 'preferredLanguage', [cfg.general.get('lang', 'en_US')])[0] session['cn'] = cn session['lang'] = lang else: pass web.config.session_parameters['cookie_name'] = 'iRedAdmin' # Session expire when client ip was changed. web.config.session_parameters['ignore_change_ip'] = False # Don't ignore session expiration. web.config.session_parameters['ignore_expiry'] = False if save_pass == 'yes': # Session timeout (in seconds). web.config.session_parameters['timeout'] = 86400 # 24 hours else: # Expire session when browser closed. web.config.session_parameters['timeout'] = 600 # 10 minutes web.logger( msg="Login success", event='login', ) return web.seeother('/dashboard/checknew') else: session['failedTimes'] += 1 web.logger( msg="Login failed.", admin=username, event='login', loglevel='error', ) return web.seeother('/login?msg=%s' % self.auth_result)