1
1
Fork 0
few permission fixes,
prepares for post edit form,
few frontend quirks including sidebar in management
dev
Jan Kužílek 5 years ago
parent 3ebe1c0b67
commit 3302de5668

@ -56,7 +56,7 @@ def create_app():
app.register_blueprint(auth.bp, url_prefix='/auth')
app.register_blueprint(manage.bp, url_prefix='/manage')
app.register_blueprint(user.bp, url_prefix='/user')
app.register_blueprint(api.bp)
# app.register_blueprint(api.bp) # now deprecated
login.login_view = 'auth.login'

@ -6,18 +6,7 @@ from yadc.models import Tag
bp = Blueprint('api', __name__)
@bp.route('/posts.json')
@bp.route('/post/index.json')
def post_index():
return jsonify(
get=request.args,
post=request.form)
@bp.route('/api/tags')
def tag_autocomplete():
query = request.args.get('q', '')
if query != '':
tags = Tag.query.filter(Tag.content.like("%{}%".format(query))).limit(15).all()
return jsonify([{"id": t.id, "content": t.content, "content_deser": t.content_deser, "category": {"id": t.category.value, "name": t.category.name}} for t in tags])
return jsonify()
# tags = request.args.get('tags', '')

@ -4,13 +4,14 @@ from flask_login import login_required, current_user
from yadc.forms import UserForm, PostForm, TagForm, CommentForm
from yadc import db
from yadc.models import User, USER_STATUS, Post, Tag, TAG_CATEGORY, Comment
from yadc.models import User, USER_STATUS, moderator_required, admin_required, Post, Tag, TAG_CATEGORY, Comment
bp = Blueprint('manage', __name__)
@bp.route('/users', defaults={'page': 1})
@bp.route('/users/<int:page>')
@login_required
@admin_required
def manage_users(page):
users = User.query.order_by(User.id.desc()).paginate(page, current_app.config.get('MANAGE_PER_PAGE'))
@ -27,6 +28,7 @@ def manage_users(page):
@bp.route('/posts', defaults={'page': 1})
@bp.route('/posts/<int:page>')
@login_required
@moderator_required
def manage_posts(page):
posts = Post.query.order_by(Post.id.desc()).paginate(page, current_app.config.get('MANAGE_PER_PAGE'))
@ -42,6 +44,7 @@ def manage_posts(page):
@bp.route('/tags', defaults={'page': 1})
@bp.route('/tags/<int:page>')
@login_required
@moderator_required
def manage_tags(page):
tags = Tag.query.order_by(Tag.content).paginate(page, current_app.config.get('MANAGE_PER_PAGE'))
@ -57,6 +60,7 @@ def manage_tags(page):
@bp.route('/modify_user', methods=['POST'])
@login_required
@admin_required
def modify_user():
form = UserForm(request.form)
flash(str(request.form))
@ -93,6 +97,7 @@ def modify_user():
@bp.route('/modify_post', methods=['POST'])
@login_required
@moderator_required
def modify_post():
form = PostForm(request.form)
flash(str(request.form))
@ -118,6 +123,7 @@ def modify_post():
# Example perfect create/edit/delete form endpoint
@bp.route('/modify_tag', methods=['POST'])
@login_required
@moderator_required
def modify_tag():
form = TagForm(request.form)
flash(str(request.form))
@ -144,7 +150,6 @@ def modify_tag():
flash('Changes to {} have been applied.'.format(str(el)))
return redirect(url_for('.manage_tags'))
# return redirect(url_for('main.index'))
# Creation/editing only through post page
@ -163,6 +168,8 @@ def modify_comment():
return redirect(url_for('.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.is_current:
return abort(403)
if form.delete.data:
db.session.delete(el)
db.session.commit()

@ -2,14 +2,14 @@ import io
import os
from flask import (Blueprint, abort, current_app, flash, redirect,
render_template, request, send_from_directory, url_for)
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#, EditCommentForm
from yadc.forms import UploadForm, CommentForm, PostForm
from yadc.models import FILETYPE, RATING, Post, Tag, Comment
from yadc.utils import query_replace
@ -33,7 +33,9 @@ def posts(page):
# PARSING ARGUMENTS
f_tags = request.args.get('tags', '').split()
m_ratings = RATING.matched(request.args.get('rating'))
# m_ratings = RATING.matched(request.args.get('rating'))
f_rating = {r.name : r for r in RATING}.get(request.args.get('rating'), RATING.safe)
m_ratings = f_rating.matched
posts_query = Post.query
if f_tags:
@ -45,6 +47,8 @@ def posts(page):
# flash(f_tags)
# flash(m_ratings)
# session['index_settings'] = dict(tags=f_tags, rating=f_rating)
session['index_settings'] = dict(tags=request.args.get('tags', ''), rating=f_rating.name)
return render_template('post/index.html', posts=posts, tags=tags)
@ -60,7 +64,7 @@ def post_show(id):
for comment in post.comments:
comment.editform = CommentForm(id=comment.id, content=comment.content)
return render_template('post/post.html', post=post, tags=post.tags, comments=post.comments, comment_form=CommentForm(post_id=post.id))
return render_template('post/post.html', post=post, tags=post.tags, comments=post.comments, editform=PostForm(id=post.id), comment_form=CommentForm(post_id=post.id))
from yadc.bp import manage
@bp.route('/comment', methods=['POST'])
@ -110,3 +114,81 @@ def upload():
return redirect(url_for('.posts'))
return render_template('post/upload.html', form=form)
@bp.route('/tags')
def tag_autocomplete():
query = request.args.get('q', '')
if query != '':
tags = Tag.query.filter(Tag.content.like("%{}%".format(query))).limit(15).all()
return jsonify([{"id": t.id, "content": t.content, "content_deser": t.content_deser, "category": {"id": t.category.value, "name": t.category.name}} for t in tags])
return jsonify()
# A TRY TO MAKE A DANBOORU COMPATIBLE API
# import json
@bp.route('/index.json')
def post_index():
# return jsonify(json.load(open('index.json', 'r')))
# return jsonify(json.load(open('test.json', 'r')))
f_tags = request.args.get('tags', '').split()
# rating = None
for t in f_tags:
if t.startswith('rating:') or t.startswith('-rating:'):
f_tags.remove(t)
# rating = t.split(':')[1]
# f_rating = {r.name : r for r in RATING}.get(rating, RATING.safe)
# m_ratings = f_rating.matched
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))
# posts_query = posts_query.filter(Post.rating.in_(m_ratings)).order_by(Post.created.desc())
posts_query = posts_query.order_by(Post.created.desc())
posts = posts_query.paginate(int(request.args.get('page', 0))+1, int(request.args.get('limit') or current_app.config.get('POSTS_PER_PAGE')))
return jsonify([dict(
id=p.id,
tags=" ".join([t.content for t in p.tags]),
created_at=int(p.created.timestamp()),
creator_id=p.author_id,
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'),
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_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_width=0,
jpeg_height=0,
jpeg_file_size=0,
rating=str(p.rating.name)[:1],
has_children=False,
parent_id=None,
status=p.status.name,
width=p.width,
height=p.height,
is_held=False,
frames_pending_string='',
frames_pending=[],
frames_string='',
frames=[]
) for p in posts.items])

