diff --git a/app/forms/forum.py b/app/forms/forum.py index dcd0549..7162415 100644 --- a/app/forms/forum.py +++ b/app/forms/forum.py @@ -1,6 +1,7 @@ from flask_wtf import FlaskForm from wtforms import StringField, FormField, SubmitField, TextAreaField from wtforms.validators import DataRequired, Length +import app.utils.validators as vd class TopicCreationForm(FlaskForm): title = StringField('Nom du sujet', @@ -8,6 +9,15 @@ class TopicCreationForm(FlaskForm): message = TextAreaField('Message principal', validators=[DataRequired()]) submit = SubmitField('Créer le sujet') +class AnonymousTopicCreationForm(TopicCreationForm): + pseudo = StringField('Pseudo', + validators=[DataRequired(), vd.name_valid, vd.name_available]) + + class CommentForm(FlaskForm): message = TextAreaField('Commentaire', validators=[DataRequired()]) submit = SubmitField('Commenter') + +class AnonymousCommentForm(CommentForm): + pseudo = StringField('Pseudo', + validators=[DataRequired(), vd.name_valid, vd.name_available]) diff --git a/app/models/users.py b/app/models/users.py index c427314..e69a830 100644 --- a/app/models/users.py +++ b/app/models/users.py @@ -51,14 +51,15 @@ class Guest(User): # ID of the [User] entry id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) - # Reusable username, can be the name of a member (will be distinguished at - # rendering time) - username = db.Column(db.Unicode(64), index=True) - # IP address, 47 characters is the max for an IPv6 address - ip = db.Column(db.String(47)) + # Reusable username, cannot be chosen as the name of a member + # but will be distinguished at rendering time if a member take it later + name = db.Column(db.Unicode(64)) + + def __init__(self, name): + self.name = name def __repr__(self): - return f'' + return f'' class Member(User): diff --git a/app/processors/utilities.py b/app/processors/utilities.py index 1531347..1fa5e62 100644 --- a/app/processors/utilities.py +++ b/app/processors/utilities.py @@ -1,5 +1,6 @@ from app import app from flask import url_for +from config import V5Config @app.context_processor def utilities_processor(): @@ -8,4 +9,5 @@ def utilities_processor(): len=len, # enumerate=enumerate, _url_for = lambda route, args, **other: url_for(route, **args, **other), + V5Config = V5Config, ) diff --git a/app/routes/account/login.py b/app/routes/account/login.py index 1147200..5f952c3 100644 --- a/app/routes/account/login.py +++ b/app/routes/account/login.py @@ -61,11 +61,6 @@ def login(): @app.route('/deconnexion') @login_required def logout(): - try: - print(request.referrer) - except Exception as e: - print('No referrer:', e) - logout_user() flash('Déconnexion réussie', 'info') if request.referrer: diff --git a/app/routes/account/notification.py b/app/routes/account/notification.py index 6ce1dd2..c73269e 100644 --- a/app/routes/account/notification.py +++ b/app/routes/account/notification.py @@ -24,7 +24,6 @@ def delete_notification(id=None): if type(id) == int: notification = Notification.query.get(id) - print(">", notification) if notification: # Only current user or admin can delete notifications if notification.owner_id == current_user.id: diff --git a/app/routes/admin/account.py b/app/routes/admin/account.py index ae32cb6..1e5497a 100644 --- a/app/routes/admin/account.py +++ b/app/routes/admin/account.py @@ -35,8 +35,6 @@ def adm_edit_account(user_id): setattr(GroupForm, "user_groups", [f'g{g.id}' for g in user.groups]) group_form = GroupForm(prefix="group") - print(group_form.__dict__.items()) - if form.submit.data: if form.validate_on_submit(): newname = form.username.data diff --git a/app/routes/forum/index.py b/app/routes/forum/index.py index ad08dbc..6c46298 100644 --- a/app/routes/forum/index.py +++ b/app/routes/forum/index.py @@ -4,11 +4,12 @@ from flask import request, redirect, url_for, abort, flash from app import app, db from config import V5Config from app.utils.render import render -from app.forms.forum import TopicCreationForm +from app.forms.forum import TopicCreationForm, AnonymousTopicCreationForm from app.models.forum import Forum from app.models.topic import Topic from app.models.thread import Thread from app.models.comment import Comment +from app.models.users import Guest @app.route('/forum/') @@ -17,7 +18,10 @@ def forum_index(): @app.route('/forum//', methods=['GET', 'POST']) def forum_page(f): - form = TopicCreationForm() + if current_user.is_authenticated: + form = TopicCreationForm() + else: + form = AnonymousTopicCreationForm() # TODO: do not hardcode name of news forums if form.validate_on_submit() and ( @@ -27,28 +31,35 @@ def forum_page(f): or ("/actus" in f.url and current_user.is_authenticated and current_user.priv('write-news')) # Forum is not news and is a leaf: - or ("/actus" not in f.url and not f.sub_forums)): + or ("/actus" not in f.url and not f.sub_forums)) and ( + V5Config.ENABLE_GUEST_POST or current_user.is_authenticated): # First create the thread, then the comment, then the topic th = Thread() db.session.add(th) db.session.commit() - c = Comment(current_user, form.message.data, th) + if current_user.is_authenticated: + author = current_user + else: + author = Guest(form.pseudo.data) + db.session.add(author) + + c = Comment(author, form.message.data, th) db.session.add(c) db.session.commit() th.set_top_comment(c) db.session.merge(th) - t = Topic(f, current_user, form.title.data, th) + t = Topic(f, author, form.title.data, th) db.session.add(t) db.session.commit() # Update member's xp and trophies - current_user.add_xp(V5Config.XP_POINTS['topic']) - current_user.update_trophies('new-post') - + if current_user.is_authenticated: + current_user.add_xp(V5Config.XP_POINTS['topic']) + current_user.update_trophies('new-post') flash('Le sujet a bien été créé', 'ok') return redirect(url_for('forum_topic', f=f, page=(t,1))) diff --git a/app/routes/forum/topic.py b/app/routes/forum/topic.py index 0539551..ac264be 100644 --- a/app/routes/forum/topic.py +++ b/app/routes/forum/topic.py @@ -4,11 +4,12 @@ from flask import request, redirect, url_for, flash, abort from app import app, db from config import V5Config from app.utils.render import render -from app.forms.forum import CommentForm +from app.forms.forum import CommentForm, AnonymousCommentForm from app.models.forum import Forum from app.models.topic import Topic from app.models.thread import Thread from app.models.comment import Comment +from app.models.users import Guest @app.route('/forum//', methods=['GET', 'POST']) @@ -19,16 +20,27 @@ def forum_topic(f, page): if f != t.forum: abort(404) - form = CommentForm() + if current_user.is_authenticated: + form = CommentForm() + else: + form = AnonymousCommentForm() - if form.validate_on_submit(): - c = Comment(current_user, form.message.data, t.thread) + if form.validate_on_submit() and \ + (V5Config.ENABLE_GUEST_POST or current_user.is_authenticated): + if current_user.is_authenticated: + author = current_user + else: + author = Guest(form.pseudo.data) + db.session.add(author) + + c = Comment(author, form.message.data, t.thread) db.session.add(c) db.session.commit() # Update member's xp and trophies - current_user.add_xp(V5Config.XP_POINTS['comment']) - current_user.update_trophies('new-post') + if current_user.is_authenticated: + current_user.add_xp(V5Config.XP_POINTS['comment']) + current_user.update_trophies('new-post') flash('Message envoyé', 'ok') # Redirect to empty the form diff --git a/app/static/css/global.css b/app/static/css/global.css index e994e2f..c969d63 100644 --- a/app/static/css/global.css +++ b/app/static/css/global.css @@ -17,7 +17,7 @@ body { margin: 0; background: var(--background); color: var(--text); - font-family: Twemoji, 'DejaVu Sans', sans-serif; + font-family: 'DejaVu Sans', sans-serif; } /* General */ diff --git a/app/static/css/table.css b/app/static/css/table.css index 4421350..0375b2c 100644 --- a/app/static/css/table.css +++ b/app/static/css/table.css @@ -71,6 +71,15 @@ table.thread { table.thread td.member { width: 20%; } +table.thread td.guest { + width: 20%; padding-top: 12px; + text-align: center; +} +table.thread td.guest em { + display: block; + font-weight: bold; font-style: normal; + margin-bottom: 8px; +} table.thread td { vertical-align: top; } diff --git a/app/templates/admin/edit_account.html b/app/templates/admin/edit_account.html index e824093..c4b821d 100644 --- a/app/templates/admin/edit_account.html +++ b/app/templates/admin/edit_account.html @@ -6,7 +6,7 @@ {% block content %}
- Visiter la page de profil de {{ user.name }} + Visiter la page de profil de {{ user.name }}
{{ form.hidden_tag() }}

Informations

diff --git a/app/templates/forum/forum.html b/app/templates/forum/forum.html index 04a3496..3ce57e9 100644 --- a/app/templates/forum/forum.html +++ b/app/templates/forum/forum.html @@ -43,11 +43,21 @@ {% if (current_user.is_authenticated and current_user.priv('write-anywhere')) or ("/actus" in f.url and current_user.is_authenticated and current_user.priv('write-news')) - or ("/actus" not in f.url and not f.sub_forums) %} + or ("/actus" not in f.url and not f.sub_forums) + and (current_user.is_authenticated or V5Config.ENABLE_GUEST_POST) %}

