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 proxyfunc(self, *args, **kw): if 'mail' in kw.keys() and iredutils.isEmail(kw.get('mail')): self.domain = web.safestr(kw['mail']).split('@')[-1] elif 'domain' in kw.keys() and iredutils.isDomain(kw.get('domain')): self.domain = web.safestr(kw['domain']) else: return False self.admin = session.get('username') if not iredutils.isEmail(self.admin): return False # Check domain global admin. if session.get('domainGlobalAdmin') is True: return func(self, *args, **kw) else: # Check whether is domain admin. try: result = self.conn.select( 'domain_admins', what='username', where='''username=%s AND domain IN %s''' % ( web.sqlquote(self.admin), web.sqlquote([self.domain, 'ALL']), ), ) except Exception, e: result = {} if len(result) != 1: return func(self, *args, **kw) else: return web.seeother('/users' + '?msg=PERMISSION_DENIED&domain=' + self.domain)
def getManagedDomains(self, mail, attrs=attrs.ADMIN_ATTRS_ALL): self.mail = web.safestr(mail) if not iredutils.isEmail(self.mail): return (False, 'INCORRECT_USERNAME') # Pre-defined filter. filter = '(&(objectClass=mailDomain)(domainAdmin=%s))' % self.mail # Check admin type: global/normal admin. try: profile = self.profile(self.mail) if profile[1][0][1].get('domainGlobalAdmin', ['no'])[0] == 'yes': filter = '(objectClass=mailDomain)' except: pass try: self.managedDomains = self.conn.search_s( self.basedn, ldap.SCOPE_ONELEVEL, filter, attrs, ) return (True, self.managedDomains) except Exception, e: return (False, ldaputils.getExceptionDesc(e))
def getManagedDomains(self, admin, domainNameOnly=False, listedOnly=False,): self.admin = web.safestr(admin) if not iredutils.isEmail(self.admin): return (False, 'INCORRECT_USERNAME') self.sql_where = '' self.sql_left_join = '' if listedOnly is True: self.sql_where = 'AND domain_admins.username=%s' % web.sqlquote(self.admin) else: self.sql_left_join = 'OR domain_admins.domain="ALL"' % web.sqlquote(self.admin) try: result = self.conn.query( """ SELECT domain.domain FROM domain LEFT JOIN domain_admins ON (domain.domain=domain_admins.domain %s) WHERE domain_admins.username=%s %s ORDER BY domain_admins.domain """ % (self.sql_left_join, web.sqlquote(self.admin), self.sql_where) ) if domainNameOnly is True: domains = [] for i in result: if iredutils.isDomain(i.domain): domains += [str(i.domain).lower()] return (True, domains) else: return (True, list(result)) except Exception, e: return (False, str(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 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 isEmailExists(self, mail): # Return True if account is invalid or exist. self.mail = web.safestr(mail) if not iredutils.isEmail(mail): return True self.sqlMail = web.sqlquote(self.mail) try: resultOfAlias = self.conn.select( 'alias', what='address', where='address=%s' % self.sqlMail, limit=1, ) resultOfMailbox = self.conn.select( 'mailbox', what='username', where='username=%s' % self.sqlMail, limit=1, ) if len(resultOfAlias) == 1 or len(resultOfMailbox) == 1: return True else: return False except Exception, e: return True
def delete(self, domain, mails=[]): self.domain = str(domain) if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') if not isinstance(mails, types.ListType): return (False, 'INVALID_MAIL') self.mails = [str(v).lower() for v in mails if iredutils.isEmail(v) and str(v).endswith('@'+self.domain)] self.sqlMails = web.sqlquote(self.mails) # Delete domain and related records. try: self.conn.delete('mailbox', where='username IN %s' % self.sqlMails) self.conn.delete('alias', where='address IN %s' % self.sqlMails) self.conn.delete('recipient_bcc_user', where='username IN %s' % self.sqlMails) self.conn.delete('sender_bcc_user', where='username IN %s' % self.sqlMails) # TODO Remove email from alias.goto. #self.conn.delete() web.logger( msg="Delete user: %s." % ', '.join(self.mails), domain=self.domain, event='delete', ) return (True,) except Exception, e: return (False, str(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)
def listLogs(self, event='all', domain='all', admin='all', cur_page=1): self.event = web.safestr(event) self.domain = web.safestr(domain) self.admin = web.safestr(admin) self.cur_page = int(cur_page) # Generate a dictionary, converted to an SQL WHERE clause. queryDict = {} if self.event in LOG_EVENTS and self.event != 'all': queryDict['event'] = self.event if iredutils.isDomain(self.domain): queryDict['domain'] = self.domain if session.get('domainGlobalAdmin') is not True: queryDict['admin'] = session.get('username') else: if iredutils.isEmail(self.admin): queryDict['admin'] = self.admin # Get number of total records. if len(queryDict) == 0: qr = db.select( 'log', what='COUNT(timestamp) AS total', ) else: qr = db.select( 'log', what='COUNT(timestamp) AS total', where=web.db.sqlwhere(queryDict), ) self.total = qr[0].total or 0 # Get records. if len(queryDict) == 0: # No addition filter. self.entries = db.select( 'log', offset=(self.cur_page - 1) * settings.PAGE_SIZE_LIMIT, limit=settings.PAGE_SIZE_LIMIT, order='timestamp DESC', ) else: # With filter. self.entries = db.select( 'log', where=web.db.sqlwhere(queryDict), offset=(self.cur_page - 1) * settings.PAGE_SIZE_LIMIT, limit=settings.PAGE_SIZE_LIMIT, order='timestamp DESC', ) return (self.total, list(self.entries))
def proxyfunc(*args, **kw): # Check domain global admin. if session.get('domainGlobalAdmin') is True: return func(*args, **kw) else: if 'domain' in kw.keys() and iredutils.isDomain(kw.get('domain')): domain = web.safestr(kw['domain']) elif 'mail' in kw.keys() and iredutils.isEmail(kw.get('mail')): domain = web.safestr(kw['mail']).split('@')[-1] elif 'admin' in kw.keys() and iredutils.isEmail(kw.get('admin')): domain = web.safestr(kw['admin']).split('@')[-1] else: return (False, 'PERMISSION_DENIED') # Check whether is domain admin. validator = core.MySQLWrap() if validator.isDomainAdmin(domain=domain, admin=session.get('username'),): return func(*args, **kw) else: return (False, 'PERMISSION_DENIED')
def getAliasMembers(self, mail): self.mail = str(mail) members = [] if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') try: qr = self.conn.select( 'dbmail_aliases', vars={'mail': self.mail, }, what='deliver_to', where='alias = $mail', ) if qr: members = [str(rcd.deliver_to) for rcd in qr if iredutils.isEmail(str(rcd.deliver_to))] return (True, members) except Exception, e: return (False, 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') # Check admin exist. connutils = connUtils.Utils() if connutils.isAdminExists(self.mail): return (False, 'ALREADY_EXISTS') # Get domainGlobalAdmin setting. self.domainGlobalAdmin = 'yes' # Get language setting. self.preferredLanguage = web.safestr(data.get('preferredLanguage', 'en_US')) # Get new 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 = result[1] else: return result try: self.conn.insert( 'admin', username=self.mail, name=self.cn, password=iredutils.getSQLPassword(self.passwd), language=self.preferredLanguage, created=iredutils.sqlNOW, active='1', ) if self.domainGlobalAdmin == 'yes': self.conn.insert( 'domain_admins', username=self.mail, domain='ALL', created=iredutils.sqlNOW, active='1', ) web.logger(msg="Create admin: %s." % (self.mail), event='create',) return (True,) except Exception, e: return (False, str(e))
def ldif_mailExternalUser(mail, ): mail = web.safestr(mail).lower() if not iredutils.isEmail(mail): return None listname, domain = mail.split('@') ldif = [ ('objectClass', ['mailExternalUser']), ('accountStatus', ['active']), ('memberOfGroup', [mail]), ('enabledService', ['mail', 'deliver']), ] return ldif
def ldif_mailExternalUser(mail,): mail = web.safestr(mail).lower() if not iredutils.isEmail(mail): return None listname, domain = mail.split('@') ldif = [ ('objectClass', ['mailExternalUser']), ('accountStatus', ['active']), ('memberOfGroup', [mail]), ('enabledService', ['mail', 'deliver']), ] return ldif
def POST(self, domain): i = web.input(_unicode=False, username=[]) self.domain = str(domain) if not iredutils.isDomain(self.domain): return web.seeother('/domains?msg=INVALID_DOMAIN_NAME') self.mails = [ str(v) for v in i.get('username', []) if iredutils.isEmail(v) and str(v).endswith('@' + self.domain) ] self.action = i.get('action', None) msg = i.get('msg', None) userLib = userlib.User() if self.action == 'delete': result = userLib.delete( domain=self.domain, mails=self.mails, ) msg = 'DELETED_SUCCESS' elif self.action == 'disable': result = userLib.enableOrDisableAccount( domain=self.domain, accounts=self.mails, active=False, ) msg = 'DISABLED_SUCCESS' elif self.action == 'enable': result = userLib.enableOrDisableAccount( domain=self.domain, accounts=self.mails, active=True, ) msg = 'ENABLED_SUCCESS' else: result = (False, 'INVALID_ACTION') if result[0] is True: return web.seeother('/users/%s?msg=%s' % ( self.domain, msg, )) else: return web.seeother('/users/%s?msg=%s' % ( self.domain, result[1], ))
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 delete(self, domain, mails=[]): self.domain = str(domain) if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') if not isinstance(mails, (list, tuple,)): return (False, 'INVALID_MAIL') self.mails = [str(v).lower() for v in mails if iredutils.isEmail(v) and str(v).endswith('@' + self.domain) ] # Remove alias from domain.defaultuseraliases. # Get domain profile. domainLib = domainlib.Domain() qr = domainLib.simpleProfile(domain=self.domain, columns=['domain', 'defaultuseraliases', ]) if qr[0] is True: self.domainProfile = qr[1] else: return qr self.defaultUserAliases = self.domainProfile.defaultuseraliases.split(',') # Remove from domain.defaultuseraliases. self.newDefaultAliases = [str(v).lower() for v in self.defaultUserAliases if v not in self.mails ] # Delete domain and related records. try: self.conn.delete('dbmail_aliases_extra', where='%s' % web.sqlors('alias = ', self.mails),) self.conn.delete('dbmail_aliases', where='%s' % web.sqlors('alias = ', self.mails),) self.conn.update('dbmail_domains', vars={'domain': self.domain, }, defaultuseraliases=','.join(self.newDefaultAliases), modified=iredutils.getGMTTime(), where='domain = $domain', ) web.logger( msg="Delete mail alias: %s." % ', '.join(self.mails), domain=self.domain, event='delete', ) return (True,) except Exception, e: return (False, str(e))
def auth(self, username, password, verifyPassword=False,): if not iredutils.isEmail(username): return (False, 'INVALID_USERNAME') if len(password) == 0: return (False, 'EMPTY_PASSWORD') # Query admin. result = self.conn.select( 'admin', where="username=%s AND active=1" % web.sqlquote(username), limit=1, ) if len(result) == 1: # It's a valid admin. record = result[0] # Get salt string from password which stored in SQL. tmpsalt = str(record.password).split('$') tmpsalt[-1] = '' salt = '$'.join(tmpsalt) # Compare passwords. if md5crypt.md5crypt(password, salt) == str(record.password): if verifyPassword is not True: session['username'] = username session['logged'] = True # Set preferred language. session['lang'] = str(record.language) or 'en_US' # Set session['domainGlobalAdmin'] try: result = self.conn.select( 'domain_admins', what='domain', where='''username=%s AND domain="ALL"''' % web.sqlquote(username), limit=1, ) if len(result) == 1: session['domainGlobalAdmin'] = True except: pass return (True,) else: return (False, 'INVALID_CREDENTIALS') else: return (False, 'INVALID_CREDENTIALS')
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 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 GET(self, profile_type, mail): i = web.input() self.mail = web.safestr(mail) self.profile_type = web.safestr(profile_type) if not iredutils.isEmail(self.mail): return web.seeother("/admins?msg=INVALID_MAIL") if session.get("domainGlobalAdmin") is not True and session.get("username") != self.mail: # Don't allow to view/update other admins' profile. return web.seeother("/profile/admin/general/%s?msg=PERMISSION_DENIED" % session.get("username")) adminLib = adminlib.Admin() result = adminLib.profile(mail=self.mail) if result[0] is True: domainGlobalAdmin, profile = result[1], result[2] # Get all domains. self.allDomains = [] domainLib = domainlib.Domain() resultOfAllDomains = domainLib.getAllDomains() if resultOfAllDomains[0] is True: self.allDomains = resultOfAllDomains[1] # Get managed domains. self.managedDomains = [] qr = adminLib.getManagedDomains(admin=self.mail, domainNameOnly=True, listedOnly=True) if qr[0] is True: self.managedDomains += qr[1] return web.render( "mysql/admin/profile.html", mail=self.mail, profile_type=self.profile_type, domainGlobalAdmin=domainGlobalAdmin, profile=profile, languagemaps=languages.getLanguageMaps(), allDomains=self.allDomains, managedDomains=self.managedDomains, min_passwd_length=cfg.general.get("min_passwd_length", "0"), max_passwd_length=cfg.general.get("max_passwd_length", "0"), msg=i.get("msg"), ) else: return web.seeother("/admins?msg=" + result[1])
def GET(self, profile_type, mail): i = web.input() self.mail = web.safestr(mail) self.profile_type = web.safestr(profile_type) if not iredutils.isEmail(self.mail): return web.seeother('/admins?msg=INVALID_MAIL') if session.get('domainGlobalAdmin') is not True and session.get('username') != self.mail: # Don't allow to view/update other admins' profile. return web.seeother('/profile/admin/general/%s?msg=PERMISSION_DENIED' % session.get('username')) adminLib = adminlib.Admin() result = adminLib.profile(mail=self.mail) if result[0] is True: domainGlobalAdmin, profile = result[1], result[2] # Get all domains. self.allDomains = [] domainLib = domainlib.Domain() resultOfAllDomains = domainLib.getAllDomains() if resultOfAllDomains[0] is True: self.allDomains = resultOfAllDomains[1] # Get managed domains. self.managedDomains = [] qr = adminLib.getManagedDomains(admin=self.mail, domainNameOnly=True, listedOnly=True,) if qr[0] is True: self.managedDomains += qr[1] return web.render( 'mysql/admin/profile.html', mail=self.mail, profile_type=self.profile_type, domainGlobalAdmin=domainGlobalAdmin, profile=profile, languagemaps=languages.getLanguageMaps(), allDomains=self.allDomains, managedDomains=self.managedDomains, min_passwd_length=cfg.general.get('min_passwd_length', '0'), max_passwd_length=cfg.general.get('max_passwd_length', '0'), msg=i.get('msg'), ) else: return web.seeother('/admins?msg=' + result[1])
def POST(self, accountType): accountType = web.safestr(accountType) # user, alias i = web.input(_unicode=False, mail=[]) # Get action. action = i.get('action', None) if action not in ['enable', 'disable', 'delete', ]: raise web.seeother('/search?msg=INVALID_ACTION') # Get list of accounts which has valid format. accounts = [web.safestr(v).lower() for v in i.get('mail', []) if iredutils.isEmail(web.safestr(v))] # Raise earlier to avoid SQL query. if not accounts: raise web.seeother('/search?msg=INVALID_MAIL') domains = set([v.split('@', 1)[-1] for v in accounts]) # Get managed accounts. if not session.get('domainGlobalAdmin'): # Get list of managed domains. connutils = connUtils.Utils() qr = connutils.getManagedDomains( admin=session.get('username'), domainNameOnly=True, listedOnly=True, ) if qr[0] is True: domains = [d for d in domains if d in qr[1]] accounts = [v for v in accounts if v.split('@', 1)[-1] in domains] else: raise web.seeother('/search?msg=%s' % str(qr[1])) if not accounts: raise web.seeother('/search?msg=INVALID_MAIL') conn = core.MySQLWrap() if action in ['enable', ]: qr = conn.setAccountStatus(accounts=accounts, accountType=accountType, active=True) elif action in ['disable', ]: qr = conn.setAccountStatus(accounts=accounts, accountType=accountType, active=False) elif action in ['delete', ]: qr = conn.deleteAccounts(accounts=accounts, accountType=accountType) if qr[0] is True: raise web.seeother('/search?msg=SUCCESS') else: raise web.seeother('/search?msg=%s' % str(qr[1]))
def delete(self, mails=[]): if not isinstance(mails, list): return (False, 'INVALID_MAIL') self.mails = [str(v).lower() for v in mails if iredutils.isEmail(v)] sql_vars = {'username': self.mails, } # Delete domain and related records. try: self.conn.delete('dbmail_admins', vars=sql_vars, where='username IN $username', ) self.conn.delete('dbmail_domain_admins', vars=sql_vars, where='username IN $username', ) web.logger(msg="Delete admin: %s." % ', '.join(self.mails), event='delete',) return (True,) except Exception, e: return (False, str(e))
def delete(self, mails=[]): if not isinstance(mails, types.ListType): return (False, 'INVALID_MAIL') self.mails = [str(v).lower() for v in mails if iredutils.isEmail(v)] self.sqlMails = web.sqlquote(self.mails) # Delete domain and related records. try: self.conn.delete('admin', where='username IN %s' % self.sqlMails) self.conn.delete('domain_admins', where='username IN %s' % self.sqlMails) web.logger(msg="Delete admin: %s." % ', '.join(self.mails), event='delete',) return (True,) except Exception, e: return (False, str(e))
def listLogs(self, event='all', domain='all', admin='all', cur_page=1): self.event = web.safestr(event) self.domain = web.safestr(domain) self.admin = web.safestr(admin) self.cur_page = int(cur_page) # Generate a dictionary, converted to an SQL WHERE clause. queryDict = {} if self.event in LOG_EVENTS and self.event != 'all': queryDict['event'] = self.event if self.domain != '' and self.domain != 'all': queryDict['domain'] = self.domain if session.get('domainGlobalAdmin') is not True: queryDict['admin'] = session.get('username','') else: if iredutils.isEmail(self.admin): queryDict['admin'] = self.admin # Get number of total records. if len(queryDict) == 0: qr = db.select('log', what='COUNT(*) AS total',) else: qr = db.select('log', what='COUNT(*) AS total', where=web.db.sqlwhere(queryDict),) self.total = qr[0].total or 0 # Get records. if len(queryDict) == 0: # No addition filter. self.entries = db.select( 'log', offset=(self.cur_page - 1) * session.pageSizeLimit, limit=session.pageSizeLimit, order='timestamp DESC', ) else: # With filter. self.entries = db.select('log', where=web.db.sqlwhere(queryDict), offset=(self.cur_page - 1) * session.pageSizeLimit, limit=session.pageSizeLimit, order='timestamp DESC', ) return (self.total, list(self.entries))
def POST(self, domain): i = web.input(_unicode=False, mail=[]) self.domain = web.safestr(domain) self.mails = [ str(v) for v in i.get('mail', []) if iredutils.isEmail(v) and str(v).endswith('@' + self.domain) ] self.action = i.get('action', None) msg = i.get('msg', None) userLib = userlib.User() if self.action == 'delete': result = userLib.delete( domain=self.domain, mails=self.mails, ) msg = 'DELETED' elif self.action == 'disable': result = userLib.enableOrDisableAccount( domain=self.domain, accounts=self.mails, active=False, ) msg = 'DISABLED' elif self.action == 'enable': result = userLib.enableOrDisableAccount( domain=self.domain, accounts=self.mails, active=True, ) msg = 'ENABLED' else: result = (False, 'INVALID_ACTION') if result[0] is True: raise web.seeother('/users/%s?msg=%s' % ( self.domain, msg, )) else: raise web.seeother('/users/%s?msg=%s' % ( self.domain, web.urlquote(result[1]), ))
def profile(self, mail): self.mail = web.safestr(mail) self.domainGlobalAdmin = False if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') self.sqladmin = web.sqlquote(self.mail) try: result = self.conn.select('admin', where='username=%s' % self.sqladmin, limit=1,) if len(result) == 1: if self.isGlobalAdmin(admin=self.mail): self.domainGlobalAdmin = True return (True, self.domainGlobalAdmin, list(result)[0]) else: return (False, 'INVALID_MAIL') except Exception, e: return (False, 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 ldif_catchall(domain, mailForwardingAddress=[],): domain = web.safestr(domain).lower() ldif = [ ('objectClass', ['inetOrgPerson', 'mailUser', ]), ('mail', '@' + domain), ('accountStatus', 'active'), ('cn', 'Catch-all account'), ('sn', 'Catch-all account'), ('uid', 'catchall'), ] catchallAddress = set([ web.safestr(v) for v in mailForwardingAddress if iredutils.isEmail(v) ]) if len(catchallAddress) > 0: ldif += [('mailForwardingAddress', list(catchallAddress))] return ldif
def isDomainAdmin(self, domain, admin=session.get('username'),): if not iredutils.isDomain(domain) or not iredutils.isEmail(admin): return False if admin == session.get('username') and session.get('domainGlobalAdmin') is True: return True try: result = self.conn.select( 'dbmail_domain_admins', vars={'domain': domain, 'admin': admin, }, what='username', where='domain=$domain AND username=$admin AND active=1', limit=1, ) if len(result) == 1: return True else: return False except Exception, e: return False
def getFilterOfDeleteUserFromGroups(self, mail): # Get valid emails as list. if isinstance(mail, types.ListType): self.mails = [web.safestr(v).lower() for v in mail if iredutils.isEmail(str(v))] else: # Single email. self.mails = [web.safestr(mail).lower()] filterUserAndAlias = '(&(|(objectClass=mailAlias)(objectClass=mailUser))(|' filterExternalUser = '******' for mail in self.mails: filterUserAndAlias += '(mailForwardingAddress=%s)' % mail filterExternalUser += '(mail=%s)' % mail # Close filter string. filterUserAndAlias += '))' filterExternalUser += '))' filter = '(|' + filterUserAndAlias + filterExternalUser + ')' return filter
def getManagedDomains( self, admin, domainNameOnly=False, listedOnly=False, ): admin = web.safestr(admin) if not iredutils.isEmail(admin): return (False, 'INCORRECT_USERNAME') sql_left_join = '' if listedOnly is False: sql_left_join = """OR dbmail_domain_admins.domain='ALL'""" try: result = self.conn.query( """ SELECT dbmail_domains.domain FROM dbmail_domains LEFT JOIN dbmail_domain_admins ON (dbmail_domains.domain=dbmail_domain_admins.domain %s) WHERE dbmail_domain_admins.username=$admin ORDER BY dbmail_domain_admins.domain """ % (sql_left_join), vars={ 'admin': admin, }, ) if domainNameOnly is True: domains = [] for i in result: if iredutils.isDomain(i.domain): domains += [str(i.domain).lower()] return (True, domains) else: return (True, list(result)) except Exception, e: return (False, 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 GET(self, profile_type, mail): i = web.input(enabledService=[], telephoneNumber=[], ) self.mail = web.safestr(mail) self.cur_domain = self.mail.split('@', 1)[-1] self.profile_type = web.safestr(profile_type) if self.mail.startswith('@') and iredutils.isDomain(self.cur_domain): # Catchall account. return web.seeother('/profile/domain/catchall/%s' % (self.cur_domain)) if not iredutils.isEmail(self.mail): return web.seeother('/domains?msg=INVALID_USER') domainAccountSetting = {} userLib = user.User() result = userLib.profile(domain=self.cur_domain, mail=self.mail) if result[0] is True: if self.profile_type == 'password': # Get accountSetting of current domain. domainLib = domainlib.Domain() result_setting = domainLib.getDomainAccountSetting(domain=self.cur_domain) if result_setting[0] is True: domainAccountSetting = result_setting[1] minPasswordLength = domainAccountSetting.get('minPasswordLength', '0') maxPasswordLength = domainAccountSetting.get('maxPasswordLength', '0') return web.render( 'ldap/user/profile.html', profile_type=self.profile_type, mail=self.mail, user_profile=result[1], minPasswordLength=minPasswordLength, maxPasswordLength=maxPasswordLength, msg=i.get('msg', None), ) else: return web.seeother('/users/%s?msg=%s' % (self.cur_domain, result[1]))
def isAdminExists(self, mail): # Return True if account is invalid or exist. mail = str(mail) if not iredutils.isEmail(mail): return True try: result = self.conn.select( 'admin', what='username', where='username = %s' % web.sqlquote(mail), limit=1, ) if len(result) > 0: # Exists. return True else: return False except: # Return True as exist to not allow to create new domain/account. return True
def profile(self, domain, mail): self.domain = str(domain) self.mail = str(mail) if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') if not iredutils.isEmail(self.mail): return (False, 'INVALID_MAIL') if not self.mail.endswith('@' + self.domain): raise web.seeother('/domains?msg=PERMISSION_DENIED') try: result = self.conn.select( 'dbmail_aliases_extra', vars={'mail': self.mail, }, where='alias = $mail', limit=1, ) return (True, list(result)[0]) except Exception, e: return (False, str(e))
def delete(self, domain, mails=[]): self.domain = str(domain) if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') if not isinstance(mails, list): return (False, 'INVALID_MAIL') self.mails = [ str(addr).lower() for addr in mails if iredutils.isEmail(addr) and str(addr).endswith('@' + self.domain) ] if not self.mails: return (False, 'INVALID_MAIL') # Delete domain and related records. try: # Delete from aliases. self.conn.delete('dbmail_aliases', where='%s' % web.sqlors('deliver_to = ', self.mails)) self.conn.delete('dbmail_aliases', where='%s' % web.sqlors('alias = ', self.mails)) # Delete user record. self.conn.delete('dbmail_users', where='%s' % web.sqlors('userid = ', self.mails)) web.logger( msg="Delete user: %s." % ', '.join(self.mails), domain=self.domain, event='delete', ) return (True, ) except Exception, e: return (False, str(e))
def isDomainAdmin(self, domain, admin=session.get('username'),): if not iredutils.isDomain(domain) or not iredutils.isEmail(admin): return False if admin == session.get('username') and session.get('domainGlobalAdmin') is True: return True try: result = self.conn.select( 'domain_admins', what='username', where='domain=%s AND username=%s AND active=1' % ( web.sqlquote(domain), web.sqlquote(admin), ), limit=1, ) if len(result) == 1: return True else: return False except Exception, e: return False
def GET(self, profile_type, mail): i = web.input() self.mail = web.safestr(mail) self.cur_domain = self.mail.split('@', 1)[-1] self.profile_type = web.safestr(profile_type) if not iredutils.isEmail(self.mail): raise web.seeother('/domains?msg=INVALID_USER') if not iredutils.isDomain(self.cur_domain): raise web.seeother('/domains?msg=INVALID_DOMAIN_NAME') aliasLib = aliaslib.Alias() qr = aliasLib.profile(domain=self.cur_domain, mail=self.mail) if qr[0] is True: self.profile = qr[1] else: raise web.seeother('/aliases/%s?msg=%s' % (self.cur_domain, web.urlquote(qr[1]))) # Get list of alias members. qr = aliasLib.getAliasMembers(mail=self.mail) if qr[0] is True: members = qr[1] else: raise web.seeother('/aliases/%s?msg=%s' % (self.cur_domain, web.urlquote(qr[1]))) return web.render( 'dbmail_mysql/alias/profile.html', cur_domain=self.cur_domain, mail=self.mail, profile_type=self.profile_type, profile=self.profile, members=members, msg=i.get('msg'), )
def getNumberOfManagedAccounts(self, admin=None, accountType='domain', domains=[],): if admin is None: self.admin = session.get('username') else: self.admin = str(admin) if not iredutils.isEmail(self.admin): return 0 self.domains = [] if len(domains) > 0: self.domains = [str(d).lower() for d in domains if iredutils.isDomain(d)] else: qr = self.getManagedDomains(admin=self.admin, domainNameOnly=True) if qr[0] is True: self.domains = qr[1] else: self.domains = [] if accountType == 'domain': try: if self.isGlobalAdmin(self.admin): result = self.conn.select('domain', what='COUNT(domain) AS total',) else: result = self.conn.query( """ SELECT COUNT(domain.domain) AS total FROM domain LEFT JOIN domain_admins ON (domain.domain=domain_admins.domain) WHERE domain_admins.username=%s """ % (web.sqlquote(self.admin)) ) total = result[0].total or 0 return total except Exception, e: pass
def getFilterOfDeleteUserFromGroups(self, mail): # Get valid emails as list. if isinstance(mail, types.ListType): self.mails = [ web.safestr(v).lower() for v in mail if iredutils.isEmail(str(v)) ] else: # Single email. self.mails = [web.safestr(mail).lower()] filterUserAndAlias = '(&(|(objectClass=mailAlias)(objectClass=mailUser))(|' filterExternalUser = '******' for mail in self.mails: filterUserAndAlias += '(mailForwardingAddress=%s)' % mail filterExternalUser += '(mail=%s)' % mail # Close filter string. filterUserAndAlias += '))' filterExternalUser += '))' filter = '(|' + filterUserAndAlias + filterExternalUser + ')' return filter
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
else: self.active = 0 self.action = 'Disable' if self.accountType == 'domain': self.accounts = [str(v) for v in accounts if iredutils.isDomain(v)] try: self.conn.update( 'domain', where='domain IN %s' % (web.sqlquote(self.accounts)), active=self.active, ) except Exception, e: return (False, str(e)) elif self.accountType == 'user': self.accounts = [str(v) for v in accounts if iredutils.isEmail(v)] try: self.conn.update( 'mailbox', where='username IN %s' % (web.sqlquote(self.accounts)), active=self.active, ) except Exception, e: return (False, str(e)) elif self.accountType == 'admin': self.accounts = [str(v) for v in accounts if iredutils.isEmail(v)] try: self.conn.update( 'admin', where='username IN %s' % (web.sqlquote(self.accounts)), active=self.active,
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))
updates['storagebasedirectory'] = self.storagebasedirectory updates['storagenode'] = self.storagenode updates['maildir'] = self.maildir # Get transport. self.defaultTransport = str(cfg.general.get('mtaTransport', 'dovecot')) self.transport = str(data.get('mtaTransport', self.defaultTransport)) updates['transport'] = self.transport # Get sender/recipient bcc. senderBccAddress = str(data.get('senderBccAddress', '')) recipientBccAddress = str(data.get('recipientBccAddress', '')) updates_sender_bcc = {} updates_recipient_bcc = {} if iredutils.isEmail(senderBccAddress): updates_sender_bcc = {'username': self.mail, 'bcc_address': senderBccAddress, 'domain': self.domain, 'created': iredutils.sqlNOW, 'active': 1, } if iredutils.isEmail(recipientBccAddress): updates_recipient_bcc = {'username': self.mail, 'bcc_address': recipientBccAddress, 'domain': self.domain, 'created': iredutils.sqlNOW, 'active': 1, }
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 if self.domain != domain: return (False, 'PERMISSION_DENIED') if not iredutils.isDomain(self.domain): return (False, 'INVALID_DOMAIN_NAME') # Check account existing. connutils = connUtils.Utils() if connutils.isEmailExists(mail=self.mail): return (False, 'ALREADY_EXISTS') # Get domain profile. domainLib = domainlib.Domain() resultOfDomainProfile = domainLib.profile(domain=self.domain) if resultOfDomainProfile[0] is True: self.domainProfile = resultOfDomainProfile[1] else: return resultOfDomainProfile # Check account limit. adminLib = adminlib.Admin() numberOfExistAccounts = adminLib.getNumberOfManagedAccounts(accountType='user', domains=[self.domain]) if self.domainProfile.mailboxes == 0: # Unlimited. pass elif self.domainProfile.mailboxes <= numberOfExistAccounts: return (False, 'EXCEEDED_DOMAIN_ACCOUNT_LIMIT') # Check spare quota and number of spare account limit. # Get quota from <form> self.mailQuota = str(data.get('mailQuota')).strip() self.defaultUserQuota = self.domainProfile.get('defaultuserquota', 0) if self.mailQuota.isdigit(): self.mailQuota = int(self.mailQuota) else: self.mailQuota = self.defaultUserQuota # Re-calculate mail quota if this domain has limited max quota. if self.domainProfile.maxquota > 0: # Get used quota. qr = domainLib.getAllocatedQuotaSize(domain=self.domain) if qr[0] is True: self.allocatedQuota = qr[1] else: return qr spareQuota = self.domainProfile.maxquota - self.allocatedQuota if spareQuota > 0: if spareQuota < self.mailQuota: self.mailQuota = spareQuota else: # No enough quota. return (False, 'EXCEEDED_DOMAIN_QUOTA_SIZE') # # Get password from <form>. # self.newpw = str(data.get('newpw', '')) self.confirmpw = str(data.get('confirmpw', '')) # Get password length limit from domain profile or global setting. self.minPasswordLength = self.domainProfile.get('minpasswordlength',cfg.general.get('min_passwd_length', '0')) self.maxPasswordLength = self.domainProfile.get('maxpasswordlength', cfg.general.get('max_passwd_length', '0')) resultOfPW = iredutils.verifyNewPasswords( self.newpw, self.confirmpw, min_passwd_length=self.minPasswordLength, max_passwd_length=self.maxPasswordLength, ) if resultOfPW[0] is True: self.passwd = iredutils.getSQLPassword(resultOfPW[1]) else: return resultOfPW # Get display name from <form> self.cn = data.get('cn', '') # Assign new user to default mail aliases. assignedAliases = [str(v).lower() for v in str(self.domainProfile.defaultuseraliases).split(',') if iredutils.isEmail(v) ] try: # Store new user in SQL db. self.conn.insert( 'mailbox', domain=self.domain, username=self.mail, password=self.passwd, name=self.cn, maildir=iredutils.setMailMessageStore(self.mail), quota=self.mailQuota, created=iredutils.sqlNOW, active='1', local_part=self.username, ) # Assign new user to default mail aliases. if len(assignedAliases) > 0: for ali in assignedAliases: try: self.conn.query( ''' UPDATE alias SET goto=CONCAT(goto, %s) WHERE address=%s AND domain=%s ''' % ( web.sqlquote(','+self.mail), web.sqlquote(ali), web.sqlquote(self.domain), ) ) except: pass # Create an alias account: address=goto. self.conn.insert( 'alias', address=self.mail, goto=self.mail, domain=self.domain, created=iredutils.sqlNOW, active='1', ) web.logger(msg="Create user: %s." % (self.mail), domain=self.domain, event='create',) return (True,) except Exception, e: return (False, str(e))
def update(self, profile_type, mail, data): self.profile_type = web.safestr(profile_type) self.mail = str(mail).lower() self.domain = self.mail.split('@', 1)[-1] # Pre-defined update key:value. updates = {'modified': iredutils.sqlNOW,} if self.profile_type == 'general': # Get name self.cn = data.get('cn', '') updates['name'] = self.cn # Get account status if 'accountStatus' in data.keys(): updates['active'] = 1 else: updates['active'] = 0 # Get mail quota size. mailQuota = str(data.get('mailQuota')) if mailQuota.isdigit(): updates['quota'] = int(mailQuota) # Get employee id. employeeNumber = data.get('employeeNumber', '') updates['employeeid'] = employeeNumber aliases = [str(v).lower() for v in data.get('memberOfAlias', []) if iredutils.isEmail(v) and str(v).endswith('@'+self.domain) ] elif self.profile_type == 'forwarding': mailForwardingAddress = [str(v).lower() for v in data.get('mailForwardingAddress', []) if iredutils.isEmail(v) ] if self.mail in mailForwardingAddress: mailForwardingAddress.remove(self.mail) try: self.conn.delete('alias', where='address=%s' % web.sqlquote(self.mail)) except Exception, e: return (False, str(e)) inserts = {} if len(mailForwardingAddress) > 0: # Get account status if 'forwarding' in data.keys(): inserts['active'] = 1 else: inserts['active'] = 0 if 'savecopy' in data.keys(): mailForwardingAddress += [self.mail] inserts['goto'] = ','.join(mailForwardingAddress) inserts['address'] = self.mail inserts['domain'] = self.domain inserts['created'] = iredutils.sqlNOW inserts['active'] = 1 try: self.conn.insert( 'alias', **inserts ) return (True,) except Exception, e: return (False, str(e))
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)