Compare commits

...

15 Commits

Author SHA1 Message Date
Floréal Toumikian 9be5804b3e Added: New translations 2020-04-19 13:41:01 +02:00
Floréal Toumikian e1bd2eab75 Updated: Cargo.lock (#753) 2020-04-19 09:34:05 +02:00
KITAITI Makoto ac7a05b09a Make blocklist deletion possible (#750) 2020-04-18 11:46:10 +02:00
KITAITI Makoto 71e0a35e06 Use LenientForm instead Form for CSRF protected pages (#751) 2020-04-18 11:45:28 +02:00
KITAITI Makoto c217e5e9b3 Move stylesheets for header from _global.sccss to _header.scss (#749) 2020-04-14 23:32:27 +02:00
KITAITI Makoto 8ba0c17db5 Build app and po files before upload pos to Crowdin (#748) 2020-04-14 20:51:53 +02:00
Floréal Toumikian 4e43c676b4 Fixed: #713: Disply likes and boosts on post cards (#744)
This is a basic and simple way to display them. No interaction possible.

Alos, this patch is not optimised. as everytime a partial post_card is
called, `Post::count_likes()` and `Post::count_reshares()` are called
which means quite a few more quesies are sent to database unless diesel
uses some cache mechanisem.

A way to enhance this this would be to keep a count of likes and reshares
are kept in Post model / table.
2020-04-12 21:29:48 +02:00
KITAITI Makoto b834d1c282 Fix #701 Preferable default theme (#746)
* Make it possible to update users.preferred_theme to NULL

* Make preferred them null when 'Default theme' is selected

* Run cargo fmt
2020-04-12 17:36:00 +02:00
Kenneth Steimel 506fe9955d Fixed #734 , passowrds are now hidden on the remote_interact pages (#741)
* Fixed #734 , passowrds are now hidden on the remote_interact pages

* Update templates/remote_interact_base.rs.html

Co-Authored-By: Floréal Toumikian <floreal+github@nimukaito.net>

Co-authored-by: Floréal Toumikian <floreal+github@nimukaito.net>
2020-04-09 20:55:22 +02:00
KemoNine 02c528cae4 Bump llvm -> 9.0.0 (fixes arm builds) (#737) 2020-01-29 21:37:54 +01:00
Christopher James Halse Rogers 2a58835f92 Snapcraft updates (#731)
* snap: Update rust compiler

* snap: Fix the build.

We now need libclang

* snap: Fix the non-x86 builds.

The goddamned environment variable is SNAPCRAFT_ARCH_TRIPLE*T*

* snap: Mark as stable.

The snap works fine; we don't need to warn people away
2020-01-22 14:10:49 +02:00
Ana Gelez 5f8d6b8e0e Rust 2018! (#726) 2020-01-21 07:02:03 +01:00
fdb-hiroshima 3663bffe5c Update compiler (#725)
* update compiler to recent nightly

* cargo fmt

* fix clippy

but ructe code is still complaining

* update circleci and rocket_csrf

* fix last clippy problems

* cargo fmt

* fix build issue

was caused be improper handling of recursive template (comment) by old ructe, which is fixed on newer version
2020-01-19 12:52:32 +01:00
KemoNine 72464fb428 Add missing dep on clang needed for crate builds (#724) 2020-01-15 10:03:52 +01:00
Wilfried OLLIVIER 23049b638c WIP: Fix RSS issues (#720)
* Add id field to RSS feed

* Add published field to RSS feed
2020-01-13 19:30:32 -05:00
148 changed files with 16375 additions and 12686 deletions
+2 -1
View File
@@ -10,7 +10,7 @@ executors:
type: boolean
default: false
docker:
- image: plumeorg/plume-buildenv:v0.0.8
- image: plumeorg/plume-buildenv:v0.0.9
- image: <<#parameters.postgres>>circleci/postgres:9.6-alpine<</parameters.postgres>><<^parameters.postgres>>alpine:latest<</parameters.postgres>>
environment:
POSTGRES_USER: postgres
@@ -226,6 +226,7 @@ jobs:
steps:
- restore_env:
cache: none
- run: cargo build
- run: crowdin upload -b master
workflows:
+1 -1
View File
@@ -8,7 +8,7 @@ RUN apt update &&\
rm -rf /var/lib/apt/lists/*
#install and configure rust
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2019-03-23 -y &&\
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2020-01-15 -y &&\
rustup component add rustfmt clippy &&\
rustup component add rust-std --target wasm32-unknown-unknown
+1
View File
@@ -18,3 +18,4 @@ tags.*
search_index
.buildconfig
__pycache__
/.vscode/
Generated
+1258 -1242
View File
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -3,6 +3,7 @@ authors = ["Plume contributors"]
name = "plume"
version = "0.4.0"
repository = "https://github.com/Plume-org/Plume"
edition = "2018"
[dependencies]
activitypub = "0.1.3"
@@ -19,11 +20,11 @@ heck = "0.3.0"
lettre = "0.9.2"
lettre_email = "0.9.2"
num_cpus = "1.10"
rocket = "0.4.0"
rocket_contrib = { version = "0.4.0", features = ["json"] }
rocket = "0.4.2"
rocket_contrib = { version = "0.4.2", features = ["json"] }
rocket_i18n = { git = "https://github.com/Plume-org/rocket_i18n", rev = "e922afa7c366038b3433278c03b1456b346074f2" }
rpassword = "4.0"
runtime-fmt = "0.3.0"
runtime-fmt = "0.4.0"
scheduled-thread-pool = "0.2.2"
serde = "1.0"
serde_json = "1.0"
@@ -66,10 +67,10 @@ path = "plume-models"
[dependencies.rocket_csrf]
git = "https://github.com/fdb-hiroshima/rocket_csrf"
rev = "4a72ea2ec716cb0b26188fb00bccf2ef7d1e031c"
rev = "29910f2829e7e590a540da3804336577b48c7b31"
[build-dependencies]
ructe = "0.6.2"
ructe = "0.9.0"
rsass = "0.9"
[features]
+2 -1
View File
@@ -10,7 +10,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
make \
openssl \
libssl-dev
libssl-dev \
clang
WORKDIR /scratch
COPY script/wasm-deps.sh .
+22 -88
View File
@@ -190,7 +190,28 @@ p.error {
background: $gray;
text-overflow: ellipsis;
text-overflow: ellipsis;
footer.authors {
div {
float: left;
margin-right: 0.25em;
}
.likes { color: $red; }
.reshares { color: $primary; }
span.likes, span.resahres {
font-family: "Route159",serif;
font-size: 1em;
}
svg.feather {
width: 0.85em;
height: 0.85em;
}
}
> * {
margin: 20px;
@@ -469,93 +490,6 @@ figure {
/// Small screens
@media screen and (max-width: 600px) {
@keyframes menuOpening {
from {
transform: scaleX(0);
transform-origin: left;
opacity: 0;
}
to {
transform: scaleX(1);
transform-origin: left;
opacity: 1;
}
}
body > header {
flex-direction: column;
nav#menu {
display: inline-flex;
z-index: 21;
}
#content {
display: none;
appearance: none;
text-align: center;
z-index: 20;
}
}
body > header:focus-within #content, #content.show {
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;
&::before {
content: "";
position: absolute;
transform: skewX(-10deg);
top: 0;
left: -20%;
width: 100%;
height: 100%;
z-index: -10;
background: $primary;
}
> nav {
flex-direction: column;
align-items: flex-start;
a {
display: flex;
flex-direction: row;
align-items: center;
margin: 0;
padding: 1rem 1.5rem;
color: $background;
font-size: 1.4em;
font-weight: 300;
&.title { font-size: 1.8em; }
> *:first-child { width: 3rem; }
> img:first-child { height: 3rem; }
> *:last-child { margin-left: 1rem; }
> nav hr {
display: block;
margin: 0;
width: 100%;
border: solid $background 0.1rem;
}
.mobile-label { display: initial; }
}
}
}
main .article-meta {
> *, .comments {
margin: 0 5%;
+90
View File
@@ -101,6 +101,96 @@ body > header {
}
}
/// Small screens
@media screen and (max-width: 600px) {
@keyframes menuOpening {
from {
transform: scaleX(0);
transform-origin: left;
opacity: 0;
}
to {
transform: scaleX(1);
transform-origin: left;
opacity: 1;
}
}
body > header {
flex-direction: column;
nav#menu {
display: inline-flex;
z-index: 21;
}
#content {
display: none;
appearance: none;
text-align: center;
z-index: 20;
}
}
body > header:focus-within #content, #content.show {
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;
&::before {
content: "";
position: absolute;
transform: skewX(-10deg);
top: 0;
left: -20%;
width: 100%;
height: 100%;
z-index: -10;
background: $primary;
}
> nav {
flex-direction: column;
align-items: flex-start;
a {
display: flex;
flex-direction: row;
align-items: center;
margin: 0;
padding: 1rem 1.5rem;
color: $background;
font-size: 1.4em;
font-weight: 300;
&.title { font-size: 1.8em; }
> *:first-child { width: 3rem; }
> img:first-child { height: 3rem; }
> *:last-child { margin-left: 1rem; }
> nav hr {
display: block;
margin: 0;
width: 100%;
border: solid $background 0.1rem;
}
.mobile-label { display: initial; }
}
}
}
}
/* Only enable label animations on large screens */
@media screen and (min-width: 600px) {
header nav a {
+3 -3
View File
@@ -1,8 +1,8 @@
extern crate rsass;
extern crate ructe;
use rsass;
use ructe::Ructe;
use std::process::{Command, Stdio};
use std::{env, ffi::OsStr, fs::*, io::Write, path::*};
use std::{ffi::OsStr, fs::*, io::Write, path::*};
fn compute_static_hash() -> String {
//"find static/ -type f ! -path 'static/media/*' | sort | xargs stat -c'%n %Y' | openssl dgst -r"
+1
View File
@@ -2,6 +2,7 @@
name = "plume-api"
version = "0.4.0"
authors = ["Plume contributors"]
edition = "2018"
[dependencies]
serde = "1.0"
-1
View File
@@ -1,4 +1,3 @@
extern crate serde;
#[macro_use]
extern crate serde_derive;
+1
View File
@@ -2,6 +2,7 @@
name = "plume-cli"
version = "0.4.0"
authors = ["Plume contributors"]
edition = "2018"
[[bin]]
name = "plm"
+1 -5
View File
@@ -1,8 +1,4 @@
extern crate clap;
extern crate diesel;
extern crate dotenv;
extern crate plume_models;
extern crate rpassword;
use dotenv;
use clap::App;
use diesel::Connection;
+1
View File
@@ -2,6 +2,7 @@
name = "plume-common"
version = "0.4.0"
authors = ["Plume contributors"]
edition = "2018"
[dependencies]
activitypub = "0.1.1"
+1 -1
View File
@@ -64,7 +64,7 @@ impl<T> ActivityStream<T> {
}
impl<'r, O: Object> Responder<'r> for ActivityStream<O> {
fn respond_to(self, request: &Request) -> Result<Response<'r>, Status> {
fn respond_to(self, request: &Request<'_>) -> Result<Response<'r>, Status> {
let mut json = serde_json::to_value(&self.0).map_err(|_| Status::InternalServerError)?;
json["@context"] = context();
serde_json::to_string(&json).respond_to(request).map(|r| {
+2 -2
View File
@@ -5,8 +5,8 @@ use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, DATE, USER_A
use std::ops::Deref;
use std::time::SystemTime;
use activity_pub::sign::Signer;
use activity_pub::{ap_accept_header, AP_CONTENT_TYPE};
use crate::activity_pub::sign::Signer;
use crate::activity_pub::{ap_accept_header, AP_CONTENT_TYPE};
const PLUME_USER_AGENT: &str = concat!("Plume/", env!("CARGO_PKG_VERSION"));
+1 -1
View File
@@ -131,7 +131,7 @@ impl SignatureValidity {
pub fn verify_http_headers<S: Signer + ::std::fmt::Debug>(
sender: &S,
all_headers: &HeaderMap,
all_headers: &HeaderMap<'_>,
data: &request::Digest,
) -> SignatureValidity {
let sig_header = all_headers.get_one("Signature");
+4 -15
View File
@@ -1,27 +1,16 @@
#![feature(custom_attribute, associated_type_defaults)]
#![feature(associated_type_defaults)]
extern crate activitypub;
#[macro_use]
extern crate activitystreams_derive;
extern crate activitystreams_traits;
extern crate array_tool;
extern crate base64;
extern crate chrono;
extern crate heck;
extern crate hex;
extern crate openssl;
extern crate pulldown_cmark;
extern crate reqwest;
extern crate rocket;
extern crate serde;
use activitystreams_traits;
use serde;
#[macro_use]
extern crate shrinkwraprs;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate syntect;
extern crate tokio;
pub mod activity_pub;
pub mod utils;
+8 -8
View File
@@ -48,7 +48,7 @@ enum State {
Ready,
}
fn to_inline(tag: Tag) -> Tag {
fn to_inline(tag: Tag<'_>) -> Tag<'_> {
match tag {
Tag::Header(_) | Tag::Table(_) | Tag::TableHead | Tag::TableRow | Tag::TableCell => {
Tag::Paragraph
@@ -146,7 +146,7 @@ fn inline_tags<'a>(
}
}
pub type MediaProcessor<'a> = Box<'a + Fn(i32) -> Option<(String, Option<String>)>>;
pub type MediaProcessor<'a> = Box<dyn 'a + Fn(i32) -> Option<(String, Option<String>)>>;
fn process_image<'a, 'b>(
evt: Event<'a>,
@@ -157,9 +157,7 @@ fn process_image<'a, 'b>(
match evt {
Event::Start(Tag::Image(id, title)) => {
if let Some((url, cw)) = id.parse::<i32>().ok().and_then(processor.as_ref()) {
if inline || cw.is_none() {
Event::Start(Tag::Image(Cow::Owned(url), title))
} else {
if let (Some(cw), false) = (cw, inline) {
// there is a cw, and where are not inline
Event::Html(Cow::Owned(format!(
r#"<label for="postcontent-cw-{id}">
@@ -170,9 +168,11 @@ fn process_image<'a, 'b>(
</span>
<img src="{url}" alt=""#,
id = random_hex(),
cw = cw.unwrap(),
cw = cw,
url = url
)))
} else {
Event::Start(Tag::Image(Cow::Owned(url), title))
}
} else {
Event::Start(Tag::Image(id, title))
@@ -214,7 +214,7 @@ pub fn md_to_html<'a>(
};
let parser = Parser::new_ext(md, Options::all());
let (parser, mentions, hashtags): (Vec<Event>, Vec<String>, Vec<String>) = parser
let (parser, mentions, hashtags): (Vec<Event<'_>>, Vec<String>, Vec<String>) = parser
// Flatten text because pulldown_cmark break #hashtag in two individual text elements
.scan(None, flatten_text)
.flatten()
@@ -247,7 +247,7 @@ pub fn md_to_html<'a>(
text_acc.push(c)
}
let mention = text_acc;
let short_mention = mention.splitn(1, '@').nth(0).unwrap_or("");
let short_mention = mention.splitn(1, '@').next().unwrap_or("");
let link = Tag::Link(
format!("{}@/{}/", base_url, &mention).into(),
short_mention.to_owned().into(),
+1
View File
@@ -2,6 +2,7 @@
name = "plume-front"
version = "0.4.0"
authors = ["Plume contributors"]
edition = "2018"
[dependencies]
stdweb = "=0.4.18"
+1 -1
View File
@@ -1,3 +1,4 @@
use crate::CATALOG;
use serde::{Deserialize, Serialize};
use serde_json;
use std::sync::Mutex;
@@ -5,7 +6,6 @@ use stdweb::{
unstable::{TryFrom, TryInto},
web::{event::*, html_element::*, *},
};
use CATALOG;
macro_rules! mv {
( $( $var:ident ),* => $exp:expr ) => {
-3
View File
@@ -1,15 +1,12 @@
#![recursion_limit = "128"]
#![feature(decl_macro, proc_macro_hygiene, try_trait)]
extern crate gettext;
#[macro_use]
extern crate gettext_macros;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate stdweb;
extern crate serde;
extern crate serde_json;
use stdweb::web::{event::*, *};
init_i18n!(
+11 -14
View File
@@ -1,8 +1,7 @@
#![recursion_limit = "128"]
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
@@ -103,19 +102,17 @@ fn file_to_migration(file: &str) -> TokenStream2 {
acc.push_str(line);
acc.push('\n');
}
} else if line.starts_with("--#!") {
acc.push_str(&line[4..]);
acc.push('\n');
} else if line.starts_with("--") {
continue;
} else {
if line.starts_with("--#!") {
acc.push_str(&line[4..]);
acc.push('\n');
} else if line.starts_with("--") {
continue;
} else {
let func: TokenStream2 = trampoline(TokenStream::from_str(&acc).unwrap().into());
actions.push(quote!(Action::Function(&#func)));
sql = true;
acc = line.to_string();
acc.push('\n');
}
let func: TokenStream2 = trampoline(TokenStream::from_str(&acc).unwrap().into());
actions.push(quote!(Action::Function(&#func)));
sql = true;
acc = line.to_string();
acc.push('\n');
}
}
if !acc.trim().is_empty() {
+2 -1
View File
@@ -2,6 +2,7 @@
name = "plume-models"
version = "0.4.0"
authors = ["Plume contributors"]
edition = "2018"
[dependencies]
activitypub = "0.1.1"
@@ -11,7 +12,7 @@ bcrypt = "0.5"
guid-create = "0.1"
heck = "0.3.0"
itertools = "0.8.0"
lazy_static = "*"
lazy_static = "1.0"
migrations_internals= "1.4.0"
openssl = "0.10.22"
rocket = "0.4.0"
+1 -2
View File
@@ -1,11 +1,10 @@
use crate::users::User;
use rocket::{
http::Status,
request::{self, FromRequest, Request},
Outcome,
};
use users::User;
/// Wrapper around User to use as a request guard on pages reserved to admins.
pub struct Admin(pub User);
+1 -4
View File
@@ -1,3 +1,4 @@
use crate::{db_conn::DbConn, schema::api_tokens, Error, Result};
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use rocket::{
@@ -6,10 +7,6 @@ use rocket::{
Outcome,
};
use db_conn::DbConn;
use schema::api_tokens;
use {Error, Result};
#[derive(Clone, Queryable)]
pub struct ApiToken {
pub id: i32,
+1 -3
View File
@@ -1,9 +1,7 @@
use crate::{schema::apps, Error, Result};
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use schema::apps;
use {Error, Result};
#[derive(Clone, Queryable, Serialize)]
pub struct App {
pub id: i32,
+3 -6
View File
@@ -1,9 +1,7 @@
use crate::{schema::email_blocklist, Connection, Error, Result};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, TextExpressionMethods};
use glob::Pattern;
use schema::email_blocklist;
use {Connection, Error, Result};
#[derive(Clone, Queryable, Identifiable)]
#[table_name = "email_blocklist"]
pub struct BlocklistedEmail {
@@ -89,10 +87,9 @@ impl BlocklistedEmail {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::{instance::tests as instance_tests, tests::rockets, Connection as Conn};
use diesel::Connection;
use instance::tests as instance_tests;
use tests::rockets;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> Vec<BlocklistedEmail> {
instance_tests::fill_database(conn);
let domainblock =
+1 -3
View File
@@ -1,8 +1,6 @@
use crate::{schema::blog_authors, Error, Result};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use schema::blog_authors;
use {Error, Result};
#[derive(Clone, Queryable, Identifiable)]
pub struct BlogAuthor {
pub id: i32,
+20 -23
View File
@@ -1,3 +1,7 @@
use crate::{
ap_url, instance::*, medias::Media, posts::Post, safe_string::SafeString, schema::blogs,
search::Searcher, users::User, Connection, Error, PlumeRocket, Result, ITEMS_PER_PAGE,
};
use activitypub::{
actor::Group,
collection::{OrderedCollection, OrderedCollectionPage},
@@ -12,22 +16,13 @@ use openssl::{
rsa::Rsa,
sign::{Signer, Verifier},
};
use serde_json;
use url::Url;
use webfinger::*;
use instance::*;
use medias::Media;
use plume_common::activity_pub::{
inbox::{AsActor, FromId},
sign, ActivityStream, ApSignature, Id, IntoId, PublicKey, Source,
};
use posts::Post;
use safe_string::SafeString;
use schema::blogs;
use search::Searcher;
use users::User;
use {ap_url, Connection, Error, PlumeRocket, Result, ITEMS_PER_PAGE};
use serde_json;
use url::Url;
use webfinger::*;
pub type CustomGroup = CustomObject<ApSignature, Group>;
@@ -106,8 +101,8 @@ impl Blog {
}
pub fn list_authors(&self, conn: &Connection) -> Result<Vec<User>> {
use schema::blog_authors;
use schema::users;
use crate::schema::blog_authors;
use crate::schema::users;
let authors_ids = blog_authors::table
.filter(blog_authors::blog_id.eq(self.id))
.select(blog_authors::author_id);
@@ -118,7 +113,7 @@ impl Blog {
}
pub fn count_authors(&self, conn: &Connection) -> Result<i64> {
use schema::blog_authors;
use crate::schema::blog_authors;
blog_authors::table
.filter(blog_authors::blog_id.eq(self.id))
.count()
@@ -127,7 +122,7 @@ impl Blog {
}
pub fn find_for_author(conn: &Connection, author: &User) -> Result<Vec<Blog>> {
use schema::blog_authors;
use crate::schema::blog_authors;
let author_ids = blog_authors::table
.filter(blog_authors::author_id.eq(author.id))
.select(blog_authors::blog_id);
@@ -501,14 +496,16 @@ impl NewBlog {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use blog_authors::*;
use crate::{
blog_authors::*,
instance::tests as instance_tests,
medias::NewMedia,
search::tests::get_searcher,
tests::{db, rockets},
users::tests as usersTests,
Connection as Conn,
};
use diesel::Connection;
use instance::tests as instance_tests;
use medias::NewMedia;
use search::tests::get_searcher;
use tests::{db, rockets};
use users::tests as usersTests;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> (Vec<User>, Vec<Blog>) {
instance_tests::fill_database(conn);
+1 -5
View File
@@ -1,10 +1,6 @@
use crate::{comments::Comment, schema::comment_seers, users::User, Connection, Error, Result};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use comments::Comment;
use schema::comment_seers;
use users::User;
use {Connection, Error, Result};
#[derive(Queryable, Clone)]
pub struct CommentSeers {
pub id: i32,
+23 -22
View File
@@ -1,3 +1,15 @@
use crate::{
comment_seers::{CommentSeers, NewCommentSeers},
instance::Instance,
medias::Media,
mentions::Mention,
notifications::*,
posts::Post,
safe_string::SafeString,
schema::comments,
users::User,
Connection, Error, PlumeRocket, Result,
};
use activitypub::{
activity::{Create, Delete},
link,
@@ -5,25 +17,15 @@ use activitypub::{
};
use chrono::{self, NaiveDateTime};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
use serde_json;
use std::collections::HashSet;
use comment_seers::{CommentSeers, NewCommentSeers};
use instance::Instance;
use medias::Media;
use mentions::Mention;
use notifications::*;
use plume_common::activity_pub::{
inbox::{AsActor, AsObject, FromId},
Id, IntoId, PUBLIC_VISIBILITY,
use plume_common::{
activity_pub::{
inbox::{AsActor, AsObject, FromId},
Id, IntoId, PUBLIC_VISIBILITY,
},
utils,
};
use plume_common::utils;
use posts::Post;
use safe_string::SafeString;
use schema::comments;
use users::User;
use {Connection, Error, PlumeRocket, Result};
use serde_json;
use std::collections::HashSet;
#[derive(Queryable, Identifiable, Clone, AsChangeset)]
pub struct Comment {
@@ -77,7 +79,7 @@ impl Comment {
}
pub fn count_local(conn: &Connection) -> Result<i64> {
use schema::users;
use crate::schema::users;
let local_authors = users::table
.filter(users::instance_id.eq(Instance::get_local()?.id))
.select(users::id);
@@ -127,9 +129,8 @@ impl Comment {
)?))?;
note.object_props
.set_published_string(chrono::Utc::now().to_rfc3339())?;
note.object_props
.set_attributed_to_link(author.clone().into_id())?;
note.object_props.set_to_link_vec(to.clone())?;
note.object_props.set_attributed_to_link(author.into_id())?;
note.object_props.set_to_link_vec(to)?;
note.object_props.set_tag_link_vec(
mentions
.into_iter()
+2 -4
View File
@@ -1,3 +1,4 @@
use crate::Connection;
use diesel::r2d2::{
ConnectionManager, CustomizeConnection, Error as ConnError, Pool, PooledConnection,
};
@@ -10,8 +11,6 @@ use rocket::{
};
use std::ops::Deref;
use Connection;
pub type DbPool = Pool<ConnectionManager<Connection>>;
// From rocket documentation
@@ -26,7 +25,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for DbConn {
type Error = ();
fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
let pool = request.guard::<State<DbPool>>()?;
let pool = request.guard::<State<'_, DbPool>>()?;
match pool.get() {
Ok(conn) => Outcome::Success(DbConn(conn)),
Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
@@ -73,5 +72,4 @@ pub(crate) mod tests {
Ok(conn.begin_test_transaction().unwrap())
}
}
}
+6 -9
View File
@@ -1,16 +1,15 @@
use crate::{
ap_url, notifications::*, schema::follows, users::User, Connection, Error, PlumeRocket, Result,
CONFIG,
};
use activitypub::activity::{Accept, Follow as FollowAct, Undo};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
use notifications::*;
use plume_common::activity_pub::{
broadcast,
inbox::{AsActor, AsObject, FromId},
sign::Signer,
Id, IntoId, PUBLIC_VISIBILITY,
};
use schema::follows;
use users::User;
use {ap_url, Connection, Error, PlumeRocket, Result, CONFIG};
#[derive(Clone, Queryable, Identifiable, Associations, AsChangeset)]
#[belongs_to(User, foreign_key = "following_id")]
@@ -56,8 +55,7 @@ impl Follow {
let target = User::get(conn, self.following_id)?;
let mut act = FollowAct::default();
act.follow_props
.set_actor_link::<Id>(user.clone().into_id())?;
act.follow_props.set_actor_link::<Id>(user.into_id())?;
act.follow_props
.set_object_link::<Id>(target.clone().into_id())?;
act.object_props.set_id_string(self.ap_url.clone())?;
@@ -202,9 +200,8 @@ impl IntoId for Follow {
#[cfg(test)]
mod tests {
use super::*;
use crate::{tests::db, users::tests as user_tests};
use diesel::Connection;
use tests::db;
use users::tests as user_tests;
#[test]
fn test_id() {
+10 -10
View File
@@ -1,14 +1,15 @@
use crate::{
ap_url,
medias::Media,
safe_string::SafeString,
schema::{instances, users},
users::{Role, User},
Connection, Error, Result,
};
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use std::sync::RwLock;
use ap_url;
use medias::Media;
use plume_common::utils::md_to_html;
use safe_string::SafeString;
use schema::{instances, users};
use users::{Role, User};
use {Connection, Error, Result};
use std::sync::RwLock;
#[derive(Clone, Identifiable, Queryable)]
pub struct Instance {
@@ -242,9 +243,8 @@ impl Instance {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::{tests::db, Connection as Conn};
use diesel::Connection;
use tests::db;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> Vec<(NewInstance, Instance)> {
let res = vec![
+5 -29
View File
@@ -1,43 +1,21 @@
#![feature(try_trait)]
#![feature(never_type)]
#![feature(custom_attribute)]
#![feature(proc_macro_hygiene)]
extern crate activitypub;
extern crate ammonia;
extern crate askama_escape;
extern crate bcrypt;
extern crate chrono;
#[macro_use]
extern crate diesel;
extern crate guid_create;
extern crate heck;
extern crate itertools;
#[macro_use]
extern crate lazy_static;
extern crate migrations_internals;
extern crate openssl;
extern crate plume_api;
extern crate plume_common;
#[macro_use]
extern crate plume_macro;
extern crate reqwest;
#[macro_use]
extern crate rocket;
extern crate rocket_i18n;
extern crate scheduled_thread_pool;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate tantivy;
extern crate glob;
extern crate url;
extern crate walkdir;
extern crate webfinger;
extern crate whatlang;
use plume_common::activity_pub::inbox::InboxError;
@@ -250,12 +228,13 @@ macro_rules! get {
/// Model::insert(connection, NewModelType::new());
/// ```
macro_rules! insert {
($table:ident, $from:ident) => {
($table:ident, $from:ty) => {
insert!($table, $from, |x, _conn| Ok(x));
};
($table:ident, $from:ident, |$val:ident, $conn:ident | $( $after:tt )+) => {
($table:ident, $from:ty, |$val:ident, $conn:ident | $( $after:tt )+) => {
last!($table);
#[allow(dead_code)]
pub fn insert(conn: &crate::Connection, new: $from) -> Result<Self> {
diesel::insert_into($table::table)
.values(new)
@@ -282,6 +261,7 @@ macro_rules! insert {
/// ```
macro_rules! last {
($table:ident) => {
#[allow(dead_code)]
pub fn last(conn: &crate::Connection) -> Result<Self> {
$table::table
.order_by($table::id.desc())
@@ -301,16 +281,12 @@ pub fn ap_url(url: &str) -> String {
#[cfg(test)]
#[macro_use]
mod tests {
use db_conn;
use crate::{db_conn, migrations::IMPORTED_MIGRATIONS, search, Connection as Conn, CONFIG};
use diesel::r2d2::ConnectionManager;
use migrations::IMPORTED_MIGRATIONS;
use plume_common::utils::random_hex;
use scheduled_thread_pool::ScheduledThreadPool;
use search;
use std::env::temp_dir;
use std::sync::Arc;
use Connection as Conn;
use CONFIG;
#[macro_export]
macro_rules! part_eq {
+4 -7
View File
@@ -1,17 +1,14 @@
use crate::{
notifications::*, posts::Post, schema::likes, timeline::*, users::User, Connection, Error,
PlumeRocket, Result,
};
use activitypub::activity;
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use notifications::*;
use plume_common::activity_pub::{
inbox::{AsActor, AsObject, FromId},
Id, IntoId, PUBLIC_VISIBILITY,
};
use posts::Post;
use schema::likes;
use timeline::*;
use users::User;
use {Connection, Error, PlumeRocket, Result};
#[derive(Clone, Queryable, Identifiable)]
pub struct Like {
+9 -10
View File
@@ -1,10 +1,11 @@
use crate::{
blogs::Blog,
schema::{blogs, list_elems, lists, users},
users::User,
Connection, Error, Result,
};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use blogs::Blog;
use schema::{blogs, list_elems, lists, users};
use std::convert::{TryFrom, TryInto};
use users::User;
use {Connection, Error, Result};
/// Represent what a list is supposed to store. Represented in database as an integer
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -164,7 +165,7 @@ impl List {
last!(lists);
get!(lists);
fn insert(conn: &Connection, val: NewList) -> Result<Self> {
fn insert(conn: &Connection, val: NewList<'_>) -> Result<Self> {
diesel::insert_into(lists::table)
.values(val)
.execute(conn)?;
@@ -309,7 +310,7 @@ mod private {
};
impl ListElem {
insert!(list_elems, NewListElem);
insert!(list_elems, NewListElem<'_>);
pub fn user_in_list(conn: &Connection, list: &List, user: i32) -> Result<bool> {
dsl::select(dsl::exists(
@@ -359,9 +360,8 @@ mod private {
#[cfg(test)]
mod tests {
use super::*;
use blogs::tests as blog_tests;
use crate::{blogs::tests as blog_tests, tests::db};
use diesel::Connection;
use tests::db;
#[test]
fn list_type() {
@@ -551,5 +551,4 @@ mod tests {
Ok(())
});
}
}
+14 -15
View File
@@ -1,20 +1,17 @@
use crate::{
ap_url, instance::Instance, safe_string::SafeString, schema::medias, users::User, Connection,
Error, PlumeRocket, Result,
};
use activitypub::object::Image;
use askama_escape::escape;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use guid_create::GUID;
use reqwest;
use std::{fs, path::Path};
use plume_common::{
activity_pub::{inbox::FromId, Id},
utils::MediaProcessor,
};
use instance::Instance;
use safe_string::SafeString;
use schema::medias;
use users::User;
use {ap_url, Connection, Error, PlumeRocket, Result};
use reqwest;
use std::{fs, path::Path};
#[derive(Clone, Identifiable, Queryable)]
pub struct Media {
@@ -117,15 +114,19 @@ impl Media {
Ok(match self.category() {
MediaCategory::Image => SafeString::trusted(&format!(
r#"<img src="{}" alt="{}" title="{}">"#,
url, escape(&self.alt_text), escape(&self.alt_text)
url,
escape(&self.alt_text),
escape(&self.alt_text)
)),
MediaCategory::Audio => SafeString::trusted(&format!(
r#"<div class="media-preview audio"></div><audio src="{}" title="{}" controls></audio>"#,
url, escape(&self.alt_text)
url,
escape(&self.alt_text)
)),
MediaCategory::Video => SafeString::trusted(&format!(
r#"<video src="{}" title="{}" controls></video>"#,
url, escape(&self.alt_text)
url,
escape(&self.alt_text)
)),
MediaCategory::Unknown => SafeString::trusted(&format!(
r#"<a href="{}" class="media-preview unknown"></a>"#,
@@ -259,13 +260,11 @@ impl Media {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::{tests::db, users::tests as usersTests, Connection as Conn};
use diesel::Connection;
use std::env::{current_dir, set_current_dir};
use std::fs;
use std::path::Path;
use tests::db;
use users::tests as usersTests;
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> (Vec<User>, Vec<Media>) {
let mut wd = current_dir().unwrap().to_path_buf();
+4 -8
View File
@@ -1,14 +1,10 @@
use crate::{
comments::Comment, notifications::*, posts::Post, schema::mentions, users::User, Connection,
Error, PlumeRocket, Result,
};
use activitypub::link;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use comments::Comment;
use notifications::*;
use plume_common::activity_pub::inbox::AsActor;
use posts::Post;
use schema::mentions;
use users::User;
use PlumeRocket;
use {Connection, Error, Result};
#[derive(Clone, Queryable, Identifiable)]
pub struct Mention {
+2 -6
View File
@@ -1,16 +1,12 @@
use Connection;
use Error;
use Result;
use crate::{Connection, Error, Result};
use diesel::connection::{Connection as Conn, SimpleConnection};
use migrations_internals::{setup_database, MigrationConnection};
use std::path::Path;
#[allow(dead_code)] //variants might not be constructed if not required by current migrations
enum Action {
Sql(&'static str),
Function(&'static Fn(&Connection, &Path) -> Result<()>),
Function(&'static dyn Fn(&Connection, &Path) -> Result<()>),
}
impl Action {
+11 -10
View File
@@ -1,16 +1,17 @@
use crate::{
comments::Comment,
follows::Follow,
likes::Like,
mentions::Mention,
posts::Post,
reshares::Reshare,
schema::{follows, notifications},
users::User,
Connection, Error, Result,
};
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, JoinOnDsl, QueryDsl, RunQueryDsl};
use comments::Comment;
use follows::Follow;
use likes::Like;
use mentions::Mention;
use posts::Post;
use reshares::Reshare;
use schema::{follows, notifications};
use users::User;
use {Connection, Error, Result};
pub mod notification_kind {
pub const COMMENT: &str = "COMMENT";
pub const FOLLOW: &str = "FOLLOW";
+2 -4
View File
@@ -1,7 +1,6 @@
use crate::{schema::password_reset_requests, Connection, Error, Result};
use chrono::{offset::Utc, Duration, NaiveDateTime};
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use schema::password_reset_requests;
use {Connection, Error, Result};
#[derive(Clone, Identifiable, Queryable)]
pub struct PasswordResetRequest {
@@ -75,9 +74,8 @@ impl PasswordResetRequest {
#[cfg(test)]
mod tests {
use super::*;
use crate::{tests::db, users::tests as user_tests};
use diesel::Connection;
use tests::db;
use users::tests as user_tests;
#[test]
fn test_insert_and_find_password_reset_request() {
+7 -11
View File
@@ -2,9 +2,7 @@ pub use self::module::PlumeRocket;
#[cfg(not(test))]
mod module {
use crate::db_conn::DbConn;
use crate::search;
use crate::users;
use crate::{db_conn::DbConn, search, users};
use rocket::{
request::{self, FlashMessage, FromRequest, Request},
Outcome, State,
@@ -29,9 +27,9 @@ mod module {
let conn = request.guard::<DbConn>()?;
let intl = request.guard::<rocket_i18n::I18n>()?;
let user = request.guard::<users::User>().succeeded();
let worker = request.guard::<State<Arc<ScheduledThreadPool>>>()?;
let searcher = request.guard::<State<Arc<search::Searcher>>>()?;
let flash_msg = request.guard::<FlashMessage>().succeeded();
let worker = request.guard::<'_, State<'_, Arc<ScheduledThreadPool>>>()?;
let searcher = request.guard::<'_, State<'_, Arc<search::Searcher>>>()?;
let flash_msg = request.guard::<FlashMessage<'_, '_>>().succeeded();
Outcome::Success(PlumeRocket {
conn,
intl,
@@ -46,9 +44,7 @@ mod module {
#[cfg(test)]
mod module {
use crate::db_conn::DbConn;
use crate::search;
use crate::users;
use crate::{db_conn::DbConn, search, users};
use rocket::{
request::{self, FromRequest, Request},
Outcome, State,
@@ -70,8 +66,8 @@ mod module {
fn from_request(request: &'a Request<'r>) -> request::Outcome<PlumeRocket, ()> {
let conn = request.guard::<DbConn>()?;
let user = request.guard::<users::User>().succeeded();
let worker = request.guard::<State<Arc<ScheduledThreadPool>>>()?;
let searcher = request.guard::<State<Arc<search::Searcher>>>()?;
let worker = request.guard::<'_, State<'_, Arc<ScheduledThreadPool>>>()?;
let searcher = request.guard::<'_, State<'_, Arc<search::Searcher>>>()?;
Outcome::Success(PlumeRocket {
conn,
user,
+1 -5
View File
@@ -1,10 +1,6 @@
use crate::{posts::Post, schema::post_authors, users::User, Error, Result};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use posts::Post;
use schema::post_authors;
use users::User;
use {Error, Result};
#[derive(Clone, Queryable, Identifiable, Associations)]
#[belongs_to(Post)]
#[belongs_to(User, foreign_key = "author_id")]
+22 -30
View File
@@ -1,3 +1,8 @@
use crate::{
ap_url, blogs::Blog, instance::Instance, medias::Media, mentions::Mention, post_authors::*,
safe_string::SafeString, schema::posts, search::Searcher, tags::*, timeline::*, users::User,
Connection, Error, PlumeRocket, Result, CONFIG,
};
use activitypub::{
activity::{Create, Delete, Update},
link,
@@ -7,13 +12,6 @@ use activitypub::{
use chrono::{NaiveDateTime, TimeZone, Utc};
use diesel::{self, BelongingToDsl, ExpressionMethods, QueryDsl, RunQueryDsl, SaveChangesDsl};
use heck::{CamelCase, KebabCase};
use serde_json;
use std::collections::HashSet;
use blogs::Blog;
use instance::Instance;
use medias::Media;
use mentions::Mention;
use plume_common::{
activity_pub::{
inbox::{AsObject, FromId},
@@ -21,14 +19,8 @@ use plume_common::{
},
utils::md_to_html,
};
use post_authors::*;
use safe_string::SafeString;
use schema::posts;
use search::Searcher;
use tags::*;
use timeline::*;
use users::User;
use {ap_url, Connection, Error, PlumeRocket, Result, CONFIG};
use serde_json;
use std::collections::HashSet;
pub type LicensedArticle = CustomObject<Licensed, Article>;
@@ -111,7 +103,7 @@ impl Post {
tag: String,
(min, max): (i32, i32),
) -> Result<Vec<Post>> {
use schema::tags;
use crate::schema::tags;
let ids = tags::table.filter(tags::tag.eq(tag)).select(tags::post_id);
posts::table
@@ -125,7 +117,7 @@ impl Post {
}
pub fn count_for_tag(conn: &Connection, tag: String) -> Result<i64> {
use schema::tags;
use crate::schema::tags;
let ids = tags::table.filter(tags::tag.eq(tag)).select(tags::post_id);
posts::table
.filter(posts::id.eq_any(ids))
@@ -139,8 +131,8 @@ impl Post {
}
pub fn count_local(conn: &Connection) -> Result<i64> {
use schema::post_authors;
use schema::users;
use crate::schema::post_authors;
use crate::schema::users;
let local_authors = users::table
.filter(users::instance_id.eq(Instance::get_local()?.id))
.select(users::id);
@@ -188,7 +180,7 @@ impl Post {
author: &User,
limit: i64,
) -> Result<Vec<Post>> {
use schema::post_authors;
use crate::schema::post_authors;
let posts = PostAuthor::belonging_to(author).select(post_authors::post_id);
posts::table
@@ -239,7 +231,7 @@ impl Post {
}
pub fn drafts_by_author(conn: &Connection, author: &User) -> Result<Vec<Post>> {
use schema::post_authors;
use crate::schema::post_authors;
let posts = PostAuthor::belonging_to(author).select(post_authors::post_id);
posts::table
@@ -251,8 +243,8 @@ impl Post {
}
pub fn get_authors(&self, conn: &Connection) -> Result<Vec<User>> {
use schema::post_authors;
use schema::users;
use crate::schema::post_authors;
use crate::schema::users;
let author_list = PostAuthor::belonging_to(self).select(post_authors::author_id);
users::table
.filter(users::id.eq_any(author_list))
@@ -261,7 +253,7 @@ impl Post {
}
pub fn is_author(&self, conn: &Connection, author_id: i32) -> Result<bool> {
use schema::post_authors;
use crate::schema::post_authors;
Ok(PostAuthor::belonging_to(self)
.filter(post_authors::author_id.eq(author_id))
.count()
@@ -270,7 +262,7 @@ impl Post {
}
pub fn get_blog(&self, conn: &Connection) -> Result<Blog> {
use schema::blogs;
use crate::schema::blogs;
blogs::table
.filter(blogs::id.eq(self.blog_id))
.first(conn)
@@ -278,7 +270,7 @@ impl Post {
}
pub fn count_likes(&self, conn: &Connection) -> Result<i64> {
use schema::likes;
use crate::schema::likes;
likes::table
.filter(likes::post_id.eq(self.id))
.count()
@@ -287,7 +279,7 @@ impl Post {
}
pub fn count_reshares(&self, conn: &Connection) -> Result<i64> {
use schema::reshares;
use crate::schema::reshares;
reshares::table
.filter(reshares::post_id.eq(self.id))
.count()
@@ -632,7 +624,7 @@ impl FromId<PlumeRocket> for Post {
.into_iter()
.map(|s| s.to_camel_case())
.collect::<HashSet<_>>();
if let Some(serde_json::Value::Array(tags)) = article.object_props.tag.clone() {
if let Some(serde_json::Value::Array(tags)) = article.object_props.tag {
for tag in tags {
serde_json::from_value::<link::Mention>(tag.clone())
.map(|m| Mention::from_activity(conn, &m, post.id, true, true))
@@ -725,7 +717,7 @@ impl FromId<PlumeRocket> for PostUpdate {
.ok()
.map(|x| x.content),
license: updated.custom_props.license_string().ok(),
tags: updated.object.object_props.tag.clone(),
tags: updated.object.object_props.tag,
})
}
}
@@ -806,7 +798,7 @@ impl AsObject<User, Update, &PlumeRocket> for PostUpdate {
impl IntoId for Post {
fn into_id(self) -> Id {
Id::new(self.ap_url.clone())
Id::new(self.ap_url)
}
}
+4 -7
View File
@@ -1,17 +1,14 @@
use crate::{
notifications::*, posts::Post, schema::reshares, timeline::*, users::User, Connection, Error,
PlumeRocket, Result,
};
use activitypub::activity::{Announce, Undo};
use chrono::NaiveDateTime;
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use notifications::*;
use plume_common::activity_pub::{
inbox::{AsActor, AsObject, FromId},
Id, IntoId, PUBLIC_VISIBILITY,
};
use posts::Post;
use schema::reshares;
use timeline::*;
use users::User;
use {Connection, Error, PlumeRocket, Result};
#[derive(Clone, Queryable, Identifiable)]
pub struct Reshare {
+4 -4
View File
@@ -82,7 +82,7 @@ lazy_static! {
};
}
fn url_add_prefix(url: &str) -> Option<Cow<str>> {
fn url_add_prefix(url: &str) -> Option<Cow<'_, str>> {
if url.starts_with('#') && !url.starts_with("#postcontent-") {
//if start with an #
let mut new_url = "#postcontent-".to_owned(); //change to valid id
@@ -139,7 +139,7 @@ struct SafeStringVisitor;
impl<'de> Visitor<'de> for SafeStringVisitor {
type Value = SafeString;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string")
}
@@ -181,7 +181,7 @@ where
DB: diesel::backend::Backend,
str: ToSql<diesel::sql_types::Text, DB>,
{
fn to_sql<W: Write>(&self, out: &mut Output<W, DB>) -> serialize::Result {
fn to_sql<W: Write>(&self, out: &mut Output<'_, W, DB>) -> serialize::Result {
str::to_sql(&self.value, out)
}
}
@@ -193,7 +193,7 @@ impl Borrow<str> for SafeString {
}
impl Display for SafeString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
+8 -6
View File
@@ -8,15 +8,17 @@ pub use self::searcher::*;
pub(crate) mod tests {
use super::{Query, Searcher};
use diesel::Connection;
use plume_common::utils::random_hex;
use std::env::temp_dir;
use std::str::FromStr;
use blogs::tests::fill_database;
use plume_common::utils::random_hex;
use post_authors::*;
use posts::{NewPost, Post};
use safe_string::SafeString;
use tests::db;
use crate::{
blogs::tests::fill_database,
post_authors::*,
posts::{NewPost, Post},
safe_string::SafeString,
tests::db,
};
pub(crate) fn get_searcher() -> Searcher {
let dir = temp_dir().join(&format!("plume-test-{}", random_hex()));
+3 -3
View File
@@ -1,5 +1,5 @@
use crate::search::searcher::Searcher;
use chrono::{naive::NaiveDate, offset::Utc, Datelike};
use search::searcher::Searcher;
use std::{cmp, ops::Bound};
use tantivy::{query::*, schema::*, Term};
@@ -153,7 +153,7 @@ impl PlumeQuery {
/// Convert this Query to a Tantivy Query
pub fn into_query(self) -> BooleanQuery {
let mut result: Vec<(Occur, Box<Query>)> = Vec::new();
let mut result: Vec<(Occur, Box<dyn Query>)> = Vec::new();
gen_to_query!(self, result; normal: title, subtitle, content, tag;
oneoff: instance, author, blog, lang, license);
@@ -279,7 +279,7 @@ impl PlumeQuery {
}
// map a token and it's field to a query
fn token_to_query(token: &str, field_name: &str) -> Box<Query> {
fn token_to_query(token: &str, field_name: &str) -> Box<dyn Query> {
let token = token.to_lowercase();
let token = token.as_str();
let field = Searcher::schema().get_field(field_name).unwrap();
+11 -13
View File
@@ -1,9 +1,11 @@
use instance::Instance;
use posts::Post;
use schema::posts;
use tags::Tag;
use Connection;
use crate::{
instance::Instance,
posts::Post,
schema::posts,
search::{query::PlumeQuery, tokenizer},
tags::Tag,
Connection, Result,
};
use chrono::Datelike;
use diesel::{ExpressionMethods, QueryDsl, RunQueryDsl};
use itertools::Itertools;
@@ -14,10 +16,6 @@ use tantivy::{
};
use whatlang::{detect as detect_lang, Lang};
use super::tokenizer;
use search::query::PlumeQuery;
use Result;
#[derive(Debug)]
pub enum SearcherError {
IndexCreationError,
@@ -72,7 +70,7 @@ impl Searcher {
schema_builder.build()
}
pub fn create(path: &AsRef<Path>) -> Result<Self> {
pub fn create(path: &dyn AsRef<Path>) -> Result<Self> {
let whitespace_tokenizer = tokenizer::WhitespaceTokenizer.filter(LowerCaser);
let content_tokenizer = SimpleTokenizer
@@ -111,7 +109,7 @@ impl Searcher {
})
}
pub fn open(path: &AsRef<Path>) -> Result<Self> {
pub fn open(path: &dyn AsRef<Path>) -> Result<Self> {
let whitespace_tokenizer = tokenizer::WhitespaceTokenizer.filter(LowerCaser);
let content_tokenizer = SimpleTokenizer
@@ -175,7 +173,7 @@ impl Searcher {
post_id => i64::from(post.id),
author => post.get_authors(conn)?.into_iter().map(|u| u.fqn).join(" "),
creation_date => i64::from(post.creation_date.num_days_from_ce()),
instance => Instance::get(conn, post.get_blog(conn)?.instance_id)?.public_domain.clone(),
instance => Instance::get(conn, post.get_blog(conn)?.instance_id)?.public_domain,
tag => Tag::for_post(conn, post.id)?.into_iter().map(|t| t.tag).join(" "),
blog_name => post.get_blog(conn)?.title,
content => post.content.get().clone(),
+1 -4
View File
@@ -1,9 +1,6 @@
use crate::{ap_url, instance::Instance, schema::tags, Connection, Error, Result};
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use instance::Instance;
use plume_common::activity_pub::Hashtag;
use schema::tags;
use {ap_url, Connection, Error, Result};
#[derive(Clone, Identifiable, Queryable)]
pub struct Tag {
+23 -22
View File
@@ -1,16 +1,16 @@
use crate::{
lists::List,
posts::Post,
schema::{posts, timeline, timeline_definition},
Connection, Error, PlumeRocket, Result,
};
use diesel::{self, BoolExpressionMethods, ExpressionMethods, QueryDsl, RunQueryDsl};
use lists::List;
use posts::Post;
use schema::{posts, timeline, timeline_definition};
use std::ops::Deref;
use {Connection, Error, PlumeRocket, Result};
pub(crate) mod query;
use self::query::{QueryError, TimelineQuery};
pub use self::query::Kind;
use self::query::{QueryError, TimelineQuery};
#[derive(Clone, Debug, PartialEq, Queryable, Identifiable, AsChangeset)]
#[table_name = "timeline_definition"]
@@ -119,7 +119,7 @@ impl Timeline {
}
})
{
Err(err)?;
return Err(err);
}
}
Self::insert(
@@ -157,7 +157,7 @@ impl Timeline {
}
})
{
Err(err)?;
return Err(err);
}
}
Self::insert(
@@ -208,7 +208,7 @@ impl Timeline {
.map_err(Error::from)
}
pub fn add_to_all_timelines(rocket: &PlumeRocket, post: &Post, kind: Kind) -> Result<()> {
pub fn add_to_all_timelines(rocket: &PlumeRocket, post: &Post, kind: Kind<'_>) -> Result<()> {
let timelines = timeline_definition::table
.load::<Self>(rocket.conn.deref())
.map_err(Error::from)?;
@@ -231,7 +231,7 @@ impl Timeline {
Ok(())
}
pub fn matches(&self, rocket: &PlumeRocket, post: &Post, kind: Kind) -> Result<bool> {
pub fn matches(&self, rocket: &PlumeRocket, post: &Post, kind: Kind<'_>) -> Result<bool> {
let query = TimelineQuery::parse(&self.query)?;
query.matches(rocket, self, post, kind)
}
@@ -240,16 +240,18 @@ impl Timeline {
#[cfg(test)]
mod tests {
use super::*;
use blogs::tests as blogTests;
use crate::{
blogs::tests as blogTests,
follows::*,
lists::ListType,
post_authors::{NewPostAuthor, PostAuthor},
posts::NewPost,
safe_string::SafeString,
tags::Tag,
tests::{db, rockets},
users::tests as userTests,
};
use diesel::Connection;
use follows::*;
use lists::ListType;
use post_authors::{NewPostAuthor, PostAuthor};
use posts::NewPost;
use safe_string::SafeString;
use tags::Tag;
use tests::{db, rockets};
use users::tests as userTests;
#[test]
fn test_timeline() {
@@ -495,8 +497,7 @@ mod tests {
),
published: true,
license: "GPL".to_string(),
source: "Actually, GNU+Linux, GNU×Linux, or GNU¿Linux are better."
.to_string(),
source: "Actually, GNU+Linux, GNU×Linux, or GNU¿Linux are better.".to_string(),
ap_url: "".to_string(),
creation_date: None,
subtitle: "".to_string(),
+31 -22
View File
@@ -1,15 +1,15 @@
use blogs::Blog;
use lists::{self, ListType};
use crate::{
blogs::Blog,
lists::{self, ListType},
posts::Post,
tags::Tag,
timeline::Timeline,
users::User,
PlumeRocket, Result,
};
use plume_common::activity_pub::inbox::AsActor;
use posts::Post;
use tags::Tag;
use users::User;
use whatlang::{self, Lang};
use {PlumeRocket, Result};
use super::Timeline;
#[derive(Debug, Clone, PartialEq)]
pub enum QueryError {
SyntaxError(usize, usize, String),
@@ -65,7 +65,7 @@ impl<'a> Token<'a> {
}
}
fn get_error<T>(&self, token: Token) -> QueryResult<T> {
fn get_error<T>(&self, token: Token<'_>) -> QueryResult<T> {
let (b, e) = self.get_pos();
let message = format!(
"Syntax Error: Expected {}, got {}",
@@ -79,7 +79,7 @@ impl<'a> Token<'a> {
impl<'a> ToString for Token<'a> {
fn to_string(&self) -> String {
if let Token::Word(0, 0, v) = self {
return v.to_string();
return (*v).to_string();
}
format!(
"'{}'",
@@ -127,7 +127,7 @@ macro_rules! gen_tokenizer {
}
}
fn lex(stream: &str) -> Vec<Token> {
fn lex(stream: &str) -> Vec<Token<'_>> {
stream
.chars()
.chain(" ".chars()) // force a last whitespace to empty scan's state
@@ -163,7 +163,7 @@ impl<'a> TQ<'a> {
rocket: &PlumeRocket,
timeline: &Timeline,
post: &Post,
kind: Kind,
kind: Kind<'_>,
) -> Result<bool> {
match self {
TQ::Or(inner) => inner.iter().try_fold(false, |s, e| {
@@ -181,7 +181,7 @@ impl<'a> TQ<'a> {
TQ::Or(inner) => inner.iter().flat_map(TQ::list_used_lists).collect(),
TQ::And(inner) => inner.iter().flat_map(TQ::list_used_lists).collect(),
TQ::Arg(Arg::In(typ, List::List(name)), _) => vec![(
name.to_string(),
(*name).to_string(),
match typ {
WithList::Blog => ListType::Blog,
WithList::Author { .. } => ListType::User,
@@ -208,7 +208,7 @@ impl<'a> Arg<'a> {
rocket: &PlumeRocket,
timeline: &Timeline,
post: &Post,
kind: Kind,
kind: Kind<'_>,
) -> Result<bool> {
match self {
Arg::In(t, l) => t.matches(rocket, timeline, post, l, kind),
@@ -233,8 +233,8 @@ impl WithList {
rocket: &PlumeRocket,
timeline: &Timeline,
post: &Post,
list: &List,
kind: Kind,
list: &List<'_>,
kind: Kind<'_>,
) -> Result<bool> {
match list {
List::List(name) => {
@@ -290,7 +290,8 @@ impl WithList {
(_, _) => Err(QueryError::RuntimeError(format!(
"The list '{}' is of the wrong type for this usage",
name
)))?,
))
.into()),
}
}
List::Array(list) => match self {
@@ -373,7 +374,7 @@ impl Bool {
rocket: &PlumeRocket,
timeline: &Timeline,
post: &Post,
kind: Kind,
kind: Kind<'_>,
) -> Result<bool> {
match self {
Bool::Followed { boosts, likes } => {
@@ -644,7 +645,7 @@ impl<'a> TimelineQuery<'a> {
rocket: &PlumeRocket,
timeline: &Timeline,
post: &Post,
kind: Kind,
kind: Kind<'_>,
) -> Result<bool> {
self.0.matches(rocket, timeline, post, kind)
}
@@ -811,9 +812,17 @@ mod tests {
);
let expect_keyword = TimelineQuery::parse(r#"not_a_field contains something"#).unwrap_err();
assert_eq!(expect_keyword, QueryError::SyntaxError(0, 11, "Syntax Error: Expected one of 'blog', \
assert_eq!(
expect_keyword,
QueryError::SyntaxError(
0,
11,
"Syntax Error: Expected one of 'blog', \
'author', 'license', 'tags', 'lang', 'title', 'subtitle', 'content', 'followed', 'has_cover', \
'local' or 'all', got 'not_a_field'".to_owned()));
'local' or 'all', got 'not_a_field'"
.to_owned()
)
);
let expect_bracket_or_comma = TimelineQuery::parse(r#"lang in [en ["#).unwrap_err();
assert_eq!(
+38 -44
View File
@@ -1,3 +1,9 @@
use crate::{
ap_url, blocklisted_emails::BlocklistedEmail, blogs::Blog, db_conn::DbConn, follows::Follow,
instance::*, medias::Media, notifications::Notification, post_authors::PostAuthor, posts::Post,
safe_string::SafeString, schema::users, search::Searcher, timeline::Timeline, Connection,
Error, PlumeRocket, Result, ITEMS_PER_PAGE,
};
use activitypub::{
activity::Delete,
actor::Person,
@@ -14,13 +20,15 @@ use openssl::{
rsa::Rsa,
sign,
};
use plume_common::activity_pub::{
ap_accept_header,
inbox::{AsActor, AsObject, FromId},
sign::{gen_keypair, Signer},
ActivityStream, ApSignature, Id, IntoId, PublicKey, PUBLIC_VISIBILITY,
use plume_common::{
activity_pub::{
ap_accept_header,
inbox::{AsActor, AsObject, FromId},
sign::{gen_keypair, Signer},
ActivityStream, ApSignature, Id, IntoId, PublicKey, PUBLIC_VISIBILITY,
},
utils,
};
use plume_common::utils;
use reqwest::{
header::{HeaderValue, ACCEPT},
ClientBuilder,
@@ -37,23 +45,6 @@ use std::{
use url::Url;
use webfinger::*;
use blogs::Blog;
use db_conn::DbConn;
use follows::Follow;
use instance::*;
use medias::Media;
use notifications::Notification;
use post_authors::PostAuthor;
use posts::Post;
use safe_string::SafeString;
use schema::users;
use search::Searcher;
use timeline::Timeline;
use {
ap_url, blocklisted_emails::BlocklistedEmail, Connection, Error, PlumeRocket, Result,
ITEMS_PER_PAGE,
};
pub type CustomPerson = CustomObject<ApSignature, Person>;
pub enum Role {
@@ -63,6 +54,7 @@ pub enum Role {
}
#[derive(Queryable, Identifiable, Clone, Debug, AsChangeset)]
#[changeset_options(treat_none_as_null = "true")]
pub struct User {
pub id: i32,
pub username: String,
@@ -139,7 +131,7 @@ impl User {
}
pub fn delete(&self, conn: &Connection, searcher: &Searcher) -> Result<()> {
use schema::post_authors;
use crate::schema::post_authors;
for blog in Blog::find_for_author(conn, self)?
.iter()
@@ -464,8 +456,8 @@ impl User {
.collect::<Vec<String>>())
}
fn get_activities_count(&self, conn: &Connection) -> i64 {
use schema::post_authors;
use schema::posts;
use crate::schema::post_authors;
use crate::schema::posts;
let posts_by_self = PostAuthor::belonging_to(self).select(post_authors::post_id);
posts::table
.filter(posts::published.eq(true))
@@ -479,8 +471,8 @@ impl User {
conn: &Connection,
(min, max): (i32, i32),
) -> Result<Vec<serde_json::Value>> {
use schema::post_authors;
use schema::posts;
use crate::schema::post_authors;
use crate::schema::posts;
let posts_by_self = PostAuthor::belonging_to(self).select(post_authors::post_id);
let posts = posts::table
.filter(posts::published.eq(true))
@@ -500,7 +492,7 @@ impl User {
}
pub fn get_followers(&self, conn: &Connection) -> Result<Vec<User>> {
use schema::follows;
use crate::schema::follows;
let follows = Follow::belonging_to(self).select(follows::follower_id);
users::table
.filter(users::id.eq_any(follows))
@@ -509,7 +501,7 @@ impl User {
}
pub fn count_followers(&self, conn: &Connection) -> Result<i64> {
use schema::follows;
use crate::schema::follows;
let follows = Follow::belonging_to(self).select(follows::follower_id);
users::table
.filter(users::id.eq_any(follows))
@@ -523,7 +515,7 @@ impl User {
conn: &Connection,
(min, max): (i32, i32),
) -> Result<Vec<User>> {
use schema::follows;
use crate::schema::follows;
let follows = Follow::belonging_to(self).select(follows::follower_id);
users::table
.filter(users::id.eq_any(follows))
@@ -534,7 +526,7 @@ impl User {
}
pub fn get_followed(&self, conn: &Connection) -> Result<Vec<User>> {
use schema::follows::dsl::*;
use crate::schema::follows::dsl::*;
let f = follows.filter(follower_id.eq(self.id)).select(following_id);
users::table
.filter(users::id.eq_any(f))
@@ -543,7 +535,7 @@ impl User {
}
pub fn count_followed(&self, conn: &Connection) -> Result<i64> {
use schema::follows;
use crate::schema::follows;
follows::table
.filter(follows::follower_id.eq(self.id))
.count()
@@ -556,7 +548,7 @@ impl User {
conn: &Connection,
(min, max): (i32, i32),
) -> Result<Vec<User>> {
use schema::follows;
use crate::schema::follows;
let follows = follows::table
.filter(follows::follower_id.eq(self.id))
.select(follows::following_id)
@@ -569,7 +561,7 @@ impl User {
}
pub fn is_followed_by(&self, conn: &Connection, other_id: i32) -> Result<bool> {
use schema::follows;
use crate::schema::follows;
follows::table
.filter(follows::follower_id.eq(other_id))
.filter(follows::following_id.eq(self.id))
@@ -580,7 +572,7 @@ impl User {
}
pub fn is_following(&self, conn: &Connection, other_id: i32) -> Result<bool> {
use schema::follows;
use crate::schema::follows;
follows::table
.filter(follows::follower_id.eq(self.id))
.filter(follows::following_id.eq(other_id))
@@ -591,7 +583,7 @@ impl User {
}
pub fn has_liked(&self, conn: &Connection, post: &Post) -> Result<bool> {
use schema::likes;
use crate::schema::likes;
likes::table
.filter(likes::post_id.eq(post.id))
.filter(likes::user_id.eq(self.id))
@@ -602,7 +594,7 @@ impl User {
}
pub fn has_reshared(&self, conn: &Connection, post: &Post) -> Result<bool> {
use schema::reshares;
use crate::schema::reshares;
reshares::table
.filter(reshares::post_id.eq(post.id))
.filter(reshares::user_id.eq(self.id))
@@ -613,7 +605,7 @@ impl User {
}
pub fn is_author_in(&self, conn: &Connection, blog: &Blog) -> Result<bool> {
use schema::blog_authors;
use crate::schema::blog_authors;
blog_authors::table
.filter(blog_authors::author_id.eq(self.id))
.filter(blog_authors::blog_id.eq(blog.id))
@@ -813,7 +805,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
impl IntoId for User {
fn into_id(self) -> Id {
Id::new(self.ap_url.clone())
Id::new(self.ap_url)
}
}
@@ -1033,11 +1025,13 @@ impl NewUser {
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::{
instance::{tests as instance_tests, Instance},
search::tests::get_searcher,
tests::{db, rockets},
Connection as Conn,
};
use diesel::Connection;
use instance::{tests as instance_tests, Instance};
use search::tests::get_searcher;
use tests::{db, rockets};
use Connection as Conn;
pub(crate) fn fill_database(conn: &Conn) -> Vec<User> {
instance_tests::fill_database(conn);
-4
View File
@@ -1,7 +1,3 @@
extern crate diesel;
extern crate plume_common;
extern crate plume_models;
use diesel::Connection;
use plume_common::utils::random_hex;
use plume_models::migrations::IMPORTED_MIGRATIONS;
+627 -478
View File
File diff suppressed because it is too large Load Diff
+627 -457
View File
File diff suppressed because it is too large Load Diff
+604 -470
View File
File diff suppressed because it is too large Load Diff
+692 -481
View File
File diff suppressed because it is too large Load Diff
+686 -474
View File
File diff suppressed because it is too large Load Diff
+557 -429
View File
File diff suppressed because it is too large Load Diff
+570 -441
View File
File diff suppressed because it is too large Load Diff
+641 -481
View File
File diff suppressed because it is too large Load Diff
+697 -475
View File
File diff suppressed because it is too large Load Diff
+688 -484
View File
File diff suppressed because it is too large Load Diff
+615 -474
View File
File diff suppressed because it is too large Load Diff
+567 -436
View File
File diff suppressed because it is too large Load Diff
+688 -474
View File
File diff suppressed because it is too large Load Diff
+663 -457
View File
File diff suppressed because it is too large Load Diff
+641 -525
View File
File diff suppressed because it is too large Load Diff
+695 -481
View File
File diff suppressed because it is too large Load Diff
+477 -408
View File
File diff suppressed because it is too large Load Diff
+690 -484
View File
File diff suppressed because it is too large Load Diff
+579 -446
View File
File diff suppressed because it is too large Load Diff
+598 -461
View File
File diff suppressed because it is too large Load Diff
+697 -481
View File
File diff suppressed because it is too large Load Diff
+561 -432
View File
File diff suppressed because it is too large Load Diff
+569 -438
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
nightly-2019-03-23
nightly-2020-01-15
+2 -2
View File
@@ -24,9 +24,9 @@ if [ $ARCH == "aarch64" -o $ARCH == "armv71" ] ; then
apt-get install -y --no-install-recommends build-essential subversion ninja-build cmake
mkdir -p /scratch/src
cd /scratch/src
svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_800/final/ llvm
svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_900/final/ llvm
cd /scratch/src/llvm/tools
svn co http://llvm.org/svn/llvm-project/lld/tags/RELEASE_800/final/ lld
svn co http://llvm.org/svn/llvm-project/lld/tags/RELEASE_900/final/ lld
mkdir -p /scratch/build/arm
cd /scratch/build/arm
if [ "$ARCH" == "aarch64" ] ; then
+4 -3
View File
@@ -8,7 +8,7 @@ description: |
* Media management: you can upload pictures to illustrate your articles, but also audio files if you host a podcast, and manage them all from Plume.
* Federation: Plume is part of a network of interconnected websites called the Fediverse. Each of these websites (often called instances) have their own rules and thematics, but they can all communicate with each other.
* Collaborative writing: invite other people to your blogs, and write articles together.
grade: devel # must be 'stable' to release into candidate/stable channels
grade: stable
confinement: strict
apps:
@@ -25,12 +25,13 @@ parts:
plume:
plugin: rust
source: .
rust-revision: nightly-2019-03-23
rust-revision: nightly-2020-01-15
build-packages:
- libssl-dev
- pkg-config
- libsqlite3-dev
- gettext
- libclang-8-dev
- on arm64,armhf,ppc64el,s390x:
- lld-8
override-build: |
@@ -42,7 +43,7 @@ parts:
# Only Tier 1 Rust platforms get rust-lld
# On the others (arm64, armhf, powerpc64, s390x) fall back to using
# the system LLD we've installed earlier.
case ${SNAPCRAFT_ARCH_TRIPLE} in \
case ${SNAPCRAFT_ARCH_TRIPLET} in \
aarch64-linux-gnu|arm-linux-gnueabihf|powerpc64-linux-gnu|s390x-linux-gnu) \
RUSTFLAGS="-C linker=lld-8" cargo web deploy -p plume-front --release \
;; \
+1 -1
View File
@@ -27,7 +27,7 @@ impl From<std::option::NoneError> for ApiError {
}
impl<'r> Responder<'r> for ApiError {
fn respond_to(self, req: &Request) -> response::Result<'r> {
fn respond_to(self, req: &Request<'_>) -> response::Result<'r> {
match self.0 {
Error::NotFound => Json(json!({
"error": "Not found"
+3 -3
View File
@@ -14,7 +14,7 @@ use std::io::Read;
pub fn handle_incoming(
rockets: PlumeRocket,
data: SignedJson<serde_json::Value>,
headers: Headers,
headers: Headers<'_>,
) -> Result<String, status::BadRequest<&'static str>> {
let conn = &*rockets.conn;
let act = data.1.into_inner();
@@ -74,7 +74,7 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for SignedJson<T> {
type Borrowed = str;
fn transform(
r: &Request,
r: &Request<'_>,
d: Data,
) -> Transform<rocket::data::Outcome<Self::Owned, Self::Error>> {
let size_limit = r.limits().get("json").unwrap_or(JSON_LIMIT);
@@ -86,7 +86,7 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for SignedJson<T> {
}
fn from_data(
_: &Request,
_: &Request<'_>,
o: Transformed<'a, Self>,
) -> rocket::data::Outcome<Self, Self::Error> {
let string = o.borrowed()?;
+3 -38
View File
@@ -1,43 +1,16 @@
#![allow(clippy::too_many_arguments)]
#![feature(decl_macro, proc_macro_hygiene, try_trait)]
extern crate activitypub;
extern crate askama_escape;
extern crate atom_syndication;
extern crate chrono;
extern crate clap;
extern crate colored;
extern crate ctrlc;
extern crate diesel;
extern crate dotenv;
#[macro_use]
extern crate gettext_macros;
extern crate gettext_utils;
extern crate guid_create;
extern crate heck;
extern crate lettre;
extern crate lettre_email;
extern crate multipart;
extern crate num_cpus;
extern crate plume_api;
extern crate plume_common;
extern crate plume_models;
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
extern crate rocket_csrf;
extern crate rocket_i18n;
#[macro_use]
extern crate runtime_fmt;
extern crate scheduled_thread_pool;
extern crate serde;
#[macro_use]
extern crate serde_json;
extern crate serde_qs;
extern crate validator;
#[macro_use]
extern crate validator_derive;
extern crate webfinger;
use clap::App;
use diesel::r2d2::ConnectionManager;
@@ -307,21 +280,13 @@ Then try to restart Plume
rocket::http::Method::Post,
)
.add_exceptions(vec![
(
"/inbox".to_owned(),
"/inbox".to_owned(),
rocket::http::Method::Post,
),
("/inbox".to_owned(), "/inbox".to_owned(), None),
(
"/@/<name>/inbox".to_owned(),
"/@/<name>/inbox".to_owned(),
rocket::http::Method::Post,
),
(
"/api/<path..>".to_owned(),
"/api/<path..>".to_owned(),
rocket::http::Method::Post,
None,
),
("/api/<path..>".to_owned(), "/api/<path..>".to_owned(), None),
])
.finalize()
.expect("main: csrf fairing creation error"),
+3 -3
View File
@@ -10,14 +10,14 @@ use rocket_i18n::I18n;
use std::{borrow::Cow, collections::HashMap};
use validator::{Validate, ValidationError, ValidationErrors};
use crate::routes::{errors::ErrorPage, Page, RespondOrRedirect};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::activity_pub::{ActivityStream, ApRequest};
use plume_common::utils;
use plume_models::{
blog_authors::*, blogs::*, instance::Instance, medias::*, posts::Post, safe_string::SafeString,
users::User, Connection, PlumeRocket,
};
use routes::{errors::ErrorPage, Page, RespondOrRedirect};
use template_utils::{IntoContext, Ructe};
#[get("/~/<name>?<page>", rank = 2)]
pub fn details(name: String, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
@@ -137,7 +137,7 @@ pub fn create(form: LenientForm<NewBlogForm>, rockets: PlumeRocket) -> RespondOr
.expect("blog::create: author error");
Flash::success(
Redirect::to(uri!(details: name = slug.clone(), page = _)),
Redirect::to(uri!(details: name = slug, page = _)),
&i18n!(intl, "Your blog was successfully created!"),
)
.into()
+3 -3
View File
@@ -1,13 +1,15 @@
use crate::template_utils::Ructe;
use activitypub::object::Note;
use rocket::{
request::LenientForm,
response::{Flash, Redirect},
};
use template_utils::Ructe;
use validator::Validate;
use std::time::Duration;
use crate::routes::errors::ErrorPage;
use crate::template_utils::IntoContext;
use plume_common::{
activity_pub::{broadcast, ActivityStream, ApRequest},
utils,
@@ -16,8 +18,6 @@ use plume_models::{
blogs::Blog, comments::*, inbox::inbox, instance::Instance, medias::Media, mentions::Mention,
posts::Post, safe_string::SafeString, tags::Tag, users::User, Error, PlumeRocket,
};
use routes::errors::ErrorPage;
use template_utils::IntoContext;
#[derive(Default, FromForm, Debug, Validate)]
pub struct NewCommentForm {
+5 -5
View File
@@ -1,9 +1,9 @@
use crate::template_utils::{IntoContext, Ructe};
use plume_models::{Error, PlumeRocket};
use rocket::{
response::{self, Responder},
Request,
};
use template_utils::{IntoContext, Ructe};
#[derive(Debug)]
pub struct ErrorPage(Error);
@@ -15,7 +15,7 @@ impl From<Error> for ErrorPage {
}
impl<'r> Responder<'r> for ErrorPage {
fn respond_to(self, req: &Request) -> response::Result<'r> {
fn respond_to(self, req: &Request<'_>) -> response::Result<'r> {
let rockets = req.guard::<PlumeRocket>().unwrap();
match self.0 {
@@ -29,19 +29,19 @@ impl<'r> Responder<'r> for ErrorPage {
}
#[catch(404)]
pub fn not_found(req: &Request) -> Ructe {
pub fn not_found(req: &Request<'_>) -> Ructe {
let rockets = req.guard::<PlumeRocket>().unwrap();
render!(errors::not_found(&rockets.to_context()))
}
#[catch(422)]
pub fn unprocessable_entity(req: &Request) -> Ructe {
pub fn unprocessable_entity(req: &Request<'_>) -> Ructe {
let rockets = req.guard::<PlumeRocket>().unwrap();
render!(errors::unprocessable_entity(&rockets.to_context()))
}
#[catch(500)]
pub fn server_error(req: &Request) -> Ructe {
pub fn server_error(req: &Request<'_>) -> Ructe {
let rockets = req.guard::<PlumeRocket>().unwrap();
render!(errors::server_error(&rockets.to_context()))
}
+6 -7
View File
@@ -9,7 +9,9 @@ use serde_json;
use std::str::FromStr;
use validator::{Validate, ValidationErrors};
use inbox;
use crate::inbox;
use crate::routes::{errors::ErrorPage, rocket_uri_macro_static_files, Page, RespondOrRedirect};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::activity_pub::{broadcast, inbox::FromId};
use plume_models::{
admin::*,
@@ -25,8 +27,6 @@ use plume_models::{
users::{Role, User},
Connection, Error, PlumeRocket, CONFIG,
};
use routes::{errors::ErrorPage, rocket_uri_macro_static_files, Page, RespondOrRedirect};
use template_utils::{IntoContext, Ructe};
#[get("/")]
pub fn index(rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
@@ -248,7 +248,7 @@ where
{
type Error = ();
fn from_form(items: &mut FormItems, _strict: bool) -> Result<Self, Self::Error> {
fn from_form(items: &mut FormItems<'_>, _strict: bool) -> Result<Self, Self::Error> {
let (ids, act) = items.fold((vec![], None), |(mut ids, act), item| {
let (name, val) = item.key_value_decoded();
@@ -379,8 +379,7 @@ fn ban(
.unwrap();
let target = User::one_by_instance(&*conn)?;
let delete_act = u.delete_activity(&*conn)?;
let u_clone = u.clone();
worker.execute(move || broadcast(&u_clone, delete_act, target));
worker.execute(move || broadcast(&u, delete_act, target));
}
Ok(())
@@ -390,7 +389,7 @@ fn ban(
pub fn shared_inbox(
rockets: PlumeRocket,
data: inbox::SignedJson<serde_json::Value>,
headers: Headers,
headers: Headers<'_>,
) -> Result<String, status::BadRequest<&'static str>> {
inbox::handle_incoming(rockets, data, headers)
}
+1 -1
View File
@@ -1,12 +1,12 @@
use rocket::response::{Flash, Redirect};
use rocket_i18n::I18n;
use crate::routes::errors::ErrorPage;
use plume_common::activity_pub::broadcast;
use plume_common::utils;
use plume_models::{
blogs::Blog, inbox::inbox, likes, posts::Post, timeline::*, users::User, Error, PlumeRocket,
};
use routes::errors::ErrorPage;
#[post("/~/<blog>/<slug>/like")]
pub fn create(
+2 -2
View File
@@ -1,3 +1,5 @@
use crate::routes::{errors::ErrorPage, Page};
use crate::template_utils::{IntoContext, Ructe};
use guid_create::GUID;
use multipart::server::{
save::{SaveResult, SavedData},
@@ -10,9 +12,7 @@ use rocket::{
Data,
};
use rocket_i18n::I18n;
use routes::{errors::ErrorPage, Page};
use std::fs;
use template_utils::{IntoContext, Ructe};
#[get("/medias?<page>")]
pub fn list(user: User, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
+6 -2
View File
@@ -1,4 +1,5 @@
#![warn(clippy::too_many_arguments)]
use crate::template_utils::Ructe;
use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder};
use plume_models::{posts::Post, Connection, CONFIG, ITEMS_PER_PAGE};
use rocket::{
@@ -16,7 +17,6 @@ use std::{
hash::Hasher,
path::{Path, PathBuf},
};
use template_utils::Ructe;
/// Special return type used for routes that "cannot fail", and instead
/// `Redirect`, or `Flash<Redirect>`, when we cannot deliver a `Ructe` Response
@@ -139,6 +139,10 @@ pub fn post_to_atom(post: Post, conn: &Connection) -> Entry {
})
.collect::<Vec<Person>>(),
)
// Using RFC 4287 format, see https://tools.ietf.org/html/rfc4287#section-3.3 for dates
// eg: 2003-12-13T18:30:02Z (Z is here because there is no timezone support with the NaiveDateTime crate)
.published(post.creation_date.format("%Y-%m-%dT%H:%M:%SZ").to_string())
.id(post.id.to_string())
.links(vec![LinkBuilder::default()
.href(post.ap_url)
.build()
@@ -174,7 +178,7 @@ pub struct CachedFile {
pub struct ThemeFile(NamedFile);
impl<'r> Responder<'r> for ThemeFile {
fn respond_to(self, r: &Request) -> response::Result<'r> {
fn respond_to(self, r: &Request<'_>) -> response::Result<'r> {
let contents = std::fs::read(self.0.path()).map_err(|_| Status::InternalServerError)?;
let mut hasher = DefaultHasher::new();
+2 -2
View File
@@ -1,10 +1,10 @@
use rocket::response::{Flash, Redirect};
use rocket_i18n::I18n;
use crate::routes::{errors::ErrorPage, Page};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::utils;
use plume_models::{notifications::Notification, users::User, PlumeRocket};
use routes::{errors::ErrorPage, Page};
use template_utils::{IntoContext, Ructe};
#[get("/notifications?<page>")]
pub fn notifications(
+11 -13
View File
@@ -10,6 +10,10 @@ use std::{
};
use validator::{Validate, ValidationError, ValidationErrors};
use crate::routes::{
comments::NewCommentForm, errors::ErrorPage, ContentLen, RemoteForm, RespondOrRedirect,
};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::activity_pub::{broadcast, ActivityStream, ApRequest};
use plume_common::utils;
use plume_models::{
@@ -27,10 +31,6 @@ use plume_models::{
users::User,
Error, PlumeRocket,
};
use routes::{
comments::NewCommentForm, errors::ErrorPage, ContentLen, RemoteForm, RespondOrRedirect,
};
use template_utils::{IntoContext, Ructe};
#[get("/~/<blog>/<slug>?<responding_to>", rank = 4)]
pub fn details(
@@ -298,7 +298,7 @@ pub fn update(
post.license = form.license.clone();
post.cover_id = form.cover;
post.update(&*conn, &rockets.searcher)
.expect("post::update: update error");;
.expect("post::update: update error");
if post.published {
post.update_mentions(
@@ -308,7 +308,7 @@ pub fn update(
.filter_map(|m| Mention::build_activity(&rockets, &m).ok())
.collect(),
)
.expect("post::update: mentions error");;
.expect("post::update: mentions error");
}
let tags = form
@@ -367,8 +367,8 @@ pub fn update(
&*form,
form.draft,
Some(post),
errors.clone(),
medias.clone(),
errors,
medias,
cl.0
))
.into()
@@ -406,7 +406,7 @@ pub fn create(
rockets: PlumeRocket,
) -> Result<RespondOrRedirect, ErrorPage> {
let conn = &*rockets.conn;
let blog = Blog::find_by_fqn(&rockets, &blog_name).expect("post::create: blog error");;
let blog = Blog::find_by_fqn(&rockets, &blog_name).expect("post::create: blog error");
let slug = form.title.to_string().to_kebab_case();
let user = rockets.user.clone().unwrap();
@@ -553,7 +553,7 @@ pub fn create(
&*form,
form.draft,
None,
errors.clone(),
errors,
medias,
cl.0
))
@@ -579,9 +579,7 @@ pub fn delete(
.any(|a| a.id == user.id)
{
return Ok(Flash::error(
Redirect::to(
uri!(details: blog = blog_name.clone(), slug = slug.clone(), responding_to = _),
),
Redirect::to(uri!(details: blog = blog_name, slug = slug, responding_to = _)),
i18n!(intl.catalog, "You are not allowed to delete this article."),
));
}
+1 -1
View File
@@ -1,13 +1,13 @@
use rocket::response::{Flash, Redirect};
use rocket_i18n::I18n;
use crate::routes::errors::ErrorPage;
use plume_common::activity_pub::broadcast;
use plume_common::utils;
use plume_models::{
blogs::Blog, inbox::inbox, posts::Post, reshares::*, timeline::*, users::User, Error,
PlumeRocket,
};
use routes::errors::ErrorPage;
#[post("/~/<blog>/<slug>/reshare")]
pub fn create(
+2 -2
View File
@@ -1,10 +1,10 @@
use chrono::offset::Utc;
use rocket::request::Form;
use crate::routes::Page;
use crate::template_utils::{IntoContext, Ructe};
use plume_models::{search::Query, PlumeRocket};
use routes::Page;
use std::str::FromStr;
use template_utils::{IntoContext, Ructe};
#[derive(Default, FromForm)]
pub struct SearchQuery {
+9 -9
View File
@@ -1,13 +1,13 @@
use crate::routes::RespondOrRedirect;
use lettre::Transport;
use rocket::http::ext::IntoOwned;
use rocket::{
http::{uri::Uri, Cookie, Cookies, SameSite},
request::{Form, LenientForm},
request::LenientForm,
response::{Flash, Redirect},
State,
};
use rocket_i18n::I18n;
use routes::RespondOrRedirect;
use std::{
borrow::Cow,
sync::{Arc, Mutex},
@@ -15,13 +15,13 @@ use std::{
};
use validator::{Validate, ValidationError, ValidationErrors};
use mail::{build_mail, Mailer};
use crate::mail::{build_mail, Mailer};
use crate::template_utils::{IntoContext, Ructe};
use plume_models::{
password_reset_requests::*,
users::{User, AUTH_COOKIE},
Error, PlumeRocket, CONFIG,
};
use template_utils::{IntoContext, Ructe};
#[get("/login?<m>")]
pub fn new(m: Option<String>, rockets: PlumeRocket) -> Ructe {
@@ -44,7 +44,7 @@ pub struct LoginForm {
#[post("/login", data = "<form>")]
pub fn create(
form: LenientForm<LoginForm>,
mut cookies: Cookies,
mut cookies: Cookies<'_>,
rockets: PlumeRocket,
) -> RespondOrRedirect {
let conn = &*rockets.conn;
@@ -118,7 +118,7 @@ pub fn create(
}
#[get("/logout")]
pub fn delete(mut cookies: Cookies, intl: I18n) -> Flash<Redirect> {
pub fn delete(mut cookies: Cookies<'_>, intl: I18n) -> Flash<Redirect> {
if let Some(cookie) = cookies.get_private(AUTH_COOKIE) {
cookies.remove_private(cookie);
}
@@ -158,8 +158,8 @@ pub struct ResetForm {
#[post("/password-reset", data = "<form>")]
pub fn password_reset_request(
mail: State<Arc<Mutex<Mailer>>>,
form: Form<ResetForm>,
mail: State<'_, Arc<Mutex<Mailer>>>,
form: LenientForm<ResetForm>,
rockets: PlumeRocket,
) -> Ructe {
if User::find_by_email(&*rockets.conn, &form.email).is_ok() {
@@ -216,7 +216,7 @@ fn passwords_match(form: &NewPasswordForm) -> Result<(), ValidationError> {
#[post("/password-reset/<token>", data = "<form>")]
pub fn password_reset(
token: String,
form: Form<NewPasswordForm>,
form: LenientForm<NewPasswordForm>,
rockets: PlumeRocket,
) -> Result<Flash<Redirect>, Ructe> {
form.validate()
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::routes::{errors::ErrorPage, Page};
use crate::template_utils::{IntoContext, Ructe};
use plume_models::{posts::Post, PlumeRocket};
use routes::{errors::ErrorPage, Page};
use template_utils::{IntoContext, Ructe};
#[get("/tag/<name>?<page>")]
pub fn tag(name: String, page: Option<Page>, rockets: PlumeRocket) -> Result<Ructe, ErrorPage> {
+2 -2
View File
@@ -1,10 +1,10 @@
#![allow(dead_code)]
use crate::routes::Page;
use crate::template_utils::IntoContext;
use crate::{routes::errors::ErrorPage, template_utils::Ructe};
use plume_models::{timeline::*, PlumeRocket};
use rocket::response::Redirect;
use routes::Page;
use template_utils::IntoContext;
#[get("/timeline/<id>?<page>")]
pub fn details(id: i32, rockets: PlumeRocket, page: Option<Page>) -> Result<Ructe, ErrorPage> {
+10 -7
View File
@@ -14,7 +14,9 @@ use serde_json;
use std::{borrow::Cow, collections::HashMap};
use validator::{Validate, ValidationError, ValidationErrors};
use inbox;
use crate::inbox;
use crate::routes::{errors::ErrorPage, Page, RemoteForm, RespondOrRedirect};
use crate::template_utils::{IntoContext, Ructe};
use plume_common::activity_pub::{broadcast, inbox::FromId, ActivityStream, ApRequest, Id};
use plume_common::utils;
use plume_models::{
@@ -31,8 +33,6 @@ use plume_models::{
users::*,
Error, PlumeRocket,
};
use routes::{errors::ErrorPage, Page, RemoteForm, RespondOrRedirect};
use template_utils::{IntoContext, Ructe};
#[get("/me")]
pub fn me(user: Option<User>) -> RespondOrRedirect {
@@ -355,7 +355,7 @@ pub fn edit(name: String, user: User, rockets: PlumeRocket) -> Result<Ructe, Err
ValidationErrors::default()
)))
} else {
Err(Error::Unauthorized)?
Err(Error::Unauthorized.into())
}
}
@@ -399,7 +399,10 @@ pub fn update(
)
.0,
);
user.preferred_theme = form.theme.clone();
user.preferred_theme = form
.theme
.clone()
.and_then(|t| if &t == "" { None } else { Some(t) });
user.hide_custom_css = form.hide_custom_css;
let _: User = user.save_changes(&*conn).map_err(Error::from)?;
@@ -413,7 +416,7 @@ pub fn update(
pub fn delete(
name: String,
user: User,
mut cookies: Cookies,
mut cookies: Cookies<'_>,
rockets: PlumeRocket,
) -> Result<Flash<Redirect>, ErrorPage> {
let account = User::find_by_fqn(&rockets, &name)?;
@@ -580,7 +583,7 @@ pub fn outbox_page(
pub fn inbox(
name: String,
data: inbox::SignedJson<serde_json::Value>,
headers: Headers,
headers: Headers<'_>,
rockets: PlumeRocket,
) -> Result<String, status::BadRequest<&'static str>> {
User::find_by_fqn(&rockets, &name).map_err(|_| status::BadRequest(Some("User not found")))?;

Some files were not shown because too many files have changed in this diff Show More