max / makenotwork
1 file changed,
+22 insertions,
-42 deletions
| @@ -7,7 +7,6 @@ | |||
| 7 | 7 | ||
| 8 | 8 | use crate::harness::{BuildOptions, TestHarness, stripe, storage::InMemoryStorage, client::TestResponse}; | |
| 9 | 9 | use makenotwork::db::{SyncAppId, UserId}; | |
| 10 | - | use serde::Deserialize; | |
| 11 | 10 | use serde_json::json; | |
| 12 | 11 | use sqlx::PgPool; | |
| 13 | 12 | use std::sync::Arc; | |
| @@ -109,38 +108,19 @@ async fn claim_key(h: &mut TestHarness, api_key: &str, key: &str) { | |||
| 109 | 108 | assert_eq!(resp.status, 200, "claim_key {} failed: {}", key, resp.text); | |
| 110 | 109 | } | |
| 111 | 110 | ||
| 112 | - | /// Run `/api/sync/auth` with the given key, set the bearer token on the | |
| 113 | - | /// client, and return the resolved (user_id, app_id) pair. | |
| 114 | - | async fn auth_as( | |
| 115 | - | h: &mut TestHarness, | |
| 116 | - | email: &str, | |
| 117 | - | password: &str, | |
| 118 | - | api_key: &str, | |
| 119 | - | key: &str, | |
| 120 | - | ) -> (UserId, SyncAppId) { | |
| 121 | - | #[derive(Deserialize)] | |
| 122 | - | struct AuthResp { | |
| 123 | - | token: String, | |
| 124 | - | user_id: UserId, | |
| 125 | - | app_id: SyncAppId, | |
| 126 | - | } | |
| 127 | - | let resp = h | |
| 128 | - | .client | |
| 129 | - | .post_json( | |
| 130 | - | "/api/sync/auth", | |
| 131 | - | &json!({ | |
| 132 | - | "email": email, | |
| 133 | - | "password": password, | |
| 134 | - | "api_key": api_key, | |
| 135 | - | "key": key, | |
| 136 | - | }) | |
| 137 | - | .to_string(), | |
| 138 | - | ) | |
| 139 | - | .await; | |
| 140 | - | assert_eq!(resp.status, 200, "/api/sync/auth (key={}) failed: {}", key, resp.text); | |
| 141 | - | let body: AuthResp = resp.json(); | |
| 142 | - | h.client.set_bearer_token(&body.token); | |
| 143 | - | (body.user_id, body.app_id) | |
| 111 | + | /// Mint a SyncKit JWT directly via `create_sync_token` and set it as the | |
| 112 | + | /// bearer token. Bypasses `/api/sync/auth` so the test doesn't blow the | |
| 113 | + | /// `SYNCKIT_AUTH_RATE_LIMIT_PER_SEC` budget when switching keys repeatedly — | |
| 114 | + | /// the rate limiter is real-environment-correct but punishes burst-y tests. | |
| 115 | + | fn auth_as(h: &mut TestHarness, user_id: UserId, app_id: SyncAppId, key: &str) { | |
| 116 | + | let token = makenotwork::synckit_auth::create_sync_token( | |
| 117 | + | "test-synckit-jwt-secret", | |
| 118 | + | user_id, | |
| 119 | + | app_id, | |
| 120 | + | key, | |
| 121 | + | ) | |
| 122 | + | .expect("mint test JWT"); | |
| 123 | + | h.client.set_bearer_token(&token); | |
| 144 | 124 | } | |
| 145 | 125 | ||
| 146 | 126 | /// 64-lowercase-hex hash for a given seed byte. | |
| @@ -217,8 +197,8 @@ async fn per_key_full_blocks_only_that_key_other_keys_keep_uploading() { | |||
| 217 | 197 | .unwrap(); | |
| 218 | 198 | ||
| 219 | 199 | // Key A: any additional byte must trip the per-key cap. | |
| 220 | - | let (uid_a, _) = auth_as(&mut h, "perkey1@example.com", "Password1!", &api_key, "A").await; | |
| 221 | - | let resp = upload_and_confirm(&mut h, &blobs, app_id, uid_a, &fake_hash(0xaa), 1).await; | |
| 200 | + | auth_as(&mut h, user_id, app_id, "A"); | |
| 201 | + | let resp = upload_and_confirm(&mut h, &blobs, app_id, user_id, &fake_hash(0xaa), 1).await; | |
| 222 | 202 | assert_eq!(resp.status, 402, "expected 402 on key A: {}", resp.text); | |
| 223 | 203 | let body: serde_json::Value = serde_json::from_str(&resp.text).expect("json body"); | |
| 224 | 204 | assert_eq!(body["reason"], "storage_limit_reached"); | |
| @@ -227,13 +207,13 @@ async fn per_key_full_blocks_only_that_key_other_keys_keep_uploading() { | |||
| 227 | 207 | assert_eq!(body["limit"], GIB); | |
| 228 | 208 | ||
| 229 | 209 | // Key B: same app, sibling key — must succeed. | |
| 230 | - | let (uid_b, _) = auth_as(&mut h, "perkey1@example.com", "Password1!", &api_key, "B").await; | |
| 231 | - | let resp = upload_and_confirm(&mut h, &blobs, app_id, uid_b, &fake_hash(0xbb), 1_000).await; | |
| 210 | + | auth_as(&mut h, user_id, app_id, "B"); | |
| 211 | + | let resp = upload_and_confirm(&mut h, &blobs, app_id, user_id, &fake_hash(0xbb), 1_000).await; | |
| 232 | 212 | assert_eq!(resp.status, 204, "key B confirm should succeed: {}", resp.text); | |
| 233 | 213 | ||
| 234 | 214 | // Key C: also fine. | |
| 235 | - | let (uid_c, _) = auth_as(&mut h, "perkey1@example.com", "Password1!", &api_key, "C").await; | |
| 236 | - | let resp = upload_and_confirm(&mut h, &blobs, app_id, uid_c, &fake_hash(0xcc), 2_000).await; | |
| 215 | + | auth_as(&mut h, user_id, app_id, "C"); | |
| 216 | + | let resp = upload_and_confirm(&mut h, &blobs, app_id, user_id, &fake_hash(0xcc), 2_000).await; | |
| 237 | 217 | assert_eq!(resp.status, 204, "key C confirm should succeed: {}", resp.text); | |
| 238 | 218 | ||
| 239 | 219 | // Per-key counters should reflect B's and C's adds; A's is unchanged. | |
| @@ -269,13 +249,13 @@ async fn per_key_full_blocks_only_that_key_other_keys_keep_uploading() { | |||
| 269 | 249 | async fn bulk_mode_returns_storage_dimension_without_key() { | |
| 270 | 250 | let (mut h, blobs) = harness_with_billing_and_blobs().await; | |
| 271 | 251 | let user_id = h.signup("bulk1", "bulk1@example.com", "Password1!").await; | |
| 272 | - | let (app_id, api_key) = create_draft_app(&h.db, user_id).await; | |
| 252 | + | let (app_id, _api_key) = create_draft_app(&h.db, user_id).await; | |
| 273 | 253 | ||
| 274 | 254 | activate_bulk(&mut h, app_id, 1).await; // 1 GiB app-wide | |
| 275 | 255 | ||
| 276 | 256 | // Bulk mode never calls claim_key but the JWT still requires *some* key | |
| 277 | 257 | // string; pick any opaque value (developer's choice). | |
| 278 | - | let (uid, _) = auth_as(&mut h, "bulk1@example.com", "Password1!", &api_key, "single").await; | |
| 258 | + | auth_as(&mut h, user_id, app_id, "single"); | |
| 279 | 259 | ||
| 280 | 260 | // Pre-fill the app counter to cap. | |
| 281 | 261 | sqlx::query("UPDATE sync_app_usage_current SET bytes_stored = $2 WHERE app_id = $1") | |
| @@ -285,7 +265,7 @@ async fn bulk_mode_returns_storage_dimension_without_key() { | |||
| 285 | 265 | .await | |
| 286 | 266 | .unwrap(); | |
| 287 | 267 | ||
| 288 | - | let resp = upload_and_confirm(&mut h, &blobs, app_id, uid, &fake_hash(0x11), 1).await; | |
| 268 | + | let resp = upload_and_confirm(&mut h, &blobs, app_id, user_id, &fake_hash(0x11), 1).await; | |
| 289 | 269 | assert_eq!(resp.status, 402, "expected 402 on bulk cap: {}", resp.text); | |
| 290 | 270 | let body: serde_json::Value = serde_json::from_str(&resp.text).expect("json"); | |
| 291 | 271 | assert_eq!(body["reason"], "storage_limit_reached"); |