Enable self-service account signup

master
kaiyou 7 years ago
parent 3b79e5196a
commit 2662abedef

@ -60,6 +60,7 @@ 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)
max_quota_bytes = db.Column(db.Integer(), nullable=False, default=0) max_quota_bytes = db.Column(db.Integer(), nullable=False, default=0)
signup_enabled = db.Column(db.Boolean(), nullable=False, default=False)
@property @property
def dkim_key(self): def dkim_key(self):

@ -47,6 +47,7 @@ class DomainForm(flask_wtf.FlaskForm):
max_users = fields_.IntegerField(_('Maximum user count'), default=10) max_users = fields_.IntegerField(_('Maximum user count'), default=10)
max_aliases = fields_.IntegerField(_('Maximum alias count'), default=10) max_aliases = fields_.IntegerField(_('Maximum alias count'), default=10)
max_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0) max_quota_bytes = fields_.IntegerSliderField(_('Maximum user quota'), default=0)
signup_enabled = fields.BooleanField(_('Enable sign-up'), default=False)
comment = fields.StringField(_('Comment')) comment = fields.StringField(_('Comment'))
submit = fields.SubmitField(_('Create')) submit = fields.SubmitField(_('Create'))
@ -74,6 +75,13 @@ class UserForm(flask_wtf.FlaskForm):
submit = fields.SubmitField(_('Save')) submit = fields.SubmitField(_('Save'))
class UserSignupForm(flask_wtf.FlaskForm):
localpart = fields.StringField(_('Email address'))
pw = fields.PasswordField(_('Password'), [validators.DataRequired()])
pw2 = fields.PasswordField(_('Confirm password'), [validators.EqualTo('pw')])
submit = fields.SubmitField(_('Sign up'))
class UserSettingsForm(flask_wtf.FlaskForm): class UserSettingsForm(flask_wtf.FlaskForm):
displayed_name = fields.StringField(_('Displayed name')) displayed_name = fields.StringField(_('Displayed name'))
spam_enabled = fields.BooleanField(_('Enable spam filter')) spam_enabled = fields.BooleanField(_('Enable spam filter'))

@ -100,10 +100,17 @@
</li> </li>
{% else %} {% else %}
<li> <li>
<a href="#"> <a href="{{ url_for('.login') }}">
<i class="fa fa-sign-in"></i> <span>{% trans %}Sign in{% endtrans %}</span> <i class="fa fa-sign-in"></i> <span>{% trans %}Sign in{% endtrans %}</span>
</a> </a>
</li> </li>
{% if signup_domains %}
<li>
<a href="{{ url_for('.user_signup') }}">
<i class="fa fa-user-plus"></i> <span>{% trans %}Sign up{% endtrans %}</span>
</a>
</li>
{% endif %}
{% endif %} {% endif %}
</ul> </ul>
</section> </section>

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block title %}
{% trans %}Sign up{% endtrans %}
{% endblock %}
{% block subtitle %}
{{ domain }}
{% endblock %}
{% block content %}
<form class="form" method="post" role="form">
{{ form.hidden_tag() }}
{% call macros.box() %}
{{ macros.form_field(form.localpart, append='<span class="input-group-addon">@'+domain.name+'</span>') }}
{{ macros.form_fields((form.pw, form.pw2)) }}
{{ macros.form_field(form.submit) }}
{% endcall %}
</form>
{% endblock %}

@ -0,0 +1,26 @@
{% extends "base.html" %}
{% block title %}
{% trans %}Sign up{% endtrans %}
{% endblock %}
{% block subtitle %}
{% trans %}pick a domain for the new account{% endtrans %}
{% endblock %}
{% block content %}
{% call macros.table() %}
<tr>
<th>{% trans %}Domain{% endtrans %}</th>
<th>{% trans %}Available slots{% endtrans %}</th>
<th>{% trans %}Quota{% endtrans %}</th>
</tr>
{% for domain_name, domain in available_domains.items() %}
<tr>
<td><a href="{{ url_for('.user_signup', domain_name=domain_name) }}">{{ domain_name }}</a></td>
<td>{{ domain.max_users - domain.users if domain.max_users else '∞' }}</td>
<td>{{ domain.max_quota_bytes or config['DEFAULT_QUOTA'] | filesizeformat }}</td>
</tr>
{% endfor %}
{% endcall %}
{% endblock %}

@ -153,3 +153,35 @@ def user_reply(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)
@ui.route('/user/signup', methods=['GET', 'POST'])
@ui.route('/user/signup/<domain_name>', methods=['GET', 'POST'])
def user_signup(domain_name=None):
available_domains = {
domain.name: domain
for domain in models.Domain.query.filter_by(signup_enabled=True).all()
if not domain.max_users or len(domain.users) < domain.max_users
}
if not available_domains:
flask.flash('No domain available for registration')
if not domain_name:
return flask.render_template('user/signup_domain.html',
available_domains=available_domains)
domain = available_domains.get(domain_name) or flask.abort(404)
quota_bytes = min(config['DEFAULT_QUOTA'], domain.max_quota_bytes)
form = forms.UserSignupForm()
if form.validate_on_submit():
if domain.has_email(form.localpart.data):
flask.flash('Email is already used', 'error')
else:
user = models.User(domain=domain)
form.populate_obj(user)
user.set_password(form.pw.data)
user.quota_bytes = quota_bytes
db.session.add(user)
db.session.commit()
user.send_welcome()
flask.flash('Successfully signed up %s' % user)
return flask.redirect(flask.url_for('.index'))
return flask.render_template('user/signup.html', domain=domain, form=form)

Loading…
Cancel
Save