From dda64fe91ed008dd4cf8dbd73e7060486797897d Mon Sep 17 00:00:00 2001 From: hoellen Date: Sat, 5 Jan 2019 13:45:55 +0100 Subject: [PATCH 1/3] allow to disable aliases or users for domains and don't allow negativ values on domain creation/edit --- core/admin/mailu/manage.py | 6 +++--- core/admin/mailu/models.py | 4 ++-- core/admin/mailu/ui/forms.py | 4 ++-- core/admin/mailu/ui/templates/domain/list.html | 4 ++-- core/admin/mailu/ui/templates/user/signup_domain.html | 2 +- core/admin/mailu/ui/views/aliases.py | 2 +- core/admin/mailu/ui/views/users.py | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/admin/mailu/manage.py b/core/admin/mailu/manage.py index 7f32f6c8..4846c2d6 100644 --- a/core/admin/mailu/manage.py +++ b/core/admin/mailu/manage.py @@ -91,7 +91,7 @@ def user(localpart, domain_name, password, hash_scheme=None): @click.option('-a', '--max_aliases') @click.option('-q', '--max_quota_bytes') @flask_cli.with_appcontext -def domain(domain_name, max_users=0, max_aliases=0, max_quota_bytes=0): +def domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0): domain = models.Domain.query.get(domain_name) if not domain: domain = models.Domain(name=domain_name) @@ -140,8 +140,8 @@ def config_update(verbose=False, delete_objects=False): 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_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) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 30a2ed64..3588b4ae 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -122,8 +122,8 @@ class Domain(Base): name = db.Column(IdnaDomain, primary_key=True, nullable=False) managers = db.relationship('User', secondary=managers, backref=db.backref('manager_of'), lazy='dynamic') - max_users = db.Column(db.Integer, nullable=False, default=0) - max_aliases = db.Column(db.Integer, nullable=False, default=0) + max_users = db.Column(db.Integer, nullable=False, default=-1) + max_aliases = db.Column(db.Integer, nullable=False, default=-1) max_quota_bytes = db.Column(db.Integer(), nullable=False, default=0) signup_enabled = db.Column(db.Boolean(), nullable=False, default=False) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index 5ee6da7d..04597872 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -53,8 +53,8 @@ class LoginForm(flask_wtf.FlaskForm): class DomainForm(flask_wtf.FlaskForm): name = fields.StringField(_('Domain name'), [validators.DataRequired()]) - max_users = fields_.IntegerField(_('Maximum user count'), default=10) - max_aliases = fields_.IntegerField(_('Maximum alias count'), default=10) + max_users = fields_.IntegerField(_('Maximum user count'), [validators.NumberRange(min=-1)], default=10) + max_aliases = fields_.IntegerField(_('Maximum alias count'), [validators.NumberRange(min=-1)], default=10) max_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0) signup_enabled = fields.BooleanField(_('Enable sign-up'), default=False) comment = fields.StringField(_('Comment')) diff --git a/core/admin/mailu/ui/templates/domain/list.html b/core/admin/mailu/ui/templates/domain/list.html index 0fa54f4f..2431faa5 100644 --- a/core/admin/mailu/ui/templates/domain/list.html +++ b/core/admin/mailu/ui/templates/domain/list.html @@ -40,8 +40,8 @@ {% endif %} {{ domain.name }} - {{ domain.users | count }} / {{ domain.max_users or '∞' }} - {{ domain.aliases | count }} / {{ domain.max_aliases or '∞' }} + {{ domain.users | count }} / {{ '∞' if domain.max_users == -1 else domain.max_users }} + {{ domain.aliases | count }} / {{ '∞' if domain.max_aliases == -1 else domain.max_aliases }} {{ domain.comment or '' }} {{ domain.created_at }} {{ domain.updated_at or '' }} diff --git a/core/admin/mailu/ui/templates/user/signup_domain.html b/core/admin/mailu/ui/templates/user/signup_domain.html index 84f33b3d..1cb65ae8 100644 --- a/core/admin/mailu/ui/templates/user/signup_domain.html +++ b/core/admin/mailu/ui/templates/user/signup_domain.html @@ -18,7 +18,7 @@ {% for domain_name, domain in available_domains.items() %} {{ domain_name }} - {{ domain.max_users - (domain.users | count) if domain.max_users else '∞' }} + {{ '∞' if domain.max_users == -1 else domain.max_users - (domain.users | count)}} {{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }} {% endfor %} diff --git a/core/admin/mailu/ui/views/aliases.py b/core/admin/mailu/ui/views/aliases.py index 5e65c86d..bd3da3dc 100644 --- a/core/admin/mailu/ui/views/aliases.py +++ b/core/admin/mailu/ui/views/aliases.py @@ -16,7 +16,7 @@ def alias_list(domain_name): @access.domain_admin(models.Domain, 'domain_name') def alias_create(domain_name): domain = models.Domain.query.get(domain_name) or flask.abort(404) - if domain.max_aliases and len(domain.aliases) >= domain.max_aliases: + if not domain.max_aliases == -1 and len(domain.aliases) >= domain.max_aliases: flask.flash('Too many aliases for domain %s' % domain, 'error') return flask.redirect( flask.url_for('.alias_list', domain_name=domain.name)) diff --git a/core/admin/mailu/ui/views/users.py b/core/admin/mailu/ui/views/users.py index e3c03848..42eb6c05 100644 --- a/core/admin/mailu/ui/views/users.py +++ b/core/admin/mailu/ui/views/users.py @@ -18,7 +18,7 @@ def user_list(domain_name): @access.domain_admin(models.Domain, 'domain_name') def user_create(domain_name): domain = models.Domain.query.get(domain_name) or flask.abort(404) - if domain.max_users and len(domain.users) >= domain.max_users: + if not domain.max_users == -1 and len(domain.users) >= domain.max_users: flask.flash('Too many users for domain %s' % domain, 'error') return flask.redirect( flask.url_for('.user_list', domain_name=domain.name)) @@ -168,7 +168,7 @@ def user_signup(domain_name=None): available_domains = { domain.name: domain for domain in models.Domain.query.filter_by(signup_enabled=True).all() - if not domain.max_users or len(domain.users) < domain.max_users + if domain.max_users == -1 or len(domain.users) < domain.max_users } if not available_domains: flask.flash('No domain available for registration') From 78f544c678ae5bf08c411454412f33e2609c8606 Mon Sep 17 00:00:00 2001 From: hoellen Date: Sat, 5 Jan 2019 14:15:49 +0100 Subject: [PATCH 2/3] update changelog for #799 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 93b51220..d925b50d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ v1.6.0 - unreleased - Enhancement: Contribution documentation ([#700](https://github.com/Mailu/Mailu/issues/700)) - Enhancement: Move Mailu Docker network to a fixed subnet ([#727](https://github.com/Mailu/Mailu/issues/727)) - Enhancement: Added regex validation for alias username ([#764](https://github.com/Mailu/Mailu/issues/764)) +- Enhancement: Allow to disable aliases or users for a specific domain ([#799](https://github.com/Mailu/Mailu/issues/799)) - Enhancement: Update documentation - Upstream: Update Roundcube - Upstream: Update Rainloop @@ -108,6 +109,7 @@ v1.6.0 - unreleased - Bug: Error when trying to log in with an account without domain ([#585](https://github.com/Mailu/Mailu/issues/585)) - Bug: Fix rainloop permissions ([#637](https://github.com/Mailu/Mailu/issues/637)) - Bug: Fix broken webmail and logo url in admin ([#792](https://github.com/Mailu/Mailu/issues/792)) +- Bug: Don't allow negative values on domain creation/edit ([#799](https://github.com/Mailu/Mailu/issues/799)) v1.5.1 - 2017-11-21 ------------------- From 501ecf13c1b676617a2e706bb41ea1f229a69975 Mon Sep 17 00:00:00 2001 From: hoellen Date: Sun, 6 Jan 2019 15:36:57 +0100 Subject: [PATCH 3/3] add migration script --- .../migrations/versions/fc099bd15cbe_.py | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 core/admin/migrations/versions/fc099bd15cbe_.py diff --git a/core/admin/migrations/versions/fc099bd15cbe_.py b/core/admin/migrations/versions/fc099bd15cbe_.py new file mode 100644 index 00000000..d20f9181 --- /dev/null +++ b/core/admin/migrations/versions/fc099bd15cbe_.py @@ -0,0 +1,65 @@ +"""change default unlimited value for max_users and max_aliases to -1 + +Revision ID: fc099bd15cbe +Revises: cd79ed46d9c2 +Create Date: 2019-01-06 13:40:23.372373 + +""" + +# revision identifiers, used by Alembic. +revision = 'fc099bd15cbe' +down_revision = 'cd79ed46d9c2' + +from alembic import op +import sqlalchemy as sa + + +domain_table = sa.Table( + 'domain', + sa.MetaData(), + sa.Column('max_users', sa.Integer(), nullable=False), + sa.Column('max_aliases', sa.Integer(), nullable=False), +) + + +def upgrade(): + connection = op.get_bind() + connection.execute( + domain_table.update().where( + domain_table.c.max_users == 0 + ).values( + max_users=-1 + ) + ) + connection.execute( + domain_table.update().where( + domain_table.c.max_aliases == 0 + ).values( + max_aliases=-1 + ) + ) + #set new unlimited default to -1 + with op.batch_alter_table('domain') as batch: + batch.alter_column('max_users', server_default='-1') + batch.alter_column('max_aliases', server_default='-1') + +def downgrade(): + connection = op.get_bind() + connection.execute( + domain_table.update().where( + domain_table.c.max_users == -1 + ).values( + max_users=0 + ) + ) + connection.execute( + domain_table.update().where( + domain_table.c.max_aliases == -1 + ).values( + max_aliases=0 + ) + ) + #set default to 0 + with op.batch_alter_table('domain') as batch: + batch.alter_column('max_users', server_default='0') + batch.alter_column('max_aliases', server_default='0')