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]]
|
||||
name = "url"
|
||||
version = "2.2.0"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
|
||||
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
|
|
|
@ -45,7 +45,7 @@ actix-web = { version = "3.3.2", default-features = false, features = ["rustls"]
|
|||
log = "0.4.14"
|
||||
env_logger = "0.8.2"
|
||||
strum = "0.20.0"
|
||||
url = { version = "2.2.0", features = ["serde"] }
|
||||
url = { version = "2.2.1", features = ["serde"] }
|
||||
openssl = "0.10.32"
|
||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||
tokio = "0.3.6"
|
||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
|||
strum = "0.20.0"
|
||||
strum_macros = "0.20.1"
|
||||
lazy_static = "1.4.0"
|
||||
url = { version = "2.2.0", features = ["serde"] }
|
||||
url = { version = "2.2.1", features = ["serde"] }
|
||||
openssl = "0.10.32"
|
||||
http = "0.2.3"
|
||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{
|
||||
check_community_ban,
|
||||
check_optional_url,
|
||||
get_user_from_jwt,
|
||||
get_user_from_jwt_opt,
|
||||
is_admin,
|
||||
|
@ -19,7 +18,7 @@ use lemmy_apub::{
|
|||
EndpointType,
|
||||
};
|
||||
use lemmy_db_queries::{
|
||||
diesel_option_overwrite,
|
||||
diesel_option_overwrite_to_url,
|
||||
source::{
|
||||
comment::Comment_,
|
||||
community::{CommunityModerator_, Community_},
|
||||
|
@ -155,11 +154,8 @@ impl Perform for CreateCommunity {
|
|||
}
|
||||
|
||||
// Check to make sure the icon and banners are urls
|
||||
let icon = diesel_option_overwrite(&data.icon);
|
||||
let banner = diesel_option_overwrite(&data.banner);
|
||||
|
||||
check_optional_url(&icon)?;
|
||||
check_optional_url(&banner)?;
|
||||
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||
|
||||
// When you create a community, make sure the user becomes a moderator and a follower
|
||||
let keypair = generate_actor_keypair()?;
|
||||
|
@ -260,11 +256,8 @@ impl Perform for EditCommunity {
|
|||
})
|
||||
.await??;
|
||||
|
||||
let icon = diesel_option_overwrite(&data.icon);
|
||||
let banner = diesel_option_overwrite(&data.banner);
|
||||
|
||||
check_optional_url(&icon)?;
|
||||
check_optional_url(&banner)?;
|
||||
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||
|
||||
let community_form = CommunityForm {
|
||||
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(
|
||||
pool: &DbPool,
|
||||
) -> Result<Option<FederatedInstances>, LemmyError> {
|
||||
|
@ -474,6 +465,15 @@ pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
|
|||
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)]
|
||||
mod tests {
|
||||
use crate::captcha_espeak_wav_base64;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{
|
||||
check_community_ban,
|
||||
check_downvotes_enabled,
|
||||
check_optional_url,
|
||||
collect_moderated_communities,
|
||||
get_user_from_jwt,
|
||||
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_optional_url(&Some(data.url.to_owned()))?;
|
||||
|
||||
// Fetch Iframely and pictrs cached image
|
||||
let data_url = data.url.as_ref();
|
||||
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 {
|
||||
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(),
|
||||
community_id: data.community_id,
|
||||
creator_id: user.id,
|
||||
|
@ -93,7 +91,7 @@ impl Perform for CreatePost {
|
|||
embed_title: iframely_title,
|
||||
embed_description: iframely_description,
|
||||
embed_html: iframely_html,
|
||||
thumbnail_url: pictrs_thumbnail,
|
||||
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||
ap_id: None,
|
||||
local: true,
|
||||
published: None,
|
||||
|
@ -385,12 +383,13 @@ impl Perform for EditPost {
|
|||
}
|
||||
|
||||
// Fetch Iframely and Pictrs cached image
|
||||
let data_url = data.url.as_ref();
|
||||
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 {
|
||||
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(),
|
||||
nsfw: data.nsfw,
|
||||
creator_id: orig_post.creator_id.to_owned(),
|
||||
|
@ -403,7 +402,7 @@ impl Perform for EditPost {
|
|||
embed_title: iframely_title,
|
||||
embed_description: iframely_description,
|
||||
embed_html: iframely_html,
|
||||
thumbnail_url: pictrs_thumbnail,
|
||||
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||
ap_id: Some(orig_post.ap_id),
|
||||
local: orig_post.local,
|
||||
published: None,
|
||||
|
|
|
@ -11,7 +11,13 @@ use actix_web::web::Data;
|
|||
use anyhow::Context;
|
||||
use lemmy_api_structs::{blocking, site::*, user::Register};
|
||||
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::{
|
||||
naive_now,
|
||||
source::{
|
||||
|
@ -157,8 +163,8 @@ impl Perform for CreateSite {
|
|||
let site_form = SiteForm {
|
||||
name: data.name.to_owned(),
|
||||
description: data.description.to_owned(),
|
||||
icon: Some(data.icon.to_owned()),
|
||||
banner: Some(data.banner.to_owned()),
|
||||
icon: Some(data.icon.to_owned().map(|url| url.into())),
|
||||
banner: Some(data.banner.to_owned().map(|url| url.into())),
|
||||
creator_id: user.id,
|
||||
enable_downvotes: data.enable_downvotes,
|
||||
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 icon = diesel_option_overwrite(&data.icon);
|
||||
let banner = diesel_option_overwrite(&data.banner);
|
||||
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||
|
||||
let site_form = SiteForm {
|
||||
name: data.name.to_owned(),
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::{
|
||||
captcha_espeak_wav_base64,
|
||||
check_optional_url,
|
||||
collect_moderated_communities,
|
||||
get_user_from_jwt,
|
||||
get_user_from_jwt_opt,
|
||||
is_admin,
|
||||
password_length_check,
|
||||
Perform,
|
||||
};
|
||||
use actix_web::web::Data;
|
||||
|
@ -23,6 +23,7 @@ use lemmy_apub::{
|
|||
};
|
||||
use lemmy_db_queries::{
|
||||
diesel_option_overwrite,
|
||||
diesel_option_overwrite_to_url,
|
||||
source::{
|
||||
comment::Comment_,
|
||||
community::Community_,
|
||||
|
@ -144,10 +145,7 @@ impl Perform for Register {
|
|||
}
|
||||
}
|
||||
|
||||
// Password length check
|
||||
if data.password.len() > 60 {
|
||||
return Err(ApiError::err("invalid_password").into());
|
||||
}
|
||||
password_length_check(&data.password)?;
|
||||
|
||||
// Make sure passwords match
|
||||
if data.password != data.password_verify {
|
||||
|
@ -366,17 +364,13 @@ impl Perform for SaveUserSettings {
|
|||
let data: &SaveUserSettings = &self;
|
||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
||||
|
||||
let avatar = diesel_option_overwrite(&data.avatar);
|
||||
let banner = diesel_option_overwrite(&data.banner);
|
||||
let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
|
||||
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||
let email = diesel_option_overwrite(&data.email);
|
||||
let bio = diesel_option_overwrite(&data.bio);
|
||||
let preferred_username = diesel_option_overwrite(&data.preferred_username);
|
||||
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 bio.chars().count() > 300 {
|
||||
return Err(ApiError::err("bio_length_overflow").into());
|
||||
|
@ -394,6 +388,8 @@ impl Perform for SaveUserSettings {
|
|||
Some(new_password) => {
|
||||
match &data.new_password_verify {
|
||||
Some(new_password_verify) => {
|
||||
password_length_check(&new_password)?;
|
||||
|
||||
// Make sure passwords match
|
||||
if new_password != new_password_verify {
|
||||
return Err(ApiError::err("passwords_dont_match").into());
|
||||
|
@ -993,6 +989,8 @@ impl Perform for PasswordChange {
|
|||
})
|
||||
.await??;
|
||||
|
||||
password_length_check(&data.password)?;
|
||||
|
||||
// Make sure passwords match
|
||||
if data.password != data.password_verify {
|
||||
return Err(ApiError::err("passwords_dont_match").into());
|
||||
|
|
|
@ -21,4 +21,4 @@ diesel = "1.4.5"
|
|||
actix-web = "3.3.2"
|
||||
chrono = { version = "0.4.19", features = ["serde"] }
|
||||
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,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct CreatePost {
|
||||
pub name: String,
|
||||
pub url: Option<String>,
|
||||
pub url: Option<Url>,
|
||||
pub body: Option<String>,
|
||||
pub nsfw: bool,
|
||||
pub community_id: i32,
|
||||
|
@ -66,7 +67,7 @@ pub struct CreatePostLike {
|
|||
pub struct EditPost {
|
||||
pub post_id: i32,
|
||||
pub name: String,
|
||||
pub url: Option<String>,
|
||||
pub url: Option<Url>,
|
||||
pub body: Option<String>,
|
||||
pub nsfw: bool,
|
||||
pub auth: String,
|
||||
|
|
|
@ -13,6 +13,7 @@ use lemmy_db_views_moderator::{
|
|||
mod_sticky_post_view::ModStickyPostView,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
pub struct Search {
|
||||
|
@ -60,8 +61,8 @@ pub struct GetModlogResponse {
|
|||
pub struct CreateSite {
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub icon: Option<Url>,
|
||||
pub banner: Option<Url>,
|
||||
pub enable_downvotes: bool,
|
||||
pub open_registration: bool,
|
||||
pub enable_nsfw: bool,
|
||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
|||
strum = "0.20.0"
|
||||
strum_macros = "0.20.1"
|
||||
lazy_static = "1.4.0"
|
||||
url = { version = "2.2.0", features = ["serde"] }
|
||||
url = { version = "2.2.1", features = ["serde"] }
|
||||
percent-encoding = "2.1.0"
|
||||
openssl = "0.10.32"
|
||||
http = "0.2.3"
|
||||
|
|
|
@ -7,6 +7,7 @@ use lemmy_db_schema::source::activity::Activity;
|
|||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
pub mod comment;
|
||||
pub mod community;
|
||||
|
@ -46,12 +47,13 @@ pub async fn get_activity(
|
|||
context: web::Data<LemmyContext>,
|
||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||
let settings = Settings::get();
|
||||
let activity_id = format!(
|
||||
let activity_id = Url::parse(&format!(
|
||||
"{}/activities/{}/{}",
|
||||
settings.get_protocol_and_hostname(),
|
||||
info.type_,
|
||||
info.id
|
||||
);
|
||||
))?
|
||||
.into();
|
||||
let activity = blocking(context.pool(), move |conn| {
|
||||
Activity::read_from_apub_id(&conn, &activity_id)
|
||||
})
|
||||
|
|
|
@ -45,7 +45,7 @@ pub(crate) async fn is_activity_already_known(
|
|||
pool: &DbPool,
|
||||
activity_id: &Url,
|
||||
) -> Result<bool, LemmyError> {
|
||||
let activity_id = activity_id.to_string();
|
||||
let activity_id = activity_id.to_owned().into();
|
||||
let existing = blocking(pool, move |conn| {
|
||||
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()
|
||||
.context(location_info!())?;
|
||||
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) => {
|
||||
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!())?;
|
||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||
PostOrComment::Post(post) => {
|
||||
receive_dislike_post(dislike, post, context, request_counter).await
|
||||
receive_dislike_post(dislike, *post, context, request_counter).await
|
||||
}
|
||||
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!())?;
|
||||
|
||||
match find_post_or_comment_by_id(context, object).await {
|
||||
Ok(PostOrComment::Post(p)) => receive_delete_post(context, p).await,
|
||||
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, c).await,
|
||||
Ok(PostOrComment::Post(p)) => receive_delete_post(context, *p).await,
|
||||
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, *c).await,
|
||||
// if we dont have the object, no need to do anything
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
|
@ -215,8 +215,8 @@ pub(in crate::inbox) async fn receive_remove_for_community(
|
|||
remove.id(community_id.domain().context(location_info!())?)?;
|
||||
|
||||
match find_post_or_comment_by_id(context, object).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::Post(p)) => receive_remove_post(context, remove, *p).await,
|
||||
Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, *c).await,
|
||||
// if we dont have the object, no need to do anything
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
|
@ -276,8 +276,8 @@ pub(in crate::inbox) async fn receive_undo_delete_for_community(
|
|||
.single_xsd_any_uri()
|
||||
.context(location_info!())?;
|
||||
match find_post_or_comment_by_id(context, object).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::Post(p)) => receive_undo_delete_post(context, *p).await,
|
||||
Ok(PostOrComment::Comment(c)) => receive_undo_delete_comment(context, *c).await,
|
||||
// if we dont have the object, no need to do anything
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
|
@ -300,8 +300,8 @@ pub(in crate::inbox) async fn receive_undo_remove_for_community(
|
|||
.single_xsd_any_uri()
|
||||
.context(location_info!())?;
|
||||
match find_post_or_comment_by_id(context, object).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::Post(p)) => receive_undo_remove_post(context, *p).await,
|
||||
Ok(PostOrComment::Comment(c)) => receive_undo_remove_comment(context, *c).await,
|
||||
// if we dont have the object, no need to do anything
|
||||
Err(_) => Ok(()),
|
||||
}
|
||||
|
@ -325,10 +325,10 @@ pub(in crate::inbox) async fn receive_undo_like_for_community(
|
|||
.context(location_info!())?;
|
||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||
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) => {
|
||||
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!())?;
|
||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||
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) => {
|
||||
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,
|
||||
) -> Result<PostOrComment, LemmyError> {
|
||||
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 {
|
||||
return Ok(PostOrComment::Comment(comment));
|
||||
return Ok(PostOrComment::Comment(Box::new(comment)));
|
||||
}
|
||||
|
||||
Err(NotFound.into())
|
||||
|
|
|
@ -26,13 +26,16 @@ use anyhow::{anyhow, Context};
|
|||
use diesel::NotFound;
|
||||
use lemmy_api_structs::blocking;
|
||||
use lemmy_db_queries::{source::activity::Activity_, ApubObject, DbPool};
|
||||
use lemmy_db_schema::source::{
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
activity::Activity,
|
||||
comment::Comment,
|
||||
community::Community,
|
||||
post::Post,
|
||||
private_message::PrivateMessage,
|
||||
user::User_,
|
||||
},
|
||||
DbUrl,
|
||||
};
|
||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
@ -216,7 +219,7 @@ pub enum EndpointType {
|
|||
pub fn generate_apub_endpoint(
|
||||
endpoint_type: EndpointType,
|
||||
name: &str,
|
||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
||||
) -> Result<DbUrl, ParseError> {
|
||||
let point = match endpoint_type {
|
||||
EndpointType::Community => "c",
|
||||
EndpointType::User => "u",
|
||||
|
@ -236,21 +239,15 @@ pub fn generate_apub_endpoint(
|
|||
)
|
||||
}
|
||||
|
||||
pub fn generate_followers_url(
|
||||
actor_id: &lemmy_db_schema::Url,
|
||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
||||
pub fn generate_followers_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
|
||||
}
|
||||
|
||||
pub fn generate_inbox_url(
|
||||
actor_id: &lemmy_db_schema::Url,
|
||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
||||
pub fn generate_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
|
||||
}
|
||||
|
||||
pub fn generate_shared_inbox_url(
|
||||
actor_id: &lemmy_db_schema::Url,
|
||||
) -> Result<lemmy_db_schema::Url, LemmyError> {
|
||||
pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
||||
let actor_id = actor_id.clone().into_inner();
|
||||
let url = format!(
|
||||
"{}://{}{}/inbox",
|
||||
|
@ -277,7 +274,7 @@ pub(crate) async fn insert_activity<T>(
|
|||
where
|
||||
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| {
|
||||
Activity::insert(conn, ap_id, &activity, local, sensitive)
|
||||
})
|
||||
|
@ -286,8 +283,8 @@ where
|
|||
}
|
||||
|
||||
pub(crate) enum PostOrComment {
|
||||
Comment(Comment),
|
||||
Post(Post),
|
||||
Comment(Box<Comment>),
|
||||
Post(Box<Post>),
|
||||
}
|
||||
|
||||
/// 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?;
|
||||
if let Ok(p) = post {
|
||||
return Ok(PostOrComment::Post(p));
|
||||
return Ok(PostOrComment::Post(Box::new(p)));
|
||||
}
|
||||
|
||||
let ap_id = apub_id.clone();
|
||||
|
@ -312,7 +309,7 @@ pub(crate) async fn find_post_or_comment_by_id(
|
|||
})
|
||||
.await?;
|
||||
if let Ok(c) = comment {
|
||||
return Ok(PostOrComment::Comment(c));
|
||||
return Ok(PostOrComment::Comment(Box::new(c)));
|
||||
}
|
||||
|
||||
Err(NotFound.into())
|
||||
|
@ -333,8 +330,8 @@ pub(crate) async fn find_object_by_id(
|
|||
let ap_id = apub_id.clone();
|
||||
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
||||
return Ok(match pc {
|
||||
PostOrComment::Post(p) => Object::Post(p),
|
||||
PostOrComment::Comment(c) => Object::Comment(c),
|
||||
PostOrComment::Post(p) => Object::Post(*p),
|
||||
PostOrComment::Comment(c) => Object::Comment(*c),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -73,13 +73,13 @@ impl ToApub for Community {
|
|||
|
||||
if let Some(icon_url) = &self.icon {
|
||||
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()?);
|
||||
}
|
||||
|
||||
if let Some(banner_url) = &self.banner {
|
||||
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()?);
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
|||
.url()
|
||||
.context(location_info!())?
|
||||
.as_single_xsd_any_uri()
|
||||
.map(|u| u.to_string()),
|
||||
.map(|u| u.to_owned().into()),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
@ -185,7 +185,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
|||
.url()
|
||||
.context(location_info!())?
|
||||
.as_single_xsd_any_uri()
|
||||
.map(|u| u.to_string()),
|
||||
.map(|u| u.to_owned().into()),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ use chrono::NaiveDateTime;
|
|||
use diesel::result::Error::NotFound;
|
||||
use lemmy_api_structs::blocking;
|
||||
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::{
|
||||
location_info,
|
||||
settings::structs::Settings,
|
||||
|
@ -96,7 +96,7 @@ where
|
|||
pub(in crate::objects) fn check_object_domain<T, Kind>(
|
||||
apub: &T,
|
||||
expected_domain: Url,
|
||||
) -> Result<lemmy_db_schema::Url, LemmyError>
|
||||
) -> Result<DbUrl, LemmyError>
|
||||
where
|
||||
T: Base + AsBase<Kind>,
|
||||
{
|
||||
|
|
|
@ -24,10 +24,13 @@ use activitystreams_ext::Ext1;
|
|||
use anyhow::Context;
|
||||
use lemmy_api_structs::blocking;
|
||||
use lemmy_db_queries::{Crud, DbPool};
|
||||
use lemmy_db_schema::source::{
|
||||
use lemmy_db_schema::{
|
||||
self,
|
||||
source::{
|
||||
community::Community,
|
||||
post::{Post, PostForm},
|
||||
user::User_,
|
||||
},
|
||||
};
|
||||
use lemmy_utils::{
|
||||
location_info,
|
||||
|
@ -70,16 +73,13 @@ impl ToApub for Post {
|
|||
set_content_and_source(&mut page, &body)?;
|
||||
}
|
||||
|
||||
// TODO: hacky code because we get self.url == Some("")
|
||||
// https://github.com/LemmyNet/lemmy/issues/602
|
||||
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(url) = &self.url {
|
||||
page.set_url::<Url>(url.to_owned().into());
|
||||
}
|
||||
|
||||
if let Some(thumbnail_url) = &self.thumbnail_url {
|
||||
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()?);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
|||
|
||||
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(
|
||||
any_image
|
||||
.to_owned()
|
||||
|
@ -158,7 +158,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
|||
.url()
|
||||
.context(location_info!())?
|
||||
.as_single_xsd_any_uri()
|
||||
.map(|u| u.to_string()),
|
||||
.map(|url| url.to_owned()),
|
||||
None => None,
|
||||
};
|
||||
let url = page
|
||||
|
@ -166,11 +166,11 @@ impl FromApubToForm<PageExt> for PostForm {
|
|||
.url()
|
||||
.map(|u| u.as_single_xsd_any_uri())
|
||||
.flatten()
|
||||
.map(|s| s.to_string());
|
||||
.map(|u| u.to_owned());
|
||||
|
||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||
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 {
|
||||
(None, None, None, thumbnail_url)
|
||||
};
|
||||
|
@ -192,7 +192,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
|||
let body_slurs_removed = body.map(|b| remove_slurs(&b));
|
||||
Ok(PostForm {
|
||||
name,
|
||||
url,
|
||||
url: url.map(|u| u.into()),
|
||||
body: body_slurs_removed,
|
||||
creator_id: creator.id,
|
||||
community_id: community.id,
|
||||
|
@ -214,7 +214,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
|||
embed_title: iframely_title,
|
||||
embed_description: iframely_description,
|
||||
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)?),
|
||||
local: false,
|
||||
})
|
||||
|
|
|
@ -50,13 +50,13 @@ impl ToApub for User_ {
|
|||
|
||||
if let Some(avatar_url) = &self.avatar {
|
||||
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()?);
|
||||
}
|
||||
|
||||
if let Some(banner_url) = &self.banner {
|
||||
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()?);
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
|||
.url()
|
||||
.context(location_info!())?
|
||||
.as_single_xsd_any_uri()
|
||||
.map(|u| u.to_string()),
|
||||
.map(|url| url.to_owned()),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
@ -139,7 +139,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
|||
.url()
|
||||
.context(location_info!())?
|
||||
.as_single_xsd_any_uri()
|
||||
.map(|u| u.to_string()),
|
||||
.map(|url| url.to_owned()),
|
||||
),
|
||||
None => None,
|
||||
};
|
||||
|
@ -174,8 +174,8 @@ impl FromApubToForm<PersonExt> for UserForm {
|
|||
admin: false,
|
||||
banned: None,
|
||||
email: None,
|
||||
avatar,
|
||||
banner,
|
||||
avatar: avatar.map(|o| o.map(|i| i.into())),
|
||||
banner: banner.map(|o| o.map(|i| i.into())),
|
||||
published: person.inner.published().map(|u| u.to_owned().naive_local()),
|
||||
updated: person.updated().map(|u| u.to_owned().naive_local()),
|
||||
show_nsfw: false,
|
||||
|
|
|
@ -20,7 +20,7 @@ strum = "0.20.0"
|
|||
strum_macros = "0.20.1"
|
||||
log = "0.4.14"
|
||||
sha2 = "0.9.3"
|
||||
url = { version = "2.2.0", features = ["serde"] }
|
||||
url = { version = "2.2.1", features = ["serde"] }
|
||||
lazy_static = "1.4.0"
|
||||
regex = "1.4.3"
|
||||
bcrypt = "0.9.0"
|
||||
|
|
|
@ -13,10 +13,12 @@ extern crate diesel_migrations;
|
|||
extern crate serial_test;
|
||||
|
||||
use diesel::{result::Error, *};
|
||||
use lemmy_db_schema::Url;
|
||||
use lemmy_db_schema::DbUrl;
|
||||
use lemmy_utils::ApiError;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{env, env::VarError};
|
||||
use url::Url;
|
||||
|
||||
pub mod aggregates;
|
||||
pub mod source;
|
||||
|
@ -112,7 +114,7 @@ pub trait Reportable<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
|
||||
Self: Sized;
|
||||
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!();
|
||||
|
||||
pub fn establish_unpooled_connection() -> PgConnection {
|
||||
|
@ -251,7 +267,7 @@ pub mod functions {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::fuzzy_search;
|
||||
use super::{fuzzy_search, *};
|
||||
use crate::is_email_regex;
|
||||
|
||||
#[test]
|
||||
|
@ -265,4 +281,32 @@ mod tests {
|
|||
assert!(is_email_regex("gush@gmail.com"));
|
||||
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 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 serde::Serialize;
|
||||
use serde_json::Value;
|
||||
|
@ -41,7 +41,7 @@ impl Crud<ActivityForm> for Activity {
|
|||
pub trait Activity_ {
|
||||
fn insert<T>(
|
||||
conn: &PgConnection,
|
||||
ap_id: String,
|
||||
ap_id: DbUrl,
|
||||
data: &T,
|
||||
local: bool,
|
||||
sensitive: bool,
|
||||
|
@ -49,20 +49,20 @@ pub trait Activity_ {
|
|||
where
|
||||
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>;
|
||||
|
||||
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
||||
fn read_community_outbox(
|
||||
conn: &PgConnection,
|
||||
community_actor_id: &Url,
|
||||
community_actor_id: &DbUrl,
|
||||
) -> Result<Vec<Value>, Error>;
|
||||
}
|
||||
|
||||
impl Activity_ for Activity {
|
||||
fn insert<T>(
|
||||
conn: &PgConnection,
|
||||
ap_id: String,
|
||||
ap_id: DbUrl,
|
||||
data: &T,
|
||||
local: 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::*;
|
||||
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ impl Activity_ for Activity {
|
|||
|
||||
fn read_community_outbox(
|
||||
conn: &PgConnection,
|
||||
community_actor_id: &Url,
|
||||
community_actor_id: &DbUrl,
|
||||
) -> Result<Vec<Value>, Error> {
|
||||
use lemmy_db_schema::schema::activity::dsl::*;
|
||||
let res: Vec<Value> = activity
|
||||
|
@ -121,6 +121,7 @@ impl Activity_ for Activity {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
establish_unpooled_connection,
|
||||
source::activity::Activity_,
|
||||
|
@ -134,6 +135,7 @@ mod tests {
|
|||
};
|
||||
use serde_json::Value;
|
||||
use serial_test::serial;
|
||||
use url::Url;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
|
@ -171,8 +173,11 @@ mod tests {
|
|||
|
||||
let inserted_creator = User_::create(&conn, &creator_form).unwrap();
|
||||
|
||||
let ap_id =
|
||||
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c";
|
||||
let ap_id: DbUrl = Url::parse(
|
||||
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
|
||||
)
|
||||
.unwrap()
|
||||
.into();
|
||||
let test_json: Value = serde_json::from_str(
|
||||
r#"{
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
|
@ -188,7 +193,7 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
let activity_form = ActivityForm {
|
||||
ap_id: ap_id.to_string(),
|
||||
ap_id: ap_id.clone(),
|
||||
data: test_json.to_owned(),
|
||||
local: true,
|
||||
sensitive: false,
|
||||
|
@ -198,7 +203,7 @@ mod tests {
|
|||
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
||||
|
||||
let expected_activity = Activity {
|
||||
ap_id: Some(ap_id.to_string()),
|
||||
ap_id: Some(ap_id.clone()),
|
||||
id: inserted_activity.id,
|
||||
data: test_json,
|
||||
local: true,
|
||||
|
@ -208,7 +213,7 @@ mod tests {
|
|||
};
|
||||
|
||||
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();
|
||||
Activity::delete(&conn, inserted_activity.id).unwrap();
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@ use lemmy_db_schema::{
|
|||
CommentSaved,
|
||||
CommentSavedForm,
|
||||
},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
|
||||
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(
|
||||
conn: &PgConnection,
|
||||
for_creator_id: i32,
|
||||
|
@ -43,7 +43,7 @@ pub trait 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::*;
|
||||
|
||||
diesel::update(comment.find(comment_id))
|
||||
|
@ -145,7 +145,7 @@ impl Crud<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::*;
|
||||
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
|||
CommunityUserBan,
|
||||
CommunityUserBanForm,
|
||||
},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
|
||||
mod safe_type {
|
||||
|
@ -90,7 +90,7 @@ impl Crud<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::*;
|
||||
community
|
||||
.filter(actor_id.eq(for_actor_id))
|
||||
|
@ -131,7 +131,10 @@ pub trait Community_ {
|
|||
new_creator_id: i32,
|
||||
) -> Result<Community, 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 {
|
||||
|
@ -194,7 +197,7 @@ impl Community_ for Community {
|
|||
|
||||
fn read_from_followers_url(
|
||||
conn: &PgConnection,
|
||||
followers_url_: &Url,
|
||||
followers_url_: &DbUrl,
|
||||
) -> Result<Community, Error> {
|
||||
use lemmy_db_schema::schema::community::dsl::*;
|
||||
community
|
||||
|
|
|
@ -12,7 +12,7 @@ use lemmy_db_schema::{
|
|||
PostSaved,
|
||||
PostSavedForm,
|
||||
},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
|
||||
impl Crud<PostForm> for Post {
|
||||
|
@ -42,7 +42,7 @@ impl Crud<PostForm> for Post {
|
|||
pub trait Post_ {
|
||||
//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 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 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>;
|
||||
|
@ -68,7 +68,7 @@ impl Post_ for Post {
|
|||
.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::*;
|
||||
|
||||
diesel::update(post.find(post_id))
|
||||
|
@ -147,7 +147,7 @@ impl Post_ 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::*;
|
||||
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{ApubObject, Crud};
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ pub trait PrivateMessage_ {
|
|||
fn update_ap_id(
|
||||
conn: &PgConnection,
|
||||
private_message_id: i32,
|
||||
apub_id: Url,
|
||||
apub_id: DbUrl,
|
||||
) -> Result<PrivateMessage, Error>;
|
||||
fn update_content(
|
||||
conn: &PgConnection,
|
||||
|
@ -80,7 +80,7 @@ impl PrivateMessage_ for PrivateMessage {
|
|||
fn update_ap_id(
|
||||
conn: &PgConnection,
|
||||
private_message_id: i32,
|
||||
apub_id: Url,
|
||||
apub_id: DbUrl,
|
||||
) -> Result<PrivateMessage, Error> {
|
||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use lemmy_db_schema::{
|
|||
naive_now,
|
||||
schema::user_::dsl::*,
|
||||
source::user::{UserForm, UserSafeSettings, User_},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
use lemmy_utils::settings::structs::Settings;
|
||||
|
||||
|
@ -242,7 +242,7 @@ impl Crud<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::*;
|
||||
user_
|
||||
.filter(deleted.eq(false))
|
||||
|
|
|
@ -12,4 +12,4 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
|||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
||||
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},
|
||||
sql_types::Text,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
io::Write,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
pub mod schema;
|
||||
pub mod source;
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone, PartialEq, Serialize, Debug, AsExpression, FromSqlRow)]
|
||||
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, AsExpression, FromSqlRow)]
|
||||
#[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
|
||||
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
|
||||
String: FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
||||
let str = String::from_sql(bytes)?;
|
||||
Ok(Url(url::Url::parse(&str)?))
|
||||
Ok(DbUrl(Url::parse(&str)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl Url {
|
||||
pub fn into_inner(self) -> url::Url {
|
||||
impl DbUrl {
|
||||
pub fn into_inner(self) -> Url {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Url {
|
||||
impl Display for DbUrl {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
self.to_owned().into_inner().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Url> for url::Url {
|
||||
fn from(url: Url) -> Self {
|
||||
impl From<DbUrl> for Url {
|
||||
fn from(url: DbUrl) -> Self {
|
||||
url.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::Url> for Url {
|
||||
fn from(url: url::Url) -> Self {
|
||||
Url(url)
|
||||
impl From<Url> for DbUrl {
|
||||
fn from(url: Url) -> Self {
|
||||
DbUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::schema::activity;
|
||||
use crate::{schema::activity, DbUrl};
|
||||
use serde_json::Value;
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
@ -10,7 +10,7 @@ pub struct Activity {
|
|||
pub local: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub ap_id: Option<String>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
pub sensitive: Option<bool>,
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,6 @@ pub struct ActivityForm {
|
|||
pub data: Value,
|
||||
pub local: bool,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub ap_id: String,
|
||||
pub ap_id: DbUrl,
|
||||
pub sensitive: bool,
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
schema::{comment, comment_alias_1, comment_like, comment_saved},
|
||||
source::post::Post,
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -26,7 +26,7 @@ pub struct Comment {
|
|||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: bool,
|
||||
pub ap_id: Url,
|
||||
pub ap_id: DbUrl,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ pub struct CommentAlias1 {
|
|||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: bool,
|
||||
pub ap_id: Url,
|
||||
pub ap_id: DbUrl,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ pub struct CommentForm {
|
|||
pub published: Option<chrono::NaiveDateTime>,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: Option<bool>,
|
||||
pub ap_id: Option<Url>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
schema::{community, community_follower, community_moderator, community_user_ban},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -17,16 +17,16 @@ pub struct Community {
|
|||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: bool,
|
||||
pub nsfw: bool,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub followers_url: Url,
|
||||
pub inbox_url: Url,
|
||||
pub shared_inbox_url: Option<Url>,
|
||||
pub icon: Option<DbUrl>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub followers_url: DbUrl,
|
||||
pub inbox_url: DbUrl,
|
||||
pub shared_inbox_url: Option<DbUrl>,
|
||||
}
|
||||
|
||||
/// A safe representation of community, without the sensitive info
|
||||
|
@ -43,10 +43,10 @@ pub struct CommunitySafe {
|
|||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: bool,
|
||||
pub nsfw: bool,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub local: bool,
|
||||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub icon: Option<DbUrl>,
|
||||
pub banner: Option<DbUrl>,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset, Debug)]
|
||||
|
@ -61,16 +61,16 @@ pub struct CommunityForm {
|
|||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub deleted: Option<bool>,
|
||||
pub nsfw: bool,
|
||||
pub actor_id: Option<Url>,
|
||||
pub actor_id: Option<DbUrl>,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||
pub icon: Option<Option<String>>,
|
||||
pub banner: Option<Option<String>>,
|
||||
pub followers_url: Option<Url>,
|
||||
pub inbox_url: Option<Url>,
|
||||
pub shared_inbox_url: Option<Option<Url>>,
|
||||
pub icon: Option<Option<DbUrl>>,
|
||||
pub banner: Option<Option<DbUrl>>,
|
||||
pub followers_url: Option<DbUrl>,
|
||||
pub inbox_url: Option<DbUrl>,
|
||||
pub shared_inbox_url: Option<Option<DbUrl>>,
|
||||
}
|
||||
|
||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
schema::{post, post_like, post_read, post_saved},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -9,7 +9,7 @@ use serde::Serialize;
|
|||
pub struct Post {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub url: Option<String>,
|
||||
pub url: Option<DbUrl>,
|
||||
pub body: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub community_id: i32,
|
||||
|
@ -23,8 +23,8 @@ pub struct Post {
|
|||
pub embed_title: Option<String>,
|
||||
pub embed_description: Option<String>,
|
||||
pub embed_html: Option<String>,
|
||||
pub thumbnail_url: Option<String>,
|
||||
pub ap_id: Url,
|
||||
pub thumbnail_url: Option<DbUrl>,
|
||||
pub ap_id: DbUrl,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ pub struct Post {
|
|||
#[table_name = "post"]
|
||||
pub struct PostForm {
|
||||
pub name: String,
|
||||
pub url: Option<String>,
|
||||
pub url: Option<DbUrl>,
|
||||
pub body: Option<String>,
|
||||
pub creator_id: i32,
|
||||
pub community_id: i32,
|
||||
|
@ -46,8 +46,8 @@ pub struct PostForm {
|
|||
pub embed_title: Option<String>,
|
||||
pub embed_description: Option<String>,
|
||||
pub embed_html: Option<String>,
|
||||
pub thumbnail_url: Option<String>,
|
||||
pub ap_id: Option<Url>,
|
||||
pub thumbnail_url: Option<DbUrl>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
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};
|
||||
|
||||
#[derive(
|
||||
|
@ -11,7 +11,7 @@ pub struct PostReport {
|
|||
pub creator_id: i32,
|
||||
pub post_id: i32,
|
||||
pub original_post_name: String,
|
||||
pub original_post_url: Option<String>,
|
||||
pub original_post_url: Option<DbUrl>,
|
||||
pub original_post_body: Option<String>,
|
||||
pub reason: String,
|
||||
pub resolved: bool,
|
||||
|
@ -26,7 +26,7 @@ pub struct PostReportForm {
|
|||
pub creator_id: i32,
|
||||
pub post_id: i32,
|
||||
pub original_post_name: String,
|
||||
pub original_post_url: Option<String>,
|
||||
pub original_post_url: Option<DbUrl>,
|
||||
pub original_post_body: Option<String>,
|
||||
pub reason: String,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{schema::private_message, Url};
|
||||
use crate::{schema::private_message, DbUrl};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
|
||||
|
@ -12,7 +12,7 @@ pub struct PrivateMessage {
|
|||
pub read: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub ap_id: Url,
|
||||
pub ap_id: DbUrl,
|
||||
pub local: bool,
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,6 @@ pub struct PrivateMessageForm {
|
|||
pub read: Option<bool>,
|
||||
pub published: Option<chrono::NaiveDateTime>,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub ap_id: Option<Url>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
pub local: bool,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::schema::site;
|
||||
use crate::{schema::site, DbUrl};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Queryable, Identifiable, PartialEq, Debug, Clone, Serialize)]
|
||||
|
@ -13,8 +13,8 @@ pub struct Site {
|
|||
pub enable_downvotes: bool,
|
||||
pub open_registration: bool,
|
||||
pub enable_nsfw: bool,
|
||||
pub icon: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub icon: Option<DbUrl>,
|
||||
pub banner: Option<DbUrl>,
|
||||
}
|
||||
|
||||
#[derive(Insertable, AsChangeset)]
|
||||
|
@ -28,6 +28,6 @@ pub struct SiteForm {
|
|||
pub open_registration: 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.
|
||||
pub icon: Option<Option<String>>,
|
||||
pub banner: Option<Option<String>>,
|
||||
pub icon: Option<Option<DbUrl>>,
|
||||
pub banner: Option<Option<DbUrl>>,
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
schema::{user_, user_alias_1, user_alias_2},
|
||||
Url,
|
||||
DbUrl,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
|
@ -12,7 +12,7 @@ pub struct User_ {
|
|||
pub preferred_username: Option<String>,
|
||||
pub password_encrypted: String,
|
||||
pub email: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
|
@ -25,16 +25,16 @@ pub struct User_ {
|
|||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
pub inbox_url: Url,
|
||||
pub shared_inbox_url: Option<Url>,
|
||||
pub inbox_url: DbUrl,
|
||||
pub shared_inbox_url: Option<DbUrl>,
|
||||
}
|
||||
|
||||
/// A safe representation of user, without the sensitive info
|
||||
|
@ -44,19 +44,19 @@ pub struct UserSafe {
|
|||
pub id: i32,
|
||||
pub name: String,
|
||||
pub preferred_username: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
pub inbox_url: Url,
|
||||
pub shared_inbox_url: Option<Url>,
|
||||
pub inbox_url: DbUrl,
|
||||
pub shared_inbox_url: Option<DbUrl>,
|
||||
}
|
||||
|
||||
/// A safe user view with only settings
|
||||
|
@ -67,7 +67,7 @@ pub struct UserSafeSettings {
|
|||
pub name: String,
|
||||
pub preferred_username: Option<String>,
|
||||
pub email: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
|
@ -80,11 +80,11 @@ pub struct UserSafeSettings {
|
|||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ pub struct UserAlias1 {
|
|||
pub preferred_username: Option<String>,
|
||||
pub password_encrypted: String,
|
||||
pub email: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
|
@ -109,13 +109,13 @@ pub struct UserAlias1 {
|
|||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
|
@ -125,16 +125,16 @@ pub struct UserSafeAlias1 {
|
|||
pub id: i32,
|
||||
pub name: String,
|
||||
pub preferred_username: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ pub struct UserAlias2 {
|
|||
pub preferred_username: Option<String>,
|
||||
pub password_encrypted: String,
|
||||
pub email: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
|
@ -159,13 +159,13 @@ pub struct UserAlias2 {
|
|||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
|
@ -175,16 +175,16 @@ pub struct UserSafeAlias2 {
|
|||
pub id: i32,
|
||||
pub name: String,
|
||||
pub preferred_username: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub avatar: Option<DbUrl>,
|
||||
pub admin: bool,
|
||||
pub banned: bool,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub matrix_user_id: Option<String>,
|
||||
pub actor_id: Url,
|
||||
pub actor_id: DbUrl,
|
||||
pub bio: Option<String>,
|
||||
pub local: bool,
|
||||
pub banner: Option<String>,
|
||||
pub banner: Option<DbUrl>,
|
||||
pub deleted: bool,
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ pub struct UserForm {
|
|||
pub admin: bool,
|
||||
pub banned: Option<bool>,
|
||||
pub email: Option<Option<String>>,
|
||||
pub avatar: Option<Option<String>>,
|
||||
pub avatar: Option<Option<DbUrl>>,
|
||||
pub published: Option<chrono::NaiveDateTime>,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
pub show_nsfw: bool,
|
||||
|
@ -208,13 +208,13 @@ pub struct UserForm {
|
|||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub matrix_user_id: Option<Option<String>>,
|
||||
pub actor_id: Option<Url>,
|
||||
pub actor_id: Option<DbUrl>,
|
||||
pub bio: Option<Option<String>>,
|
||||
pub local: bool,
|
||||
pub private_key: Option<String>,
|
||||
pub public_key: Option<String>,
|
||||
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||
pub banner: Option<Option<String>>,
|
||||
pub inbox_url: Option<Url>,
|
||||
pub shared_inbox_url: Option<Option<Url>>,
|
||||
pub banner: Option<Option<DbUrl>>,
|
||||
pub inbox_url: Option<DbUrl>,
|
||||
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"] }
|
||||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
log = "0.4.14"
|
||||
url = "2.2.0"
|
||||
url = "2.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.5.1"
|
|
@ -25,6 +25,6 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
|||
rss = "1.10.0"
|
||||
serde = { version = "1.0.123", features = ["derive"] }
|
||||
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"
|
||||
lazy_static = "1.4.0"
|
||||
|
|
|
@ -22,7 +22,7 @@ thiserror = "1.0.23"
|
|||
comrak = { version = "0.9.0", default-features = false }
|
||||
lazy_static = "1.4.0"
|
||||
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-rt = { version = "1.1.1", default-features = false }
|
||||
anyhow = "1.0.38"
|
||||
|
|
|
@ -6,6 +6,7 @@ use reqwest::Client;
|
|||
use serde::Deserialize;
|
||||
use std::future::Future;
|
||||
use thiserror::Error;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[error("Error sending request, {0}")]
|
||||
|
@ -50,13 +51,13 @@ where
|
|||
pub(crate) struct IframelyResponse {
|
||||
title: Option<String>,
|
||||
description: Option<String>,
|
||||
thumbnail_url: Option<String>,
|
||||
thumbnail_url: Option<Url>,
|
||||
html: Option<String>,
|
||||
}
|
||||
|
||||
pub(crate) async fn fetch_iframely(
|
||||
client: &Client,
|
||||
url: &str,
|
||||
url: &Url,
|
||||
) -> Result<IframelyResponse, LemmyError> {
|
||||
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(
|
||||
client: &Client,
|
||||
image_url: &str,
|
||||
image_url: &Url,
|
||||
) -> Result<PictrsResponse, LemmyError> {
|
||||
is_image_content_type(client, image_url).await?;
|
||||
|
||||
let fetch_url = format!(
|
||||
"{}/image/download?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?;
|
||||
|
@ -109,13 +110,8 @@ pub(crate) async fn fetch_pictrs(
|
|||
|
||||
pub async fn fetch_iframely_and_pictrs_data(
|
||||
client: &Client,
|
||||
url: Option<String>,
|
||||
) -> (
|
||||
Option<String>,
|
||||
Option<String>,
|
||||
Option<String>,
|
||||
Option<String>,
|
||||
) {
|
||||
url: Option<&Url>,
|
||||
) -> (Option<String>, Option<String>, Option<String>, Option<Url>) {
|
||||
match &url {
|
||||
Some(url) => {
|
||||
// Fetch iframely data
|
||||
|
@ -149,11 +145,19 @@ pub async fn fetch_iframely_and_pictrs_data(
|
|||
|
||||
// The full urls are necessary for federation
|
||||
let pictrs_thumbnail = if let Some(pictrs_hash) = pictrs_hash {
|
||||
Some(format!(
|
||||
let url = Url::parse(&format!(
|
||||
"{}/pictrs/image/{}",
|
||||
Settings::get().get_protocol_and_hostname(),
|
||||
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 {
|
||||
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> {
|
||||
let response = retry(|| client.get(test).send()).await?;
|
||||
|
||||
async fn is_image_content_type(client: &Client, test: &Url) -> Result<(), LemmyError> {
|
||||
let response = retry(|| client.get(test.to_owned()).send()).await?;
|
||||
if response
|
||||
.headers()
|
||||
.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