Skip to content

Commit cf52be6

Browse files
committed
Port remaining 12 follow-request lifecycle MultiUserTests
Add reject_follow_request to social.rs; fix accept_follow_request to only persist entry point when reciprocate=true (matching Java). All 12 tests pass; no regressions in existing tests.
1 parent 0d2a6da commit cf52be6

3 files changed

Lines changed: 722 additions & 3 deletions

File tree

crates/peergos-fs/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub use social::{
3939
get_pending_outgoing, get_public_keys, get_shared_with, group_uid, unblock, unfollow,
4040
load_read_access_sharing_links, load_write_access_sharing_links, move_file,
4141
process_follow_reply, read_shared_capabilities, read_write_shared_capabilities, record_link,
42-
remove_link, send_follow_request, share_read_access, share_read_with_group, share_write_access,
42+
reject_follow_request, remove_link, send_follow_request, share_read_access, share_read_with_group, share_write_access,
4343
share_write_with_group, unshare_read_access, unshare_write_access, Access, CapabilitiesFromUser,
4444
CapabilityWithPath, FileSharedWithState, FriendAnnotation, Groups, LinkProperties,
4545
ReceivedFollowRequest, SharedWithState, SocialState, FOLLOWERS_GROUP, FRIENDS_GROUP,

crates/peergos-fs/src/social.rs

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,12 @@ pub async fn accept_follow_request(
652652
}
653653
blind_and_send(&their_identity, &their_boxer, &reply.build(), poster).await?;
654654

655-
// Persist their entry point so we retain read access after this session.
656-
persist_friend_entry_point(user, entry, store.clone(), mutable).await?;
655+
// Persist their entry point only when reciprocating (mutual friendship), so we
656+
// get read access to their shared files — matching Java's `sendReplyFollowRequest`
657+
// which skips `addExternalEntryPoint` when `accept=true, reciprocate=false`.
658+
if reciprocate {
659+
persist_friend_entry_point(user, entry, store.clone(), mutable).await?;
660+
}
657661

658662
// Add them to our followers group, and — if reciprocating (mutual friends) —
659663
// our friends group, matching Java's accept flow. This shares each group's
@@ -669,6 +673,56 @@ pub async fn accept_follow_request(
669673
Ok(())
670674
}
671675

676+
/// `sendReplyFollowRequest` with `accept=false`: send a rejection reply (null
677+
/// entry point) back to the requester. If `reciprocate` is true the requester's
678+
/// read base key is echoed so they become a follower even though we didn't accept
679+
/// their request (Java's `accept=false, reciprocate=true` path).
680+
pub async fn reject_follow_request(
681+
user: &LoggedInUser,
682+
request: &ReceivedFollowRequest,
683+
reciprocate: bool,
684+
poster: &dyn HttpPoster,
685+
store: Arc<dyn ContentAddressedStorage>,
686+
mutable: &dyn MutablePointers,
687+
) -> Result<()> {
688+
let entry = request
689+
.entry
690+
.as_ref()
691+
.ok_or_else(|| Error::Protocol("follow request has no entry point".into()))?;
692+
let their_name = entry.owner_name.clone();
693+
let (their_identity, their_boxer) =
694+
get_public_keys(poster, store.as_ref(), mutable, &their_name).await?;
695+
696+
// Null capability: all-zero identity, map_key, and r_base_key.
697+
let null_hash = PublicKeyHash::identity(vec![0u8; 32])?;
698+
let null_key = SymmetricKey::new(vec![0u8; 32], false)?;
699+
let null_cap = AbsoluteCapability {
700+
owner: null_hash,
701+
writer: PublicKeyHash::identity(vec![0u8; 32])?,
702+
map_key: vec![0u8; 32],
703+
bat: None,
704+
r_base_key: null_key,
705+
w_base_key: None,
706+
};
707+
let null_entry = EntryPoint { pointer: null_cap.clone(), owner_name: user.username.clone() };
708+
709+
let mut reply = CborObject::map().put("e", null_entry.to_cbor());
710+
if reciprocate {
711+
reply = reply.put("k", entry.pointer.r_base_key.to_cbor());
712+
}
713+
blind_and_send(&their_identity, &their_boxer, &reply.build(), poster).await?;
714+
715+
// If reciprocating, persist the requester's entry point so we can see their
716+
// shared files (Java's `addExternalEntryPoint` + `retrieveAndAddEntryPointToTrie`).
717+
if reciprocate {
718+
persist_friend_entry_point(user, entry, store.clone(), mutable).await?;
719+
add_member_to_group(user, FOLLOWERS_GROUP, &their_name, store.clone(), mutable).await?;
720+
}
721+
722+
remove_follow_request(user, &request.raw_cipher, poster).await?;
723+
Ok(())
724+
}
725+
672726
/// Process a reply to one of our outgoing follow requests: persist the sender's
673727
/// entry point and remove the request. (The reply needs no further response.)
674728
pub async fn process_follow_reply(

0 commit comments

Comments
 (0)