templates: slightly restructure and improve design
This commit is contained in:
parent
07a685f3c4
commit
9faabea997
|
@ -127,7 +127,7 @@ class Member(User, db.Model):
|
|||
|
||||
def priv(self, priv):
|
||||
"""Check whether the member has the specified privilege."""
|
||||
if SpecialPrivilege.query.filter_by(mid=self.id, priv=priv):
|
||||
if SpecialPrivilege.query.filter_by(mid=self.id, priv=priv).first():
|
||||
return True
|
||||
return False
|
||||
# return db.session.query(User, Group, GroupPrivilege).filter(
|
||||
|
|
|
@ -10,7 +10,7 @@ from app.utils.render import render
|
|||
from app import app, db
|
||||
|
||||
@app.route('/admin', methods=['GET', 'POST'])
|
||||
@priv_required('panel-admin')
|
||||
@priv_required('admin-panel')
|
||||
def admin():
|
||||
class AdminForm(FlaskForm):
|
||||
submit = SubmitField('Régénérer groupes, privilèges, membres de test')
|
||||
|
@ -38,7 +38,7 @@ def admin():
|
|||
m = Member.query.filter_by(name=name).first()
|
||||
if m is not None:
|
||||
db.session.delete(m)
|
||||
db.session.commit()
|
||||
db.session.commit()
|
||||
|
||||
# Create template members
|
||||
m = Member('PlanèteCasio','contact@planet-casio.com','v5-forever')
|
||||
|
|
|
@ -9,9 +9,9 @@ section {
|
|||
|
||||
section h1 {
|
||||
margin-top: 0;
|
||||
border-bottom: 1px solid #a0a0a0;
|
||||
font-family: Raleway; font-size: 32px;
|
||||
font-weight: 300; color: #242424;
|
||||
border-bottom: 1px solid #d8d8d8;
|
||||
font-family: Cantarell; font-weight: bold;
|
||||
font-size: 26px; color: #101010;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
@font-face { font-family: Raleway; font-weight: 200; src: url(../fonts/raleway_200.ttf); }
|
||||
@font-face { font-family: Raleway; font-weight: 300; src: url(../fonts/raleway_300.ttf); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
ALL
|
||||
*/
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
header {
|
||||
height: 50px; margin: 0; padding: 0 30px;
|
||||
height: 50px; margin: 0; padding: 0 16px;
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
background: #f4f4f6; border-bottom: 1px solid #d0d0d0;
|
||||
}
|
||||
|
@ -14,6 +14,10 @@ header h1 {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
header .spacer {
|
||||
flex: auto 1 0;
|
||||
}
|
||||
|
||||
header svg {
|
||||
width: 24px; height: 24px; vertical-align: middle;
|
||||
transition: .15s ease;
|
||||
|
@ -22,7 +26,7 @@ header a:hover > svg, header a:focus > svg {
|
|||
fill: black;
|
||||
}
|
||||
header a {
|
||||
fill: #484848;
|
||||
fill: #363636;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,6 @@ nav a:focus {
|
|||
align-items: center; flex-grow: 1;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
font-family: Raleway; font-size: 13px;
|
||||
color: #ffffff;
|
||||
}
|
||||
#light-menu li {
|
||||
|
@ -82,6 +81,7 @@ nav a:focus {
|
|||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
width: 100%; height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
#light-menu li > a > div {
|
||||
display: none;
|
||||
|
@ -363,4 +363,4 @@ footer {
|
|||
}
|
||||
footer p {
|
||||
margin: 3px 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
nav a {
|
||||
color: #ffffff;
|
||||
opacity: .7;
|
||||
opacity: 0.75;
|
||||
cursor: pointer;
|
||||
}
|
||||
nav a:hover,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block title %}
|
||||
Panneau d'administration » <h1>Utilisateurs et groupes</h1>
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr-FR">
|
||||
{% include "base/head.html" %}
|
||||
<body>
|
||||
{% include "base/navbar.html" %}
|
||||
|
||||
{% block container %}
|
||||
{% endblock container %}
|
||||
<div class="container">
|
||||
<header>
|
||||
<div>{% block title %}(page title){% endblock %}</div>
|
||||
{% include "base/header.html" %}
|
||||
</header>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% include "base/footer.html" %}
|
||||
{% include "base/flash.html" %}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
{% extends "base/base.html" %}
|
||||
|
||||
{% block container %}
|
||||
<div class="container">
|
||||
{% include "base/header.html" %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock container %}
|
|
@ -1,29 +1,22 @@
|
|||
<header>
|
||||
<div>
|
||||
{% block title %}
|
||||
Test
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div style="flex: auto 1 0"></div>
|
||||
<form action={{url_for('search')}} method="get">
|
||||
<input type="search" name="q" id="q" placeholder="{{search_form.label}}" />
|
||||
<a role="button" onclick="this.parentNode.submit();" href="#" class="light-hidden">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path fill="#adb0b4"d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</form>
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
<a href="{{ url_for('user', username=current_user.name) }}" role=button title='Mon compte'>
|
||||
<div class=spacer></div>
|
||||
<form action={{url_for('search')}} method="get">
|
||||
<input type="search" name="q" id="q" placeholder="{{search_form.label}}" />
|
||||
<a role="button" onclick="this.parentNode.submit();" href="#" class="light-hidden">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z"></path>
|
||||
<path fill="#adb0b4"d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
</form>
|
||||
|
||||
{% if current_user.is_authenticated %}
|
||||
<a href="{{ url_for('user', username=current_user.name) }}" role=button title='Mon compte'>
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z"></path>
|
||||
</svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div id="spotlight">
|
||||
<a href="#">Concours</a>
|
||||
<a href="#">Jeu du mois : février 2019</a>
|
||||
</div>
|
||||
</header>
|
||||
<div id="spotlight">
|
||||
<a href="#">Concours</a>
|
||||
<a href="#">Jeu du mois : février 2019</a>
|
||||
</div>
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#" label="Outils">
|
||||
<a role="button" label="Outils" tabindex="0">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path fill="#ffffff" d="M22.7,19L13.6,9.9C14.5,7.6 14,4.9 12.1,3C10.1,1 7.1,0.6 4.7,1.7L9,6L6,9L1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1C4.8,14 7.5,14.5 9.8,13.6L18.9,22.7C19.3,23.1 19.9,23.1 20.3,22.7L22.6,20.4C23.1,20 23.1,19.3 22.7,19Z"></path>
|
||||
</svg>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block title %}
|
||||
<h1>Planète Casio</h1>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="home-pinned-content">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form" style="width:40%;">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form" style="width:40%;">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "base/container.html" %}
|
||||
{% extends "base/base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
from flask import redirect, url_for, flash
|
||||
from flask import current_user
|
||||
import functools
|
||||
|
||||
# Use only with @login_required.
|
||||
def privilege_required(priv):
|
||||
def privilege_decorator(f):
|
||||
@functools.wraps(f)
|
||||
def wrapper():
|
||||
if not current_user.priv(priv):
|
||||
flash(f'Cette page est protégée par le privilège <code>{priv}'+
|
||||
'</code>', 'error')
|
||||
return redirect(url_for('index'))
|
||||
else:
|
||||
f()
|
||||
return wrapper
|
||||
return privilege_decorator
|
|
@ -6,19 +6,19 @@ from app import app
|
|||
|
||||
def priv_required(*perms):
|
||||
"""
|
||||
If you decorate a view with this, it will ensure that the current user is
|
||||
authenticated and has required permissions before calling the actual view.
|
||||
(If they are not, it calls the :attr:`LoginManager.unauthorized` callback.)
|
||||
For example::
|
||||
Requires the user to be an authenticated member with privileges [perms].
|
||||
Calls :attr:`LoginManager.unauthorized` if the user is not authenticated,
|
||||
and a 403 if some of the privileges are missing.
|
||||
|
||||
Example:
|
||||
@app.route('/admin')
|
||||
@priv_required('access-admin-board')
|
||||
def admin_board():
|
||||
pass
|
||||
|
||||
It can be convenient to globally turn off authentication when unit testing.
|
||||
To enable this, if the application configuration variable `LOGIN_DISABLED`
|
||||
is set to `True`, this decorator will be ignored.
|
||||
Setting the `LOGIN_DISABLED` configuration variable to `True` will silence
|
||||
this decorator.
|
||||
"""
|
||||
def decorated_view(func):
|
||||
@wraps(func)
|
||||
|
@ -32,6 +32,7 @@ def priv_required(*perms):
|
|||
else:
|
||||
for p in perms:
|
||||
if not current_user.priv(p):
|
||||
# TODO: Add error message and privilege name
|
||||
abort(403)
|
||||
return func(*args, **kwargs)
|
||||
return wrapped
|
||||
|
|
|
@ -35,4 +35,7 @@ Miscellaenous:
|
|||
footer-statistics View performance statistics in the page footer
|
||||
community-login Automatically login as a community account
|
||||
|
||||
Administration panel...
|
||||
Administration panel:
|
||||
admin-panel Access administration panel (read-only as it is)
|
||||
edt-account Edit details of any account
|
||||
delete-account Remove member accounts
|
||||
|
|
|
@ -6,6 +6,7 @@ class Config(object):
|
|||
'postgresql+psycopg2://' + os.environ.get('USER') + ':@/pcv5'
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
UPLOAD_FOLDER = './app/static/avatars'
|
||||
LOGIN_DISABLED=True
|
||||
|
||||
class V5Config(object):
|
||||
# Length allocated to privilege names (slugs)
|
||||
|
@ -14,4 +15,3 @@ class V5Config(object):
|
|||
FORBIDDEN_USERNAMES = [ "admin", "root", "webmaster", "contact" ]
|
||||
# Unauthorized message (@priv_required)
|
||||
UNAUTHORIZED_MSG = "Vous n'avez pas l'autorisation d'effectuer cette action !"
|
||||
|
||||
|
|
Loading…
Reference in New Issue