Browse Source

Grosses modifs sur le design. Ajout des routes /user

master
Dark-Storm 8 months ago
parent
commit
584b1188d8
Signed by: Dark-Storm <l.gatin@neuf.fr> GPG Key ID: F61F10FA138E797C

+ 1
- 0
.gitignore View File

@@ -2,6 +2,7 @@ app.db

__pycache__/
app/__pycache__/
app/static/avatars/

venv/


+ 1
- 1
app/__init__.py View File

@@ -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

+ 3
- 1
app/models/privs.py View File

@@ -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):

+ 2
- 2
app/routes/admin.py View File

@@ -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")')

+ 9
- 1
app/routes/index.py View File

@@ -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

+ 0
- 2
app/routes/search.py View File

@@ -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()

+ 13
- 23
app/routes/users.py View File

@@ -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))

+ 7
- 1
app/static/css/container.css View File

@@ -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;

+ 1
- 0
app/static/css/form.css View File

@@ -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;

BIN
app/static/images/403.webp View File


BIN
app/static/images/404.webp View File


+ 1
- 1
app/templates/account.html View File

@@ -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">

+ 39
- 38
app/templates/admin.html View File

@@ -1,42 +1,43 @@
{% extends "base/container.html" %}

{% block content %}

<form action='' method='POST'>
{{ form.hidden_tag() }}
{{ form.submit }}
</form>

<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>

{% 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>

<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>
<form action='' method='POST'>
{{ form.hidden_tag() }}
{{ form.submit }}
</form>

<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>

{% 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>

<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>
</section>
{% endblock %}

+ 1
- 1
app/templates/base/navbar/account.html View File

@@ -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
- 1
app/templates/delete_account.html View File

@@ -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() }}

+ 9
- 0
app/templates/errors/403.html View File

@@ -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 %}

+ 9
- 0
app/templates/errors/404.html View File

@@ -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
- 1
app/templates/search.html View File

@@ -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">

+ 9
- 0
app/templates/user.html View File

@@ -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 %}

+ 5
- 5
app/templates/validation.html View File

@@ -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 %}

+ 3
- 6
app/utils/priv_required.py View File

@@ -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…
Cancel
Save