Switched to blueprints for the main app

master
Pierre Jaury 8 years ago
parent 1c1c8e9cf6
commit 40d4a22240

@ -10,7 +10,7 @@ import os
app = Flask(__name__) app = Flask(__name__)
default_config = { default_config = {
'SQLALCHEMY_DATABASE_URI': 'sqlite:////tmp/freeposte.db', 'SQLALCHEMY_DATABASE_URI': 'sqlite:////data/freeposte.db',
'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_TRACK_MODIFICATIONS': False,
'SECRET_KEY': "changeMe", 'SECRET_KEY': "changeMe",
'DEBUG': False 'DEBUG': False
@ -20,24 +20,12 @@ default_config = {
for key, value in default_config.items(): for key, value in default_config.items():
app.config[key] = os.environ.get(key, value) app.config[key] = os.environ.get(key, value)
# Setup Bootstrap # Setup components
Bootstrap(app) Bootstrap(app)
# Create the database
db = SQLAlchemy(app) db = SQLAlchemy(app)
# Import models once the database is ready
from freeposte import models
# Setup Flask-login
login_manager = flask_login.LoginManager() login_manager = flask_login.LoginManager()
login_manager.init_app(app) login_manager.init_app(app)
login_manager.login_view = "login"
login_manager.user_loader(models.User.get_by_email)
@app.context_processor # Finally setup the blueprint
def inject_user(): from freeposte import admin
return dict(current_user=flask_login.current_user) app.register_blueprint(admin.app, url_prefix='/admin')
# Finally import view
from freeposte import views

@ -0,0 +1,28 @@
from flask import Blueprint
from flask.ext import login as flask_login
from freeposte import login_manager, db
app = Blueprint(
'admin', __name__,
template_folder='templates',
static_folder='static')
# Import models
from freeposte.admin import models
# Register the login components
login_manager.login_view = "admin.login"
login_manager.user_loader(models.User.get_by_email)
@app.context_processor
def inject_user():
return dict(current_user=flask_login.current_user)
# Import views
from freeposte.admin.views import \
administrators, \
base, \
aliases, \
users, \
domains

@ -1,9 +1,11 @@
from freeposte import db from freeposte.admin import db
from sqlalchemy.ext import declarative from sqlalchemy.ext import declarative
from passlib import context from passlib import context
from datetime import datetime from datetime import datetime
import re
# Many-to-many association table for domain administrators # Many-to-many association table for domain administrators
admins = db.Table('admin', admins = db.Table('admin',
@ -89,13 +91,16 @@ class User(Address):
is_active = True is_active = True
is_anonymous = False is_anonymous = False
pw_context = context.CryptContext(["sha512_crypt", "sha256_crypt"]) pw_context = context.CryptContext(
["sha512_crypt", "sha256_crypt", "md5_crypt"]
)
def check_password(self, password): def check_password(self, password):
return User.pw_context.verify(password, self.password) reference = re.match('({[^}]+})?(.*)', self.password).group(2)
return User.pw_context.verify(password, reference)
def set_password(self, password): def set_password(self, password):
self.password = User.pw_context.encrypt(password) self.password = '{SHA512-CRYPT}' + User.pw_context.encrypt(password)
def get_managed_domains(self): def get_managed_domains(self):
if self.global_admin: if self.global_admin:

@ -9,7 +9,7 @@ Alias list
{% endblock %} {% endblock %}
{% block main_action %} {% block main_action %}
<a class="btn btn-primary" href="{{ url_for('alias_create', domain_name=domain.name) }}">Add alias</a> <a class="btn btn-primary" href="{{ url_for('.alias_create', domain_name=domain.name) }}">Add alias</a>
{% endblock %} {% endblock %}
{% block box %} {% block box %}
@ -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.get_id()) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp; <a href="{{ url_for('.alias_edit', alias=alias.get_id()) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp;
<a href="{{ url_for('alias_delete', alias=alias.get_id()) }}" title="Delete"><i class="fa fa-trash"></i></a> <a href="{{ url_for('.alias_delete', alias=alias.get_id()) }}" 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>

@ -5,8 +5,8 @@
{% block styles %} {% block styles %}
{{super()}} {{super()}}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="/static/adminlte/css/AdminLTE.min.css"> <link rel="stylesheet" href="{{ url_for('.static', filename='adminlte/css/AdminLTE.min.css') }}">
<link rel="stylesheet" href="/static/adminlte/css/skin-blue.min.css"> <link rel="stylesheet" href="{{ url_for('.static', filename='adminlte/css/skin-blue.min.css') }}">
{% endblock %} {% endblock %}
{% block body_attribs %} {% block body_attribs %}
@ -68,7 +68,7 @@ class="hold-transition skin-blue sidebar-mini"
{% block scripts %} {% block scripts %}
{{super()}} {{super()}}
<script src="/static/adminlte/js/app.min.js"></script> <script src="{{ url_for('.static', filename='adminlte/js/app.min.js') }}"></script>
{% endblock %} {% endblock %}
</div> </div>
{% endblock %} {% endblock %}

@ -6,7 +6,7 @@ Domain list
{% block main_action %} {% block main_action %}
{% if current_user.global_admin %} {% if current_user.global_admin %}
<a class="btn btn-primary" href="{{ url_for('domain_create') }}">New domain</a> <a class="btn btn-primary" href="{{ url_for('.domain_create') }}">New domain</a>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -25,11 +25,11 @@ Domain list
{% for domain in current_user.get_managed_domains() %} {% for domain in current_user.get_managed_domains() %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('user_list', domain_name=domain.name) }}" title="Users"><i class="fa fa-envelope-o"></i></a>&nbsp; <a href="{{ url_for('.user_list', domain_name=domain.name) }}" title="Users"><i class="fa fa-envelope-o"></i></a>&nbsp;
<a href="{{ url_for('alias_list', domain_name=domain.name) }}" title="Aliases"><i class="fa fa-at"></i></a>&nbsp; <a href="{{ url_for('.alias_list', domain_name=domain.name) }}" title="Aliases"><i class="fa fa-at"></i></a>&nbsp;
<a href="{{ url_for('domain_admins', domain_name=domain.name) }}" title="Administrators"><i class="fa fa-user"></i></a>&nbsp; <a href="{{ url_for('.domain_admins', domain_name=domain.name) }}" title="Administrators"><i class="fa fa-user"></i></a>&nbsp;
<a href="{{ url_for('domain_delete', domain_name=domain.name) }}" title="Delete"><i class="fa fa-trash"></i></a>&nbsp; <a href="{{ url_for('.domain_delete', domain_name=domain.name) }}" title="Delete"><i class="fa fa-trash"></i></a>&nbsp;
<a href="{{ url_for('domain_edit', domain_name=domain.name) }}" title="Edit"><i class="fa fa-pencil"></i></a> <a href="{{ url_for('.domain_edit', domain_name=domain.name) }}" title="Edit"><i class="fa fa-pencil"></i></a>
</td> </td>
<td>{{ domain.name }}</td> <td>{{ domain.name }}</td>
<td>{{ domain.users | count }} / {{ domain.max_users or '∞' }}</td> <td>{{ domain.users | count }} / {{ domain.max_users or '∞' }}</td>

@ -4,51 +4,51 @@
<ul class="sidebar-menu"> <ul class="sidebar-menu">
<li class="header">My account</li> <li class="header">My account</li>
<li> <li>
<a href="{{ url_for('user_settings') }}"> <a href="{{ url_for('.user_settings') }}">
<i class="fa fa-wrench"></i> <span>Settings</span> <i class="fa fa-wrench"></i> <span>Settings</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('user_password') }}"> <a href="{{ url_for('.user_password') }}">
<i class="fa fa-lock"></i> <span>Update password</span> <i class="fa fa-lock"></i> <span>Update password</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('user_forward') }}"> <a href="{{ url_for('.user_forward') }}">
<i class="fa fa-share"></i> <span>Auto-forward</span> <i class="fa fa-share"></i> <span>Auto-forward</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('user_reply') }}"> <a href="{{ url_for('.user_reply') }}">
<i class="fa fa-plane"></i> <span>Auto-reply</span> <i class="fa fa-plane"></i> <span>Auto-reply</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('user_fetchmail') }}"> <a href="{{ url_for('.user_fetchmail') }}">
<i class="fa fa-download"></i> <span>Fetched accounts</span> <i class="fa fa-download"></i> <span>Fetched accounts</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('logout') }}"> <a href="{{ url_for('.logout') }}">
<i class="fa fa-sign-out"></i> <span>Sign out</span> <i class="fa fa-sign-out"></i> <span>Sign out</span>
</a> </a>
</li> </li>
<li class="header">Administration</li> <li class="header">Administration</li>
{% if current_user.global_admin %} {% if current_user.global_admin %}
<li> <li>
<a href="{{ url_for('status') }}"> <a href="{{ url_for('.status') }}">
<i class="fa fa-dashboard"></i> <span>Services status</span> <i class="fa fa-dashboard"></i> <span>Services status</span>
</a> </a>
</li> </li>
<li> <li>
<a href="{{ url_for('admins') }}"> <a href="{{ url_for('.admins') }}">
<i class="fa fa-user"></i> <span>Adminitrators</span> <i class="fa fa-user"></i> <span>Adminitrators</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if current_user.admin_of %} {% if current_user.admin_of or current_user.global_admin %}
<li> <li>
<a href="{{ url_for('domain_list') }}"> <a href="{{ url_for('.domain_list') }}">
<i class="fa fa-envelope"></i> <span>Mail domains</span> <i class="fa fa-envelope"></i> <span>Mail domains</span>
</a> </a>
</li> </li>

