Added password change form

This commit is contained in:
Yusur 2019-10-24 18:27:53 +02:00
parent a9006bf1bc
commit 5536e764e7
8 changed files with 111 additions and 10 deletions

View file

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% block body %}
<h2>Change Password</h2>
<form method="POST">
<dl>
<dt>Old password:</dt>
<dd><input type="password" name="old_password"></dd>
<dt>New password:</dt>
<dd><input type="password" name="new_password"></dd>
<dt>New password, again:</dt>
<dd><input type="password" name="confirm_password"></dd>
<dd><input type="submit" value="Save"></dd>
</dl>
</form>
{% endblock %}

View file

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% block body %}
<h2>Confirm Deletion</h2>
<p>Are you sure you want to permanently delete this post?
Neither you nor others will be able to see it;
you cannot recover a post after it's deleted.</p>
<p>If you only want to hide it from the public,
you can <a href="/edit/{{ message.id }}">set its privacy</a> to "Only me".</p>
<p>Here's the content of the message for reference:</p>
<ul>
<li>{% include "includes/message.html" %}</li>
</ul>
<form method="POST">
<input type="submit" value="Delete">
</form>
{% endblock %}

View file

@ -20,7 +20,7 @@
<ul class="message-options">
{% if message.user == current_user %}
<li><a href="/edit/{{ message.id }}">Edit or change privacy</a></li>
<!--li><a href="/confirm_delete/{{ message.id }}">Delete</a></li-->
<li><a href="/delete/{{ message.id }}">Delete permanently</a></li>
{% else %}
<!--li><a href="/report/{{ message.id }}">Report</a></li-->
{% endif %}

0
app/templates/user_list.html Executable file → Normal file
View file

View file

@ -2,10 +2,9 @@
A list of utilities used across modules.
'''
import datetime, re, base64, hashlib, string
import datetime, re, base64, hashlib, string, sys, json
from .models import User, Notification
from flask import abort, render_template, request, session
import sys, json
_forbidden_extensions = 'com net org txt'.split()
_username_characters = frozenset(string.ascii_letters + string.digits + '_')
@ -43,7 +42,7 @@ def int_to_b64(n):
return base64.b64encode(b).lstrip(b'A').decode()
def pwdhash(s):
return hashlib.md5((request.form['password']).encode('utf-8')).hexdigest()
return hashlib.md5(s.encode('utf-8')).hexdigest()
def get_object_or_404(model, *expressions):
try:
@ -160,3 +159,32 @@ def tokenize(characters, table):
break
pos = mo.end(0)
return tokens
def get_secret_key():
from . import app
secret_key = app.config['SECRET_KEY']
if isinstance(secret_key, str):
secret_key = secret_key.encode('utf-8')
return secret_key
def generate_access_token(user):
'''
Generate access token for public API.
'''
h = hashlib.sha256(get_secret_key())
h.update(b':')
h.update(str(user.id).encode('utf-8'))
h.update(b':')
h.update(str(user.password).encode('utf-8'))
return str(user.id) + ':' + h.hexdigest()[:32]
def check_access_token(user, token):
uid, hh = token.split(':')
if uid != user.get_id():
return False
h = hashlib.sha256(get_secret_key())
h.update(b':')
h.update(str(user.id).encode('utf-8'))
h.update(b':')
h.update(str(user.password).encode('utf-8'))
return h.hexdigest()[:32] == hh

View file

@ -29,8 +29,7 @@ def private_timeline():
.where((Message.user << user.following())
| (Message.user == user))
.order_by(Message.pub_date.desc()))
# TODO change to "feed.html"
return object_list('private_messages.html', messages, 'message_list')
return object_list('feed.html', messages, 'message_list')
@bp.route('/explore/')
def public_timeline():
@ -246,9 +245,15 @@ def edit(id):
return redirect(url_for('website.user_detail', username=user.username))
return render_template('edit.html', message=message)
#@bp.route('/delete/<int:id>', methods=['GET', 'POST'])
#def confirm_delete(id):
# return render_template('confirm_delete.html')
@bp.route('/delete/<int:id>', methods=['GET', 'POST'])
def confirm_delete(id):
user = get_current_user()
message = get_object_or_404(Message, Message.id == id)
if message.user != user:
abort(404)
if request.method == 'POST':
abort(501, 'CSRF-Token missing.')
return render_template('confirm_delete.html', message=message)
# Workaround for problems related to invalid data.
# Without that, changes will be lost across requests.
@ -261,7 +266,8 @@ def profile_checkpoint():
year=int(request.form['year'] if request.form.get('has_year') else '0'),
website=request.form['website'] or None,
instagram=request.form['instagram'] or None,
facebook=request.form['facebook'] or None
facebook=request.form['facebook'] or None,
telegram=request.form['telegram'] or None
)
@bp.route('/edit_profile/', methods=['GET', 'POST'])
@ -299,6 +305,30 @@ def edit_profile():
return redirect(url_for('website.user_detail', username=username))
return render_template('edit_profile.html')
@bp.route('/change_password/', methods=['GET', 'POST'])
def change_password():
user = get_current_user()
if request.method == 'POST':
old_password = request.form['old_password']
new_password = request.form['new_password']
confirm_password = request.form['confirm_password']
errors = False
if not new_password:
flash('Password cannot be empty')
errors = True
if new_password != confirm_password:
flash('Password mismatch')
errors = True
if pwdhash(old_password) != user.password:
flash('The old password is incorrect')
errors = True
if not errors:
user.update(
password=pwdhash(new_password)
)
return redirect(url_for('website.edit_profile'))
return render_template('change_password.html')
@bp.route('/notifications/')
@login_required
def notifications():