Rename the generic 'address' to 'email'

master
Pierre Jaury 9 years ago
parent 5343a397ff
commit 3eca6864c3

@ -64,12 +64,12 @@ class AliasForm(Form):
class AdminForm(Form): class AdminForm(Form):
admin = fields.StringField('Admin address', [validators.Email()]) admin = fields.StringField('Admin email', [validators.Email()])
submit = fields.SubmitField('Submit') submit = fields.SubmitField('Submit')
class ManagerForm(Form): class ManagerForm(Form):
manager = fields.StringField('Manager address', [validators.Email()]) manager = fields.StringField('Manager email', [validators.Email()])
submit = fields.SubmitField('Submit') submit = fields.SubmitField('Submit')

@ -10,7 +10,7 @@ import re
# Many-to-many association table for domain managers # Many-to-many association table for domain managers
managers = db.Table('manager', managers = db.Table('manager',
db.Column('domain_name', db.String(80), db.ForeignKey('domain.name')), db.Column('domain_name', db.String(80), db.ForeignKey('domain.name')),
db.Column('user_address', db.String(255), db.ForeignKey('user.address')) db.Column('user_email', db.String(255), db.ForeignKey('user.email'))
) )
@ -34,9 +34,9 @@ class Domain(Base):
max_users = db.Column(db.Integer, nullable=False, default=0) max_users = db.Column(db.Integer, nullable=False, default=0)
max_aliases = db.Column(db.Integer, nullable=False, default=0) max_aliases = db.Column(db.Integer, nullable=False, default=0)
def has_address(self, localpart): def has_email(self, localpart):
for address in self.users + self.aliases: for email in self.users + self.aliases:
if address.localpart == localpart: if email.localpart == localpart:
return True return True
else: else:
return False return False
@ -45,8 +45,8 @@ class Domain(Base):
return self.name return self.name
class Address(Base): class Email(Base):
""" Abstraction for a mail address (localpart and domain). """ Abstraction for an email address (localpart and domain).
""" """
__abstract__ = True __abstract__ = True
@ -61,7 +61,7 @@ class Address(Base):
# It is however very useful for quick lookups without joining tables, # 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 il reading the database.
@declarative.declared_attr @declarative.declared_attr
def address(cls): def email(cls):
updater = lambda context: "{0}@{1}".format( updater = lambda context: "{0}@{1}".format(
context.current_parameters["localpart"], context.current_parameters["localpart"],
context.current_parameters["domain_name"], context.current_parameters["domain_name"],
@ -72,14 +72,14 @@ class Address(Base):
@classmethod @classmethod
def get_by_email(cls, email): def get_by_email(cls, email):
return cls.query.filter_by(address=email).first() return cls.query.filter_by(email=email).first()
def __str__(self): def __str__(self):
return self.address return self.email
class User(Address): class User(Email):
""" A user is a mail address that has a password to access a mailbox. """ A user is an email address that has a password to access a mailbox.
""" """
domain = db.relationship(Domain, backref='users') domain = db.relationship(Domain, backref='users')
password = db.Column(db.String(255), nullable=False) password = db.Column(db.String(255), nullable=False)
@ -106,7 +106,7 @@ class User(Address):
is_anonymous = False is_anonymous = False
def get_id(self): def get_id(self):
return self.address return self.email
pw_context = context.CryptContext( pw_context = context.CryptContext(
["sha512_crypt", "sha256_crypt", "md5_crypt"] ["sha512_crypt", "sha256_crypt", "md5_crypt"]
@ -125,12 +125,12 @@ class User(Address):
else: else:
return self.manager_of return self.manager_of
def get_managed_addresses(self): def get_managed_emails(self):
addresses = [] emails = []
for domain in self.get_managed_domains(): for domain in self.get_managed_domains():
addresses.extend(domain.users) emails.extend(domain.users)
addresses.extend(domain.aliases) emails.extend(domain.aliases)
return addresses return emails
@classmethod @classmethod
def login(cls, email, password): def login(cls, email, password):
@ -138,8 +138,8 @@ class User(Address):
return user if (user and user.check_password(password)) else None return user if (user and user.check_password(password)) else None
class Alias(Address): class Alias(Email):
""" An alias is a mail address that redirects to some other addresses. """ An alias is an email address that redirects to some destination.
""" """
domain = db.relationship(Domain, backref='aliases') domain = db.relationship(Domain, backref='aliases')
destination = db.Column(db.String(), nullable=False) destination = db.Column(db.String(), nullable=False)
@ -150,7 +150,7 @@ class Fetch(Base):
account. account.
""" """
id = db.Column(db.Integer(), primary_key=True) id = db.Column(db.Integer(), primary_key=True)
user_address = db.Column(db.String(255), db.ForeignKey(User.address), user_email = db.Column(db.String(255), db.ForeignKey(User.email),
nullable=False) nullable=False)
user = db.relationship(User, backref='fetches') user = db.relationship(User, backref='fetches')
protocol = db.Column(db.Enum('imap', 'pop3'), nullable=False) protocol = db.Column(db.Enum('imap', 'pop3'), nullable=False)

@ -15,7 +15,7 @@ Add a global administrator
tagClass: 'label label-primary large', tagClass: 'label label-primary large',
typeahead: { typeahead: {
afterSelect: function(val) { this.$element.val(""); }, afterSelect: function(val) { this.$element.val(""); },
source: {{ current_user.get_managed_addresses()|map('string')|list|tojson }} source: {{ current_user.get_managed_emails()|map('string')|list|tojson }}
} }
}); });
</script> </script>

