mirror of
https://github.com/Mailu/Mailu.git
synced 2025-01-14 02:34:22 +02:00
Display the user quota in the admin interface
This commit is contained in:
parent
e13593f29a
commit
091369915b
@ -11,6 +11,7 @@ import os
|
||||
import docker
|
||||
import socket
|
||||
import uuid
|
||||
import redis
|
||||
|
||||
from werkzeug.contrib import fixers
|
||||
|
||||
@ -26,6 +27,7 @@ default_config = {
|
||||
'BABEL_DEFAULT_TIMEZONE': 'UTC',
|
||||
'BOOTSTRAP_SERVE_LOCAL': True,
|
||||
'RATELIMIT_STORAGE_URL': 'redis://redis/2',
|
||||
'QUOTA_STORAGE_URL': 'redis://redis/1',
|
||||
'DEBUG': False,
|
||||
'DOMAIN_REGISTRATION': False,
|
||||
# Statistics management
|
||||
@ -87,6 +89,9 @@ manager.add_command('db', flask_migrate.MigrateCommand)
|
||||
babel = flask_babel.Babel(app)
|
||||
translations = list(map(str, babel.list_translations()))
|
||||
|
||||
# Quota manager
|
||||
quota = redis.Redis.from_url(app.config.get("QUOTA_STORAGE_URL"))
|
||||
|
||||
@babel.localeselector
|
||||
def get_locale():
|
||||
return flask.request.accept_languages.best_match(translations)
|
||||
|
@ -1,4 +1,4 @@
|
||||
from mailu import app, db, dkim, login_manager
|
||||
from mailu import app, db, dkim, login_manager, quota
|
||||
|
||||
from sqlalchemy.ext import declarative
|
||||
from passlib import context, hash
|
||||
@ -20,9 +20,8 @@ class IdnaDomain(db.TypeDecorator):
|
||||
|
||||
impl = db.String(80)
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return idna.encode(value)
|
||||
return idna.encode(value).decode("ascii")
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return idna.decode(value)
|
||||
@ -34,31 +33,19 @@ class IdnaEmail(db.TypeDecorator):
|
||||
|
||||
impl = db.String(255, collation="NOCASE")
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
localpart, domain_name = value.split('@')
|
||||
|
||||
email = "{0}@{1}".format(
|
||||
return "{0}@{1}".format(
|
||||
localpart,
|
||||
idna.encode(domain_name).decode('ascii'),
|
||||
)
|
||||
return email
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
localpart, domain_name = value.split('@')
|
||||
|
||||
email = "{0}@{1}".format(
|
||||
return "{0}@{1}".format(
|
||||
localpart,
|
||||
idna.decode(domain_name),
|
||||
)
|
||||
return email
|
||||
|
||||
|
||||
# Many-to-many association table for domain managers
|
||||
managers = db.Table('manager',
|
||||
db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', IdnaEmail, db.ForeignKey('user.email'))
|
||||
)
|
||||
|
||||
|
||||
class CommaSeparatedList(db.TypeDecorator):
|
||||
@ -67,7 +54,6 @@ class CommaSeparatedList(db.TypeDecorator):
|
||||
|
||||
impl = db.String
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
if type(value) is not list:
|
||||
raise TypeError("Shoud be a list")
|
||||
@ -80,6 +66,13 @@ class CommaSeparatedList(db.TypeDecorator):
|
||||
return filter(bool, value.split(","))
|
||||
|
||||
|
||||
# Many-to-many association table for domain managers
|
||||
managers = db.Table('manager',
|
||||
db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', IdnaEmail, db.ForeignKey('user.email'))
|
||||
)
|
||||
|
||||
|
||||
class Base(db.Model):
|
||||
""" Base class for all models
|
||||
"""
|
||||
@ -264,6 +257,10 @@ class User(Base, Email):
|
||||
def get_id(self):
|
||||
return self.email
|
||||
|
||||
@property
|
||||
def quota_bytes_used(self):
|
||||
return quota.get(self.email) or 0
|
||||
|
||||
scheme_dict = {'SHA512-CRYPT': "sha512_crypt",
|
||||
'SHA256-CRYPT': "sha256_crypt",
|
||||
'MD5-CRYPT': "md5_crypt",
|
||||
|
@ -40,7 +40,7 @@
|
||||
{% if user.enable_imap %}<span class="label label-info">imap</span>{% endif %}
|
||||
{% if user.enable_pop %}<span class="label label-info">pop3</span>{% endif %}
|
||||
</td>
|
||||
<td>{{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }}</td>
|
||||
<td>{{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }}</td>
|
||||
<td>{{ user.comment or '-' }}</td>
|
||||
<td>{{ user.created_at }}</td>
|
||||
<td>{{ user.updated_at or '' }}</td>
|
||||
|
@ -5,7 +5,7 @@ log_path = /dev/stderr
|
||||
protocols = imap pop3 lmtp sieve
|
||||
postmaster_address = {{ POSTMASTER }}@{{ DOMAIN }}
|
||||
hostname = {{ HOSTNAMES.split(",")[0] }}
|
||||
mail_plugins = $mail_plugins quota
|
||||
mail_plugins = $mail_plugins quota quota_clone
|
||||
submission_host = front
|
||||
|
||||
service dict {
|
||||
@ -119,6 +119,7 @@ service lmtp {
|
||||
|
||||
plugin {
|
||||
quota = maildir:User quota
|
||||
quota_clone_dict = redis:host={{ REDIS_ADDRESS }}:db=1
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@ convert = lambda src, dst: open(dst, "w").write(jinja2.Template(open(src).read()
|
||||
|
||||
# Actual startup script
|
||||
os.environ["FRONT_ADDRESS"] = socket.gethostbyname("front")
|
||||
os.environ["REDIS_ADDRESS"] = socket.gethostbyname("redis")
|
||||
if os.environ["WEBMAIL"] != "none":
|
||||
os.environ["WEBMAIL_ADDRESS"] = socket.gethostbyname("webmail")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user