from flask import ( abort, current_app, Flask, jsonify, redirect, render_template, request, send_from_directory, url_for ) from flask_login import current_user, login_required, logout_user from threading import Thread from app import db from app.models import Avatar, User from . import bp @bp.route('') @login_required def index(): return redirect(url_for('main.social_area', _anchor='users')) @bp.route('/') @login_required def user(user_id: int): user = User.query.get_or_404(user_id) if not ( user.is_public or user == current_user or current_user.is_administrator ): abort(403) accept_json = request.accept_mimetypes.accept_json accept_html = request.accept_mimetypes.accept_html if accept_json and not accept_html: return user.to_json_serializeable( backrefs=True, relationships=True ) return render_template( 'users/user.html.j2', title=user.username, user=user ) def _delete_user(app: Flask, user_id: int): with app.app_context(): user = User.query.get(user_id) user.delete() db.session.commit() @bp.route('/', methods=['DELETE']) @login_required def delete_user(user_id: int): user = User.query.get_or_404(user_id) if not ( user == current_user or current_user.is_administrator ): abort(403) if user == current_user: logout_user() thread = Thread( target=_delete_user, args=(current_app._get_current_object(), user.id) ) thread.start() return jsonify(f'User "{user.username}" marked for deletion'), 202 @bp.route('//avatar') @login_required def user_avatar(user_id: int): user = User.query.get_or_404(user_id) if not ( user.is_public or user == current_user or current_user.is_administrator ): abort(403) if user.avatar is None: return redirect(url_for('static', filename='images/user_avatar.png')) return send_from_directory( user.avatar.path.parent, user.avatar.path.name, as_attachment=True, download_name=user.avatar.filename, mimetype=user.avatar.mimetype ) def _delete_avatar(app: Flask, avatar_id: int): with app.app_context(): avatar = Avatar.query.get(avatar_id) avatar.delete() db.session.commit() @bp.route('//avatar', methods=['DELETE']) @login_required def delete_user_avatar(user_id: int): user = User.query.get_or_404(user_id) if user.avatar is None: abort(409) if not ( user == current_user or current_user.is_administrator ): abort(403) thread = Thread( target=_delete_avatar, args=(current_app._get_current_object(), user.avatar.id) ) thread.start() return jsonify('Avatar marked for deletion'), 202 # TODO: Move this to main blueprint(?) @bp.route('/accept-terms-of-use', methods=['POST']) @login_required def accept_terms_of_use(): if not ( current_user.is_authenticated or current_user.confirmed ): abort(403) current_user.terms_of_use_accepted = True db.session.commit() return jsonify('You accepted the terms of use'), 202