diff --git a/app/blueprints/users/settings.py b/app/blueprints/users/settings.py index 85ea151..b9e6fab 100644 --- a/app/blueprints/users/settings.py +++ b/app/blueprints/users/settings.py @@ -1,6 +1,7 @@ from flask import * from flask_login import current_user, login_required, logout_user from flask_wtf import FlaskForm +from sqlalchemy import or_ from wtforms import * from wtforms.validators import * @@ -36,11 +37,39 @@ def get_setting_tabs(user): class UserProfileForm(FlaskForm): + display_name = StringField("Display Name", [Optional(), Length(1, 20)], filters=[lambda x: nonEmptyOrNone(x)]) website_url = StringField("Website URL", [Optional(), URL()], filters = [lambda x: x or None]) donate_url = StringField("Donation URL", [Optional(), URL()], filters = [lambda x: x or None]) submit = SubmitField("Save") +def handle_profile_edit(form, user, username): + severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION + addAuditLog(severity, current_user, "Edited {}'s profile".format(user.display_name), + url_for("users.profile", username=username)) + + if user.checkPerm(current_user, Permission.CHANGE_DISPLAY_NAME) and \ + user.display_name != form.display_name.data: + if User.query.filter(id != user.id, + or_(User.username == form.display_name.data, + User.display_name.ilike(form.display_name.data))).count() > 0: + flash("A user already has that name", "danger") + return None + + user.display_name = form.display_name.data + addAuditLog(severity, current_user, "Changed display name of {} to {}" + .format(user.username, user.display_name), + url_for("users.profile", username=username)) + + if user.checkPerm(current_user, Permission.CHANGE_PROFILE_URLS): + user.website_url = form["website_url"].data + user.donate_url = form["donate_url"].data + + db.session.commit() + + return redirect(url_for("users.profile", username=username)) + + @bp.route("/users//settings/profile/", methods=["GET", "POST"]) @login_required def profile_edit(username): @@ -54,17 +83,9 @@ def profile_edit(username): form = UserProfileForm(obj=user) if form.validate_on_submit(): - severity = AuditSeverity.NORMAL if current_user == user else AuditSeverity.MODERATION - addAuditLog(severity, current_user, "Edited {}'s profile".format(user.display_name), - url_for("users.profile", username=username)) - - if user.checkPerm(current_user, Permission.CHANGE_PROFILE_URLS): - user.website_url = form["website_url"].data - user.donate_url = form["donate_url"].data - - db.session.commit() - - return redirect(url_for("users.profile", username=username)) + ret = handle_profile_edit(form, user, username) + if ret: + return ret # Process GET or invalid POST return render_template("users/profile_edit.html", user=user, form=form, tabs=get_setting_tabs(user), current_tab="edit_profile") diff --git a/app/models/users.py b/app/models/users.py index 0aa8372..fe461d3 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -88,6 +88,7 @@ class Permission(enum.Enum): CREATE_TOKEN = "CREATE_TOKEN" EDIT_MAINTAINERS = "EDIT_MAINTAINERS" CHANGE_PROFILE_URLS = "CHANGE_PROFILE_URLS" + CHANGE_DISPLAY_NAME = "CHANGE_DISPLAY_NAME" # Only return true if the permission is valid for *all* contexts # See Package.checkPerm for package-specific contexts @@ -216,6 +217,8 @@ class User(db.Model, UserMixin): return user.rank.atLeast(UserRank.MODERATOR) elif perm == Permission.CHANGE_EMAIL or perm == Permission.CHANGE_PROFILE_URLS: return user == self or user.rank.atLeast(UserRank.ADMIN) + elif perm == Permission.CHANGE_DISPLAY_NAME: + return user.rank.atLeast(UserRank.MEMBER if user == self else UserRank.MODERATOR) elif perm == Permission.CREATE_TOKEN: if user == self: return user.rank.atLeast(UserRank.MEMBER) diff --git a/app/templates/admin/audit_view.html b/app/templates/admin/audit_view.html index 8955781..25df9b7 100644 --- a/app/templates/admin/audit_view.html +++ b/app/templates/admin/audit_view.html @@ -13,11 +13,11 @@ {% if entry.causer %}