@ -0,0 +1,52 @@
{% extends "base.html" %}
{% block title %}
User list
{% endblock %}
{% block subtitle %}
{{ domain.name }}
{% endblock %}
{% block main_action %}
<a class="btn btn-primary" href="{{ url_for('.user_create', domain_name=domain.name) }}">Add user</a>
{% endblock %}
{% block box %}
<table class="table table-bordered">
<tbody>
<tr>
<th>Actions</th>
<th>Address</th>
<th>Name</th>
<th>Forward</th>
<th>Reply</th>
<th>Quota</th>
<th>Comment</th>
<th>Created</th>
<th>Last edit</th>
</tr>
{% for user in domain.users %}
<tr>
<td>
<a href="{{ url_for('.user_settings', user_email=user.get_id()) }}" title="Settings"><i class="fa fa-wrench"></i></a>&nbsp;
<a href="{{ url_for('.user_password', user_email=user.get_id()) }}" title="Update password"><i class="fa fa-lock"></i></a>&nbsp;
<a href="{{ url_for('.user_forward', user_email=user.get_id()) }}" title="Auto-forward"><i class="fa fa-share"></i></a>&nbsp;
<a href="{{ url_for('.user_reply', user_email=user.get_id()) }}" title="Auto-reply"><i class="fa fa-plane"></i></a>&nbsp;
<a href="{{ url_for('.user_fetchmail', user_email=user.get_id()) }}" title="Fetched accounts"><i class="fa fa-download"></i></a>&nbsp;
<a href="{{ url_for('.user_edit', user_email=user.get_id()) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp;
<a href="{{ url_for('.user_delete', user_email=user.get_id()) }}" title="Delete"><i class="fa fa-trash"></i></a>
</td>
<td>{{ user }}</td>
<td>{{ user.displayed_name }}</td>
<td>{% if user.forward %}<span class="label label-info">enabled</span>{% endif %}</td>
<td>{% if user.reply_subject %}<span class="label label-info">enabled</span>{% endif %}</td>
<td>{{ user.quota_bytes | filesizeformat }}</td>
<td>{{ user.comment or '' }}</td>
<td>{{ user.created_at }}</td>
<td>{{ user.updated_at or '' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

@ -1,4 +1,4 @@
from freeposte import models from freeposte.admin import models
from flask.ext import login as flask_login from flask.ext import login as flask_login
import flask import flask

@ -1,4 +1,4 @@
from freeposte import app, db, models, forms, utils from freeposte.admin import app, db, models, forms, utils
from flask.ext import login as flask_login from flask.ext import login as flask_login
import os import os

@ -1,4 +1,4 @@
from freeposte import app, db, models, forms, utils from freeposte.admin import app, db, models, forms, utils
from flask.ext import login as flask_login from flask.ext import login as flask_login
import os import os
@ -18,7 +18,8 @@ def alias_create(domain_name):
domain = utils.get_domain_admin(domain_name) domain = utils.get_domain_admin(domain_name)
if domain.max_aliases and len(domain.aliases) >= domain.max_aliases: if domain.max_aliases and len(domain.aliases) >= domain.max_aliases:
flask.flash('Too many aliases for domain %s' % domain, 'error') flask.flash('Too many aliases for domain %s' % domain, 'error')
return flask.redirect(flask.url_for('alias_list', domain_name=domain.name)) return flask.redirect(
flask.url_for('.alias_list', domain_name=domain.name))
form = forms.AliasCreateForm() form = forms.AliasCreateForm()
if form.validate_on_submit(): if form.validate_on_submit():
for address in domain.users + domain.aliases: for address in domain.users + domain.aliases:
@ -33,7 +34,7 @@ def alias_create(domain_name):
db.session.commit() db.session.commit()
flask.flash('Alias %s created' % alias) flask.flash('Alias %s created' % alias)
return flask.redirect( return flask.redirect(
flask.url_for('alias_list', domain_name=domain.name)) flask.url_for('.alias_list', domain_name=domain.name))
return flask.render_template('alias/create.html', return flask.render_template('alias/create.html',
domain=domain, form=form) domain=domain, form=form)
@ -50,7 +51,7 @@ def alias_edit(alias):
db.session.commit() db.session.commit()
flask.flash('Alias %s updated' % alias) flask.flash('Alias %s updated' % alias)
return flask.redirect( return flask.redirect(
flask.url_for('alias_list', domain_name=alias.domain.name)) flask.url_for('.alias_list', domain_name=alias.domain.name))
return flask.render_template('alias/edit.html', form=form, alias=alias) return flask.render_template('alias/edit.html', form=form, alias=alias)
@ -61,4 +62,5 @@ def alias_delete(alias):
db.session.delete(alias) db.session.delete(alias)
db.session.commit() db.session.commit()
flask.flash('Alias %s deleted' % alias) flask.flash('Alias %s deleted' % alias)
return flask.redirect(flask.url_for('alias_list', domain_name=alias.domain.name)) return flask.redirect(
flask.url_for('.alias_list', domain_name=alias.domain.name))

@ -1,4 +1,4 @@
from freeposte import app, db, models, forms from freeposte.admin import app, db, models, forms
from flask.ext import login as flask_login from flask.ext import login as flask_login
import os import os
@ -8,7 +8,7 @@ import flask
@app.route('/', methods=["GET"]) @app.route('/', methods=["GET"])
@flask_login.login_required @flask_login.login_required
def index(): def index():
return flask.redirect(flask.url_for('user_settings')) return flask.redirect(flask.url_for('.user_settings'))
@app.route('/login', methods=['GET', 'POST']) @app.route('/login', methods=['GET', 'POST'])
@ -18,7 +18,7 @@ def login():
user = models.User.login(form.email.data, form.pw.data) user = models.User.login(form.email.data, form.pw.data)
if user: if user:
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 address or password', 'error')
return flask.render_template('login.html', form=form) return flask.render_template('login.html', form=form)
@ -28,4 +28,4 @@ def login():
@flask_login.login_required @flask_login.login_required
def logout(): def logout():
flask_login.logout_user() flask_login.logout_user()
return flask.redirect(flask.url_for('index')) return flask.redirect(flask.url_for('.index'))

@ -1,4 +1,4 @@
from freeposte import app, db, models, forms, utils from freeposte.admin import app, db, models, forms, utils
from flask.ext import login as flask_login from flask.ext import login as flask_login
import os import os
@ -25,7 +25,7 @@ def domain_create():
db.session.add(domain) db.session.add(domain)
db.session.commit() db.session.commit()
flask.flash('Domain %s created' % domain) flask.flash('Domain %s created' % domain)
return flask.redirect(flask.url_for('domain_list')) return flask.redirect(flask.url_for('.domain_list'))
return flask.render_template('domain/create.html', form=form) return flask.render_template('domain/create.html', form=form)
@ -42,7 +42,7 @@ def domain_edit(domain_name):
db.session.add(domain) db.session.add(domain)
db.session.commit() db.session.commit()
flask.flash('Domain %s saved' % domain) flask.flash('Domain %s saved' % domain)
return flask.redirect(flask.url_for('domain_list')) return flask.redirect(flask.url_for('.domain_list'))
return flask.render_template('domain/edit.html', form=form, return flask.render_template('domain/edit.html', form=form,
domain=domain) domain=domain)
@ -55,7 +55,7 @@ def domain_delete(domain_name):
db.session.delete(domain) db.session.delete(domain)
db.session.commit() db.session.commit()
flask.flash('Domain %s deleted' % domain) flask.flash('Domain %s deleted' % domain)
return flask.redirect(flask.url_for('domain_list')) return flask.redirect(flask.url_for('.domain_list'))
@app.route('/domain/admins/<domain_name>', methods=['GET']) @app.route('/domain/admins/<domain_name>', methods=['GET'])

@ -1,4 +1,4 @@
from freeposte import app, db, models, forms, utils from freeposte.admin import app, db, models, forms, utils
from flask.ext import login as flask_login from flask.ext import login as flask_login
import os import os
@ -16,9 +16,10 @@ def user_list(domain_name):
@flask_login.login_required @flask_login.login_required
def user_create(domain_name): def user_create(domain_name):
domain = utils.get_domain_admin(domain_name) domain = utils.get_domain_admin(domain_name)
if domain.mex_users and len(domain.users) >= domain.max_users: if domain.max_users and len(domain.users) >= domain.max_users:
flask.flash('Too many users for domain %s' % domain, 'error') flask.flash('Too many users for domain %s' % domain, 'error')
return flask.redirect(flask.url_for('user_list', domain_name=domain.name)) return flask.redirect(
flask.url_for('.user_list', domain_name=domain.name))
form = forms.UserCreateForm() form = forms.UserCreateForm()
if form.validate_on_submit(): if form.validate_on_submit():
for address in domain.users + domain.aliases: for address in domain.users + domain.aliases:
@ -33,7 +34,7 @@ def user_create(domain_name):
db.session.commit() db.session.commit()
flask.flash('User %s created' % user) flask.flash('User %s created' % user)
return flask.redirect( return flask.redirect(
flask.url_for('user_list', domain_name=domain.name)) flask.url_for('.user_list', domain_name=domain.name))
return flask.render_template('user/create.html', return flask.render_template('user/create.html',
domain=domain, form=form) domain=domain, form=form)
@ -50,7 +51,7 @@ def user_edit(user_email):
db.session.commit() db.session.commit()
flask.flash('User %s updated' % user) flask.flash('User %s updated' % user)
return flask.redirect( return flask.redirect(
flask.url_for('user_list', domain_name=user.domain.name)) flask.url_for('.user_list', domain_name=user.domain.name))
return flask.render_template('user/edit.html', form=form, user=user) return flask.render_template('user/edit.html', form=form, user=user)
@ -61,7 +62,8 @@ def user_delete(user_email):
db.session.delete(user) db.session.delete(user)
db.session.commit() db.session.commit()
flask.flash('User %s deleted' % user) flask.flash('User %s deleted' % user)
return flask.redirect(flask.url_for('user_list', domain_name=user.domain.name)) return flask.redirect(
flask.url_for('.user_list', domain_name=user.domain.name))
@app.route('/user/settings', methods=['GET', 'POST'], defaults={'user_email': None}) @app.route('/user/settings', methods=['GET', 'POST'], defaults={'user_email': None})
@ -79,7 +81,7 @@ def user_settings(user_email):
flask.flash('Settings updated for %s' % user) flask.flash('Settings updated for %s' % user)
if user_email: if user_email:
return flask.redirect( return flask.redirect(
flask.url_for('user_list', domain_name=user.domain.name)) flask.url_for('.user_list', domain_name=user.domain.name))
return flask.render_template('user/settings.html', form=form, user=user) return flask.render_template('user/settings.html', form=form, user=user)
@ -98,8 +100,8 @@ def user_password(user_email):
db.session.commit() db.session.commit()
flask.flash('Password updated for %s' % user) flask.flash('Password updated for %s' % user)
if user_email: if user_email:
return flask.redirect( return flask.redirect(flask.url_for('.user_list',
flask.url_for('user_list', domain_name=user.domain.name)) domain_name=user.domain.name))
return flask.render_template('user/password.html', form=form, user=user) return flask.render_template('user/password.html', form=form, user=user)
@ -116,7 +118,7 @@ def user_forward(user_email):
flask.flash('Forward destination updated for %s' % user) flask.flash('Forward destination updated for %s' % user)
if user_email: if user_email:
return flask.redirect( return flask.redirect(
flask.url_for('user_list', domain_name=user.domain.name)) flask.url_for('.user_list', domain_name=user.domain.name))
return flask.render_template('user/forward.html', form=form, user=user) return flask.render_template('user/forward.html', form=form, user=user)
@ -134,7 +136,7 @@ def user_reply(user_email):
flask.flash('Auto-reply message updated for %s' % user) flask.flash('Auto-reply message updated for %s' % user)
if user_email: if user_email:
return flask.redirect( return flask.redirect(
flask.url_for('user_list', domain_name=user.domain.name)) flask.url_for('.user_list', domain_name=user.domain.name))
return flask.render_template('user/reply.html', form=form, user=user) return flask.render_template('user/reply.html', form=form, user=user)

@ -1,52 +0,0 @@
{% extends "base.html" %}
{% block title %}
User list
{% endblock %}
{% block subtitle %}
{{ domain.name }}
{% endblock %}
{% block main_action %}
<a class="btn btn-primary" href="{{ url_for('user_create', domain_name=domain.name) }}">Add user</a>
{% endblock %}
{% block box %}
<table class="table table-bordered">
<tbody>
<tr>
<th>Actions</th>
<th>Address</th>
<th>Name</th>
<th>Forward</th>
<th>Reply</th>
<th>Quota</th>
<th>Comment</th>
<th>Created</th>
<th>Last edit</th>
</tr>
{% for user in domain.users %}
<tr>
<td>
<a href="{{ url_for('user_settings', user_email=user.get_id()) }}" title="Settings"><i class="fa fa-wrench"></i></a>&nbsp;
<a href="{{ url_for('user_password', user_email=user.get_id()) }}" title="Update password"><i class="fa fa-lock"></i></a>&nbsp;
<a href="{{ url_for('user_forward', user_email=user.get_id()) }}" title="Auto-forward"><i class="fa fa-share"></i></a>&nbsp;
<a href="{{ url_for('user_reply', user_email=user.get_id()) }}" title="Auto-reply"><i class="fa fa-plane"></i></a>&nbsp;
<a href="{{ url_for('user_fetchmail', user_email=user.get_id()) }}" title="Fetched accounts"><i class="fa fa-download"></i></a>&nbsp;
<a href="{{ url_for('user_edit', user_email=user.get_id()) }}" title="Edit"><i class="fa fa-pencil"></i></a>&nbsp;
<a href="{{ url_for('user_delete', user_email=user.get_id()) }}" title="Delete"><i class="fa fa-trash"></i></a>
</td>
<td>{{ user }}</td>
<td>{{ user.displayed_name }}</td>
<td>{% if user.forward %}<span class="label label-info">enabled</span>{% endif %}</td>
<td>{% if user.reply_subject %}<span class="label label-info">enabled</span>{% endif %}</td>
<td>{{ user.quota_bytes | filesizeformat }}</td>
<td>{{ user.comment or '' }}</td>
<td>{{ user.created_at }}</td>
<td>{{ user.updated_at or '' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

@ -1 +0,0 @@
from freeposte.views import base, admin, domains, users, aliases
Loading…
Cancel
Save