Merge branch 'main' of https://github.com/lemmynet/lemmy
This commit is contained in:
commit
ca3c1269f5
44 changed files with 327 additions and 269 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -3655,9 +3655,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
|
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
|
|
|
@ -45,7 +45,7 @@ actix-web = { version = "3.3.2", default-features = false, features = ["rustls"]
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
env_logger = "0.8.2"
|
env_logger = "0.8.2"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||||
tokio = "0.3.6"
|
tokio = "0.3.6"
|
||||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
check_optional_url,
|
|
||||||
get_user_from_jwt,
|
get_user_from_jwt,
|
||||||
get_user_from_jwt_opt,
|
get_user_from_jwt_opt,
|
||||||
is_admin,
|
is_admin,
|
||||||
|
@ -19,7 +18,7 @@ use lemmy_apub::{
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_queries::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite_to_url,
|
||||||
source::{
|
source::{
|
||||||
comment::Comment_,
|
comment::Comment_,
|
||||||
community::{CommunityModerator_, Community_},
|
community::{CommunityModerator_, Community_},
|
||||||
|
@ -155,11 +154,8 @@ impl Perform for CreateCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure the icon and banners are urls
|
// Check to make sure the icon and banners are urls
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
check_optional_url(&icon)?;
|
|
||||||
check_optional_url(&banner)?;
|
|
||||||
|
|
||||||
// When you create a community, make sure the user becomes a moderator and a follower
|
// When you create a community, make sure the user becomes a moderator and a follower
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
|
@ -260,11 +256,8 @@ impl Perform for EditCommunity {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
check_optional_url(&icon)?;
|
|
||||||
check_optional_url(&banner)?;
|
|
||||||
|
|
||||||
let community_form = CommunityForm {
|
let community_form = CommunityForm {
|
||||||
name: read_community.name,
|
name: read_community.name,
|
||||||
|
|
|
@ -186,15 +186,6 @@ pub(crate) async fn collect_moderated_communities(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_optional_url(item: &Option<Option<String>>) -> Result<(), LemmyError> {
|
|
||||||
if let Some(Some(item)) = &item {
|
|
||||||
if Url::parse(item).is_err() {
|
|
||||||
return Err(ApiError::err("invalid_url").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn build_federated_instances(
|
pub(crate) async fn build_federated_instances(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<Option<FederatedInstances>, LemmyError> {
|
) -> Result<Option<FederatedInstances>, LemmyError> {
|
||||||
|
@ -474,6 +465,15 @@ pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
|
||||||
Ok(base64)
|
Ok(base64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks the password length
|
||||||
|
pub(crate) fn password_length_check(pass: &str) -> Result<(), LemmyError> {
|
||||||
|
if pass.len() > 60 {
|
||||||
|
Err(ApiError::err("invalid_password").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::captcha_espeak_wav_base64;
|
use crate::captcha_espeak_wav_base64;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
check_downvotes_enabled,
|
check_downvotes_enabled,
|
||||||
check_optional_url,
|
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
get_user_from_jwt,
|
get_user_from_jwt,
|
||||||
get_user_from_jwt_opt,
|
get_user_from_jwt_opt,
|
||||||
|
@ -72,15 +71,14 @@ impl Perform for CreatePost {
|
||||||
|
|
||||||
check_community_ban(user.id, data.community_id, context.pool()).await?;
|
check_community_ban(user.id, data.community_id, context.pool()).await?;
|
||||||
|
|
||||||
check_optional_url(&Some(data.url.to_owned()))?;
|
|
||||||
|
|
||||||
// Fetch Iframely and pictrs cached image
|
// Fetch Iframely and pictrs cached image
|
||||||
|
let data_url = data.url.as_ref();
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await;
|
fetch_iframely_and_pictrs_data(context.client(), data_url).await;
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.trim().to_owned(),
|
name: data.name.trim().to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data_url.map(|u| u.to_owned().into()),
|
||||||
body: data.body.to_owned(),
|
body: data.body.to_owned(),
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
creator_id: user.id,
|
creator_id: user.id,
|
||||||
|
@ -93,7 +91,7 @@ impl Perform for CreatePost {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: None,
|
ap_id: None,
|
||||||
local: true,
|
local: true,
|
||||||
published: None,
|
published: None,
|
||||||
|
@ -385,12 +383,13 @@ impl Perform for EditPost {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch Iframely and Pictrs cached image
|
// Fetch Iframely and Pictrs cached image
|
||||||
|
let data_url = data.url.as_ref();
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await;
|
fetch_iframely_and_pictrs_data(context.client(), data_url).await;
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.trim().to_owned(),
|
name: data.name.trim().to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data_url.map(|u| u.to_owned().into()),
|
||||||
body: data.body.to_owned(),
|
body: data.body.to_owned(),
|
||||||
nsfw: data.nsfw,
|
nsfw: data.nsfw,
|
||||||
creator_id: orig_post.creator_id.to_owned(),
|
creator_id: orig_post.creator_id.to_owned(),
|
||||||
|
@ -403,7 +402,7 @@ impl Perform for EditPost {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: Some(orig_post.ap_id),
|
ap_id: Some(orig_post.ap_id),
|
||||||
local: orig_post.local,
|
local: orig_post.local,
|
||||||
published: None,
|
published: None,
|
||||||
|
|
|
@ -11,7 +11,13 @@ use actix_web::web::Data;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_structs::{blocking, site::*, user::Register};
|
use lemmy_api_structs::{blocking, site::*, user::Register};
|
||||||
use lemmy_apub::fetcher::search::search_by_apub_id;
|
use lemmy_apub::fetcher::search::search_by_apub_id;
|
||||||
use lemmy_db_queries::{diesel_option_overwrite, source::site::Site_, Crud, SearchType, SortType};
|
use lemmy_db_queries::{
|
||||||
|
diesel_option_overwrite_to_url,
|
||||||
|
source::site::Site_,
|
||||||
|
Crud,
|
||||||
|
SearchType,
|
||||||
|
SortType,
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::{
|
source::{
|
||||||
|
@ -157,8 +163,8 @@ impl Perform for CreateSite {
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
description: data.description.to_owned(),
|
description: data.description.to_owned(),
|
||||||
icon: Some(data.icon.to_owned()),
|
icon: Some(data.icon.to_owned().map(|url| url.into())),
|
||||||
banner: Some(data.banner.to_owned()),
|
banner: Some(data.banner.to_owned().map(|url| url.into())),
|
||||||
creator_id: user.id,
|
creator_id: user.id,
|
||||||
enable_downvotes: data.enable_downvotes,
|
enable_downvotes: data.enable_downvotes,
|
||||||
open_registration: data.open_registration,
|
open_registration: data.open_registration,
|
||||||
|
@ -196,8 +202,8 @@ impl Perform for EditSite {
|
||||||
|
|
||||||
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
captcha_espeak_wav_base64,
|
captcha_espeak_wav_base64,
|
||||||
check_optional_url,
|
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
get_user_from_jwt,
|
get_user_from_jwt,
|
||||||
get_user_from_jwt_opt,
|
get_user_from_jwt_opt,
|
||||||
is_admin,
|
is_admin,
|
||||||
|
password_length_check,
|
||||||
Perform,
|
Perform,
|
||||||
};
|
};
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
|
@ -23,6 +23,7 @@ use lemmy_apub::{
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_queries::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
|
diesel_option_overwrite_to_url,
|
||||||
source::{
|
source::{
|
||||||
comment::Comment_,
|
comment::Comment_,
|
||||||
community::Community_,
|
community::Community_,
|
||||||
|
@ -144,10 +145,7 @@ impl Perform for Register {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Password length check
|
password_length_check(&data.password)?;
|
||||||
if data.password.len() > 60 {
|
|
||||||
return Err(ApiError::err("invalid_password").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure passwords match
|
// Make sure passwords match
|
||||||
if data.password != data.password_verify {
|
if data.password != data.password_verify {
|
||||||
|
@ -366,17 +364,13 @@ impl Perform for SaveUserSettings {
|
||||||
let data: &SaveUserSettings = &self;
|
let data: &SaveUserSettings = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let avatar = diesel_option_overwrite(&data.avatar);
|
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
let email = diesel_option_overwrite(&data.email);
|
let email = diesel_option_overwrite(&data.email);
|
||||||
let bio = diesel_option_overwrite(&data.bio);
|
let bio = diesel_option_overwrite(&data.bio);
|
||||||
let preferred_username = diesel_option_overwrite(&data.preferred_username);
|
let preferred_username = diesel_option_overwrite(&data.preferred_username);
|
||||||
let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
|
let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
|
||||||
|
|
||||||
// Check to make sure the avatar and banners are urls
|
|
||||||
check_optional_url(&avatar)?;
|
|
||||||
check_optional_url(&banner)?;
|
|
||||||
|
|
||||||
if let Some(Some(bio)) = &bio {
|
if let Some(Some(bio)) = &bio {
|
||||||
if bio.chars().count() > 300 {
|
if bio.chars().count() > 300 {
|
||||||
return Err(ApiError::err("bio_length_overflow").into());
|
return Err(ApiError::err("bio_length_overflow").into());
|
||||||
|
@ -394,6 +388,8 @@ impl Perform for SaveUserSettings {
|
||||||
Some(new_password) => {
|
Some(new_password) => {
|
||||||
match &data.new_password_verify {
|
match &data.new_password_verify {
|
||||||
Some(new_password_verify) => {
|
Some(new_password_verify) => {
|
||||||
|
password_length_check(&new_password)?;
|
||||||
|
|
||||||
// Make sure passwords match
|
// Make sure passwords match
|
||||||
if new_password != new_password_verify {
|
if new_password != new_password_verify {
|
||||||
return Err(ApiError::err("passwords_dont_match").into());
|
return Err(ApiError::err("passwords_dont_match").into());
|
||||||
|
@ -993,6 +989,8 @@ impl Perform for PasswordChange {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
password_length_check(&data.password)?;
|
||||||
|
|
||||||
// Make sure passwords match
|
// Make sure passwords match
|
||||||
if data.password != data.password_verify {
|
if data.password != data.password_verify {
|
||||||
return Err(ApiError::err("passwords_dont_match").into());
|
return Err(ApiError::err("passwords_dont_match").into());
|
||||||
|
|
|
@ -21,4 +21,4 @@ diesel = "1.4.5"
|
||||||
actix-web = "3.3.2"
|
actix-web = "3.3.2"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
||||||
url = "2.2.0"
|
url = "2.2.1"
|
||||||
|
|
|
@ -8,11 +8,12 @@ use lemmy_db_views_actor::{
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct CreatePost {
|
pub struct CreatePost {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<Url>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
|
@ -66,7 +67,7 @@ pub struct CreatePostLike {
|
||||||
pub struct EditPost {
|
pub struct EditPost {
|
||||||
pub post_id: i32,
|
pub post_id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<Url>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
|
|
@ -13,6 +13,7 @@ use lemmy_db_views_moderator::{
|
||||||
mod_sticky_post_view::ModStickyPostView,
|
mod_sticky_post_view::ModStickyPostView,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Search {
|
pub struct Search {
|
||||||
|
@ -60,8 +61,8 @@ pub struct GetModlogResponse {
|
||||||
pub struct CreateSite {
|
pub struct CreateSite {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<Url>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<Url>,
|
||||||
pub enable_downvotes: bool,
|
pub enable_downvotes: bool,
|
||||||
pub open_registration: bool,
|
pub open_registration: bool,
|
||||||
pub enable_nsfw: bool,
|
pub enable_nsfw: bool,
|
||||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
|
|
|
@ -7,6 +7,7 @@ use lemmy_db_schema::source::activity::Activity;
|
||||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
@ -46,12 +47,13 @@ pub async fn get_activity(
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let settings = Settings::get();
|
let settings = Settings::get();
|
||||||
let activity_id = format!(
|
let activity_id = Url::parse(&format!(
|
||||||
"{}/activities/{}/{}",
|
"{}/activities/{}/{}",
|
||||||
settings.get_protocol_and_hostname(),
|
settings.get_protocol_and_hostname(),
|
||||||
info.type_,
|
info.type_,
|
||||||
info.id
|
info.id
|
||||||
);
|
))?
|
||||||
|
.into();
|
||||||
let activity = blocking(context.pool(), move |conn| {
|
let activity = blocking(context.pool(), move |conn| {
|
||||||
Activity::read_from_apub_id(&conn, &activity_id)
|
Activity::read_from_apub_id(&conn, &activity_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -45,7 +45,7 @@ pub(crate) async fn is_activity_already_known(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
activity_id: &Url,
|
activity_id: &Url,
|
||||||
) -> Result<bool, LemmyError> {
|
) -> Result<bool, LemmyError> {
|
||||||
let activity_id = activity_id.to_string();
|
let activity_id = activity_id.to_owned().into();
|
||||||
let existing = blocking(pool, move |conn| {
|
let existing = blocking(pool, move |conn| {
|
||||||
Activity::read_from_apub_id(&conn, &activity_id)
|
Activity::read_from_apub_id(&conn, &activity_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -120,9 +120,9 @@ pub(in crate::inbox) async fn receive_like_for_community(
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => receive_like_post(like, post, context, request_counter).await,
|
PostOrComment::Post(post) => receive_like_post(like, *post, context, request_counter).await,
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_like_comment(like, comment, context, request_counter).await
|
receive_like_comment(like, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,10 +152,10 @@ pub(in crate::inbox) async fn receive_dislike_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_dislike_post(dislike, post, context, request_counter).await
|
receive_dislike_post(dislike, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_dislike_comment(dislike, comment, context, request_counter).await
|
receive_dislike_comment(dislike, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,8 @@ pub(in crate::inbox) async fn receive_delete_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_delete_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_delete_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -215,8 +215,8 @@ pub(in crate::inbox) async fn receive_remove_for_community(
|
||||||
remove.id(community_id.domain().context(location_info!())?)?;
|
remove.id(community_id.domain().context(location_info!())?)?;
|
||||||
|
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_remove_post(context, remove, p).await,
|
Ok(PostOrComment::Post(p)) => receive_remove_post(context, remove, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -276,8 +276,8 @@ pub(in crate::inbox) async fn receive_undo_delete_for_community(
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_undo_delete_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_undo_delete_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_undo_delete_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_undo_delete_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -300,8 +300,8 @@ pub(in crate::inbox) async fn receive_undo_remove_for_community(
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_undo_remove_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_undo_remove_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_undo_remove_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_undo_remove_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -325,10 +325,10 @@ pub(in crate::inbox) async fn receive_undo_like_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_undo_like_post(&like, post, context, request_counter).await
|
receive_undo_like_post(&like, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_undo_like_comment(&like, comment, context, request_counter).await
|
receive_undo_like_comment(&like, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,10 +351,10 @@ pub(in crate::inbox) async fn receive_undo_dislike_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_undo_dislike_post(&dislike, post, context, request_counter).await
|
receive_undo_dislike_post(&dislike, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_undo_dislike_comment(&dislike, comment, context, request_counter).await
|
receive_undo_dislike_comment(&dislike, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,11 +365,11 @@ async fn fetch_post_or_comment_by_id(
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<PostOrComment, LemmyError> {
|
) -> Result<PostOrComment, LemmyError> {
|
||||||
if let Ok(post) = get_or_fetch_and_insert_post(apub_id, context, request_counter).await {
|
if let Ok(post) = get_or_fetch_and_insert_post(apub_id, context, request_counter).await {
|
||||||
return Ok(PostOrComment::Post(post));
|
return Ok(PostOrComment::Post(Box::new(post)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(comment) = get_or_fetch_and_insert_comment(apub_id, context, request_counter).await {
|
if let Ok(comment) = get_or_fetch_and_insert_comment(apub_id, context, request_counter).await {
|
||||||
return Ok(PostOrComment::Comment(comment));
|
return Ok(PostOrComment::Comment(Box::new(comment)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
|
|
|
@ -26,13 +26,16 @@ use anyhow::{anyhow, Context};
|
||||||
use diesel::NotFound;
|
use diesel::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{source::activity::Activity_, ApubObject, DbPool};
|
use lemmy_db_queries::{source::activity::Activity_, ApubObject, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
activity::Activity,
|
source::{
|
||||||
comment::Comment,
|
activity::Activity,
|
||||||
community::Community,
|
comment::Comment,
|
||||||
post::Post,
|
community::Community,
|
||||||
private_message::PrivateMessage,
|
post::Post,
|
||||||
user::User_,
|
private_message::PrivateMessage,
|
||||||
|
user::User_,
|
||||||
|
},
|
||||||
|
DbUrl,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -216,7 +219,7 @@ pub enum EndpointType {
|
||||||
pub fn generate_apub_endpoint(
|
pub fn generate_apub_endpoint(
|
||||||
endpoint_type: EndpointType,
|
endpoint_type: EndpointType,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
) -> Result<DbUrl, ParseError> {
|
||||||
let point = match endpoint_type {
|
let point = match endpoint_type {
|
||||||
EndpointType::Community => "c",
|
EndpointType::Community => "c",
|
||||||
EndpointType::User => "u",
|
EndpointType::User => "u",
|
||||||
|
@ -236,21 +239,15 @@ pub fn generate_apub_endpoint(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_followers_url(
|
pub fn generate_followers_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
|
||||||
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
|
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_inbox_url(
|
pub fn generate_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
|
||||||
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
|
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_shared_inbox_url(
|
pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, LemmyError> {
|
|
||||||
let actor_id = actor_id.clone().into_inner();
|
let actor_id = actor_id.clone().into_inner();
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}://{}{}/inbox",
|
"{}://{}{}/inbox",
|
||||||
|
@ -277,7 +274,7 @@ pub(crate) async fn insert_activity<T>(
|
||||||
where
|
where
|
||||||
T: Serialize + std::fmt::Debug + Send + 'static,
|
T: Serialize + std::fmt::Debug + Send + 'static,
|
||||||
{
|
{
|
||||||
let ap_id = ap_id.to_string();
|
let ap_id = ap_id.to_owned().into();
|
||||||
blocking(pool, move |conn| {
|
blocking(pool, move |conn| {
|
||||||
Activity::insert(conn, ap_id, &activity, local, sensitive)
|
Activity::insert(conn, ap_id, &activity, local, sensitive)
|
||||||
})
|
})
|
||||||
|
@ -286,8 +283,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum PostOrComment {
|
pub(crate) enum PostOrComment {
|
||||||
Comment(Comment),
|
Comment(Box<Comment>),
|
||||||
Post(Post),
|
Post(Box<Post>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to find a post or comment in the local database, without any network requests.
|
/// Tries to find a post or comment in the local database, without any network requests.
|
||||||
|
@ -303,7 +300,7 @@ pub(crate) async fn find_post_or_comment_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(p) = post {
|
if let Ok(p) = post {
|
||||||
return Ok(PostOrComment::Post(p));
|
return Ok(PostOrComment::Post(Box::new(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
|
@ -312,7 +309,7 @@ pub(crate) async fn find_post_or_comment_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(c) = comment {
|
if let Ok(c) = comment {
|
||||||
return Ok(PostOrComment::Comment(c));
|
return Ok(PostOrComment::Comment(Box::new(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
|
@ -333,8 +330,8 @@ pub(crate) async fn find_object_by_id(
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
||||||
return Ok(match pc {
|
return Ok(match pc {
|
||||||
PostOrComment::Post(p) => Object::Post(p),
|
PostOrComment::Post(p) => Object::Post(*p),
|
||||||
PostOrComment::Comment(c) => Object::Comment(c),
|
PostOrComment::Comment(c) => Object::Comment(*c),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,13 @@ impl ToApub for Community {
|
||||||
|
|
||||||
if let Some(icon_url) = &self.icon {
|
if let Some(icon_url) = &self.icon {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(icon_url)?);
|
image.set_url::<Url>(icon_url.to_owned().into());
|
||||||
group.set_icon(image.into_any_base()?);
|
group.set_icon(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(banner_url) = &self.banner {
|
if let Some(banner_url) = &self.banner {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(banner_url)?);
|
image.set_url::<Url>(banner_url.to_owned().into());
|
||||||
group.set_image(image.into_any_base()?);
|
group.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|u| u.to_owned().into()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -185,7 +185,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|u| u.to_owned().into()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ use chrono::NaiveDateTime;
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{ApubObject, Crud, DbPool};
|
use lemmy_db_queries::{ApubObject, Crud, DbPool};
|
||||||
use lemmy_db_schema::source::community::Community;
|
use lemmy_db_schema::{source::community::Community, DbUrl};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
settings::structs::Settings,
|
settings::structs::Settings,
|
||||||
|
@ -96,7 +96,7 @@ where
|
||||||
pub(in crate::objects) fn check_object_domain<T, Kind>(
|
pub(in crate::objects) fn check_object_domain<T, Kind>(
|
||||||
apub: &T,
|
apub: &T,
|
||||||
expected_domain: Url,
|
expected_domain: Url,
|
||||||
) -> Result<lemmy_db_schema::Url, LemmyError>
|
) -> Result<DbUrl, LemmyError>
|
||||||
where
|
where
|
||||||
T: Base + AsBase<Kind>,
|
T: Base + AsBase<Kind>,
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,10 +24,13 @@ use activitystreams_ext::Ext1;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
community::Community,
|
self,
|
||||||
post::{Post, PostForm},
|
source::{
|
||||||
user::User_,
|
community::Community,
|
||||||
|
post::{Post, PostForm},
|
||||||
|
user::User_,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
|
@ -70,16 +73,13 @@ impl ToApub for Post {
|
||||||
set_content_and_source(&mut page, &body)?;
|
set_content_and_source(&mut page, &body)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hacky code because we get self.url == Some("")
|
if let Some(url) = &self.url {
|
||||||
// https://github.com/LemmyNet/lemmy/issues/602
|
page.set_url::<Url>(url.to_owned().into());
|
||||||
let url = self.url.as_ref().filter(|u| !u.is_empty());
|
|
||||||
if let Some(u) = url {
|
|
||||||
page.set_url(Url::parse(u)?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(thumbnail_url) = &self.thumbnail_url {
|
if let Some(thumbnail_url) = &self.thumbnail_url {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(thumbnail_url)?);
|
image.set_url::<Url>(thumbnail_url.to_owned().into());
|
||||||
page.set_image(image.into_any_base()?);
|
page.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
|
|
||||||
let community = get_to_community(page, context, request_counter).await?;
|
let community = get_to_community(page, context, request_counter).await?;
|
||||||
|
|
||||||
let thumbnail_url = match &page.inner.image() {
|
let thumbnail_url: Option<Url> = match &page.inner.image() {
|
||||||
Some(any_image) => Image::from_any_base(
|
Some(any_image) => Image::from_any_base(
|
||||||
any_image
|
any_image
|
||||||
.to_owned()
|
.to_owned()
|
||||||
|
@ -158,7 +158,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let url = page
|
let url = page
|
||||||
|
@ -166,11 +166,11 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
.url()
|
.url()
|
||||||
.map(|u| u.as_single_xsd_any_uri())
|
.map(|u| u.as_single_xsd_any_uri())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|s| s.to_string());
|
.map(|u| u.to_owned());
|
||||||
|
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
if let Some(url) = &url {
|
if let Some(url) = &url {
|
||||||
fetch_iframely_and_pictrs_data(context.client(), Some(url.to_owned())).await
|
fetch_iframely_and_pictrs_data(context.client(), Some(url)).await
|
||||||
} else {
|
} else {
|
||||||
(None, None, None, thumbnail_url)
|
(None, None, None, thumbnail_url)
|
||||||
};
|
};
|
||||||
|
@ -192,7 +192,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
let body_slurs_removed = body.map(|b| remove_slurs(&b));
|
let body_slurs_removed = body.map(|b| remove_slurs(&b));
|
||||||
Ok(PostForm {
|
Ok(PostForm {
|
||||||
name,
|
name,
|
||||||
url,
|
url: url.map(|u| u.into()),
|
||||||
body: body_slurs_removed,
|
body: body_slurs_removed,
|
||||||
creator_id: creator.id,
|
creator_id: creator.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
|
@ -214,7 +214,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: Some(check_object_domain(page, expected_domain)?),
|
ap_id: Some(check_object_domain(page, expected_domain)?),
|
||||||
local: false,
|
local: false,
|
||||||
})
|
})
|
||||||
|
|
|
@ -50,13 +50,13 @@ impl ToApub for User_ {
|
||||||
|
|
||||||
if let Some(avatar_url) = &self.avatar {
|
if let Some(avatar_url) = &self.avatar {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(avatar_url)?);
|
image.set_url::<Url>(avatar_url.to_owned().into());
|
||||||
person.set_icon(image.into_any_base()?);
|
person.set_icon(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(banner_url) = &self.banner {
|
if let Some(banner_url) = &self.banner {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(banner_url)?);
|
image.set_url::<Url>(banner_url.to_owned().into());
|
||||||
person.set_image(image.into_any_base()?);
|
person.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -139,7 +139,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -174,8 +174,8 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
admin: false,
|
admin: false,
|
||||||
banned: None,
|
banned: None,
|
||||||
email: None,
|
email: None,
|
||||||
avatar,
|
avatar: avatar.map(|o| o.map(|i| i.into())),
|
||||||
banner,
|
banner: banner.map(|o| o.map(|i| i.into())),
|
||||||
published: person.inner.published().map(|u| u.to_owned().naive_local()),
|
published: person.inner.published().map(|u| u.to_owned().naive_local()),
|
||||||
updated: person.updated().map(|u| u.to_owned().naive_local()),
|
updated: person.updated().map(|u| u.to_owned().naive_local()),
|
||||||
show_nsfw: false,
|
show_nsfw: false,
|
||||||
|
|
|
@ -20,7 +20,7 @@ strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
sha2 = "0.9.3"
|
sha2 = "0.9.3"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
bcrypt = "0.9.0"
|
bcrypt = "0.9.0"
|
||||||
|
|
|
@ -13,10 +13,12 @@ extern crate diesel_migrations;
|
||||||
extern crate serial_test;
|
extern crate serial_test;
|
||||||
|
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::Url;
|
use lemmy_db_schema::DbUrl;
|
||||||
|
use lemmy_utils::ApiError;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{env, env::VarError};
|
use std::{env, env::VarError};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod aggregates;
|
pub mod aggregates;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
|
@ -112,7 +114,7 @@ pub trait Reportable<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ApubObject<T> {
|
pub trait ApubObject<T> {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn upsert(conn: &PgConnection, user_form: &T) -> Result<Self, Error>
|
fn upsert(conn: &PgConnection, user_form: &T) -> Result<Self, Error>
|
||||||
|
@ -219,6 +221,20 @@ pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn diesel_option_overwrite_to_url(
|
||||||
|
opt: &Option<String>,
|
||||||
|
) -> Result<Option<Option<DbUrl>>, ApiError> {
|
||||||
|
match opt.as_ref().map(|s| s.as_str()) {
|
||||||
|
// An empty string is an erase
|
||||||
|
Some("") => Ok(Some(None)),
|
||||||
|
Some(str_url) => match Url::parse(str_url) {
|
||||||
|
Ok(url) => Ok(Some(Some(url.into()))),
|
||||||
|
Err(_) => Err(ApiError::err("invalid_url")),
|
||||||
|
},
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
embed_migrations!();
|
embed_migrations!();
|
||||||
|
|
||||||
pub fn establish_unpooled_connection() -> PgConnection {
|
pub fn establish_unpooled_connection() -> PgConnection {
|
||||||
|
@ -251,7 +267,7 @@ pub mod functions {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::fuzzy_search;
|
use super::{fuzzy_search, *};
|
||||||
use crate::is_email_regex;
|
use crate::is_email_regex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -265,4 +281,32 @@ mod tests {
|
||||||
assert!(is_email_regex("gush@gmail.com"));
|
assert!(is_email_regex("gush@gmail.com"));
|
||||||
assert!(!is_email_regex("nada_neutho"));
|
assert!(!is_email_regex("nada_neutho"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_diesel_option_overwrite() {
|
||||||
|
assert_eq!(diesel_option_overwrite(&None), None);
|
||||||
|
assert_eq!(diesel_option_overwrite(&Some("".to_string())), Some(None));
|
||||||
|
assert_eq!(
|
||||||
|
diesel_option_overwrite(&Some("test".to_string())),
|
||||||
|
Some(Some("test".to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_diesel_option_overwrite_to_url() {
|
||||||
|
assert!(matches!(diesel_option_overwrite_to_url(&None), Ok(None)));
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some("".to_string())),
|
||||||
|
Ok(Some(None))
|
||||||
|
));
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some("invalid_url".to_string())),
|
||||||
|
Err(_)
|
||||||
|
));
|
||||||
|
let example_url = "https://example.com";
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some(example_url.to_string())),
|
||||||
|
Ok(Some(Some(url))) if url == Url::parse(&example_url).unwrap().into()
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Crud;
|
use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
||||||
use lemmy_db_schema::{source::activity::*, Url};
|
use lemmy_db_schema::{source::activity::*, DbUrl};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -41,7 +41,7 @@ impl Crud<ActivityForm> for Activity {
|
||||||
pub trait Activity_ {
|
pub trait Activity_ {
|
||||||
fn insert<T>(
|
fn insert<T>(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
ap_id: String,
|
ap_id: DbUrl,
|
||||||
data: &T,
|
data: &T,
|
||||||
local: bool,
|
local: bool,
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
|
@ -49,20 +49,20 @@ pub trait Activity_ {
|
||||||
where
|
where
|
||||||
T: Serialize + Debug;
|
T: Serialize + Debug;
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Activity, Error>;
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error>;
|
||||||
fn delete_olds(conn: &PgConnection) -> Result<usize, Error>;
|
fn delete_olds(conn: &PgConnection) -> Result<usize, Error>;
|
||||||
|
|
||||||
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
||||||
fn read_community_outbox(
|
fn read_community_outbox(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_actor_id: &Url,
|
community_actor_id: &DbUrl,
|
||||||
) -> Result<Vec<Value>, Error>;
|
) -> Result<Vec<Value>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Activity_ for Activity {
|
impl Activity_ for Activity {
|
||||||
fn insert<T>(
|
fn insert<T>(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
ap_id: String,
|
ap_id: DbUrl,
|
||||||
data: &T,
|
data: &T,
|
||||||
local: bool,
|
local: bool,
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
|
@ -88,7 +88,7 @@ impl Activity_ for Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Activity, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl Activity_ for Activity {
|
||||||
|
|
||||||
fn read_community_outbox(
|
fn read_community_outbox(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_actor_id: &Url,
|
community_actor_id: &DbUrl,
|
||||||
) -> Result<Vec<Value>, Error> {
|
) -> Result<Vec<Value>, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
let res: Vec<Value> = activity
|
let res: Vec<Value> = activity
|
||||||
|
@ -121,6 +121,7 @@ impl Activity_ for Activity {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
source::activity::Activity_,
|
source::activity::Activity_,
|
||||||
|
@ -134,6 +135,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
|
@ -171,8 +173,11 @@ mod tests {
|
||||||
|
|
||||||
let inserted_creator = User_::create(&conn, &creator_form).unwrap();
|
let inserted_creator = User_::create(&conn, &creator_form).unwrap();
|
||||||
|
|
||||||
let ap_id =
|
let ap_id: DbUrl = Url::parse(
|
||||||
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c";
|
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
let test_json: Value = serde_json::from_str(
|
let test_json: Value = serde_json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"@context": "https://www.w3.org/ns/activitystreams",
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
@ -188,7 +193,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let activity_form = ActivityForm {
|
let activity_form = ActivityForm {
|
||||||
ap_id: ap_id.to_string(),
|
ap_id: ap_id.clone(),
|
||||||
data: test_json.to_owned(),
|
data: test_json.to_owned(),
|
||||||
local: true,
|
local: true,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
|
@ -198,7 +203,7 @@ mod tests {
|
||||||
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
||||||
|
|
||||||
let expected_activity = Activity {
|
let expected_activity = Activity {
|
||||||
ap_id: Some(ap_id.to_string()),
|
ap_id: Some(ap_id.clone()),
|
||||||
id: inserted_activity.id,
|
id: inserted_activity.id,
|
||||||
data: test_json,
|
data: test_json,
|
||||||
local: true,
|
local: true,
|
||||||
|
@ -208,7 +213,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
||||||
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, ap_id).unwrap();
|
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, &ap_id).unwrap();
|
||||||
User_::delete(&conn, inserted_creator.id).unwrap();
|
User_::delete(&conn, inserted_creator.id).unwrap();
|
||||||
Activity::delete(&conn, inserted_activity.id).unwrap();
|
Activity::delete(&conn, inserted_activity.id).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ use lemmy_db_schema::{
|
||||||
CommentSaved,
|
CommentSaved,
|
||||||
CommentSavedForm,
|
CommentSavedForm,
|
||||||
},
|
},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Comment_ {
|
pub trait Comment_ {
|
||||||
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: Url) -> Result<Comment, Error>;
|
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: DbUrl) -> Result<Comment, Error>;
|
||||||
fn permadelete_for_creator(
|
fn permadelete_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: i32,
|
||||||
|
@ -43,7 +43,7 @@ pub trait Comment_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Comment_ for Comment {
|
impl Comment_ for Comment {
|
||||||
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: Url) -> Result<Self, Error> {
|
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
|
||||||
diesel::update(comment.find(comment_id))
|
diesel::update(comment.find(comment_id))
|
||||||
|
@ -145,7 +145,7 @@ impl Crud<CommentForm> for Comment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommentForm> for Comment {
|
impl ApubObject<CommentForm> for Comment {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
||||||
CommunityUserBan,
|
CommunityUserBan,
|
||||||
CommunityUserBanForm,
|
CommunityUserBanForm,
|
||||||
},
|
},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod safe_type {
|
mod safe_type {
|
||||||
|
@ -90,7 +90,7 @@ impl Crud<CommunityForm> for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommunityForm> for Community {
|
impl ApubObject<CommunityForm> for Community {
|
||||||
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community
|
community
|
||||||
.filter(actor_id.eq(for_actor_id))
|
.filter(actor_id.eq(for_actor_id))
|
||||||
|
@ -131,7 +131,10 @@ pub trait Community_ {
|
||||||
new_creator_id: i32,
|
new_creator_id: i32,
|
||||||
) -> Result<Community, Error>;
|
) -> Result<Community, Error>;
|
||||||
fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error>;
|
fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error>;
|
||||||
fn read_from_followers_url(conn: &PgConnection, followers_url: &Url) -> Result<Community, Error>;
|
fn read_from_followers_url(
|
||||||
|
conn: &PgConnection,
|
||||||
|
followers_url: &DbUrl,
|
||||||
|
) -> Result<Community, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Community_ for Community {
|
impl Community_ for Community {
|
||||||
|
@ -194,7 +197,7 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn read_from_followers_url(
|
fn read_from_followers_url(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
followers_url_: &Url,
|
followers_url_: &DbUrl,
|
||||||
) -> Result<Community, Error> {
|
) -> Result<Community, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community
|
community
|
||||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
||||||
PostSaved,
|
PostSaved,
|
||||||
PostSavedForm,
|
PostSavedForm,
|
||||||
},
|
},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Crud<PostForm> for Post {
|
impl Crud<PostForm> for Post {
|
||||||
|
@ -42,7 +42,7 @@ impl Crud<PostForm> for Post {
|
||||||
pub trait Post_ {
|
pub trait Post_ {
|
||||||
//fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
|
//fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
|
||||||
fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Post>, Error>;
|
fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Post>, Error>;
|
||||||
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: Url) -> Result<Post, Error>;
|
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: DbUrl) -> Result<Post, Error>;
|
||||||
fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Post>, Error>;
|
fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Post>, Error>;
|
||||||
fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Post, Error>;
|
fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Post, Error>;
|
||||||
fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Post, Error>;
|
fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Post, Error>;
|
||||||
|
@ -68,7 +68,7 @@ impl Post_ for Post {
|
||||||
.load::<Self>(conn)
|
.load::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: Url) -> Result<Self, Error> {
|
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
|
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
|
@ -147,7 +147,7 @@ impl Post_ for Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PostForm> for Post {
|
impl ApubObject<PostForm> for Post {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{ApubObject, Crud};
|
use crate::{ApubObject, Crud};
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::private_message::*, Url};
|
use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl};
|
||||||
|
|
||||||
impl Crud<PrivateMessageForm> for PrivateMessage {
|
impl Crud<PrivateMessageForm> for PrivateMessage {
|
||||||
fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
|
||||||
|
@ -28,7 +28,7 @@ impl Crud<PrivateMessageForm> for PrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,7 @@ pub trait PrivateMessage_ {
|
||||||
fn update_ap_id(
|
fn update_ap_id(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: i32,
|
||||||
apub_id: Url,
|
apub_id: DbUrl,
|
||||||
) -> Result<PrivateMessage, Error>;
|
) -> Result<PrivateMessage, Error>;
|
||||||
fn update_content(
|
fn update_content(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
|
@ -80,7 +80,7 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
fn update_ap_id(
|
fn update_ap_id(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: i32,
|
||||||
apub_id: Url,
|
apub_id: DbUrl,
|
||||||
) -> Result<PrivateMessage, Error> {
|
) -> Result<PrivateMessage, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
schema::user_::dsl::*,
|
schema::user_::dsl::*,
|
||||||
source::user::{UserForm, UserSafeSettings, User_},
|
source::user::{UserForm, UserSafeSettings, User_},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
use lemmy_utils::settings::structs::Settings;
|
use lemmy_utils::settings::structs::Settings;
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ impl Crud<UserForm> for User_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<UserForm> for User_ {
|
impl ApubObject<UserForm> for User_ {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::user_::dsl::*;
|
use lemmy_db_schema::schema::user_::dsl::*;
|
||||||
user_
|
user_
|
||||||
.filter(deleted.eq(false))
|
.filter(deleted.eq(false))
|
||||||
|
|
|
@ -12,4 +12,4 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
|
|
|
@ -8,21 +8,22 @@ use diesel::{
|
||||||
serialize::{Output, ToSql},
|
serialize::{Output, ToSql},
|
||||||
sql_types::Text,
|
sql_types::Text,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
io::Write,
|
io::Write,
|
||||||
};
|
};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, PartialEq, Serialize, Debug, AsExpression, FromSqlRow)]
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, AsExpression, FromSqlRow)]
|
||||||
#[sql_type = "Text"]
|
#[sql_type = "Text"]
|
||||||
pub struct Url(url::Url);
|
pub struct DbUrl(Url);
|
||||||
|
|
||||||
impl<DB: Backend> ToSql<Text, DB> for Url
|
impl<DB: Backend> ToSql<Text, DB> for DbUrl
|
||||||
where
|
where
|
||||||
String: ToSql<Text, DB>,
|
String: ToSql<Text, DB>,
|
||||||
{
|
{
|
||||||
|
@ -31,37 +32,37 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: Backend> FromSql<Text, DB> for Url
|
impl<DB: Backend> FromSql<Text, DB> for DbUrl
|
||||||
where
|
where
|
||||||
String: FromSql<Text, DB>,
|
String: FromSql<Text, DB>,
|
||||||
{
|
{
|
||||||
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
||||||
let str = String::from_sql(bytes)?;
|
let str = String::from_sql(bytes)?;
|
||||||
Ok(Url(url::Url::parse(&str)?))
|
Ok(DbUrl(Url::parse(&str)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Url {
|
impl DbUrl {
|
||||||
pub fn into_inner(self) -> url::Url {
|
pub fn into_inner(self) -> Url {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Url {
|
impl Display for DbUrl {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.to_owned().into_inner().fmt(f)
|
self.to_owned().into_inner().fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Url> for url::Url {
|
impl From<DbUrl> for Url {
|
||||||
fn from(url: Url) -> Self {
|
fn from(url: DbUrl) -> Self {
|
||||||
url.0
|
url.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<url::Url> for Url {
|
impl From<Url> for DbUrl {
|
||||||
fn from(url: url::Url) -> Self {
|
fn from(url: Url) -> Self {
|
||||||
Url(url)
|
DbUrl(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::schema::activity;
|
use crate::{schema::activity, DbUrl};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ pub struct Activity {
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: Option<String>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub sensitive: Option<bool>,
|
pub sensitive: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,6 @@ pub struct ActivityForm {
|
||||||
pub data: Value,
|
pub data: Value,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: String,
|
pub ap_id: DbUrl,
|
||||||
pub sensitive: bool,
|
pub sensitive: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{comment, comment_alias_1, comment_like, comment_saved},
|
schema::{comment, comment_alias_1, comment_like, comment_saved},
|
||||||
source::post::Post,
|
source::post::Post,
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ pub struct Comment {
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ pub struct CommentAlias1 {
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ pub struct CommentForm {
|
||||||
pub published: Option<chrono::NaiveDateTime>,
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub ap_id: Option<Url>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{community, community_follower, community_moderator, community_user_ban},
|
schema::{community, community_follower, community_moderator, community_user_ban},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -17,16 +17,16 @@ pub struct Community {
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<DbUrl>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub followers_url: Url,
|
pub followers_url: DbUrl,
|
||||||
pub inbox_url: Url,
|
pub inbox_url: DbUrl,
|
||||||
pub shared_inbox_url: Option<Url>,
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe representation of community, without the sensitive info
|
/// A safe representation of community, without the sensitive info
|
||||||
|
@ -43,10 +43,10 @@ pub struct CommunitySafe {
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<DbUrl>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Debug)]
|
#[derive(Insertable, AsChangeset, Debug)]
|
||||||
|
@ -61,16 +61,16 @@ pub struct CommunityForm {
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Option<Url>,
|
pub actor_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||||
pub icon: Option<Option<String>>,
|
pub icon: Option<Option<DbUrl>>,
|
||||||
pub banner: Option<Option<String>>,
|
pub banner: Option<Option<DbUrl>>,
|
||||||
pub followers_url: Option<Url>,
|
pub followers_url: Option<DbUrl>,
|
||||||
pub inbox_url: Option<Url>,
|
pub inbox_url: Option<DbUrl>,
|
||||||
pub shared_inbox_url: Option<Option<Url>>,
|
pub shared_inbox_url: Option<Option<DbUrl>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{post, post_like, post_read, post_saved},
|
schema::{post, post_like, post_read, post_saved},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use serde::Serialize;
|
||||||
pub struct Post {
|
pub struct Post {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<DbUrl>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
|
@ -23,8 +23,8 @@ pub struct Post {
|
||||||
pub embed_title: Option<String>,
|
pub embed_title: Option<String>,
|
||||||
pub embed_description: Option<String>,
|
pub embed_description: Option<String>,
|
||||||
pub embed_html: Option<String>,
|
pub embed_html: Option<String>,
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<DbUrl>,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ pub struct Post {
|
||||||
#[table_name = "post"]
|
#[table_name = "post"]
|
||||||
pub struct PostForm {
|
pub struct PostForm {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<DbUrl>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: i32,
|
||||||
|
@ -46,8 +46,8 @@ pub struct PostForm {
|
||||||
pub embed_title: Option<String>,
|
pub embed_title: Option<String>,
|
||||||
pub embed_description: Option<String>,
|
pub embed_description: Option<String>,
|
||||||
pub embed_html: Option<String>,
|
pub embed_html: Option<String>,
|
||||||
pub thumbnail_url: Option<String>,
|
pub thumbnail_url: Option<DbUrl>,
|
||||||
pub ap_id: Option<Url>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{schema::post_report, source::post::Post};
|
use crate::{schema::post_report, source::post::Post, DbUrl};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -11,7 +11,7 @@ pub struct PostReport {
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub post_id: i32,
|
pub post_id: i32,
|
||||||
pub original_post_name: String,
|
pub original_post_name: String,
|
||||||
pub original_post_url: Option<String>,
|
pub original_post_url: Option<DbUrl>,
|
||||||
pub original_post_body: Option<String>,
|
pub original_post_body: Option<String>,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
pub resolved: bool,
|
pub resolved: bool,
|
||||||
|
@ -26,7 +26,7 @@ pub struct PostReportForm {
|
||||||
pub creator_id: i32,
|
pub creator_id: i32,
|
||||||
pub post_id: i32,
|
pub post_id: i32,
|
||||||
pub original_post_name: String,
|
pub original_post_name: String,
|
||||||
pub original_post_url: Option<String>,
|
pub original_post_url: Option<DbUrl>,
|
||||||
pub original_post_body: Option<String>,
|
pub original_post_body: Option<String>,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{schema::private_message, Url};
|
use crate::{schema::private_message, DbUrl};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
|
#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
@ -12,7 +12,7 @@ pub struct PrivateMessage {
|
||||||
pub read: bool,
|
pub read: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,6 @@ pub struct PrivateMessageForm {
|
||||||
pub read: Option<bool>,
|
pub read: Option<bool>,
|
||||||
pub published: Option<chrono::NaiveDateTime>,
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: Option<Url>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::schema::site;
|
use crate::{schema::site, DbUrl};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Clone, Serialize)]
|
#[derive(Queryable, Identifiable, PartialEq, Debug, Clone, Serialize)]
|
||||||
|
@ -13,8 +13,8 @@ pub struct Site {
|
||||||
pub enable_downvotes: bool,
|
pub enable_downvotes: bool,
|
||||||
pub open_registration: bool,
|
pub open_registration: bool,
|
||||||
pub enable_nsfw: bool,
|
pub enable_nsfw: bool,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<DbUrl>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
|
@ -28,6 +28,6 @@ pub struct SiteForm {
|
||||||
pub open_registration: bool,
|
pub open_registration: bool,
|
||||||
pub enable_nsfw: bool,
|
pub enable_nsfw: bool,
|
||||||
// when you want to null out a column, you have to send Some(None)), since sending None means you just don't want to update that column.
|
// when you want to null out a column, you have to send Some(None)), since sending None means you just don't want to update that column.
|
||||||
pub icon: Option<Option<String>>,
|
pub icon: Option<Option<DbUrl>>,
|
||||||
pub banner: Option<Option<String>>,
|
pub banner: Option<Option<DbUrl>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{user_, user_alias_1, user_alias_2},
|
schema::{user_, user_alias_1, user_alias_2},
|
||||||
Url,
|
DbUrl,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub struct User_ {
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub password_encrypted: String,
|
pub password_encrypted: String,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
@ -25,16 +25,16 @@ pub struct User_ {
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub inbox_url: Url,
|
pub inbox_url: DbUrl,
|
||||||
pub shared_inbox_url: Option<Url>,
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe representation of user, without the sensitive info
|
/// A safe representation of user, without the sensitive info
|
||||||
|
@ -44,19 +44,19 @@ pub struct UserSafe {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub inbox_url: Url,
|
pub inbox_url: DbUrl,
|
||||||
pub shared_inbox_url: Option<Url>,
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe user view with only settings
|
/// A safe user view with only settings
|
||||||
|
@ -67,7 +67,7 @@ pub struct UserSafeSettings {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
@ -80,11 +80,11 @@ pub struct UserSafeSettings {
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ pub struct UserAlias1 {
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub password_encrypted: String,
|
pub password_encrypted: String,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
@ -109,13 +109,13 @@ pub struct UserAlias1 {
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,16 +125,16 @@ pub struct UserSafeAlias1 {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ pub struct UserAlias2 {
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub password_encrypted: String,
|
pub password_encrypted: String,
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
@ -159,13 +159,13 @@ pub struct UserAlias2 {
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,16 +175,16 @@ pub struct UserSafeAlias2 {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<DbUrl>,
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub bio: Option<String>,
|
pub bio: Option<String>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ pub struct UserForm {
|
||||||
pub admin: bool,
|
pub admin: bool,
|
||||||
pub banned: Option<bool>,
|
pub banned: Option<bool>,
|
||||||
pub email: Option<Option<String>>,
|
pub email: Option<Option<String>>,
|
||||||
pub avatar: Option<Option<String>>,
|
pub avatar: Option<Option<DbUrl>>,
|
||||||
pub published: Option<chrono::NaiveDateTime>,
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub show_nsfw: bool,
|
pub show_nsfw: bool,
|
||||||
|
@ -208,13 +208,13 @@ pub struct UserForm {
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
pub matrix_user_id: Option<Option<String>>,
|
pub matrix_user_id: Option<Option<String>>,
|
||||||
pub actor_id: Option<Url>,
|
pub actor_id: Option<DbUrl>,
|
||||||
pub bio: Option<Option<String>>,
|
pub bio: Option<Option<String>>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||||
pub banner: Option<Option<String>>,
|
pub banner: Option<Option<DbUrl>>,
|
||||||
pub inbox_url: Option<Url>,
|
pub inbox_url: Option<DbUrl>,
|
||||||
pub shared_inbox_url: Option<Option<Url>>,
|
pub shared_inbox_url: Option<Option<DbUrl>>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ lemmy_db_schema = { path = "../db_schema" }
|
||||||
diesel = { version = "1.4.5", features = ["postgres","chrono","r2d2","serde_json"] }
|
diesel = { version = "1.4.5", features = ["postgres","chrono","r2d2","serde_json"] }
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
url = "2.2.0"
|
url = "2.2.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serial_test = "0.5.1"
|
serial_test = "0.5.1"
|
|
@ -25,6 +25,6 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
rss = "1.10.0"
|
rss = "1.10.0"
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
awc = { version = "2.0.3", default-features = false }
|
awc = { version = "2.0.3", default-features = false }
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
|
|
@ -22,7 +22,7 @@ thiserror = "1.0.23"
|
||||||
comrak = { version = "0.9.0", default-features = false }
|
comrak = { version = "0.9.0", default-features = false }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
actix-web = { version = "3.3.2", default-features = false, features = ["rustls"] }
|
actix-web = { version = "3.3.2", default-features = false, features = ["rustls"] }
|
||||||
actix-rt = { version = "1.1.1", default-features = false }
|
actix-rt = { version = "1.1.1", default-features = false }
|
||||||
anyhow = "1.0.38"
|
anyhow = "1.0.38"
|
||||||
|
|
|
@ -6,6 +6,7 @@ use reqwest::Client;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[error("Error sending request, {0}")]
|
#[error("Error sending request, {0}")]
|
||||||
|
@ -50,13 +51,13 @@ where
|
||||||
pub(crate) struct IframelyResponse {
|
pub(crate) struct IframelyResponse {
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
thumbnail_url: Option<String>,
|
thumbnail_url: Option<Url>,
|
||||||
html: Option<String>,
|
html: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn fetch_iframely(
|
pub(crate) async fn fetch_iframely(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
url: &str,
|
url: &Url,
|
||||||
) -> Result<IframelyResponse, LemmyError> {
|
) -> Result<IframelyResponse, LemmyError> {
|
||||||
let fetch_url = format!("{}/oembed?url={}", Settings::get().iframely_url(), url);
|
let fetch_url = format!("{}/oembed?url={}", Settings::get().iframely_url(), url);
|
||||||
|
|
||||||
|
@ -83,14 +84,14 @@ pub(crate) struct PictrsFile {
|
||||||
|
|
||||||
pub(crate) async fn fetch_pictrs(
|
pub(crate) async fn fetch_pictrs(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
image_url: &str,
|
image_url: &Url,
|
||||||
) -> Result<PictrsResponse, LemmyError> {
|
) -> Result<PictrsResponse, LemmyError> {
|
||||||
is_image_content_type(client, image_url).await?;
|
is_image_content_type(client, image_url).await?;
|
||||||
|
|
||||||
let fetch_url = format!(
|
let fetch_url = format!(
|
||||||
"{}/image/download?url={}",
|
"{}/image/download?url={}",
|
||||||
Settings::get().pictrs_url(),
|
Settings::get().pictrs_url(),
|
||||||
utf8_percent_encode(image_url, NON_ALPHANUMERIC) // TODO this might not be needed
|
utf8_percent_encode(image_url.as_str(), NON_ALPHANUMERIC) // TODO this might not be needed
|
||||||
);
|
);
|
||||||
|
|
||||||
let response = retry(|| client.get(&fetch_url).send()).await?;
|
let response = retry(|| client.get(&fetch_url).send()).await?;
|
||||||
|
@ -109,13 +110,8 @@ pub(crate) async fn fetch_pictrs(
|
||||||
|
|
||||||
pub async fn fetch_iframely_and_pictrs_data(
|
pub async fn fetch_iframely_and_pictrs_data(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
url: Option<String>,
|
url: Option<&Url>,
|
||||||
) -> (
|
) -> (Option<String>, Option<String>, Option<String>, Option<Url>) {
|
||||||
Option<String>,
|
|
||||||
Option<String>,
|
|
||||||
Option<String>,
|
|
||||||
Option<String>,
|
|
||||||
) {
|
|
||||||
match &url {
|
match &url {
|
||||||
Some(url) => {
|
Some(url) => {
|
||||||
// Fetch iframely data
|
// Fetch iframely data
|
||||||
|
@ -149,11 +145,19 @@ pub async fn fetch_iframely_and_pictrs_data(
|
||||||
|
|
||||||
// The full urls are necessary for federation
|
// The full urls are necessary for federation
|
||||||
let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
|
let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
|
||||||
Some(format!(
|
let url = Url::parse(&format!(
|
||||||
"{}/pictrs/image/{}",
|
"{}/pictrs/image/{}",
|
||||||
Settings::get().get_protocol_and_hostname(),
|
Settings::get().get_protocol_and_hostname(),
|
||||||
pictrs_hash
|
pictrs_hash
|
||||||
))
|
));
|
||||||
|
match url {
|
||||||
|
Ok(parsed_url) => Some(parsed_url),
|
||||||
|
Err(e) => {
|
||||||
|
// This really shouldn't happen unless the settings or hash are malformed
|
||||||
|
error!("Unexpected error constructing pictrs thumbnail URL: {}", e);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -169,9 +173,8 @@ pub async fn fetch_iframely_and_pictrs_data(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn is_image_content_type(client: &Client, test: &str) -> Result<(), LemmyError> {
|
async fn is_image_content_type(client: &Client, test: &Url) -> Result<(), LemmyError> {
|
||||||
let response = retry(|| client.get(test).send()).await?;
|
let response = retry(|| client.get(test.to_owned()).send()).await?;
|
||||||
|
|
||||||
if response
|
if response
|
||||||
.headers()
|
.headers()
|
||||||
.get("Content-Type")
|
.get("Content-Type")
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- This is a clean-up migration that cannot be undone,
|
||||||
|
-- but Diesel requires a non-empty script so run a no-op.
|
||||||
|
SELECT 1;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
UPDATE post SET url = NULL where url = '';
|
Loading…
Reference in a new issue