Esempio n. 1
0
def get_allocated_domain_quota(domain, conn=None):
    domain = web.safestr(domain).strip().lower()

    if not iredutils.is_domain(domain):
        return (False, 'INVALID_DOMAIN_NAME')

    dn = ldaputils.rdn_value_to_domain_dn(domain)

    allocated_quota = 0

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    try:
        # Use '(!([email protected]))' to exclude catch-all account.
        qr = conn.search_s(attrs.DN_BETWEEN_USER_AND_DOMAIN + dn,
                           ldap.SCOPE_SUBTREE,
                           '(objectClass=mailUser)',
                           ['mailQuota'])

        for (_dn, _ldif) in qr:
            _ldif = iredutils.bytes2str(_ldif)
            quota = _ldif.get('mailQuota', ['0'])[0]
            if quota.isdigit():
                allocated_quota += int(quota)

        return (True, allocated_quota)
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except ldap.SIZELIMIT_EXCEEDED:
        return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT')
    except Exception as e:
        return (False, repr(e))
Esempio n. 2
0
def __update_num_domain_current_accounts(domain,
                                         increase=False,
                                         decrease=False,
                                         step_number=1,
                                         account_type='user',
                                         conn=None):
    """Increase or decrease number of existing accounts in domain profile."""
    if not isinstance(step_number, int):
        step_number = 1

    if step_number <= 0:
        step_number = 1

    attr_map = {
        'user': '******',
        'alias': 'domainCurrentAliasNumber',
        'maillist': 'domainCurrentListNumber',
    }
    attr_count = attr_map[account_type]

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    dn = ldaputils.rdn_value_to_domain_dn(domain)

    # Get domain profile first
    try:
        qr = conn.search_s(dn,
                           ldap.SCOPE_BASE,
                           '(&(objectClass=mailDomain)(domainName=%s))' % domain,
                           [attr_count])

    except Exception as e:
        log_traceback()
        return (False, repr(e))

    if qr:
        _ldif = iredutils.bytes2str(qr[0][1])
        _current = int(_ldif.get(attr_count, [0])[0])

        _num = _current
        if increase:
            _num = _current + step_number
        elif decrease:
            _num = _current - step_number

        if _num < 0:
            _num = 0

        # Update count
        update_attr_with_single_value(dn=dn,
                                      attr=attr_count,
                                      value=_num,
                                      conn=conn)

    return (True, )
Esempio n. 3
0
def __num_accounts_under_domain(domain,
                                account_type='user',
                                disabled_only=False,
                                first_char=None,
                                update_statistics=False,
                                conn=None):
    """Get number of accounts under specified domain.

    :param domain: domain name you want to query.
    :param account_type: one of 'user', 'list', 'alias', 'ml', 'mixed_ml'.
    :param conn: ldap connection cursor.
    """
    domain = str(domain).lower()
    if not iredutils.is_domain(domain):
        return (False, 'INVALID_DOMAIN_NAME')

    dn_domain = ldaputils.rdn_value_to_domain_dn(domain)

    statistics_attr = None
    if account_type == 'user':
        search_filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % domain
        statistics_attr = 'domainCurrentUserNumber'
    else:
        search_filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % domain

    if disabled_only:
        search_filter = '(&' + search_filter + '(accountStatus=disabled)' + ')'

    if first_char:
        search_filter = '(&' + search_filter + '(|(cn=%s*)(mail=%s*))' + ')'

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    try:
        qr = conn.search_s(dn_domain,
                           ldap.SCOPE_SUBTREE,
                           search_filter,
                           ['dn'])

        num = len(qr)

        if update_statistics and statistics_attr:
            mod_attr = ldaputils.mod_replace(statistics_attr, num)
            try:
                conn.modify_s(dn_domain, mod_attr)
            except:
                log_traceback()

        return num
    except:
        log_traceback()
        return 0
Esempio n. 4
0
def get_domain_account_setting(domain, profile=None, conn=None):
    domain = str(domain).lower()
    if not iredutils.is_domain(domain):
        return (False, 'INVALID_DOMAIN_NAME')

    if profile:
        dn = None
    else:
        dn = ldaputils.rdn_value_to_domain_dn(domain)

    return __get_account_setting_by_dn(dn=dn, profile=profile, conn=conn)
