Пример #1
0
def admin(localpart, domain_name, password, mode='create'):
    """ Create an admin user
        'mode' can be:
            - 'create' (default) Will try to create user and will raise an exception if present
            - 'ifmissing': if user exists, nothing happens, else it will be created
            - 'update': user is created or, if it exists, its password gets updated
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)

    user = None
    if mode == 'ifmissing' or mode == 'update':
        email = '{}@{}'.format(localpart, domain_name)
        user = models.User.query.get(email)

        if user and mode == 'ifmissing':
            print('user %s exists, not updating' % email)
            return

    if not user:
        user = models.User(localpart=localpart,
                           domain=domain,
                           global_admin=True)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        print("created admin user")
    elif mode == 'update':
        user.set_password(password)
        db.session.commit()
        print("updated admin password")
Пример #2
0
def domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0):
    """ Create a domain
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name, max_users=max_users,
                               max_aliases=max_aliases, max_quota_bytes=max_quota_bytes)
        db.session.add(domain)
        db.session.commit()
Пример #3
0
def admin(localpart, domain_name, password):
    """ Create an admin user
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    user = models.User(localpart=localpart, domain=domain, global_admin=True)
    user.set_password(password)
    db.session.add(user)
    db.session.commit()
Пример #4
0
def user_import(localpart, domain_name, password_hash):
    """ Import a user along with password hash
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    user = models.User(localpart=localpart, domain=domain, global_admin=False)
    user.set_password(password_hash, raw=True)
    db.session.add(user)
    db.session.commit()
Пример #5
0
def alias(localpart, domain_name, destination):
    """ Create an alias
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    alias = models.Alias(localpart=localpart,
                         domain=domain,
                         destination=destination.split(','),
                         email="%s@%s" % (localpart, domain_name))
    db.session.add(alias)
    db.session.commit()
Пример #6
0
def user(localpart, domain_name, password, hash_scheme=None):
    """ Create a user
    """
    if hash_scheme is None:
        hash_scheme = app.config['PASSWORD_SCHEME']
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    user = models.User(localpart=localpart, domain=domain, global_admin=False)
    user.set_password(password, hash_scheme=hash_scheme)
    db.session.add(user)
    db.session.commit()
Пример #7
0
def user_import(localpart, domain_name, password_hash, hash_scheme=None):
    """ Import a user along with password hash.
    """
    if hash_scheme is None:
        hash_scheme = app.config['PASSWORD_SCHEME']
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    user = models.User(localpart=localpart, domain=domain, global_admin=False)
    user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)
    db.session.add(user)
    db.session.commit()
Пример #8
0
def alias(localpart, domain_name, destination, wildcard=False):
    """ Create an alias
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    alias = models.Alias(localpart=localpart,
                         domain=domain,
                         wildcard=wildcard,
                         destination=destination.split(','),
                         email=f'{localpart}@{domain_name}')
    db.session.add(alias)
    db.session.commit()
Пример #9
0
def domain_create():
    form = forms.DomainForm()
    if form.validate_on_submit():
        conflicting_domain = models.Domain.query.get(form.name.data)
        conflicting_alternative = models.Alternative.query.get(form.name.data)
        conflicting_relay = models.Relay.query.get(form.name.data)
        if conflicting_domain or conflicting_alternative or conflicting_relay:
            flask.flash('Domain %s is already used' % form.name.data, 'error')
        else:
            domain = models.Domain()
            form.populate_obj(domain)
            db.session.add(domain)
            db.session.commit()
            flask.flash('Domain %s created' % domain)
            return flask.redirect(flask.url_for('.domain_list'))
    return flask.render_template('domain/create.html', form=form)
