From 60c889ad762888f0df76a84cae213891ffe7af41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xos=C3=A9=20M?= Date: Tue, 21 Aug 2018 07:28:00 +0200 Subject: [PATCH 01/33] primera ao galego --- po/gl.po | 279 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 140 insertions(+), 139 deletions(-) diff --git a/po/gl.po b/po/gl.po index d5a558d..d27b2f6 100644 --- a/po/gl.po +++ b/po/gl.po @@ -4,7 +4,7 @@ msgstr "" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2018-06-15 16:33-0700\n" "PO-Revision-Date: 2018-06-15 16:33-0700\n" -"Last-Translator: Automatically generated\n" +"Last-Translator: Xosé M. \n" "Language-Team: none\n" "Language: gl\n" "MIME-Version: 1.0\n" @@ -13,413 +13,414 @@ msgstr "" "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" msgid "Latest articles" -msgstr "" +msgstr "Últimos artigos" msgid "No posts to see here yet." -msgstr "" +msgstr "Aínda non hai entradas publicadas" msgid "New article" -msgstr "" +msgstr "Novo artigo" msgid "New blog" -msgstr "" +msgstr "Novo blog" msgid "Create a blog" -msgstr "" +msgstr "Crear un blog" msgid "Title" -msgstr "" +msgstr "Título" msgid "Create blog" -msgstr "" +msgstr "Crear blog" msgid "Comment \"{{ post }}\"" -msgstr "" +msgstr "Comentar \"{{ post }}\"" msgid "Content" -msgstr "" +msgstr "Contido" msgid "Submit comment" -msgstr "" +msgstr "Enviar comentario" msgid "Something broke on our side." -msgstr "" +msgstr "Algo fallou pola nosa parte" msgid "Sorry about that. If you think this is a bug, please report it." -msgstr "" +msgstr "Lamentálmolo. Si cree que é un bug, infórmenos por favor." msgid "Configuration" -msgstr "" +msgstr "Axustes" msgid "Configure your instance" -msgstr "" +msgstr "Configure a súa instancia" msgid "Name" -msgstr "" +msgstr "Nome" msgid "Let's go!" -msgstr "" +msgstr "Imos!" msgid "Welcome on {{ instance_name | escape }}" -msgstr "" +msgstr "Ben vida a {{ instance_name | escape }}" msgid "Notifications" -msgstr "" +msgstr "Notificacións" msgid "" "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" -msgstr "" +msgstr "Escrito por {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" msgid "This article is under the {{ license }} license." -msgstr "" +msgstr "Este artigo ten licenza {{ license }}" msgid "One like" msgid_plural "{{ count }} likes" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Un gústame" +msgstr[1] "{{ count }} gústame" msgid "I don't like this anymore" -msgstr "" +msgstr "Xa non me gusta" msgid "Add yours" -msgstr "" +msgstr "Engada os seus" msgid "One reshare" msgid_plural "{{ count }} reshares" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Compartido unha vez" +msgstr[1] "Compartido {{ count }} veces" msgid "I don't want to reshare this anymore" -msgstr "" +msgstr "Xa non quero compartir esto" msgid "Reshare" -msgstr "" +msgstr "Compartir" msgid "Comments" -msgstr "" +msgstr "Comentarios" msgid "Respond" -msgstr "" +msgstr "Respostar" msgid "Comment" -msgstr "" +msgstr "Comentar" msgid "New post" -msgstr "" +msgstr "Nova entrada" msgid "Create a post" -msgstr "" +msgstr "Crear unha entrada" msgid "Publish" -msgstr "" +msgstr "Publicar" msgid "Login" -msgstr "" +msgstr "Conectar" msgid "Username or email" -msgstr "" +msgstr "Usuaria ou correo-e" msgid "Password" -msgstr "" +msgstr "Contrasinal" msgid "Dashboard" -msgstr "" +msgstr "Taboleiro" msgid "Your Dashboard" -msgstr "" +msgstr "O seu taboleiro" msgid "Your Blogs" -msgstr "" +msgstr "Os seus Blogs" msgid "You don't have any blog yet. Create your own, or ask to join one." -msgstr "" +msgstr "Aínda non ten blogs. Publique un, ou solicita unirse a un." msgid "Start a new blog" -msgstr "" +msgstr "Iniciar un blog" msgid "Admin" -msgstr "" +msgstr "Admin" msgid "It is you" -msgstr "" +msgstr "É vosted" msgid "Edit your profile" -msgstr "" +msgstr "Edite o seu perfil" msgid "Open on {{ instance_url }}" -msgstr "" +msgstr "Abrir en {{ instance_url }}" msgid "Follow" -msgstr "" +msgstr "Seguir" msgid "Unfollow" -msgstr "" +msgstr "Deixar de seguir" msgid "Recently reshared" -msgstr "" +msgstr "Compartido recentemente" msgid "One follower" msgid_plural "{{ count }} followers" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Unha seguidora" +msgstr[1] "{{ count }} seguidoras" msgid "Edit your account" -msgstr "" +msgstr "Edite a súa conta" msgid "Your Profile" -msgstr "" +msgstr "O seu perfil" msgid "Display Name" -msgstr "" +msgstr "Nome mostrado" msgid "Email" -msgstr "" +msgstr "Correo-e" msgid "Summary" -msgstr "" +msgstr "Resumen" msgid "Update account" -msgstr "" +msgstr "Actualizar conta" msgid "{{ name | escape }}'s followers" -msgstr "" +msgstr "Seguidoras de {{ name | escape }}" msgid "Followers" -msgstr "" +msgstr "Seguidoras" msgid "New Account" -msgstr "" +msgstr "Nova conta" msgid "Create an account" -msgstr "" +msgstr "Crear unha conta" msgid "Username" -msgstr "" +msgstr "Nome de usuaria" msgid "Password confirmation" -msgstr "" +msgstr "Confirmación do contrasinal" msgid "Create account" -msgstr "" +msgstr "Crear conta" msgid "Plume" -msgstr "" +msgstr "Plume" msgid "Menu" -msgstr "" +msgstr "Menú" msgid "My account" -msgstr "" +msgstr "A miña conta" msgid "Log Out" -msgstr "" +msgstr "Desconectar" msgid "Log In" -msgstr "" +msgstr "Conectar" msgid "Register" -msgstr "" +msgstr "Rexistrar" msgid "You need to be logged in order to create a new blog" -msgstr "" +msgstr "Debe estar conectada para crear un novo blog" msgid "You need to be logged in order to post a comment" -msgstr "" +msgstr "Debe estar conectada para publicar un comentario" msgid "You need to be logged in order to like a post" -msgstr "" +msgstr "Debe estar conectada para gustar unha entrada" msgid "You need to be logged in order to see your notifications" -msgstr "" +msgstr "Debe estar conectada para ver as súas notificacións" msgid "You need to be logged in order to write a new post" -msgstr "" +msgstr "Debe estar conectada para escribir unha nova entrada" msgid "You need to be logged in order to reshare a post" -msgstr "" +msgstr "Debe estar conectada para compartir unha entrada" msgid "Invalid username or password" -msgstr "" +msgstr "Usuaria ou Contrasinal incorrectos" msgid "You need to be logged in order to access your dashboard" -msgstr "" +msgstr "Debe estar conectada para acceder ao seu taboleiro" msgid "You need to be logged in order to follow someone" -msgstr "" +msgstr "Debe estar conectada para seguir a alguén" msgid "You need to be logged in order to edit your profile" -msgstr "" +msgstr "Debe estar conectada para editar o seu perfil" msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" -msgstr "" +msgstr "Por {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" msgid "{{ data }} reshared your article" -msgstr "" +msgstr "{{ data }} comparteu o seu artigo" msgid "{{ data }} started following you" -msgstr "" +msgstr "{{ data }} comezou a seguila" msgid "{{ data }} liked your article" -msgstr "" +msgstr "{{ data }} gustou do seu artigo" msgid "{{ data }} commented your article" -msgstr "" +msgstr "{{ data }} comentou o seu artigo" msgid "We couldn't find this page." -msgstr "" +msgstr "Non atopamos esta páxina" msgid "The link that led you here may be broken." -msgstr "" +msgstr "A ligazón que a trouxo aquí podería estar quebrado" msgid "You are not authorized." -msgstr "" +msgstr "Non ten permiso." msgid "You are not author in this blog." -msgstr "" +msgstr "Vostede non é autora en este blog." msgid "{{ data }} mentioned you." -msgstr "" +msgstr "{{ data }} mencionouna." msgid "Your comment" -msgstr "" +msgstr "O seu comentario" msgid "Unknown error" -msgstr "" +msgstr "Fallo descoñecido" msgid "Invalid name" -msgstr "" +msgstr "Nome non válido" msgid "A blog with the same name already exists." -msgstr "" +msgstr "Xa existe un blog co mismo nome." msgid "Your comment can't be empty" -msgstr "" +msgstr "O seu comentario non pode estar baldeiro" msgid "A post with the same title already exists." -msgstr "" +msgstr "Xa existe unha entrada co mismo nome." msgid "We need an email or a username to identify you" -msgstr "" +msgstr "Precisamos un correo-e ou un nome de usuaria para identificala" msgid "Your password can't be empty" -msgstr "" +msgstr "O contrasinal non pode estar baldeiro" msgid "Passwords are not matching" -msgstr "" +msgstr "Con coinciden os contrasinais" msgid "Username can't be empty" -msgstr "" +msgstr "O nome de usuaria non pode estar baldeiro" msgid "Invalid email" -msgstr "" +msgstr "Correo-e non válido" msgid "Password should be at least 8 characters long" -msgstr "" +msgstr "O contrasinal debe ter ao menos 8 caracteres" msgid "One author in this blog: " msgid_plural "{{ count }} authors in this blog: " -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Unha autora en este blog: " +msgstr[1] "{{ count }} autoras en este blog: " msgid "Login or use your Fediverse account to interact with this article" -msgstr "" +msgstr "Conéctese ou utilice a súa conta no fediverso para interactuar con este artigo" msgid "Optional" -msgstr "" +msgstr "Opcional" msgid "One article in this blog" msgid_plural "{{ count }} articles in this blog" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Un artigo en este blog" +msgstr[1] "{{ count }} artigos en este blog" msgid "Previous page" -msgstr "" +msgstr "Páxina anterior" msgid "Next page" -msgstr "" +msgstr "Páxina seguinte" msgid "{{ user }} mentioned you." -msgstr "" +msgstr "{{ user }} mencionouna." msgid "{{ user }} commented your article." -msgstr "" +msgstr "{{ user }} comentou o artigo." msgid "{{ user }} is now following you." -msgstr "" +msgstr "{{ user }} está a seguila." msgid "{{ user }} liked your article." -msgstr "" +msgstr "{{ user }} gustou do seu artigo." msgid "{{ user }} reshared your article." -msgstr "" +msgstr "{{ user }} comparteu o seu artigo." msgid "Source code" -msgstr "" +msgstr "Código fonte" msgid "Matrix room" -msgstr "" +msgstr "Sala Matrix" msgid "Administration" -msgstr "" +msgstr "Administración" msgid "Instance settings" -msgstr "" +msgstr "Axustes da instancia" msgid "Allow anyone to register" -msgstr "" +msgstr "Permitir o rexistro aberto" msgid "Short description" -msgstr "" +msgstr "Descrición curta" msgid "Markdown is supported" -msgstr "" +msgstr "Escritura Markdown activada" msgid "Long description" -msgstr "" +msgstr "Descrición longa" msgid "Default license" -msgstr "" +msgstr "Licenza por omisión" msgid "Save settings" -msgstr "" +msgstr "Gardar axustes" msgid "No comments yet. Be the first to react!" -msgstr "" +msgstr "Sin comentarios. Sexa a primeira e comentar!" msgid "About this instance" -msgstr "" +msgstr "Sobre esta instancia" msgid "What is Plume?" -msgstr "" +msgstr "Qué é Plume?" msgid "Plume is a decentralized blogging engine." -msgstr "" +msgstr "Plume é un motor de publicación descentralizada." msgid "Authors can manage various blogs from an unique website." -msgstr "" +msgstr "As autoras poden xestionar varios blogs desde un único sitio web." msgid "" "Articles are also visible on other Plume websites, and you can interact with " "them directly from other platforms like Mastodon." -msgstr "" +msgstr "Os artigos son visibles tamén en outros sitios Plume, e pode interactuar con" +"eles desde outras plataformas como Mastadon." msgid "Create your account" -msgstr "" +msgstr "Cree a súa conta" msgid "About {{ instance_name }}" -msgstr "" +msgstr "Acerca de {{ instance_name }}" msgid "Home to" -msgstr "" +msgstr "Fogar de" msgid "people" -msgstr "" +msgstr "persoas" msgid "Who wrote" -msgstr "" +msgstr "Que escribiron" msgid "articles" -msgstr "" +msgstr "artigos" msgid "Read the detailed rules" -msgstr "" +msgstr "Lea o detalle das normas" From 5bc7284a7284f741d0cb4d335472cc5bbd0761c0 Mon Sep 17 00:00:00 2001 From: GnoxR Date: Tue, 21 Aug 2018 15:22:00 +0000 Subject: [PATCH 02/33] Improve French translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consistently use infinitive for action strings (Commentez → Commenter). Fix a few typos and simplify inclusive writing (aut⋅eur⋅ice⋅s → auteur⋅ice⋅s). End more error messages with a period to make forms more consistent. Translate previous page and next page. --- po/fr.po | 59 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/po/fr.po b/po/fr.po index 8ce372d..b1e246e 100644 --- a/po/fr.po +++ b/po/fr.po @@ -43,18 +43,18 @@ msgid "Submit comment" msgstr "Envoyer le commentaire" msgid "Something broke on our side." -msgstr "Nous avons cassé quelque chose" +msgstr "Nous avons cassé quelque chose." msgid "Sorry about that. If you think this is a bug, please report it." msgstr "" "Nous sommes désolé⋅e⋅s. Si vous pensez que c'est un bogue, merci de le " -"rapporter." +"signaler." msgid "Configuration" msgstr "Configuration" msgid "Configure your instance" -msgstr "Configurez votre instance" +msgstr "Configurer votre instance" msgid "Name" msgstr "Nom" @@ -78,7 +78,7 @@ msgstr "Cet article est placé sous la licence {{ license }}" msgid "One like" msgid_plural "{{ count }} likes" -msgstr[0] "{{ count }} personne aime cet article" +msgstr[0] "Une personne aime cet article" msgstr[1] "{{ count }} personnes aiment cet article" msgid "I don't like this anymore" @@ -93,10 +93,10 @@ msgstr[0] "{{ count }} repartage" msgstr[1] "{{ count }} repartages" msgid "I don't want to reshare this anymore" -msgstr "Je ne veux plus repartager" +msgstr "Je ne veux plus repartager ceci" msgid "Reshare" -msgstr "Repartagez" +msgstr "Repartager" msgid "Comments" msgstr "Commentaires" @@ -105,7 +105,7 @@ msgid "Respond" msgstr "Répondre" msgid "Comment" -msgstr "Commentez" +msgstr "Commenter" msgid "New post" msgstr "Nouvel article" @@ -140,7 +140,7 @@ msgstr "" "un." msgid "Start a new blog" -msgstr "Commencez un nouveau blog" +msgstr "Commencer un nouveau blog" msgid "Admin" msgstr "Administrateur" @@ -149,7 +149,7 @@ msgid "It is you" msgstr "C'est vous" msgid "Edit your profile" -msgstr "Éditez votre profil" +msgstr "Éditer votre profil" msgid "Open on {{ instance_url }}" msgstr "Ouvrir sur {{ instance_url }}" @@ -165,7 +165,7 @@ msgstr "Récemment repartagé" msgid "One follower" msgid_plural "{{ count }} followers" -msgstr[0] "{{ count }} abonné⋅e" +msgstr[0] "Un⋅e abonné⋅e" msgstr[1] "{{ count }} abonné⋅e⋅s" msgid "Edit your account" @@ -256,7 +256,7 @@ msgid "You need to be logged in order to edit your profile" msgstr "Vous devez vous connecter pour modifier votre profil" msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" -msgstr "De {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" +msgstr "Par {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" msgid "{{ data }} reshared your article" msgstr "{{ data }} a repartagé votre article" @@ -274,13 +274,13 @@ msgid "We couldn't find this page." msgstr "Page introuvable." msgid "The link that led you here may be broken." -msgstr "Le lien que vous avez suivi est cassé." +msgstr "Vous avez probablement suivi un lien cassé." msgid "You are not authorized." msgstr "Vous n'avez pas les droits." msgid "You are not author in this blog." -msgstr "Vous n'êtes pas auteur dans ce blog." +msgstr "Vous n'êtes pas auteur⋅ice dans ce blog." msgid "{{ data }} mentioned you." msgstr "{{ data }} vous a mentionné." @@ -298,7 +298,7 @@ msgid "A blog with the same name already exists." msgstr "Un blog avec le même nom existe déjà." msgid "Your comment can't be empty" -msgstr "Votre commentaire ne peux pas être vide" +msgstr "Votre commentaire ne peut pas être vide." msgid "A post with the same title already exists." msgstr "Un article avec le même titre existe déjà." @@ -310,7 +310,7 @@ msgstr "" #, fuzzy msgid "Your password can't be empty" -msgstr "Votre commentaire ne peux pas être vide" +msgstr "Votre mot de passe ne peut pas être vide." msgid "Passwords are not matching" msgstr "Les mots de passe ne correspondent pas." @@ -319,15 +319,15 @@ msgid "Username can't be empty" msgstr "Le nom d'utilisateur ne peut pas être vide." msgid "Invalid email" -msgstr "Adresse mail invalide" +msgstr "Adresse mail invalide." msgid "Password should be at least 8 characters long" msgstr "Le mot de passe doit faire au moins 8 caractères." msgid "One author in this blog: " msgid_plural "{{ count }} authors in this blog: " -msgstr[0] "{{ count }} aut⋅eur⋅rice dans ce blog : " -msgstr[1] "{{ count }} aut⋅eur⋅rice⋅s dans ce blog : " +msgstr[0] "Un⋅e auteur⋅ice dans ce blog : " +msgstr[1] "{{ count }} auteur⋅ice⋅s dans ce blog : " msgid "Login or use your Fediverse account to interact with this article" msgstr "" @@ -340,14 +340,14 @@ msgstr "Optionnel" #, fuzzy msgid "One article in this blog" msgid_plural "{{ count }} articles in this blog" -msgstr[0] "{{ count }} aut⋅eur⋅rice dans ce blog : " -msgstr[1] "{{ count }} aut⋅eur⋅rice⋅s dans ce blog : " +msgstr[0] "Un article dans ce blog" +msgstr[1] "{{ count }} articles dans ce blog" msgid "Previous page" -msgstr "" +msgstr "Page précédente" msgid "Next page" -msgstr "" +msgstr "Page suivante" msgid "{{ user }} mentioned you." msgstr "{{ user }} vous a mentionné." @@ -395,7 +395,7 @@ msgid "Save settings" msgstr "Enregistrer les paramètres" msgid "No comments yet. Be the first to react!" -msgstr "Pas encore de commentaires. Soyez læ premi⋅er⋅ère à réagir !" +msgstr "Pas encore de commentaires. Soyez læ premier⋅ère à réagir !" msgid "About this instance" msgstr "À propos de cette instance" @@ -407,15 +407,14 @@ msgid "Plume is a decentralized blogging engine." msgstr "Plume est un moteur de blog décentralisé." msgid "Authors can manage various blogs from an unique website." -msgstr "Les auteurs peuvent gérer différents blogs au sein d'un même site." +msgstr "Les auteur⋅ice⋅s peuvent gérer différents blogs au sein d'un même site." msgid "" "Articles are also visible on other Plume websites, and you can interact with " "them directly from other platforms like Mastodon." msgstr "" -"Les articles sont également visibles sur d'autres sites Plume et vous pouvez " -"interagir avec eux directement depuis d'autres plateformes telles que " -"Mastodon." +"Les articles sont également visibles sur d'autres sites Plume, et vous pouvez " +"interagir avec directement depuis d'autres plateformes telles que Mastodon." msgid "Create your account" msgstr "Créer votre compte" @@ -427,16 +426,16 @@ msgid "Home to" msgstr "Accueille" msgid "people" -msgstr "personnnes" +msgstr "personnes" msgid "Who wrote" -msgstr "Qui ont écrit" +msgstr "Ayant écrit" msgid "articles" msgstr "articles" msgid "Read the detailed rules" -msgstr "Lisez le détail des règles" +msgstr "Lire les règles détaillées" #~ msgid "Your password should be at least 8 characters long" #~ msgstr "Votre mot de passe doit faire au moins 8 caractères." From d03d14b2ca412c6475bb9e2cb9b95a03a17fc825 Mon Sep 17 00:00:00 2001 From: GnoxR Date: Wed, 22 Aug 2018 20:08:09 +0000 Subject: [PATCH 03/33] Revert bad changes in the French translation I didn't look up how plurals worked with this i18n engine and I had the wrong belief that the zero in French was plural. --- po/fr.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/po/fr.po b/po/fr.po index b1e246e..7d7c5d7 100644 --- a/po/fr.po +++ b/po/fr.po @@ -78,7 +78,7 @@ msgstr "Cet article est placé sous la licence {{ license }}" msgid "One like" msgid_plural "{{ count }} likes" -msgstr[0] "Une personne aime cet article" +msgstr[0] "{{ count }} personne aime cet article" msgstr[1] "{{ count }} personnes aiment cet article" msgid "I don't like this anymore" @@ -165,7 +165,7 @@ msgstr "Récemment repartagé" msgid "One follower" msgid_plural "{{ count }} followers" -msgstr[0] "Un⋅e abonné⋅e" +msgstr[0] "{{ count }} abonné⋅e" msgstr[1] "{{ count }} abonné⋅e⋅s" msgid "Edit your account" @@ -326,7 +326,7 @@ msgstr "Le mot de passe doit faire au moins 8 caractères." msgid "One author in this blog: " msgid_plural "{{ count }} authors in this blog: " -msgstr[0] "Un⋅e auteur⋅ice dans ce blog : " +msgstr[0] "{{ count }} auteur⋅ice dans ce blog : " msgstr[1] "{{ count }} auteur⋅ice⋅s dans ce blog : " msgid "Login or use your Fediverse account to interact with this article" @@ -340,7 +340,7 @@ msgstr "Optionnel" #, fuzzy msgid "One article in this blog" msgid_plural "{{ count }} articles in this blog" -msgstr[0] "Un article dans ce blog" +msgstr[0] "{{ count }} article dans ce blog" msgstr[1] "{{ count }} articles dans ce blog" msgid "Previous page" From ce289b79fa987b252683146ed34e4ae48e7157f3 Mon Sep 17 00:00:00 2001 From: "Kevin \"Ilphrin\" Pellet" Date: Thu, 30 Aug 2018 22:47:25 +0200 Subject: [PATCH 04/33] 151 - Make the editor bigger and autosize it --- static/js/autoExpand.js | 14 ++++++++++++++ static/main.css | 3 +++ templates/posts/new.html.tera | 3 ++- 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 static/js/autoExpand.js diff --git a/static/js/autoExpand.js b/static/js/autoExpand.js new file mode 100644 index 0000000..33fb32e --- /dev/null +++ b/static/js/autoExpand.js @@ -0,0 +1,14 @@ +function autosize(){ + const el = this; + el.style.height = 'auto'; + el.style.height = (el.scrollHeight ) + 'px'; +} + +const articleContent = document.querySelector('#content'); +let offset = 0; +let style = window.getComputedStyle(articleContent, null); + +offset += parseInt(style['paddingTop']) + parseInt(style['paddingBottom']); +autosize.bind(articleContent)(); +articleContent.addEventListener('keyup', autosize); + diff --git a/static/main.css b/static/main.css index 0ed247d..d2c05ba 100644 --- a/static/main.css +++ b/static/main.css @@ -422,6 +422,9 @@ form.new-post .title { } form.new-post textarea { min-height: 20em; + overflow-y: hidden; + resize: none; + box-sizing: content-box; } form.new-post input[type="submit"] { background: #ECECEC; diff --git a/templates/posts/new.html.tera b/templates/posts/new.html.tera index 9a4b297..1892f2f 100644 --- a/templates/posts/new.html.tera +++ b/templates/posts/new.html.tera @@ -17,11 +17,12 @@ {% endif %} - + {% set license_infos = "Default license will be {{ instance.default_license }}" | _(instance=instance) %} {{ macros::input(name="license", label="License", errors=errors, form=form, optional=true, details=license_infos) }} + {% endblock content %} From 62d299bd7ed59eaa8d69c115e57063db4df7aac5 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 11:32:18 +0100 Subject: [PATCH 05/33] Put all documentation in the docs folder --- DEVELOPMENT.md => docs/DEVELOPMENT.md | 0 INSTALL.md => docs/INSTALL.md | 0 INTERNATIONALIZATION.md => docs/INTERNATIONALIZATION.md | 0 {doc => docs}/PREREQUISITES.md | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename DEVELOPMENT.md => docs/DEVELOPMENT.md (100%) rename INSTALL.md => docs/INSTALL.md (100%) rename INTERNATIONALIZATION.md => docs/INTERNATIONALIZATION.md (100%) rename {doc => docs}/PREREQUISITES.md (100%) diff --git a/DEVELOPMENT.md b/docs/DEVELOPMENT.md similarity index 100% rename from DEVELOPMENT.md rename to docs/DEVELOPMENT.md diff --git a/INSTALL.md b/docs/INSTALL.md similarity index 100% rename from INSTALL.md rename to docs/INSTALL.md diff --git a/INTERNATIONALIZATION.md b/docs/INTERNATIONALIZATION.md similarity index 100% rename from INTERNATIONALIZATION.md rename to docs/INTERNATIONALIZATION.md diff --git a/doc/PREREQUISITES.md b/docs/PREREQUISITES.md similarity index 100% rename from doc/PREREQUISITES.md rename to docs/PREREQUISITES.md From 44ac96b3140a95b4dbb78929130ca413ac87675b Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 12:53:14 +0100 Subject: [PATCH 06/33] Clean up installation docs --- docs/DEVELOPMENT.md | 74 ++-------------- docs/INSTALL.md | 198 ++++++++++++++++++++++++++++++++---------- docs/PREREQUISITES.md | 2 +- 3 files changed, 160 insertions(+), 114 deletions(-) diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 2555fe2..374a0f3 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -1,74 +1,10 @@ # Development Guide -## Running Plume locally +## Installing the development environment -### Mac OSX +Please refer to the [installation guide](INSTALL.md). -All commands are run in the Mac Terminal or terminal emulator of your choice, such as iTerm2. First, you will need [Git](https://git-scm.com/download/mac), [Homebrew](https://brew.sh/), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Follow the instructions to install Homebrew before continuing if you don't already have it. - -### Linux - -Similar to Mac OSX all commands should be run from a terminal (a.k.a command line). First, you will need [Git](https://git-scm.com/download/mac), [Rust](https://www.rust-lang.org/en-US/), and [Postgres](https://www.postgresql.org/). Step-by-step instructions are also available here: [Installing Prerequisites](/doc/PREREQUISITES.md) - -#### Download the Repository - -Navigate to the directory on your machine where you would like to install the repository, such as in `~/dev` by running `cd dev`. Now, clone the remote repository by running `git clone https://github.com/Plume-org/Plume.git`. This will install the codebase to the `Plume` subdirectory. Navigate into that directory by running `cd Plume`. - -#### Rust - -If you think you might already have rust on your machine, you can check by running - -``` -rustc --version -# Should output something like -# rustc 1.28.0-nightly (a805a2a5e 2018-06-10) -``` - -If you don't already have Rust, install it by running - -``` -curl https://sh.rustup.rs -sSf | sh -``` - -In the interactive installation, choose the option of the nightly toolchain. Restart your console so that the `rustc` CLI tool is available. - -#### Postgres - -Now we will use Homebrew to install Postgres. If you think you might already have it, try running `brew info postgres`. If it is not available, continue to install Postgres by running the following: - -``` -brew install postgres -``` - -Now, you can use the following command to start Postgres on a one-time basis. - -``` -pg_ctl -D /usr/local/var/postgres start -``` - -When you will launch Plume for the first time, it will setup the database by itself. - -#### Database Migration - -To run migrations and correctly setup the database, Plume use the `diesel` CLI tool under the hood. Therefore you should install it before running Plume. If this was your time installing Rust, you will probably need to run that using `cargo`. `cargo` is installed with `rustc` so if you followed the earlier instructions it will already be available. - -``` -cargo install diesel_cli --version '=1.2.0' -``` - -#### Running Plume - -To run Plume locally, make sure you are once again in the Plume directory, such as `~/dev/Plume`. Now you will be able to run the application using the command - -``` -cargo run -``` - -#### Configuration - -The first time you'll run Plume, it will help you setup your instance through an interactive tool. Once you'll have answered all its question, your instance will start. - -#### Testing the federation +## Testing the federation To test the federation, you'll need to setup another database (see "Setup the database"), also owned by the "plume" user, but with a different name. Then, you'll need to run the @@ -93,7 +29,7 @@ If you don't want to setup HTTPS locally, you can also disable it by running you USE_HTTPS=0 cargo run ``` -#### Making a Pull Request +## Making a Pull Request To create an upstream fork of the repository in GitHub, click "Fork" in the top right button on the main page of the [Plume repository](https://github.com/Plume-org/Plume). Now, in the command line, set another remote for the repository by running the following command, replacing `myname` with the name under which you forked the repo. You can use another name besides `upstream` if you prefer. Using [SSH](https://help.github.com/articles/connecting-to-github-with-ssh/) is recommended. ``` @@ -105,7 +41,7 @@ Now, make any changes to the code you want. After committing your changes, push The project maintainers may suggest further changes to improve the pull request even more. After implementing this locally, you can push to your upstream fork again and the changes will immediately show up in the pull request after pushing. Once all the suggested changes are made, the pull request may be accepted. Thanks for contributing. -#### When working with Tera templates +## When working with Tera templates When working with the interface, or any message that will be displayed to the final user, keep in mind that Plume is an internationalized software. To make sure that the parts of the interface you are changing are translatable, you should: diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 778c677..413a85c 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -1,32 +1,100 @@ -# How to install Plume on a Debian stretch: +# Installing Plume (for development or production) -## Basic setup: +## Prerequisites + +In order to be installed and to work correctly, Plume needs: + +- Git +- PostgreSQL +- GetText +- Rust and Cargo + +All the following instructions will need a terminal. + +Here are the commands to install PostgreSQL and GetText on various operating systems. +Some of them may need root permissions. + +On **Debian**: ```bash apt update -apt install gettext postgresql postgresql-contrib libpq-dev -adduser plume -su - plume -cd /home/plume -git clone https://github.com/Plume-org/Plume.git -curl https://sh.rustup.rs -sSf | sh -cd Plume -rustup toolchain install nightly -rustup toolchain default nightly -rustup update -cargo install diesel_cli --no-default-features --features postgres --version '=1.2.0' # we dont need to compile anything else than pgsql +apt install gettext postgresql postgresql-contrib libpq-dev git ``` -## Now, if you want to run postgresql on the same server: +On **Fedora**, **CentOS** or **RHEL**: ```bash -service postgresql start -cargo run # this will configure and launch Plume on the server. +dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel +# TODO: GetText + Git install ``` -## If you want to run Plume with a remote DB this time ( Postgresql is not installed on the same server/container): +On **Gentoo**: -* On the DB server: +```bash +emerge --sync +emerge -av postgresql eselect-postgresql +# TODO: GetText + Git install +``` + +On **Mac OS X**, with [Homebrew](https://brew.sh/): + +```bash +brew update +brew install postgres +# TODO: GetText + Git install +``` + +## Creating a new user (optional) + +This step is recommended if you are in a **production environment**, but it is not necessary. + +```bash +adduser plume +su - plume +cd ~ +``` + +Creating a new user will let you use systemd to manage Plume if you want (see the dedicated section below). + +## Installing Rust and Cargo + +We said that Plume needed Rust and Cargo to work, but we didn't installed them at the same time as PostgreSQL and GetText, because there is an universal installation method called RustUp. + +You can install it on **GNU/Linux** and **Mac OS X** with: + +```bash +curl https://sh.rustup.rs -sSf | sh +``` + +On **Windows**, you'll need, if you don't already have them, to download and install the [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools). Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. + +## Getting and compiling the Plume source code + +Plume needs to be compiled from source. + +```bash +git clone https://github.com/Plume-org/Plume.git +cd Plume + +# This may take some time as RustUp will download all +# the required Rust components, and Cargo will download +# and compile all dependencies. +cargo build +``` + +We may provide precompiled packages and Docker images in the future (if you have experience in these fields and want to help, you're welcome). + +## Configuring PostgreSQL + +You can either run PostgreSQL from the machine that runs Plume, or from another server. We recommend you to use the first setup for development environments, or in production for small instances. + +In the first case, just run this command after the PostgreSQL installation, to start it: + +``` +service postgresql start +``` + +If you want to have two separate machines, run these commands on the database server after you installed the dependencies mentionned above on both servers: ```bash service postgresql start @@ -35,38 +103,80 @@ createuser -d -P plume createdb -O plume plume ``` -* On the Plume server: - ```bash -cd /home/plume/Plume -diesel migration run --database-url postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume -DB_URL=postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume cargo run # the first launch will ask questions to configure the instance. A second launch will not need the DB_URL. ``` -## Plume is now accessible as seen on your console. You can have fun now, or configure an nginx proxy with the following excerpt: +## Running migrations - location / { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $http_host; - - proxy_pass http://localhost:8000; - - client_max_body_size 16m; - } - -# Caveats: - -* Pgbouncer is not yet supported ( named transactions are used ). - -* Rust nightly is a moving target, dependancies can break and sometimes you need to check a few versions to find the one working. +Migrations are scripts to update the database. They are run by a tool called Diesel, which can be installed with: ```bash -cd /home/plume/Plume -rustup override set nightly-2018-05-15 # this could be needed for compilation. If errors, try 2018-05-31. -# rustup override unset # remove the override for this directory. +cargo install diesel_cli --no-default-features --features postgres --version '=1.2.0' ``` -* Rust nightly 2018-06-28 is known to be failing to compile diesel 1.3.2 +Plume should normally run migrations for you when needed, but if you want to run them manually, the command is: +```bash +diesel migration run --database-url postgres://USER:PASSWORD@IP:PORT/plume +``` + +This command may be useful if you decided to use a separate database server. + +## Starting Plume + +When you launch Plume for the first time, it will ask you a few questions to setup your instance before it actually launches. To start it, run these commands. + +``` +# Optional, only do it if the database URL is not +# postgres://plume:plume@localhost/plume +export DB_URL=postgres://plume:PASSWORD@DBSERVERIP:DBPORT/plume + +cargo run +``` + +## Configuring Nginx + +Here is a sample Nginx configuration for a Plume instance: + +```nginx +location / { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + + proxy_pass http://localhost:7878; + + client_max_body_size 16m; +} +``` + +## Systemd integration + +If you want to manage your Plume instance with systemd, you can use the following unit file (to be saved in `/lib/systemd/system/plume.service`): + +```toml +[Unit] +Description=plume + +[Service] +Type=simple +User=plume +WorkingDirectory=/home/plume/Plume +ExecStart=/home/dev/.cargo/bin/cargo run +TimeoutSec=30 +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +## Caveats: + +- Pgbouncer is not yet supported (named transactions are used). +- Rust nightly is a moving target, dependancies can break and sometimes you need to check a few versions to find the one working (run `rustup override set nightly-2018-05-15` or `rustup override set nightly-2018-05-31` in the Plume directory if you have issues during the compilation) +- Rust nightly 2018-06-28 is known to be failing to compile diesel 1.3.2 + +## Acknowledgements + +Most of this documentation have been written by *gled-rs*. The systemd unit file have been written by *nonbinaryanargeek*. Some parts (especially the instructions to install native dependencies) are from the [Aardwolf project](https://github.com/Aardwolf-Social/aardwolf). diff --git a/docs/PREREQUISITES.md b/docs/PREREQUISITES.md index a7007f8..7f2e811 100644 --- a/docs/PREREQUISITES.md +++ b/docs/PREREQUISITES.md @@ -5,7 +5,7 @@ As such, this notification should be updated once verified for Plume installs. > NOTE: These instructions may help in installing a production version, but are intended for developers to be able to build and test their changes. If in doubt, -seek out documentation from your distribution package or from [the `doc` folder](doc). +seek out documentation from your distribution package or from [the `docs` folder](docs). ## Installing Requirements From 577f63a7e8fe8af3bce7909100fa0991df7279d2 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 12:53:33 +0100 Subject: [PATCH 07/33] Remove legacy install docs --- docs/PREREQUISITES.md | 96 ------------------------------------------- 1 file changed, 96 deletions(-) delete mode 100644 docs/PREREQUISITES.md diff --git a/docs/PREREQUISITES.md b/docs/PREREQUISITES.md deleted file mode 100644 index 7f2e811..0000000 --- a/docs/PREREQUISITES.md +++ /dev/null @@ -1,96 +0,0 @@ -# Installing Software Prerequisites - -These instructions have been adapted from the Aardwolf documentation, and may not be accurate. -As such, this notification should be updated once verified for Plume installs. - -> NOTE: These instructions may help in installing a production version, but are -intended for developers to be able to build and test their changes. If in doubt, -seek out documentation from your distribution package or from [the `docs` folder](docs). - -## Installing Requirements - -### Installing PostgreSQL - -In order to run the Plume backend, you will need to have access to a -[PostgreSQL](https://www.postgresql.org/) database. There are a few options for doing this, but for -this guide we’re going to assume you are running the database on your -development machine. - -#### Linux/OSX Instructions - -If you're on an Ubuntu-like machine, you should be able to install -PostgreSQL like this: - - $ sudo apt-get update - $ sudo apt-get install postgresql postgresql-contrib - -If you see an error like: - - = note: /usr/bin/ld: cannot find -lpq - collect2: error: ld returned 1 exit statusb - -Then you may need to install the libpq (PostgreSQL C-library) package as well : - - $ sudo apt-get install libpq-dev - -If you're on OSX and using `brew`, do - - $ brew update - $ brew install postgres - -For Gentoo (eselect-postgresql is optional), - - # emerge --sync - # emerge -av postgresql eselect-postgresql - -For Fedora/CentOS/RHEL, do - - # dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel - - -#### Windows Instructions - -For Windows, just download the installer [here](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads#windows) and run it. After installing, make sure to add the /lib directory to your PATH system variable. - -### Installing rustup - -> Note: Rustup managed installations do appear to co-exist with system - installations on Gentoo, and should work on most other distributions. - If not, please file an issue with the Rust and Rustup teams or your distribution’s - managers. - -Next, you’ll need to have the [Rust](https://rust-lang.org/) toolchain -installed. The best way to do this is to install -[rustup](https://rustup.rs), which is a Rust toolchain manager. - -#### Linux/OSX Instructions - -Open your terminal and run the following command: - - $ curl https://sh.rustup.rs -sSf | sh - -For those who are (understandably) uncomfortable with piping a shell -script from the internet directly into `sh`, you can also -[use an alternate installation method](https://github.com/rust-lang-nursery/rustup.rs/#other-installation-methods). - -#### Windows Instructions - -If you don't already have them, download and install the [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools). - -Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. That's it! - -### Installing Rust Toolchain - -Once you have `rustup` installed, make sure you have the `nightly` rust -toolchain installed: - - $ rustup toolchain install nightly - -### Installing GetText - -GetText is the tool we use to manage translations. It will be needed at runtime, since we only compile -translation files when starting Plume. - -#### Ubuntu-like Linux - - $ sudo apt-get install gettext From 70ef4d6a74617b2720a09e49470c493125a14239 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 12:55:56 +0100 Subject: [PATCH 08/33] Add a ToC to documentation --- docs/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/README.md diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..557b157 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# Plume documentation + +- [Installing Plume (for development or production)](INSTALL.md) +- [Development Guide](DEVELOPMENT.md) +- [Making Plume available in your language](INTERNATIONALIZATION.md) From 30166d4008d97d1f366a4b4d2b9fdc36bba0a3af Mon Sep 17 00:00:00 2001 From: Baptiste Gelez Date: Sat, 1 Sep 2018 12:58:18 +0100 Subject: [PATCH 09/33] Set theme jekyll-theme-cayman --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..c419263 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file From 836897cdad7cfce52cf5dd83b929ff29a0261bea Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Sat, 1 Sep 2018 16:11:42 +0200 Subject: [PATCH 10/33] New mobile menu. --- .gitignore | 1 + static/images/boxicon-menu.svg | 1 + static/js/menu.js | 10 ++++ static/main.css | 96 ++++++++++++++++++++++++++++------ templates/base.html.tera | 39 ++++++++------ 5 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 static/images/boxicon-menu.svg create mode 100644 static/js/menu.js diff --git a/.gitignore b/.gitignore index 925d54c..33acb32 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ rls translations po/*.po~ .env +Rocket.toml diff --git a/static/images/boxicon-menu.svg b/static/images/boxicon-menu.svg new file mode 100644 index 0000000..0dd7a2b --- /dev/null +++ b/static/images/boxicon-menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/js/menu.js b/static/js/menu.js new file mode 100644 index 0000000..b40b565 --- /dev/null +++ b/static/js/menu.js @@ -0,0 +1,10 @@ +document.addEventListener("DOMContentLoaded", () => { + let content = document.getElementById("content"); + document.getElementById("menu").querySelector("a").addEventListener("click", () => { + content.classList.add("opened"); + }); + content.addEventListener("click", (e) => { + if (e.target === content) + content.classList.remove("opened"); + }); +}); \ No newline at end of file diff --git a/static/main.css b/static/main.css index 5f218a5..ebd7310 100644 --- a/static/main.css +++ b/static/main.css @@ -25,14 +25,31 @@ a, a:visited { */ header { + background: #ECECEC; +} +header #content { display: flex; align-content: center; justify-content: space-between; - background: #ECECEC; } -header #menu { +header nav#menu { + position: relative; display: none; + transform: skewX(-15deg); + left: -1em; + padding: 1em 1em 1em 2em; + background: #7765E3; + align-self: flex-start; +} +header nav#menu a { + transform: skewX(15deg); + width: 1.75em; + height: 1.75em; + margin: 0; + padding: 0; + background: url("/static/images/boxicon-menu.svg") no-repeat center; + background-size: contain; } header nav { @@ -483,31 +500,80 @@ form.new-post input[type="submit"] { * Small Screens * * ================= */ -@media screen and (max-width: 500px) { - header { - padding: 1em; +@media screen and (max-width: 900px) { + header { flex-direction: column; } - header #menu { - display: flex; + header nav#menu { + display: inline-flex; } - header > nav { + header #content { display: none; text-align: center; } - header nav a, header nav a.title { padding: 0.5em; } - header nav a.title { - width: 100vw; - margin: 0; - border: none; - font-size: 1.75em; + + @keyframes menuOpening { + from { + transform: scaleX(0); + transform-origin: left; + opacity: 0; + } + + to { + transform: scaleX(1); + transform-origin: left; + opacity: 1; + } } - header:focus-within > nav { + header #content.opened, header:focus-within #content { + position: fixed; display: flex; flex-direction: column; + justify-content: flex-start; + + top: 0; + left: 0; + width: 100%; + height: 100%; + box-sizing: border-box; + + animation: 0.2s menuOpening; + } + header #content.opened::before, header:focus-within #content::before { + content: ""; + position: absolute; + transform: skewX(-10deg); + top: 0; + left: -20%; + width: 100%; + height: 100%; + + z-index: -10; + + background: #7765E3; + } + header #content.opened > nav, header:focus-within #content > nav { + flex-direction: column; + align-items: flex-start; + } + header #content.opened > nav a, header:focus-within #content > nav a { + margin: 0; + padding: 1rem 1.5rem; + color: #F4F4F4; + font-size: 1.4em; + font-weight: 300; + } + header #content.opened > nav a.title, header:focus-within #content > nav a.title { + font-size: 1.8em; + } + header #content.opened > nav hr, header:focus-within #content > nav hr { + display: block; + margin: 0; + width: 100%; + border: solid #F4F4F4 0.1rem; } body > main > * { diff --git a/templates/base.html.tera b/templates/base.html.tera index 6d84311..6c8c3f6 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -6,27 +6,32 @@ +
- - -
{% block content %} From 82dc9ee1012348474d7cf471c191bee84dcbe43f Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Sat, 1 Sep 2018 16:34:44 +0200 Subject: [PATCH 11/33] Fixed tags that were showing on top of the menu. --- static/main.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/static/main.css b/static/main.css index a1c3d92..6b530eb 100644 --- a/static/main.css +++ b/static/main.css @@ -24,8 +24,7 @@ a, a:visited { small { margin-left: 1em; - color: #242424; - opacity: 0.6; + color: rgba(36, 36, 36, 0.6); font-size: 0.75em; word-wrap: break-word; word-break: break-all; @@ -462,6 +461,7 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } flex-direction: row; align-items: center; margin-bottom: 0; + z-index: -20; } .badge { margin-left: 1em; From cea548b8214ddfeb52efbcc68f75ef0f1a279ab7 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 16:28:47 +0100 Subject: [PATCH 12/33] Add a way to delete articles Fixes #116 --- plume-common/src/activity_pub/inbox.rs | 9 ++++--- plume-models/src/likes.rs | 33 +++++++++++------------- plume-models/src/posts.rs | 27 +++++++++++++++++--- plume-models/src/reshares.rs | 35 ++++++++++++-------------- po/plume.pot | 3 +++ src/inbox.rs | 11 +++++--- src/main.rs | 1 + src/routes/likes.rs | 2 +- src/routes/posts.rs | 27 +++++++++++++++++--- src/routes/reshares.rs | 2 +- src/setup.rs | 2 +- templates/posts/details.html.tera | 4 +++ 12 files changed, 103 insertions(+), 53 deletions(-) diff --git a/plume-common/src/activity_pub/inbox.rs b/plume-common/src/activity_pub/inbox.rs index 6ce93c1..ffbdbe6 100644 --- a/plume-common/src/activity_pub/inbox.rs +++ b/plume-common/src/activity_pub/inbox.rs @@ -1,4 +1,4 @@ -use activitypub::{Object, activity::Create}; +use activitypub::{Object, activity::{Create, Delete}}; use activity_pub::Id; @@ -29,9 +29,10 @@ pub trait Notify { fn notify(&self, conn: &C); } -pub trait Deletable { - /// true if success - fn delete_activity(conn: &C, id: Id) -> bool; +pub trait Deletable { + fn delete(&self, conn: &C) -> A; + fn delete_id(id: String, conn: &C); + } pub trait WithInbox { diff --git a/plume-models/src/likes.rs b/plume-models/src/likes.rs index 651b4d8..f0a3973 100644 --- a/plume-models/src/likes.rs +++ b/plume-models/src/likes.rs @@ -48,19 +48,6 @@ impl Like { } } - pub fn delete(&self, conn: &PgConnection) -> activity::Undo { - diesel::delete(self).execute(conn).unwrap(); - - let mut act = activity::Undo::default(); - act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::delete: actor error"); - act.undo_props.set_object_object(self.into_activity(conn)).expect("Like::delete: object error"); - act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Like::delete: id error"); - act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Like::delete: to error"); - act.object_props.set_cc_link_vec::(vec![]).expect("Like::delete: cc error"); - - act - } - pub fn into_activity(&self, conn: &PgConnection) -> activity::Like { let mut act = activity::Like::default(); act.like_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::into_activity: actor error"); @@ -100,13 +87,23 @@ impl Notify for Like { } } -impl Deletable for Like { - fn delete_activity(conn: &PgConnection, id: Id) -> bool { +impl Deletable for Like { + fn delete(&self, conn: &PgConnection) -> activity::Undo { + diesel::delete(self).execute(conn).unwrap(); + + let mut act = activity::Undo::default(); + act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).expect("Like::delete: actor error"); + act.undo_props.set_object_object(self.into_activity(conn)).expect("Like::delete: object error"); + act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Like::delete: id error"); + act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Like::delete: to error"); + act.object_props.set_cc_link_vec::(vec![]).expect("Like::delete: cc error"); + + act + } + + fn delete_id(id: String, conn: &PgConnection) { if let Some(like) = Like::find_by_ap_url(conn, id.into()) { like.delete(conn); - true - } else { - false } } } diff --git a/plume-models/src/posts.rs b/plume-models/src/posts.rs index 7ed756f..5b67a66 100644 --- a/plume-models/src/posts.rs +++ b/plume-models/src/posts.rs @@ -1,7 +1,7 @@ use activitypub::{ - activity::Create, + activity::{Create, Delete}, link, - object::Article + object::{Article, Tombstone} }; use chrono::{NaiveDateTime, TimeZone, Utc}; use diesel::{self, PgConnection, RunQueryDsl, QueryDsl, ExpressionMethods, BelongingToDsl, dsl::any}; @@ -10,7 +10,7 @@ use serde_json; use plume_common::activity_pub::{ PUBLIC_VISIBILTY, Id, IntoId, - inbox::FromActivity + inbox::{Deletable, FromActivity} }; use {BASE_URL, ap_url}; use blogs::Blog; @@ -273,6 +273,27 @@ impl FromActivity for Post { } } +impl Deletable for Post { + fn delete(&self, conn: &PgConnection) -> Delete { + let mut act = Delete::default(); + act.delete_props.set_actor_link(self.get_authors(conn)[0].clone().into_id()).expect("Post::delete: actor error"); + + let mut tombstone = Tombstone::default(); + tombstone.object_props.set_id_string(self.ap_url.clone()).expect("Post::delete: object.id error"); + act.delete_props.set_object_object(tombstone).expect("Post::delete: object error"); + + act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Post::delete: id error"); + act.object_props.set_to_link_vec(vec![Id::new(PUBLIC_VISIBILTY)]).expect("Post::delete: to error"); + + diesel::delete(self).execute(conn).expect("Post::delete: DB error"); + act + } + + fn delete_id(id: String, conn: &PgConnection) { + Post::find_by_ap_url(conn, id).map(|p| p.delete(conn)); + } +} + impl IntoId for Post { fn into_id(self) -> Id { Id::new(self.ap_url.clone()) diff --git a/plume-models/src/reshares.rs b/plume-models/src/reshares.rs index 2acb0a4..4fd1a63 100644 --- a/plume-models/src/reshares.rs +++ b/plume-models/src/reshares.rs @@ -59,19 +59,6 @@ impl Reshare { User::get(conn, self.user_id) } - pub fn delete(&self, conn: &PgConnection) -> Undo { - diesel::delete(self).execute(conn).unwrap(); - - let mut act = Undo::default(); - act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); - act.undo_props.set_object_object(self.into_activity(conn)).unwrap(); - act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Reshare::delete: id error"); - act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Reshare::delete: to error"); - act.object_props.set_cc_link_vec::(vec![]).expect("Reshare::delete: cc error"); - - act - } - pub fn into_activity(&self, conn: &PgConnection) -> Announce { let mut act = Announce::default(); act.announce_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); @@ -111,13 +98,23 @@ impl Notify for Reshare { } } -impl Deletable for Reshare { - fn delete_activity(conn: &PgConnection, id: Id) -> bool { - if let Some(reshare) = Reshare::find_by_ap_url(conn, id.into()) { +impl Deletable for Reshare { + fn delete(&self, conn: &PgConnection) -> Undo { + diesel::delete(self).execute(conn).unwrap(); + + let mut act = Undo::default(); + act.undo_props.set_actor_link(User::get(conn, self.user_id).unwrap().into_id()).unwrap(); + act.undo_props.set_object_object(self.into_activity(conn)).unwrap(); + act.object_props.set_id_string(format!("{}#delete", self.ap_url)).expect("Reshare::delete: id error"); + act.object_props.set_to_link(Id::new(PUBLIC_VISIBILTY.to_string())).expect("Reshare::delete: to error"); + act.object_props.set_cc_link_vec::(vec![]).expect("Reshare::delete: cc error"); + + act + } + + fn delete_id(id: String, conn: &PgConnection) { + if let Some(reshare) = Reshare::find_by_ap_url(conn, id) { reshare.delete(conn); - true - } else { - false } } } diff --git a/po/plume.pot b/po/plume.pot index 51dc694..aeff569 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -420,3 +420,6 @@ msgstr "" msgid "Read the detailed rules" msgstr "" + +msgid "Delete this article" +msgstr "" diff --git a/src/inbox.rs b/src/inbox.rs index d5b2dce..5a4d0bb 100644 --- a/src/inbox.rs +++ b/src/inbox.rs @@ -1,4 +1,4 @@ -use activitypub::activity::{Announce, Create, Like, Undo}; +use activitypub::{activity::{Announce, Create, Delete, Like, Undo}, object::Tombstone}; use diesel::PgConnection; use failure::Error; use serde_json; @@ -32,6 +32,11 @@ pub trait Inbox { Err(InboxError::InvalidType)? } }, + "Delete" => { + let act: Delete = serde_json::from_value(act.clone())?; + Post::delete_id(act.delete_props.object_object::()?.object_props.id_string()?, conn); + Ok(()) + }, "Follow" => { Follow::from_activity(conn, serde_json::from_value(act.clone())?, actor_id); Ok(()) @@ -44,11 +49,11 @@ pub trait Inbox { let act: Undo = serde_json::from_value(act.clone())?; match act.undo_props.object["type"].as_str().unwrap() { "Like" => { - likes::Like::delete_activity(conn, Id::new(act.undo_props.object_object::()?.object_props.id_string()?)); + likes::Like::delete_id(act.undo_props.object_object::()?.object_props.id_string()?, conn); Ok(()) }, "Announce" => { - Reshare::delete_activity(conn, Id::new(act.undo_props.object_object::()?.object_props.id_string()?)); + Reshare::delete_id(act.undo_props.object_object::()?.object_props.id_string()?, conn); Ok(()) } _ => Err(InboxError::CantUndo)? diff --git a/src/main.rs b/src/main.rs index 2e0c76f..1b7acb2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -68,6 +68,7 @@ fn main() { routes::posts::new, routes::posts::new_auth, routes::posts::create, + routes::posts::delete, routes::reshares::create, routes::reshares::create_auth, diff --git a/src/routes/likes.rs b/src/routes/likes.rs index a3a2dd3..8e68ff4 100644 --- a/src/routes/likes.rs +++ b/src/routes/likes.rs @@ -1,7 +1,7 @@ use rocket::{State, response::{Redirect, Flash}}; use workerpool::{Pool, thunk::*}; -use plume_common::activity_pub::{broadcast, inbox::Notify}; +use plume_common::activity_pub::{broadcast, inbox::{Notify, Deletable}}; use plume_common::utils; use plume_models::{ blogs::Blog, diff --git a/src/routes/posts.rs b/src/routes/posts.rs index 1fd4f4f..63d5620 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -8,7 +8,7 @@ use std::{collections::HashMap, borrow::Cow}; use validator::{Validate, ValidationError, ValidationErrors}; use workerpool::{Pool, thunk::*}; -use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest}; +use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest, inbox::Deletable}; use plume_common::utils; use plume_models::{ blogs::*, @@ -53,10 +53,11 @@ fn details_response(blog: String, slug: String, conn: DbConn, user: Option "has_liked": user.clone().map(|u| u.has_liked(&*conn, &post)).unwrap_or(false), "n_reshares": post.get_reshares(&*conn).len(), "has_reshared": user.clone().map(|u| u.has_reshared(&*conn, &post)).unwrap_or(false), - "account": user, + "account": &user, "date": &post.creation_date.timestamp(), "previous": query.and_then(|q| q.responding_to.map(|r| Comment::get(&*conn, r).expect("Error retrieving previous comment").to_json(&*conn, &vec![]))), - "user_fqn": user.map(|u| u.get_fqn(&*conn)).unwrap_or(String::new()) + "user_fqn": user.clone().map(|u| u.get_fqn(&*conn)).unwrap_or(String::new()), + "is_author": user.map(|u| post.get_authors(&*conn).into_iter().any(|a| u.id == a.id)).unwrap_or(false) })) }) }) @@ -176,3 +177,23 @@ fn create(blog_name: String, data: LenientForm, user: User, conn: D }))) } } + +#[post("/~///delete")] +fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker: State>>) -> Redirect { + let post = Blog::find_by_fqn(&*conn, blog_name.clone()) + .and_then(|blog| Post::find_by_slug(&*conn, slug.clone(), blog.id)); + + if let Some(post) = post { + if !post.get_authors(&*conn).into_iter().any(|a| a.id == user.id) { + Redirect::to(uri!(details: blog = blog_name.clone(), slug = slug.clone())) + } else { + let audience = user.get_followers(&*conn); + let delete_activity = post.delete(&*conn); + worker.execute(Thunk::of(move || broadcast(&user, delete_activity, audience))); + + Redirect::to(uri!(super::blogs::details: name = blog_name)) + } + } else { + Redirect::to(uri!(super::blogs::details: name = blog_name)) + } +} diff --git a/src/routes/reshares.rs b/src/routes/reshares.rs index 1ba673a..f57efc4 100644 --- a/src/routes/reshares.rs +++ b/src/routes/reshares.rs @@ -1,7 +1,7 @@ use rocket::{State, response::{Redirect, Flash}}; use workerpool::{Pool, thunk::*}; -use plume_common::activity_pub::{broadcast, inbox::Notify}; +use plume_common::activity_pub::{broadcast, inbox::{Deletable, Notify}}; use plume_common::utils; use plume_models::{ blogs::Blog, diff --git a/src/setup.rs b/src/setup.rs index 8efd038..9239196 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -215,7 +215,7 @@ fn create_admin(instance: Instance, conn: DbConn) { fn check_native_deps() { let mut not_found = Vec::new(); if !try_run("psql") { - not_found.push(("PostgreSQL", "sudo apt install postgres")); + not_found.push(("PostgreSQL", "sudo apt install postgresql")); } if !try_run("gettext") { not_found.push(("GetText", "sudo apt install gettext")) diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index c20fa49..f17ad56 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -22,6 +22,10 @@ }} — {{ date | date(format="%B %e, %Y") }} + — + {% if is_author %} + {{ "Delete this article" | _ }} + {% endif %}

{{ article.post.content | safe }} From 6f29c109689d659d093a8d67dc7de870589edc6b Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 16:34:49 +0100 Subject: [PATCH 13/33] Docs: updating your instance --- docs/README.md | 1 + docs/UPDATE.md | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 docs/UPDATE.md diff --git a/docs/README.md b/docs/README.md index 557b157..2133ad7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,6 @@ # Plume documentation - [Installing Plume (for development or production)](INSTALL.md) +- [Updating your instance](UPDATE.md) - [Development Guide](DEVELOPMENT.md) - [Making Plume available in your language](INTERNATIONALIZATION.md) diff --git a/docs/UPDATE.md b/docs/UPDATE.md new file mode 100644 index 0000000..4e851e6 --- /dev/null +++ b/docs/UPDATE.md @@ -0,0 +1,15 @@ +# Updating your instance + +To update your instance, run these commands with `plume` user if you created it, or with your default user, in the Plume directory. + +``` +git pull origin master + +# If you are not using systemd +cargo run + +# If you are using systemd +service plume restart +``` + +That's it! From b66e8942a97de208c8e979bad27416bdd4cb69a7 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 16:46:23 +0100 Subject: [PATCH 14/33] Fix the deletion route --- src/routes/posts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/posts.rs b/src/routes/posts.rs index 63d5620..f047ec3 100644 --- a/src/routes/posts.rs +++ b/src/routes/posts.rs @@ -178,7 +178,7 @@ fn create(blog_name: String, data: LenientForm, user: User, conn: D } } -#[post("/~///delete")] +#[get("/~///delete")] fn delete(blog_name: String, slug: String, conn: DbConn, user: User, worker: State>>) -> Redirect { let post = Blog::find_by_fqn(&*conn, blog_name.clone()) .and_then(|blog| Post::find_by_slug(&*conn, slug.clone(), blog.id)); From 092ad5b79597f5f36a43eec76eda847e23a2fba1 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 17:39:40 +0100 Subject: [PATCH 15/33] Instance about page Fixes #39 --- plume-models/src/instance.rs | 12 +++++++++ po/de.po | 18 ++++++++++++++ po/en.po | 15 +++++++++++ po/fr.po | 29 +++++++++++++++++++--- po/gl.po | 33 ++++++++++++++++++++---- po/nb.po | 18 ++++++++++++++ po/pl.po | 18 ++++++++++++++ po/plume.pot | 12 +++++++++ src/main.rs | 1 + src/routes/instance.rs | 13 ++++++++++ static/main.css | 7 ++++++ templates/instance/about.html.tera | 40 ++++++++++++++++++++++++++++++ 12 files changed, 207 insertions(+), 9 deletions(-) create mode 100644 templates/instance/about.html.tera diff --git a/plume-models/src/instance.rs b/plume-models/src/instance.rs index 5cb2a3f..d0d553e 100644 --- a/plume-models/src/instance.rs +++ b/plume-models/src/instance.rs @@ -72,6 +72,14 @@ impl Instance { .len() > 0 } + pub fn main_admin(&self, conn: &PgConnection) -> User { + users::table.filter(users::instance_id.eq(self.id)) + .filter(users::is_admin.eq(true)) + .limit(1) + .get_result::(conn) + .expect("Couldn't load admins") + } + pub fn compute_box(&self, prefix: &'static str, name: String, box_name: &'static str) -> String { ap_url(format!( "{instance}/{prefix}/{name}/{box_name}", @@ -96,4 +104,8 @@ impl Instance { )).get_result::(conn) .expect("Couldn't update instance") } + + pub fn count(conn: &PgConnection) -> i64 { + instances::table.count().get_result(conn).expect("Couldn't count instances") + } } diff --git a/po/de.po b/po/de.po index 9b4b2ec..950ef74 100644 --- a/po/de.po +++ b/po/de.po @@ -438,5 +438,23 @@ msgstr "Artikel geschrieben haben" msgid "Read the detailed rules" msgstr "Lies die detailierten Regeln" +#, fuzzy +msgid "Delete this article" +msgstr "Neueste Artikel" + +msgid "And connected to" +msgstr "" + +#, fuzzy +msgid "other instances" +msgstr "Über diese Instanz" + +#, fuzzy +msgid "Administred by" +msgstr "Administration" + +msgid "Runs Plume {{ version }}" +msgstr "" + #~ msgid "Your password should be at least 8 characters long" #~ msgstr "Das Passwort sollte mindestens 8 Zeichen lang sein" diff --git a/po/en.po b/po/en.po index d365eb0..5403fc1 100644 --- a/po/en.po +++ b/po/en.po @@ -430,3 +430,18 @@ msgstr "" msgid "Read the detailed rules" msgstr "" + +msgid "Delete this article" +msgstr "" + +msgid "And connected to" +msgstr "" + +msgid "other instances" +msgstr "" + +msgid "Administred by" +msgstr "" + +msgid "Runs Plume {{ version }}" +msgstr "" diff --git a/po/fr.po b/po/fr.po index 7d7c5d7..043b53c 100644 --- a/po/fr.po +++ b/po/fr.po @@ -256,7 +256,8 @@ msgid "You need to be logged in order to edit your profile" msgstr "Vous devez vous connecter pour modifier votre profil" msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" -msgstr "Par {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" +msgstr "" +"Par {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" msgid "{{ data }} reshared your article" msgstr "{{ data }} a repartagé votre article" @@ -407,14 +408,16 @@ msgid "Plume is a decentralized blogging engine." msgstr "Plume est un moteur de blog décentralisé." msgid "Authors can manage various blogs from an unique website." -msgstr "Les auteur⋅ice⋅s peuvent gérer différents blogs au sein d'un même site." +msgstr "" +"Les auteur⋅ice⋅s peuvent gérer différents blogs au sein d'un même site." msgid "" "Articles are also visible on other Plume websites, and you can interact with " "them directly from other platforms like Mastodon." msgstr "" -"Les articles sont également visibles sur d'autres sites Plume, et vous pouvez " -"interagir avec directement depuis d'autres plateformes telles que Mastodon." +"Les articles sont également visibles sur d'autres sites Plume, et vous " +"pouvez interagir avec directement depuis d'autres plateformes telles que " +"Mastodon." msgid "Create your account" msgstr "Créer votre compte" @@ -437,5 +440,23 @@ msgstr "articles" msgid "Read the detailed rules" msgstr "Lire les règles détaillées" +#, fuzzy +msgid "Delete this article" +msgstr "Derniers articles" + +msgid "And connected to" +msgstr "" + +#, fuzzy +msgid "other instances" +msgstr "À propos de cette instance" + +#, fuzzy +msgid "Administred by" +msgstr "Administration" + +msgid "Runs Plume {{ version }}" +msgstr "" + #~ msgid "Your password should be at least 8 characters long" #~ msgstr "Votre mot de passe doit faire au moins 8 caractères." diff --git a/po/gl.po b/po/gl.po index d27b2f6..3b1247b 100644 --- a/po/gl.po +++ b/po/gl.po @@ -68,7 +68,8 @@ msgstr "Notificacións" msgid "" "Written by {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" -msgstr "Escrito por {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" +msgstr "" +"Escrito por {{ link_1 }}{{ url }}{{ link_2 }}{{ name | escape }}{{ link_3 }}" msgid "This article is under the {{ license }} license." msgstr "Este artigo ten licenza {{ license }}" @@ -251,7 +252,8 @@ msgid "You need to be logged in order to edit your profile" msgstr "Debe estar conectada para editar o seu perfil" msgid "By {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" -msgstr "Por {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" +msgstr "" +"Por {{ link_1 }}{{ link_2 }}{{ link_3 }}{{ name | escape }}{{ link_4 }}" msgid "{{ data }} reshared your article" msgstr "{{ data }} comparteu o seu artigo" @@ -322,7 +324,9 @@ msgstr[0] "Unha autora en este blog: " msgstr[1] "{{ count }} autoras en este blog: " msgid "Login or use your Fediverse account to interact with this article" -msgstr "Conéctese ou utilice a súa conta no fediverso para interactuar con este artigo" +msgstr "" +"Conéctese ou utilice a súa conta no fediverso para interactuar con este " +"artigo" msgid "Optional" msgstr "Opcional" @@ -401,8 +405,9 @@ msgstr "As autoras poden xestionar varios blogs desde un único sitio web." msgid "" "Articles are also visible on other Plume websites, and you can interact with " "them directly from other platforms like Mastodon." -msgstr "Os artigos son visibles tamén en outros sitios Plume, e pode interactuar con" -"eles desde outras plataformas como Mastadon." +msgstr "" +"Os artigos son visibles tamén en outros sitios Plume, e pode interactuar " +"coneles desde outras plataformas como Mastadon." msgid "Create your account" msgstr "Cree a súa conta" @@ -424,3 +429,21 @@ msgstr "artigos" msgid "Read the detailed rules" msgstr "Lea o detalle das normas" + +#, fuzzy +msgid "Delete this article" +msgstr "Últimos artigos" + +msgid "And connected to" +msgstr "" + +#, fuzzy +msgid "other instances" +msgstr "Sobre esta instancia" + +#, fuzzy +msgid "Administred by" +msgstr "Administración" + +msgid "Runs Plume {{ version }}" +msgstr "" diff --git a/po/nb.po b/po/nb.po index c7d7b1c..6482079 100644 --- a/po/nb.po +++ b/po/nb.po @@ -433,5 +433,23 @@ msgstr "artikler" msgid "Read the detailed rules" msgstr "Les reglene" +#, fuzzy +msgid "Delete this article" +msgstr "Siste artikler" + +msgid "And connected to" +msgstr "" + +#, fuzzy +msgid "other instances" +msgstr "Om denne instansen" + +#, fuzzy +msgid "Administred by" +msgstr "Administrasjon" + +msgid "Runs Plume {{ version }}" +msgstr "" + #~ msgid "Your password should be at least 8 characters long" #~ msgstr "Passordet ditt må bestå av minst åtte tegn" diff --git a/po/pl.po b/po/pl.po index 3d0367f..30ba204 100644 --- a/po/pl.po +++ b/po/pl.po @@ -444,6 +444,24 @@ msgstr "artykuły" msgid "Read the detailed rules" msgstr "Przeczytaj szczegółowe zasady" +#, fuzzy +msgid "Delete this article" +msgstr "Najnowsze artykuły" + +msgid "And connected to" +msgstr "" + +#, fuzzy +msgid "other instances" +msgstr "O tej instancji" + +#, fuzzy +msgid "Administred by" +msgstr "Administracja" + +msgid "Runs Plume {{ version }}" +msgstr "" + #~ msgid "Your password should be at least 8 characters long" #~ msgstr "Twoje hasło musi składać się przynajmniej z 8 znaków" diff --git a/po/plume.pot b/po/plume.pot index aeff569..3780c29 100644 --- a/po/plume.pot +++ b/po/plume.pot @@ -423,3 +423,15 @@ msgstr "" msgid "Delete this article" msgstr "" + +msgid "And connected to" +msgstr "" + +msgid "other instances" +msgstr "" + +msgid "Administred by" +msgstr "" + +msgid "Runs Plume {{ version }}" +msgstr "" diff --git a/src/main.rs b/src/main.rs index 1b7acb2..e93429e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,6 +54,7 @@ fn main() { routes::instance::update_settings, routes::instance::shared_inbox, routes::instance::nodeinfo, + routes::instance::about, routes::likes::create, routes::likes::create_auth, diff --git a/src/routes/instance.rs b/src/routes/instance.rs index cf8ec98..b4f395f 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -123,3 +123,16 @@ fn nodeinfo(conn: DbConn) -> Json { "metadata": {} })) } + +#[get("/about")] +fn about(user: User, conn: DbConn) -> Template { + Template::render("instance/about", json!({ + "account": user, + "instance": Instance::get_local(&*conn), + "admin": Instance::get_local(&*conn).map(|i| i.main_admin(&*conn).to_json(&*conn)), + "version": "0.1.0", + "n_users": User::count_local(&*conn), + "n_articles": Post::count_local(&*conn), + "n_instances": Instance::count(&*conn) - 1 + })) +} diff --git a/static/main.css b/static/main.css index d2c05ba..a53268b 100644 --- a/static/main.css +++ b/static/main.css @@ -42,6 +42,13 @@ small { margin: 4rem 0; } +.banner { + background: #DADADA; + padding-top: 2em; + padding-bottom: 1em; + margin: 3em 0px; +} + /* * == Header == */ diff --git a/templates/instance/about.html.tera b/templates/instance/about.html.tera new file mode 100644 index 0000000..69a70e3 --- /dev/null +++ b/templates/instance/about.html.tera @@ -0,0 +1,40 @@ +{% extends "base" %} +{% import "macros" as macros %} + +{% block title %} +About {{ instance.name }} +{% endblock title %} + +{% block content %} +

{{ "About {{ instance_name }}" | _(instance_name=instance.name) }}

+
+ {{ instance.short_description_html | safe }} +
+ +
+ {{ instance.long_description_html | safe }} +
+{% endblock content %} From 06127a9f4887bd450c5af676061b649b9350c852 Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Sat, 1 Sep 2018 19:14:15 +0200 Subject: [PATCH 16/33] Removed JS. --- static/js/menu.js | 10 ---------- static/main.css | 12 ++++++------ templates/base.html.tera | 1 - 3 files changed, 6 insertions(+), 17 deletions(-) delete mode 100644 static/js/menu.js diff --git a/static/js/menu.js b/static/js/menu.js deleted file mode 100644 index b40b565..0000000 --- a/static/js/menu.js +++ /dev/null @@ -1,10 +0,0 @@ -document.addEventListener("DOMContentLoaded", () => { - let content = document.getElementById("content"); - document.getElementById("menu").querySelector("a").addEventListener("click", () => { - content.classList.add("opened"); - }); - content.addEventListener("click", (e) => { - if (e.target === content) - content.classList.remove("opened"); - }); -}); \ No newline at end of file diff --git a/static/main.css b/static/main.css index 6b530eb..f488461 100644 --- a/static/main.css +++ b/static/main.css @@ -593,7 +593,7 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } } } - header #content.opened, header:focus-within #content { + header:focus-within #content { position: fixed; display: flex; flex-direction: column; @@ -607,7 +607,7 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } animation: 0.2s menuOpening; } - header #content.opened::before, header:focus-within #content::before { + header:focus-within #content::before { content: ""; position: absolute; transform: skewX(-10deg); @@ -620,21 +620,21 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } background: #7765E3; } - header #content.opened > nav, header:focus-within #content > nav { + header:focus-within #content > nav { flex-direction: column; align-items: flex-start; } - header #content.opened > nav a, header:focus-within #content > nav a { + header:focus-within #content > nav a { margin: 0; padding: 1rem 1.5rem; color: #F4F4F4; font-size: 1.4em; font-weight: 300; } - header #content.opened > nav a.title, header:focus-within #content > nav a.title { + header:focus-within #content > nav a.title { font-size: 1.8em; } - header #content.opened > nav hr, header:focus-within #content > nav hr { + header:focus-within #content > nav hr { display: block; margin: 0; width: 100%; diff --git a/templates/base.html.tera b/templates/base.html.tera index 1bbdd41..d54b885 100644 --- a/templates/base.html.tera +++ b/templates/base.html.tera @@ -6,7 +6,6 @@ -
From 98ce619b790bc26fb4bd259881433d8b7d8e752a Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 18:18:58 +0100 Subject: [PATCH 17/33] Docs: fix systemd unit file --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 413a85c..fefab4d 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -163,7 +163,7 @@ Description=plume Type=simple User=plume WorkingDirectory=/home/plume/Plume -ExecStart=/home/dev/.cargo/bin/cargo run +ExecStart=/home/plume/.cargo/bin/cargo run TimeoutSec=30 Restart=always From 163484eff8a85130b8a9dcde67562bd9046fca8d Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 18:24:35 +0100 Subject: [PATCH 18/33] Docs: update Nginx conf and add Apache conf --- docs/INSTALL.md | 107 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index fefab4d..117b2ce 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -136,19 +136,106 @@ cargo run ## Configuring Nginx -Here is a sample Nginx configuration for a Plume instance: +Here is a sample Nginx configuration for a Plume instance (replace `blog.example.com` with your domain name): ```nginx -location / { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $http_host; +server { + listen 80; + server_name blog.example.com; - proxy_pass http://localhost:7878; - - client_max_body_size 16m; + location /.well-known/acme-challenge {} + location / { + return 301 https://$host$request_uri; + } } + +server { + server_name blog.example.org; + access_log /var/log/nginx/access.log; + + listen [::]:443 ssl; # managed by Certbot + SSLCertificateFile /etc/letsencrypt/live/blog.example.com/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/blog.example.com/privkey.pem + SSLCertificateChainFile /etc/letsencrypt/live/blog.example.com/chain.pem + + # for ssl conf: https://cipherli.st/ + ssl_protocols TLSv1.2 TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2 + ssl_prefer_server_ciphers on; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;# openssl dhparam -out /etc/letsencrypt/ssl-dhparam.pem 4096 + ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; + ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 + ssl_session_timeout 10m; + ssl_session_cache shared:SSL:10m; + ssl_session_tickets off; # Requires nginx >= 1.5.9 + ssl_stapling on; # Requires nginx >= 1.3.7 + ssl_stapling_verify on; # Requires nginx => 1.3.7 + resolver 9.9.9.9 80.67.169.12 valid=300s; + resolver_timeout 5s; + add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + add_header Content-Security-Policy "default-src 'self';"; + add_header Content-Security-Policy "frame-ancestors 'self'"; + + location ~* \.(jpg|jpeg|png|gif|ico|js|pdf)$ { + add_header Cache-Control "public"; + expires 7d; + } + + location / { + proxy_pass http://localhost:8000/; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + client_max_body_size 10m; + } +} +``` + +## Configuring Apache + +If you prefer Apache, you can use this configuration (here too replace `blog.example.com` with your domain): + +```apache + + ServerName blog.example.com + Redirect / https://blog.example.com/ + + + + ServerAdmin admin@example.com + ServerName blog.example.com + + Header always set Referrer-Policy "strict-origin-when-cross-origin" + Header always set Strict-Transport-Security "max-age=31536000" + SSLEngine on + + # for cipher conf: https://cipherli.st/ + SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH + SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 + SSLHonorCipherOrder On + Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" + Header always set X-Frame-Options DENY + Header always set X-Content-Type-Options nosniff + SSLCompression off + SSLUseStapling on + SSLStaplingCache "shmcb:logs/stapling-cache(150000)" + + # Requires Apache >= 2.4.11 + SSLSessionTickets Off + + SSLCertificateFile /etc/letsencrypt/live/blog.example.com/cert.pem + SSLCertificateKeyFile /etc/letsencrypt/live/blog.example.com/privkey.pem + SSLCertificateChainFile /etc/letsencrypt/live/blog.example.com/chain.pem + + ProxyPreserveHost On + RequestHeader set X-Forwarded-Proto "https" + + ProxyPass / http://127.0.0.1:7878/ + ProxyPassReverse / http://127.0.0.1:7878/ + ``` ## Systemd integration @@ -179,4 +266,4 @@ WantedBy=multi-user.target ## Acknowledgements -Most of this documentation have been written by *gled-rs*. The systemd unit file have been written by *nonbinaryanargeek*. Some parts (especially the instructions to install native dependencies) are from the [Aardwolf project](https://github.com/Aardwolf-Social/aardwolf). +Most of this documentation have been written by *gled-rs*. The systemd unit file, Nginx and Apache configurations have been written by *nonbinaryanargeek*. Some parts (especially the instructions to install native dependencies) are from the [Aardwolf project](https://github.com/Aardwolf-Social/aardwolf). From 1b096ba6e1464bbb31cef3cde9f1e1462d362619 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 18:32:31 +0100 Subject: [PATCH 19/33] Docs: update VS C++ link --- docs/INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 117b2ce..bae31b9 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -66,7 +66,7 @@ You can install it on **GNU/Linux** and **Mac OS X** with: curl https://sh.rustup.rs -sSf | sh ``` -On **Windows**, you'll need, if you don't already have them, to download and install the [Visual C++ 2015 Build Tools](http://landinghub.visualstudio.com/visual-cpp-build-tools). Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. +On **Windows**, you'll need, if you don't already have them, to download and install the [Visual C++ 2015 Build Tools](https://www.microsoft.com/en-us/download/details.aspx?id=48159). Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. ## Getting and compiling the Plume source code From 97c0b533abe29043ab9bc0e886651d7992a72e86 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 21:08:26 +0100 Subject: [PATCH 20/33] Add Atom feeds for blogs and users --- Cargo.lock | 44 ++++++++++++++++++++++++++ Cargo.toml | 1 + plume-common/src/activity_pub/inbox.rs | 2 +- plume-models/src/comments.rs | 2 +- src/main.rs | 3 ++ src/routes/blogs.rs | 19 ++++++++++- src/routes/mod.rs | 23 ++++++++++++++ src/routes/user.rs | 19 ++++++++++- 8 files changed, 109 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9b58dc7..409af0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,16 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "atom_syndication" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "backtrace" version = "0.3.6" @@ -332,6 +342,25 @@ dependencies = [ "syntex_fmt_macros 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_builder" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "derive_builder_core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "diesel" version = "1.2.2" @@ -985,6 +1014,7 @@ name = "plume" version = "0.1.0" dependencies = [ "activitypub 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1100,6 +1130,16 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-xml" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quote" version = "0.3.15" @@ -2074,6 +2114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9a7ab83635ff7a3b04856f4ad95324dccc9b947ab1e790fc5c769ee6d6f60c" "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" @@ -2103,6 +2144,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csrf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38f2ee2a7e76740d81de006e61eff53206c56448a30d8017b4ac97b5486682bd" "checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e" "checksum derive-error-chain 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4450afbe280461e78299b39182a085b70e3e71be049cf4a588ad72f1e44d33" +"checksum derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c998e6ab02a828dd9735c18f154e14100e674ed08cb4e1938f0e4177543f439" +"checksum derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "735e24ee9e5fa8e16b86da5007856e97d592e11867e45d76e0c0d0a164a0b757" "checksum diesel 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24815a0c2094f2c8dafe74ab3b9e975892f44acbb94b4d4b4898025a7615efa4" "checksum diesel_derives 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6471a2b637b414d3ee1504cf230409a550381c79204282f8fe06c527e4ae56be" "checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc" @@ -2186,6 +2229,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" +"checksum quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14c27e04216596a49f2b82398a24f67ed9f131a5c0e0235496ea446bdacfb12" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" diff --git a/Cargo.toml b/Cargo.toml index f76918f..b566705 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ name = "plume" version = "0.1.0" [dependencies] activitypub = "0.1.1" +atom_syndication = "0.6" colored = "1.6" dotenv = "*" failure = "0.1" diff --git a/plume-common/src/activity_pub/inbox.rs b/plume-common/src/activity_pub/inbox.rs index ffbdbe6..4a302a1 100644 --- a/plume-common/src/activity_pub/inbox.rs +++ b/plume-common/src/activity_pub/inbox.rs @@ -1,4 +1,4 @@ -use activitypub::{Object, activity::{Create, Delete}}; +use activitypub::{Object, activity::Create}; use activity_pub::Id; diff --git a/plume-models/src/comments.rs b/plume-models/src/comments.rs index 39926d5..b7511d8 100644 --- a/plume-models/src/comments.rs +++ b/plume-models/src/comments.rs @@ -105,7 +105,7 @@ impl FromActivity for Comment { sensitive: false // "sensitive" is not a standard property, we need to think about how to support it with the activitypub crate }); - // save mentions + // save mentionsd if let Some(serde_json::Value::Array(tags)) = note.object_props.tag.clone() { for tag in tags.into_iter() { serde_json::from_value::(tag) diff --git a/src/main.rs b/src/main.rs index e93429e..9e1083b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ #![plugin(rocket_codegen)] extern crate activitypub; +extern crate atom_syndication; extern crate colored; extern crate diesel; extern crate dotenv; @@ -45,6 +46,7 @@ fn main() { routes::blogs::new, routes::blogs::new_auth, routes::blogs::create, + routes::blogs::atom_feed, routes::comments::create, @@ -98,6 +100,7 @@ fn main() { routes::user::ap_followers, routes::user::new, routes::user::create, + routes::user::atom_feed, routes::well_known::host_meta, routes::well_known::nodeinfo, diff --git a/src/routes/blogs.rs b/src/routes/blogs.rs index 528e0ae..f4d783a 100644 --- a/src/routes/blogs.rs +++ b/src/routes/blogs.rs @@ -1,7 +1,9 @@ use activitypub::collection::OrderedCollection; +use atom_syndication::{Entry, FeedBuilder}; use rocket::{ request::LenientForm, - response::{Redirect, Flash} + response::{Redirect, Flash, content::Content}, + http::ContentType }; use rocket_contrib::Template; use serde_json; @@ -129,3 +131,18 @@ fn outbox(name: String, conn: DbConn) -> ActivityStream { let blog = Blog::find_local(&*conn, name).unwrap(); blog.outbox(&*conn) } + +#[get("/~//atom.xml")] +fn atom_feed(name: String, conn: DbConn) -> Content { + let blog = Blog::find_by_fqn(&*conn, name.clone()).expect("Unable to find blog"); + let feed = FeedBuilder::default() + .title(blog.title.clone()) + .id(Instance::get_local(&*conn).unwrap().compute_box("~", name, "atom.xml")) + .entries(Post::get_recents_for_blog(&*conn, &blog, 15) + .into_iter() + .map(|p| super::post_to_atom(p, &*conn)) + .collect::>()) + .build() + .expect("Error building Atom feed"); + Content(ContentType::new("application", "atom+xml"), feed.to_string()) +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index c46fc2f..dd2be41 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,3 +1,5 @@ +use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder}; +use diesel::PgConnection; use rocket::{ http::uri::{FromUriParam, UriDisplay}, response::NamedFile @@ -7,6 +9,8 @@ use std::{ path::{Path, PathBuf} }; +use plume_models::posts::Post; + macro_rules! may_fail { ($account:expr, $expr:expr, $template:expr, $msg:expr, | $res:ident | $block:block) => { { @@ -75,6 +79,25 @@ impl Page { } } +pub fn post_to_atom(post: Post, conn: &PgConnection) -> Entry { + EntryBuilder::default() + .title(post.title.clone()) + .content(ContentBuilder::default() + .value(format!("", *post.content.get())) + .src(post.ap_url.clone()) + .content_type("html".to_string()) + .build().expect("Atom feed: content error")) + .authors(post.get_authors(&*conn) + .into_iter() + .map(|a| PersonBuilder::default() + .name(a.display_name) + .uri(a.ap_url) + .build().expect("Atom feed: author error")) + .collect::>()) + .links(vec![LinkBuilder::default().href(post.ap_url).build().expect("Atom feed: link error")]) + .build().expect("Atom feed: entry error") +} + pub mod blogs; pub mod comments; pub mod errors; diff --git a/src/routes/user.rs b/src/routes/user.rs index 2688b38..2246c05 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -3,10 +3,12 @@ use activitypub::{ collection::OrderedCollection, object::Article }; +use atom_syndication::{Entry, FeedBuilder}; use rocket::{ State, request::LenientForm, - response::{Redirect, Flash} + response::{Redirect, Flash, Content}, + http::ContentType }; use rocket_contrib::Template; use serde_json; @@ -276,3 +278,18 @@ fn ap_followers(name: String, conn: DbConn, _ap: ApRequest) -> ActivityStream/atom.xml")] +fn atom_feed(name: String, conn: DbConn) -> Content { + let author = User::find_by_fqn(&*conn, name.clone()).expect("Unable to find author"); + let feed = FeedBuilder::default() + .title(author.display_name.clone()) + .id(Instance::get_local(&*conn).unwrap().compute_box("~", name, "atom.xml")) + .entries(Post::get_recents_for_author(&*conn, &author, 15) + .into_iter() + .map(|p| super::post_to_atom(p, &*conn)) + .collect::>()) + .build() + .expect("Error building Atom feed"); + Content(ContentType::new("application", "atom+xml"), feed.to_string()) +} From 52860efa850b41d9a200e2c39750dc21f03b88c3 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 21:16:38 +0100 Subject: [PATCH 21/33] Add a link for Atom feeds --- templates/blogs/details.html.tera | 5 ++++- templates/posts/details.html.tera | 2 +- templates/users/details.html.tera | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/templates/blogs/details.html.tera b/templates/blogs/details.html.tera index aa4be52..a07cdb7 100644 --- a/templates/blogs/details.html.tera +++ b/templates/blogs/details.html.tera @@ -23,7 +23,10 @@

-

{{ "Latest articles" | _ }}

+

+ {{ "Latest articles" | _ }} + +

{% if posts | length < 1 %}

{{ "No posts to see here yet." | _ }}

{% endif %} diff --git a/templates/posts/details.html.tera b/templates/posts/details.html.tera index f17ad56..b82624d 100644 --- a/templates/posts/details.html.tera +++ b/templates/posts/details.html.tera @@ -22,8 +22,8 @@ }} — {{ date | date(format="%B %e, %Y") }} - — {% if is_author %} + — {{ "Delete this article" | _ }} {% endif %}

