diff --git a/templates/_nav_userlogin.html b/templates/_nav_userlogin.html index c79de41..8b96071 100644 --- a/templates/_nav_userlogin.html +++ b/templates/_nav_userlogin.html @@ -22,13 +22,20 @@
  • - Configurer mon site web + Personnaliser mon blog
  • - - Voir le blog + + Voir mon blog + +
  • +
  • + + Voir le blog général + +
  • diff --git a/templates/blog.html b/templates/blog.html index ff88043..a39527f 100644 --- a/templates/blog.html +++ b/templates/blog.html @@ -12,7 +12,7 @@

    {{ post_info.title }}

    -
    Publié le : {{ post_info.creation_date }}
    +
    Publié le : {{ post_info.creation_date }} par {{ post_info.author }}
    {% if post_info.last_updated %}
    Mis à jour le : {{ post_info.last_updated }}
    {% endif %} diff --git a/templates/blog_author.html b/templates/blog_author.html new file mode 100644 index 0000000..5f237ac --- /dev/null +++ b/templates/blog_author.html @@ -0,0 +1,26 @@ + + + + Article de {{ post_info.author }} + + + + + + +
    + +

    {{ post_info.title }}

    + +
    Publié le : {{ post_info.creation_date }}
    + {% if post_info.last_updated %} +
    Mis à jour le : {{ post_info.last_updated }}
    + {% endif %} +

    {{ post_info.subtitle }}

    +
    + {{ content|safe }} + + +
    + + diff --git a/templates/blog_rss.xml b/templates/blog_rss.xml new file mode 100644 index 0000000..f78d80d --- /dev/null +++ b/templates/blog_rss.xml @@ -0,0 +1,35 @@ + + + + Le blog de {{ blog_name }} + {{ base_url }}/blog/ + {% if blog_description %} + {{ blog_description }} + {% endif %} + fr + {{ last_build_date }} + + {% for post in posts %} + + {{ post.title }} + {% if post.last_updated %} {{ post.last_updated }} {% else %} {{ post.time }} {% endif %} + {{base_url}}/blog/{{ post.status }}/{{post.author}}/{{post.title}} + {{base_url}}/blog/{{ post.status }}/{{post.author}}/{{post.title}} + + + {{ post.subtitle }} + + + + {{ post.content | safe }} + + + {% endfor %} + + + diff --git a/templates/edit_article.html b/templates/edit_article.html index bf91e9f..c095450 100644 --- a/templates/edit_article.html +++ b/templates/edit_article.html @@ -1,17 +1,18 @@ {% extends 'up_squelette.html' %} {% block main %} - -

    Vous pouvez modifier votre article.

    -

    {{ oldpost['title'] }}


    -
    +


    -
    + + +
    +

    Visibilité

    +

    Les articles brouillons ne sont visibles que par vous même

    Les articles privés ne sont visibles que par les membres du serveur

    @@ -34,15 +35,23 @@ {% endif %}
    -
    - + +
    + +
    +
    -
    {% endblock %} - {% block js %} {% include '_js_editor.html' %} {% endblock %} diff --git a/templates/index_author_blog.html b/templates/index_author_blog.html new file mode 100644 index 0000000..4d8a11e --- /dev/null +++ b/templates/index_author_blog.html @@ -0,0 +1,41 @@ + + + + Le Blog du serveur + + + + + + + {% if not(posts) %} +

    Désolé ce blog n'existe pas encore :/

    + + + {% else %} + +
    + {% for post in posts %} + +

    {{ post.title }}

    + + +
    + {% if post.last_updated %} + + + {% endif %} +
    +
    +

    {{ post.subtitle }}

    +

    Lire la suite...

    +
    + {% endfor %} +
    + {% endif %} + + diff --git a/templates/index_blog.html b/templates/index_blog.html index 45e0ac6..d9c5fb9 100644 --- a/templates/index_blog.html +++ b/templates/index_blog.html @@ -14,13 +14,15 @@ {% else %} +
    + S'abonner au flux RSS {% for post in posts %} -

    {{ post.title }}

    +

    {{ post.title }}


    {% if post.last_updated %} diff --git a/templates/list_articles.html b/templates/list_articles.html index 4e010ae..c03b9e2 100644 --- a/templates/list_articles.html +++ b/templates/list_articles.html @@ -3,9 +3,10 @@ {% block main %} - -

    Vos articles de blog

    - +{% if nb_articles > 1 %} +

    Vos {{ nb_articles }} articles de blog

    +{% endif %} +
    {% for article in list_posts %}
    @@ -14,9 +15,25 @@
    Créé le : {{ article.time }}
    - Modifié le : {{ article.last_updated }} -

    Status : {{ article.status }}

    -
    + + {% if article.last_updated == "private" %} + Modifié le : {{ article.last_updated }}
    + {% endif %} + + {% if article.status == "private" %} + Status : privé + (L'article n'est pas publié dans le blog général) + {% elif article.status == "private_unified" %} + Status : privé + (L'article est publié dans le blog général) + {% elif article.status == "public" %} + Status : public + (L'article n'est pas publié dans le blog général) + {% elif article.status == "public_unified" %} + Status : public + (L'article est publié dans le blog général) + {% endif %} +
    diff --git a/templates/new_article_blog.html b/templates/new_article_blog.html index 7cca29f..331775b 100644 --- a/templates/new_article_blog.html +++ b/templates/new_article_blog.html @@ -32,6 +32,18 @@ Public

    + +
    + +
    + diff --git a/templates/personnalize_blog.html b/templates/personnalize_blog.html index b781ae0..89dea47 100644 --- a/templates/personnalize_blog.html +++ b/templates/personnalize_blog.html @@ -3,6 +3,32 @@ {% block main %} -

    Ça va venir dans la prochaine version !

    +

    Personnalisation du blog

    +
    + +
    + + + + + + +
    +

    Vous pouvez faire le choix d'envoyer un fichier css pour personnaliser votre blog directement. + + +
    +

    + +
    + + + {% endblock %} diff --git a/tools/databaseinit.py b/tools/databaseinit.py index 4749e53..62ae828 100755 --- a/tools/databaseinit.py +++ b/tools/databaseinit.py @@ -45,7 +45,6 @@ def init_db(database): category TEXT, author TEXT, status TEXT, - blog_theme TEXT, PRIMARY KEY(title, author) ) """) @@ -74,19 +73,22 @@ def check_directories(users_folder): print("Le dossier {} a été créé".format(users_folder)) def db_migrate(database): + + + invitations_col = False + lost_password_token_col = False + totp_col = False + blog_unified_col = False + blog_theme_col = False + updated_col = False + creation_date_col = False + content_col = False + conn = sqlite3.connect(database) cursor = conn.cursor() cursor.execute("""SELECT name FROM PRAGMA_TABLE_INFO('users');""") db_columns = cursor.fetchall() - invitations_col = False - lost_password_token_col = False - totp_col = False - blog_theme_col = False - updated_col = False - creation_date_col = False - content_col = False - for col in db_columns: if "invitations" == col[0]: invitations_col = True @@ -94,12 +96,13 @@ def db_migrate(database): lost_password_token_col = True if "totp" == col[0]: totp_col = True + if "blog_theme" == col[0]: + blog_theme_col = True + cursor.execute("""SELECT name FROM PRAGMA_TABLE_INFO('Blog_posts');""") db_columns = cursor.fetchall() for col in db_columns: - if "blog_theme" == col[0]: - blog_theme_col = True if "last_updated" == col[0]: updated_col = True if "content" == col[0]: @@ -125,8 +128,7 @@ def db_migrate(database): cursor.execute("""ALTER TABLE Users ADD COLUMN totp CHAR(40);""") conn.commit() print ("Ajout du champ totp dans la table Users") - - + if not(blog_theme_col): cursor.execute("""ALTER TABLE Blog_posts ADD COLUMN blog_theme TEXT;""") diff --git a/views/blog.py b/views/blog.py index 9f2db59..7dab167 100644 --- a/views/blog.py +++ b/views/blog.py @@ -7,6 +7,7 @@ import sqlite3 from markdown import markdown from tools.filesutils import getFileSizeKo import string +from shutil import copy from tools.utils import login_required blog = Blueprint('blog', __name__, template_folder='templates') @@ -18,10 +19,11 @@ app.config.from_pyfile('config.py') ########################### Variables Globales ################################# extensionimg = app.config['EXT_IMG'] DATABASE = app.config['DATABASE'] -BASE_URL= app.config['BASE_URL'] -DOSSIER_PERSO= app.config['DOSSIER_APP']+'/' -DOSSIER_PUBLIC= app.config['DOSSIER_PUBLIC']+'/' - +BASE_URL = app.config['BASE_URL'] +DOSSIER_PERSO = app.config['DOSSIER_APP']+'/' +DOSSIER_PUBLIC = app.config['DOSSIER_PUBLIC']+'/' +TITLE_SERVER = app.config['TITLE_SERVER'] +DESC_SERVER = app.config['DESC_SERVER'] ################################################################################ @blog.route('/myblog/new-article/', methods=['GET', 'POST']) @@ -30,12 +32,14 @@ def new_article(): user = '%s'% escape(session['username']) if request.method == 'POST': title = request.form['title'] - subtitle = request.form['subtitle'] + subtitle = request.form['subtitle'] category = request.form['category'] content = request.form['content'] status = request.form['status'] post_date = time.strftime("%d/%m/%Y %H:%M:%S") - + if 'blog-unified' in request.form.keys(): + status = status+'_unified' + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée cursor = conn.cursor() # Création de l'objet "curseur" cursor.execute("""INSERT INTO Blog_posts(title, subtitle, category, content, creation_date, author, status) VALUES(?, ?, ?, ?, ?, ?, ?)""", (title, subtitle, category, content, post_date, user, status)) # Insérer des valeurs @@ -51,7 +55,7 @@ def edit(title): user='%s'% escape(session['username']) folder_blog = DOSSIER_PERSO + user + "/blog/articles/" if request.method == 'POST' : - title = requrest.form['title'] + title = request.form['title'] subtitle = request.form['subtitle'] category = request.form['category'] newcontent = request.form['content'] @@ -59,7 +63,10 @@ def edit(title): updated = time.strftime("%d/%m/%Y %H:%M:%S") conn = sqlite3.connect(DATABASE) cursor = conn.cursor() - cursor.execute("""UPDATE Blog_posts SET title, subtitle=?, category=?, last_updated=?, status=?, content=? WHERE title=? AND author=?""", (title, subtitle, category, updated, newstatus, newcontent, title, user)) + if 'blog-unified' in request.form.keys(): + newstatus = newstatus+'_unified' + + cursor.execute("""UPDATE Blog_posts SET title=?, subtitle=?, category=?, last_updated=?, status=?, content=? WHERE title=? AND author=?""", (title, subtitle, category, updated, newstatus, newcontent, title, user)) conn.commit() conn.close() return redirect(url_for('blog.list_articles_blog')) @@ -91,14 +98,13 @@ def list_articles_blog(): time=post[2], last_updated=post[3], status=post[4])] + posts - nb_articles =+ 1 + nb_articles = nb_articles + 1 - return render_template('list_articles.html', - section="Articles", - list_posts=posts, - nb_articles=nb_articles - ) - + return render_template('list_articles.html', + section="Articles", + list_posts=posts, + nb_articles=nb_articles ) + @blog.route('/myblog/delete/') @login_required def delete(title): @@ -114,17 +120,62 @@ def delete(title): return redirect(url_for('blog.list_articles_blog')) -@blog.route('/myblog/personnalize/', methods=['GET']) +@blog.route('/myblog/personnalize/', methods=['GET', 'POST']) @login_required def personnalize_blog(): - return render_template('personnalize_blog.html') + user='%s' % escape(session['username']) + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée + cursor = conn.cursor() # Création de l'objet "curseur" + cursor.execute("""SELECT blog_unified, blog_theme FROM users WHERE name=?""", (user,)) + blog_info = cursor.fetchone() + conn.close() + blog_unified = blog_info[0] + if request.method == 'POST' : + + f = request.files['personnal-blog-theme'] + + blog_theme = escape(request.form['blog-theme']) + + + if blog_theme != "Default": + copy( "static/blog-"+blog_theme+".css", + DOSSIER_PERSO+ user +'blog.css' ) + + if f: # On vérifie qu'un fichier a bien été envoyé + nom = secure_filename(f.filename) + f.save(DOSSIER_PERSO + user + nom) + else: + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée + cursor = conn.cursor() # Création de l\'objet "curseur" + cursor.execute("UPDATE users SET blog_unified=?, blog_theme=? WHERE name=?", (blog_unified, blog_theme, user)) + conn.commit() + + return render_template('personnalize_blog.html', section='personnalize_blog', blog_unified=blog_unified, blog_theme=blog_info[1]) +@blog.route('/myblog/', methods=['GET']) +@login_required +def viewmyblog(): + user='%s' % escape(session['username']) + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée + cursor = conn.cursor() # Création de l'objet "curseur" + cursor.execute("""SELECT title, subtitle, creation_date, author, status FROM Blog_posts WHERE author=? AND status!='draft'""", (user,)) + list_posts=cursor.fetchall() + posts=list() + id=0 + conn.close() + if list_posts != None: + for post in list_posts: + posts=[dict(title=post[0], subtitle=post[1], creation_date=post[2], author=post[3], status=post[4])] + posts + + return render_template('index_blog.html', section='Blog', posts=posts) + + @blog.route('/private-blog/', methods=['GET']) @login_required def view_internal(): conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée cursor = conn.cursor() # Création de l'objet "curseur" - cursor.execute("""SELECT title, subtitle, content, creation_date, last_updated, author, status FROM Blog_posts WHERE status!='draft' """ ) + cursor.execute("""SELECT title, subtitle, content, creation_date, last_updated, author, status FROM Blog_posts WHERE status='private_unified' OR status='public_unified' """ ) list_posts=cursor.fetchall() conn.close() posts=list() @@ -141,17 +192,14 @@ def view_internal(): def view(): conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée cursor = conn.cursor() # Création de l'objet "curseur" - cursor.execute("""SELECT title, subtitle, creation_date, author, status FROM Blog_posts WHERE status='public'""" ) + cursor.execute("""SELECT title, subtitle, creation_date, author, status FROM Blog_posts WHERE status='public_unified'""" ) list_posts=cursor.fetchall() posts=list() id=0 conn.close() - if list_posts != None: + if list_posts != None: for post in list_posts: posts=[dict(title=post[0], subtitle=post[1], creation_date=post[2], author=post[3], status=post[4])] + posts - else: - return redirect(BASE_URL, code=404) - return render_template('index_blog.html', section='Blog', posts=posts) @@ -161,22 +209,46 @@ def viewuser(author): author = escape(author) conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée cursor = conn.cursor() # Création de l'objet "curseur" - cursor.execute("""SELECT title, subtitle, creation_date, last_updated, author FROM Blog_posts WHERE author=? AND status='public' """, (author,)) + if 'username' in session : + cursor.execute("""SELECT title, subtitle, creation_date, last_updated, author, status FROM Blog_posts WHERE author=? AND status != 'draft' """, (author,)) + else: + cursor.execute("""SELECT title, subtitle, creation_date, last_updated, author, status FROM Blog_posts WHERE author=? AND status='public' OR status='public_unified' """, (author,)) list_posts=cursor.fetchall() posts=None id=0 conn.close() - if list_posts != None: + if list_posts != None: posts=list() for post in list_posts: - posts=[dict(title=post[0], subtitle=post[1], creation_date=post[2], author=post[3], status=post[4])] + posts - else: - return redirect(BASE_URL, code=404) + posts=[dict(title=post[0], subtitle=post[1], creation_date=post[2], last_updated=post[3], author=post[4], status=post[5])] + posts - return render_template('index_blog.html', section='Blog', posts=posts) + return render_template('index_author_blog.html', section='Blog', posts=posts) + +@blog.route('/blog/<author>/rss.xml', methods=['GET']) +def viewauthorrss(author): + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée + cursor = conn.cursor() # Création de l'objet "curseur" + cursor.execute("""SELECT MAX (creation_date) FROM Blog_posts WHERE author=? AND status='public_unified' OR status='public'""", (author, ) ) + last_article_date = cursor.fetchone() + cursor.execute("""SELECT title, subtitle, content, creation_date, author, status FROM Blog_posts WHERE author=? AND status='public_unified' OR status='public'""", (author, ) ) + list_posts=cursor.fetchall() + posts=list() + id=0 + conn.close() + if list_posts != None: + last_build=last_article_date[0] + for post in list_posts: + posts=[dict(title=post[0], subtitle=post[1], content=markdown(post[2]), creation_date=post[3], author=post[4], status=post[5])] + posts + + return render_template('blog_rss.xml', + base_url=BASE_URL, + blog_name=author, + last_build_date=last_build, + posts=posts) +@blog.route('/blog/private_unified/<username>/<title>', methods=['GET']) @blog.route('/blog/private/<username>/<title>', methods=['GET']) @login_required def viewPrivateArticle(username, title): @@ -192,17 +264,16 @@ def viewPrivateArticle(username, title): content= markdown(post[2]) return render_template('blog.html', post_info=post_info, content=content) else: - return redirect(url_for('blog'), code=404); + return redirect(url_for('blog'), code=404) - - +@blog.route('/blog/public_unified/<username>/<title>', methods=['GET']) @blog.route('/blog/public/<username>/<title>', methods=['GET']) def viewArticle(username, title): user = username conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée cursor = conn.cursor() # Création de l'objet "curseur" - cursor.execute("""SELECT title, subtitle, content, creation_date, last_updated, author FROM Blog_posts WHERE author=? AND title=? AND status='public' """, (user, title) ) + cursor.execute("""SELECT title, subtitle, content, creation_date, last_updated, author FROM Blog_posts WHERE author=? AND title=? AND status='public_unified' """, (user, title) ) post = cursor.fetchone() conn.close() if post != None: @@ -211,5 +282,29 @@ def viewArticle(username, title): return render_template('blog.html', post_info=post_info, content=content) else: - return redirect(url_for('blog'), code=404); - + return redirect(url_for('blog.view'), code=404) + +@blog.route('/blog/rss.xml', methods=['GET']) +def viewrss(): + conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée + cursor = conn.cursor() # Création de l'objet "curseur" + cursor.execute("""SELECT MAX(creation_date) FROM Blog_posts WHERE status='public_unified'""") + last_article_date = cursor.fetchone() + print (last_article_date[0]) + cursor.execute("""SELECT title, subtitle, content, creation_date, author, status FROM Blog_posts WHERE status='public_unified'""" ) + list_posts=cursor.fetchall() + posts=list() + id=0 + conn.close() + if list_posts != None: + last_build=last_article_date[0] + for post in list_posts: + posts=[dict(title=post[0], subtitle=post[1], content=markdown(post[2]), creation_date=post[3], author=post[4], status=post[5])] + posts + + return render_template('blog_rss.xml', + base_url=BASE_URL, + blog_name= TITLE_SERVER, + last_build_date=last_build, + blog_description=DESC_SERVER, + posts=posts) + diff --git a/views/filesupload.py b/views/filesupload.py index 741912e..0757bd3 100644 --- a/views/filesupload.py +++ b/views/filesupload.py @@ -173,7 +173,16 @@ def remove_publicFile(filename): except FileNotFoundError: flash(u'Fichier {filename} inexistant.'.format(filename=filename), 'error') return redirect(url_for('filesupload.list', _external=True)) - + + +@filesupload.route('/<author>/blog.css') +def blog_theme(author): + user = author + if os.path.isfile(DOSSIER_PERSO+ user +'/blog-theme.css'): + return send_file(DOSSIER_PERSO+ user +'blog-theme.css', mimetype='text/css') + else: + return send_file("static/blog.css", mimetype='text/css') + @filesupload.route('/theme.min.css') def theme(): if 'username' in session: diff --git a/views/profil.py b/views/profil.py index 7811153..982337d 100644 --- a/views/profil.py +++ b/views/profil.py @@ -327,8 +327,9 @@ def totp_qrcode(): os.path.join(DOSSIER_PERSO, user, "totp.png"), "totp.png") -@profil.route('/deltoken-password-lost/<token>', methods=['GET','POST'] ) +@profil.route('/deltoken-password-lost/<token>', methods=['GET'] ) def deltoken_passwd_lost(token) : + token = escape(token) if valid_token_register(token, "Lost password"): user = get_user_by_token(token, "Lost password") conn = sqlite3.connect(DATABASE) # Connexion à la base de donnée