Пример #10
0
def domain_signup(domain_name=None):
    if not app.config['DOMAIN_REGISTRATION']:
        flask.abort(403)
    form = forms.DomainSignupForm()
    if flask_login.current_user.is_authenticated:
        del form.localpart
        del form.pw
        del form.pw2
    if form.validate_on_submit():
        conflicting_domain = models.Domain.query.get(form.name.data)
        conflicting_alternative = models.Alternative.query.get(form.name.data)
        conflicting_relay = models.Relay.query.get(form.name.data)
        hostnames = app.config['HOSTNAMES'].split(',')
        if conflicting_domain or conflicting_alternative or conflicting_relay:
            flask.flash('Domain %s is already used' % form.name.data, 'error')
        else:
            # Check if the domain MX actually points to this server
            try:
                mxok = any(str(rset).split()[-1][:-1] in hostnames
                           for rset in dns.resolver.query(form.name.data, 'MX'))
            except Exception as e:
                mxok = False
            if mxok:
                # Actually create the domain
                domain = models.Domain()
                form.populate_obj(domain)
                domain.max_quota_bytes = app.config['DEFAULT_QUOTA']
                domain.max_users = 10
                domain.max_aliases = 10
                db.session.add(domain)
                if flask_login.current_user.is_authenticated:
                    user = models.User.query.get(flask_login.current_user.email)
                else:
                    user = models.User()
                    user.domain = domain
                    form.populate_obj(user)
                    user.set_password(form.pw.data)
                    user.quota_bytes = domain.max_quota_bytes
                db.session.add(user)
                domain.managers.append(user)
                db.session.commit()
                flask.flash('Domain %s created' % domain)
                return flask.redirect(flask.url_for('.domain_list'))
            else:
                flask.flash('The MX record was not properly set', 'error')
    return flask.render_template('domain/signup.html', form=form)
Пример #11
0
def user_import(localpart,
                domain_name,
                password_hash,
                hash_scheme=app.config['PASSWORD_SCHEME']):
    """ Import a user along with password hash. Available hashes:
                   'SHA512-CRYPT'
                   'SHA256-CRYPT'
                   'MD5-CRYPT'
                   'CRYPT'
    """
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
    user = models.User(localpart=localpart, domain=domain, global_admin=False)
    user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)
    db.session.add(user)
    db.session.commit()
Пример #12
0
def domain_signup(domain_name=None):
    if not app.config['DOMAIN_REGISTRATION']:
        flask.abort(403)
    form = forms.DomainSignupForm()
    if flask_login.current_user.is_authenticated:
        del form.localpart
        del form.pw
        del form.pw2
    if form.validate_on_submit():
        conflicting_domain = models.Domain.query.get(form.name.data)
        conflicting_alternative = models.Alternative.query.get(form.name.data)
        conflicting_relay = models.Relay.query.get(form.name.data)
        if conflicting_domain or conflicting_alternative or conflicting_relay:
            flask.flash('Domain %s is already used' % form.name.data, 'error')
        else:
            domain = models.Domain()
            form.populate_obj(domain)
            domain.max_quota_bytes = app.config['DEFAULT_QUOTA']
            domain.max_users = 10
            domain.max_aliases = 10
            if domain.check_mx():
                models.db.session.add(domain)
                if flask_login.current_user.is_authenticated:
                    user = models.User.query.get(
                        flask_login.current_user.email)
                else:
                    user = models.User()
                    user.domain = domain
                    form.populate_obj(user)
                    user.set_password(form.pw.data)
                    user.quota_bytes = domain.max_quota_bytes
                models.db.session.add(user)
                domain.managers.append(user)
                models.db.session.commit()
                flask.flash('Domain %s created' % domain)
                return flask.redirect(flask.url_for('.domain_list'))
            else:
                flask.flash('The MX record was not properly set', 'error')
    return flask.render_template('domain/signup.html', form=form)
Пример #13
0
def admin(localpart, domain_name, password, mode):
    """ Create an admin user
    """

    if not mode in ('create', 'update', 'ifmissing'):
        raise click.ClickException(f'invalid mode: {mode!r}')

    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)

    email = f'{localpart}@{domain_name}'
    if user := models.User.query.get(email):
        if mode == 'ifmissing':
            print(f'user {email!r} exists, not updating')
            return
        elif mode == 'update':
            user.set_password(password)
            db.session.commit()
            print("updated admin password")
        else:
            raise click.ClickException(f'user {email!r} exists, not created')
