Grosses modifs sur le design. Ajout des routes /user
This commit is contained in:
parent
cd533a4ea3
commit
584b1188d8
|
@ -2,6 +2,7 @@ app.db
|
|||
|
||||
__pycache__/
|
||||
app/__pycache__/
|
||||
app/static/avatars/
|
||||
|
||||
venv/
|
||||
|
||||
|
|
|
@ -14,4 +14,4 @@ login.login_view = 'login'
|
|||
login.login_message = "Veuillez vous authentifier avant de continuer."
|
||||
|
||||
from app import models
|
||||
from app.routes import index, login, search, account, admin
|
||||
from app.routes import index, login, search, account, admin, users
|
||||
|
|
|
@ -28,8 +28,10 @@ class SpecialPrivilege(db.Model):
|
|||
return f'<Privilege "{self.priv}" of member #{mid}>'
|
||||
|
||||
# TODO: clean this. filter does not work ootb
|
||||
# This ensure that refresh the page should sometime fail with a 403
|
||||
def filter(*args, **kwargs):
|
||||
return False
|
||||
from random import randint
|
||||
return not not randint(0, 2)
|
||||
|
||||
# Group: User group, corresponds to a community role and a set of privileges
|
||||
class Group(db.Model):
|
||||
|
|
|
@ -4,12 +4,12 @@ from wtforms import SubmitField
|
|||
from app.models.users import Member, Group, GroupPrivilege
|
||||
from app.models.privs import SpecialPrivilege
|
||||
from app.utils.render import render
|
||||
from app.utils.priv_required import priv_required
|
||||
from app import app, db
|
||||
|
||||
@app.route('/admin', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
@priv_required('panel-admin')
|
||||
def admin():
|
||||
|
||||
class AdminForm(FlaskForm):
|
||||
submit = SubmitField('Régénérer les groupes, les privilèges, et les ' +
|
||||
'membres de test "PlanèteCasio" et "GLaDOS" (mdp "v5-forever")')
|
||||
|
|
|
@ -4,4 +4,12 @@ from app.utils.render import render
|
|||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render('index.html')
|
||||
return render('index.html')
|
||||
|
||||
@app.errorhandler(404)
|
||||
def file_not_found(e):
|
||||
return render('errors/404.html'), 404
|
||||
|
||||
@app.errorhandler(403)
|
||||
def unauthorized_access(e):
|
||||
return render('errors/403.html'), 403
|
|
@ -2,8 +2,6 @@ from app import app
|
|||
from app.forms.search import AdvancedSearchForm
|
||||
from app.utils.render import render
|
||||
|
||||
from app.utils.priv_required import priv_required
|
||||
|
||||
@app.route('/search')
|
||||
def search():
|
||||
form = AdvancedSearchForm()
|
||||
|
|
|
@ -1,30 +1,20 @@
|
|||
from flask import redirect, url_for, request, flash
|
||||
from flask import redirect, url_for, abort
|
||||
from flask_login import login_required, current_user, logout_user
|
||||
from app import app, db
|
||||
from app.forms.account import UpdateAccountForm, RegistrationForm, DeleteAccountForm
|
||||
from app.models.users import Member
|
||||
from app.utils.render import render
|
||||
|
||||
@app.route('/users/<username>')
|
||||
def user():
|
||||
form = UpdateAccountForm()
|
||||
if request.method == "POST":
|
||||
if form.validate_on_submit():
|
||||
if form.avatar.data:
|
||||
f = form.avatar.data
|
||||
f.save("./app/static/"+current_user.avatar)
|
||||
current_user.update(
|
||||
email = form.email.data or None,
|
||||
password = form.password.data or None,
|
||||
birthday = form.birthday.data,
|
||||
signature = form.signature.data,
|
||||
biography = form.biography.data,
|
||||
newsletter = form.newsletter.data
|
||||
)
|
||||
db.session.merge(current_user)
|
||||
db.session.commit()
|
||||
flash('Modifications effectuées', 'ok')
|
||||
else:
|
||||
flash('Erreur lors de la modification', 'error')
|
||||
@app.route('/user/<username>')
|
||||
def user(username):
|
||||
user = Member.query.filter_by(name=username).first()
|
||||
if not user:
|
||||
abort(404)
|
||||
return render('user.html', user=user)
|
||||
|
||||
return render('account.html', form=form)
|
||||
@app.route('/user/id/<int:user_id>')
|
||||
def user_by_id(user_id):
|
||||
user = Member.query.filter_by(id=user_id).first()
|
||||
if not user:
|
||||
abort(404)
|
||||
return redirect(url_for('user', username=user.name))
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
section {
|
||||
min-width: 350px;
|
||||
min-width: 350px; width: 90%;
|
||||
margin: 20px auto 0; padding: 20px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dddddd; border-radius: 5px;
|
||||
|
@ -23,6 +23,12 @@ section h2 {
|
|||
font-weight: 300; color: #242424;
|
||||
}
|
||||
|
||||
section .avatar {
|
||||
display: block;
|
||||
border-radius: 100%;
|
||||
width: 150px; height: 150px;
|
||||
}
|
||||
|
||||
/* #container h1 {
|
||||
margin-left: 5%;
|
||||
font-family: Raleway; font-size: 24px;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
border-radius: 100%;
|
||||
width: 150px; height: 150px;
|
||||
}
|
||||
|
||||
.form .avatar + input[type="file"] {
|
||||
display: inline-block; margin-left: 20px;
|
||||
vertical-align: middle;
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
|
@ -1,7 +1,7 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form" style="width:80%;">
|
||||
<section class="form">
|
||||
<h1>Gestion du compte</h1>
|
||||
|
||||
<form action="{{ url_for('account') }}" method="post" enctype="multipart/form-data">
|
||||
|
|
|
@ -1,42 +1,43 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
<form action='' method='POST'>
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.submit }}
|
||||
</form>
|
||||
|
||||
<form action='' method='POST'>
|
||||
{{ form.hidden_tag() }}
|
||||
{{ form.submit }}
|
||||
</form>
|
||||
<h2>List of members</h2>
|
||||
|
||||
<h2>List of members</h2>
|
||||
<table style="width:70%; margin: auto;">
|
||||
<tr><th>Name</th><th>Email</th><th>Register</th><th>XP</th><th>Inn.</th>
|
||||
<th>Newsletter</th></tr>
|
||||
|
||||
<table style="width:70%; margin: auto;">
|
||||
<tr><th>Name</th><th>Email</th><th>Register</th><th>XP</th><th>Inn.</th>
|
||||
<th>Newsletter</th></tr>
|
||||
{% for user in users %}
|
||||
<tr><td><a href="{{ url_for('user_by_id', user_id=user.id) }}" >{{ user.name }}</a></td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>{{ user.register_date }}</td><td>{{ user.xp }}</td>
|
||||
<td>{{ user.innovation }}</td>
|
||||
<td>{{ "Yes" if user.newsletter else "No" }}</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
{% for user in users %}
|
||||
<tr><td>{{ user.name }}</td><td>{{ user.email }}</td>
|
||||
<td>{{ user.register_date }}</td><td>{{ user.xp }}</td>
|
||||
<td>{{ user.innovation }}</td>
|
||||
<td>{{ "Yes" if user.newsletter else "No" }}</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<h2>List of groups</h2>
|
||||
|
||||
<h2>List of groups</h2>
|
||||
|
||||
<table style="width:70%; margin: auto;">
|
||||
<tr><th>Group</th><th>Members</th><th>Privileges</th></tr>
|
||||
|
||||
{% for group in groups %}
|
||||
<tr><td><span style="{{ group.css }}">{{ group.name }}</span></td><td>
|
||||
{% for user in group.members %}
|
||||
{{ user.name }}
|
||||
{% endfor %}
|
||||
</td><td>
|
||||
{% for priv in group.privs %}
|
||||
<code>{{ priv }}</code>
|
||||
{% endfor %}
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
<table style="width:70%; margin: auto;">
|
||||
<tr><th>Group</th><th>Members</th><th>Privileges</th></tr>
|
||||
|
||||
{% for group in groups %}
|
||||
<tr><td><span style="{{ group.css }}">{{ group.name }}</span></td><td>
|
||||
{% for user in group.members %}
|
||||
{{ user.name }}
|
||||
{% endfor %}
|
||||
</td><td>
|
||||
{% for priv in group.privs %}
|
||||
<code>{{ priv }}</code>
|
||||
{% endfor %}
|
||||
</td></tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</svg>
|
||||
Topics favoris
|
||||
</a>
|
||||
<a href="#">
|
||||
<a href="{{ url_for('admin') }}">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path fill="#ffffff" d="M3,1H19A1,1 0 0,1 20,2V6A1,1 0 0,1 19,7H3A1,1 0 0,1 2,6V2A1,1 0 0,1 3,1M3,9H19A1,1 0 0,1 20,10V10.67L17.5,9.56L11,12.44V15H3A1,1 0 0,1 2,14V10A1,1 0 0,1 3,9M3,17H11C11.06,19.25 12,21.4 13.46,23H3A1,1 0 0,1 2,22V18A1,1 0 0,1 3,17M8,5H9V3H8V5M8,13H9V11H8V13M8,21H9V19H8V21M4,3V5H6V3H4M4,11V13H6V11H4M4,19V21H6V19H4M17.5,12L22,14V17C22,19.78 20.08,22.37 17.5,23C14.92,22.37 13,19.78 13,17V14L17.5,12M17.5,13.94L15,15.06V17.72C15,19.26 16.07,20.7 17.5,21.06V13.94Z"></path>
|
||||
</svg>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form" style="width:80%;">
|
||||
<section class="form">
|
||||
<h1>Suppression du compte</h2>
|
||||
<form action="{{ url_for('delete_account') }}" method="post">
|
||||
{{ del_form.hidden_tag() }}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
<h1>403 - Accès non autorisé</h1>
|
||||
|
||||
<img src="{{url_for('static', filename = 'images/403.webp')}}" style="display:block;margin:auto"; />
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
<h1>404 - Page non trouvée</h1>
|
||||
|
||||
<img src="{{url_for('static', filename = 'images/404.webp')}}" style="display:block;margin:auto"; />
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="form" style="width:80%;">
|
||||
<section class="form">
|
||||
<h1>Recherche avancée</h1>
|
||||
|
||||
<form action="" method="get">
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section>
|
||||
<h1>
|
||||
<img class="avatar" src="{{ url_for('static', filename=user.avatar) }}" alt="{{ user.name }}" style="display:inline; vertical-align:middle;"/>
|
||||
Profil de {{ user.name }}</h1>
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,10 +1,10 @@
|
|||
{% extends "base/container.html" %}
|
||||
|
||||
{% block content %}
|
||||
<section class="home-pinned-content">
|
||||
<div>
|
||||
<p>ici il y aura la page qui demande de checker les mails pour valider</p><br>
|
||||
<a href="{{url_for('index')}}">Retour à la page d'accueil</a>
|
||||
</div>
|
||||
<section>
|
||||
<div>
|
||||
<p>ici il y aura la page qui demande de checker les mails pour valider</p><br>
|
||||
<a href="{{url_for('index')}}">Retour à la page d'accueil</a>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from functools import wraps
|
||||
from flask import redirect, url_for, request, flash
|
||||
from flask import redirect, url_for, request, flash, abort
|
||||
from flask_login import current_user
|
||||
from flask_login.config import EXEMPT_METHODS
|
||||
from app import app
|
||||
from config import V5Config
|
||||
|
||||
def priv_required(*perms):
|
||||
"""
|
||||
|
@ -27,15 +26,13 @@ def priv_required(*perms):
|
|||
if request.method in EXEMPT_METHODS:
|
||||
return func(*args, **kwargs)
|
||||
elif app.config.get('LOGIN_DISABLED'):
|
||||
#if app.config.get('LOGIN_DISABLED'):
|
||||
return func(*args, **kwargs)
|
||||
elif not current_user.is_authenticated:
|
||||
return app.login_manager.unauthorized()
|
||||
else:
|
||||
for p in perms:
|
||||
if not current_user.priv(p):
|
||||
flash(V5Config.UNAUTHORIZED_MSG, 'error')
|
||||
return redirect(url_for('index'))
|
||||
abort(403)
|
||||
return func(*args, **kwargs)
|
||||
return wrapped
|
||||
return decorated_view
|
||||
return decorated_view
|
||||
|
|
Loading…
Reference in New Issue