@ -13,14 +13,14 @@ Global administrators
<tbody> <tbody>
<tr> <tr>
<th>Actions</th> <th>Actions</th>
<th>Address</th> <th>Email</th>
<th>Created</th> <th>Created</th>
<th>Last edit</th> <th>Last edit</th>
</tr> </tr>
{% for admin in admins %} {% for admin in admins %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('.admin_delete', admin=admin.address) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a> <a href="{{ url_for('.admin_delete', admin=admin.email) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a>
</td> </td>
<td>{{ admin }}</td> <td>{{ admin }}</td>
<td>{{ admin.created_at }}</td> <td>{{ admin.created_at }}</td>

@ -21,7 +21,7 @@ Create alias
tagClass: 'label label-primary large', tagClass: 'label label-primary large',
typeahead: { typeahead: {
afterSelect: function(val) { this.$element.val(""); }, afterSelect: function(val) { this.$element.val(""); },
source: {{ current_user.get_managed_addresses()|map('string')|list|tojson }} source: {{ current_user.get_managed_emails()|map('string')|list|tojson }}
} }
}); });
</script> </script>

@ -17,7 +17,7 @@ Alias list
<tbody> <tbody>
<tr> <tr>
<th>Actions</th> <th>Actions</th>
<th>Address</th> <th>Email</th>
<th>Destination</th> <th>Destination</th>
<th>Comment</th> <th>Comment</th>
<th>Created</th> <th>Created</th>
@ -26,8 +26,8 @@ Alias list
{% for alias in domain.aliases %} {% for alias in domain.aliases %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('.alias_edit', alias=alias.address) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp; <a href="{{ url_for('.alias_edit', alias=alias.email) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp;
<a href="{{ url_for('.alias_delete', alias=alias.address) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a> <a href="{{ url_for('.alias_delete', alias=alias.email) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a>
</td> </td>
<td>{{ alias }}</td> <td>{{ alias }}</td>
<td>{{ alias.destination or '-' }}</td> <td>{{ alias.destination or '-' }}</td>

@ -9,7 +9,7 @@ Fetched accounts
{% endblock %} {% endblock %}
{% block main_action %} {% block main_action %}
<a class="btn btn-primary" href="{{ url_for('.fetch_create', user_address=user.address) }}">Add an account</a> <a class="btn btn-primary" href="{{ url_for('.fetch_create', user_email=user.email) }}">Add an account</a>
{% endblock %} {% endblock %}
{% block box %} {% block box %}

@ -19,7 +19,7 @@ Add a manager
tagClass: 'label label-primary large', tagClass: 'label label-primary large',
typeahead: { typeahead: {
afterSelect: function(val) { this.$element.val(""); }, afterSelect: function(val) { this.$element.val(""); },
source: {{ current_user.get_managed_addresses()|map('string')|list|tojson }} source: {{ current_user.get_managed_emails()|map('string')|list|tojson }}
} }
}); });
</script> </script>