Créer un nouveau sujet

{{ form.hidden_tag() }} + {% if form.pseudo %} +
+ {{ form.pseudo.label }} + {{ form.pseudo() }} + {% for error in form.pseudo.errors %} + {{ error }} + {% endfor %} +
+ {% endif %}
{{ form.title.label }} diff --git a/app/templates/forum/topic.html b/app/templates/forum/topic.html index b0008f1..50ba387 100644 --- a/app/templates/forum/topic.html +++ b/app/templates/forum/topic.html @@ -11,7 +11,11 @@

{{ t.title }}

- + {% if t.author.type == "member" %} + + {% else %} + + {% endif %}
{{ widget_member.profile(t.author ) }}{{ widget_member.profile(t.author ) }}Invité{{ t.author.name }}{{ t.thread.top_comment.text }}
@@ -21,7 +25,11 @@ {% for c in comments.items %} {% if c != t.thread.top_comment %} - {{ widget_member.profile(c.author ) }} + {% if c.author.type == "member" %} + {{ widget_member.profile(c.author ) }} + {% else %} + Invité{{ c.author.name }} + {% endif %}
{% if c.date_created != c.date_modified %} Posté le {{ c.date_created|date }} (Modifié le {{ c.date_modified|date }}) @@ -44,15 +52,25 @@ {{ widget_pagination.paginate(comments, 'forum_topic', t, {'f': t.forum}) }} + {% if current_user.is_authenticated or V5Config.ENABLE_GUEST_POST %}

