diff --git a/app/routes/users.py b/app/routes/users.py index 2290b67..a4eebf9 100644 --- a/app/routes/users.py +++ b/app/routes/users.py @@ -4,7 +4,12 @@ from flask import ( from functools import wraps from ..db import db from ..lib.babycode import babycode_to_html, BABYCODE_VERSION -from ..models import Users, Sessions, Subscriptions, Avatars, PasswordResetLinks, InviteKeys, BookmarkCollections, BookmarkedThreads, Mentions, PostHistory +from ..models import ( + Users, Sessions, Subscriptions, + Avatars, PasswordResetLinks, InviteKeys, + BookmarkCollections, BookmarkedThreads, + Mentions, PostHistory, + ) from ..constants import InfoboxKind, PermissionLevel from ..auth import digest, verify from wand.image import Image @@ -197,6 +202,53 @@ def get_prefers_theme(): return session['theme'] + +def anonymize_user(user_id): + deleted_user = Users.find({'username': 'deleteduser'}) + + from ..models import Threads, Posts + from ..lib.babycode import sanitize + threads = Threads.findall({'user_id': user_id}) + posts = Posts.findall({'user_id': user_id}) + + revs_q = """SELECT DISTINCT m.revision_id FROM mentions m + WHERE m.mentioned_user_id = ?""" + + mentioned_revs = db.query(revs_q, int(user_id)) + with db.transaction(): + for thread in threads: + thread.update({'user_id': int(deleted_user.id)}) + for post in posts: + post.update({'user_id': int(deleted_user.id)}) + + revs = {} + for rev in mentioned_revs: + ph = PostHistory.find({'id': int(rev['revision_id'])}) + ms = Mentions.findall({ + 'mentioned_user_id': int(user_id), + 'revision_id': int(rev['revision_id']) + }) + data = { + 'text': sanitize(ph.original_markup), + 'mentions': ms, + } + data['mentions'] = sorted(data['mentions'], key=lambda x: int(x.end_index), reverse=True) + revs[rev['revision_id']] = data + + for rev_id, data in revs.items(): + text = data['text'] + for mention in data['mentions']: + text = text[:mention.start_index] + '@deleteduser' + text[mention.end_index:] + mention.delete() + + res = babycode_to_html(text) + ph = PostHistory.find({'id': int(rev_id)}) + ph.update({ + 'original_markup': text.unescape(), + 'content': res.result, + }) + + @bp.get("/log_in") @redirect_if_logged_in(".page", username = lambda: get_active_user().username) def log_in(): @@ -756,3 +808,34 @@ def bookmark_collections(username): collections = target_user.get_bookmark_collections() return render_template('users/bookmark_collections.html', collections=collections) + + +@bp.get('//delete-account') +@login_required +@redirect_to_own +def delete_page(username): + target_user = get_active_user() + + return render_template('users/delete_page.html') + + +@bp.post('//delete-account') +@login_required +@redirect_to_own +def delete_page_confirm(username): + target_user = get_active_user() + + password = request.form.get('password', default='') + + if not verify(target_user.password_hash, password): + flash('Incorrect password.', InfoboxKind.ERROR) + return redirect(url_for('.delete_page', username=username)) + + anonymize_user(target_user.id) + sessions = Sessions.findall({'user_id': int(target_user.id)}) + for session_obj in sessions: + session_obj.delete() + + session.clear() + target_user.delete() + return redirect(url_for('topics.all_topics')) diff --git a/app/templates/users/delete_page.html b/app/templates/users/delete_page.html new file mode 100644 index 0000000..e0d715d --- /dev/null +++ b/app/templates/users/delete_page.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% block title %}delete confirmation{% endblock %} +{% block content %} + +{% endblock %} diff --git a/app/templates/users/settings.html b/app/templates/users/settings.html index a247aad..11a8c43 100644 --- a/app/templates/users/settings.html +++ b/app/templates/users/settings.html @@ -43,5 +43,8 @@
+
+ Delete account +
{% endblock %}