multi-domain support
This commit is contained in:
parent
58f46d0bbe
commit
a1c6b656d7
@ -39,7 +39,8 @@ def get_alias_with_user_by_id(cur, alias_id):
|
|||||||
cur.execute(
|
cur.execute(
|
||||||
"""\
|
"""\
|
||||||
SELECT a.id, a.source_email_id, ea.email, a.destination_user_id, a.enabled, a.note,
|
SELECT a.id, a.source_email_id, ea.email, a.destination_user_id, a.enabled, a.note,
|
||||||
u.id, u.email_id, eu.email, u.passwordhash, u.enabled, u.is_admin, u.note
|
u.id, u.email_id, eu.email, u.passwordhash, u.enabled, u.is_admin,
|
||||||
|
u.can_use_different_alias_domain, u.note
|
||||||
FROM aliases a
|
FROM aliases a
|
||||||
INNER JOIN emails ea ON a.source_email_id=ea.id
|
INNER JOIN emails ea ON a.source_email_id=ea.id
|
||||||
INNER JOIN users u ON a.destination_user_id=u.id
|
INNER JOIN users u ON a.destination_user_id=u.id
|
||||||
|
|||||||
@ -16,6 +16,7 @@ CREATE TABLE IF NOT EXISTS users (
|
|||||||
passwordhash varchar(255) NOT NULL,
|
passwordhash varchar(255) NOT NULL,
|
||||||
enabled boolean NOT NULL DEFAULT TRUE,
|
enabled boolean NOT NULL DEFAULT TRUE,
|
||||||
is_admin boolean NOT NULL DEFAULT FALSE,
|
is_admin boolean NOT NULL DEFAULT FALSE,
|
||||||
|
can_use_different_alias_domain boolean NOT NULL DEFAULT FALSE,
|
||||||
note text NOT NULL DEFAULT ''
|
note text NOT NULL DEFAULT ''
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -28,10 +29,3 @@ CREATE TABLE IF NOT EXISTS aliases (
|
|||||||
note text,
|
note text,
|
||||||
UNIQUE(source_email_id, destination_user_id)
|
UNIQUE(source_email_id, destination_user_id)
|
||||||
);
|
);
|
||||||
|
|
||||||
DO $$
|
|
||||||
BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM domains) THEN
|
|
||||||
INSERT INTO domains (name) VALUES ('finn.st');
|
|
||||||
END IF;
|
|
||||||
END$$;
|
|
||||||
|
|||||||
@ -12,6 +12,7 @@ class User(NoteLinesMixin):
|
|||||||
passwordhash: str
|
passwordhash: str
|
||||||
enabled: bool
|
enabled: bool
|
||||||
is_admin: bool
|
is_admin: bool
|
||||||
|
can_use_different_alias_domain: bool
|
||||||
note: str
|
note: str
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ def get_users(cur):
|
|||||||
|
|
||||||
@with_cursor
|
@with_cursor
|
||||||
def update_user(cur, id, **fields):
|
def update_user(cur, id, **fields):
|
||||||
"""only pwhash, enabled, is_admin, note"""
|
"""only pwhash, enabled, is_admin, can_use_different_alias_domain, note"""
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"UPDATE users SET "
|
"UPDATE users SET "
|
||||||
+ ", ".join(f"{field}=%s" for field in fields.keys())
|
+ ", ".join(f"{field}=%s" for field in fields.keys())
|
||||||
@ -62,13 +63,23 @@ def update_user(cur, id, **fields):
|
|||||||
|
|
||||||
|
|
||||||
@with_cursor
|
@with_cursor
|
||||||
def create_user(cur, email, passwordhash, enabled, is_admin, note):
|
def create_user(
|
||||||
|
cur, email, passwordhash, enabled, is_admin, can_use_different_alias_domain, note
|
||||||
|
):
|
||||||
email_id = create_email(cur, email)
|
email_id = create_email(cur, email)
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"""\
|
"""\
|
||||||
INSERT INTO users (email_id, passwordhash, enabled, is_admin, note)
|
INSERT INTO users
|
||||||
VALUES (%s, %s, %s, %s, %s)""",
|
(email_id, passwordhash, enabled, is_admin, can_use_different_alias_domain, note)
|
||||||
[email_id, passwordhash, enabled, is_admin, note],
|
VALUES (%s, %s, %s, %s, %s, %s)""",
|
||||||
|
[
|
||||||
|
email_id,
|
||||||
|
passwordhash,
|
||||||
|
enabled,
|
||||||
|
is_admin,
|
||||||
|
can_use_different_alias_domain,
|
||||||
|
note,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -105,8 +116,8 @@ def reset_or_create_user(cur, email, hash, is_admin):
|
|||||||
cur.execute("INSERT INTO emails (email) VALUES (%s) RETURNING id", [email])
|
cur.execute("INSERT INTO emails (email) VALUES (%s) RETURNING id", [email])
|
||||||
email_id = cur.fetchone()[0]
|
email_id = cur.fetchone()[0]
|
||||||
cur.execute(
|
cur.execute(
|
||||||
"INSERT INTO users (email_id, passwordhash, enabled, is_admin, note) VALUES (%s, %s, %s, %s, %s)", # noqa
|
"INSERT INTO users (email_id, passwordhash, enabled, is_admin, can_use_different_alias_domain, note) VALUES (%s, %s, %s, %s, %s, %s)", # noqa
|
||||||
[email_id, hash, True, is_admin, "Created by commandline"],
|
[email_id, hash, True, is_admin, is_admin, "Created by commandline"],
|
||||||
)
|
)
|
||||||
user_type = "admin" if is_admin else "user"
|
user_type = "admin" if is_admin else "user"
|
||||||
print(f"Created {user_type} {email}")
|
print(f"Created {user_type} {email}")
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"test.test": "LOL",
|
|
||||||
"Hi": "Moin",
|
"Hi": "Moin",
|
||||||
"You are not logged in": "Du bist nicht angemeldet",
|
"You are not logged in": "Du bist nicht angemeldet",
|
||||||
"Not found": "Nicht gefunden",
|
"Not found": "Nicht gefunden",
|
||||||
@ -44,7 +43,6 @@
|
|||||||
"Login was sucessfull!": "Erfolgreich angemeldet!",
|
"Login was sucessfull!": "Erfolgreich angemeldet!",
|
||||||
"Logout was sucessfull!": "Erfolgreich abgemeldet!",
|
"Logout was sucessfull!": "Erfolgreich abgemeldet!",
|
||||||
"The email is not valid": "Die Email ist nicht valide",
|
"The email is not valid": "Die Email ist nicht valide",
|
||||||
"The domain is invalid. Must be one of: {domains}": "Die Domain ist nacht valide. Dies sind die erlaubten Domains: {domains}",
|
|
||||||
"Email must be given": "Die Email muss gegeben sein",
|
"Email must be given": "Die Email muss gegeben sein",
|
||||||
"Enabled is not set": "Aktiviert ist nicht gesetzt",
|
"Enabled is not set": "Aktiviert ist nicht gesetzt",
|
||||||
"Note must be a string": "Die Notiz muss eine Zeichenkette sein",
|
"Note must be a string": "Die Notiz muss eine Zeichenkette sein",
|
||||||
@ -64,5 +62,8 @@
|
|||||||
"Email already exists.": "Email existiert bereits.",
|
"Email already exists.": "Email existiert bereits.",
|
||||||
"Email already exists: {msg}": "Email existiert bereits: {msg}",
|
"Email already exists: {msg}": "Email existiert bereits: {msg}",
|
||||||
"Used as an user.": "Wird für einen Nutzer verwendet",
|
"Used as an user.": "Wird für einen Nutzer verwendet",
|
||||||
"Used as an alias by {alias}.": "Word für den Alias {alias} verwendet"
|
"Used as an alias by {alias}.": "Word für den Alias {alias} verwendet",
|
||||||
|
"Invalid domain": "Invalide Domain",
|
||||||
|
"Can use different alias domains": "Kann unterschiedliche Aliasdomains benutzen",
|
||||||
|
"Can use different alias domains is not set": "Kann unterschiedliche Aliasdomains benutzen ist nicht gesetzt"
|
||||||
}
|
}
|
||||||
@ -15,12 +15,16 @@ from .user.detail import UserDetail
|
|||||||
from .user.edit_note import UserEditNote
|
from .user.edit_note import UserEditNote
|
||||||
from .user.list import UserList
|
from .user.list import UserList
|
||||||
from .user.toggle_admin import UserToggleAdmin
|
from .user.toggle_admin import UserToggleAdmin
|
||||||
|
from .user.toggle_can_use_different_alias_domain import (
|
||||||
|
UserToggleCanUseDifferentAliasDomain,
|
||||||
|
)
|
||||||
from .user.toggle_enabled import UserToggleEnabled
|
from .user.toggle_enabled import UserToggleEnabled
|
||||||
|
|
||||||
|
|
||||||
def init_routes(app):
|
def init_routes(app):
|
||||||
app.add_url_rule("/", "own-user-detail", UserDetail.as_view())
|
app.add_url_rule("/", "own-user-detail", UserDetail.as_view())
|
||||||
app.add_url_rule("/list", "user-list", UserList.as_view())
|
app.add_url_rule("/list", "user-list", UserList.as_view())
|
||||||
|
|
||||||
app.add_url_rule("/user/<int:user_id>", "user-detail", UserDetail.as_view())
|
app.add_url_rule("/user/<int:user_id>", "user-detail", UserDetail.as_view())
|
||||||
app.add_url_rule("/user/create", "user-create", UserCreate.as_view())
|
app.add_url_rule("/user/create", "user-create", UserCreate.as_view())
|
||||||
app.add_url_rule(
|
app.add_url_rule(
|
||||||
@ -41,10 +45,16 @@ def init_routes(app):
|
|||||||
"user-toggle-admin",
|
"user-toggle-admin",
|
||||||
UserToggleAdmin.as_view(),
|
UserToggleAdmin.as_view(),
|
||||||
)
|
)
|
||||||
|
app.add_url_rule(
|
||||||
|
"/user/<int:user_id>/ser-toggle-can-use-different-alias-domain",
|
||||||
|
"user-toggle-can-use-different-alias-domain",
|
||||||
|
UserToggleCanUseDifferentAliasDomain.as_view(),
|
||||||
|
)
|
||||||
app.add_url_rule("/user/<int:user_id>/delete", "user-delete", UserDelete.as_view())
|
app.add_url_rule("/user/<int:user_id>/delete", "user-delete", UserDelete.as_view())
|
||||||
app.add_url_rule(
|
app.add_url_rule(
|
||||||
"/user/<int:user_id>/aliases/create", "alias-create", AliasCreate.as_view()
|
"/user/<int:user_id>/aliases/create", "alias-create", AliasCreate.as_view()
|
||||||
)
|
)
|
||||||
|
|
||||||
app.add_url_rule("/alias/<int:alias_id>", "alias-detail", AliasDetail.as_view())
|
app.add_url_rule("/alias/<int:alias_id>", "alias-detail", AliasDetail.as_view())
|
||||||
app.add_url_rule(
|
app.add_url_rule(
|
||||||
"/alias/<int:alias_id>/delete", "alias-delete", AliasDelete.as_view()
|
"/alias/<int:alias_id>/delete", "alias-delete", AliasDelete.as_view()
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
from flask import flash
|
from flask import flash
|
||||||
|
|
||||||
from max.db import EmailAlreadyExists, create_alias
|
from max.db import EmailAlreadyExists, create_alias, get_domains
|
||||||
from max.permissions import AllowAdminOrSelf
|
from max.permissions import AllowAdminOrSelf
|
||||||
from max.translations import t
|
from max.translations import t
|
||||||
|
|
||||||
@ -26,7 +26,21 @@ class AliasCreate(
|
|||||||
else:
|
else:
|
||||||
self.email = email
|
self.email = email
|
||||||
|
|
||||||
if not self.is_email_valid(email):
|
if self.user.can_use_different_alias_domain:
|
||||||
|
domain = self.request.form.get("domain")
|
||||||
|
if not isinstance(domain, str) or not domain:
|
||||||
|
flash(t("Domain must be given"), category="error")
|
||||||
|
error = True
|
||||||
|
elif domain not in get_domains():
|
||||||
|
flash(t("Invalid domain"), category="error")
|
||||||
|
error = True
|
||||||
|
else:
|
||||||
|
self.domain = domain
|
||||||
|
else:
|
||||||
|
self.domain = self.get_user_domain()
|
||||||
|
|
||||||
|
full_email = f"{self.email}@{self.domain}"
|
||||||
|
if not self.is_email_valid(full_email):
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
enabled = self.request.form.get("enabled")
|
enabled = self.request.form.get("enabled")
|
||||||
@ -49,7 +63,7 @@ class AliasCreate(
|
|||||||
return # force re-rendering
|
return # force re-rendering
|
||||||
|
|
||||||
try:
|
try:
|
||||||
create_alias(self.email, self.user, self.enabled, self.note)
|
create_alias(full_email, self.user, self.enabled, self.note)
|
||||||
except EmailAlreadyExists as e:
|
except EmailAlreadyExists as e:
|
||||||
if self.auth_user.is_admin:
|
if self.auth_user.is_admin:
|
||||||
flash(
|
flash(
|
||||||
@ -61,14 +75,24 @@ class AliasCreate(
|
|||||||
return
|
return
|
||||||
|
|
||||||
flash(
|
flash(
|
||||||
t("Creation of alias {email} was successful!", email=email),
|
t("Creation of alias {email} was successful!", email=full_email),
|
||||||
category="success",
|
category="success",
|
||||||
)
|
)
|
||||||
return self.redirect()
|
return self.redirect()
|
||||||
|
|
||||||
def get_context(self):
|
def get_context(self):
|
||||||
context = super().get_context()
|
context = super().get_context()
|
||||||
for key in ("email", "enabled", "note"):
|
for key in ("email", "domain", "enabled", "note"):
|
||||||
if hasattr(self, key):
|
if hasattr(self, key):
|
||||||
context[key] = getattr(self, key)
|
context[key] = getattr(self, key)
|
||||||
|
context[
|
||||||
|
"can_use_different_alias_domain"
|
||||||
|
] = self.user.can_use_different_alias_domain
|
||||||
|
if self.user.can_use_different_alias_domain:
|
||||||
|
context["domains"] = get_domains()
|
||||||
|
else:
|
||||||
|
context["domain"] = self.get_user_domain()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
def get_user_domain(self):
|
||||||
|
return self.user.email.split("@")[1]
|
||||||
|
|||||||
@ -6,26 +6,14 @@ from max.db import get_domains
|
|||||||
from max.translations import t
|
from max.translations import t
|
||||||
|
|
||||||
|
|
||||||
EMAIL_REGEX = re.compile(r"^[a-zA-Z0-9+_-]+@(?P<domain>[a-zA-Z0-9-]+\.[a-z]{2,61})$")
|
|
||||||
|
|
||||||
|
|
||||||
class CheckEmailMixin:
|
class CheckEmailMixin:
|
||||||
def is_email_valid(self, email: str):
|
def is_email_valid(self, email: str):
|
||||||
"""Checks for the email being valid and that it has a valid domain."""
|
"""Checks for the email being valid and that it has a valid domain."""
|
||||||
match = EMAIL_REGEX.match(email)
|
regex = re.compile(f"^[a-zA-Z0-9+_-]+@({ '|'.join(get_domains()) })$")
|
||||||
|
print(regex, email)
|
||||||
|
match = regex.match(email)
|
||||||
if not match:
|
if not match:
|
||||||
flash(t("The email is not valid"), category="error")
|
flash(t("The email is not valid"), category="error")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
domains = get_domains()
|
|
||||||
if match.group("domain") not in domains:
|
|
||||||
flash(
|
|
||||||
t(
|
|
||||||
"The domain is invalid. Must be one of: {domains}",
|
|
||||||
domains=",".join(domains),
|
|
||||||
),
|
|
||||||
category="error",
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
from flask import flash
|
from flask import flash
|
||||||
|
|
||||||
from max.auth import hash_password
|
from max.auth import hash_password
|
||||||
from max.db import EmailAlreadyExists, create_user
|
from max.db import EmailAlreadyExists, create_user, get_domains
|
||||||
from max.permissions import AllowAdmin
|
from max.permissions import AllowAdmin
|
||||||
from max.translations import t
|
from max.translations import t
|
||||||
from max.views import BaseTemplateGetView
|
from max.views import BaseTemplateGetView
|
||||||
@ -22,7 +22,18 @@ class UserCreate(AllowAdmin, CheckEmailMixin, BackToUsersMixin, BaseTemplateGetV
|
|||||||
else:
|
else:
|
||||||
self.email = email
|
self.email = email
|
||||||
|
|
||||||
if not self.is_email_valid(email):
|
domain = self.request.form.get("domain")
|
||||||
|
if not isinstance(domain, str) or not domain:
|
||||||
|
flash(t("Domain must be given"), category="error")
|
||||||
|
error = True
|
||||||
|
elif domain not in get_domains():
|
||||||
|
flash(t("Invalid domain"), category="error")
|
||||||
|
error = True
|
||||||
|
else:
|
||||||
|
self.domain = domain
|
||||||
|
|
||||||
|
full_email = f"{self.email}@{self.domain}"
|
||||||
|
if not self.is_email_valid(full_email):
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
pw1 = self.request.form.get("password1")
|
pw1 = self.request.form.get("password1")
|
||||||
@ -57,6 +68,17 @@ class UserCreate(AllowAdmin, CheckEmailMixin, BackToUsersMixin, BaseTemplateGetV
|
|||||||
flash(t("Admin is not set"), category="error")
|
flash(t("Admin is not set"), category="error")
|
||||||
error = True
|
error = True
|
||||||
|
|
||||||
|
can_use_different_alias_domain = self.request.form.get(
|
||||||
|
"can_use_different_alias_domain"
|
||||||
|
)
|
||||||
|
if can_use_different_alias_domain == "on":
|
||||||
|
self.can_use_different_alias_domain = True
|
||||||
|
elif can_use_different_alias_domain is None:
|
||||||
|
self.can_use_different_alias_domain = False
|
||||||
|
else:
|
||||||
|
flash(t("Can use different alias domains is not set"), category="error")
|
||||||
|
error = True
|
||||||
|
|
||||||
note = self.request.form.get("note", "")
|
note = self.request.form.get("note", "")
|
||||||
if not isinstance(note, str):
|
if not isinstance(note, str):
|
||||||
flash(t("Note must be a string"), category="error")
|
flash(t("Note must be a string"), category="error")
|
||||||
@ -70,7 +92,12 @@ class UserCreate(AllowAdmin, CheckEmailMixin, BackToUsersMixin, BaseTemplateGetV
|
|||||||
passwordhash = hash_password(self.password)
|
passwordhash = hash_password(self.password)
|
||||||
try:
|
try:
|
||||||
create_user(
|
create_user(
|
||||||
self.email, passwordhash, self.enabled, self.is_admin, self.note
|
full_email,
|
||||||
|
passwordhash,
|
||||||
|
self.enabled,
|
||||||
|
self.is_admin,
|
||||||
|
self.can_use_different_alias_domain,
|
||||||
|
self.note,
|
||||||
)
|
)
|
||||||
except EmailAlreadyExists as e:
|
except EmailAlreadyExists as e:
|
||||||
if self.auth_user.is_admin:
|
if self.auth_user.is_admin:
|
||||||
@ -82,14 +109,26 @@ class UserCreate(AllowAdmin, CheckEmailMixin, BackToUsersMixin, BaseTemplateGetV
|
|||||||
flash(t("Email already exists."))
|
flash(t("Email already exists."))
|
||||||
return
|
return
|
||||||
|
|
||||||
flash(t("Creation of {email} was successful!", email=email), category="success")
|
flash(
|
||||||
|
t("Creation of {email} was successful!", email=full_email),
|
||||||
|
category="success",
|
||||||
|
)
|
||||||
return self.redirect()
|
return self.redirect()
|
||||||
|
|
||||||
def get_context(self):
|
def get_context(self):
|
||||||
context = super().get_context()
|
context = super().get_context()
|
||||||
for key in ("email", "password", "enabled", "is_admin", "note"):
|
for key in (
|
||||||
|
"email",
|
||||||
|
"domain",
|
||||||
|
"password",
|
||||||
|
"enabled",
|
||||||
|
"is_admin",
|
||||||
|
"can_use_different_alias_domain",
|
||||||
|
"note",
|
||||||
|
):
|
||||||
if hasattr(self, key):
|
if hasattr(self, key):
|
||||||
context[key] = getattr(self, key)
|
context[key] = getattr(self, key)
|
||||||
|
context["domains"] = get_domains()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_webpagetitle(self):
|
def get_webpagetitle(self):
|
||||||
|
|||||||
19
max/routes/user/toggle_can_use_different_alias_domain.py
Normal file
19
max/routes/user/toggle_can_use_different_alias_domain.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from max.db import update_user
|
||||||
|
from max.permissions import AllowAdmin
|
||||||
|
from max.views import BaseView
|
||||||
|
|
||||||
|
from ..base_user_views import BackToUsersMixin, FetchUserMixin
|
||||||
|
|
||||||
|
|
||||||
|
class UserToggleCanUseDifferentAliasDomain(
|
||||||
|
AllowAdmin, FetchUserMixin, BackToUsersMixin, BaseView
|
||||||
|
):
|
||||||
|
def post(self):
|
||||||
|
update_user(
|
||||||
|
self.user.id,
|
||||||
|
can_use_different_alias_domain=(
|
||||||
|
not self.user.can_use_different_alias_domain
|
||||||
|
),
|
||||||
|
)
|
||||||
|
_, back_url = self.get_back_text_and_url()
|
||||||
|
return self.redirect(back_url)
|
||||||
@ -193,6 +193,10 @@ form {
|
|||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.domain-selector {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
body {
|
body {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
@ -7,7 +7,18 @@
|
|||||||
<form id="form" class="pure-form pure-form-aligned" action="{{ url_for('alias-create', user_id=user.id) }}" method="post">
|
<form id="form" class="pure-form pure-form-aligned" action="{{ url_for('alias-create', user_id=user.id) }}" method="post">
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<label for="email">{{ t("Email") }}</label>
|
<label for="email">{{ t("Email") }}</label>
|
||||||
<input id="email" type="email" name="email" {% if email is defined %}value="{{ email }}"{% endif %} placeholder="{{ t("Email") }}">
|
<input id="email" type="text" name="email" {% if email is defined %}value="{{ email }}"{% endif %} placeholder="{{ t("Email") }}">
|
||||||
|
|
||||||
|
<div class="domain-selector">
|
||||||
|
{% if can_use_different_alias_domain %}
|
||||||
|
@
|
||||||
|
<select id="domain" name="domain">
|
||||||
|
{% for d in domains %}<option{% if d == domain %} selected{% endif %}>{{ d }}</option>{% endfor %}
|
||||||
|
</select>
|
||||||
|
{% else %}
|
||||||
|
@{{ domain }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-controls checkbox">
|
<div class="pure-controls checkbox">
|
||||||
|
|||||||
@ -7,7 +7,14 @@
|
|||||||
<form id="form" class="pure-form pure-form-aligned" action="{{ url_for('user-create') }}" method="post">
|
<form id="form" class="pure-form pure-form-aligned" action="{{ url_for('user-create') }}" method="post">
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<label for="email">{{ t("Email") }}</label>
|
<label for="email">{{ t("Email") }}</label>
|
||||||
<input id="email" type="email" name="email" {% if email is defined %}value="{{ email }}"{% endif %} placeholder="{{ t("Email") }}">
|
<input id="email" type="text" name="email" {% if email is defined %}value="{{ email }}"{% endif %} placeholder="{{ t("Email") }}">
|
||||||
|
|
||||||
|
<div class="domain-selector">
|
||||||
|
@
|
||||||
|
<select id="domain" name="domain">
|
||||||
|
{% for d in domains %}<option{% if d == domain %} selected{% endif %}>{{ d }}</option>{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
@ -34,6 +41,13 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="pure-controls checkbox">
|
||||||
|
<label for="can_use_different_alias_domain">
|
||||||
|
<input id="can_use_different_alias_domain" type="checkbox" name="can_use_different_alias_domain" {% if can_use_different_alias_domain %}checked{% endif %}>
|
||||||
|
{{ t("Can use different alias domains") }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="pure-control-group">
|
<div class="pure-control-group">
|
||||||
<label for="note">{{ t("Note") }}</label>
|
<label for="note">{{ t("Note") }}</label>
|
||||||
<textarea id="note" name="note" form="form">{% if note is defined %}{{ note }}{% endif %}</textarea>
|
<textarea id="note" name="note" form="form">{% if note is defined %}{{ note }}{% endif %}</textarea>
|
||||||
|
|||||||
@ -24,6 +24,10 @@
|
|||||||
<b>{{ t("Admin") }}:</b>
|
<b>{{ t("Admin") }}:</b>
|
||||||
{{ macros.checkbox(user, "is_admin", url_for('user-toggle-admin', user_id=user.id, return='detail')) }}
|
{{ macros.checkbox(user, "is_admin", url_for('user-toggle-admin', user_id=user.id, return='detail')) }}
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<b>{{ t("Can use different alias domains") }}:</b>
|
||||||
|
{{ macros.checkbox(user, "can_use_different_alias_domain", url_for('user-toggle-can-use-different-alias-domain', user_id=user.id, return='detail')) }}
|
||||||
|
</div>
|
||||||
<div class="note">
|
<div class="note">
|
||||||
<b>{{ t("Note") }}:</b><div>{{ macros.format_note(user) }}</div>
|
<b>{{ t("Note") }}:</b><div>{{ macros.format_note(user) }}</div>
|
||||||
<a href="{{ url_for('user-edit-note', user_id=user.id, return='detail') }}" class="button-small pure-button optional">
|
<a href="{{ url_for('user-edit-note', user_id=user.id, return='detail') }}" class="button-small pure-button optional">
|
||||||
|
|||||||
@ -5,6 +5,7 @@ set -e
|
|||||||
source db-setup.sh
|
source db-setup.sh
|
||||||
|
|
||||||
flask add-domain finn.st
|
flask add-domain finn.st
|
||||||
|
flask add-domain stutzenste.in
|
||||||
flask reset-admin admin@finn.st admin
|
flask reset-admin admin@finn.st admin
|
||||||
|
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user