Esempio n. 5
0
def reset_forwardings(mail, forwardings=None, conn=None):
    if forwardings:
        _addresses = [
            str(v).lower() for v in forwardings if iredutils.is_email(v)
        ]
    else:
        _addresses = []

    # Remove duplicate addresses
    if _addresses:
        _addresses = list(set(_addresses))

    # Remove non-existing addresses in same domain.
    domain = mail.split('@', 1)[-1]
    addrs_in_domain = set()
    addrs_not_in_domain = set()

    for addr in _addresses:
        if addr.endswith('@' + domain):
            addrs_in_domain.add(addr)
        else:
            addrs_not_in_domain.add(addr)

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    # Get existing addresses
    valid_addrs_in_domain = set()
    if addrs_in_domain:
        dn = ldaputils.rdn_value_to_domain_dn(domain)
        _qr = ldap_lib_general.filter_existing_emails(mails=addrs_in_domain,
                                                      base_dn=dn,
                                                      conn=conn)

        valid_addrs_in_domain = set(_qr['exist'])

    fwd_addrs = list(valid_addrs_in_domain | addrs_not_in_domain)

    if fwd_addrs:
        mod_attr = ldaputils.mod_replace('mailForwardingAddress', fwd_addrs)
    else:
        mod_attr = ldaputils.mod_replace('mailForwardingAddress', None)

    try:
        dn = ldaputils.rdn_value_to_user_dn(mail)
        conn.modify_s(dn, mod_attr)
        return (True, )
    except Exception as e:
        return (False, repr(e))
Esempio n. 6
0
def exclude_non_existing_emails_in_domain(domain, mails, conn=None):
    """
    Remove non-existing addresses in specified domain from given list of mail
    addresses. Return a list of existing and external addresses.

    :param domain: mail domain name.
    :param mails: a list/set/tuple of email addresses
    :param conn: ldap connection cursor
    """
    domain = domain.lower()
    mails = {str(v).lower()
             for v in mails
             if iredutils.is_email(v)}

    _internals = {i for i in mails if i.endswith('@' + domain)}
    _externals = {i for i in mails if not i.endswith('@' + domain)}

    dn = ldaputils.rdn_value_to_domain_dn(domain)
    qr = filter_existing_emails(mails=_internals, base_dn=dn, conn=conn)
    return list(_externals) + qr['exist']
Esempio n. 7
0
def __unmark_user_as_admin(user, domains=None, all_domains=False, conn=None):
    user = str(user).lower()
    if not iredutils.is_email(user):
        return (False, 'INVALID_MAIL')

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    if domains:
        try:
            for d in domains:
                domain_dn = ldaputils.rdn_value_to_domain_dn(d)
                qr = ldap_lib_general.remove_attr_values(dn=domain_dn,
                                                         attr='domainAdmin',
                                                         values=[user],
                                                         conn=conn)
                if not qr[0]:
                    return qr

            return (True, )
        except Exception as e:
            return (False, repr(e))
    else:
        if all_domains:
            # Remove this user admin from all domains by default.
            qr_filter = '(&(objectClass=mailDomain)(domainAdmin=%s))' % user

            qr = conn.search_s(settings.ldap_basedn, ldap.SCOPE_ONELEVEL,
                               qr_filter, ['dn'])

            for (dn, _ldif) in qr:
                try:
                    ldap_lib_general.remove_attr_values(dn=dn,
                                                        attr='domainAdmin',
                                                        values=[user],
                                                        conn=conn)
                except Exception as e:
                    return (False, repr(e))

        return (True, )