diff --git a/templates/users/details.html.tera b/templates/users/details.html.tera index f129135..3437847 100644 --- a/templates/users/details.html.tera +++ b/templates/users/details.html.tera @@ -19,7 +19,10 @@ {% if recents | length != 0 %} -

{{ "Latest articles" | _ }}

+

+ {{ "Latest articles" | _ }} + +

{% for article in recents %} {{ macros::post_card(article=article) }} From e752c2a4deae55950a12f2610189f13727535f66 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 21:30:03 +0100 Subject: [PATCH 22/33] Add a .editorconfig Fixes #179 --- .editorconfig | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7130076 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{js,rs,css,tera}] +charset = utf-8 + +[*.{rs,tera,css}] +indent_style = space +indent_size = 4 + +[*.js] +indent_style = space +indent_size = 2 From 93cb70455d5f5c661b89e8e3c15b9ed886a5afb6 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 21:34:05 +0100 Subject: [PATCH 23/33] Add code stye recommendations to the doc --- docs/DEVELOPMENT.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 374a0f3..449f7ff 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -75,3 +75,13 @@ msgstr[1] "" ``` And that's it! Once these new messages will have been translated, they will correctly be displayed in the requested locale! + +## Code Style + +For Rust, use the standard style. `rustfmt` can help you keeping your code clean. + +For CSS, the only rule is to use One True Brace Style. + +For JavaScript, we use [the JavaScript Standard Style](https://standardjs.com/). + +For HTML/Tera templates, we use HTML5 syntax. From 4d4a58361b009af4544d8072099a32aa8ef2d276 Mon Sep 17 00:00:00 2001 From: Bat Date: Sat, 1 Sep 2018 21:42:53 +0100 Subject: [PATCH 24/33] Use Standard JS for JS code --- static/js/autoExpand.js | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/static/js/autoExpand.js b/static/js/autoExpand.js index 33fb32e..fbc25e8 100644 --- a/static/js/autoExpand.js +++ b/static/js/autoExpand.js @@ -1,14 +1,9 @@ -function autosize(){ - const el = this; - el.style.height = 'auto'; - el.style.height = (el.scrollHeight ) + 'px'; +function autosize () { + const el = this + el.style.height = 'auto' + el.style.height = `${el.scrollHeight}px` } -const articleContent = document.querySelector('#content'); -let offset = 0; -let style = window.getComputedStyle(articleContent, null); - -offset += parseInt(style['paddingTop']) + parseInt(style['paddingBottom']); -autosize.bind(articleContent)(); -articleContent.addEventListener('keyup', autosize); - +const articleContent = document.querySelector('#content') +autosize.bind(articleContent)() +articleContent.addEventListener('keyup', autosize) From 5af9af60f4ff2daf8f4919c44109d7bac7013799 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 2 Sep 2018 00:34:03 +0100 Subject: [PATCH 25/33] Docs: Add SysVinit snippet And small fixes --- docs/INSTALL.md | 66 ++++++++++++++++++++++++++++++++---- plume-models/src/reshares.rs | 4 +-- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index bae31b9..0e4aabd 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -103,8 +103,6 @@ createuser -d -P plume createdb -O plume plume ``` -```bash -``` ## Running migrations @@ -160,7 +158,7 @@ server { # for ssl conf: https://cipherli.st/ ssl_protocols TLSv1.2 TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2 - ssl_prefer_server_ciphers on; + ssl_prefer_server_ciphers on; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;# openssl dhparam -out /etc/letsencrypt/ssl-dhparam.pem 4096 ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 @@ -170,7 +168,7 @@ server { ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 9.9.9.9 80.67.169.12 valid=300s; - resolver_timeout 5s; + resolver_timeout 5s; add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; @@ -184,7 +182,7 @@ server { } location / { - proxy_pass http://localhost:8000/; + proxy_pass http://localhost:7878/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -240,7 +238,7 @@ If you prefer Apache, you can use this configuration (here too replace `blog.exa ## Systemd integration -If you want to manage your Plume instance with systemd, you can use the following unit file (to be saved in `/lib/systemd/system/plume.service`): +If you want to manage your Plume instance with systemd, you can use the following unit file (to be saved in `/etc/systemd/system/plume.service`): ```toml [Unit] @@ -258,6 +256,62 @@ Restart=always WantedBy=multi-user.target ``` +## SysVinit integration + +This script can also be useful if you are using SysVinit. + +```bash +#!/bin/bash +# +# chkconfig: 35 90 12 +# description: Plume +# + +# Get function from functions library +. /etc/init.d/functions + +# Start Plume +start() { + initlog -c "echo -n Démarrage de Plume: " + cd /home/plume/Plume & cargo run + ### Create the lock file ### + touch /var/lock/subsys/plume + success $"Plume est prêt !" + echo +} + +# Restart Plume +stop() { + initlog -c "echo -n Arrêt de Plume: " + killproc cargo run + ### Now, delete the lock file ### + rm -f /var/lock/subsys/plume + echo +} + +### main logic ### +case "$1" in + start) + start + ;; + stop) + stop + ;; + status) + status FOO + ;; + restart|reload|condrestart) + stop + start + ;; + *) + echo $"Usage: $0 {start|stop|restart|reload|status}" + exit 1 +esac + +exit 0 +``` + ## Caveats: - Pgbouncer is not yet supported (named transactions are used). diff --git a/plume-models/src/reshares.rs b/plume-models/src/reshares.rs index 4fd1a63..734da12 100644 --- a/plume-models/src/reshares.rs +++ b/plume-models/src/reshares.rs @@ -73,8 +73,8 @@ impl Reshare { impl FromActivity for Reshare { fn from_activity(conn: &PgConnection, announce: Announce, _actor: Id) -> Reshare { - let user = User::from_url(conn, announce.announce_props.actor.as_str().unwrap().to_string()); - let post = Post::find_by_ap_url(conn, announce.announce_props.object.as_str().unwrap().to_string()); + let user = User::from_url(conn, announce.announce_props.actor_link::().expect("Reshare::from_activity: actor error").into()); + let post = Post::find_by_ap_url(conn, announce.announce_props.object_link::().expect("Reshare::from_activity: object error").into()); let reshare = Reshare::insert(conn, NewReshare { post_id: post.unwrap().id, user_id: user.unwrap().id, From 2c33e1612db518a344c28f92acf6ab25b6fee980 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 2 Sep 2018 12:13:17 +0100 Subject: [PATCH 26/33] Docs: add some details about installation --- docs/INSTALL.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 0e4aabd..024b326 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -4,10 +4,12 @@ In order to be installed and to work correctly, Plume needs: -- Git -- PostgreSQL -- GetText -- Rust and Cargo +- *Git* (to get the code) +- *Curl* (for RustUp, the Rust installer) +- *GCC* (to compile C dependencies) +- *PostgreSQL* (for the database) +- *GetText* (to manage translations) +- *Rust* and *Cargo* (to build the code) All the following instructions will need a terminal. @@ -66,6 +68,14 @@ You can install it on **GNU/Linux** and **Mac OS X** with: curl https://sh.rustup.rs -sSf | sh ``` +When asked, choose the *"1) Proceed with installation (default)"* option. + +Then run this command to be able to run cargo in the current session: + +```bash +export PATH="$PATH:/home/plume/.cargo/bin:/home/plume/.local/bin:/usr/local/sbin" +``` + On **Windows**, you'll need, if you don't already have them, to download and install the [Visual C++ 2015 Build Tools](https://www.microsoft.com/en-us/download/details.aspx?id=48159). Then, download the [rustup installer](https://www.rust-lang.org/en-US/install.html) and run it. ## Getting and compiling the Plume source code From 0b5eb2c94617949bbaca9a57d836743286ac11a3 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 2 Sep 2018 12:34:48 +0100 Subject: [PATCH 27/33] Add a Media model --- .../2018-09-02-111458_create_medias/down.sql | 2 ++ .../2018-09-02-111458_create_medias/up.sql | 10 +++++++ plume-models/src/lib.rs | 5 ++-- plume-models/src/medias.rs | 29 +++++++++++++++++++ plume-models/src/schema.rs | 13 +++++++++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 migrations/2018-09-02-111458_create_medias/down.sql create mode 100644 migrations/2018-09-02-111458_create_medias/up.sql create mode 100644 plume-models/src/medias.rs diff --git a/migrations/2018-09-02-111458_create_medias/down.sql b/migrations/2018-09-02-111458_create_medias/down.sql new file mode 100644 index 0000000..3ba0178 --- /dev/null +++ b/migrations/2018-09-02-111458_create_medias/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE medias; diff --git a/migrations/2018-09-02-111458_create_medias/up.sql b/migrations/2018-09-02-111458_create_medias/up.sql new file mode 100644 index 0000000..f89f448 --- /dev/null +++ b/migrations/2018-09-02-111458_create_medias/up.sql @@ -0,0 +1,10 @@ +-- Your SQL goes here +CREATE TABLE medias ( + id SERIAL PRIMARY KEY, + file_path TEXT NOT NULL DEFAULT '', + alt_text TEXT NOT NULL DEFAULT '', + is_remote BOOLEAN NOT NULL DEFAULT 'f', + remote_url TEXT, + sensitive BOOLEAN NOT NULL DEFAULT 'f', + content_warning TEXT +) diff --git a/plume-models/src/lib.rs b/plume-models/src/lib.rs index e0bd5b2..f2c80c6 100644 --- a/plume-models/src/lib.rs +++ b/plume-models/src/lib.rs @@ -78,7 +78,7 @@ fn get_next_id(conn: &PgConnection, seq: &str) -> i32 { // We cant' use currval because it may fail if nextval have never been called before let next = select(nextval(seq)).get_result::(conn).expect("Next ID fail"); if next > 1 { - select(setval(seq, next - 1)).get_result::(conn).expect("Reset ID fail"); + select(setval(seq, next - 1)).get_result::(conn).expect("Reset ID fail"); } next as i32 } @@ -87,7 +87,7 @@ fn get_next_id(conn: &PgConnection, seq: &str) -> i32 { lazy_static! { pub static ref BASE_URL: String = env::var("BASE_URL") .unwrap_or(format!("127.0.0.1:{}", env::var("ROCKET_PORT").unwrap_or(String::from("8000")))); - + pub static ref DB_URL: String = env::var("DB_URL") .unwrap_or(format!("postgres://plume:plume@localhost/{}", env::var("DB_NAME").unwrap_or(String::from("plume")))); @@ -111,6 +111,7 @@ pub mod db_conn; pub mod follows; pub mod instance; pub mod likes; +pub mod medias; pub mod mentions; pub mod notifications; pub mod post_authors; diff --git a/plume-models/src/medias.rs b/plume-models/src/medias.rs new file mode 100644 index 0000000..23c2890 --- /dev/null +++ b/plume-models/src/medias.rs @@ -0,0 +1,29 @@ +use diesel::{self, PgConnection, QueryDsl, ExpressionMethods, RunQueryDsl}; +use schema::medias; + +#[derive(Queryable)] +pub struct Media { + pub id: i32, + pub file_path: String, + pub alt_text: String, + pub is_remote: bool, + pub remote_url: Option, + pub sensitive: bool, + pub content_warning: Option +} + +#[derive(Insertable)] +#[table_name = "medias"] +pub struct NewMedia { + pub file_path: String, + pub alt_text: String, + pub is_remote: bool, + pub remote_url: Option, + pub sensitive: bool, + pub content_warning: Option +} + +impl Media { + insert!(medias, NewMedia); + get!(medias); +} diff --git a/plume-models/src/schema.rs b/plume-models/src/schema.rs index 7980709..f296717 100644 --- a/plume-models/src/schema.rs +++ b/plume-models/src/schema.rs @@ -72,6 +72,18 @@ table! { } } +table! { + medias (id) { + id -> Int4, + file_path -> Text, + alt_text -> Text, + is_remote -> Bool, + remote_url -> Nullable, + sensitive -> Bool, + content_warning -> Nullable, + } +} + table! { mentions (id) { id -> Int4, @@ -170,6 +182,7 @@ allow_tables_to_appear_in_same_query!( follows, instances, likes, + medias, mentions, notifications, post_authors, From 726b4e25fde3c495d2a8ded8ada8707b9afe000b Mon Sep 17 00:00:00 2001 From: maximesrd <42911617+maximesrd@users.noreply.github.com> Date: Sun, 2 Sep 2018 17:25:28 +0200 Subject: [PATCH 28/33] Update INSTALL.md Rewriting of sysvinit script to make it works properly --- docs/INSTALL.md | 128 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 38 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 024b326..6c337c0 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -271,55 +271,107 @@ WantedBy=multi-user.target This script can also be useful if you are using SysVinit. ```bash -#!/bin/bash -# -# chkconfig: 35 90 12 -# description: Plume -# +#!/bin/sh +### BEGIN INIT INFO +# Provides: +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Start daemon at boot time +# Description: Federated blogging +# Based on https://raw.githubusercontent.com/fhd/init-script-template/master/template +### END INIT INFO -# Get function from functions library -. /etc/init.d/functions +dir="/home/plume/Plume" +cmd="/home/plume/.cargo/bin/cargo run" +user="plume" -# Start Plume -start() { - initlog -c "echo -n Démarrage de Plume: " - cd /home/plume/Plume & cargo run - ### Create the lock file ### - touch /var/lock/subsys/plume - success $"Plume est prêt !" - echo +name=`basename $0` +pid_file="/var/run/$name.pid" +stdout_log="/home/plume/Plume/plume.log" +stderr_log="/home/plume/Plume/plume.err" + +get_pid() { + cat "$pid_file" } -# Restart Plume -stop() { - initlog -c "echo -n Arrêt de Plume: " - killproc cargo run - ### Now, delete the lock file ### - rm -f /var/lock/subsys/plume - echo +is_running() { + [ -f "$pid_file" ] && ps -p `get_pid` > /dev/null 2>&1 } -### main logic ### case "$1" in - start) - start - ;; - stop) - stop - ;; - status) - status FOO - ;; - restart|reload|condrestart) - stop - start - ;; - *) - echo $"Usage: $0 {start|stop|restart|reload|status}" + start) + if is_running; then + echo "Already started" + else + echo "Starting $name" + cd "$dir" + if [ -z "$user" ]; then + sudo $cmd >> "$stdout_log" 2>> "$stderr_log" & + else + sudo -u "$user" $cmd >> "$stdout_log" 2>> "$stderr_log" & + fi + echo $! > "$pid_file" + if ! is_running; then + echo "Unable to start, see $stdout_log and $stderr_log" + exit 1 + fi + fi + ;; + stop) + if is_running; then + echo -n "Stopping $name.." + kill `get_pid` + for i in 1 2 3 4 5 6 7 8 9 10 + # for i in `seq 10` + do + if ! is_running; then + break + fi + + echo -n "." + sleep 1 + done + echo + + if is_running; then + echo "Not stopped; may still be shutting down or shutdown may have failed" + exit 1 + else + echo "Stopped" + if [ -f "$pid_file" ]; then + rm "$pid_file" + fi + fi + else + echo "Not running" + fi + ;; + restart) + $0 stop + if is_running; then + echo "Unable to stop, will not attempt to start" exit 1 + fi + $0 start + ;; + status) + if is_running; then + echo "Running" + else + echo "Stopped" + exit 1 + fi + ;; + *) + echo "Usage: $0 {start|stop|restart|status}" + exit 1 + ;; esac exit 0 + ``` ## Caveats: From 25a1ef09ee2330257170487d133f4f106675e6e4 Mon Sep 17 00:00:00 2001 From: maximesrd <42911617+maximesrd@users.noreply.github.com> Date: Sun, 2 Sep 2018 17:43:20 +0200 Subject: [PATCH 29/33] Update INSTALL.md Missing dependencies to compile Plume --- docs/INSTALL.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 6c337c0..8628801 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -6,10 +6,11 @@ In order to be installed and to work correctly, Plume needs: - *Git* (to get the code) - *Curl* (for RustUp, the Rust installer) -- *GCC* (to compile C dependencies) +- *GCC* and *make* (to compile C dependencies) - *PostgreSQL* (for the database) - *GetText* (to manage translations) - *Rust* and *Cargo* (to build the code) +- *OpenSSL* and *OpenSSL librairies* (for security) All the following instructions will need a terminal. @@ -20,13 +21,13 @@ On **Debian**: ```bash apt update -apt install gettext postgresql postgresql-contrib libpq-dev git +apt install gettext postgresql postgresql-contrib libpq-dev git curl gcc make openssl libssl-dev ``` On **Fedora**, **CentOS** or **RHEL**: ```bash -dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel +dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl libssl-dev # TODO: GetText + Git install ``` From 8b1130f0ddbea96c79af3eaed3c2b9f1e5695a77 Mon Sep 17 00:00:00 2001 From: maximesrd <42911617+maximesrd@users.noreply.github.com> Date: Sun, 2 Sep 2018 17:57:18 +0200 Subject: [PATCH 30/33] Update INSTALL.md correction of two errors: about openssl library and deletion omission --- docs/INSTALL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 8628801..e1caf8e 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -27,8 +27,8 @@ apt install gettext postgresql postgresql-contrib libpq-dev git curl gcc make op On **Fedora**, **CentOS** or **RHEL**: ```bash -dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl libssl-dev -# TODO: GetText + Git install +dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl openssl-devel +# TODO: GetText ``` On **Gentoo**: From e5ade7d65916cdab61066cfe4b88ecee135d50f0 Mon Sep 17 00:00:00 2001 From: maximesrd <42911617+maximesrd@users.noreply.github.com> Date: Sun, 2 Sep 2018 18:01:36 +0200 Subject: [PATCH 31/33] Update INSTALL.md adding packages to install for other distributions --- docs/INSTALL.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index e1caf8e..47391db 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -27,24 +27,21 @@ apt install gettext postgresql postgresql-contrib libpq-dev git curl gcc make op On **Fedora**, **CentOS** or **RHEL**: ```bash -dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl openssl-devel -# TODO: GetText +dnf install postgresql-server postgresql-contrib mariadb-devel libsq3-devel libpqxx libpqxx-devel git curl gcc make openssl openssl-devel gettext ``` On **Gentoo**: ```bash emerge --sync -emerge -av postgresql eselect-postgresql -# TODO: GetText + Git install +emerge -av postgresql eselect-postgresql gettext && emerge --ask dev-vcs/git ``` On **Mac OS X**, with [Homebrew](https://brew.sh/): ```bash brew update -brew install postgres -# TODO: GetText + Git install +brew install postgres gettext git ``` ## Creating a new user (optional) From f44b6fffa32b86a53f987bb05c95a90c61817066 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 2 Sep 2018 21:55:42 +0100 Subject: [PATCH 32/33] Media upload --- .gitignore | 1 + Cargo.lock | 415 +++++++++++++++++- Cargo.toml | 4 +- .../down.sql | 2 + .../2018-09-02-123623_medias_owner_id/up.sql | 2 + plume-models/src/medias.rs | 39 +- plume-models/src/schema.rs | 2 + src/main.rs | 12 +- src/routes/medias.rs | 104 +++++ src/routes/mod.rs | 3 +- static/main.css | 40 +- templates/medias/details.html.tera | 24 + templates/medias/index.html.tera | 31 ++ templates/medias/new.html.tera | 17 + 14 files changed, 680 insertions(+), 16 deletions(-) create mode 100644 migrations/2018-09-02-123623_medias_owner_id/down.sql create mode 100644 migrations/2018-09-02-123623_medias_owner_id/up.sql create mode 100644 src/routes/medias.rs create mode 100644 templates/medias/details.html.tera create mode 100644 templates/medias/index.html.tera create mode 100644 templates/medias/new.html.tera diff --git a/.gitignore b/.gitignore index 33acb32..5b06904 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ translations po/*.po~ .env Rocket.toml +media diff --git a/Cargo.lock b/Cargo.lock index 409af0a..8820fa5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,11 @@ dependencies = [ "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ascii" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atom_syndication" version = "0.6.0" @@ -99,6 +104,20 @@ dependencies = [ "quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "debug-builders 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "backtrace" version = "0.3.6" @@ -150,6 +169,11 @@ dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bitflags" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "0.9.1" @@ -178,6 +202,16 @@ dependencies = [ "opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "buf_redux" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slice-deque 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "build_const" version = "0.2.1" @@ -212,6 +246,17 @@ name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chomp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "debugtrace 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "chrono" version = "0.4.2" @@ -223,6 +268,11 @@ dependencies = [ "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "chunked_transfer" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cloudabi" version = "0.0.3" @@ -239,6 +289,14 @@ dependencies = [ "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "conv" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cookie" version = "0.11.0-dev" @@ -326,11 +384,38 @@ dependencies = [ "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "custom_derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "data-encoding" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dbghelp-sys" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "debug-builders" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "debugtrace" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "derive-error-chain" version = "0.11.1" @@ -399,6 +484,68 @@ name = "dtoa" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "either" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "encoding" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-japanese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-korean" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-simpchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-singlebyte" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding-index-tradchinese" +version = "1.20141219.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "encoding_index_tests" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "encoding_rs" version = "0.7.2" @@ -519,6 +666,59 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "groupable" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "guid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "guid-macro-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "guid-create" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "guid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "guid-macro-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "guid-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heck" version = "0.3.0" @@ -640,6 +840,21 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "iron" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "isatty" version = "0.1.7" @@ -737,6 +952,14 @@ name = "mac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "mach" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "maplit" version = "1.0.1" @@ -791,6 +1014,17 @@ dependencies = [ "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mime_guess" +version = "1.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime_guess" version = "2.0.0-alpha.4" @@ -831,6 +1065,41 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "modifier" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "multipart" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", + "nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mustache" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "native-tls" version = "0.1.5" @@ -863,6 +1132,25 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nickel" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "nodrop" version = "0.1.12" @@ -1009,6 +1297,14 @@ name = "pkg-config" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "plugin" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "plume" version = "0.1.0" @@ -1020,13 +1316,15 @@ dependencies = [ "dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "guid-create 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)", "plume-common 0.1.0", "plume-models 0.1.0", "rocket 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", "rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)", - "rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume)", + "rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d)", "rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)", "rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1098,6 +1396,19 @@ name = "precomputed-hash" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "proc-macro-hack" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack-impl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.2.3" @@ -1130,6 +1441,11 @@ dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quick-xml" version = "0.12.1" @@ -1369,7 +1685,7 @@ dependencies = [ [[package]] name = "rocket_csrf" version = "0.1.0" -source = "git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume#5309b7634a9cd204d003312cb70ce9d36b660e6b" +source = "git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d#0fbacab1bc6a32419a18edb600586c5c02fdac4d" dependencies = [ "csrf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1441,6 +1757,11 @@ name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "schannel" version = "0.1.12" @@ -1549,6 +1870,16 @@ name = "slab" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "slice-deque" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "mach 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slug" version = "0.1.3" @@ -1733,6 +2064,19 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tiny_http" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" version = "0.1.5" @@ -1895,11 +2239,27 @@ name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "typemap" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.10.0" @@ -1967,6 +2327,14 @@ dependencies = [ "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unsafe-any" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "untrusted" version = "0.6.2" @@ -2114,25 +2482,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" "checksum array_tool 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" +"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atom_syndication 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9a7ab83635ff7a3b04856f4ad95324dccc9b947ab1e790fc5c769ee6d6f60c" +"checksum backtrace 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "150ae7828afa7afb6d474f909d64072d21de1f3365b6e8ad8029bf7b1c6350a0" "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e" "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" "checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" "checksum base64 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9263aa6a38da271eec5c91a83ce1e800f093c8535788d403d626d8d5c3f8f007" "checksum bcrypt 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a1512813db09170b44a00870b58421876d797b77b085c5205a24db90905f758" +"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum block-cipher-trait 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6136d803280ae3532efa36114335255ea94f3d75d735ddedd66b0d7cd30bad3" "checksum blowfish 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95ede07672d9f4144c578439aa352604ec5c67a80c940fe8d382ddbeeeb3c6d8" +"checksum buf_redux 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20c6687a26c9ce967594b78038c06139a0d3a5b3005d16572284d543924a01aa" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum bytes 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2f1d50c876fb7545f5f289cd8b2aee3f359d073ae819eed5d6373638e2c61e59" "checksum cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8b9d2900f78631a5876dc5d6c9033ede027253efcd33dd36b1309fc6cab97ee0" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum chomp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9f74ad218e66339b11fd23f693fb8f1d621e80ba6ac218297be26073365d163d" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" +"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" +"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299" "checksum cookie 0.11.0-dev (git+https://github.com/alexcrichton/cookie-rs?rev=0365a18)" = "" "checksum core-foundation 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25bfd746d203017f7d5cbd31ee5d8e17f94b6521c7af77ece6c9e4b2d4b16c67" "checksum core-foundation-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "065a5d7ffdcbc8fa145d6f0746f3555025b9097a9e9cda59f7467abae670c78d" @@ -2142,7 +2517,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b" "checksum csrf 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "38f2ee2a7e76740d81de006e61eff53206c56448a30d8017b4ac97b5486682bd" +"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" "checksum data-encoding 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "67df0571a74bf0d97fb8b2ed22abdd9a48475c96bd327db968b7d9cace99655e" +"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" +"checksum debug-builders 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f5d8e3d14cabcb2a8a59d7147289173c6ada77a0bc526f6b85078f941c0cf12" +"checksum debugtrace 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "62e432bd83c5d70317f6ebd8a50ed4afb32907c64d6e2e1e65e339b06dc553f3" "checksum derive-error-chain 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4450afbe280461e78299b39182a085b70e3e71be049cf4a588ad72f1e44d33" "checksum derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c998e6ab02a828dd9735c18f154e14100e674ed08cb4e1938f0e4177543f439" "checksum derive_builder_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "735e24ee9e5fa8e16b86da5007856e97d592e11867e45d76e0c0d0a164a0b757" @@ -2150,6 +2529,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum diesel_derives 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6471a2b637b414d3ee1504cf230409a550381c79204282f8fe06c527e4ae56be" "checksum dotenv 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a70de3c590ce18df70743cace1cf12565637a0b26fd8b04ef10c7d33fdc66cdc" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum either 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a39bffec1e2015c5d8a6773cb0cf48d0d758c842398f624c34969071f5499ea7" +"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" +"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" +"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" +"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" +"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" +"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" +"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum encoding_rs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98fd0f24d1fb71a4a6b9330c8ca04cbd4e7cc5d846b54ca74ff376bc7c9f798d" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" @@ -2166,6 +2553,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum gettext-rs 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b8c2412d5758f68a9eeba161f9ecb9a55f56bfdbf17857650b98f2b9b281a47" "checksum gettext-sys 0.19.8 (registry+https://github.com/rust-lang/crates.io-index)" = "62c644c0b8b73706fb8c7420533fd30abf6f41c2703994bc6f0826fceb7fb3d6" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum groupable 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32619942b8be646939eaf3db0602b39f5229b74575b67efc897811ded1db4e57" +"checksum guid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e691c64d9b226c7597e29aeb46be753beb8c9eeef96d8c78dfd4d306338a38da" +"checksum guid-create 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcea207bf7a6092166ab590f98fe5dde5a7deed1f1920d98dcac31f80814c40d" +"checksum guid-macro-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d50f7c496073b5a5dec0f6f1c149113a50960ce25dd2a559987a5a71190816" +"checksum guid-parser 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abc7adb441828023999e6cff9eb1ea63156f7ec37ab5bf690005e8fc6c1148ad" "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" "checksum html5ever 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b04478cf718862650a0bf66acaf8f2f8c906fbc703f35c916c1f4211b069a364" @@ -2178,6 +2570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "61bb90bdd39e3af69b0172dfc6130f6cd6332bf040fbb9bdd4401d37adbd48b8" "checksum indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08173ba1e906efb6538785a8844dd496f5d34f0a2d88038e95195172fc667220" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum iron 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8e17268922834707e1c29e8badbf9c712c9c43378e1b6a3388946baff10be2" "checksum isatty 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a118a53ba42790ef25c82bb481ecf36e2da892646cccd361e69a6bb881e19398" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" @@ -2192,6 +2585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +"checksum mach 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "977262a11cfd76b94da10b8898cea6e9ac391301ab74741e6da6bee13d7df46d" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" @@ -2199,12 +2593,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" +"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" "checksum mime_guess 2.0.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130ea3c9c1b65dba905ab5a4d9ac59234a9585c24d135f264e187fe7336febbd" "checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum modifier 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41f5c9112cb662acd3b204077e0de5bc66305fa8df65c8019d5adb10e9ab6e58" +"checksum multipart 0.15.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b3bd50d71866514b14d2ca09823d81390d92daa40bc835f83a908c52ab0a802e" +"checksum mustache 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb004e419334fc9172d0a5ff91c0770bdd6239091b0b343eb5926101f0a7d13" "checksum native-tls 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f74dbadc8b43df7864539cedb7bc91345e532fdd913cfdc23ad94f4d2d40fbc0" "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4" +"checksum nickel 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "22b40e35b9f46a076dcbd8193125cea0e4130b1c015f68655038010f3e826e04" "checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" @@ -2223,12 +2622,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" +"checksum plugin 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a6a0dc3910bc8db877ffed8e457763b317cf880df4ae19109b9f77d277cf6e0" "checksum pq-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4dfb5e575ef93a1b7b2a381d47ba7c5d4e4f73bff37cee932195de769aad9a54" "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +"checksum proc-macro-hack 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ba8d4f9257b85eb6cdf13f055cea3190520aab1409ca2ab43493ea4820c25f0" +"checksum proc-macro-hack-impl 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5cb6f960ad471404618e9817c0e5d10b1ae74cfdf01fab89ea0641fe7fb2892" "checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" "checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quick-xml 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b14c27e04216596a49f2b82398a24f67ed9f131a5c0e0235496ea446bdacfb12" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" @@ -2252,7 +2655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rocket_codegen 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_codegen_next 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_contrib 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" -"checksum rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?branch=plume)" = "" +"checksum rocket_csrf 0.1.0 (git+https://github.com/fdb-hiroshima/rocket_csrf?rev=0fbacab1bc6a32419a18edb600586c5c02fdac4d)" = "" "checksum rocket_http 0.4.0-dev (git+https://github.com/SergioBenitez/Rocket?rev=df7111143e466c18d1f56377a8d9530a5a306aba)" = "" "checksum rocket_i18n 0.1.1 (git+https://github.com/BaptisteGelez/rocket_i18n?rev=5b4225d5bed5769482dc926a7e6d6b79f1217be6)" = "" "checksum rpassword 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d127299b02abda51634f14025aec43ae87a7aa7a95202b6a868ec852607d1451" @@ -2260,6 +2663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" "checksum scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2ff3fc5223829be817806c6441279c676e454cc7da608faf03b0ccc09d3889" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" @@ -2274,6 +2678,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" "checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" +"checksum slice-deque 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "79e5bb98247a0eb0cfdedb7e792962ec71ac1003033f70558bd9961f8912e487" "checksum slug 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "797bcb4d24e91239a8615415814f4afb2d8ca400c472de3c73f803a5a7689e11" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8" @@ -2294,6 +2699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tera 0.11.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e815b67d44c26feb06630011fb58b5b243f4e9585aac1ed0592c5795de64cd75" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" "checksum tokio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be15ef40f675c9fe66e354d74c73f3ed012ca1aa14d65846a33ee48f1ae8d922" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" "checksum tokio-executor 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8cac2a7883ff3567e9d66bb09100d09b33d90311feca0206c7ca034bc0c55113" @@ -2308,7 +2714,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-udp 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "137bda266504893ac4774e0ec4c2108f7ccdbcb7ac8dced6305fe9e4e0b5041a" "checksum toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a0263c6c02c4db6c8f7681f9fd35e90de799ebd4cfdeab77a38f4ff6b3d8c0d9" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" +"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" +"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" @@ -2320,6 +2728,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unidecode 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum unsafe-any 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f" "checksum untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "55cd1f4b4e96b46aeb8d4855db4a7a9bd96eeeb5c6a1ab54593328761642ce2f" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf-8 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1262dfab4c30d5cb7c07026be00ee343a6cf5027fdc0104a9160f354e5db75c" diff --git a/Cargo.toml b/Cargo.toml index b566705..2f13ef6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,9 @@ colored = "1.6" dotenv = "*" failure = "0.1" gettext-rs = "0.4" +guid-create = "0.1" heck = "0.3.0" +multipart = "0.15" rpassword = "2.0" serde = "1.0" serde_derive = "1.0" @@ -43,8 +45,8 @@ git = "https://github.com/SergioBenitez/Rocket" rev = "df7111143e466c18d1f56377a8d9530a5a306aba" [dependencies.rocket_csrf] -branch = "plume" git = "https://github.com/fdb-hiroshima/rocket_csrf" +rev = "0fbacab1bc6a32419a18edb600586c5c02fdac4d" [dependencies.rocket_i18n] git = "https://github.com/BaptisteGelez/rocket_i18n" diff --git a/migrations/2018-09-02-123623_medias_owner_id/down.sql b/migrations/2018-09-02-123623_medias_owner_id/down.sql new file mode 100644 index 0000000..c44809d --- /dev/null +++ b/migrations/2018-09-02-123623_medias_owner_id/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +ALTER TABLE medias DROP COLUMN owner_id; diff --git a/migrations/2018-09-02-123623_medias_owner_id/up.sql b/migrations/2018-09-02-123623_medias_owner_id/up.sql new file mode 100644 index 0000000..52dfa5c --- /dev/null +++ b/migrations/2018-09-02-123623_medias_owner_id/up.sql @@ -0,0 +1,2 @@ +-- Your SQL goes here +ALTER TABLE medias ADD COLUMN owner_id INTEGER REFERENCES users(id) ON DELETE CASCADE NOT NULL; diff --git a/plume-models/src/medias.rs b/plume-models/src/medias.rs index 23c2890..4ede485 100644 --- a/plume-models/src/medias.rs +++ b/plume-models/src/medias.rs @@ -1,7 +1,11 @@ use diesel::{self, PgConnection, QueryDsl, ExpressionMethods, RunQueryDsl}; +use serde_json; + +use ap_url; +use instance::Instance; use schema::medias; -#[derive(Queryable)] +#[derive(Queryable, Serialize)] pub struct Media { pub id: i32, pub file_path: String, @@ -9,7 +13,8 @@ pub struct Media { pub is_remote: bool, pub remote_url: Option, pub sensitive: bool, - pub content_warning: Option + pub content_warning: Option, + pub owner_id: i32 } #[derive(Insertable)] @@ -20,10 +25,38 @@ pub struct NewMedia { pub is_remote: bool, pub remote_url: Option, pub sensitive: bool, - pub content_warning: Option + pub content_warning: Option, + pub owner_id: i32 } impl Media { insert!(medias, NewMedia); get!(medias); + list_by!(medias, for_user, owner_id as i32); + + pub fn to_json(&self, conn: &PgConnection) -> serde_json::Value { + let mut json = serde_json::to_value(self).unwrap(); + let (preview, html) = match self.file_path.rsplitn(2, '.').next().unwrap() { + "png" | "jpg" | "jpeg" | "gif" => ( + format!("\"{}\"", self.url(conn), self.alt_text, self.alt_text), + format!("\"{}\"", self.url(conn), self.alt_text, self.alt_text) + ), + "mp3" | "wav" | "flac" => ( + format!("", self.url(conn), self.alt_text), + format!("", self.url(conn), self.alt_text) + ), + "mp4" | "avi" | "webm" | "mov" => ( + format!("", self.url(conn), self.alt_text), + format!("", self.url(conn), self.alt_text) + ), + _ => (String::new(), String::new()) + }; + json["html_preview"] = json!(preview); + json["html"] = json!(html); + json + } + + pub fn url(&self, conn: &PgConnection) -> String { + ap_url(format!("{}/static/{}", Instance::get_local(conn).unwrap().public_domain, self.file_path)) + } } diff --git a/plume-models/src/schema.rs b/plume-models/src/schema.rs index f296717..6fa2dc7 100644 --- a/plume-models/src/schema.rs +++ b/plume-models/src/schema.rs @@ -81,6 +81,7 @@ table! { remote_url -> Nullable, sensitive -> Bool, content_warning -> Nullable, + owner_id -> Int4, } } @@ -164,6 +165,7 @@ joinable!(comments -> posts (post_id)); joinable!(comments -> users (author_id)); joinable!(likes -> posts (post_id)); joinable!(likes -> users (user_id)); +joinable!(medias -> users (owner_id)); joinable!(mentions -> comments (comment_id)); joinable!(mentions -> posts (post_id)); joinable!(mentions -> users (mentioned_id)); diff --git a/src/main.rs b/src/main.rs index 9e1083b..2bb9ddf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![feature(custom_derive, decl_macro, plugin)] #![plugin(rocket_codegen)] - + extern crate activitypub; extern crate atom_syndication; extern crate colored; @@ -8,7 +8,9 @@ extern crate diesel; extern crate dotenv; extern crate failure; extern crate gettextrs; +extern crate guid_create; extern crate heck; +extern crate multipart; extern crate plume_common; extern crate plume_models; extern crate rocket; @@ -61,6 +63,12 @@ fn main() { routes::likes::create, routes::likes::create_auth, + routes::medias::list, + routes::medias::new, + routes::medias::upload, + routes::medias::details, + routes::medias::static_files, + routes::notifications::paginated_notifications, routes::notifications::notifications, routes::notifications::notifications_auth, @@ -123,7 +131,7 @@ fn main() { .add_exceptions(vec![ ("/inbox".to_owned(), "/inbox".to_owned(), rocket::http::Method::Post), ("/@//inbox".to_owned(), "/@//inbox".to_owned(), rocket::http::Method::Post), - + ("/medias/new".to_owned(), "/medias/new".to_owned(), rocket::http::Method::Post), // not compatible with multipart/form-data ]) .finalize().unwrap()) .launch(); diff --git a/src/routes/medias.rs b/src/routes/medias.rs new file mode 100644 index 0000000..3c1ff94 --- /dev/null +++ b/src/routes/medias.rs @@ -0,0 +1,104 @@ +use guid_create::GUID; +use multipart::server::{Multipart, save::{SavedData, SaveResult}}; +use rocket::{Data, http::ContentType, response::{NamedFile, Redirect}}; +use rocket_contrib::Template; +use serde_json; +use std::{fs, path::{Path, PathBuf}}; +use plume_models::{db_conn::DbConn, medias::*, users::User}; + +#[get("/medias")] +fn list(user: User, conn: DbConn) -> Template { + let medias = Media::for_user(&*conn, user.id); + Template::render("medias/index", json!({ + "account": user, + "medias": medias.into_iter().map(|m| m.to_json(&*conn)).collect::>() + })) +} + +#[get("/medias/new")] +fn new(user: User) -> Template { + Template::render("medias/new", json!({ + "account": user, + "form": {}, + "errors": {} + })) +} + +#[post("/medias/new", data = "")] +fn upload(user: User, data: Data, ct: &ContentType, conn: DbConn) -> Redirect { + if ct.is_form_data() { + let (_, boundary) = ct.params().find(|&(k, _)| k == "boundary").expect("No boundary"); + + match Multipart::with_body(data.open(), boundary).save().temp() { + SaveResult::Full(entries) => { + let fields = entries.fields; + + let filename = fields.get(&"file".to_string()).unwrap().into_iter().next().unwrap().headers + .filename.clone() + .unwrap_or("x.png".to_string()); // PNG by default + let ext = filename.rsplitn(2, ".") + .next() + .unwrap(); + let dest = format!("media/{}.{}", GUID::rand().to_string(), ext); + + if let SavedData::Bytes(ref bytes) = fields[&"file".to_string()][0].data { + fs::write(&dest, bytes).expect("Couldn't save upload"); + } else { + if let SavedData::File(ref path, _) = fields[&"file".to_string()][0].data { + fs::copy(path, &dest).expect("Couldn't copy temp upload"); + } else { + println!("not file"); + return Redirect::to(uri!(new)); + } + } + + let has_cw = read(&fields[&"cw".to_string()][0].data).len() > 0; + let media = Media::insert(&*conn, NewMedia { + file_path: dest, + alt_text: read(&fields[&"alt".to_string()][0].data), + is_remote: false, + remote_url: None, + sensitive: has_cw, + content_warning: if has_cw { + Some(read(&fields[&"cw".to_string()][0].data)) + } else { + None + }, + owner_id: user.id + }); + println!("ok"); + Redirect::to(uri!(details: id = media.id)) + }, + SaveResult::Partial(_, _) | SaveResult::Error(_) => { + println!("partial err"); + Redirect::to(uri!(new)) + } + } + } else { + println!("not form data"); + Redirect::to(uri!(new)) + } +} + +fn read(data: &SavedData) -> String { + if let SavedData::Text(s) = data { + s.clone() + } else { + panic!("Field is not a string") + } +} + +#[get("/medias/")] +fn details(id: i32, user: User, conn: DbConn) -> Template { + let media = Media::get(&*conn, id); + Template::render("medias/details", json!({ + "account": user, + "media": media.map(|m| m.to_json(&*conn)) + })) +} + +#[get("/static/media/", rank = 1)] +fn static_files(file: PathBuf) -> Option { + NamedFile::open(Path::new("media/").join(file)).ok() +} + diff --git a/src/routes/mod.rs b/src/routes/mod.rs index dd2be41..d444273 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -103,6 +103,7 @@ pub mod comments; pub mod errors; pub mod instance; pub mod likes; +pub mod medias; pub mod notifications; pub mod posts; pub mod reshares; @@ -110,7 +111,7 @@ pub mod session; pub mod user; pub mod well_known; -#[get("/static/")] +#[get("/static/", rank = 2)] fn static_files(file: PathBuf) -> Option { NamedFile::open(Path::new("static/").join(file)).ok() } diff --git a/static/main.css b/static/main.css index 85b7ade..a872af3 100644 --- a/static/main.css +++ b/static/main.css @@ -384,7 +384,7 @@ input:focus, textarea:focus { textarea { resize: vertical; - + font-family: "Lora", serif; font-size: 1.1em; line-height: 1.5em; @@ -577,7 +577,7 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } flex-direction: column; } - header nav#menu { + header nav#menu { display: inline-flex; } @@ -648,18 +648,18 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } border: solid #F4F4F4 0.1rem; } - body > main > * { + body > main > * { padding: 0 5%; } main .article-meta > * { margin: 0 5%; } - main .article-meta > p { + main .article-meta > p { margin: 2em 5%; font-size: 0.9em; } main .article-meta .comments > * { margin-left: 5%; margin-right: 5%; } - .card { + .card { min-width: 80%; min-height: 80%; } @@ -678,7 +678,8 @@ form.new-post input[type="submit"]:hover { background: #DADADA; } /*== Flex boxes ==*/ .flex { display: flex; - flex-direction: row; + flex-direction: row; + align-items: center; } .flex .grow { @@ -707,3 +708,30 @@ body > footer { body > footer * { margin: 5em 0; } + +/** Medias **/ + +figure { + text-align: center; + margin: 2em; + max-width: 100%; + width: auto; + height: auto; +} + +figure > * { + width: 100%; +} + +figcaption { + padding: 1em; +} + +.preview { + display: block; + max-width: 100px; + max-height: 100px; + width: auto; + height: auto; + margin-right: 20px; +} diff --git a/templates/medias/details.html.tera b/templates/medias/details.html.tera new file mode 100644 index 0000000..b9f8869 --- /dev/null +++ b/templates/medias/details.html.tera @@ -0,0 +1,24 @@ +{% extends "base" %} +{% import "macros" as macros %} + +{% block title %} +Your medias +{% endblock title %} + +{% block content %} +

