You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
8.8 KiB
Python
203 lines
8.8 KiB
Python
from wtforms import Form
|
|
from wtforms import StringField, PasswordField, BooleanField, SubmitField, FileField, MultipleFileField, ValidationError, RadioField, TextAreaField, HiddenField, SelectField, IntegerField
|
|
from wtforms.validators import DataRequired, InputRequired, Email, EqualTo, AnyOf, optional, StopValidation, URL
|
|
|
|
from werkzeug.utils import cached_property
|
|
|
|
from flask import current_app, flash
|
|
from flask_wtf.csrf import _FlaskFormCSRF
|
|
|
|
from yadc.models import USER_STATUS, OP_LEVEL, RATING, POST_STATUS, TAG_CATEGORY
|
|
from yadc.models import User, Post
|
|
|
|
class CSRFForm(Form):
|
|
class Meta:
|
|
csrf = True
|
|
csrf_class = _FlaskFormCSRF
|
|
|
|
@cached_property
|
|
def csrf_secret(self):
|
|
return current_app.secret_key
|
|
|
|
csrf_time_limit = 3600
|
|
csrf_field_name = 'csrf_token'
|
|
|
|
class LoginForm(CSRFForm):
|
|
username = StringField('Username', validators=[DataRequired()], render_kw=dict(placeholder="Username"))
|
|
password = PasswordField('Password', validators=[DataRequired()], render_kw=dict(placeholder="Password"))
|
|
remember_me = BooleanField('Remember me')
|
|
submit = SubmitField('Log In')
|
|
|
|
class ResetPasswordForm(CSRFForm):
|
|
email = StringField('Email', validators=[DataRequired(), Email()], render_kw=dict(placeholder="Your email address"))
|
|
submit = SubmitField('Reset password')
|
|
|
|
class RegisterForm(CSRFForm):
|
|
username = StringField('Username', validators=[DataRequired()], render_kw=dict(placeholder="Username"))
|
|
email = StringField('Email', validators=[DataRequired(), Email()], render_kw=dict(placeholder="Email"))
|
|
password = PasswordField('Password', validators=[DataRequired()], render_kw=dict(placeholder="Password"))
|
|
password_again = PasswordField('Repeat password', validators=[DataRequired(), EqualTo('password')], render_kw=dict(placeholder="Repeat password"))
|
|
submit = SubmitField('Register')
|
|
|
|
def validate_username(form, field):
|
|
user = User.query.filter_by(username=field.data).first()
|
|
if user is not None:
|
|
raise ValidationError('Username already taken. Try different username.')
|
|
|
|
def validate_email(form, field):
|
|
email = User.query.filter_by(email=field.data).first()
|
|
if email is not None:
|
|
raise ValidationError('This email address is already registered. Maybe try logging in instead?')
|
|
|
|
from flask import request
|
|
from magic import Magic
|
|
from PIL import Image
|
|
|
|
def validate_file(form, field):
|
|
file = request.files.get(field.name)
|
|
if not file or file.filename == '':
|
|
raise ValidationError('Please select a file.')
|
|
|
|
class UploadForm(CSRFForm):
|
|
post_img = FileField('Image', validators=[validate_file], render_kw={'required':''})
|
|
sauce = StringField('Sauce', validators=[DataRequired(), URL()], render_kw=dict(placeholder='Source URL', autocomplete='off'))
|
|
tags = StringField('Tags', validators=[DataRequired()], render_kw=dict(placeholder='Tags', autocomplete='off')) # CUSTOM VALIDATOR (also for Post edits)
|
|
rating = RadioField('Rating',
|
|
choices=[(e.name, e.name.capitalize()) for e in RATING],
|
|
default=RATING.safe.name,
|
|
validators=[DataRequired()])
|
|
submit = SubmitField('Upload')
|
|
|
|
def validate_post_img(form, field):
|
|
file = request.files.get(field.name)
|
|
|
|
client_mimetype = file.mimetype
|
|
|
|
file.seek(0)
|
|
real_mimetype = Magic(mime=True).from_buffer(file.read())
|
|
# flash(client_mimetype)
|
|
# flash(real_mimetype)
|
|
# if client_mimetype != real_mimetype or client_mimetype not in ['image/png','image/jpeg']:
|
|
if real_mimetype not in ['image/png','image/jpeg']:
|
|
raise ValidationError('Please select an image file of PNG or JPEG format.')
|
|
|
|
try:
|
|
Image.open(file).verify()
|
|
except Exception as e:
|
|
raise ValidationError('Image is corrupted.')
|
|
|
|
fileinfo = Post.fileinfo(file)
|
|
post = Post.query.filter_by(md5=fileinfo['md5']).first()
|
|
if post is not None:
|
|
raise ValidationError('Image with same hash already exists. Reposting is not allowed.')
|
|
|
|
width, height = fileinfo['resolution']
|
|
if width*height<1280*720 or width<720 or height<720:
|
|
raise ValidationError('Image has too low resolution.')
|
|
|
|
# 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()], render_kw=dict(placeholder="Current password"))
|
|
password = PasswordField('Password', validators=[DataRequired()], render_kw=dict(placeholder="New password"))
|
|
password_again = PasswordField('Repeat password', validators=[DataRequired(), EqualTo('password')], render_kw=dict(placeholder="Repeat password"))
|
|
pass_submit = SubmitField('Change password')
|
|
|
|
class ChangeMailForm(CSRFForm):
|
|
email = StringField('Email', validators=[DataRequired(), Email()], render_kw=dict(placeholder="Email"))
|
|
email_again = StringField('Repeat email', validators=[DataRequired(), EqualTo('email')], render_kw=dict(placeholder="Repeat email"))
|
|
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=dict(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?')")
|
|
)
|
|
|
|
|
|
class EditForm(CSRFForm):
|
|
id = HiddenField('ID')
|
|
|
|
create = SubmitField('Create')
|
|
edit = SubmitField('Modify')
|
|
delete = SubmitField('Delete')
|
|
|
|
def validate_id(form, field):
|
|
# if (form.edit.data or form.delete.data) and not field.data:
|
|
if not form.create.data and not field.data:
|
|
raise ValidationError('ID must be defined to be able to modify.')
|
|
|
|
def validate_create_required(form, field):
|
|
if form.create.data and not field.data:
|
|
raise ValidationError('Please fill out this field.')
|
|
|
|
class UserForm(EditForm):
|
|
username = StringField('Username', validators=[validate_create_required], render_kw=dict(placeholder='Username'))
|
|
email = StringField('Email', validators=[optional(), Email()], render_kw=dict(placeholder='Email'))
|
|
user_status = SelectField('User status',
|
|
choices=[(e.name, e.name.capitalize()) for e in USER_STATUS],
|
|
validators=[optional()])
|
|
op_level = SelectField('Permission level',
|
|
choices=[(e.name, e.name.capitalize()) for e in OP_LEVEL],
|
|
validators=[optional()])
|
|
|
|
class PostForm(EditForm):
|
|
tags = StringField('Tags', render_kw=dict(placeholder='Tags', autocomplete='off'))
|
|
rating = SelectField('Rating',
|
|
choices=[(e.name, e.name.capitalize()) for e in RATING],
|
|
validators=[optional()])
|
|
status = SelectField('Status',
|
|
choices=[(e.name, e.name.capitalize()) for e in POST_STATUS],
|
|
validators=[optional()])
|
|
source = StringField('Source', validators=[optional(), URL()], render_kw=dict(placeholder='Source URL', autocomplete='off'))
|
|
|
|
parent = IntegerField('Parent', validators=[optional()], render_kw=dict(placeholder='Parent ID', autocomplete='off'))
|
|
|
|
def validate_parent(form, field):
|
|
if not Post.query.get(field.data):
|
|
raise ValidationError('Enter valid parent post.')
|
|
|
|
referer = HiddenField()
|
|
approve = SubmitField('Approve')
|
|
|
|
class TagForm(EditForm):
|
|
content = StringField('Content', validators=[validate_create_required], render_kw=dict(autocomplete='off'))
|
|
category = SelectField('Category',
|
|
choices=[(e.name, e.name.capitalize()) for e in TAG_CATEGORY],
|
|
validators=[optional()])
|
|
|
|
# Creation/editing only through post page
|
|
class CommentForm(EditForm):
|
|
post_id = HiddenField(validators=[validate_create_required])
|
|
content = TextAreaField('Comment', render_kw=dict(autocomplete='off'))
|
|
|
|
def validate_content(form, field):
|
|
if (form.create.data or form.edit.data) and not field.data:
|
|
raise ValidationError('Please fill out this field.')
|
|
|
|
# referer = HiddenField()
|
|
ban = SubmitField('Ban')
|
|
unban = SubmitField('Unban')
|
|
|
|
# def validate_id(form, field):
|
|
# if form.ban.data and not field.data:
|
|
# raise ValidationError('ID must be defined to be able to ban.')
|
|
# super().validate_id(form, field) |