Пример #14
0
def config_update(verbose=False, delete_objects=False):
    """sync configuration with data from YAML-formatted stdin"""
    import yaml
    import sys
    new_config = yaml.load(sys.stdin)
    # print new_config
    domains = new_config.get('domains', [])
    tracked_domains = set()
    for domain_config in domains:
        if verbose:
            print(str(domain_config))
        domain_name = domain_config['name']
        max_users = domain_config.get('max_users', 0)
        max_aliases = domain_config.get('max_aliases', 0)
        max_quota_bytes = domain_config.get('max_quota_bytes', 0)
        tracked_domains.add(domain_name)
        domain = models.Domain.query.get(domain_name)
        if not domain:
            domain = models.Domain(name=domain_name,
                                   max_users=max_users,
                                   max_aliases=max_aliases,
                                   max_quota_bytes=max_quota_bytes)
            db.session.add(domain)
            print("Added " + str(domain_config))
        else:
            domain.max_users = max_users
            domain.max_aliases = max_aliases
            domain.max_quota_bytes = max_quota_bytes
            db.session.add(domain)
            print("Updated " + str(domain_config))

    users = new_config.get('users', [])
    tracked_users = set()
    user_optional_params = ('comment', 'quota_bytes', 'global_admin',
                            'enable_imap', 'enable_pop', 'forward_enabled',
                            'forward_destination', 'reply_enabled',
                            'reply_subject', 'reply_body', 'displayed_name',
                            'spam_enabled', 'email', 'spam_threshold')
    for user_config in users:
        if verbose:
            print(str(user_config))
        localpart = user_config['localpart']
        domain_name = user_config['domain']
        password_hash = user_config.get('password_hash', None)
        hash_scheme = user_config.get('hash_scheme', None)
        domain = models.Domain.query.get(domain_name)
        email = '{0}@{1}'.format(localpart, domain_name)
        optional_params = {}
        for k in user_optional_params:
            if k in user_config:
                optional_params[k] = user_config[k]
        if not domain:
            domain = models.Domain(name=domain_name)
            db.session.add(domain)
        user = models.User.query.get(email)
        tracked_users.add(email)
        tracked_domains.add(domain_name)
        if not user:
            user = models.User(localpart=localpart,
                               domain=domain,
                               **optional_params)
        else:
            for k in optional_params:
                setattr(user, k, optional_params[k])
        user.set_password(password_hash, hash_scheme=hash_scheme, raw=True)
        db.session.add(user)

    aliases = new_config.get('aliases', [])
    tracked_aliases = set()
    for alias_config in aliases:
        if verbose:
            print(str(alias_config))
        localpart = alias_config['localpart']
        domain_name = alias_config['domain']
        if type(alias_config['destination']) is str:
            destination = alias_config['destination'].split(',')
        else:
            destination = alias_config['destination']
        wildcard = alias_config.get('wildcard', False)
        domain = models.Domain.query.get(domain_name)
        email = '{0}@{1}'.format(localpart, domain_name)
        if not domain:
            domain = models.Domain(name=domain_name)
            db.session.add(domain)
        alias = models.Alias.query.get(email)
        tracked_aliases.add(email)
        tracked_domains.add(domain_name)
        if not alias:
            alias = models.Alias(localpart=localpart,
                                 domain=domain,
                                 wildcard=wildcard,
                                 destination=destination,
                                 email=email)
        else:
            alias.destination = destination
            alias.wildcard = wildcard
        db.session.add(alias)

    db.session.commit()

    managers = new_config.get('managers', [])
    # tracked_managers=set()
    for manager_config in managers:
        if verbose:
            print(str(manager_config))
        domain_name = manager_config['domain']
        user_name = manager_config['user']
        domain = models.Domain.query.get(domain_name)
        manageruser = models.User.query.get(user_name + '@' + domain_name)
        if manageruser not in domain.managers:
            domain.managers.append(manageruser)
        db.session.add(domain)

    db.session.commit()

    if delete_objects:
        for user in db.session.query(models.User).all():
            if not (user.email in tracked_users):
                if verbose:
                    print("Deleting user: "******"Deleting alias: " + str(alias.email))
                db.session.delete(alias)
        for domain in db.session.query(models.Domain).all():
            if not (domain.name in tracked_domains):
                if verbose:
                    print("Deleting domain: " + str(domain.name))
                db.session.delete(domain)
    db.session.commit()
Пример #15
0
def domain(domain_name, max_users=0, max_aliases=0, max_quota_bytes=0):
    domain = models.Domain.query.get(domain_name)
    if not domain:
        domain = models.Domain(name=domain_name)
        db.session.add(domain)
        db.session.commit()