@ -34,4 +34,4 @@ def settings():
flash('Password changed successfully.')
return redirect(url_for('.settings'))
return render_template('manage/profile.html', form=form)
return render_template('user/settings.html', form=form)

@ -116,6 +116,7 @@ class UserForm(EditForm):
validators=[optional()])
class PostForm(EditForm):
tags = StringField('Tags', render_kw={'placeholder':'Tags','autocomplete':'off'})
rating = SelectField('Rating',
choices=[(e.name, e.name.capitalize()) for e in RATING],
validators=[optional()])

@ -3,8 +3,9 @@ import hashlib
import humanize
import os
from datetime import datetime, timezone
from functools import wraps
from flask import current_app, url_for
from flask import current_app, url_for, abort
from flask_login import UserMixin, login_user, logout_user, current_user
from PIL import Image
from sqlalchemy_utc import UtcDateTime, utcnow
@ -33,10 +34,14 @@ class RATING(enum.Enum):
questionable = 1
explicit = 2
@staticmethod
def matched(rating=None):
rat = {r.name : r for r in RATING}.get(rating, RATING.safe)
return [r for r in RATING if r.value<=rat.value]
# @staticmethod
# def matched(rating=None):
# rat = {r.name : r for r in RATING}.get(rating, RATING.safe)
# return [r for r in RATING if r.value<=rat.value]
@property
def matched(self):
return [r for r in RATING if r.value<=self.value]
class POST_STATUS(enum.Enum):
pending = 0
@ -108,10 +113,33 @@ class User(UserMixin, TimestampMixin, db.Model):
def is_admin(self):
return self.op_level is OP_LEVEL.admin
@property
def is_current(self):
return self == current_user
@login.user_loader
def load_user(id):
return User.query.get(int(id))
def moderator_required(func):
@wraps(func)
def dec_view(*args, **kwargs):
if current_user:
if not current_user.is_moderator or not current_user.is_admin:
return abort(403)
return func(*args, **kwargs)
return dec_view
def admin_required(func):
@wraps(func)
def dec_view(*args, **kwargs):
if current_user:
if not current_user.is_admin:
return abort(403)
return func(*args, **kwargs)
return dec_view
# class UserPreferences(db.Model):
# user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
# user = db.relationship('User', backref=db.backref('profile', uselist=False))

