Related to #19, implement domain specific field and database type

master
Pierre Jaury 8 years ago
parent e471a252c8
commit 5f36e6f4f2

@ -1,6 +1,34 @@
from flask_wtf import Form
from wtforms import validators, fields, widgets
from wtforms_components import fields as fields_
from flask.ext import login as flask_login
import re
class DestinationField(fields.SelectMultipleField):
""" Allow for multiple emails selection from current user choices and
additional email addresses.
"""
validator = re.compile(r'^.+@([^.@][^@]+)$', re.IGNORECASE)
def iter_choices(self):
managed = [
str(email)
for email in flask_login.current_user.get_managed_emails()
]
for email in managed:
selected = self.data is not None and self.coerce(email) in self.data
yield (email, email, selected)
for email in self.data:
if email not in managed:
yield (email, email, True)
def pre_validate(self, form):
for item in self.data:
if not self.validator.match(item):
raise validators.ValidationError("Invalid email address.")
class LoginForm(Form):
@ -58,7 +86,7 @@ class UserReplyForm(Form):
class AliasForm(Form):
localpart = fields.StringField('Alias', [validators.DataRequired()])
destination = fields.SelectField('Destination')
destination = DestinationField('Destination')
comment = fields.StringField('Comment')
submit = fields.SubmitField('Create')

@ -18,6 +18,24 @@ managers = db.Table('manager',
)
class CommaSeparatedList(db.TypeDecorator):
""" Stores a list as a comma-separated string, compatible with Postfix.
"""
impl = db.String
def process_bind_param(self, value, dialect):
if type(value) is not list:
raise TypeError("Shoud be a list")
for item in value:
if "," in item:
raise ValueError("No item should contain a comma")
return ",".join(value)
def process_result_value(self, value, dialect):
return value.split(",")
class Base(db.Model):
""" Base class for all models
"""
@ -169,7 +187,7 @@ class Alias(Email):
""" An alias is an email address that redirects to some destination.
"""
domain = db.relationship(Domain, backref='aliases')
destination = db.Column(db.String(), nullable=False)
destination = db.Column(CommaSeparatedList, nullable=False)
class Fetch(Base):

@ -12,7 +12,7 @@ Create alias
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
{{ macros.form_field(form.destination, id='destination', multiple='multiple') }}
{{ macros.form_field(form.destination, id='destination') }}
{{ macros.form_field(form.comment) }}
{{ macros.form_field(form.submit) }}
<script>

@ -22,10 +22,6 @@ def alias_create(domain_name):
return flask.redirect(
flask.url_for('.alias_list', domain_name=domain.name))
form = forms.AliasForm()
form.destination.choices = [
(email.email, email.email) for email in
flask_login.current_user.get_managed_emails()
]
if form.validate_on_submit():
if domain.has_email(form.localpart.data):
flask.flash('Email is already used', 'error')
@ -46,10 +42,6 @@ def alias_create(domain_name):
def alias_edit(alias):
alias = utils.get_alias(alias)
form = forms.AliasForm(obj=alias)
form.destination.choices = [
(email.email, email.email) for email in
flask_login.current_user.get_managed_emails()
]
wtforms_components.read_only(form.localpart)
if form.validate_on_submit():
form.populate_obj(alias)

Loading…
Cancel
Save