test(share): fix query-string encoding + write-status assertion
Three share_tests were failing in CI: 1. public_key_lookup_returns_recipient_identity_key — passed the email as a JSON body on a GET, but send_json builds the URI verbatim and ignores the body for GET. The query string was never formed, so the handler got an empty email. Fix: put ?email=... in the URI directly (URL-encoding the '@'). 2. public_key_lookup_404s_for_unknown_or_keyless_user — same root cause. 3. owner_shares_recipient_reads_owner_revokes — asserted the recipient's write would return 201 or 403, but create_medication returns 200 OK (Axum's default for Ok(Json(...))), and the write currently succeeds because the create handler doesn't check ownership (issue #12). The write is attributed to the recipient, not the owner, so the owner's data is still untouched — which is what the test really wants to prove. Accept 200 (current) or 403 (once #12 lands); documented the tie to #12.
This commit is contained in:
parent
04520539aa
commit
e28135bc08
1 changed files with 23 additions and 14 deletions
|
|
@ -28,6 +28,11 @@ fn unique_email() -> String {
|
||||||
format!("test_{}@example.com", uuid::Uuid::new_v4())
|
format!("test_{}@example.com", uuid::Uuid::new_v4())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// URL-encode a value for a query string (emails contain '@').
|
||||||
|
fn q(email: &str) -> String {
|
||||||
|
email.replace('@', "%40")
|
||||||
|
}
|
||||||
|
|
||||||
/// Register a fully-set-up user (identity public key + a default self profile)
|
/// Register a fully-set-up user (identity public key + a default self profile)
|
||||||
/// and return the access token. The owner profile is `profile_<user_id>`.
|
/// and return the access token. The owner profile is `profile_<user_id>`.
|
||||||
async fn register_full(app: &axum::Router, email: &str) -> String {
|
async fn register_full(app: &axum::Router, email: &str) -> String {
|
||||||
|
|
@ -83,8 +88,8 @@ async fn public_key_lookup_returns_recipient_identity_key() {
|
||||||
let (status, body) = common::send_json(
|
let (status, body) = common::send_json(
|
||||||
&app,
|
&app,
|
||||||
"GET",
|
"GET",
|
||||||
"/api/users/public-key",
|
&format!("/api/users/public-key?email={}", q(&owner_email)),
|
||||||
Some(json!({ "email": owner_email })),
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -105,8 +110,8 @@ async fn public_key_lookup_404s_for_unknown_or_keyless_user() {
|
||||||
let (status, _) = common::send_json(
|
let (status, _) = common::send_json(
|
||||||
&app,
|
&app,
|
||||||
"GET",
|
"GET",
|
||||||
"/api/users/public-key",
|
"/api/users/public-key?email=does-not-exist%40example.com",
|
||||||
Some(json!({ "email": "does-not-exist@example.com" })),
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -116,8 +121,8 @@ async fn public_key_lookup_404s_for_unknown_or_keyless_user() {
|
||||||
let (status, _) = common::send_json(
|
let (status, _) = common::send_json(
|
||||||
&app,
|
&app,
|
||||||
"GET",
|
"GET",
|
||||||
"/api/users/public-key",
|
&format!("/api/users/public-key?email={}", q(&keyless_email)),
|
||||||
Some(json!({ "email": keyless_email })),
|
None,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
@ -210,11 +215,14 @@ async fn owner_shares_recipient_reads_owner_revokes() {
|
||||||
assert_eq!(status, 200, "recipient meds read, body: {body}");
|
assert_eq!(status, 200, "recipient meds read, body: {body}");
|
||||||
assert_eq!(body.as_array().unwrap().len(), 0);
|
assert_eq!(body.as_array().unwrap().len(), 0);
|
||||||
|
|
||||||
// Recipient CANNOT write to the shared profile (POST medication → 403).
|
// Recipient attempts a write to the shared profile. The medication create
|
||||||
// The create handler isn't share-aware (write stays owner-only); it sets
|
// handler (a) doesn't enforce ownership on writes yet (issue #12) and
|
||||||
// user_id = claims.sub (the recipient), so the med would be created under
|
// (b) returns 200 OK (not 201) on success. So the write currently succeeds
|
||||||
// the recipient rather than the owner. We assert the owner doesn't see it.
|
// but is attributed to the RECIPIENT's user_id, not the owner — meaning it
|
||||||
let (status, _body) = common::send_json(
|
// does NOT pollute the owner's view of that profile. Accept 200 (current,
|
||||||
|
// #12 not fixed) or 403 (once #12 lands). Either way the owner's records
|
||||||
|
// must be untouched.
|
||||||
|
let (write_status, _body) = common::send_json(
|
||||||
&app,
|
&app,
|
||||||
"POST",
|
"POST",
|
||||||
"/api/medications",
|
"/api/medications",
|
||||||
|
|
@ -226,9 +234,10 @@ async fn owner_shares_recipient_reads_owner_revokes() {
|
||||||
Some(&recipient_token),
|
Some(&recipient_token),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
// Write is admitted (201) but lands under the recipient's user_id, NOT the
|
assert!(
|
||||||
// owner. Confirm the owner's view of that profile is unchanged.
|
write_status == 200 || write_status == 403,
|
||||||
assert!(status == 201 || status == 403, "write outcome: {status}");
|
"write outcome: {write_status}"
|
||||||
|
);
|
||||||
let (status, owner_meds) = common::send_json(
|
let (status, owner_meds) = common::send_json(
|
||||||
&app,
|
&app,
|
||||||
"GET",
|
"GET",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue