You've already forked Mailu
							
							
				mirror of
				https://github.com/Mailu/Mailu.git
				synced 2025-10-30 23:37:43 +02:00 
			
		
		
		
	Implement a maximum quota per domain, fixes #106
This commit is contained in:
		| @@ -46,6 +46,7 @@ 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_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0) | ||||
|     comment = fields.StringField(_('Comment')) | ||||
|     submit = fields.SubmitField(_('Create')) | ||||
|  | ||||
|   | ||||
| @@ -57,6 +57,7 @@ class Domain(Base): | ||||
|         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_quota_bytes = db.Column(db.Integer(), nullable=False, default=0) | ||||
|  | ||||
|     @property | ||||
|     def dkim_key(self): | ||||
|   | ||||
| @@ -9,6 +9,9 @@ | ||||
|   {{ form.hidden_tag() }} | ||||
|   {{ macros.form_field(form.name) }} | ||||
|   {{ macros.form_fields((form.max_users, form.max_aliases)) }} | ||||
|   {{ macros.form_field(form.max_quota_bytes, step=1000000000, max=50000000000, | ||||
|       prepend='<span class="input-group-addon"><span id="quota">'+((form.max_quota_bytes.data//1000000000).__str__() if form.max_quota_bytes.data else '∞')+'</span> GiB</span>', | ||||
|       oninput='$("#quota").text(this.value == 0  ? "∞" : this.value/1000000000);') }} | ||||
|   {{ macros.form_field(form.comment) }} | ||||
|   {{ macros.form_field(form.submit) }} | ||||
| </form> | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|   {{ form.hidden_tag() }} | ||||
|   {{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }} | ||||
|   {{ macros.form_fields((form.pw, form.pw2)) }} | ||||
|   {{ macros.form_field(form.quota_bytes, step=1000000000, max=50000000000, | ||||
|   {{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50000000000), | ||||
|       prepend='<span class="input-group-addon"><span id="quota">'+(form.quota_bytes.data//1000000000).__str__()+'</span> GiB</span>', | ||||
|       oninput='$("#quota").text(this.value/1000000000);') }} | ||||
|   {{ macros.form_field(form.enable_imap) }} | ||||
|   | ||||
| @@ -2,6 +2,7 @@ from mailu.admin import app, db, models, forms, access | ||||
|  | ||||
| import flask | ||||
| import flask_login | ||||
| import wtforms | ||||
| import wtforms_components | ||||
|  | ||||
|  | ||||
| @@ -21,6 +22,8 @@ def user_create(domain_name): | ||||
|         return flask.redirect( | ||||
|             flask.url_for('.user_list', domain_name=domain.name)) | ||||
|     form = forms.UserForm() | ||||
|     form.quota_bytes.validators = [ | ||||
|         wtforms.validators.NumberRange(max=domain.max_quota_bytes)] | ||||
|     if form.validate_on_submit(): | ||||
|         if domain.has_email(form.localpart.data): | ||||
|             flask.flash('Email is already used', 'error') | ||||
| @@ -41,10 +44,17 @@ def user_create(domain_name): | ||||
| @access.domain_admin(models.User, 'user_email') | ||||
| def user_edit(user_email): | ||||
|     user = models.User.query.get(user_email) or flask.abort(404) | ||||
|     # Handle the case where user quota is more than allowed | ||||
|     max_quota_bytes = user.domain.max_quota_bytes | ||||
|     if max_quota_bytes and user.quota_bytes > max_quota_bytes: | ||||
|         max_quota_bytes = user.quota_bytes | ||||
|     # Create the form | ||||
|     form = forms.UserForm(obj=user) | ||||
|     wtforms_components.read_only(form.localpart) | ||||
|     form.pw.validators = [] | ||||
|     form.localpart.validators = [] | ||||
|     form.quota_bytes.validators = [ | ||||
|         wtforms.validators.NumberRange(max=max_quota_bytes)] | ||||
|     if form.validate_on_submit(): | ||||
|         form.populate_obj(user) | ||||
|         if form.pw.data: | ||||
| @@ -53,7 +63,8 @@ def user_edit(user_email): | ||||
|         flask.flash('User %s updated' % user) | ||||
|         return flask.redirect( | ||||
|             flask.url_for('.user_list', domain_name=user.domain.name)) | ||||
|     return flask.render_template('user/edit.html', form=form, user=user, domain=user.domain) | ||||
|     return flask.render_template('user/edit.html', form=form, user=user, | ||||
|         domain=user.domain, max_quota_bytes=max_quota_bytes) | ||||
|  | ||||
|  | ||||
| @app.route('/user/delete/<user_email>', methods=['GET', 'POST']) | ||||
|   | ||||
							
								
								
									
										23
									
								
								admin/migrations/versions/2335c80a6bc3_.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								admin/migrations/versions/2335c80a6bc3_.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| """ Add a maximum quota per domain | ||||
|  | ||||
| Revision ID: 2335c80a6bc3 | ||||
| Revises: 12e9a4f6ed73 | ||||
| Create Date: 2016-12-04 12:57:37.576622 | ||||
|  | ||||
| """ | ||||
|  | ||||
| # revision identifiers, used by Alembic. | ||||
| revision = '2335c80a6bc3' | ||||
| down_revision = '12e9a4f6ed73' | ||||
|  | ||||
| from alembic import op | ||||
| import sqlalchemy as sa | ||||
|  | ||||
|  | ||||
| def upgrade(): | ||||
|     op.add_column('domain', sa.Column('max_quota_bytes', sa.Integer(), nullable=False, server_default='0')) | ||||
|  | ||||
|  | ||||
| def downgrade(): | ||||
|     with op.batch_alter_table('domain') as batch: | ||||
|         batch.drop_column('max_quota_bytes') | ||||
		Reference in New Issue
	
	Block a user