Пример #16
0
def config_update(verbose=False, delete_objects=False):
    """ Sync configuration with data from YAML (deprecated)
    """
    new_config = yaml.safe_load(sys.stdin)
    # print new_config
    domains = new_config.get('domains', [])
    tracked_domains = set()
    for domain_config in domains:
        if verbose:
            print(str(domain_config))
        domain_name = domain_config['name']
        max_users = domain_config.get('max_users', -1)
        max_aliases = domain_config.get('max_aliases', -1)
        max_quota_bytes = domain_config.get('max_quota_bytes', 0)
        tracked_domains.add(domain_name)
        domain = models.Domain.query.get(domain_name)
        if not domain:
            domain = models.Domain(name=domain_name,
                                   max_users=max_users,
                                   max_aliases=max_aliases,
                                   max_quota_bytes=max_quota_bytes)
            db.session.add(domain)
            print(f'Added {domain_config}')
        else:
            domain.max_users = max_users
            domain.max_aliases = max_aliases
            domain.max_quota_bytes = max_quota_bytes
            db.session.add(domain)
            print(f'Updated {domain_config}')

    users = new_config.get('users', [])
    tracked_users = set()
    user_optional_params = ('comment', 'quota_bytes', 'global_admin',
                            'enable_imap', 'enable_pop', 'forward_enabled',
                            'forward_destination', 'reply_enabled',
                            'reply_subject', 'reply_body', 'displayed_name',
                            'spam_enabled', 'email', 'spam_threshold')
    for user_config in users:
        if verbose:
            print(str(user_config))
        localpart = user_config['localpart']
        domain_name = user_config['domain']
        password_hash = user_config.get('password_hash', None)
        domain = models.Domain.query.get(domain_name)
        email = f'{localpart}@{domain_name}'
        optional_params = {}
        for k in user_optional_params:
            if k in user_config:
                optional_params[k] = user_config[k]
        if not domain:
            domain = models.Domain(name=domain_name)
            db.session.add(domain)
        user = models.User.query.get(email)
        tracked_users.add(email)
        tracked_domains.add(domain_name)
        if not user:
            user = models.User(localpart=localpart,
                               domain=domain,
                               **optional_params)
        else:
            for k in optional_params:
                setattr(user, k, optional_params[k])
        user.set_password(password_hash, raw=True)
        db.session.add(user)

    aliases = new_config.get('aliases', [])
    tracked_aliases = set()
    for alias_config in aliases:
        if verbose:
            print(str(alias_config))
        localpart = alias_config['localpart']
        domain_name = alias_config['domain']
        if isinstance(alias_config['destination'], str):
            destination = alias_config['destination'].split(',')
        else:
            destination = alias_config['destination']
        wildcard = alias_config.get('wildcard', False)
        domain = models.Domain.query.get(domain_name)
        email = f'{localpart}@{domain_name}'
        if not domain:
            domain = models.Domain(name=domain_name)
            db.session.add(domain)
        alias = models.Alias.query.get(email)
        tracked_aliases.add(email)
        tracked_domains.add(domain_name)
        if not alias:
            alias = models.Alias(localpart=localpart,
                                 domain=domain,
                                 wildcard=wildcard,
                                 destination=destination,
                                 email=email)
        else:
            alias.destination = destination
            alias.wildcard = wildcard
        db.session.add(alias)

    db.session.commit()

    managers = new_config.get('managers', [])
    # tracked_managers=set()
    for manager_config in managers:
        if verbose:
            print(str(manager_config))
        domain_name = manager_config['domain']
        user_name = manager_config['user']
        domain = models.Domain.query.get(domain_name)
        manageruser = models.User.query.get(f'{user_name}@{domain_name}')
        if manageruser not in domain.managers:
            domain.managers.append(manageruser)
        db.session.add(domain)

    db.session.commit()

    if delete_objects:
        for user in db.session.query(models.User).all():
            if not user.email in tracked_users:
                if verbose:
                    print(f'Deleting user: {user.email}')
                db.session.delete(user)
        for alias in db.session.query(models.Alias).all():
            if not alias.email in tracked_aliases:
                if verbose:
                    print(f'Deleting alias: {alias.email}')
                db.session.delete(alias)
        for domain in db.session.query(models.Domain).all():
            if not domain.name in tracked_domains:
                if verbose:
                    print(f'Deleting domain: {domain.name}')
                db.session.delete(domain)
    db.session.commit()