Esempio n. 8
0
def get_domain_password_lengths(domain,
                                account_settings=None,
                                fallback_to_global_settings=False,
                                db_settings=None,
                                conn=None):
    das = {}

    if account_settings:
        das = account_settings
    else:
        if not conn:
            _wrap = LDAPWrap()
            conn = _wrap.conn

        dn = ldaputils.rdn_value_to_domain_dn(domain)
        _filter = '(&(objectClass=mailDomain)(|(domainName={})(domainAliasName={})))'.format(domain, domain)

        _qr = conn.search_s(dn,
                            ldap.SCOPE_BASE,
                            _filter,
                            ['domainName', 'accountSetting'])
        if _qr:
            das = ldaputils.get_account_settings_from_qr(_qr).get(domain, {})

    min_pw_len = das.get('minPasswordLength', 0)
    max_pw_len = das.get('maxPasswordLength', 0)

    if fallback_to_global_settings:
        if not db_settings:
            db_settings = iredutils.get_settings_from_db(params=['min_passwd_length', 'max_passwd_length'])

        if min_pw_len < db_settings['min_passwd_length']:
            min_pw_len = db_settings['min_passwd_length']

        if max_pw_len < db_settings['max_passwd_length']:
            max_pw_len = db_settings['max_passwd_length']

    return (min_pw_len, max_pw_len)
Esempio n. 9
0
def __mark_user_as_admin(user, domains, conn=None):
    user = str(user).lower()
    if not iredutils.is_email(user):
        return (False, 'INVALID_MAIL')

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    for i in domains:
        domain_dn = ldaputils.rdn_value_to_domain_dn(i)
        try:
            qr = ldap_lib_general.add_attr_values(dn=domain_dn,
                                                  attr='domainAdmin',
                                                  values=[user],
                                                  conn=conn)
            if not qr[0]:
                return qr

        except Exception as e:
            return (False, repr(e))

    return (True, )
Esempio n. 10
0
def __reset_num_domain_current_accounts(domain, num, account_type='user', conn=None):
    """Update number of existing accounts in domain profile."""
    dn = ldaputils.rdn_value_to_domain_dn(domain)
    if not isinstance(num, int):
        return (False, 'INVALID_NUMBER')

    if num < 0:
        num = 0

    mapping = {'user': '******',
               'alias': 'domainCurrentAliasNumber',
               'maillist': 'domainCurrentListNumber'}
    attr_count = mapping[account_type]

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    qr = update_attr_with_single_value(dn=dn,
                                       attr=attr_count,
                                       value=num,
                                       conn=conn)

    return qr
Esempio n. 11
0
def list_accounts(domain,
                  search_filter=None,
                  attrlist=None,
                  email_only=False,
                  disabled_only=False,
                  conn=None):
    # Update number of existing users in domain profile.
    update_count = False

    if not search_filter:
        # Use '(!([email protected]))' to hide catch-all account.
        search_filter = '(&(objectClass=mailUser)(!(mail=@%s)))' % domain
        update_count = True

    if disabled_only:
        # use "is True" here to prevent client input invalid value in url.
        search_filter = '(&' + search_filter + '(accountStatus=disabled)' + ')'

    if not attrlist:
        if email_only:
            attrlist = ['mail']
        else:
            attrlist = list(attrs.USER_SEARCH_ATTRS)

    dn_domain = ldaputils.rdn_value_to_domain_dn(domain)

    # Search only admins INSIDE same domain.
    dn = attrs.DN_BETWEEN_USER_AND_DOMAIN + dn_domain

    if not conn:
        _wrap = LDAPWrap()
        conn = _wrap.conn

    try:
        qr = conn.search_s(dn, ldap.SCOPE_ONELEVEL, search_filter, attrlist)
        if qr:
            qr = iredutils.bytes2str(qr)

        _emails = []
        if email_only:
            for (_dn, _ldif) in qr:
                _emails += _ldif.get('mail', [])

            _emails.sort()

        if update_count:
            # Reset number of existing users in domain profile.
            ldap_lib_general.reset_num_domain_current_users(domain=domain,
                                                            num=len(qr),
                                                            conn=conn)

        if email_only:
            return (True, _emails)
        else:
            return (True, qr)
    except ldap.NO_SUCH_OBJECT:
        return (False, 'NO_SUCH_ACCOUNT')
    except ldap.SIZELIMIT_EXCEEDED:
        return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT')
    except Exception as e:
        return (False, repr(e))
