account: make default avatar selection less hacky

This commit is contained in:
Lephe 2022-05-05 20:18:30 +01:00
parent a3ed633791
commit 5a87d29c7f
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
7 changed files with 37 additions and 29 deletions

View File

@ -1,8 +1,7 @@
from datetime import date
from flask import url_for
from flask_login import UserMixin
from sqlalchemy import func as SQLfunc
from os.path import isfile
from PIL import Image
import werkzeug.security
from app import app, db
from app.models.priv import SpecialPrivilege, Group, GroupMember, \
@ -19,7 +18,9 @@ import app.utils.ldap as ldap
from app.utils.unicode_names import normalize
from config import V5Config
import werkzeug.security
from os.path import isfile
from datetime import date
from PIL import Image
import math
import app
import os
@ -89,16 +90,6 @@ class Member(User):
xp = db.Column(db.Integer)
register_date = db.Column(db.Date, default=date.today)
avatar_id = db.Column(db.Integer, default=0)
@property
def avatar(self):
return f'{self.id}_{self.avatar_id}.png'
@property
def level(self):
level = math.asinh(self.xp / 1000) * (100 / math.asinh(10))
return int(level), int(level * 100) % 100
# Groups and related privileges
groups = db.relationship('Group', secondary=GroupMember,
back_populates='members')
@ -115,6 +106,7 @@ class Member(User):
# Settings
newsletter = db.Column(db.Boolean, default=False)
theme = db.Column(db.Unicode(32))
avatar_id = db.Column(db.Integer, default=0)
# Relations
trophies = db.relationship('Trophy', secondary=TrophyMember,
@ -129,6 +121,23 @@ class Member(User):
def programs(self):
return db.session.query(Program).filter(Post.author_id==self.id).all()
@property
def avatar_filename(self):
return f'{self.id}_{self.avatar_id}.png'
@property
def avatar_url(self):
if self.avatar_id == 0:
return url_for('static', filename='images/default_avatar.png')
else:
return url_for('avatar',filename=self.avatar_filename)
@property
def level(self):
level = math.asinh(self.xp / 1000) * (100 / math.asinh(10))
return int(level), int(level * 100) % 100
# Other fields populated automatically through relations:
# <notifications> List of unseen notifications (of type Notification)
# <polls> Polls created by the member (of class Poll)
@ -312,20 +321,22 @@ class Member(User):
def set_avatar(self, avatar):
# Save old avatar filepath
old_avatar = os.path.join(V5Config.DATA_FOLDER, "avatars", self.avatar)
old_avatar = os.path.join(V5Config.DATA_FOLDER, "avatars",
self.avatar_filename)
# Resize & convert image
size = 128, 128
im = Image.open(avatar)
im.thumbnail(size, Image.ANTIALIAS)
im.thumbnail((128, 128), Image.ANTIALIAS)
# Change avatar id
# TODO: verify concurrency behavior
current_id = db.session.query(SQLfunc.max(Member.avatar_id)).first()[0]
self.avatar_id = current_id + 1
db.session.merge(self)
db.session.commit()
# Save the new avatar
im.save(os.path.join(V5Config.DATA_FOLDER, "avatars", self.avatar),
'PNG')
im.save(os.path.join(V5Config.DATA_FOLDER, "avatars",
self.avatar_filename), 'PNG')
# If nothing has failed, remove old one (allow failure to regularize
# exceptional situations like missing avatar or folder migration)
try:
@ -553,8 +564,7 @@ class Member(User):
# TODO: Trophy "actif"
if context in ["on-profile-update", None]:
if isfile(os.path.join(
V5Config.DATA_FOLDER, "avatars", self.avatar)):
if self.avatar_id != 0:
self.add_trophy("Artiste")
else:
self.del_trophy("Artiste")

View File

@ -11,9 +11,7 @@ import os
def avatar(filename):
filename = secure_filename(filename) # No h4ckers allowed
filepath = os.path.join(V5Config.DATA_FOLDER, "avatars", filename)
if os.path.isfile(filepath):
return send_file(filepath)
return redirect(url_for('static', filename='images/default_avatar.png'))
return send_file(filepath)
@app.route('/fichiers/<path>/<name>')
def attachment(path, name):

View File

@ -13,7 +13,7 @@
<div>
{{ form.avatar.label }}
<div>
<img class="avatar" src="{{ url_for('avatar', filename=current_user.avatar) }}" meta="{{ current_user.avatar }}" />
<img class="avatar" src="{{ current_user.avatar_url }}" />
{{ form.avatar }}
</div>
{% for error in form.avatar.errors %}

View File

@ -14,7 +14,7 @@
<div>
{{ form.avatar.label }}
<div>
<img class="avatar" src="{{ url_for('avatar', filename=user.avatar) }}" meta="{{ user.avatar }}" />
<img class="avatar" src="{{ user.avatar_url }}" />
{{ form.avatar }}
</div>
{% for error in form.avatar.errors %}

View File

@ -61,7 +61,7 @@
<li>
{% if current_user.is_authenticated %}
<a href="{{ url_for('user', username=current_user.name) }}" role="button" label="Compte" tabindex="0">
<img src="{{ url_for('avatar', filename=current_user.avatar) }}" alt="Avatar de {{ current_user.name }}">
<img src="{{ current_user.avatar_url }}" alt="Avatar de {{ current_user.name }}">
<div>Compte</div>
</a>
{% else %}

View File

@ -2,7 +2,7 @@
<div>
<h2>
<a href="{{ url_for('user', username=current_user.name) }}">
<img src="{{ url_for('avatar', filename=current_user.avatar) }}" alt="Avatar de {{ current_user.name }}"></a>
<img src="{{ current_user.avatar_url }}" alt="Avatar de {{ current_user.name }}"></a>
<a href="{{ url_for('user', username=current_user.name) }}">
{{ current_user.name }}</a>
</h2>

View File

@ -1,7 +1,7 @@
{% macro profile(user) %}
{% if user.type == "member" %}
<div class="profile">
<img class="profile-avatar" src="{{ url_for('avatar', filename=user.avatar) }}" alt="Avatar de {{ user.name }}">
<img class="profile-avatar" src="{{ user.avatar_url }}" alt="Avatar de {{ user.name }}">
<div>
<div class="profile-name"><a href="{{ url_for('user', username=user.name) }}">{{ user.name }}</a></div>
{% if user.title %}