Commenter le sujet

- + {{ form.hidden_tag() }} + {% if form.pseudo %} + {{ form.pseudo.label }} + {{ form.pseudo }} + {% for error in form.pseudo.errors %} + {{ error }} + {% endfor %} + {% endif %} + {{ widget_editor.text_editor(form.message, label=False) }}
{{ form.submit(class_='bg-ok') }}
+ {% endif %}
{% endblock %} diff --git a/config.py b/config.py index 4cc9911..69c5deb 100644 --- a/config.py +++ b/config.py @@ -18,6 +18,7 @@ class Config(object): class DefaultConfig(object): + """Every value here can be overrided in the local_config.py class""" # Length allocated to privilege names (slugs) PRIVS_MAXLEN = 64 # Forbidden user names @@ -54,7 +55,9 @@ class DefaultConfig(object): SECRET_KEY = "a-random-secret-key" # Avatars folder AVATARS_FOLDER = '/avatar/folder/' + # Enable guest post + ENABLE_GUEST_POST = True class V5Config(LocalConfig, DefaultConfig): - # Args put here cannot be overidden with local_config + # Values put here cannot be overidden with local_config pass diff --git a/local_config.py.default b/local_config.py.default index 82c0aa4..7885f5f 100644 --- a/local_config.py.default +++ b/local_config.py.default @@ -1,3 +1,6 @@ +# This is a sample file +# You can override every value available in the class DefaultConfig + class LocalConfig(object): DB_NAME = "pcv5" USE_LDAP = True @@ -5,3 +8,4 @@ class LocalConfig(object): LDAP_ORGANIZATION = "o=planet-casio" SECRET_KEY = "a-random-secret-key" # CHANGE THIS VALUE *NOW* AVATARS_FOLDER = '/home/pc/data/avatars/' + ENABLE_GUEST_POST = True diff --git a/migrations/versions/d1b465f88d3b_modification_du_guest.py b/migrations/versions/d1b465f88d3b_modification_du_guest.py new file mode 100644 index 0000000..2b33458 --- /dev/null +++ b/migrations/versions/d1b465f88d3b_modification_du_guest.py @@ -0,0 +1,42 @@ +"""Modification du Guest + +Revision ID: d1b465f88d3b +Revises: c40b1f0ed821 +Create Date: 2020-07-17 22:56:36.260431 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'd1b465f88d3b' +down_revision = 'c40b1f0ed821' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('guest', sa.Column('name', sa.Unicode(length=64), nullable=True)) + op.drop_index('ix_guest_username', table_name='guest') + op.drop_column('guest', 'ip') + op.drop_column('guest', 'username') + op.alter_column('member', 'avatar_id', + existing_type=sa.INTEGER(), + nullable=True, + existing_server_default=sa.text('0')) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('member', 'avatar_id', + existing_type=sa.INTEGER(), + nullable=False, + existing_server_default=sa.text('0')) + op.add_column('guest', sa.Column('username', sa.VARCHAR(length=64), autoincrement=False, nullable=True)) + op.add_column('guest', sa.Column('ip', sa.VARCHAR(length=47), autoincrement=False, nullable=True)) + op.create_index('ix_guest_username', 'guest', ['username'], unique=False) + op.drop_column('guest', 'name') + # ### end Alembic commands ###