1
1
Fork 0
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.
yadc/yadc/forms.py

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)