mirror of
https://tangled.org/tranquil.farm/tranquil-pds
synced 2026-02-08 21:30:08 +00:00
444 lines
13 KiB
Rust
444 lines
13 KiB
Rust
mod common;
|
|
mod helpers;
|
|
|
|
use common::*;
|
|
use helpers::*;
|
|
use reqwest::StatusCode;
|
|
use serde_json::Value;
|
|
|
|
#[tokio::test]
|
|
async fn test_get_repo_takendown_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepo",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_repo_deactivated_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_deactivated(&did, true).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepo",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoDeactivated");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_latest_commit_takendown_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getLatestCommit",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_blocks_takendown_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
let commit_res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getLatestCommit",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to get commit");
|
|
let commit_body: Value = commit_res.json().await.unwrap();
|
|
let cid = commit_body["cid"].as_str().unwrap();
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getBlocks",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str()), ("cids", cid)])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_repo_status_shows_takendown_status() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepoStatus",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["active"], false);
|
|
assert_eq!(body["status"], "takendown");
|
|
assert!(body.get("rev").is_none() || body["rev"].is_null());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_repo_status_shows_deactivated_status() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_deactivated(&did, true).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepoStatus",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["active"], false);
|
|
assert_eq!(body["status"], "deactivated");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_list_repos_shows_status_field() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.listRepos?limit=1000",
|
|
base_url().await
|
|
))
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
let repos = body["repos"].as_array().unwrap();
|
|
|
|
let takendown_repo = repos.iter().find(|r| r["did"] == did);
|
|
assert!(takendown_repo.is_some(), "Takendown repo should be in list");
|
|
let repo = takendown_repo.unwrap();
|
|
assert_eq!(repo["active"], false);
|
|
assert_eq!(repo["status"], "takendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_blob_takendown_returns_error() {
|
|
let client = client();
|
|
let (jwt, did) = create_account_and_login(&client).await;
|
|
|
|
let blob_res = client
|
|
.post(format!(
|
|
"{}/xrpc/com.atproto.repo.uploadBlob",
|
|
base_url().await
|
|
))
|
|
.header("Content-Type", "image/png")
|
|
.bearer_auth(&jwt)
|
|
.body(vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
|
|
.send()
|
|
.await
|
|
.expect("Failed to upload blob");
|
|
let blob_body: Value = blob_res.json().await.unwrap();
|
|
let cid = blob_body["blob"]["ref"]["$link"].as_str().unwrap();
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getBlob",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str()), ("cid", cid)])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_blob_has_security_headers() {
|
|
let client = client();
|
|
let (jwt, did) = create_account_and_login(&client).await;
|
|
|
|
let blob_res = client
|
|
.post(format!(
|
|
"{}/xrpc/com.atproto.repo.uploadBlob",
|
|
base_url().await
|
|
))
|
|
.header("Content-Type", "image/png")
|
|
.bearer_auth(&jwt)
|
|
.body(vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
|
|
.send()
|
|
.await
|
|
.expect("Failed to upload blob");
|
|
let blob_body: Value = blob_res.json().await.unwrap();
|
|
let cid = blob_body["blob"]["ref"]["$link"].as_str().unwrap();
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getBlob",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str()), ("cid", cid)])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
|
|
let headers = res.headers();
|
|
assert_eq!(
|
|
headers
|
|
.get("x-content-type-options")
|
|
.map(|v| v.to_str().unwrap()),
|
|
Some("nosniff"),
|
|
"Missing x-content-type-options: nosniff header"
|
|
);
|
|
assert_eq!(
|
|
headers
|
|
.get("content-security-policy")
|
|
.map(|v| v.to_str().unwrap()),
|
|
Some("default-src 'none'; sandbox"),
|
|
"Missing content-security-policy header"
|
|
);
|
|
assert!(
|
|
headers.get("content-length").is_some(),
|
|
"Missing content-length header"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_blocks_missing_cids_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
let fake_cid = "bafyreif2pall7dybz7vecqka3zo24irdwabwdi4wc55jznaq75q7eaavvu";
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getBlocks",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str()), ("cids", fake_cid)])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "InvalidRequest");
|
|
assert!(
|
|
body["message"]
|
|
.as_str()
|
|
.unwrap()
|
|
.contains("Could not find blocks"),
|
|
"Error message should mention missing blocks"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_blocks_accepts_array_format() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
let commit_res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getLatestCommit",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to get commit");
|
|
let commit_body: Value = commit_res.json().await.unwrap();
|
|
let cid = commit_body["cid"].as_str().unwrap();
|
|
|
|
let url = format!(
|
|
"{}/xrpc/com.atproto.sync.getBlocks?did={}&cids={}&cids={}",
|
|
base_url().await,
|
|
did,
|
|
cid,
|
|
cid
|
|
);
|
|
let res = client
|
|
.get(&url)
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::OK);
|
|
let content_type = res.headers().get("content-type").unwrap().to_str().unwrap();
|
|
assert!(
|
|
content_type.contains("application/vnd.ipld.car"),
|
|
"Response should be a CAR file"
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_repo_since_returns_partial() {
|
|
let client = client();
|
|
let (jwt, did) = create_account_and_login(&client).await;
|
|
|
|
let initial_commit_res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getLatestCommit",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to get initial commit");
|
|
let initial_body: Value = initial_commit_res.json().await.unwrap();
|
|
let initial_rev = initial_body["rev"].as_str().unwrap();
|
|
|
|
let full_repo_res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepo",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to get full repo");
|
|
assert_eq!(full_repo_res.status(), StatusCode::OK);
|
|
let full_repo_bytes = full_repo_res.bytes().await.unwrap();
|
|
let full_repo_size = full_repo_bytes.len();
|
|
|
|
create_post(&client, &did, &jwt, "Test post for since param").await;
|
|
|
|
let partial_repo_res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRepo",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str()), ("since", initial_rev)])
|
|
.send()
|
|
.await
|
|
.expect("Failed to get partial repo");
|
|
assert_eq!(partial_repo_res.status(), StatusCode::OK);
|
|
let partial_repo_bytes = partial_repo_res.bytes().await.unwrap();
|
|
let partial_repo_size = partial_repo_bytes.len();
|
|
|
|
assert!(
|
|
partial_repo_size < full_repo_size,
|
|
"Partial export (since={}) should be smaller than full export: {} vs {}",
|
|
initial_rev,
|
|
partial_repo_size,
|
|
full_repo_size
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_list_blobs_takendown_returns_error() {
|
|
let client = client();
|
|
let (_, did) = create_account_and_login(&client).await;
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.listBlobs",
|
|
base_url().await
|
|
))
|
|
.query(&[("did", did.as_str())])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_get_record_takendown_returns_error() {
|
|
let client = client();
|
|
let (jwt, did) = create_account_and_login(&client).await;
|
|
|
|
let (uri, _cid) = create_post(&client, &did, &jwt, "Test post").await;
|
|
let parts: Vec<&str> = uri.split('/').collect();
|
|
let collection = parts[parts.len() - 2];
|
|
let rkey = parts[parts.len() - 1];
|
|
|
|
set_account_takedown(&did, Some("test-takedown-ref")).await;
|
|
|
|
let res = client
|
|
.get(format!(
|
|
"{}/xrpc/com.atproto.sync.getRecord",
|
|
base_url().await
|
|
))
|
|
.query(&[
|
|
("did", did.as_str()),
|
|
("collection", collection),
|
|
("rkey", rkey),
|
|
])
|
|
.send()
|
|
.await
|
|
.expect("Failed to send request");
|
|
|
|
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
|
let body: Value = res.json().await.expect("Response was not valid JSON");
|
|
assert_eq!(body["error"], "RepoTakendown");
|
|
}
|