@ -17,14 +17,14 @@ Manager list
<tbody> <tbody>
<tr> <tr>
<th>Actions</th> <th>Actions</th>
<th>Address</th> <th>Email</th>
<th>Created</th> <th>Created</th>
<th>Last edit</th> <th>Last edit</th>
</tr> </tr>
{% for manager in domain.managers %} {% for manager in domain.managers %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('.manager_delete', manager=manager.address) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a> <a href="{{ url_for('.manager_delete', manager=manager.email) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a>
</td> </td>
<td>{{ manager }}</td> <td>{{ manager }}</td>
<td>{{ manager.created_at }}</td> <td>{{ manager.created_at }}</td>

@ -18,7 +18,7 @@ User list
<tr> <tr>
<th>Actions</th> <th>Actions</th>
<th>User settings</th> <th>User settings</th>
<th>Address</th> <th>Email</th>
<th>Features</th> <th>Features</th>
<th>Quota</th> <th>Quota</th>
<th>Comment</th> <th>Comment</th>
@ -28,14 +28,14 @@ User list
{% for user in domain.users %} {% for user in domain.users %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('.user_edit', user_email=user.address) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp; <a href="{{ url_for('.user_edit', user_email=user.email) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp;
<a href="{{ url_for('.user_delete', user_email=user.address) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a> <a href="{{ url_for('.user_delete', user_email=user.email) }}" onclick="return confirm('Are you sure?')" title="Delete"><i class="fa fa-trash"></i></a>
</td> </td>
<td> <td>
<a href="{{ url_for('.user_settings', user_email=user.address) }}" title="Settings"><i class="fa fa-wrench"></i></a>&nbsp; <a href="{{ url_for('.user_settings', user_email=user.email) }}" title="Settings"><i class="fa fa-wrench"></i></a>&nbsp;
<a href="{{ url_for('.user_forward', user_email=user.address) }}" title="Auto-forward"><i class="fa fa-share"></i></a>&nbsp; <a href="{{ url_for('.user_forward', user_email=user.email) }}" title="Auto-forward"><i class="fa fa-share"></i></a>&nbsp;
<a href="{{ url_for('.user_reply', user_email=user.address) }}" title="Auto-reply"><i class="fa fa-plane"></i></a>&nbsp; <a href="{{ url_for('.user_reply', user_email=user.email) }}" title="Auto-reply"><i class="fa fa-plane"></i></a>&nbsp;
<a href="{{ url_for('.fetch_list', user_address=user.address) }}" title="Fetched accounts"><i class="fa fa-download"></i></a>&nbsp; <a href="{{ url_for('.fetch_list', user_email=user.email) }}" title="Fetched accounts"><i class="fa fa-download"></i></a>&nbsp;
</td> </td>
<td>{{ user }}</td> <td>{{ user }}</td>
<td> <td>

@ -19,7 +19,7 @@ def admin_list():
def admin_create(): def admin_create():
form = forms.AdminForm() form = forms.AdminForm()
if form.validate_on_submit(): if form.validate_on_submit():
user = models.User.query.filter_by(address=form.admin.data).first() user = models.User.query.filter_by(email=form.admin.data).first()
if user: if user:
user.global_admin = True user.global_admin = True
db.session.add(user) db.session.add(user)
@ -34,7 +34,7 @@ def admin_create():
@app.route('/admin/delete/<admin>', methods=['GET']) @app.route('/admin/delete/<admin>', methods=['GET'])
@flask_login.login_required @flask_login.login_required
def admin_delete(admin): def admin_delete(admin):
user = models.User.query.filter_by(address=admin).first() user = models.User.query.filter_by(email=admin).first()
if user: if user:
user.global_admin = False user.global_admin = False
db.session.add(user) db.session.add(user)

@ -23,8 +23,9 @@ def alias_create(domain_name):
flask.url_for('.alias_list', domain_name=domain.name)) flask.url_for('.alias_list', domain_name=domain.name))
form = forms.AliasForm() form = forms.AliasForm()
if form.validate_on_submit(): if form.validate_on_submit():
if domain.has_address(form.localpart.data): if domain.has_email(form.localpart.data):
flask.flash('Address %s is already used' % address, 'error') # TODO email is not declared
flask.flash('Email %s is already used' % email, 'error')
else: else:
alias = models.Alias(localpart=form.localpart.data, domain=domain) alias = models.Alias(localpart=form.localpart.data, domain=domain)
alias.destination = form.destination.data alias.destination = form.destination.data

@ -21,7 +21,7 @@ def login():
flask_login.login_user(user) flask_login.login_user(user)
return flask.redirect(flask.url_for('.index')) return flask.redirect(flask.url_for('.index'))
else: else:
flask.flash('Wrong e-mail address or password', 'error') flask.flash('Wrong e-mail or password', 'error')
return flask.render_template('login.html', form=form) return flask.render_template('login.html', form=form)

