|
|
@ -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 sqlalchemy.ext import declarative
|
|
|
|
from passlib import context, hash
|
|
|
|
from passlib import context, hash
|
|
|
@ -20,9 +20,8 @@ class IdnaDomain(db.TypeDecorator):
|
|
|
|
|
|
|
|
|
|
|
|
impl = db.String(80)
|
|
|
|
impl = db.String(80)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
return idna.encode(value)
|
|
|
|
return idna.encode(value).decode("ascii")
|
|
|
|
|
|
|
|
|
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
return idna.decode(value)
|
|
|
|
return idna.decode(value)
|
|
|
@ -34,31 +33,19 @@ class IdnaEmail(db.TypeDecorator):
|
|
|
|
|
|
|
|
|
|
|
|
impl = db.String(255, collation="NOCASE")
|
|
|
|
impl = db.String(255, collation="NOCASE")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
localpart, domain_name = value.split('@')
|
|
|
|
localpart, domain_name = value.split('@')
|
|
|
|
|
|
|
|
return "{0}@{1}".format(
|
|
|
|
email = "{0}@{1}".format(
|
|
|
|
|
|
|
|
localpart,
|
|
|
|
localpart,
|
|
|
|
idna.encode(domain_name).decode('ascii'),
|
|
|
|
idna.encode(domain_name).decode('ascii'),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return email
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
localpart, domain_name = value.split('@')
|
|
|
|
localpart, domain_name = value.split('@')
|
|
|
|
|
|
|
|
return "{0}@{1}".format(
|
|
|
|
email = "{0}@{1}".format(
|
|
|
|
|
|
|
|
localpart,
|
|
|
|
localpart,
|
|
|
|
idna.decode(domain_name),
|
|
|
|
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):
|
|
|
|
class CommaSeparatedList(db.TypeDecorator):
|
|
|
@ -67,7 +54,6 @@ class CommaSeparatedList(db.TypeDecorator):
|
|
|
|
|
|
|
|
|
|
|
|
impl = db.String
|
|
|
|
impl = db.String
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
if type(value) is not list:
|
|
|
|
if type(value) is not list:
|
|
|
|
raise TypeError("Shoud be a list")
|
|
|
|
raise TypeError("Shoud be a list")
|
|
|
@ -80,6 +66,13 @@ class CommaSeparatedList(db.TypeDecorator):
|
|
|
|
return filter(bool, value.split(","))
|
|
|
|
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):
|
|
|
|
class Base(db.Model):
|
|
|
|
""" Base class for all models
|
|
|
|
""" Base class for all models
|
|
|
|
"""
|
|
|
|
"""
|
|
|
@ -264,6 +257,10 @@ class User(Base, Email):
|
|
|
|
def get_id(self):
|
|
|
|
def get_id(self):
|
|
|
|
return self.email
|
|
|
|
return self.email
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
|
|
|
def quota_bytes_used(self):
|
|
|
|
|
|
|
|
return quota.get(self.email) or 0
|
|
|
|
|
|
|
|
|
|
|
|
scheme_dict = {'SHA512-CRYPT': "sha512_crypt",
|
|
|
|
scheme_dict = {'SHA512-CRYPT': "sha512_crypt",
|
|
|
|
'SHA256-CRYPT': "sha256_crypt",
|
|
|
|
'SHA256-CRYPT': "sha256_crypt",
|
|
|
|
'MD5-CRYPT': "md5_crypt",
|
|
|
|
'MD5-CRYPT': "md5_crypt",
|
|
|
|