mirror of
https://github.com/Mailu/Mailu.git
synced 2025-03-17 20:57:54 +02:00
Merge pull request #447 from sanduhrs/feature/446
Add a sqlalchemy custom type for unicode to idna conversion of domain names
This commit is contained in:
commit
dfaedb76f1
@ -11,12 +11,53 @@ import time
|
||||
import os
|
||||
import glob
|
||||
import smtplib
|
||||
import idna
|
||||
|
||||
|
||||
class IdnaDomain(db.TypeDecorator):
|
||||
""" Stores a Unicode string in it's IDNA representation (ASCII only)
|
||||
"""
|
||||
|
||||
impl = db.String(80)
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return idna.encode(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
return idna.decode(value)
|
||||
|
||||
|
||||
class IdnaEmail(db.TypeDecorator):
|
||||
""" Stores a Unicode string in it's IDNA representation (ASCII only)
|
||||
"""
|
||||
|
||||
impl = db.String(255, collation="NOCASE")
|
||||
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
localpart, domain_name = value.split('@')
|
||||
|
||||
email = "{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(
|
||||
localpart,
|
||||
idna.decode(domain_name),
|
||||
)
|
||||
return email
|
||||
|
||||
|
||||
# Many-to-many association table for domain managers
|
||||
managers = db.Table('manager',
|
||||
db.Column('domain_name', db.String(80), db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', db.String(255), db.ForeignKey('user.email'))
|
||||
db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')),
|
||||
db.Column('user_email', IdnaEmail, db.ForeignKey('user.email'))
|
||||
)
|
||||
|
||||
|
||||
@ -26,6 +67,7 @@ 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")
|
||||
@ -54,7 +96,7 @@ class Domain(Base):
|
||||
"""
|
||||
__tablename__ = "domain"
|
||||
|
||||
name = db.Column(db.String(80), primary_key=True, nullable=False)
|
||||
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)
|
||||
@ -110,8 +152,8 @@ class Alternative(Base):
|
||||
|
||||
__tablename__ = "alternative"
|
||||
|
||||
name = db.Column(db.String(80), primary_key=True, nullable=False)
|
||||
domain_name = db.Column(db.String(80), db.ForeignKey(Domain.name))
|
||||
name = db.Column(IdnaDomain, primary_key=True, nullable=False)
|
||||
domain_name = db.Column(IdnaDomain, db.ForeignKey(Domain.name))
|
||||
domain = db.relationship(Domain,
|
||||
backref=db.backref('alternatives', cascade='all, delete-orphan'))
|
||||
|
||||
@ -141,19 +183,19 @@ class Email(object):
|
||||
|
||||
@declarative.declared_attr
|
||||
def domain_name(cls):
|
||||
return db.Column(db.String(80), db.ForeignKey(Domain.name),
|
||||
nullable=False)
|
||||
return db.Column(IdnaDomain, db.ForeignKey(Domain.name),
|
||||
nullable=False, default=IdnaDomain)
|
||||
|
||||
# This field is redundant with both localpart and domain name.
|
||||
# It is however very useful for quick lookups without joining tables,
|
||||
# especially when the mail server il reading the database.
|
||||
# especially when the mail server is reading the database.
|
||||
@declarative.declared_attr
|
||||
def email(cls):
|
||||
updater = lambda context: "{0}@{1}".format(
|
||||
context.current_parameters["localpart"],
|
||||
context.current_parameters["domain_name"],
|
||||
)
|
||||
return db.Column(db.String(255, collation="NOCASE"),
|
||||
return db.Column(IdnaEmail,
|
||||
primary_key=True, nullable=False,
|
||||
default=updater)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user