WIP: Verify permissions in shared inbox

This commit is contained in:
Felix Ableitner 2020-06-17 17:09:57 +02:00
parent cfa40e482a
commit a2e2b762d7
2 changed files with 58 additions and 9 deletions

View file

@ -38,6 +38,7 @@ use crate::{
}, },
db::user_view::UserView, db::user_view::UserView,
}; };
use crate::apub::ActorType;
// Fetch nodeinfo metadata from a remote instance. // Fetch nodeinfo metadata from a remote instance.
fn _fetch_node_info(domain: &str) -> Result<NodeInfo, Error> { fn _fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
@ -245,6 +246,22 @@ pub fn get_or_fetch_and_upsert_remote_community(
} }
} }
pub fn get_or_fetch_and_upsert_remote_actor(
apub_id: &str,
conn: &PgConnection,
) -> Result<Box<dyn ActorType>, Error> {
let user = get_or_fetch_and_upsert_remote_user(apub_id, &conn);
if user.is_ok() {
return Ok(Box::new(user?));
}
let community = get_or_fetch_and_upsert_remote_community(apub_id, &conn);
if community.is_ok() {
return Ok(Box::new(community?));
} else {
todo!() // need proper error handling
}
}
fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result<Post, Error> { fn upsert_post(post_form: &PostForm, conn: &PgConnection) -> Result<Post, Error> {
let existing = Post::read_from_apub_id(conn, &post_form.ap_id); let existing = Post::read_from_apub_id(conn, &post_form.ap_id);
match existing { match existing {

View file

@ -9,7 +9,6 @@ use crate::{
fetcher::{ fetcher::{
get_or_fetch_and_insert_remote_comment, get_or_fetch_and_insert_remote_comment,
get_or_fetch_and_insert_remote_post, get_or_fetch_and_insert_remote_post,
get_or_fetch_and_upsert_remote_community,
get_or_fetch_and_upsert_remote_user, get_or_fetch_and_upsert_remote_user,
}, },
FromApub, FromApub,
@ -47,6 +46,10 @@ use diesel::PgConnection;
use failure::{Error, _core::fmt::Debug}; use failure::{Error, _core::fmt::Debug};
use log::debug; use log::debug;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use http::Uri;
use crate::apub::ActorType;
use crate::apub::fetcher::get_or_fetch_and_upsert_remote_actor;
use activitystreams::primitives::XsdAnyUri;
#[serde(untagged)] #[serde(untagged)]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
@ -127,14 +130,8 @@ pub async fn shared_inbox(
// TODO: this is hacky, we should probably send the community id directly somehow // TODO: this is hacky, we should probably send the community id directly somehow
let to = cc.replace("/followers", ""); let to = cc.replace("/followers", "");
// TODO: this is ugly let actor = get_or_fetch_and_upsert_remote_actor(&sender.to_string(), &conn)?;
match get_or_fetch_and_upsert_remote_user(&sender.to_string(), &conn) { verify(&request, actor.as_ref())?;
Ok(u) => verify(&request, &u),
Err(_) => {
let c = get_or_fetch_and_upsert_remote_community(&sender.to_string(), &conn)?;
verify(&request, &c)
}
}?;
match (activity, object.kind()) { match (activity, object.kind()) {
(SharedAcceptedObjects::Create(c), Some("Page")) => { (SharedAcceptedObjects::Create(c), Some("Page")) => {
@ -142,6 +139,9 @@ pub async fn shared_inbox(
announce_activity_if_valid::<Create>(*c, &to, sender, conn) announce_activity_if_valid::<Create>(*c, &to, sender, conn)
} }
(SharedAcceptedObjects::Update(u), Some("Page")) => { (SharedAcceptedObjects::Update(u), Some("Page")) => {
// TODO: need to get the object::attributed_to here
// (ideally from the database in case we received malicious data)
verify_update_valid(actor, object)?;
receive_update_post(&u, &conn, chat_server)?; receive_update_post(&u, &conn, chat_server)?;
announce_activity_if_valid::<Update>(*u, &to, sender, conn) announce_activity_if_valid::<Update>(*u, &to, sender, conn)
} }
@ -154,10 +154,12 @@ pub async fn shared_inbox(
announce_activity_if_valid::<Dislike>(*d, &to, sender, conn) announce_activity_if_valid::<Dislike>(*d, &to, sender, conn)
} }
(SharedAcceptedObjects::Delete(d), Some("Page")) => { (SharedAcceptedObjects::Delete(d), Some("Page")) => {
//verify_delete_valid()?;
receive_delete_post(&d, &conn, chat_server)?; receive_delete_post(&d, &conn, chat_server)?;
announce_activity_if_valid::<Delete>(*d, &to, sender, conn) announce_activity_if_valid::<Delete>(*d, &to, sender, conn)
} }
(SharedAcceptedObjects::Remove(r), Some("Page")) => { (SharedAcceptedObjects::Remove(r), Some("Page")) => {
//verify_remove_valid()?;
receive_remove_post(&r, &conn, chat_server)?; receive_remove_post(&r, &conn, chat_server)?;
announce_activity_if_valid::<Remove>(*r, &to, sender, conn) announce_activity_if_valid::<Remove>(*r, &to, sender, conn)
} }
@ -166,6 +168,7 @@ pub async fn shared_inbox(
announce_activity_if_valid::<Create>(*c, &to, sender, conn) announce_activity_if_valid::<Create>(*c, &to, sender, conn)
} }
(SharedAcceptedObjects::Update(u), Some("Note")) => { (SharedAcceptedObjects::Update(u), Some("Note")) => {
verify_update_valid(actor, u.object_props.get_id().unwrap())?;
receive_update_comment(&u, &conn, chat_server)?; receive_update_comment(&u, &conn, chat_server)?;
announce_activity_if_valid::<Update>(*u, &to, sender, conn) announce_activity_if_valid::<Update>(*u, &to, sender, conn)
} }
@ -178,26 +181,33 @@ pub async fn shared_inbox(
announce_activity_if_valid::<Dislike>(*d, &to, sender, conn) announce_activity_if_valid::<Dislike>(*d, &to, sender, conn)
} }
(SharedAcceptedObjects::Delete(d), Some("Note")) => { (SharedAcceptedObjects::Delete(d), Some("Note")) => {
//verify_delete_valid()?;
receive_delete_comment(&d, &conn, chat_server)?; receive_delete_comment(&d, &conn, chat_server)?;
announce_activity_if_valid::<Delete>(*d, &to, sender, conn) announce_activity_if_valid::<Delete>(*d, &to, sender, conn)
} }
(SharedAcceptedObjects::Remove(r), Some("Note")) => { (SharedAcceptedObjects::Remove(r), Some("Note")) => {
//verify_remove_valid()?;
receive_remove_comment(&r, &conn, chat_server)?; receive_remove_comment(&r, &conn, chat_server)?;
announce_activity_if_valid::<Remove>(*r, &to, sender, conn) announce_activity_if_valid::<Remove>(*r, &to, sender, conn)
} }
(SharedAcceptedObjects::Delete(d), Some("Group")) => { (SharedAcceptedObjects::Delete(d), Some("Group")) => {
//verify_delete_valid()?;
receive_delete_community(&d, &conn, chat_server)?; receive_delete_community(&d, &conn, chat_server)?;
announce_activity_if_valid::<Delete>(*d, &to, sender, conn) announce_activity_if_valid::<Delete>(*d, &to, sender, conn)
} }
(SharedAcceptedObjects::Remove(r), Some("Group")) => { (SharedAcceptedObjects::Remove(r), Some("Group")) => {
//verify_remove_valid()?;
receive_remove_community(&r, &conn, chat_server)?; receive_remove_community(&r, &conn, chat_server)?;
announce_activity_if_valid::<Remove>(*r, &to, sender, conn) announce_activity_if_valid::<Remove>(*r, &to, sender, conn)
} }
// TODO: for any undo, we should check if the activity to be undone exists
(SharedAcceptedObjects::Undo(u), Some("Delete")) => { (SharedAcceptedObjects::Undo(u), Some("Delete")) => {
//verify_delete_valid()?;
receive_undo_delete(&u, &conn, chat_server)?; receive_undo_delete(&u, &conn, chat_server)?;
announce_activity_if_valid::<Undo>(*u, &to, sender, conn) announce_activity_if_valid::<Undo>(*u, &to, sender, conn)
} }
(SharedAcceptedObjects::Undo(u), Some("Remove")) => { (SharedAcceptedObjects::Undo(u), Some("Remove")) => {
//verify_remove_valid()?;
receive_undo_remove(&u, &conn, chat_server)?; receive_undo_remove(&u, &conn, chat_server)?;
announce_activity_if_valid::<Undo>(*u, &to, sender, conn) announce_activity_if_valid::<Undo>(*u, &to, sender, conn)
} }
@ -221,6 +231,12 @@ where
A: Activity + Base + Serialize + Debug, A: Activity + Base + Serialize + Debug,
{ {
let community = Community::read_from_actor_id(conn, &community_uri)?; let community = Community::read_from_actor_id(conn, &community_uri)?;
// TODO: only allow specific types of activities here:
// - create/like/dislike page/note
// - update only from the same user that created a page/note
// - undo for the activities above
// - delete or undo delete only from the user that created the object
// - remove only for local admins or local mods of the community
if community.local { if community.local {
let sending_user = get_or_fetch_and_upsert_remote_user(&sender.to_string(), &conn)?; let sending_user = get_or_fetch_and_upsert_remote_user(&sender.to_string(), &conn)?;
Community::do_announce(activity, &community, &sending_user, conn) Community::do_announce(activity, &community, &sending_user, conn)
@ -1613,3 +1629,19 @@ fn receive_undo_like_post(
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
fn verify_update_valid(actor_id: Box<dyn ActorType>, object: &BaseBox) -> Result<(), Error> {
todo!()
// can only come from the user that created the object
}
fn verify_delete_valid(actor_id: Box<dyn ActorType>, object_id: Uri) -> Result<(), Error> {
todo!()
// can only come from the user that created the object
}
fn verify_remove_valid(actor_id: Box<dyn ActorType>, object_id: Uri, community: &Community) -> Result<(), Error> {
todo!()
// can only come from admins or mods on the instance of the community
}