- {{ _("Caused by %(author)s.", author=entry.causer.display_name) }} + {{ _("Caused by %(author)s.", author=entry.causer.username) }}

{% else %}

- {{ _("Caused by a deleted user.", author=entry.causer.display_name) }} + {{ _("Caused by a deleted user.") }}

{% endif %} diff --git a/app/templates/emails/notification.html b/app/templates/emails/notification.html index f5891d9..597f026 100644 --- a/app/templates/emails/notification.html +++ b/app/templates/emails/notification.html @@ -5,14 +5,12 @@ {{ notification.title }} - -

{% if notification.package %} {{ _("From %(username)s and on package %(package)s.", - username=notification.causer.display_name, package=notification.package.title) }} + username=notification.causer.username, package=notification.package.title) }} {% else %} - {{ _("From %(username)s.", username=notification.causer.display_name) }} + {{ _("From %(username)s.", username=notification.causer.username) }} {% endif %}

diff --git a/app/templates/emails/notification_digest.html b/app/templates/emails/notification_digest.html index 5cf6d58..67c68af 100644 --- a/app/templates/emails/notification_digest.html +++ b/app/templates/emails/notification_digest.html @@ -11,7 +11,7 @@ {% for notification in group %}
  • {{ notification.title }} - - {{ _("from %(username)s.", username=notification.causer.display_name) }} + {{ _("from %(username)s.", username=notification.causer.username) }}
  • {% endfor %} diff --git a/app/templates/macros/audit_log.html b/app/templates/macros/audit_log.html index 7700816..38c18ec 100644 --- a/app/templates/macros/audit_log.html +++ b/app/templates/macros/audit_log.html @@ -27,7 +27,7 @@ style="max-height: 22px;" src="{{ entry.causer.getProfilePicURL() }}" /> - {{ entry.causer.display_name }} + {{ entry.causer.username }} {% else %} Deleted User {% endif %} diff --git a/app/templates/threads/delete_reply.html b/app/templates/threads/delete_reply.html index 6c4061d..4865b56 100644 --- a/app/templates/threads/delete_reply.html +++ b/app/templates/threads/delete_reply.html @@ -8,7 +8,7 @@
    -

    Delete reply by {{ reply.author.display_name }}

    +

    Delete reply by {{ reply.author.username }}

    {{ reply.comment | markdown }}
    diff --git a/app/templates/threads/delete_thread.html b/app/templates/threads/delete_thread.html index 5552546..804263b 100644 --- a/app/templates/threads/delete_thread.html +++ b/app/templates/threads/delete_thread.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block title %} - {{ _('Delete "%(title)s" by %(author)s', title=thread.title, author=thread.author.display_name) }} + {{ _('Delete "%(title)s" by %(author)s', title=thread.title, author=thread.author.username) }} {% endblock %} {% block content %} diff --git a/app/templates/users/delete.html b/app/templates/users/delete.html index 9e9057f..ed3a43a 100644 --- a/app/templates/users/delete.html +++ b/app/templates/users/delete.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block title %} - Delete user {{ user.display_name }} + Delete user {{ user.username }} {% endblock %} {% block content %} diff --git a/app/templates/users/list.html b/app/templates/users/list.html index bfe07fe..99b63b2 100644 --- a/app/templates/users/list.html +++ b/app/templates/users/list.html @@ -49,6 +49,11 @@ {{ user.display_name }} + {% if user.username != user.display_name %} + + ({{ user.username }}) + + {% endif %}
    diff --git a/app/templates/users/profile_edit.html b/app/templates/users/profile_edit.html index 1135bac..5f31e6e 100644 --- a/app/templates/users/profile_edit.html +++ b/app/templates/users/profile_edit.html @@ -48,6 +48,10 @@ {{ form.hidden_tag() }} + {% if user.checkPerm(current_user, "CHANGE_DISPLAY_NAME") %} + {{ render_field(form.display_name, tabindex=230, hint=_("Pretending to be another user is grounds for a permanent ban")) }} + {% endif %} + {% if user.checkPerm(current_user, "CHANGE_PROFILE_URLS") %} {{ render_field(form.website_url, tabindex=232) }} {{ render_field(form.donate_url, tabindex=233) }}