mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-10-01 01:36:12 -04:00
Merge 56a8f9fbaf
into f7d881ac78
This commit is contained in:
commit
6d1b767af9
@ -1,5 +1,4 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
activity_lists::GroupInboxActivities,
|
|
||||||
collections::{
|
collections::{
|
||||||
community_featured::ApubCommunityFeatured,
|
community_featured::ApubCommunityFeatured,
|
||||||
community_follower::ApubCommunityFollower,
|
community_follower::ApubCommunityFollower,
|
||||||
@ -7,15 +6,13 @@ use crate::{
|
|||||||
community_outbox::ApubCommunityOutbox,
|
community_outbox::ApubCommunityOutbox,
|
||||||
},
|
},
|
||||||
http::{check_community_public, create_apub_response, create_apub_tombstone_response},
|
http::{check_community_public, create_apub_response, create_apub_tombstone_response},
|
||||||
objects::{community::ApubCommunity, person::ApubPerson},
|
objects::community::ApubCommunity,
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{
|
||||||
actix_web::inbox::receive_activity,
|
|
||||||
config::Data,
|
config::Data,
|
||||||
protocol::context::WithContext,
|
|
||||||
traits::{Collection, Object},
|
traits::{Collection, Object},
|
||||||
};
|
};
|
||||||
use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
|
use actix_web::{web, HttpResponse};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{source::community::Community, traits::ApubActor};
|
use lemmy_db_schema::{source::community::Community, traits::ApubActor};
|
||||||
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
|
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
|
||||||
@ -47,19 +44,6 @@ pub(crate) async fn get_apub_community_http(
|
|||||||
create_apub_response(&apub)
|
create_apub_response(&apub)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handler for all incoming receive to community inboxes.
|
|
||||||
#[tracing::instrument(skip_all)]
|
|
||||||
pub async fn community_inbox(
|
|
||||||
request: HttpRequest,
|
|
||||||
body: Bytes,
|
|
||||||
data: Data<LemmyContext>,
|
|
||||||
) -> LemmyResult<HttpResponse> {
|
|
||||||
receive_activity::<WithContext<GroupInboxActivities>, ApubPerson, LemmyContext>(
|
|
||||||
request, body, &data,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns an empty followers collection, only populating the size (for privacy).
|
/// Returns an empty followers collection, only populating the size (for privacy).
|
||||||
pub(crate) async fn get_apub_community_followers(
|
pub(crate) async fn get_apub_community_followers(
|
||||||
info: web::Path<CommunityQuery>,
|
info: web::Path<CommunityQuery>,
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
activity_lists::PersonInboxActivities,
|
|
||||||
fetcher::user_or_community::UserOrCommunity,
|
|
||||||
http::{create_apub_response, create_apub_tombstone_response},
|
http::{create_apub_response, create_apub_tombstone_response},
|
||||||
objects::person::ApubPerson,
|
objects::person::ApubPerson,
|
||||||
protocol::collections::empty_outbox::EmptyOutbox,
|
protocol::collections::empty_outbox::EmptyOutbox,
|
||||||
};
|
};
|
||||||
use activitypub_federation::{
|
use activitypub_federation::{config::Data, traits::Object};
|
||||||
actix_web::inbox::receive_activity,
|
use actix_web::{web, HttpResponse};
|
||||||
config::Data,
|
|
||||||
protocol::context::WithContext,
|
|
||||||
traits::Object,
|
|
||||||
};
|
|
||||||
use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
|
|
||||||
use lemmy_api_common::{context::LemmyContext, utils::generate_outbox_url};
|
use lemmy_api_common::{context::LemmyContext, utils::generate_outbox_url};
|
||||||
use lemmy_db_schema::{source::person::Person, traits::ApubActor};
|
use lemmy_db_schema::{source::person::Person, traits::ApubActor};
|
||||||
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
|
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
|
||||||
@ -44,18 +37,6 @@ pub(crate) async fn get_apub_person_http(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
|
||||||
pub async fn person_inbox(
|
|
||||||
request: HttpRequest,
|
|
||||||
body: Bytes,
|
|
||||||
data: Data<LemmyContext>,
|
|
||||||
) -> LemmyResult<HttpResponse> {
|
|
||||||
receive_activity::<WithContext<PersonInboxActivities>, UserOrCommunity, LemmyContext>(
|
|
||||||
request, body, &data,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub(crate) async fn get_apub_person_outbox(
|
pub(crate) async fn get_apub_person_outbox(
|
||||||
info: web::Path<PersonQuery>,
|
info: web::Path<PersonQuery>,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use crate::http::{
|
use crate::http::{
|
||||||
comment::get_apub_comment,
|
comment::get_apub_comment,
|
||||||
community::{
|
community::{
|
||||||
community_inbox,
|
|
||||||
get_apub_community_featured,
|
get_apub_community_featured,
|
||||||
get_apub_community_followers,
|
get_apub_community_followers,
|
||||||
get_apub_community_http,
|
get_apub_community_http,
|
||||||
@ -9,7 +8,7 @@ use crate::http::{
|
|||||||
get_apub_community_outbox,
|
get_apub_community_outbox,
|
||||||
},
|
},
|
||||||
get_activity,
|
get_activity,
|
||||||
person::{get_apub_person_http, get_apub_person_outbox, person_inbox},
|
person::{get_apub_person_http, get_apub_person_outbox},
|
||||||
post::get_apub_post,
|
post::get_apub_post,
|
||||||
shared_inbox,
|
shared_inbox,
|
||||||
site::{get_apub_site_http, get_apub_site_outbox},
|
site::{get_apub_site_http, get_apub_site_outbox},
|
||||||
@ -56,8 +55,6 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
|||||||
cfg.service(
|
cfg.service(
|
||||||
web::scope("")
|
web::scope("")
|
||||||
.guard(InboxRequestGuard)
|
.guard(InboxRequestGuard)
|
||||||
.route("/c/{community_name}/inbox", web::post().to(community_inbox))
|
|
||||||
.route("/u/{user_name}/inbox", web::post().to(person_inbox))
|
|
||||||
.route("/inbox", web::post().to(shared_inbox)),
|
.route("/inbox", web::post().to(shared_inbox)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -278,8 +278,7 @@ mod tests {
|
|||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: "pubkey".to_owned(),
|
public_key: "pubkey".to_owned(),
|
||||||
last_refreshed_at: inserted_person.published,
|
last_refreshed_at: inserted_person.published,
|
||||||
inbox_url: inserted_person.inbox_url.clone(),
|
inbox_id: 0,
|
||||||
shared_inbox_url: None,
|
|
||||||
matrix_user_id: None,
|
matrix_user_id: None,
|
||||||
ban_expires: None,
|
ban_expires: None,
|
||||||
instance_id: inserted_instance.id,
|
instance_id: inserted_instance.id,
|
||||||
|
@ -321,6 +321,14 @@ diesel::table! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
inbox (id) {
|
||||||
|
id -> Int4,
|
||||||
|
#[max_length = 255]
|
||||||
|
url -> Varchar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
instance (id) {
|
instance (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
@ -677,14 +685,11 @@ diesel::table! {
|
|||||||
last_refreshed_at -> Timestamptz,
|
last_refreshed_at -> Timestamptz,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Text>,
|
||||||
deleted -> Bool,
|
deleted -> Bool,
|
||||||
#[max_length = 255]
|
|
||||||
inbox_url -> Varchar,
|
|
||||||
#[max_length = 255]
|
|
||||||
shared_inbox_url -> Nullable<Varchar>,
|
|
||||||
matrix_user_id -> Nullable<Text>,
|
matrix_user_id -> Nullable<Text>,
|
||||||
bot_account -> Bool,
|
bot_account -> Bool,
|
||||||
ban_expires -> Nullable<Timestamptz>,
|
ban_expires -> Nullable<Timestamptz>,
|
||||||
instance_id -> Int4,
|
instance_id -> Int4,
|
||||||
|
inbox_id -> Int4,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,6 +1047,7 @@ diesel::joinable!(mod_transfer_community -> community (community_id));
|
|||||||
diesel::joinable!(oauth_account -> local_user (local_user_id));
|
diesel::joinable!(oauth_account -> local_user (local_user_id));
|
||||||
diesel::joinable!(oauth_account -> oauth_provider (oauth_provider_id));
|
diesel::joinable!(oauth_account -> oauth_provider (oauth_provider_id));
|
||||||
diesel::joinable!(password_reset_request -> local_user (local_user_id));
|
diesel::joinable!(password_reset_request -> local_user (local_user_id));
|
||||||
|
diesel::joinable!(person -> inbox (inbox_id));
|
||||||
diesel::joinable!(person -> instance (instance_id));
|
diesel::joinable!(person -> instance (instance_id));
|
||||||
diesel::joinable!(person_aggregates -> person (person_id));
|
diesel::joinable!(person_aggregates -> person (person_id));
|
||||||
diesel::joinable!(person_ban -> person (person_id));
|
diesel::joinable!(person_ban -> person (person_id));
|
||||||
@ -1099,6 +1105,7 @@ diesel::allow_tables_to_appear_in_same_query!(
|
|||||||
federation_blocklist,
|
federation_blocklist,
|
||||||
federation_queue_state,
|
federation_queue_state,
|
||||||
image_details,
|
image_details,
|
||||||
|
inbox,
|
||||||
instance,
|
instance,
|
||||||
instance_block,
|
instance_block,
|
||||||
language,
|
language,
|
||||||
|
@ -3,7 +3,6 @@ use crate::schema::{person, person_follower};
|
|||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{DbUrl, InstanceId, PersonId},
|
newtypes::{DbUrl, InstanceId, PersonId},
|
||||||
sensitive::SensitiveString,
|
sensitive::SensitiveString,
|
||||||
source::placeholder_apub_url,
|
|
||||||
};
|
};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -45,11 +44,6 @@ pub struct Person {
|
|||||||
pub banner: Option<DbUrl>,
|
pub banner: Option<DbUrl>,
|
||||||
/// Whether the person is deleted.
|
/// Whether the person is deleted.
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
#[cfg_attr(feature = "full", ts(skip))]
|
|
||||||
#[serde(skip, default = "placeholder_apub_url")]
|
|
||||||
pub inbox_url: DbUrl,
|
|
||||||
#[serde(skip)]
|
|
||||||
pub shared_inbox_url: Option<DbUrl>,
|
|
||||||
/// A matrix id, usually given an @person:matrix.org
|
/// A matrix id, usually given an @person:matrix.org
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
/// Whether the person is a bot account.
|
/// Whether the person is a bot account.
|
||||||
@ -57,6 +51,9 @@ pub struct Person {
|
|||||||
/// When their ban, if it exists, expires, if at all.
|
/// When their ban, if it exists, expires, if at all.
|
||||||
pub ban_expires: Option<DateTime<Utc>>,
|
pub ban_expires: Option<DateTime<Utc>>,
|
||||||
pub instance_id: InstanceId,
|
pub instance_id: InstanceId,
|
||||||
|
#[cfg_attr(feature = "full", ts(skip))]
|
||||||
|
#[serde(skip, default)]
|
||||||
|
pub inbox_id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, derive_new::new)]
|
#[derive(Clone, derive_new::new)]
|
||||||
@ -91,9 +88,7 @@ pub struct PersonInsertForm {
|
|||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub inbox_url: Option<DbUrl>,
|
pub inbox_id: Option<i32>,
|
||||||
#[new(default)]
|
|
||||||
pub shared_inbox_url: Option<DbUrl>,
|
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub matrix_user_id: Option<String>,
|
pub matrix_user_id: Option<String>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
@ -118,8 +113,7 @@ pub struct PersonUpdateForm {
|
|||||||
pub last_refreshed_at: Option<DateTime<Utc>>,
|
pub last_refreshed_at: Option<DateTime<Utc>>,
|
||||||
pub banner: Option<Option<DbUrl>>,
|
pub banner: Option<Option<DbUrl>>,
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub inbox_url: Option<DbUrl>,
|
pub inbox_id: Option<i32>,
|
||||||
pub shared_inbox_url: Option<Option<DbUrl>>,
|
|
||||||
pub matrix_user_id: Option<Option<String>>,
|
pub matrix_user_id: Option<Option<String>>,
|
||||||
pub bot_account: Option<bool>,
|
pub bot_account: Option<bool>,
|
||||||
pub ban_expires: Option<Option<DateTime<Utc>>>,
|
pub ban_expires: Option<Option<DateTime<Utc>>>,
|
||||||
|
@ -4,13 +4,14 @@ use diesel::{
|
|||||||
dsl::{count_star, not},
|
dsl::{count_star, not},
|
||||||
result::Error,
|
result::Error,
|
||||||
ExpressionMethods,
|
ExpressionMethods,
|
||||||
|
JoinOnDsl,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
};
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
newtypes::{CommunityId, DbUrl, InstanceId, PersonId},
|
||||||
schema::{community, community_follower, person},
|
schema::{community, community_follower, inbox, person},
|
||||||
utils::{functions::coalesce, get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl CommunityFollowerView {
|
impl CommunityFollowerView {
|
||||||
@ -32,15 +33,13 @@ impl CommunityFollowerView {
|
|||||||
community_follower::table
|
community_follower::table
|
||||||
.inner_join(community::table)
|
.inner_join(community::table)
|
||||||
.inner_join(person::table)
|
.inner_join(person::table)
|
||||||
|
.inner_join(inbox::table.on(person::inbox_id.eq(inbox::id)))
|
||||||
.filter(person::instance_id.eq(instance_id))
|
.filter(person::instance_id.eq(instance_id))
|
||||||
.filter(community::local) // this should be a no-op since community_followers table only has
|
.filter(community::local) // this should be a no-op since community_followers table only has
|
||||||
// local-person+remote-community or remote-person+local-community
|
// local-person+remote-community or remote-person+local-community
|
||||||
.filter(not(person::local))
|
.filter(not(person::local))
|
||||||
.filter(community_follower::published.gt(published_since.naive_utc()))
|
.filter(community_follower::published.gt(published_since.naive_utc()))
|
||||||
.select((
|
.select((community::id, inbox::url))
|
||||||
community::id,
|
|
||||||
coalesce(person::shared_inbox_url, person::inbox_url),
|
|
||||||
))
|
|
||||||
.distinct() // only need each community_id, inbox combination once
|
.distinct() // only need each community_id, inbox combination once
|
||||||
.load::<(CommunityId, DbUrl)>(conn)
|
.load::<(CommunityId, DbUrl)>(conn)
|
||||||
.await
|
.await
|
||||||
@ -51,10 +50,11 @@ impl CommunityFollowerView {
|
|||||||
) -> Result<Vec<DbUrl>, Error> {
|
) -> Result<Vec<DbUrl>, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
let res = community_follower::table
|
let res = community_follower::table
|
||||||
|
.inner_join(person::table)
|
||||||
|
.inner_join(inbox::table.on(person::inbox_id.eq(inbox::id)))
|
||||||
.filter(community_follower::community_id.eq(community_id))
|
.filter(community_follower::community_id.eq(community_id))
|
||||||
.filter(not(person::local))
|
.filter(not(person::local))
|
||||||
.inner_join(person::table)
|
.select(inbox::url)
|
||||||
.select(coalesce(person::shared_inbox_url, person::inbox_url))
|
|
||||||
.distinct()
|
.distinct()
|
||||||
.load::<DbUrl>(conn)
|
.load::<DbUrl>(conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
11
migrations/2024-09-24-110638_only-shared-inbox/down.sql
Normal file
11
migrations/2024-09-24-110638_only-shared-inbox/down.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
ALTER TABLE person
|
||||||
|
DROP CONSTRAINT person_inbox_id_fkey;
|
||||||
|
|
||||||
|
ALTER TABLE person
|
||||||
|
DROP COLUMN inbox_url;
|
||||||
|
|
||||||
|
DROP TABLE inbox;
|
||||||
|
|
||||||
|
ALTER TABLE person add COLUMN inbox_url character varying(255) not null default generate_unique_changeme();
|
||||||
|
ALTER TABLE person add COLUMN shared_inbox_url character varying(255) not null default generate_unique_changeme();
|
||||||
|
|
52
migrations/2024-09-24-110638_only-shared-inbox/up.sql
Normal file
52
migrations/2024-09-24-110638_only-shared-inbox/up.sql
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
-- Remove text fields inbox_url, shared_inbox_url from person, community and site.
|
||||||
|
-- Instead use a foreign key for these urls so they can be deduplicated.
|
||||||
|
-- New inbox table
|
||||||
|
-- TODO: add trigger which removes unused inbox items
|
||||||
|
CREATE TABLE inbox (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
url varchar(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Move existing inbox values to inbox table, and replace with foreign key
|
||||||
|
ALTER TABLE person
|
||||||
|
ADD COLUMN inbox_id int;
|
||||||
|
|
||||||
|
WITH inboxes AS (
|
||||||
|
SELECT
|
||||||
|
id AS person_id,
|
||||||
|
coalesce(shared_inbox_url, inbox_url) AS url
|
||||||
|
FROM
|
||||||
|
person
|
||||||
|
),
|
||||||
|
inserted AS (
|
||||||
|
INSERT INTO inbox (url)
|
||||||
|
SELECT
|
||||||
|
url
|
||||||
|
FROM
|
||||||
|
inboxes
|
||||||
|
ON CONFLICT
|
||||||
|
DO NOTHING
|
||||||
|
RETURNING id,
|
||||||
|
url)
|
||||||
|
UPDATE
|
||||||
|
person
|
||||||
|
SET
|
||||||
|
inbox_id = inserted.id
|
||||||
|
FROM
|
||||||
|
inboxes,
|
||||||
|
inserted
|
||||||
|
WHERE
|
||||||
|
person.id = inboxes.person_id
|
||||||
|
AND inserted.url = inboxes.url;
|
||||||
|
|
||||||
|
ALTER TABLE person
|
||||||
|
ADD CONSTRAINT person_inbox_id_fkey FOREIGN KEY (inbox_id) REFERENCES inbox(id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE person
|
||||||
|
ALTER COLUMN inbox_id SET NOT NULL;
|
||||||
|
|
||||||
|
-- Drop old columns and rename new one
|
||||||
|
ALTER TABLE person DROP COLUMN inbox_url;
|
||||||
|
ALTER TABLE person DROP COLUMN shared_inbox_url;
|
||||||
|
|
||||||
|
-- TODO: same thing for community and site
|
Loading…
Reference in New Issue
Block a user