1
1
Fork 0

User settings,

moving endpoints,
restructuring forms
and some other BS
dev
Jan Kužílek 5 years ago
parent 6770ab7ec5
commit afe26e10e3

@ -0,0 +1,47 @@
"""empty message
Revision ID: b1a3eed8e38f
Revises: f4e1b4727000
Create Date: 2020-03-09 23:58:53.716242
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utc
# revision identifiers, used by Alembic.
revision = 'b1a3eed8e38f'
down_revision = 'f4e1b4727000'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('user_tags_blacklist',
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('tag_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['tag_id'], ['tag.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], )
)
op.add_column('user', sa.Column('ban_reason', sa.String(length=512), nullable=True))
op.add_column('user', sa.Column('ban_until', sqlalchemy_utc.sqltypes.UtcDateTime(timezone=True), nullable=True))
op.add_column('user', sa.Column('biography', sa.String(length=512), nullable=True))
op.add_column('user', sa.Column('rating', sa.Enum('safe', 'questionable', 'explicit', name='rating'), server_default='safe', nullable=False))
op.alter_column('user', 'op_level', server_default='user')
op.alter_column('user', 'user_status', server_default='active')
op.alter_column('post', 'status', server_default='pending')
op.alter_column('tag', 'category', server_default='general')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('user', 'rating')
op.drop_column('user', 'biography')
op.drop_column('user', 'ban_until')
op.drop_column('user', 'ban_reason')
op.drop_table('user_tags_blacklist')
# ### end Alembic commands ###

@ -114,10 +114,11 @@ def modify_post():
pass
else:
el = Post.query.filter_by(id=form.id.data).first()
if not current_user.is_moderator or not el.author.is_current:
if not current_user.is_moderator and not (el.author.is_current if el.author is not None else None):
flash("You don't have sufficient rights to do this.")
return redirect(url_for('main.index'))
if form.delete.data:
el.remove_image_files()
db.session.delete(el)
db.session.commit()
flash('{} deleted.'.format(str(el)))
@ -128,6 +129,16 @@ def modify_post():
db.session.commit()
flash('Changes to {} have been applied.'.format(str(el)))
elif form.approve.data:
if not current_user.is_moderator:
flash("You don't have sufficient rights to do this.")
return redirect(url_for('main.index'))
post.status = POST_STATUS.active
post.approver = current_user
db.session.commit()
flash('Approved post {}'.format(str(post)))
redirect(url_for('post.post_show', id=post.id))
return redirect(url_for('.manage_posts'))
@ -179,7 +190,7 @@ def modify_comment():
return redirect(url_for('post.post_show', id=form.post_id.data))
else:
el = Comment.query.filter_by(id=form.id.data).first()
if not current_user.is_moderator or not el.user.is_current:
if not current_user.is_moderator and not (el.user.is_current if el.user is not None else None):
flash("You don't have sufficient rights to do this.")
return redirect(url_for('main.index'))
if form.delete.data:

@ -4,13 +4,12 @@ import os
from flask import (Blueprint, abort, current_app, flash, redirect,
render_template, request, send_from_directory, url_for, session, jsonify)
from flask_login import current_user, login_required
from PIL import Image
from sqlalchemy import func
from sqlalchemy.orm import aliased
from yadc import db
from yadc.forms import UploadForm, CommentForm, PostForm
from yadc.models import FILETYPE, RATING, Post, Tag, Comment
from yadc.models import FILETYPE, RATING, POST_STATUS, Post, Tag, Comment, moderator_required
from yadc.utils import query_replace
bp = Blueprint('post', __name__)
@ -35,6 +34,10 @@ def posts(page):
f_rating = {r.name : r for r in RATING}.get(request.args.get('rating'), RATING.safe)
m_ratings = f_rating.matched
# filter user's blacklist
if current_user.is_authenticated:
f_tags = list(t for t in f_tags if t not in [tb.content for tb in current_user.tag_blacklist])
posts_query = Post.query
if f_tags:
posts_query = posts_query.join(Post.tags).group_by(Post.id).filter(Tag.content.in_(f_tags)).having(func.count(Post.id)==len(f_tags))
@ -66,6 +69,11 @@ from yadc.bp import manage
def comment():
return manage.modify_comment()
@bp.route('/editpost', methods=['POST'])
@login_required
def editpost():
return manage.modify_post()
@bp.route('/upload', methods=['GET', 'POST'])
@login_required
def upload():
@ -79,32 +87,11 @@ def upload():
post = Post(file, source=form.sauce.data, tags=tags, rating=RATING[form.rating.data], author=current_user)
with open(post.image_path, "wb") as f:
f.write(file.data.getbuffer())
# file.seek(0)
# file.save(post.image_path)
with Image.open(file.data) as im:
im = im.convert('RGB')
if post.jpeg_path is not None:
im.save(post.jpeg_path, 'JPEG', quality=80)
sim = im.copy()
sim.thumbnail([800,800])
sim.save(post.sample_path, 'JPEG', quality=80)
im.thumbnail([512,512])
im.save(post.thumb_path, 'JPEG', quality=80)
db.session.add(post)
db.session.commit()
flash('Successfully submitted {}'.format(str(post)))
#return redirect(url_for('.upload'))
return redirect(url_for('.posts'))
return render_template('post/upload.html', form=form)
@ -151,21 +138,21 @@ def posts_api():
source=p.source,
md5=p.md5,
file_size=p.filesize,
file_url=p.url(path=p.image_url, endpoint='img'),
preview_url=p.url(path=p.image_url, endpoint='thumb'),
file_url=p.url(path=p.file_uri, endpoint='img'),
preview_url=p.url(path=p.file_uri, endpoint='thumb'),
preview_width=0,
preview_height=0,
actual_preview_width=0,
actual_preview_height=0,
sample_url=p.url(path=p.image_url, endpoint='sample'),
sample_url=p.url(path=p.file_uri, endpoint='sample'),
sample_width=0,
sample_height=0,
sample_file_size=0,
jpeg_url=p.url(path=p.image_url, endpoint='img') if p.filetype is FILETYPE.jpeg else p.url(path=p.image_url, endpoint='jpeg'),
jpeg_url=p.url(path=p.file_uri, endpoint='img') if p.filetype is FILETYPE.jpeg else p.url(path=p.file_uri, endpoint='jpeg'),
jpeg_width=0,
jpeg_height=0,

@ -1,10 +1,10 @@
from flask import (Blueprint, abort, current_app, flash, redirect,
render_template, request, send_from_directory, url_for)
from flask_login import current_user, login_required
from yadc.forms import ChangePassForm
from yadc.forms import ChangeUserInfoForm, ChangePassForm, ChangeMailForm, ChangeUserRatingForm, ChangeTagBlacklistForm, DeleteUserDataForm
from yadc import db
from yadc.models import User
from yadc.models import User, Post, Comment
bp = Blueprint('user', __name__)
@ -15,23 +15,102 @@ def profile(username):
if user is not None:
return render_template('user/profile.html', user=user)
return "FUCK YOU, THIS USER DOES NOT EXIST"
return redirect(url_for('main.index'))
@bp.route('/settings', methods=['GET','POST'])
@bp.route('/settings')
@login_required
def settings():
form = ChangePassForm(request.form)
if request.method == 'POST' and form.validate():
user = current_user
return render_template(
'user/settings.html',
userinfo_form=ChangeUserInfoForm(bio=current_user.biography),
pass_form=ChangePassForm(),
mail_form=ChangeMailForm(),
rating_form=ChangeUserRatingForm(rating=current_user.rating.name),
tags_form=ChangeTagBlacklistForm(),
delete_form=DeleteUserDataForm()
)
@bp.route('/change_info', methods=['POST'])
@login_required
def change_info():
form = ChangeUserInfoForm(request.form)
if form.validate():
current_user.biography = form.bio.data
db.session.commit()
flash('Your biography was updated.')
if not user.check_password(form.password_current.data):
return redirect(url_for('.settings'))
@bp.route('/change_pass', methods=['POST'])
@login_required
def change_pass():
form = ChangePassForm(request.form)
if form.validate():
if not current_user.check_password(form.password_current.data):
flash('Incorrect password')
return redirect(url_for('.settings'))
user.create_password(form.password.data)
db.session.commit()
current_user.create_password(form.password.data)
db.session.commit()
flash('Password changed successfully.')
return redirect(url_for('.settings'))
return render_template('user/settings.html', form=form)
@bp.route('/change_mail', methods=['POST'])
@login_required
def change_mail():
form = ChangeMailForm(request.form)
if form.validate():
current_user.email = form.email.data
db.session.commit()
flash('Your email was updated.')
return redirect(url_for('.settings'))
@bp.route('/change_rating', methods=['POST'])
@login_required
def change_rating():
form = ChangeUserRatingForm(request.form)
if form.validate():
current_user.rating = form.rating.data
db.session.commit()
flash('Your rating preference was updated.')
return redirect(url_for('.settings'))
@bp.route('/change_tagblacklist', methods=['POST'])
@login_required
def change_tagblacklist():
form = ChangeTagBlacklistForm(request.form)
if form.validate():
f_tags = form.tags.data.split()
tags = Tag.query.filter(Tag.content.in_(f_tags)).all()
current_user.tag_blacklist = tags
db.session.commit()
flash('Your tag blacklist was updated.')
return redirect(url_for('.settings'))
@bp.route('/delete_data', methods=['POST'])
@login_required
def delete_data():
form = DeleteUserDataForm(request.form)
if form.validate():
if form.all_posts:
Post.query.filter_by(author_id=current_user.id).delete()
if form.all_comments:
Comment.query.filter_by(user_id=current_user.id).delete()
db.session.delete(current_user)
db.session.commit()
flash('Thank you for using our service.')
return redirect(url_for('main.index'))
return redirect(url_for('.settings'))

@ -7,6 +7,8 @@ from werkzeug.utils import cached_property
from flask import current_app
from flask_wtf.csrf import _FlaskFormCSRF
from yadc.models import USER_STATUS, OP_LEVEL, RATING, POST_STATUS, TAG_CATEGORY
class CSRFForm(Form):
class Meta:
csrf = True
@ -66,8 +68,8 @@ class UploadForm(CSRFForm):
sauce = StringField('Sauce', validators=[DataRequired()], render_kw={'placeholder':'Source URL','autocomplete':'off'})
tags = StringField('Tags', validators=[DataRequired()], render_kw={'placeholder':'Tags','autocomplete':'off'}) # CUSTOM VALIDATOR (also for Post edits)
rating = RadioField('Rating',
choices=[('safe', 'Safe'), ('questionable', 'Questionable'), ('explicit', 'Explicit')],
default='safe',
choices=[(e.name, e.name.capitalize()) for e in RATING],
default=RATING.safe.name,
validators=[DataRequired()])
submit = SubmitField('Upload')
@ -80,15 +82,43 @@ class UploadForm(CSRFForm):
if client_mimetype not in ['image/png','image/jpeg']:
raise ValidationError('Please select an image file of PNG or JPEG format')
# Change user section
class ChangeUserInfoForm(CSRFForm):
bio = TextAreaField('Biography')
userinfo_submit = SubmitField('Change your info')
class ChangePassForm(CSRFForm):
password_current = PasswordField('Current password', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
password_again = PasswordField('Repeat password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Change password')
pass_submit = SubmitField('Change password')
class ChangeMailForm(CSRFForm):
email = StringField('E-mail', validators=[DataRequired(), Email()], render_kw=dict(placeholder="E-mail"))
email_again = StringField('Repeat e-mail', validators=[DataRequired(), EqualTo('email')], render_kw=dict(placeholder="Repeat e-mail"))
mail_submit = SubmitField('Change email')
class ChangeUserRatingForm(CSRFForm):
rating = SelectField('Rating',
choices=[(e.name, e.name.capitalize()) for e in RATING],
validators=[DataRequired()],
render_kw=dict(onchange="submit()"))
rating_submit = SubmitField('Change default rating')
class ChangeTagBlacklistForm(CSRFForm):
tags = StringField('Tags', render_kw={'placeholder':'Tags','autocomplete':'off'})
tags_submit = SubmitField('Change blacklisted tags', validators=[DataRequired()])
class DeleteUserDataForm(CSRFForm):
all_posts = BooleanField('Delete all posts')
all_comments = BooleanField('Delete all comments')
delete_submit = SubmitField(
'Delete your data',
validators=[DataRequired()],
render_kw=dict(onclick="return confirm('Do you really want to delete all your data?')")
)
from yadc.models import USER_STATUS, OP_LEVEL, RATING, POST_STATUS, TAG_CATEGORY
class EditForm(CSRFForm):
id = HiddenField('ID')
@ -125,6 +155,8 @@ class PostForm(EditForm):
validators=[optional()])
source = StringField('Source', render_kw={'autocomplete':'off'})
approve = SubmitField('Approve')
class TagForm(EditForm):
content = StringField('Content', validators=[validate_create_required], render_kw={'autocomplete':'off'})
category = SelectField('Category',

@ -70,21 +70,27 @@ class TimestampMixin(object):
def natural_updated(self):
return humanize.naturaltime(datetime.now().astimezone(self.updated.tzinfo) - self.updated)
user_tags_blacklist = db.Table('user_tags_blacklist', db.metadata,
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'))
)
class User(UserMixin, TimestampMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(128), unique=True, nullable=False)
email = db.Column(db.String(256), unique=True)
pass_hash = db.Column(db.String(128))
op_level = db.Column(db.Enum(OP_LEVEL), default=OP_LEVEL.user, nullable=False)
user_status = db.Column(db.Enum(USER_STATUS), default=USER_STATUS.active, nullable=False)
op_level = db.Column(db.Enum(OP_LEVEL), server_default=OP_LEVEL.user.name, nullable=False)
user_status = db.Column(db.Enum(USER_STATUS), server_default=USER_STATUS.active.name, nullable=False)
last_login = db.Column(UtcDateTime)
ban_status = None
ban_until = None
ban_reason = None
ban_until = db.Column(UtcDateTime)
ban_reason = db.Column(db.String(512))
biography = db.Column(db.String(512))
#authored_posts = db.relationship('Post', back_populates='author')
#approved_posts = db.relationship('Post', back_populates='approver')
rating = db.Column(db.Enum(RATING), server_default=RATING.safe.name, nullable=False)
tag_blacklist = db.relationship('Tag', secondary=user_tags_blacklist, backref=db.backref('user_blacklisted'))
def __repr__(self):
return '<User {}>'.format(self.username)
@ -93,8 +99,10 @@ class User(UserMixin, TimestampMixin, db.Model):
self.pass_hash = generate_password_hash(password, salt_length=16)
def check_password(self, password):
# if self.pass_hash is None:
# return True
if self.pass_hash is None:
return True
return False
return check_password_hash(self.pass_hash, password)
def login(self, remember):
@ -146,9 +154,6 @@ def admin_required(func):
# user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
# user = db.relationship('User', backref=db.backref('profile', uselist=False))
# rating = db.Column(db.Enum(RATING), default=RATING.safe, nullable=False)
# tag_blacklist = None
post_tags = db.Table('post_tags', db.metadata,
db.Column('post_id', db.Integer, db.ForeignKey('post.id')),
@ -160,7 +165,7 @@ class Post(TimestampMixin, db.Model):
md5 = db.Column(db.String(32), unique=True, nullable=False)
filetype = db.Column(db.Enum(FILETYPE), nullable=False)
rating = db.Column(db.Enum(RATING), nullable=False)
status = db.Column(db.Enum(POST_STATUS), default=POST_STATUS.pending, nullable=False)
status = db.Column(db.Enum(POST_STATUS), server_default=POST_STATUS.pending.name, nullable=False)
width = db.Column(db.Integer, default=0)
height = db.Column(db.Integer, default=0)
@ -189,6 +194,8 @@ class Post(TimestampMixin, db.Model):
self.origin_filename = file.filename
self.generate_image_files(file)
def __repr__(self):
return('<Post #{} by {}, {} of {} bytes>'.format(self.id, self.author, self.filetype.name, self.filesize))
@ -197,7 +204,7 @@ class Post(TimestampMixin, db.Model):
return "flex: {0:.2f} 1 {0:.2f}px;".format(self.width/self.height*current_app.config.get('POST_LIST_THUMB_HEIGHT', 240))
@property
def image_url(self):
def file_uri(self):
# filename = "{}.{}".format('maybe_later_generated_cute_filename', 'jpg' if self.filetype is FILETYPE.jpeg else 'png')
# filename = 'maybe_later_generated_cute_filename'
filename = "{} - {} {}".format(current_app.config.get('INSTANCE_NAME'), self.id, " ".join(tag.content.replace(' ', '_') for tag in self.tags))
@ -213,28 +220,39 @@ class Post(TimestampMixin, db.Model):
elif endpoint == 'thumb':
return url_for('main.uploaded_thumb', path="{}.{}".format(path,'jpg'))
@property
def image_path(self):
filename = "{}.{}".format(self.md5, 'jpg' if self.filetype is FILETYPE.jpeg else 'png')
return os.path.join(current_app.config.get('POST_UPLOADS'), 'img', filename)
@property
def jpeg_path(self):
if self.filetype is FILETYPE.jpeg:
return None
def generate_image_files(self, file):
with open(self.image_files['image'], "wb") as f:
f.write(file.data.getbuffer())
# file.seek(0)
# file.save(post.image_path)
with Image.open(file.data) as im:
im = im.convert('RGB')
jpeg_filename = "{}.{}".format(self.md5, 'jpg')
return os.path.join(current_app.config.get('POST_UPLOADS'), 'jpeg', jpeg_filename)
if self.image_files['jpeg'] is not None:
im.save(self.image_files['jpeg'], 'JPEG', quality=80)
@property
def sample_path(self):
jpeg_filename = "{}.{}".format(self.md5, 'jpg')
return os.path.join(current_app.config.get('POST_UPLOADS'), 'sample', jpeg_filename)
sim = im.copy()
sim.thumbnail([800,800])
sim.save(self.image_files['sample'], 'JPEG', quality=80)
sim = im.copy()
sim.thumbnail([512,512])
sim.save(self.image_files['thumb'], 'JPEG', quality=80)
def remove_image_files(self):
for im in self.image_files.values():
os.remove(im)
@property
def thumb_path(self):
jpeg_filename = "{}.{}".format(self.md5, 'jpg')
return os.path.join(current_app.config.get('POST_UPLOADS'), 'thumb', jpeg_filename)
def image_files(self):
return dict(
image=os.path.join(current_app.config.get('POST_UPLOADS'), 'img', "{}.{}".format(self.md5, 'jpg' if self.filetype is FILETYPE.jpeg else 'png')),
jpeg=(None if self.filetype is FILETYPE.jpeg else os.path.join(current_app.config.get('POST_UPLOADS'), 'jpeg', "{}.{}".format(self.md5, 'jpg'))),
sample=os.path.join(current_app.config.get('POST_UPLOADS'), 'sample', "{}.{}".format(self.md5, 'jpg')),
thumb=os.path.join(current_app.config.get('POST_UPLOADS'), 'thumb', "{}.{}".format(self.md5, 'jpg'))
)
@cached_property
def image_resolution(self):
@ -257,7 +275,7 @@ class Post(TimestampMixin, db.Model):
class Tag(TimestampMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.String(128), unique=True, nullable=False)
category = db.Column(db.Enum(TAG_CATEGORY), default=TAG_CATEGORY.general, nullable=False)
category = db.Column(db.Enum(TAG_CATEGORY), server_default=TAG_CATEGORY.general.name, nullable=False)
@property
def content_deser(self):

@ -30,7 +30,9 @@
<label class="show to-edit"><span class="fa fa-edit"></span></label>
<label class="edit to-close"><span class="fa fa-close"></span></label>
<label class="edit"><span class="fa fa-check"></span>{{ user.editform.edit() }}</label>
<label><span class="fa fa-trash-o"></span>{{ user.editform.delete() }}</label>
<label><span class="fa fa-trash-o"></span>{{ user.editform.delete(
onclick="return confirm('Do you really want to delete this user?')"
)}}</label>
</td>
</tr>
</form>

@ -9,7 +9,7 @@
{% for post in posts.items %}
<figure style="{{ post.flex }}">
<a href="{{ url_for('post.post_show', id=post.id) }}">
<img src="{{ post.url(path=post.image_url, endpoint='thumb') }}" srcset="{{ post.url(path=post.image_url, endpoint='thumb') }} 512w, {{ post.url(path=post.image_url, endpoint='sample') }} 800w" alt=""> <!--sizes="(min-width: 513px) 1000w" -->
<img src="{{ post.url(path=post.file_uri, endpoint='thumb') }}" srcset="{{ post.url(path=post.file_uri, endpoint='thumb') }} 512w, {{ post.url(path=post.file_uri, endpoint='sample') }} 800w" alt=""> <!--sizes="(min-width: 513px) 1000w" -->
</a>
</figure>
{% endfor %}

@ -21,10 +21,10 @@
<div class="source">Source: <a href="{{ post.source }}">{{ post.source }}</a></div>
<div class="size">File size: {{ post.filesize_human }}</div>
<div class="resolution">Image res: {{ post.image_resolution }}</div>
<div class="jpeg"><a href="{{ post.url(path=post.image_url, endpoint='jpeg') }}">Enlarge image</a></div>
<div class="jpeg"><a href="{{ post.url(path=post.file_uri, endpoint='jpeg') }}">Enlarge image</a></div>
{% if post.filetype.name == 'png' %}
<div class="png"><a href="{{ post.url(path=post.image_url) }}">Original PNG file</a></div>
<div class="png"><a href="{{ post.url(path=post.file_uri) }}">Original PNG file</a></div>
{% endif %}
</article>
@ -33,7 +33,7 @@
{% if post.can_edit %}
<article class="edit">
<h3>Edit</h3>
<form action="{{ url_for('manage.modify_post') }}" method="post">
<form action="{{ url_for('post.editpost') }}" method="post">
{{ editform.csrf_token }}
{{ editform.id() }}
<div>
@ -54,7 +54,7 @@
{% block main_content %}
<section class="post_single">
<div class="image">
<img src="{{ post.url(path=post.image_url, endpoint='jpeg') }}" alt="">
<img src="{{ post.url(path=post.file_uri, endpoint='jpeg') }}" alt="">
</div>
</section>
{% endblock %}
@ -77,7 +77,7 @@
{% if not comment.deleted %}
<form class="comment_editform editingable" action="{{ url_for('manage.modify_comment') }}" method="post">
<form class="comment_editform editingable" action="{{ url_for('post.comment') }}" method="post">
{{ comment.editform.csrf_token }}
{{ comment.editform.id() }}
<p class="comment_content notedit">{{ comment.content }}</p>
@ -103,7 +103,7 @@
{% if current_user.is_authenticated %}
<div class="form">
<h3>Reply</h3>
<form action="{{ url_for('manage.modify_comment') }}" method="post">
<form action="{{ url_for('post.comment') }}" method="post">
{{ comment_form.csrf_token }}
{{ comment_form.post_id() }}
<div>

@ -6,5 +6,5 @@
{% endblock %}
{% block main_content %}
<p class="bio">{{ user.biography }}</p>
{% endblock %}

@ -3,23 +3,75 @@
{% block main_content %}
<section class="manage_profile">
<form action="" method="post">
<form action="{{ url_for('user.change_info') }}" method="post">
<h3>Change user info</h3>
{{ userinfo_form.csrf_token }}
<div>
{{ userinfo_form.bio() }}
{{ errors(userinfo_form.bio) }}
</div>
<div>
{{ userinfo_form.userinfo_submit() }}
</div>
</form>
<form action="{{ url_for('user.change_pass') }}" method="post">
<h3>Change password</h3>
{{ form.csrf_token }}
{{ pass_form.csrf_token }}
<div>
{{ pass_form.password_current(placeholder="Current password") }}
{{ errors(pass_form.password_current) }}
</div>
<div>
{{ pass_form.password(placeholder="Password") }}
{{ errors(pass_form.password) }}
</div>
<div>
{{ pass_form.password_again(placeholder="Repeat password") }}
{{ errors(pass_form.password_again) }}
</div>
<div>
{{ pass_form.pass_submit() }}
</div>
</form>
<form action="{{ url_for('user.change_mail') }}" method="post">
<h3>Change e-mail address</h3>
{{ mail_form.csrf_token }}
<div>
{{ mail_form.email() }}
{{ errors(mail_form.email) }}
</div>
<div>
{{ mail_form.email_again() }}
{{ errors(mail_form.email_again) }}
</div>
<div>
{{ form.password_current(placeholder="Current password") }}
{{ errors(form.password_current) }}
{{ mail_form.mail_submit() }}
</div>
</form>
<form action="{{ url_for('user.change_rating') }}" method="post">
<h3>Preferred rating</h3>
{{ rating_form.csrf_token }}
<div>
{{ rating_form.rating() }}
{{ errors(rating_form.rating) }}
</div>
<div>
{{ rating_form.rating_submit() }}
</div>
</form>
<form action="{{ url_for('user.delete_data') }}" method="post">
<h3>Delete user data</h3>
{{ delete_form.csrf_token }}
<div>
{{ form.password(placeholder="Password") }}
{{ errors(form.password) }}
{{ delete_form.all_comments() }}{{ delete_form.all_comments.label }}
{{ errors(delete_form.all_posts) }}
</div>
<div>
{{ form.password_again(placeholder="Repeat password") }}
{{ errors(form.password_again) }}
{{ delete_form.all_posts() }}{{ delete_form.all_posts.label }}
{{ errors(delete_form.all_posts) }}
</div>
<div>
{{ form.submit() }}
{{ delete_form.delete_submit() }}
</div>
</form>
</section>

Loading…
Cancel
Save