Password protection of admin pages, publish-switch and small fixes

This commit is contained in:
Thomas Lovén 2017-05-24 12:09:02 +02:00
parent 149a5d4b24
commit c3b0ce9537
8 changed files with 67 additions and 30 deletions

View File

@ -2,11 +2,13 @@ from flask import Flask
from flask_bootstrap import Bootstrap from flask_bootstrap import Bootstrap
from flaskext.markdown import Markdown from flaskext.markdown import Markdown
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_basicauth import BasicAuth
app = Flask(__name__) app = Flask(__name__)
app.config.from_object('config') app.config.from_object('config')
Bootstrap(app) Bootstrap(app)
Markdown(app) Markdown(app)
basic_auth = BasicAuth(app)
db = SQLAlchemy(app) db = SQLAlchemy(app)
from . import views, models from . import views, models

View File

@ -10,11 +10,13 @@ class PageForm(FlaskForm):
title = StringField('Title', validators=[DataRequired()]) title = StringField('Title', validators=[DataRequired()])
description = TextAreaField('Beskrivning') description = TextAreaField('Beskrivning')
endpoint = BooleanField('Produkt') endpoint = BooleanField('Produkt')
published = BooleanField('Publicerad')
thumbnail = QuerySelectField('Bild', get_label=lambda p: '{} ({})'.format(p.alt, p.id)) thumbnail = QuerySelectField('Bild', get_label=lambda p: '{} ({})'.format(p.alt, p.id))
photos = QuerySelectMultipleField('Galleri', photos = QuerySelectMultipleField('Galleri',
option_widget=widgets.CheckboxInput(), option_widget=widgets.CheckboxInput(),
widget=widgets.ListWidget(prefix_label=False), widget=widgets.ListWidget(prefix_label=False),
get_label = lambda p: '<img src="/thumbnail/{}">'.format(p.id)) get_label = lambda p: '<img src="/thumbnail/{}">'.format(p.id))
parent = QuerySelectField('Kategori', get_label = lambda p: '{} - {}'.format(p.permalink, p.title))
submit = SubmitField('Ok') submit = SubmitField('Ok')
class PhotoForm(FlaskForm): class PhotoForm(FlaskForm):

View File

@ -32,7 +32,8 @@ class Page(db.Model):
thumbnail = db.relationship('Photo', secondary=thumbnails, uselist=False) thumbnail = db.relationship('Photo', secondary=thumbnails, uselist=False)
photos = db.relationship('Photo', secondary=photos) photos = db.relationship('Photo', secondary=photos)
endpoint = db.Column(db.Boolean) endpoint = db.Column(db.Boolean, default=False)
published = db.Column(db.Boolean, default=False)
def update_permalink(self, name=None, parent_id=None): def update_permalink(self, name=None, parent_id=None):

View File