Esempio n. 12
0
def get_paged_account_list(account_profiles,
                           current_page=1,
                           domain=None,
                           account_type=None,
                           order_name=None,
                           order_by_desc=False,
                           size_limit=None,
                           conn=None):
    """Sort accounts. Return a dict which contains keys:

    - total : number of total accounts
    - account_profiles: list of ldap query result sets ((<dn>: {...}) tuples)
    - pages: number of total pages show be showed in account list page.

    @account_profiles -- list of account_profiles (with many account details)
    @current_page -- offset page
    @domain -- accounts are under this domain
    @account_type -- account type
    @order_name -- order result set by given attribute.
    @order_by_desc -- order result set descending (desc)
    @size_limit -- show how many accounts in one page
    """
    if not size_limit:
        size_limit = settings.PAGE_SIZE_LIMIT

    current_page = int(current_page)

    # Initial a dict to set default values.
    result = {
        'total': 0,
        'account_profiles': [],
        'pages': 0,
    }

    # Get total accounts.
    total = len(account_profiles)
    result['total'] = total

    # Get number of actual pages.
    if total % size_limit == 0:
        pages = total / size_limit
    else:
        pages = (total / size_limit) + 1

    result['pages'] = pages

    if current_page >= pages:
        current_page = pages

    _total_quota = 0
    if (account_type == 'user') and domain:
        if order_name == 'quota':
            # sort accounts by real-time quota usage
            _all_used_quota = get_all_account_used_quota_under_domain(domain)
            _dict_all_used_quota = {}
            for _uq in _all_used_quota:
                _dict_all_used_quota[str(_uq.username)] = _uq.bytes

            del _all_used_quota

            # Generate new list to store quota <-> user map
            tmp_map = []
            for act in account_profiles:
                _ldif = iredutils.bytes2str(act[1])
                _mail = _ldif['mail'][0].lower()
                _quota = int(_ldif.get('mailQuota', [0])[0])

                if _quota > 0:
                    _used_quota = _dict_all_used_quota.get(_mail, 0)
                    _mailbox_usage_percent = '%2f' % (float(_used_quota) / _quota)
                else:
                    _mailbox_usage_percent = 0

                tmp_map.append((_mailbox_usage_percent, act))

                # Update total quota size
                _total_quota += _quota

            del _dict_all_used_quota

            if order_by_desc:
                tmp_map.sort(reverse=True)
            else:
                tmp_map.sort()

            account_profiles = [r[1] for r in tmp_map]
            del tmp_map

        elif order_name == 'name':
            # Generate new list to store name <-> user map
            tmp_map = []
            for act in account_profiles:
                (_dn, _ldif) = act
                _mail = _ldif['mail'][0]
                _name = _ldif.get('cn', [None])[0]
                if not _name:
                    # If no display name, use username part of email address instead.
                    _name = _mail.split('@', 1)[0]

                tmp_map.append((_name, act))

            if order_by_desc:
                tmp_map.sort(reverse=True)
            else:
                tmp_map.sort()

            account_profiles = [r[1] for r in tmp_map]
            del tmp_map
    else:
        # Sort accounts in place.
        account_profiles.sort()

    # Get account list used to display in current page.
    if size_limit < total < ((current_page - 1) * size_limit):
        result['account_profiles'] = account_profiles[-1:-size_limit]
    else:
        result['account_profiles'] = account_profiles[int((current_page - 1) * size_limit): int((current_page - 1) * size_limit + size_limit)]

    # Get total domain mailbox quota
    if account_type == 'user':
        if order_name == 'quota' and domain:
            pass
        else:
            counter = 0
            for i in account_profiles:
                # Get total quota of this domain
                quota = i[1].get('mailQuota', ['0'])[0]
                if quota.isdigit():
                    _total_quota += int(quota)
                    counter += 1

        # Update number of current domain quota size in LDAP (@attrs.ATTR_DOMAIN_CURRENT_QUOTA_SIZE).
        if domain:
            # Update number of current domain quota size in LDAP.
            dn_domain = ldaputils.rdn_value_to_domain_dn(domain)
            update_attr_with_single_value(dn=dn_domain,
                                          attr=attrs.ATTR_DOMAIN_CURRENT_QUOTA_SIZE,
                                          value=str(_total_quota),
                                          conn=conn)

    return result