From 5e34252cb4b6a124b5323ec06fb6db2df3eefbda Mon Sep 17 00:00:00 2001 From: Inga Kirschnick Date: Fri, 23 Dec 2022 09:55:46 +0100 Subject: [PATCH 1/2] Fix ID/Hashid Problem --- app/profile/routes.py | 5 ++++- app/templates/profile/profile.html.j2 | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/profile/routes.py b/app/profile/routes.py index 60eef6ad..bbbf99e6 100644 --- a/app/profile/routes.py +++ b/app/profile/routes.py @@ -33,13 +33,16 @@ def profile(user_id): abort(403) return render_template( 'profile/profile.html.j2', - user=user.to_json_serializeable() + user=user.to_json_serializeable(), + user_id=user_id ) @bp.route('//avatar') def profile_avatar(user_id): + print(user_id) user = User.query.get_or_404(user_id) + print(user) if user.avatar is None: abort(404) if not user.is_public and not (user == current_user or current_user.is_administrator()): diff --git a/app/templates/profile/profile.html.j2 b/app/templates/profile/profile.html.j2 index 37077ca3..b8c0ad19 100644 --- a/app/templates/profile/profile.html.j2 +++ b/app/templates/profile/profile.html.j2 @@ -13,7 +13,7 @@

{% if user.avatar %} - user-image + user-image {% else %} user-image {% endif %} From 647969ef0e1472ca51952272c05fe14ead113553 Mon Sep 17 00:00:00 2001 From: Inga Kirschnick Date: Fri, 23 Dec 2022 18:08:33 +0100 Subject: [PATCH 2/2] profile to users --- app/__init__.py | 3 - app/admin/routes.py | 2 +- app/profile/__init__.py | 5 - app/profile/routes.py | 138 ----------------- .../js/RessourceLists/PublicUserList.js | 4 +- app/static/js/Utils.js | 2 +- app/templates/_navbar.html.j2 | 2 +- app/templates/_sidenav.html.j2 | 4 +- .../{profile => users}/edit_profile.html.j2 | 0 .../{profile => users}/profile.html.j2 | 0 app/{profile => users}/forms.py | 0 app/users/routes.py | 144 +++++++++++++++++- 12 files changed, 147 insertions(+), 157 deletions(-) delete mode 100644 app/profile/__init__.py delete mode 100644 app/profile/routes.py rename app/templates/{profile => users}/edit_profile.html.j2 (100%) rename app/templates/{profile => users}/profile.html.j2 (100%) rename app/{profile => users}/forms.py (100%) diff --git a/app/__init__.py b/app/__init__.py index 77742800..cc747a89 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -77,9 +77,6 @@ def create_app(config: Config = Config) -> Flask: from .main import bp as main_blueprint app.register_blueprint(main_blueprint, url_prefix='/') - - from .profile import bp as profile_blueprint - app.register_blueprint(profile_blueprint, url_prefix='/profile') from .services import bp as services_blueprint app.register_blueprint(services_blueprint, url_prefix='/services') diff --git a/app/admin/routes.py b/app/admin/routes.py index 2f50b999..b14c52fb 100644 --- a/app/admin/routes.py +++ b/app/admin/routes.py @@ -7,7 +7,7 @@ from app.models import Role, User, UserSettingJobStatusMailNotificationLevel from app.settings.forms import ( EditNotificationSettingsForm ) -from app.profile.forms import EditProfileSettingsForm +from app.users.forms import EditProfileSettingsForm from . import bp from .forms import AdminEditUserForm diff --git a/app/profile/__init__.py b/app/profile/__init__.py deleted file mode 100644 index c8f843f4..00000000 --- a/app/profile/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from flask import Blueprint - - -bp = Blueprint('profile', __name__) -from . import routes # noqa diff --git a/app/profile/routes.py b/app/profile/routes.py deleted file mode 100644 index bbbf99e6..00000000 --- a/app/profile/routes.py +++ /dev/null @@ -1,138 +0,0 @@ -from flask import ( - abort, - current_app, - flash, - Markup, - redirect, - render_template, - send_from_directory, - url_for -) -from flask_login import current_user, login_required -from threading import Thread -import os -from app import db -from app.models import Avatar, ProfilePrivacySettings, User -from . import bp -from .forms import ( - EditPrivacySettingsForm, - EditProfileSettingsForm, - EditPublicProfileInformationForm -) - -@bp.before_request -@login_required -def before_request(): - pass - - -@bp.route('/') -def profile(user_id): - user = User.query.get_or_404(user_id) - if not user.is_public and user != current_user: - abort(403) - return render_template( - 'profile/profile.html.j2', - user=user.to_json_serializeable(), - user_id=user_id - ) - - -@bp.route('//avatar') -def profile_avatar(user_id): - print(user_id) - user = User.query.get_or_404(user_id) - print(user) - if user.avatar is None: - abort(404) - if not user.is_public and not (user == current_user or current_user.is_administrator()): - abort(403) - return send_from_directory( - os.path.dirname(user.avatar.path), - os.path.basename(user.avatar.path), - as_attachment=True, - attachment_filename=user.avatar.filename, - mimetype=user.avatar.mimetype - ) - - -@bp.route('//avatar', methods=['DELETE']) -def delete_profile_avatar(user_id): - def _delete_avatar(app, avatar_id): - with app.app_context(): - avatar = Avatar.query.get(avatar_id) - avatar.delete() - db.session.commit() - - user = User.query.get_or_404(user_id) - if user.avatar is None: - abort(404) - thread = Thread( - target=_delete_avatar, - args=(current_app._get_current_object(), user.avatar.id) - ) - thread.start() - return {}, 202 - - -@bp.route('//edit', methods=['GET', 'POST']) -def edit_profile(user_id): - user = User.query.get_or_404(user_id) - edit_profile_settings_form = EditProfileSettingsForm( - current_user, - data=current_user.to_json_serializeable(), - prefix='edit-profile-settings-form' - ) - edit_privacy_settings_form = EditPrivacySettingsForm( - data=current_user.to_json_serializeable(), - prefix='edit-privacy-settings-form' - ) - edit_public_profile_information_form = EditPublicProfileInformationForm( - data=current_user.to_json_serializeable(), - prefix='edit-public-profile-information-form' - ) - if edit_profile_settings_form.validate_on_submit(): - current_user.email = edit_profile_settings_form.email.data - current_user.username = edit_profile_settings_form.username.data - db.session.commit() - flash('Profile settings updated') - return redirect(url_for('.profile', user_id=user.id)) - if edit_privacy_settings_form.submit.data and edit_privacy_settings_form.validate(): - current_user.is_public = edit_privacy_settings_form.is_public.data - if edit_privacy_settings_form.show_email.data: - current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL) - else: - current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL) - if edit_privacy_settings_form.show_last_seen.data: - current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) - else: - current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) - if edit_privacy_settings_form.show_member_since.data: - current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) - else: - current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) - db.session.commit() - flash('Your changes have been saved') - return redirect(url_for('.profile', user_id=user.id)) - if edit_public_profile_information_form.validate_on_submit(): - if edit_public_profile_information_form.avatar.data: - try: - Avatar.create(edit_public_profile_information_form.avatar.data, user=current_user) - except (AttributeError, OSError): - abort(500) - current_user.about_me = edit_public_profile_information_form.about_me.data - current_user.location = edit_public_profile_information_form.location.data - current_user.organization = edit_public_profile_information_form.organization.data - current_user.website = edit_public_profile_information_form.website.data - current_user.full_name = edit_public_profile_information_form.full_name.data - db.session.commit() - flash('Profile settings updated') - return redirect(url_for('.profile', user_id=user.id)) - return render_template( - 'profile/edit_profile.html.j2', - edit_profile_settings_form=edit_profile_settings_form, - edit_privacy_settings_form=edit_privacy_settings_form, - edit_public_profile_information_form=edit_public_profile_information_form, - user=user, - title='Edit Profile' - ) diff --git a/app/static/js/RessourceLists/PublicUserList.js b/app/static/js/RessourceLists/PublicUserList.js index f5c93b8b..1a1d7bf5 100644 --- a/app/static/js/RessourceLists/PublicUserList.js +++ b/app/static/js/RessourceLists/PublicUserList.js @@ -47,7 +47,7 @@ class PublicUserList extends RessourceList { return { 'id': user.id, 'member-since': user.member_since, - 'avatar': user.avatar ? `/profile/${user.id}/avatar` : '/static/images/user_avatar.png', + 'avatar': user.avatar ? `/users/${user.id}/avatar` : '/static/images/user_avatar.png', 'username': user.username, 'full-name': user.full_name ? user.full_name : '', 'location': user.location ? user.location : '', @@ -83,7 +83,7 @@ class PublicUserList extends RessourceList { let publicUserId = publicUserElement.dataset.id; switch (action) { case 'view': { - window.location.href = `/profile/${publicUserId}`; + window.location.href = `/users/${publicUserId}`; break; } default: { diff --git a/app/static/js/Utils.js b/app/static/js/Utils.js index c38c5620..5d98bcc8 100644 --- a/app/static/js/Utils.js +++ b/app/static/js/Utils.js @@ -257,7 +257,7 @@ class Utils { let confirmElement = modalElement.querySelector('.action-button[data-action="confirm"]'); confirmElement.addEventListener('click', (event) => { - fetch(`/profile/${userId}/avatar`, {method: 'DELETE', headers: {Accept: 'application/json'}}) + fetch(`/users/${userId}/avatar`, {method: 'DELETE', headers: {Accept: 'application/json'}}) .then( (response) => { if (response.status === 403) {app.flash('Forbidden', 'error'); reject(response);} diff --git a/app/templates/_navbar.html.j2 b/app/templates/_navbar.html.j2 index d90118b8..d943c0e4 100644 --- a/app/templates/_navbar.html.j2 +++ b/app/templates/_navbar.html.j2 @@ -30,7 +30,7 @@
  • helpManual
  • {% if current_user.is_authenticated %}
  • settingsGeneral settings
  • -
  • contact_pageProfile settings
  • +
  • contact_pageProfile settings
  • Log out
  • {% else %} diff --git a/app/templates/_sidenav.html.j2 b/app/templates/_sidenav.html.j2 index ffdf86a6..886efc40 100644 --- a/app/templates/_sidenav.html.j2 +++ b/app/templates/_sidenav.html.j2 @@ -4,7 +4,7 @@
    @@ -34,7 +34,7 @@
  • Account
  • settingsGeneral Settings
  • -
  • contact_pageProfile settings
  • +
  • contact_pageProfile settings
  • Log out
  • {% if current_user.can(Permission.ADMINISTRATE) or current_user.can(Permission.USE_API) %}
  • diff --git a/app/templates/profile/edit_profile.html.j2 b/app/templates/users/edit_profile.html.j2 similarity index 100% rename from app/templates/profile/edit_profile.html.j2 rename to app/templates/users/edit_profile.html.j2 diff --git a/app/templates/profile/profile.html.j2 b/app/templates/users/profile.html.j2 similarity index 100% rename from app/templates/profile/profile.html.j2 rename to app/templates/users/profile.html.j2 diff --git a/app/profile/forms.py b/app/users/forms.py similarity index 100% rename from app/profile/forms.py rename to app/users/forms.py diff --git a/app/users/routes.py b/app/users/routes.py index 4c06cad3..48a8d7b5 100644 --- a/app/users/routes.py +++ b/app/users/routes.py @@ -1,16 +1,41 @@ -from flask import abort, current_app +from flask import ( + abort, + current_app, + flash, + Markup, + redirect, + render_template, + send_from_directory, + url_for +) from flask_login import current_user, login_required from threading import Thread +import os from app import db -from app.models import User +from app.models import Avatar, ProfilePrivacySettings, User from . import bp +from .forms import ( + EditPrivacySettingsForm, + EditProfileSettingsForm, + EditPublicProfileInformationForm +) +@bp.before_request +@login_required +def before_request(): + pass @bp.route('/') @login_required def user(user_id): - abort(503) - + user = User.query.get_or_404(user_id) + if not user.is_public and user != current_user: + abort(403) + return render_template( + 'users/profile.html.j2', + user=user.to_json_serializeable(), + user_id=user_id + ) @bp.route('/', methods=['DELETE']) @login_required @@ -30,3 +55,114 @@ def delete_user(user_id): ) thread.start() return {}, 202 + +@bp.route('/') +def profile(user_id): + user = User.query.get_or_404(user_id) + if not user.is_public and user != current_user: + abort(403) + return render_template( + 'users/profile.html.j2', + user=user.to_json_serializeable(), + user_id=user_id + ) + + +@bp.route('//avatar') +def profile_avatar(user_id): + user = User.query.get_or_404(user_id) + if user.avatar is None: + abort(404) + if not user.is_public and not (user == current_user or current_user.is_administrator()): + abort(403) + return send_from_directory( + os.path.dirname(user.avatar.path), + os.path.basename(user.avatar.path), + as_attachment=True, + attachment_filename=user.avatar.filename, + mimetype=user.avatar.mimetype + ) + + +@bp.route('//avatar', methods=['DELETE']) +def delete_profile_avatar(user_id): + def _delete_avatar(app, avatar_id): + with app.app_context(): + avatar = Avatar.query.get(avatar_id) + avatar.delete() + db.session.commit() + + user = User.query.get_or_404(user_id) + if user.avatar is None: + abort(404) + thread = Thread( + target=_delete_avatar, + args=(current_app._get_current_object(), user.avatar.id) + ) + thread.start() + return {}, 202 + + +@bp.route('//edit', methods=['GET', 'POST']) +def edit_profile(user_id): + user = User.query.get_or_404(user_id) + if not (user == current_user or current_user.is_administrator()): + abort(403) + edit_profile_settings_form = EditProfileSettingsForm( + current_user, + data=current_user.to_json_serializeable(), + prefix='edit-profile-settings-form' + ) + edit_privacy_settings_form = EditPrivacySettingsForm( + data=current_user.to_json_serializeable(), + prefix='edit-privacy-settings-form' + ) + edit_public_profile_information_form = EditPublicProfileInformationForm( + data=current_user.to_json_serializeable(), + prefix='edit-public-profile-information-form' + ) + if edit_profile_settings_form.validate_on_submit(): + current_user.email = edit_profile_settings_form.email.data + current_user.username = edit_profile_settings_form.username.data + db.session.commit() + flash('Profile settings updated') + return redirect(url_for('.user', user_id=user.id)) + if edit_privacy_settings_form.submit.data and edit_privacy_settings_form.validate(): + current_user.is_public = edit_privacy_settings_form.is_public.data + if edit_privacy_settings_form.show_email.data: + current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL) + else: + current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_EMAIL) + if edit_privacy_settings_form.show_last_seen.data: + current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) + else: + current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_LAST_SEEN) + if edit_privacy_settings_form.show_member_since.data: + current_user.add_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) + else: + current_user.remove_profile_privacy_setting(ProfilePrivacySettings.SHOW_MEMBER_SINCE) + db.session.commit() + flash('Your changes have been saved') + return redirect(url_for('.user', user_id=user.id)) + if edit_public_profile_information_form.validate_on_submit(): + if edit_public_profile_information_form.avatar.data: + try: + Avatar.create(edit_public_profile_information_form.avatar.data, user=current_user) + except (AttributeError, OSError): + abort(500) + current_user.about_me = edit_public_profile_information_form.about_me.data + current_user.location = edit_public_profile_information_form.location.data + current_user.organization = edit_public_profile_information_form.organization.data + current_user.website = edit_public_profile_information_form.website.data + current_user.full_name = edit_public_profile_information_form.full_name.data + db.session.commit() + flash('Profile settings updated') + return redirect(url_for('.user', user_id=user.id)) + return render_template( + 'users/edit_profile.html.j2', + edit_profile_settings_form=edit_profile_settings_form, + edit_privacy_settings_form=edit_privacy_settings_form, + edit_public_profile_information_form=edit_public_profile_information_form, + user=user, + title='Edit Profile' + )