@ -40,6 +40,9 @@
{% macro delete_button(type, title, id) -%} {% macro delete_button(type, title, id) -%}
<button type="button" class="btn btn-danger" data-toggle="modal" data-target="#deletemodal" data-type="{{type}}" data-id="{{id}}" data-title="{{title}}"><span class="glyphicon glyphicon-remove"></button> <button type="button" class="btn btn-danger" data-toggle="modal" data-target="#deletemodal" data-type="{{type}}" data-id="{{id}}" data-title="{{title}}"><span class="glyphicon glyphicon-remove"></button>
{%- endmacro %} {%- endmacro %}
{% macro glyphicon(icon) -%}
<span class="glyphicon glyphicon-{{icon}}"></span>
{%- endmacro %}
{% block content %} {% block content %}
<div class="modal fade" id="deletemodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"><!-- Delete modal --> <div class="modal fade" id="deletemodal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"><!-- Delete modal -->
@ -73,6 +76,11 @@
{% for page in pages recursive %} {% for page in pages recursive %}
<div class="list-group-item"> <div class="list-group-item">
/{{ page.permalink }} - {{ page.title }} /{{ page.permalink }} - {{ page.title }}
{% if page.published %}
<span class="glyphicon glyphicon-eye-open"></span>
{% else %}
<span class="glyphicon glyphicon-eye-close"></span>
{% endif %}
<a href="{{url_for('admin_page', id=page.id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></a> <a href="{{url_for('admin_page', id=page.id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></a>
{% if page.endpoint %} {% if page.endpoint %}
{% else %} {% else %}
@ -145,17 +153,17 @@
<script> <script>
$('#deletemodal').on('show.bs.modal', function (event) { $('#deletemodal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget) var button = $(event.relatedTarget)
var type = button.data('type') , type = button.data('type')
var id = button.data('id') , id = button.data('id')
var title = button.data('title') , title = button.data('title')
var modal = $(this) var modal = $(this)
if(type == 'page') { if(type == 'page') {
var message = 'Vill du verkligen ta bort sidan - ' + title + '?' var message = 'Vill du verkligen ta bort sidan - ' + title + '?'
var href = '/admin/delpage/' + id , href = '/admin/delpage/' + id
} else { } else {
var message = 'Vill du verkligen ta bort bilden - ' + title + '?' var message = 'Vill du verkligen ta bort bilden - ' + title + '?'
var href = '/admin/delphoto/' + id , href = '/admin/delphoto/' + id
} }
modal.find('.modal-body p').text(message) modal.find('.modal-body p').text(message)
modal.find('.modal-footer a').attr('href', href) modal.find('.modal-footer a').attr('href', href)

View File

@ -14,6 +14,8 @@
{{ wtf.form_field(form.title, form_type="horizontal") }} {{ wtf.form_field(form.title, form_type="horizontal") }}
{{ wtf.form_field(form.parent, form_type="horizontal") }}
<div class="form-group"> <div class="form-group">
<label class="control-label col-lg-2" for="description">Beskrivning</label> <label class="control-label col-lg-2" for="description">Beskrivning</label>
<div class="col-lg-10"> <div class="col-lg-10">
@ -22,6 +24,7 @@
</div> </div>
{{ wtf.form_field(form.endpoint, form_type="horizontal") }} {{ wtf.form_field(form.endpoint, form_type="horizontal") }}
{{ wtf.form_field(form.published, form_type="horizontal") }}
<div class="form-group"> <div class="form-group">
<label class="control-label col-lg-2" for="thumbnail">Bild</label> <label class="control-label col-lg-2" for="thumbnail">Bild</label>

View File

@ -44,14 +44,14 @@
<div class="col-md-6 col-sm-12"> <!-- Content --> <div class="col-md-6 col-sm-12"> <!-- Content -->
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body"> <div class="panel-body">
<div class="panel-title"> <h2>{{ page.title }}</h2> </div> <!-- <div class="panel-title"> <h2>{{ page.title }}</h2> </div> -->
{{ page.description | markdown }} {{ page.description | markdown }}
</div> </div>
<div class="panel-footer">
{% if page.endpoint %} {% if page.endpoint %}
<div class="panel-footer">
<a href="mailto:order@designbyloven.se" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span>&nbsp;Beställ</a> <a href="mailto:order@designbyloven.se" class="btn btn-default"><span class="glyphicon glyphicon-envelope"></span>&nbsp;Beställ</a>
{% endif %}
</div> </div>
{% endif %}
</div> </div>
</div> <!-- Content --> </div> <!-- Content -->
</div> <!-- Content row --> </div> <!-- Content row -->
@ -75,6 +75,7 @@
{% else %} {% else %}
<div class="row"> <!-- Subsection list !--> <div class="row"> <!-- Subsection list !-->
{% for c in page.children %} {% for c in page.children %}
{% if c.published %}
<div class="col-xs-6 col-md-3"> <div class="col-xs-6 col-md-3">
<div class="thumbnail"> <div class="thumbnail">
<div class="caption" style="padding: 0;"> <div class="caption" style="padding: 0;">
@ -83,6 +84,7 @@
<a href="{{ c.permalink }}"><img src="{{ c.thumbnail.thumbnail }}" class="img-responsive"></a> <a href="{{ c.permalink }}"><img src="{{ c.thumbnail.thumbnail }}" class="img-responsive"></a>
</div> </div>
</div> </div>
{% endif %}
{% endfor %} {% endfor %}
</div> <!-- Subsection list --> </div> <!-- Subsection list -->
{% endif %} {% endif %}

View File

@ -1,7 +1,7 @@
import os import os
from flask import render_template, send_from_directory, redirect, url_for, request, render_template_string from flask import render_template, send_from_directory, redirect, url_for, request, render_template_string
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
from . import app, db from . import app, db, basic_auth
from .models import Page, Photo from .models import Page, Photo
from .forms import PageForm, PhotoForm from .forms import PageForm, PhotoForm
@ -32,24 +32,37 @@ def favicon():
@app.route('/admin') @app.route('/admin')
@basic_auth.required
def admin(): def admin():
pages = [Page.query.first()] pages = [Page.query.first()]
photos = Photo.query.all() photos = Photo.query.all()
return render_template("admin.html", pages=pages, photos=photos) return render_template("admin.html", pages=pages, photos=photos)
@app.route('/admin/page/<id>', methods=['GET', 'POST']) @app.route('/admin/page/<id>', methods=['GET', 'POST'])
@basic_auth.required
def admin_page(id): def admin_page(id):
page = Page.query.filter_by(id=id).first_or_404() page = Page.query.filter_by(id=id).first_or_404()
form = PageForm(obj=page) form = PageForm(obj=page)
form.thumbnail.query = form.photos.query = Photo.query.all() form.thumbnail.query = form.photos.query = Photo.query.all()
form.parent.query = Page.query.filter_by(endpoint = False)
# print(form.parent.query)
if form.validate_on_submit(): if form.validate_on_submit():
print((form.parent.data))
if form.parent.data == page:
if page.id == 1:
print("Clearing")
form.parent.data = None
else:
print("Setting root")
form.parent.data = Page.query.filter_by(id=1).first()
form.populate_obj(page) form.populate_obj(page)
db.session.commit() db.session.commit()
return redirect(url_for('admin')) return redirect(url_for('admin'))
else: else:
return render_template('admin_page.html', page=page, form=form) return render_template('admin_page.html', page=page, form=form)
@app.route('/admin/newpage/<parent>') @app.route('/admin/newpage/<parent>')
@basic_auth.required
def admin_newpage(parent): def admin_newpage(parent):
parent = Page.query.filter_by(id=parent).first_or_404() parent = Page.query.filter_by(id=parent).first_or_404()
new = Page(name="child_{}".format(len(parent.children)+1), title="Ny sida", endpoint=True, parent=parent, parent_id=parent.id) new = Page(name="child_{}".format(len(parent.children)+1), title="Ny sida", endpoint=True, parent=parent, parent_id=parent.id)
@ -59,6 +72,7 @@ def admin_newpage(parent):
db.session.commit() db.session.commit()
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route('/admin/delpage/<id>') @app.route('/admin/delpage/<id>')
@basic_auth.required
def admin_delpage(id): def admin_delpage(id):
page = Page.query.filter_by(id=id).first_or_404() page = Page.query.filter_by(id=id).first_or_404()
root = Page.query.filter_by(id=1).first() root = Page.query.filter_by(id=1).first()
@ -70,6 +84,7 @@ def markdown():
return render_template_string('{{ md | markdown }}', md=request.form['md']) return render_template_string('{{ md | markdown }}', md=request.form['md'])
@app.route('/admin/upload', methods=['POST']) @app.route('/admin/upload', methods=['POST'])
@basic_auth.required
def upload(): def upload():
from PIL import Image, ImageOps from PIL import Image, ImageOps
def genimg(img, imgout, size): def genimg(img, imgout, size):
@ -95,12 +110,13 @@ def upload():
slide = os.path.join('app', 'photos', 'slides', filename) slide = os.path.join('app', 'photos', 'slides', filename)
img.save(imgpath, 'JPEG') img.save(imgpath, 'JPEG')
genimg(img, imgpath, img.size) genimg(img, imgpath, img.size)
genimg(img, thumb, (171, 180))
genimg(img, slide, (550, 400)) genimg(img, slide, (550, 400))
genimg(img, thumb, (171, 180))
os.remove(tempname) os.remove(tempname)
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route('/admin/delphoto/<id>') @app.route('/admin/delphoto/<id>')
@basic_auth.required
def admin_delphoto(id): def admin_delphoto(id):
photo = Photo.query.filter_by(id=id).first_or_404() photo = Photo.query.filter_by(id=id).first_or_404()
db.session.delete(photo) db.session.delete(photo)
@ -114,6 +130,7 @@ def admin_delphoto(id):
os.remove(slide) os.remove(slide)
return redirect(url_for('admin')) return redirect(url_for('admin'))
@app.route('/admin/photo/<id>', methods=['GET', 'POST']) @app.route('/admin/photo/<id>', methods=['GET', 'POST'])
@basic_auth.required
def admin_photo(id): def admin_photo(id):
photo = Photo.query.filter_by(id=id).first_or_404() photo = Photo.query.filter_by(id=id).first_or_404()
form = PhotoForm(obj=photo) form = PhotoForm(obj=photo)

View File

@ -4,32 +4,34 @@ from app import db, models
db.create_all() db.create_all()
ph1 = models.Photo(alt="Kuvertbody superman") ph1 = models.Photo(alt="Design by Lovén")
ph2 = models.Photo(alt="Kuvertbody linjer") # ph2 = models.Photo(alt="Kuvertbody linjer")
ph3 = models.Photo(alt="Kuvertbody Hedvig") # ph3 = models.Photo(alt="Kuvertbody Hedvig")
index = models.Page(name="", title="Design by Lovén", description="Välkommen till *Design* by **Lovén**") index = models.Page(name="", title="Design by Lovén", description="Välkommen till Design by Lovén.", thumbnail=ph1, published=True)
kuvertbody = models.Page(name="kuvertbody", title="Kuvertbody", description="An praktisk body som man kan dra av neråt", thumbnail=ph1) # kuvertbody = models.Page(name="kuvertbody", title="Kuvertbody", description="An praktisk body som man kan dra av neråt", thumbnail=ph1)
linjer = models.Page(name="linjer", title="Kuvertbody - Linjer", description="Raka sömmar på framsidan", photos=[ph2, ph3], thumbnail=ph2, endpoint = True) # linjer = models.Page(name="linjer", title="Kuvertbody - Linjer", description="Raka sömmar på framsidan", photos=[ph2, ph3], thumbnail=ph2, endpoint = True)
superman = models.Page(name="superman", title="Kuvertbody - Superman", description="Alla barn är superhjältar", photos=[ph1], thumbnail=ph1, endpoint = True) # superman = models.Page(name="superman", title="Kuvertbody - Superman", description="Alla barn är superhjältar", photos=[ph1], thumbnail=ph1, endpoint = True)
index.children = [kuvertbody] # index.children = [kuvertbody]
kuvertbody.children.append(linjer) # kuvertbody.children.append(linjer)
kuvertbody.children.append(superman) # kuvertbody.children.append(superman)
ph1.link = superman # ph1.link = superman
ph2.link = linjer # ph2.link = linjer
ph3.link = linjer # ph3.link = linjer
db.session.add(ph1) # db.session.add(ph1)
db.session.add(ph2) # db.session.add(ph2)
db.session.add(ph3) # db.session.add(ph3)
db.session.add(index) db.session.add(index)
db.session.add(kuvertbody) # db.session.add(kuvertbody)
db.session.add(linjer) # db.session.add(linjer)
db.session.add(superman) # db.session.add(superman)
db.session.commit()
index.name = "/"
db.session.commit() db.session.commit()