This commit is contained in:
parent
d83a53e905
commit
4a23ee4d8b
19 changed files with 182 additions and 148 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1847,6 +1847,7 @@ dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
"itertools",
|
||||||
"lemmy_db_schema",
|
"lemmy_db_schema",
|
||||||
"lemmy_db_views",
|
"lemmy_db_views",
|
||||||
"lemmy_db_views_actor",
|
"lemmy_db_views_actor",
|
||||||
|
|
|
@ -8,22 +8,17 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
is_admin,
|
is_admin,
|
||||||
|
resolve_actor_identifier,
|
||||||
send_application_approved_email,
|
send_application_approved_email,
|
||||||
site::*,
|
site::*,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_apub::fetcher::search::{search_by_apub_id, SearchableObjects};
|
||||||
fetcher::{
|
|
||||||
search::{search_by_apub_id, SearchableObjects},
|
|
||||||
webfinger::webfinger_resolve,
|
|
||||||
},
|
|
||||||
objects::community::ApubCommunity,
|
|
||||||
EndpointType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite,
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
newtypes::PersonId,
|
newtypes::PersonId,
|
||||||
source::{
|
source::{
|
||||||
|
community::Community,
|
||||||
local_user::{LocalUser, LocalUserForm},
|
local_user::{LocalUser, LocalUserForm},
|
||||||
moderator::*,
|
moderator::*,
|
||||||
person::Person,
|
person::Person,
|
||||||
|
@ -195,9 +190,10 @@ impl Perform for Search {
|
||||||
let search_type: SearchType = from_opt_str_to_opt_enum(&data.type_).unwrap_or(SearchType::All);
|
let search_type: SearchType = from_opt_str_to_opt_enum(&data.type_).unwrap_or(SearchType::All);
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let community_actor_id = if let Some(name) = &data.community_name {
|
let community_actor_id = if let Some(name) = &data.community_name {
|
||||||
webfinger_resolve::<ApubCommunity>(name, EndpointType::Community, context, &mut 0)
|
resolve_actor_identifier::<Community>(name, context.pool())
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
|
.map(|c| c.actor_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,3 +25,4 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde_json = { version = "1.0.72", features = ["preserve_order"] }
|
serde_json = { version = "1.0.72", features = ["preserve_order"] }
|
||||||
tracing = "0.1.29"
|
tracing = "0.1.29"
|
||||||
url = "2.2.2"
|
url = "2.2.2"
|
||||||
|
itertools = "0.10.3"
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub mod site;
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
use crate::site::FederatedInstances;
|
use crate::site::FederatedInstances;
|
||||||
|
use itertools::Itertools;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
|
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
|
||||||
source::{
|
source::{
|
||||||
|
@ -18,7 +19,7 @@ use lemmy_db_schema::{
|
||||||
secret::Secret,
|
secret::Secret,
|
||||||
site::Site,
|
site::Site,
|
||||||
},
|
},
|
||||||
traits::{Crud, Readable},
|
traits::{ApubActor, Crud, Readable},
|
||||||
DbPool,
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
|
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
|
||||||
|
@ -521,3 +522,36 @@ pub async fn check_private_instance_and_federation_enabled(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolve actor identifier (eg `!news@example.com`) from local database to avoid network requests.
|
||||||
|
/// This only works for local actors, and remote actors which were previously fetched (so it doesnt
|
||||||
|
/// trigger any new fetch).
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
pub async fn resolve_actor_identifier<Actor>(
|
||||||
|
identifier: &str,
|
||||||
|
pool: &DbPool,
|
||||||
|
) -> Result<Actor, LemmyError>
|
||||||
|
where
|
||||||
|
Actor: ApubActor + Send + 'static,
|
||||||
|
{
|
||||||
|
// remote actor
|
||||||
|
if identifier.contains('@') {
|
||||||
|
let (name, domain) = identifier
|
||||||
|
.splitn(2, '@')
|
||||||
|
.collect_tuple()
|
||||||
|
.expect("invalid query");
|
||||||
|
let name = name.to_string();
|
||||||
|
let domain = format!("{}://{}", Settings::get().get_protocol_string(), domain);
|
||||||
|
Ok(
|
||||||
|
blocking(pool, move |conn| {
|
||||||
|
Actor::read_from_name_and_domain(conn, &name, &domain)
|
||||||
|
})
|
||||||
|
.await??,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// local actor
|
||||||
|
else {
|
||||||
|
let identifier = identifier.to_string();
|
||||||
|
Ok(blocking(pool, move |conn| Actor::read_from_name(conn, &identifier)).await??)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,14 +5,11 @@ use lemmy_api_common::{
|
||||||
check_private_instance,
|
check_private_instance,
|
||||||
comment::*,
|
comment::*,
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
};
|
resolve_actor_identifier,
|
||||||
use lemmy_apub::{
|
|
||||||
fetcher::webfinger::webfinger_resolve,
|
|
||||||
objects::community::ApubCommunity,
|
|
||||||
EndpointType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
|
source::community::Community,
|
||||||
traits::DeleteableOrRemoveable,
|
traits::DeleteableOrRemoveable,
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
|
@ -82,9 +79,10 @@ impl PerformCrud for GetComments {
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let community_actor_id = if let Some(name) = &data.community_name {
|
let community_actor_id = if let Some(name) = &data.community_name {
|
||||||
webfinger_resolve::<ApubCommunity>(name, EndpointType::Community, context, &mut 0)
|
resolve_actor_identifier::<Community>(name, context.pool())
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
|
.map(|c| c.actor_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,15 +5,11 @@ use lemmy_api_common::{
|
||||||
check_private_instance,
|
check_private_instance,
|
||||||
community::*,
|
community::*,
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
|
resolve_actor_identifier,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
|
||||||
fetcher::webfinger::webfinger_resolve,
|
|
||||||
objects::community::ApubCommunity,
|
|
||||||
EndpointType,
|
|
||||||
};
|
|
||||||
use lemmy_apub_lib::object_id::ObjectId;
|
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
|
source::community::Community,
|
||||||
traits::DeleteableOrRemoveable,
|
traits::DeleteableOrRemoveable,
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
|
@ -48,12 +44,7 @@ impl PerformCrud for GetCommunity {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => {
|
None => {
|
||||||
let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
|
let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
|
||||||
let community_actor_id =
|
resolve_actor_identifier::<Community>(&name, context.pool())
|
||||||
webfinger_resolve::<ApubCommunity>(&name, EndpointType::Community, context, &mut 0)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
ObjectId::<ApubCommunity>::new(community_actor_id)
|
|
||||||
.dereference(context, context.client(), &mut 0)
|
|
||||||
.await
|
.await
|
||||||
.map_err(LemmyError::from)
|
.map_err(LemmyError::from)
|
||||||
.map_err(|e| e.with_message("couldnt_find_community"))?
|
.map_err(|e| e.with_message("couldnt_find_community"))?
|
||||||
|
|
|
@ -6,14 +6,11 @@ use lemmy_api_common::{
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
mark_post_as_read,
|
mark_post_as_read,
|
||||||
post::*,
|
post::*,
|
||||||
};
|
resolve_actor_identifier,
|
||||||
use lemmy_apub::{
|
|
||||||
fetcher::webfinger::webfinger_resolve,
|
|
||||||
objects::community::ApubCommunity,
|
|
||||||
EndpointType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
from_opt_str_to_opt_enum,
|
from_opt_str_to_opt_enum,
|
||||||
|
source::community::Community,
|
||||||
traits::DeleteableOrRemoveable,
|
traits::DeleteableOrRemoveable,
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
|
@ -157,9 +154,10 @@ impl PerformCrud for GetPosts {
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let community_actor_id = if let Some(name) = &data.community_name {
|
let community_actor_id = if let Some(name) = &data.community_name {
|
||||||
webfinger_resolve::<ApubCommunity>(name, EndpointType::Community, context, &mut 0)
|
resolve_actor_identifier::<Community>(name, context.pool())
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
|
.map(|c| c.actor_id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,14 +5,9 @@ use lemmy_api_common::{
|
||||||
check_private_instance,
|
check_private_instance,
|
||||||
get_local_user_view_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
person::*,
|
person::*,
|
||||||
|
resolve_actor_identifier,
|
||||||
};
|
};
|
||||||
use lemmy_apub::{
|
use lemmy_db_schema::{from_opt_str_to_opt_enum, source::person::Person, SortType};
|
||||||
fetcher::webfinger::webfinger_resolve,
|
|
||||||
objects::person::ApubPerson,
|
|
||||||
EndpointType,
|
|
||||||
};
|
|
||||||
use lemmy_apub_lib::object_id::ObjectId;
|
|
||||||
use lemmy_db_schema::{from_opt_str_to_opt_enum, SortType};
|
|
||||||
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
|
use lemmy_db_views::{comment_view::CommentQueryBuilder, post_view::PostQueryBuilder};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
|
@ -55,13 +50,9 @@ impl PerformCrud for GetPersonDetails {
|
||||||
.username
|
.username
|
||||||
.to_owned()
|
.to_owned()
|
||||||
.unwrap_or_else(|| "admin".to_string());
|
.unwrap_or_else(|| "admin".to_string());
|
||||||
let actor_id =
|
|
||||||
webfinger_resolve::<ApubPerson>(&name, EndpointType::Person, context, &mut 0).await?;
|
|
||||||
|
|
||||||
let person = ObjectId::<ApubPerson>::new(actor_id)
|
resolve_actor_identifier::<Person>(&name, context.pool())
|
||||||
.dereference(context, context.client(), &mut 0)
|
.await
|
||||||
.await;
|
|
||||||
person
|
|
||||||
.map_err(LemmyError::from)
|
.map_err(LemmyError::from)
|
||||||
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?
|
.map_err(|e| e.with_message("couldnt_find_that_username_or_email"))?
|
||||||
.id
|
.id
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
fetcher::webfinger::webfinger_resolve,
|
fetcher::webfinger::webfinger_resolve_actor,
|
||||||
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
|
||||||
protocol::objects::{group::Group, note::Note, page::Page, person::Person},
|
protocol::objects::{group::Group, note::Note, page::Page, person::Person},
|
||||||
EndpointType,
|
|
||||||
};
|
};
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
||||||
|
@ -34,13 +33,8 @@ pub async fn search_by_apub_id(
|
||||||
let (kind, identifier) = query.split_at(1);
|
let (kind, identifier) = query.split_at(1);
|
||||||
match kind {
|
match kind {
|
||||||
"@" => {
|
"@" => {
|
||||||
let id = webfinger_resolve::<ApubPerson>(
|
let id =
|
||||||
identifier,
|
webfinger_resolve_actor::<ApubPerson>(identifier, context, request_counter).await?;
|
||||||
EndpointType::Person,
|
|
||||||
context,
|
|
||||||
request_counter,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(SearchableObjects::Person(
|
Ok(SearchableObjects::Person(
|
||||||
ObjectId::new(id)
|
ObjectId::new(id)
|
||||||
.dereference(context, context.client(), request_counter)
|
.dereference(context, context.client(), request_counter)
|
||||||
|
@ -48,13 +42,8 @@ pub async fn search_by_apub_id(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
"!" => {
|
"!" => {
|
||||||
let id = webfinger_resolve::<ApubCommunity>(
|
let id =
|
||||||
identifier,
|
webfinger_resolve_actor::<ApubCommunity>(identifier, context, request_counter).await?;
|
||||||
EndpointType::Community,
|
|
||||||
context,
|
|
||||||
request_counter,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
Ok(SearchableObjects::Community(
|
Ok(SearchableObjects::Community(
|
||||||
ObjectId::new(id)
|
ObjectId::new(id)
|
||||||
.dereference(context, context.client(), request_counter)
|
.dereference(context, context.client(), request_counter)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::{generate_local_apub_endpoint, EndpointType};
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_apub_lib::{
|
use lemmy_apub_lib::{
|
||||||
object_id::ObjectId,
|
object_id::ObjectId,
|
||||||
|
@ -28,37 +27,6 @@ pub struct WebfingerResponse {
|
||||||
pub links: Vec<WebfingerLink>,
|
pub links: Vec<WebfingerLink>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes in a shortname of the type dessalines@xyz.tld or dessalines (assumed to be local), and
|
|
||||||
/// outputs the actor id. Used in the API for communities and users.
|
|
||||||
///
|
|
||||||
/// TODO: later provide a method in ApubObject to generate the endpoint, so that we dont have to
|
|
||||||
/// pass in EndpointType
|
|
||||||
#[tracing::instrument(skip_all)]
|
|
||||||
pub async fn webfinger_resolve<Kind>(
|
|
||||||
identifier: &str,
|
|
||||||
endpoint_type: EndpointType,
|
|
||||||
context: &LemmyContext,
|
|
||||||
request_counter: &mut i32,
|
|
||||||
) -> Result<DbUrl, LemmyError>
|
|
||||||
where
|
|
||||||
Kind: ApubObject<DataType = LemmyContext> + ActorType + Send + 'static,
|
|
||||||
for<'de2> <Kind as ApubObject>::ApubType: serde::Deserialize<'de2>,
|
|
||||||
{
|
|
||||||
// remote actor
|
|
||||||
if identifier.contains('@') {
|
|
||||||
webfinger_resolve_actor::<Kind>(identifier, context, request_counter).await
|
|
||||||
}
|
|
||||||
// local actor
|
|
||||||
else {
|
|
||||||
let domain = context.settings().get_protocol_and_hostname();
|
|
||||||
Ok(generate_local_apub_endpoint(
|
|
||||||
endpoint_type,
|
|
||||||
identifier,
|
|
||||||
&domain,
|
|
||||||
)?)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
||||||
/// using webfinger.
|
/// using webfinger.
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::{
|
||||||
use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
|
use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
use lemmy_apub_lib::{object_id::ObjectId, traits::ApubObject};
|
||||||
use lemmy_db_schema::source::community::Community;
|
use lemmy_db_schema::{source::community::Community, traits::ApubActor};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
|
@ -14,7 +14,7 @@ use crate::{
|
||||||
use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
|
use actix_web::{web, web::Payload, HttpRequest, HttpResponse};
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub_lib::traits::ApubObject;
|
use lemmy_apub_lib::traits::ApubObject;
|
||||||
use lemmy_db_schema::source::person::Person;
|
use lemmy_db_schema::{source::person::Person, traits::ApubActor};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -34,7 +34,7 @@ pub(crate) async fn get_apub_person_http(
|
||||||
let user_name = info.into_inner().user_name;
|
let user_name = info.into_inner().user_name;
|
||||||
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
||||||
let person: ApubPerson = blocking(context.pool(), move |conn| {
|
let person: ApubPerson = blocking(context.pool(), move |conn| {
|
||||||
Person::find_by_name(conn, &user_name)
|
Person::read_from_name(conn, &user_name)
|
||||||
})
|
})
|
||||||
.await??
|
.await??
|
||||||
.into();
|
.into();
|
||||||
|
@ -77,7 +77,7 @@ pub(crate) async fn get_apub_person_outbox(
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
let person = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
Person::find_by_name(conn, &info.user_name)
|
Person::read_from_name(conn, &info.user_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
let outbox = PersonOutbox::new(person).await?;
|
let outbox = PersonOutbox::new(person).await?;
|
||||||
|
|
|
@ -18,7 +18,7 @@ use lemmy_apub_lib::{
|
||||||
traits::{ActorType, ApubObject},
|
traits::{ActorType, ApubObject},
|
||||||
values::MediaTypeMarkdown,
|
values::MediaTypeMarkdown,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::community::Community;
|
use lemmy_db_schema::{source::community::Community, traits::ApubActor};
|
||||||
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{convert_datetime, markdown_to_html},
|
utils::{convert_datetime, markdown_to_html},
|
||||||
|
|
|
@ -22,6 +22,7 @@ use lemmy_apub_lib::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::person::{Person as DbPerson, PersonForm},
|
source::person::{Person as DbPerson, PersonForm},
|
||||||
|
traits::ApubActor,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
|
utils::{check_slurs, check_slurs_opt, convert_datetime, markdown_to_html},
|
||||||
|
|
|
@ -13,9 +13,17 @@ use crate::{
|
||||||
CommunityPersonBanForm,
|
CommunityPersonBanForm,
|
||||||
CommunitySafe,
|
CommunitySafe,
|
||||||
},
|
},
|
||||||
traits::{Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable},
|
traits::{ApubActor, Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable},
|
||||||
|
};
|
||||||
|
use diesel::{
|
||||||
|
dsl::*,
|
||||||
|
result::Error,
|
||||||
|
ExpressionMethods,
|
||||||
|
PgConnection,
|
||||||
|
QueryDsl,
|
||||||
|
RunQueryDsl,
|
||||||
|
TextExpressionMethods,
|
||||||
};
|
};
|
||||||
use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
mod safe_type {
|
mod safe_type {
|
||||||
|
@ -92,14 +100,6 @@ impl Crud for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Community {
|
impl Community {
|
||||||
pub fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error> {
|
|
||||||
use crate::schema::community::dsl::*;
|
|
||||||
community
|
|
||||||
.filter(local.eq(true))
|
|
||||||
.filter(lower(name).eq(lower(community_name)))
|
|
||||||
.first::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_deleted(
|
pub fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: CommunityId,
|
community_id: CommunityId,
|
||||||
|
@ -136,17 +136,6 @@ impl Community {
|
||||||
.set(community_form)
|
.set(community_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
|
|
||||||
use crate::schema::community::dsl::*;
|
|
||||||
let object_id: DbUrl = object_id.into();
|
|
||||||
Ok(
|
|
||||||
community
|
|
||||||
.filter(actor_id.eq(object_id))
|
|
||||||
.first::<Community>(conn)
|
|
||||||
.ok()
|
|
||||||
.map(Into::into),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Joinable for CommunityModerator {
|
impl Joinable for CommunityModerator {
|
||||||
|
@ -299,6 +288,40 @@ impl Followable for CommunityFollower {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ApubActor for Community {
|
||||||
|
fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
|
||||||
|
use crate::schema::community::dsl::*;
|
||||||
|
let object_id: DbUrl = object_id.into();
|
||||||
|
Ok(
|
||||||
|
community
|
||||||
|
.filter(actor_id.eq(object_id))
|
||||||
|
.first::<Community>(conn)
|
||||||
|
.ok()
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error> {
|
||||||
|
use crate::schema::community::dsl::*;
|
||||||
|
community
|
||||||
|
.filter(local.eq(true))
|
||||||
|
.filter(lower(name).eq(lower(community_name)))
|
||||||
|
.first::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_from_name_and_domain(
|
||||||
|
conn: &PgConnection,
|
||||||
|
community_name: &str,
|
||||||
|
protocol_domain: &str,
|
||||||
|
) -> Result<Community, Error> {
|
||||||
|
use crate::schema::community::dsl::*;
|
||||||
|
community
|
||||||
|
.filter(lower(name).eq(lower(community_name)))
|
||||||
|
.filter(actor_id.like(format!("{}%", protocol_domain)))
|
||||||
|
.first::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -4,9 +4,17 @@ use crate::{
|
||||||
newtypes::{DbUrl, PersonId},
|
newtypes::{DbUrl, PersonId},
|
||||||
schema::person::dsl::*,
|
schema::person::dsl::*,
|
||||||
source::person::{Person, PersonForm, PersonSafe},
|
source::person::{Person, PersonForm, PersonSafe},
|
||||||
traits::Crud,
|
traits::{ApubActor, Crud},
|
||||||
|
};
|
||||||
|
use diesel::{
|
||||||
|
dsl::*,
|
||||||
|
result::Error,
|
||||||
|
ExpressionMethods,
|
||||||
|
PgConnection,
|
||||||
|
QueryDsl,
|
||||||
|
RunQueryDsl,
|
||||||
|
TextExpressionMethods,
|
||||||
};
|
};
|
||||||
use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
mod safe_type {
|
mod safe_type {
|
||||||
|
@ -202,14 +210,6 @@ impl Person {
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
|
|
||||||
person
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(local.eq(true))
|
|
||||||
.filter(lower(name).eq(lower(from_name)))
|
|
||||||
.first::<Person>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
|
pub fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
|
||||||
diesel::update(person.find(person_id))
|
diesel::update(person.find(person_id))
|
||||||
.set((last_refreshed_at.eq(naive_now()),))
|
.set((last_refreshed_at.eq(naive_now()),))
|
||||||
|
@ -247,19 +247,6 @@ impl Person {
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
|
|
||||||
use crate::schema::person::dsl::*;
|
|
||||||
let object_id: DbUrl = object_id.into();
|
|
||||||
Ok(
|
|
||||||
person
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(actor_id.eq(object_id))
|
|
||||||
.first::<Person>(conn)
|
|
||||||
.ok()
|
|
||||||
.map(Into::into),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_deleted(
|
pub fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
person_id: PersonId,
|
person_id: PersonId,
|
||||||
|
@ -296,6 +283,41 @@ fn is_banned(banned_: bool, expires: Option<chrono::NaiveDateTime>) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ApubActor for Person {
|
||||||
|
fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
|
||||||
|
use crate::schema::person::dsl::*;
|
||||||
|
let object_id: DbUrl = object_id.into();
|
||||||
|
Ok(
|
||||||
|
person
|
||||||
|
.filter(deleted.eq(false))
|
||||||
|
.filter(actor_id.eq(object_id))
|
||||||
|
.first::<Person>(conn)
|
||||||
|
.ok()
|
||||||
|
.map(Into::into),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_from_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
|
||||||
|
person
|
||||||
|
.filter(deleted.eq(false))
|
||||||
|
.filter(local.eq(true))
|
||||||
|
.filter(lower(name).eq(lower(from_name)))
|
||||||
|
.first::<Person>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_from_name_and_domain(
|
||||||
|
conn: &PgConnection,
|
||||||
|
person_name: &str,
|
||||||
|
protocol_domain: &str,
|
||||||
|
) -> Result<Person, Error> {
|
||||||
|
use crate::schema::person::dsl::*;
|
||||||
|
person
|
||||||
|
.filter(lower(name).eq(lower(person_name)))
|
||||||
|
.filter(actor_id.like(format!("{}%", protocol_domain)))
|
||||||
|
.first::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{establish_unpooled_connection, source::person::*, traits::Crud};
|
use crate::{establish_unpooled_connection, source::person::*, traits::Crud};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::newtypes::{CommunityId, PersonId};
|
use crate::newtypes::{CommunityId, PersonId};
|
||||||
use diesel::{result::Error, PgConnection};
|
use diesel::{result::Error, PgConnection};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub trait Crud {
|
pub trait Crud {
|
||||||
type Form;
|
type Form;
|
||||||
|
@ -162,3 +163,20 @@ pub trait ViewToVec {
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ApubActor {
|
||||||
|
// TODO: this should be in a trait ApubObject (and implemented for Post, Comment, PrivateMessage as well)
|
||||||
|
fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn read_from_name(conn: &PgConnection, actor_name: &str) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn read_from_name_and_domain(
|
||||||
|
conn: &PgConnection,
|
||||||
|
actor_name: &str,
|
||||||
|
protocol_domain: &str,
|
||||||
|
) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use lemmy_api_common::blocking;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::LocalUserId,
|
newtypes::LocalUserId,
|
||||||
source::{community::Community, local_user::LocalUser, person::Person},
|
source::{community::Community, local_user::LocalUser, person::Person},
|
||||||
traits::Crud,
|
traits::{ApubActor, Crud},
|
||||||
ListingType,
|
ListingType,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
|
@ -175,7 +175,7 @@ fn get_feed_user(
|
||||||
protocol_and_hostname: &str,
|
protocol_and_hostname: &str,
|
||||||
) -> Result<ChannelBuilder, LemmyError> {
|
) -> Result<ChannelBuilder, LemmyError> {
|
||||||
let site_view = SiteView::read(conn)?;
|
let site_view = SiteView::read(conn)?;
|
||||||
let person = Person::find_by_name(conn, user_name)?;
|
let person = Person::read_from_name(conn, user_name)?;
|
||||||
|
|
||||||
let posts = PostQueryBuilder::create(conn)
|
let posts = PostQueryBuilder::create(conn)
|
||||||
.listing_type(ListingType::All)
|
.listing_type(ListingType::All)
|
||||||
|
|
|
@ -2,7 +2,10 @@ use actix_web::{web, web::Query, HttpResponse};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_common::blocking;
|
use lemmy_api_common::blocking;
|
||||||
use lemmy_apub::fetcher::webfinger::{WebfingerLink, WebfingerResponse};
|
use lemmy_apub::fetcher::webfinger::{WebfingerLink, WebfingerResponse};
|
||||||
use lemmy_db_schema::source::{community::Community, person::Person};
|
use lemmy_db_schema::{
|
||||||
|
source::{community::Community, person::Person},
|
||||||
|
traits::ApubActor,
|
||||||
|
};
|
||||||
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;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -44,7 +47,7 @@ async fn get_webfinger_response(
|
||||||
|
|
||||||
let name_ = name.clone();
|
let name_ = name.clone();
|
||||||
let user_id: Option<Url> = blocking(context.pool(), move |conn| {
|
let user_id: Option<Url> = blocking(context.pool(), move |conn| {
|
||||||
Person::find_by_name(conn, &name_)
|
Person::read_from_name(conn, &name_)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
.ok()
|
.ok()
|
||||||
|
|
Loading…
Reference in a new issue