modified: web/blueprints/site_admin.py
modified: web/panel_db.py modified: web/templates/admin/user_edit.html modified: web/templates/admin/users.html
This commit is contained in:
@@ -352,28 +352,139 @@ def group_invite_resend(group_id, invite_id):
|
||||
@site_admin.route("/users")
|
||||
@admin_required
|
||||
def users():
|
||||
return render_template("admin/users.html", users=db.list_all_users())
|
||||
return render_template(
|
||||
"admin/users.html",
|
||||
users=db.list_all_users(),
|
||||
pending_invites=db.list_all_active_invites(),
|
||||
)
|
||||
|
||||
|
||||
@site_admin.route("/users/new", methods=["GET", "POST"])
|
||||
@admin_required
|
||||
def user_new():
|
||||
groups = db.list_all_groups()
|
||||
if request.method == "POST":
|
||||
username = request.form.get("username", "").strip()
|
||||
email = request.form.get("email", "").strip()
|
||||
password = request.form.get("password", "")
|
||||
is_site_admin = request.form.get("is_site_admin") == "1"
|
||||
if not username or not email or not password:
|
||||
flash("All fields are required.", "danger")
|
||||
group_id_raw = request.form.get("group_id", "").strip()
|
||||
role = request.form.get("role", "viewer")
|
||||
group_id = int(group_id_raw) if group_id_raw else None
|
||||
|
||||
error = None
|
||||
if not username or not email:
|
||||
error = "Username and email are required."
|
||||
elif db.get_user_by_username(username):
|
||||
flash("Username already taken.", "danger")
|
||||
error = "Username already taken."
|
||||
elif db.get_user_by_email(email):
|
||||
flash("Email address already in use.", "danger")
|
||||
error = "Email address already in use."
|
||||
elif db.get_active_invite_by_username_global(username):
|
||||
error = "There is already an active invitation for this username."
|
||||
elif db.get_active_invite_by_email_global(email):
|
||||
error = "There is already an active invitation for this email."
|
||||
elif group_id and role not in GROUP_ROLE_SET:
|
||||
error = "Invalid role selected."
|
||||
|
||||
if error:
|
||||
flash(error, "danger")
|
||||
return render_template("admin/user_edit.html", user=None, groups=groups)
|
||||
|
||||
effective_role = role if group_id else "member"
|
||||
token = db.create_group_invite(group_id, username, email, effective_role,
|
||||
session["user_id"], is_site_admin=is_site_admin)
|
||||
invite_url = url_for("auth.accept_invite", token=token, _external=True)
|
||||
mail_settings = db.get_site_mail_settings()
|
||||
|
||||
if mail_settings:
|
||||
if group_id:
|
||||
group = db.get_group_by_id(group_id)
|
||||
subject = f"Invitation to join {group['name']}"
|
||||
body = (
|
||||
f"Hello {username},\n\n"
|
||||
f"You have been invited to join the group '{group['name']}' on MCLogger"
|
||||
f" as {role_label(effective_role)}.\n"
|
||||
f"Open this link to create your account:\n\n{invite_url}\n\n"
|
||||
f"This invite expires in {Config.INVITE_EXPIRY_HOURS} hours.\n"
|
||||
)
|
||||
else:
|
||||
subject = "You have been invited to MCLogger"
|
||||
body = (
|
||||
f"Hello {username},\n\n"
|
||||
f"You have been invited to create an account on MCLogger.\n"
|
||||
f"Open this link to create your account:\n\n{invite_url}\n\n"
|
||||
f"This invite expires in {Config.INVITE_EXPIRY_HOURS} hours.\n"
|
||||
)
|
||||
try:
|
||||
send_mail(mail_settings, email, subject, body)
|
||||
invite = db.get_invite_by_token(token)
|
||||
if invite:
|
||||
db.mark_invite_sent_global(invite["id"])
|
||||
flash(f"Invitation email sent to '{email}'.", "success")
|
||||
except Exception:
|
||||
flash(
|
||||
f"Invitation created, but email delivery failed. "
|
||||
f"Share this link manually: {invite_url}",
|
||||
"warning",
|
||||
)
|
||||
else:
|
||||
db.create_user(username, email, password, is_site_admin)
|
||||
flash(f"User '{username}' created.", "success")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
return render_template("admin/user_edit.html", user=None)
|
||||
flash(f"Invitation created for '{username}'. Share this link: {invite_url}", "success")
|
||||
|
||||
return redirect(url_for("site_admin.users"))
|
||||
return render_template("admin/user_edit.html", user=None, groups=groups)
|
||||
|
||||
|
||||
@site_admin.route("/users/invites/<int:invite_id>/revoke", methods=["POST"])
|
||||
@admin_required
|
||||
def user_invite_revoke(invite_id):
|
||||
db.revoke_invite_global(invite_id)
|
||||
flash("Invitation revoked.", "success")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
|
||||
|
||||
@site_admin.route("/users/invites/<int:invite_id>/resend", methods=["POST"])
|
||||
@admin_required
|
||||
def user_invite_resend(invite_id):
|
||||
invite = db.get_invite_by_id_global(invite_id)
|
||||
if not invite:
|
||||
flash("Invitation not found.", "danger")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
if invite.get("accepted_at") or invite.get("revoked_at") or invite["expires_at"] <= datetime.utcnow():
|
||||
flash("Invitation is no longer active.", "danger")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
last_sent = invite.get("last_sent_at")
|
||||
if last_sent and (datetime.utcnow() - last_sent) < timedelta(seconds=Config.INVITE_RESEND_COOLDOWN_SECONDS):
|
||||
flash("Please wait before resending this invite again.", "warning")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
mail_settings = db.get_site_mail_settings()
|
||||
if not mail_settings:
|
||||
flash("No SMTP settings configured.", "danger")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
invite_url = url_for("auth.accept_invite", token=invite["token"], _external=True)
|
||||
if invite["group_id"]:
|
||||
group = db.get_group_by_id(invite["group_id"])
|
||||
subject = f"Invitation to join {group['name']}"
|
||||
body = (
|
||||
f"Hello {invite['invited_username']},\n\n"
|
||||
f"You have been invited to join the group '{group['name']}' on MCLogger"
|
||||
f" as {role_label(invite['role'])}.\n"
|
||||
f"Open this link to create your account:\n\n{invite_url}\n\n"
|
||||
f"This invite expires on {invite['expires_at']}.\n"
|
||||
)
|
||||
else:
|
||||
subject = "You have been invited to MCLogger"
|
||||
body = (
|
||||
f"Hello {invite['invited_username']},\n\n"
|
||||
f"You have been invited to create an account on MCLogger.\n"
|
||||
f"Open this link to create your account:\n\n{invite_url}\n\n"
|
||||
f"This invite expires on {invite['expires_at']}.\n"
|
||||
)
|
||||
try:
|
||||
send_mail(mail_settings, invite["invited_email"], subject, body)
|
||||
db.mark_invite_sent_global(invite_id)
|
||||
flash("Invitation email resent.", "success")
|
||||
except Exception:
|
||||
flash("Resend failed. Please verify SMTP settings and try again.", "danger")
|
||||
return redirect(url_for("site_admin.users"))
|
||||
|
||||
|
||||
@site_admin.route("/users/<int:user_id>/edit", methods=["GET", "POST"])
|
||||
|
||||
Reference in New Issue
Block a user