@ -6,19 +6,19 @@ import flask
import wtforms_components import wtforms_components
@app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_address': None}) @app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_email': None})
@app.route('/fetch/list/<user_address>', methods=['GET']) @app.route('/fetch/list/<user_email>', methods=['GET'])
@flask_login.login_required @flask_login.login_required
def fetch_list(user_address): def fetch_list(user_email):
user = utils.get_user(user_address, True) user = utils.get_user(user_email, True)
return flask.render_template('fetch/list.html', user=user) return flask.render_template('fetch/list.html', user=user)
@app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_address': None}) @app.route('/fetch/list', methods=['GET', 'POST'], defaults={'user_email': None})
@app.route('/fetch/create/<user_address>', methods=['GET', 'POST']) @app.route('/fetch/create/<user_email>', methods=['GET', 'POST'])
@flask_login.login_required @flask_login.login_required
def fetch_create(user_address): def fetch_create(user_email):
user = utils.get_user(user_address) user = utils.get_user(user_email)
form = forms.FetchForm() form = forms.FetchForm()
if form.validate_on_submit(): if form.validate_on_submit():
fetch = models.Fetch(user=user) fetch = models.Fetch(user=user)
@ -32,7 +32,7 @@ def fetch_create(user_address):
db.session.commit() db.session.commit()
flask.flash('Fetch configuration created') flask.flash('Fetch configuration created')
return flask.redirect( return flask.redirect(
flask.url_for('.fetch_list', user_address=user.address)) flask.url_for('.fetch_list', user_email=user.email))
return flask.render_template('fetch/create.html', form=form) return flask.render_template('fetch/create.html', form=form)
@ -52,7 +52,7 @@ def fetch_edit(fetch_id):
db.session.commit() db.session.commit()
flask.flash('Fetch configuration updated') flask.flash('Fetch configuration updated')
return flask.redirect( return flask.redirect(
flask.url_for('.fetch_list', user_address=fetch.user.address)) flask.url_for('.fetch_list', user_email=fetch.user.email))
return flask.render_template('fetch/edit.html', return flask.render_template('fetch/edit.html',
form=form, fetch=fetch) form=form, fetch=fetch)
@ -65,4 +65,4 @@ def fetch_delete(fetch_id):
db.session.commit() db.session.commit()
flask.flash('Fetch configuration delete') flask.flash('Fetch configuration delete')
return flask.redirect( return flask.redirect(
flask.url_for('.fetch_list', user_address=fetch.user.address)) flask.url_for('.fetch_list', user_email=fetch.user.email))

@ -23,8 +23,9 @@ def user_create(domain_name):
flask.url_for('.user_list', domain_name=domain.name)) flask.url_for('.user_list', domain_name=domain.name))
form = forms.UserForm() form = forms.UserForm()
if form.validate_on_submit(): if form.validate_on_submit():
if domain.has_address(form.localpart.data): if domain.has_email(form.localpart.data):
flask.flash('Address %s is already used' % address, 'error') # TODO: email is not declared
flask.flash('Email %s is already used' % email, 'error')
else: else:
user = models.User(localpart=form.localpart.data, domain=domain) user = models.User(localpart=form.localpart.data, domain=domain)
user.comment = form.comment.data user.comment = form.comment.data

@ -5,10 +5,10 @@ connect = /data/freeposte.db
password_query = \ password_query = \
SELECT password \ SELECT password \
FROM user \ FROM user \
WHERE user.address = '%u' WHERE user.email = '%u'
# Mostly get the user quota # Mostly get the user quota
user_query = \ user_query = \
SELECT '*:bytes=' || user.quota_bytes AS quota_rule \ SELECT '*:bytes=' || user.quota_bytes AS quota_rule \
FROM user \ FROM user \
WHERE user.address = '%u' WHERE user.email = '%u'

@ -3,20 +3,20 @@ connect = /data/freeposte.db
map { map {
pattern = priv/reply_subject pattern = priv/reply_subject
table = user table = user
username_field = address username_field = email
value_field = reply_subject value_field = reply_subject
} }
map { map {
pattern = priv/reply_body pattern = priv/reply_body
table = user table = user
username_field = address username_field = email
value_field = reply_body value_field = reply_body
} }
map { map {
pattern = priv/forward pattern = priv/forward
table = user table = user
username_field = address username_field = email
value_field = forward value_field = forward
} }

@ -10,7 +10,7 @@ RC_LINE = """
poll {host} proto {protocol} port {port} poll {host} proto {protocol} port {port}
user "{username}" password "{password}" user "{username}" password "{password}"
smtphost "smtp" smtphost "smtp"
smtpname {user_address} smtpname {user_email}
{options} {options}
""" """
@ -25,15 +25,15 @@ def fetchmail(fetchmailrc):
def run(cursor): def run(cursor):
cursor.execute(""" cursor.execute("""
SELECT user_address, protocol, host, port, tls, username, password SELECT user_email, protocol, host, port, tls, username, password
FROM fetch FROM fetch
""") """)
fetchmailrc = "" fetchmailrc = ""
for line in cursor.fetchall(): for line in cursor.fetchall():
user_address, protocol, host, port, tls, username, password = line user_email, protocol, host, port, tls, username, password = line
options = "options ssl" if tls else "" options = "options ssl" if tls else ""
fetchmailrc += RC_LINE.format( fetchmailrc += RC_LINE.format(
user_address=user_address, user_email=user_email,
protocol=protocol, protocol=protocol,
host=host, host=host,
port=port, port=port,

@ -2,4 +2,4 @@ dbpath = /data/freeposte.db
query = query =
SELECT destination SELECT destination
FROM alias FROM alias
WHERE alias.address = '%s' WHERE alias.email = '%s'

Loading…
Cancel
Save