@ -13,7 +13,8 @@ if (suggest_input.hasAttribute('required')) {
suggest_input.removeAttribute('required')
suggest_hidden.setAttribute('required', '')
}
suggest_input.value = ''
// suggest_input.value = ''
suggest_input.removeAttribute('value')
let tag_suggest_dropdown = suggestroot.querySelector('.tag_suggest_dropdown')
@ -152,7 +153,7 @@ suggest_input.addEventListener('input', (event) => {
}
ajax_timeout = setTimeout(() => {
fetch('/api/tags?q='+value).then((response) => {
fetch('/post/tags?q='+value).then((response) => {
console.log(response)
return response.json()
}).then((data) => {

@ -32,7 +32,7 @@
<a href="{{ url_for('auth.login') }}">Login</a>
<a href="{{ url_for('auth.register') }}">Register</a>
{% else %}
<a href="#">Profile</a>
<a href="{{ url_for('user.profile', username=current_user.username) }}">Profile</a>
<a href="{{ url_for('user.settings') }}">Settings</a>
<a href="{{ url_for('auth.logout') }}">Log out</a>
{% endif%}

@ -12,9 +12,7 @@
<div class="rating">
{% for rating in ('safe', 'questionable', 'explicit') %}
<input type="radio" name="rating" id="rating-{{ rating }}" value="{{ rating }}" {%
if (rating == request.args.get('rating') if request.args.get('rating') in ('safe', 'explicit', 'questionable') else rating == 'safe')
%}checked{% endif %}>
<input type="radio" name="rating" id="rating-{{ rating }}" value="{{ rating }}" {% if rating == session.get('index_settings', {}).get('rating', 'safe') %}checked{% endif %} onclick="submit()">
<label for="rating-{{ rating }}">{{ rating.capitalize() }}</label>
<br>
{% endfor %}

@ -1,6 +1,11 @@
{% extends 'layout/base_sidebar.html' %}
{% from '_includes.html' import render_sidenav with context %}
{% block sidebar %}
{{ render_sidenav({"speedtest": ("Speedtest", "http://speedtest.cesnet.cz")}) }}
<article class="sidenav">
{#<!-- <a href="{{ url_for('user.profile') }}">Profile</a> -->#}
<a href="{{ url_for('user.settings') }}">Settings</a>
<a href="{{ url_for('manage.manage_posts') }}">Post management</a>
<a href="{{ url_for('manage.manage_tags') }}">Tag management</a>
<a href="{{ url_for('manage.manage_users') }}">User management</a>
</article>
{% endblock %}

@ -1,5 +1,5 @@
{% extends 'layout/base_sidebar_tags.html' %}
{% from '_includes.html' import render_post_edit with context %}
{% from '_includes.html' import render_post_edit, render_tag_input with context %}
{% from "_formhelpers.html" import errors %}
{% block sidebar %}
@ -33,7 +33,20 @@
{% if post.can_edit %}
<article class="edit">
<h3>Edit</h3>
<a href="">edit?</a>
<form action="{{ url_for('manage.modify_post') }}" method="post">
{{ editform.csrf_token }}
{{ editform.id() }}
<div>
{{ render_tag_input(editform.tags) }}
{{ errors(editform.tags) }}
</div>
<div>
{{ editform.source }}
</div>
<div>
{{ editform.edit() }}
</div>
</form>
</article>
{% endif %}
{% endblock %}
@ -54,7 +67,7 @@
{% for comment in comments %}
<article class="comment">
<div class="comment_head">
<h4>{{ comment.user.username }}</h4>
<h4>{{ comment.user.username or "Deleted account" }}</h4>
{% if comment.can_edit %}
<span class="controls">
<span class="control_edit">edit</span>

Loading…
Cancel
Save