Merge pull request 'Upgrade Tantivy to 0.13.3' (#878) from upgrade-tantivy into main

Reviewed-on: https://git.joinplu.me/Plume/Plume/pulls/878
This commit is contained in:
KitaitiMakoto 2021-01-16 05:40:14 +00:00
commit a11205324b
85 changed files with 24854 additions and 24891 deletions

View File

@ -71,7 +71,7 @@ commands:
type: string type: string
steps: steps:
- run: | - run: |
export RUSTFLAGS="-Zprofile -Zfewer-names -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads -Clink-arg=-Xlinker -Clink-arg=--no-keep-memory -Clink-arg=-Xlinker -Clink-arg=--reduce-memory-overheads" export RUSTFLAGS="-Zprofile -Zfewer-names -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off -Clink-arg=-Xlinker -Clink-arg=--no-keep-memory -Clink-arg=-Xlinker -Clink-arg=--reduce-memory-overheads"
export CARGO_INCREMENTAL=0 export CARGO_INCREMENTAL=0
<< parameters.cmd >> << parameters.cmd >>

View File

@ -11,7 +11,7 @@ RUN apt update &&\
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
#install and configure rust #install and configure rust
RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2020-12-07 -y &&\ RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain nightly-2021-01-15 -y &&\
rustup component add rustfmt clippy &&\ rustup component add rustfmt clippy &&\
rustup component add rust-std --target wasm32-unknown-unknown rustup component add rust-std --target wasm32-unknown-unknown

3938
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,3 @@
use rsass;
use ructe::Ructe; use ructe::Ructe;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::{ffi::OsStr, fs::*, io::Write, path::*}; use std::{ffi::OsStr, fs::*, io::Write, path::*};

View File

@ -1,5 +1,3 @@
use dotenv;
use clap::App; use clap::App;
use diesel::Connection; use diesel::Connection;
use plume_models::{instance::Instance, Connection as Conn, CONFIG}; use plume_models::{instance::Instance, Connection as Conn, CONFIG};

View File

@ -106,7 +106,7 @@ fn refill<'a>(args: &ArgMatches<'a>, conn: &Connection, searcher: Option<Searche
searcher.commit(); searcher.commit();
} }
fn unlock<'a>(args: &ArgMatches<'a>) { fn unlock(args: &ArgMatches) {
let path = match args.value_of("path") { let path = match args.value_of("path") {
None => Path::new(&CONFIG.search_index), None => Path::new(&CONFIG.search_index),
Some(x) => Path::new(x), Some(x) => Path::new(x),

View File

@ -1,7 +1,6 @@
use clap::{App, Arg, ArgMatches, SubCommand}; use clap::{App, Arg, ArgMatches, SubCommand};
use plume_models::{instance::Instance, users::*, Connection}; use plume_models::{instance::Instance, users::*, Connection};
use rpassword;
use std::io::{self, Write}; use std::io::{self, Write};
pub fn command<'a, 'b>() -> App<'a, 'b> { pub fn command<'a, 'b>() -> App<'a, 'b> {

View File

@ -7,7 +7,6 @@ use rocket::{
response::{Responder, Response}, response::{Responder, Response},
Outcome, Outcome,
}; };
use serde_json;
use tokio::prelude::*; use tokio::prelude::*;
use tracing::{debug, warn}; use tracing::{debug, warn};

View File

@ -1,4 +1,3 @@
use base64;
use chrono::{offset::Utc, DateTime}; use chrono::{offset::Utc, DateTime};
use openssl::hash::{Hasher, MessageDigest}; use openssl::hash::{Hasher, MessageDigest};
use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, DATE, USER_AGENT}; use reqwest::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, DATE, USER_AGENT};
@ -10,6 +9,9 @@ use crate::activity_pub::{ap_accept_header, AP_CONTENT_TYPE};
const PLUME_USER_AGENT: &str = concat!("Plume/", env!("CARGO_PKG_VERSION")); const PLUME_USER_AGENT: &str = concat!("Plume/", env!("CARGO_PKG_VERSION"));
#[derive(Debug)]
pub struct Error();
pub struct Digest(String); pub struct Digest(String);
impl Digest { impl Digest {
@ -62,16 +64,16 @@ impl Digest {
base64::decode(&self.0[pos..]).expect("Digest::value: invalid encoding error") base64::decode(&self.0[pos..]).expect("Digest::value: invalid encoding error")
} }
pub fn from_header(dig: &str) -> Result<Self, ()> { pub fn from_header(dig: &str) -> Result<Self, Error> {
if let Some(pos) = dig.find('=') { if let Some(pos) = dig.find('=') {
let pos = pos + 1; let pos = pos + 1;
if base64::decode(&dig[pos..]).is_ok() { if base64::decode(&dig[pos..]).is_ok() {
Ok(Digest(dig.to_owned())) Ok(Digest(dig.to_owned()))
} else { } else {
Err(()) Err(Error())
} }
} else { } else {
Err(()) Err(Error())
} }
} }
@ -110,7 +112,7 @@ pub fn headers() -> HeaderMap {
headers headers
} }
pub fn signature<S: Signer>(signer: &S, headers: &HeaderMap) -> Result<HeaderValue, ()> { pub fn signature<S: Signer>(signer: &S, headers: &HeaderMap) -> Result<HeaderValue, Error> {
let signed_string = headers let signed_string = headers
.iter() .iter()
.map(|(h, v)| { .map(|(h, v)| {
@ -130,7 +132,7 @@ pub fn signature<S: Signer>(signer: &S, headers: &HeaderMap) -> Result<HeaderVal
.join(" ") .join(" ")
.to_lowercase(); .to_lowercase();
let data = signer.sign(&signed_string).map_err(|_| ())?; let data = signer.sign(&signed_string).map_err(|_| Error())?;
let sign = base64::encode(&data); let sign = base64::encode(&data);
HeaderValue::from_str(&format!( HeaderValue::from_str(&format!(
@ -138,5 +140,5 @@ pub fn signature<S: Signer>(signer: &S, headers: &HeaderMap) -> Result<HeaderVal
key_id = signer.get_key_id(), key_id = signer.get_key_id(),
signed_headers = signed_headers, signed_headers = signed_headers,
signature = sign signature = sign
)).map_err(|_| ()) )).map_err(|_| Error())
} }

View File

@ -1,10 +1,7 @@
use super::request; use super::request;
use base64;
use chrono::{naive::NaiveDateTime, DateTime, Duration, Utc}; use chrono::{naive::NaiveDateTime, DateTime, Duration, Utc};
use hex;
use openssl::{pkey::PKey, rsa::Rsa, sha::sha256}; use openssl::{pkey::PKey, rsa::Rsa, sha::sha256};
use rocket::http::HeaderMap; use rocket::http::HeaderMap;
use serde_json;
/// Returns (public key, private key) /// Returns (public key, private key)
pub fn gen_keypair() -> (Vec<u8>, Vec<u8>) { pub fn gen_keypair() -> (Vec<u8>, Vec<u8>) {
@ -20,6 +17,9 @@ pub fn gen_keypair() -> (Vec<u8>, Vec<u8>) {
) )
} }
#[derive(Debug)]
pub struct Error();
pub trait Signer { pub trait Signer {
type Error; type Error;
@ -32,7 +32,7 @@ pub trait Signer {
} }
pub trait Signable { pub trait Signable {
fn sign<T>(&mut self, creator: &T) -> Result<&mut Self, ()> fn sign<T>(&mut self, creator: &T) -> Result<&mut Self, Error>
where where
T: Signer; T: Signer;
fn verify<T>(self, creator: &T) -> bool fn verify<T>(self, creator: &T) -> bool
@ -46,7 +46,7 @@ pub trait Signable {
} }
impl Signable for serde_json::Value { impl Signable for serde_json::Value {
fn sign<T: Signer>(&mut self, creator: &T) -> Result<&mut serde_json::Value, ()> { fn sign<T: Signer>(&mut self, creator: &T) -> Result<&mut serde_json::Value, Error> {
let creation_date = Utc::now().to_rfc3339(); let creation_date = Utc::now().to_rfc3339();
let mut options = json!({ let mut options = json!({
"type": "RsaSignature2017", "type": "RsaSignature2017",
@ -64,7 +64,7 @@ impl Signable for serde_json::Value {
let document_hash = Self::hash(&self.to_string()); let document_hash = Self::hash(&self.to_string());
let to_be_signed = options_hash + &document_hash; let to_be_signed = options_hash + &document_hash;
let signature = base64::encode(&creator.sign(&to_be_signed).map_err(|_| ())?); let signature = base64::encode(&creator.sign(&to_be_signed).map_err(|_| Error())?);
options["signatureValue"] = serde_json::Value::String(signature); options["signatureValue"] = serde_json::Value::String(signature);
self["signature"] = options; self["signature"] = options;

3
plume-common/src/lib.rs Normal file → Executable file
View File

@ -2,9 +2,6 @@
#[macro_use] #[macro_use]
extern crate activitystreams_derive; extern crate activitystreams_derive;
use activitystreams_traits;
use serde;
#[macro_use] #[macro_use]
extern crate shrinkwraprs; extern crate shrinkwraprs;
#[macro_use] #[macro_use]

View File

@ -60,6 +60,7 @@ fn to_inline(tag: Tag<'_>) -> Tag<'_> {
struct HighlighterContext { struct HighlighterContext {
content: Vec<String>, content: Vec<String>,
} }
#[allow(clippy::unnecessary_wraps)]
fn highlight_code<'a>( fn highlight_code<'a>(
context: &mut Option<HighlighterContext>, context: &mut Option<HighlighterContext>,
evt: Event<'a>, evt: Event<'a>,
@ -119,6 +120,7 @@ fn highlight_code<'a>(
_ => Some(vec![evt]), _ => Some(vec![evt]),
} }
} }
#[allow(clippy::unnecessary_wraps)]
fn flatten_text<'a>(state: &mut Option<String>, evt: Event<'a>) -> Option<Vec<Event<'a>>> { fn flatten_text<'a>(state: &mut Option<String>, evt: Event<'a>) -> Option<Vec<Event<'a>>> {
let (s, res) = match evt { let (s, res) = match evt {
Event::Text(txt) => match state.take() { Event::Text(txt) => match state.take() {
@ -137,6 +139,7 @@ fn flatten_text<'a>(state: &mut Option<String>, evt: Event<'a>) -> Option<Vec<Ev
Some(res) Some(res)
} }
#[allow(clippy::unnecessary_wraps)]
fn inline_tags<'a>( fn inline_tags<'a>(
(state, inline): &mut (Vec<Tag<'a>>, bool), (state, inline): &mut (Vec<Tag<'a>>, bool),
evt: Event<'a>, evt: Event<'a>,

View File

@ -1,6 +1,5 @@
use crate::CATALOG; use crate::CATALOG;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json;
use std::sync::Mutex; use std::sync::Mutex;
use stdweb::{ use stdweb::{
unstable::{TryFrom, TryInto}, unstable::{TryFrom, TryInto},

8
plume-macro/src/lib.rs Normal file → Executable file
View File

@ -89,12 +89,12 @@ fn file_to_migration(file: &str) -> TokenStream2 {
let mut actions = vec![]; let mut actions = vec![];
for line in file.lines() { for line in file.lines() {
if sql { if sql {
if line.starts_with("--#!") { if let Some(acc_str) = line.strip_prefix("--#!") {
if !acc.trim().is_empty() { if !acc.trim().is_empty() {
actions.push(quote!(Action::Sql(#acc))); actions.push(quote!(Action::Sql(#acc)));
} }
sql = false; sql = false;
acc = line[4..].to_string(); acc = acc_str.to_string();
acc.push('\n'); acc.push('\n');
} else if line.starts_with("--") { } else if line.starts_with("--") {
continue; continue;
@ -102,8 +102,8 @@ fn file_to_migration(file: &str) -> TokenStream2 {
acc.push_str(line); acc.push_str(line);
acc.push('\n'); acc.push('\n');
} }
} else if line.starts_with("--#!") { } else if let Some(acc_str) = line.strip_prefix("--#!") {
acc.push_str(&line[4..]); acc.push_str(&acc_str);
acc.push('\n'); acc.push('\n');
} else if line.starts_with("--") { } else if line.starts_with("--") {
continue; continue;

View File

@ -23,7 +23,7 @@ scheduled-thread-pool = "0.2.2"
serde = "1.0" serde = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0" serde_json = "1.0"
tantivy = "0.12.0" tantivy = "0.13.3"
url = "2.1" url = "2.1"
walkdir = "2.2" walkdir = "2.2"
webfinger = "0.4.1" webfinger = "0.4.1"
@ -31,7 +31,7 @@ whatlang = "0.11.1"
shrinkwraprs = "0.2.1" shrinkwraprs = "0.2.1"
diesel-derive-newtype = "0.1.2" diesel-derive-newtype = "0.1.2"
glob = "0.3.0" glob = "0.3.0"
lindera-tantivy = { version = "0.1.3", optional = true } lindera-tantivy = { version = "0.7.1", optional = true }
tracing = "0.1.22" tracing = "0.1.22"
[dependencies.chrono] [dependencies.chrono]

View File

@ -20,7 +20,6 @@ use plume_common::activity_pub::{
inbox::{AsActor, FromId}, inbox::{AsActor, FromId},
sign, ActivityStream, ApSignature, Id, IntoId, PublicKey, Source, sign, ActivityStream, ApSignature, Id, IntoId, PublicKey, Source,
}; };
use serde_json;
use url::Url; use url::Url;
use webfinger::*; use webfinger::*;
@ -217,16 +216,16 @@ impl Blog {
pub fn outbox(&self, conn: &Connection) -> Result<ActivityStream<OrderedCollection>> { pub fn outbox(&self, conn: &Connection) -> Result<ActivityStream<OrderedCollection>> {
let mut coll = OrderedCollection::default(); let mut coll = OrderedCollection::default();
coll.collection_props.items = serde_json::to_value(self.get_activities(conn)?)?; coll.collection_props.items = serde_json::to_value(self.get_activities(conn))?;
coll.collection_props coll.collection_props
.set_total_items_u64(self.get_activities(conn)?.len() as u64)?; .set_total_items_u64(self.get_activities(conn).len() as u64)?;
coll.collection_props coll.collection_props
.set_first_link(Id::new(ap_url(&format!("{}?page=1", &self.outbox_url))))?; .set_first_link(Id::new(ap_url(&format!("{}?page=1", &self.outbox_url))))?;
coll.collection_props coll.collection_props
.set_last_link(Id::new(ap_url(&format!( .set_last_link(Id::new(ap_url(&format!(
"{}?page={}", "{}?page={}",
&self.outbox_url, &self.outbox_url,
(self.get_activities(conn)?.len() as u64 + ITEMS_PER_PAGE as u64 - 1) as u64 (self.get_activities(conn).len() as u64 + ITEMS_PER_PAGE as u64 - 1) as u64
/ ITEMS_PER_PAGE as u64 / ITEMS_PER_PAGE as u64
))))?; ))))?;
Ok(ActivityStream::new(coll)) Ok(ActivityStream::new(coll))
@ -237,7 +236,7 @@ impl Blog {
(min, max): (i32, i32), (min, max): (i32, i32),
) -> Result<ActivityStream<OrderedCollectionPage>> { ) -> Result<ActivityStream<OrderedCollectionPage>> {
let mut coll = OrderedCollectionPage::default(); let mut coll = OrderedCollectionPage::default();
let acts = self.get_activity_page(&conn, (min, max))?; let acts = self.get_activity_page(&conn, (min, max));
//This still doesn't do anything because the outbox //This still doesn't do anything because the outbox
//doesn't do anything yet //doesn't do anything yet
coll.collection_page_props.set_next_link(Id::new(&format!( coll.collection_page_props.set_next_link(Id::new(&format!(
@ -253,15 +252,15 @@ impl Blog {
coll.collection_props.items = serde_json::to_value(acts)?; coll.collection_props.items = serde_json::to_value(acts)?;
Ok(ActivityStream::new(coll)) Ok(ActivityStream::new(coll))
} }
fn get_activities(&self, _conn: &Connection) -> Result<Vec<serde_json::Value>> { fn get_activities(&self, _conn: &Connection) -> Vec<serde_json::Value> {
Ok(vec![]) vec![]
} }
fn get_activity_page( fn get_activity_page(
&self, &self,
_conn: &Connection, _conn: &Connection,
(_min, _max): (i32, i32), (_min, _max): (i32, i32),
) -> Result<Vec<serde_json::Value>> { ) -> Vec<serde_json::Value> {
Ok(vec![]) vec![]
} }
pub fn get_keypair(&self) -> Result<PKey<Private>> { pub fn get_keypair(&self) -> Result<PKey<Private>> {

View File

@ -24,7 +24,6 @@ use plume_common::{
}, },
utils, utils,
}; };
use serde_json;
use std::collections::HashSet; use std::collections::HashSet;
#[derive(Queryable, Identifiable, Clone, AsChangeset)] #[derive(Queryable, Identifiable, Clone, AsChangeset)]

View File

@ -164,8 +164,8 @@ impl Default for LogoConfig {
}; };
let mut custom_icons = env::vars() let mut custom_icons = env::vars()
.filter_map(|(var, val)| { .filter_map(|(var, val)| {
if var.starts_with("PLUME_LOGO_") { if let Some(size) = var.strip_prefix("PLUME_LOGO_") {
Some((var[11..].to_owned(), val)) Some((size.to_owned(), val))
} else { } else {
None None
} }
@ -295,7 +295,7 @@ fn get_proxy_config() -> Option<ProxyConfig> {
let proxy_url = url.clone(); let proxy_url = url.clone();
let only_domains: Option<HashSet<String>> = var("PROXY_DOMAINS") let only_domains: Option<HashSet<String>> = var("PROXY_DOMAINS")
.ok() .ok()
.map(|ods| ods.split(",").map(str::to_owned).collect()); .map(|ods| ods.split(',').map(str::to_owned).collect());
let proxy = if let Some(ref only_domains) = only_domains { let proxy = if let Some(ref only_domains) = only_domains {
let only_domains = only_domains.clone(); let only_domains = only_domains.clone();
reqwest::Proxy::custom(move |url| { reqwest::Proxy::custom(move |url| {
@ -303,9 +303,7 @@ fn get_proxy_config() -> Option<ProxyConfig> {
if only_domains.contains(domain) if only_domains.contains(domain)
|| only_domains || only_domains
.iter() .iter()
.filter(|target| domain.ends_with(&format!(".{}", target))) .any(|target| domain.ends_with(&format!(".{}", target)))
.next()
.is_some()
{ {
Some(proxy_url.clone()) Some(proxy_url.clone())
} else { } else {
@ -316,9 +314,7 @@ fn get_proxy_config() -> Option<ProxyConfig> {
} }
}) })
} else { } else {
reqwest::Proxy::all(proxy_url) reqwest::Proxy::all(proxy_url).expect("Invalid PROXY_URL")
.ok()
.expect("Invalid PROXY_URL")
}; };
Some(ProxyConfig { Some(ProxyConfig {
url, url,

View File

@ -1,5 +1,4 @@
use activitypub::activity::*; use activitypub::activity::*;
use serde_json;
use crate::{ use crate::{
comments::Comment, comments::Comment,

1
plume-models/src/lib.rs Normal file → Executable file
View File

@ -11,7 +11,6 @@ extern crate lazy_static;
extern crate plume_macro; extern crate plume_macro;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
#[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use] #[macro_use]
extern crate serde_json; extern crate serde_json;

View File

@ -30,9 +30,9 @@ impl TryFrom<i32> for ListType {
} }
} }
impl Into<i32> for ListType { impl From<ListType> for i32 {
fn into(self) -> i32 { fn from(list_type: ListType) -> Self {
match self { match list_type {
ListType::User => 0, ListType::User => 0,
ListType::Blog => 1, ListType::Blog => 1,
ListType::Word => 2, ListType::Word => 2,
@ -246,22 +246,22 @@ impl List {
private::ListElem::prefix_in_list(conn, self, word) private::ListElem::prefix_in_list(conn, self, word)
} }
/// Insert new users in a list // Insert new users in a list
func! {add: add_users, User} func! {add: add_users, User}
/// Insert new blogs in a list // Insert new blogs in a list
func! {add: add_blogs, Blog} func! {add: add_blogs, Blog}
/// Insert new words in a list // Insert new words in a list
func! {add: add_words, Word} func! {add: add_words, Word}
/// Insert new prefixes in a list // Insert new prefixes in a list
func! {add: add_prefixes, Prefix} func! {add: add_prefixes, Prefix}
/// Get all users in the list // Get all users in the list
func! {list: list_users, User, users} func! {list: list_users, User, users}
/// Get all blogs in the list // Get all blogs in the list
func! {list: list_blogs, Blog, blogs} func! {list: list_blogs, Blog, blogs}
/// Get all words in the list /// Get all words in the list

View File

@ -10,7 +10,6 @@ use plume_common::{
activity_pub::{inbox::FromId, Id}, activity_pub::{inbox::FromId, Id},
utils::MediaProcessor, utils::MediaProcessor,
}; };
use reqwest;
use std::{fs, path::Path}; use std::{fs, path::Path};
#[derive(Clone, Identifiable, Queryable)] #[derive(Clone, Identifiable, Queryable)]

View File

@ -19,7 +19,6 @@ use plume_common::{
}, },
utils::md_to_html, utils::md_to_html,
}; };
use serde_json;
use std::collections::HashSet; use std::collections::HashSet;
pub type LicensedArticle = CustomObject<Licensed, Article>; pub type LicensedArticle = CustomObject<Licensed, Article>;
@ -124,8 +123,7 @@ impl Post {
.filter(posts::published.eq(true)) .filter(posts::published.eq(true))
.count() .count()
.load(conn)? .load(conn)?
.iter() .get(0)
.next()
.cloned() .cloned()
.ok_or(Error::NotFound) .ok_or(Error::NotFound)
} }
@ -288,12 +286,11 @@ impl Post {
} }
pub fn get_receivers_urls(&self, conn: &Connection) -> Result<Vec<String>> { pub fn get_receivers_urls(&self, conn: &Connection) -> Result<Vec<String>> {
let followers = self Ok(self
.get_authors(conn)? .get_authors(conn)?
.into_iter() .into_iter()
.filter_map(|a| a.get_followers(conn).ok()) .filter_map(|a| a.get_followers(conn).ok())
.collect::<Vec<Vec<User>>>(); .fold(vec![], |mut acc, f| {
Ok(followers.into_iter().fold(vec![], |mut acc, f| {
for x in f { for x in f {
acc.push(x.ap_url); acc.push(x.ap_url);
} }

View File

@ -81,6 +81,7 @@ lazy_static! {
}; };
} }
#[allow(clippy::unnecessary_wraps)]
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 url.starts_with('#') && !url.starts_with("#postcontent-") {
//if start with an # //if start with an #

View File

@ -11,7 +11,6 @@ use activitypub::{
object::{Image, Tombstone}, object::{Image, Tombstone},
Activity, CustomObject, Endpoint, Activity, CustomObject, Endpoint,
}; };
use bcrypt;
use chrono::{NaiveDateTime, Utc}; use chrono::{NaiveDateTime, Utc};
use diesel::{self, BelongingToDsl, ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl}; use diesel::{self, BelongingToDsl, ExpressionMethods, OptionalExtension, QueryDsl, RunQueryDsl};
use ldap3::{LdapConn, Scope, SearchEntry}; use ldap3::{LdapConn, Scope, SearchEntry};
@ -38,7 +37,6 @@ use rocket::{
outcome::IntoOutcome, outcome::IntoOutcome,
request::{self, FromRequest, Request}, request::{self, FromRequest, Request},
}; };
use serde_json;
use std::{ use std::{
cmp::PartialEq, cmp::PartialEq,
hash::{Hash, Hasher}, hash::{Hash, Hasher},

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
nightly-2020-01-15 nightly-2021-01-15

1
src/api/mod.rs Normal file → Executable file
View File

@ -4,7 +4,6 @@ use rocket::{
response::{self, Responder}, response::{self, Responder},
}; };
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use serde_json;
use plume_common::utils::random_hex; use plume_common::utils::random_hex;
use plume_models::{api_tokens::*, apps::App, users::User, Error, PlumeRocket}; use plume_models::{api_tokens::*, apps::App, users::User, Error, PlumeRocket};

View File

@ -28,7 +28,6 @@ use std::process::exit;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use tracing::warn; use tracing::warn;
use tracing_subscriber;
init_i18n!( init_i18n!(
"plume", af, ar, bg, ca, cs, cy, da, de, el, en, eo, es, fa, fi, fr, gl, he, hi, hr, hu, it, "plume", af, ar, bg, ca, cs, cy, da, de, el, en, eo, es, fa, fi, fr, gl, he, hi, hr, hu, it,

View File

@ -91,9 +91,11 @@ pub fn create(
}); });
Flash::success( Flash::success(
Redirect::to( Redirect::to(uri!(
uri!(super::posts::details: blog = blog_name, slug = slug, responding_to = _), super::posts::details: blog = blog_name,
), slug = slug,
responding_to = _
)),
i18n!(&rockets.intl.catalog, "Your comment has been posted."), i18n!(&rockets.intl.catalog, "Your comment has been posted."),
) )
}) })
@ -168,7 +170,11 @@ pub fn delete(
} }
} }
Ok(Flash::success( Ok(Flash::success(
Redirect::to(uri!(super::posts::details: blog = blog, slug = slug, responding_to = _)), Redirect::to(uri!(
super::posts::details: blog = blog,
slug = slug,
responding_to = _
)),
i18n!(&rockets.intl.catalog, "Your comment has been deleted."), i18n!(&rockets.intl.catalog, "Your comment has been deleted."),
)) ))
} }

View File

@ -5,7 +5,6 @@ use rocket::{
use rocket_contrib::json::Json; use rocket_contrib::json::Json;
use rocket_i18n::I18n; use rocket_i18n::I18n;
use scheduled_thread_pool::ScheduledThreadPool; use scheduled_thread_pool::ScheduledThreadPool;
use serde_json;
use std::str::FromStr; use std::str::FromStr;
use validator::{Validate, ValidationErrors}; use validator::{Validate, ValidationErrors};
@ -409,9 +408,14 @@ pub fn interact(rockets: PlumeRocket, user: Option<User>, target: String) -> Opt
} }
if let Ok(post) = Post::from_id(&rockets, &target, None, CONFIG.proxy()) { if let Ok(post) = Post::from_id(&rockets, &target, None, CONFIG.proxy()) {
return Some(Redirect::to( return Some(Redirect::to(uri!(
uri!(super::posts::details: blog = post.get_blog(&rockets.conn).expect("Can't retrieve blog").fqn, slug = &post.slug, responding_to = _), super::posts::details: blog = post
)); .get_blog(&rockets.conn)
.expect("Can't retrieve blog")
.fqn,
slug = &post.slug,
responding_to = _
)));
} }
if let Ok(comment) = Comment::from_id(&rockets, &target, None, CONFIG.proxy()) { if let Ok(comment) = Comment::from_id(&rockets, &target, None, CONFIG.proxy()) {

View File

@ -45,9 +45,11 @@ pub fn create(
.execute(move || broadcast(&user, delete_act, dest, CONFIG.proxy().cloned())); .execute(move || broadcast(&user, delete_act, dest, CONFIG.proxy().cloned()));
} }
Ok(Redirect::to( Ok(Redirect::to(uri!(
uri!(super::posts::details: blog = blog, slug = slug, responding_to = _), super::posts::details: blog = blog,
)) slug = slug,
responding_to = _
)))
} }
#[post("/~/<blog>/<slug>/like", rank = 2)] #[post("/~/<blog>/<slug>/like", rank = 2)]

View File

@ -45,7 +45,7 @@ pub fn upload(
let (_, boundary) = ct let (_, boundary) = ct
.params() .params()
.find(|&(k, _)| k == "boundary") .find(|&(k, _)| k == "boundary")
.ok_or_else(|| status::BadRequest(Some("No boundary")))?; .ok_or(status::BadRequest(Some("No boundary")))?;
if let SaveResult::Full(entries) = Multipart::with_body(data.open(), boundary).save().temp() { if let SaveResult::Full(entries) = Multipart::with_body(data.open(), boundary).save().temp() {
let fields = entries.fields; let fields = entries.fields;
@ -53,7 +53,7 @@ pub fn upload(
let filename = fields let filename = fields
.get("file") .get("file")
.and_then(|v| v.iter().next()) .and_then(|v| v.iter().next())
.ok_or_else(|| status::BadRequest(Some("No file uploaded")))? .ok_or(status::BadRequest(Some("No file uploaded")))?
.headers .headers
.filename .filename
.clone(); .clone();

View File

@ -246,8 +246,9 @@ pub fn theme_files(file: PathBuf, _build_id: &RawStr) -> Option<ThemeFile> {
.map(ThemeFile) .map(ThemeFile)
} }
#[get("/static/cached/<_build_id>/<file..>", rank = 2)] #[allow(unused_variables)]
pub fn plume_static_files(file: PathBuf, _build_id: &RawStr) -> Option<CachedFile> { #[get("/static/cached/<build_id>/<file..>", rank = 2)]
pub fn plume_static_files(file: PathBuf, build_id: &RawStr) -> Option<CachedFile> {
static_files(file) static_files(file)
} }
#[get("/static/media/<file..>")] #[get("/static/media/<file..>")]

View File

@ -356,7 +356,11 @@ pub fn update(
} }
Flash::success( Flash::success(
Redirect::to(uri!(details: blog = blog, slug = new_slug, responding_to = _)), Redirect::to(uri!(
details: blog = blog,
slug = new_slug,
responding_to = _
)),
i18n!(intl, "Your article has been updated."), i18n!(intl, "Your article has been updated."),
) )
.into() .into()
@ -543,7 +547,11 @@ pub fn create(
} }
Ok(Flash::success( Ok(Flash::success(
Redirect::to(uri!(details: blog = blog_name, slug = slug, responding_to = _)), Redirect::to(uri!(
details: blog = blog_name,
slug = slug,
responding_to = _
)),
i18n!(&rockets.intl.catalog, "Your article has been saved."), i18n!(&rockets.intl.catalog, "Your article has been saved."),
) )
.into()) .into())
@ -583,7 +591,11 @@ pub fn delete(
.any(|a| a.id == user.id) .any(|a| a.id == user.id)
{ {
return Ok(Flash::error( return Ok(Flash::error(
Redirect::to(uri!(details: blog = blog_name, slug = slug, responding_to = _)), Redirect::to(uri!(
details: blog = blog_name,
slug = slug,
responding_to = _
)),
i18n!(intl.catalog, "You are not allowed to delete this article."), i18n!(intl.catalog, "You are not allowed to delete this article."),
)); ));
} }

View File

@ -45,9 +45,11 @@ pub fn create(
.execute(move || broadcast(&user, delete_act, dest, CONFIG.proxy().cloned())); .execute(move || broadcast(&user, delete_act, dest, CONFIG.proxy().cloned()));
} }
Ok(Redirect::to( Ok(Redirect::to(uri!(
uri!(super::posts::details: blog = blog, slug = slug, responding_to = _), super::posts::details: blog = blog,
)) slug = slug,
responding_to = _
)))
} }
#[post("/~/<blog>/<slug>/reshare", rank = 1)] #[post("/~/<blog>/<slug>/reshare", rank = 1)]

View File

@ -55,8 +55,7 @@ pub fn search(query: Option<Form<SearchQuery>>, rockets: PlumeRocket) -> Ructe {
let query = query.map(Form::into_inner).unwrap_or_default(); let query = query.map(Form::into_inner).unwrap_or_default();
let page = query.page.unwrap_or_default(); let page = query.page.unwrap_or_default();
let mut parsed_query = let mut parsed_query =
Query::from_str(&query.q.as_ref().map(String::as_str).unwrap_or_default()) Query::from_str(&query.q.as_deref().unwrap_or_default()).unwrap_or_default();
.unwrap_or_default();
param_to_query!(query, parsed_query; normal: title, subtitle, content, tag, param_to_query!(query, parsed_query; normal: title, subtitle, content, tag,
instance, author, blog, lang, license; instance, author, blog, lang, license;

View File

@ -210,9 +210,7 @@ pub fn password_reset(
.map_err(|err| password_reset_error_response(err, &rockets))?; .map_err(|err| password_reset_error_response(err, &rockets))?;
Ok(Flash::success( Ok(Flash::success(
Redirect::to(uri!( Redirect::to(uri!(new: m = _)),
new: m = _
)),
i18n!( i18n!(
rockets.intl.catalog, rockets.intl.catalog,
"Your password was successfully reset." "Your password was successfully reset."

View File

@ -9,7 +9,6 @@ use rocket::{
response::{status, Content, Flash, Redirect}, response::{status, Content, Flash, Redirect},
}; };
use rocket_i18n::I18n; use rocket_i18n::I18n;
use serde_json;
use std::{borrow::Cow, collections::HashMap}; use std::{borrow::Cow, collections::HashMap};
use tracing::{info, warn}; use tracing::{info, warn};
use validator::{Validate, ValidationError, ValidationErrors}; use validator::{Validate, ValidationError, ValidationErrors};
@ -379,9 +378,10 @@ pub struct UpdateUserForm {
pub hide_custom_css: bool, pub hide_custom_css: bool,
} }
#[put("/@/<_name>/edit", data = "<form>")] #[allow(unused_variables)]
#[put("/@/<name>/edit", data = "<form>")]
pub fn update( pub fn update(
_name: String, name: String,
conn: DbConn, conn: DbConn,
mut user: User, mut user: User,
form: LenientForm<UpdateUserForm>, form: LenientForm<UpdateUserForm>,
@ -402,7 +402,7 @@ pub fn update(
user.preferred_theme = form user.preferred_theme = form
.theme .theme
.clone() .clone()
.and_then(|t| if &t == "" { None } else { Some(t) }); .and_then(|t| if t.is_empty() { None } else { Some(t) });
user.hide_custom_css = form.hide_custom_css; user.hide_custom_css = form.hide_custom_css;
let _: User = user.save_changes(&*conn).map_err(Error::from)?; let _: User = user.save_changes(&*conn).map_err(Error::from)?;

View File

@ -1,6 +1,5 @@
use rocket::http::ContentType; use rocket::http::ContentType;
use rocket::response::Content; use rocket::response::Content;
use serde_json;
use webfinger::*; use webfinger::*;
use plume_models::{ap_url, blogs::Blog, users::User, PlumeRocket, CONFIG}; use plume_models::{ap_url, blogs::Blog, users::User, PlumeRocket, CONFIG};

View File

@ -12,9 +12,9 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>@title ⋅ @i18n!(ctx.1, "Plume")</title> <title>@title ⋅ @i18n!(ctx.1, "Plume")</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(ctx.2.clone().and_then(|u| u.preferred_theme).unwrap_or_else(|| CONFIG.default_theme.clone())).join("theme.css"), _build_id = CACHE_NAME)" /> <link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(ctx.2.clone().and_then(|u| u.preferred_theme).unwrap_or_else(|| CONFIG.default_theme.clone())).join("theme.css"), build_id = CACHE_NAME)" />
<link rel="manifest" href="@uri!(instance::web_manifest)" /> <link rel="manifest" href="@uri!(instance::web_manifest)" />
<link rel="icon" type="image/png" href="@uri!(plume_static_files: file = CONFIG.logo.favicon.as_str(), _build_id = CACHE_NAME)"> <link rel="icon" type="image/png" href="@uri!(plume_static_files: file = CONFIG.logo.favicon.as_str(), build_id = CACHE_NAME)">
<meta content='#282c37' name='theme-color'/> <meta content='#282c37' name='theme-color'/>
@:head() @:head()
</head> </head>
@ -26,7 +26,7 @@
<div id="content"> <div id="content">
<nav> <nav>
<a href="@uri!(instance::index)" class="title"> <a href="@uri!(instance::index)" class="title">
<img src="@uri!(plume_static_files: file = CONFIG.logo.main.as_str(), _build_id = CACHE_NAME)"> <img src="@uri!(plume_static_files: file = CONFIG.logo.main.as_str(), build_id = CACHE_NAME)">
<p>@i18n!(ctx.1, "Plume")</p> <p>@i18n!(ctx.1, "Plume")</p>
</a> </a>
<hr/> <hr/>
@ -96,6 +96,6 @@
<a href="https://matrix.to/#/#plume-blog:matrix.org">@i18n!(ctx.1, "Matrix room")</a> <a href="https://matrix.to/#/#plume-blog:matrix.org">@i18n!(ctx.1, "Matrix room")</a>
</div> </div>
</footer> </footer>
<script src="@uri!(plume_static_files: file = "plume-front.js", _build_id = CACHE_NAME)"></script> <script src="@uri!(plume_static_files: file = "plume-front.js", build_id = CACHE_NAME)"></script>
</body> </body>
</html> </html>

View File

@ -27,7 +27,7 @@
<link href='@blog.ap_url' rel='canonical'> <link href='@blog.ap_url' rel='canonical'>
@if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) { @if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) {
@if let Some(ref theme) = blog.theme { @if let Some(ref theme) = blog.theme {
<link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(theme).join("theme.css"), _build_id = CACHE_NAME)"> <link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(theme).join("theme.css"), build_id = CACHE_NAME)">
} }
} }
}, { }, {

View File

@ -42,7 +42,7 @@
} }
</main> </main>
@for res in &comment_tree.responses { @for res in &comment_tree.responses {
@:comment_html(ctx, res, comm.ap_url.as_ref().map(|u| &**u), blog, slug) @:comment_html(ctx, res, comm.ap_url.as_deref(), blog, slug)
} }
</div> </div>
}} }}

View File

@ -24,7 +24,7 @@
@if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) { @if !ctx.2.clone().map(|u| u.hide_custom_css).unwrap_or(false) {
@if let Some(ref theme) = blog.theme { @if let Some(ref theme) = blog.theme {
<link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(theme).join("theme.css"), _build_id = CACHE_NAME)"> <link rel="stylesheet" href="@uri!(plume_static_files: file = Path::new("css").join(theme).join("theme.css"), build_id = CACHE_NAME)">
} }
} }
}, { }, {

View File

@ -14,7 +14,7 @@
@i18n!(ctx.1, "To change your avatar, upload it to your gallery and then select from there.") @i18n!(ctx.1, "To change your avatar, upload it to your gallery and then select from there.")
<a href="@uri!(medias::new)">@i18n!(ctx.1, "Upload an avatar")</a> <a href="@uri!(medias::new)">@i18n!(ctx.1, "Upload an avatar")</a>
</p> </p>
<form method="post" action="@uri!(user::update: _name = u.username.clone())"> <form method="post" action="@uri!(user::update: name = u.username.clone())">
<!-- Rocket hack to use various HTTP methods --> <!-- Rocket hack to use various HTTP methods -->
<input type=hidden name="_method" value="put"> <input type=hidden name="_method" value="put">