{{ "Media details" }}

+
+ Go back to the gallery +
+ +
+
+ {{ media.html | safe }} +
{{ media.alt_text }}
+
+ +
+{% endblock content %} diff --git a/templates/medias/index.html.tera b/templates/medias/index.html.tera new file mode 100644 index 0000000..3e4280f --- /dev/null +++ b/templates/medias/index.html.tera @@ -0,0 +1,31 @@ +{% extends "base" %} +{% import "macros" as macros %} + +{% block title %} +Your medias +{% endblock title %} + +{% block content %} +

{{ "Your medias" }}

+
+ Upload +
+ +
+ {% if medias | length < 1 %} +

{{ "You don't have any media yet." | _ }}

+ {% endif %} +
+ {% for media in medias %} +
+ {{ media.html_preview | safe }} +
+

{{ media.alt_text }}

+
+ Delete +
+ {% endfor %} +
+ {# macros::paginate(page=page, total=n_pages) #} +
+{% endblock content %} diff --git a/templates/medias/new.html.tera b/templates/medias/new.html.tera new file mode 100644 index 0000000..0c347a3 --- /dev/null +++ b/templates/medias/new.html.tera @@ -0,0 +1,17 @@ +{% extends "base" %} +{% import "macros" as macros %} + +{% block title %} +{{ "Media upload" | _ }} +{% endblock title %} + +{% block content %} +

{{ "Media upload" | _ }}

+
+ {{ macros::input(name="alt", label="Description", errors=errors, form=form, props='required minlength="1"', details='Useful for visually impaired people and licensing') }} + {{ macros::input(name="cw", label="Content warning", errors=errors, form=form, details='Let it empty if there is none') }} + {{ macros::input(name="file", type='file', label="File", errors=errors, form=form, props='required') }} + + +
+{% endblock content %} From 99fdb8e68071ffbfad70cb05da59d1b9bd4f3e77 Mon Sep 17 00:00:00 2001 From: Bat Date: Sun, 2 Sep 2018 22:10:15 +0100 Subject: [PATCH 33/33] Media deletion --- plume-models/src/medias.rs | 8 +++++++- src/main.rs | 1 + src/routes/medias.rs | 7 +++++++ static/main.css | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/plume-models/src/medias.rs b/plume-models/src/medias.rs index 4ede485..b656631 100644 --- a/plume-models/src/medias.rs +++ b/plume-models/src/medias.rs @@ -1,11 +1,12 @@ use diesel::{self, PgConnection, QueryDsl, ExpressionMethods, RunQueryDsl}; use serde_json; +use std::fs; use ap_url; use instance::Instance; use schema::medias; -#[derive(Queryable, Serialize)] +#[derive(Identifiable, Queryable, Serialize)] pub struct Media { pub id: i32, pub file_path: String, @@ -59,4 +60,9 @@ impl Media { pub fn url(&self, conn: &PgConnection) -> String { ap_url(format!("{}/static/{}", Instance::get_local(conn).unwrap().public_domain, self.file_path)) } + + pub fn delete(&self, conn: &PgConnection) { + fs::remove_file(self.file_path.as_str()).expect("Couldn't delete media from disk"); + diesel::delete(self).execute(conn).expect("Couldn't remove media from DB"); + } } diff --git a/src/main.rs b/src/main.rs index 2bb9ddf..014d811 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,6 +67,7 @@ fn main() { routes::medias::new, routes::medias::upload, routes::medias::details, + routes::medias::delete, routes::medias::static_files, routes::notifications::paginated_notifications, diff --git a/src/routes/medias.rs b/src/routes/medias.rs index 3c1ff94..d5e3910 100644 --- a/src/routes/medias.rs +++ b/src/routes/medias.rs @@ -97,6 +97,13 @@ fn details(id: i32, user: User, conn: DbConn) -> Template { })) } +#[get("/medias//delete")] +fn delete(id: i32, _user: User, conn: DbConn) -> Redirect { + let media = Media::get(&*conn, id).expect("Media to delete not found"); + media.delete(&*conn); + Redirect::to(uri!(list)) +} + #[get("/static/media/", rank = 1)] fn static_files(file: PathBuf) -> Option { NamedFile::open(Path::new("media/").join(file)).ok() diff --git a/static/main.css b/static/main.css index a872af3..5d22ce2 100644 --- a/static/main.css +++ b/static/main.css @@ -720,7 +720,7 @@ figure { } figure > * { - width: 100%; + max-width: 100%; } figcaption {