fix: test & lint

This commit is contained in:
DarkSky
2026-06-22 03:39:34 +08:00
parent 778d34ca7c
commit be9f4708ba
4 changed files with 75 additions and 13 deletions
+1 -1
View File
@@ -29,7 +29,7 @@
"test": "node --test ./__tests__/**/*.spec.js",
"bench": "node ./benchmark/index.js",
"build": "napi build --release --strip --no-const-enum",
"build:debug": "napi build"
"build:debug": "napi build --no-const-enum"
},
"devDependencies": {
"@napi-rs/cli": "3.5.0",
@@ -3,7 +3,7 @@ use std::{
path::{Path, PathBuf},
};
use base64::{Engine as _, engine::general_purpose::URL_SAFE};
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use napi::Result;
use serde::Deserialize;
use sha2::{Digest, Sha256};
@@ -41,8 +41,16 @@ fn blob_complete_success(
}
}
fn sha256_base64_url_with_padding(body: &[u8]) -> String {
URL_SAFE.encode(Sha256::digest(body))
fn normalize_base64_url_key(key: &str) -> &str {
key.trim_end_matches('=')
}
fn sha256_base64_url(body: &[u8]) -> String {
URL_SAFE_NO_PAD.encode(Sha256::digest(body))
}
fn sha256_base64_url_matches(body: &[u8], key: &str) -> bool {
sha256_base64_url(body) == normalize_base64_url_key(key)
}
#[derive(Deserialize)]
@@ -178,7 +186,7 @@ impl BackendRuntime {
return Ok(blob_complete_failure("mime_mismatch"));
}
if sha256_base64_url_with_padding(&object.body) != key {
if !sha256_base64_url_matches(&object.body, &key) {
match self.object_storage_delete(object_key).await {
Ok(()) => {}
Err(err) if object_missing_error(&err) => {}
@@ -243,7 +251,7 @@ impl BackendRuntime {
Err(err) => return Err(napi_error(format!("BlobComplete read fs object failed: {err}"))),
};
if sha256_base64_url_with_padding(&body) != key {
if !sha256_base64_url_matches(&body, &key) {
let _ = fs::remove_file(&path);
let _ = fs::remove_file(PathBuf::from(format!("{}.metadata.json", path.display())));
return Ok(blob_complete_failure("checksum_mismatch"));
@@ -268,13 +276,21 @@ impl BackendRuntime {
#[cfg(test)]
mod tests {
use super::sha256_base64_url_with_padding;
use super::{sha256_base64_url, sha256_base64_url_matches};
#[test]
fn sha256_base64_url_keeps_padding() {
fn sha256_base64_url_omits_padding() {
assert_eq!(
sha256_base64_url_with_padding(b"hello"),
"LPJNul-wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
sha256_base64_url(b"hello"),
"LPJNul-wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ"
);
}
#[test]
fn sha256_base64_url_matches_legacy_padding() {
assert!(sha256_base64_url_matches(
b"hello",
"LPJNul-wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
));
}
}
@@ -321,6 +321,38 @@ impl RuntimeStateRows {
Ok(row.get::<i64, _>("expires_at_ms"))
}
pub(super) async fn upsert_expired_or_consumed_payload_returning_expires_in_tx(
&self,
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
input: RuntimeStateInsertPayload<'_>,
) -> Result<Option<i64>> {
let row = sqlx::query(
r#"
INSERT INTO runtime_states (purpose, token_hash, lookup_key, payload, expires_at)
VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP + ($5 * INTERVAL '1 millisecond'))
ON CONFLICT (purpose, token_hash) DO UPDATE
SET lookup_key = EXCLUDED.lookup_key,
payload = EXCLUDED.payload,
attempts = 0,
consumed_at = NULL,
expires_at = EXCLUDED.expires_at
WHERE runtime_states.consumed_at IS NOT NULL
OR runtime_states.expires_at <= CURRENT_TIMESTAMP
RETURNING (EXTRACT(EPOCH FROM expires_at) * 1000)::BIGINT AS expires_at_ms
"#,
)
.bind(input.purpose)
.bind(token_hash(input.token))
.bind(input.lookup_key)
.bind(input.payload)
.bind(input.ttl_ms as f64)
.fetch_optional(&mut **tx)
.await
.map_err(|err| napi_error(format!("{} failed: {err}", input.context)))?;
Ok(row.map(|row| row.get::<i64, _>("expires_at_ms")))
}
pub(super) async fn update_attempts_in_tx(
&self,
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
@@ -33,6 +33,11 @@ pub(super) async fn create(
}
let mut tx = rows.begin("RuntimeState workspace invite link").await?;
sqlx::query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))")
.bind(&workspace_id)
.execute(&mut *tx)
.await
.map_err(|err| napi_error(format!("RuntimeState workspace invite link active lock failed: {err}")))?;
if let Some(existing) =
get_by_key_in_tx(rows, &mut tx, WORKSPACE_INVITE_LINK_WORKSPACE_PURPOSE, &workspace_id).await?
@@ -51,8 +56,8 @@ pub(super) async fn create(
"inviterUserId": inviter_user_id,
});
let expires_at_ms = rows
.insert_payload_returning_expires_in_tx(
let Some(expires_at_ms) = rows
.upsert_expired_or_consumed_payload_returning_expires_in_tx(
&mut tx,
RuntimeStateInsertPayload {
purpose: WORKSPACE_INVITE_LINK_WORKSPACE_PURPOSE,
@@ -63,7 +68,16 @@ pub(super) async fn create(
context: "RuntimeState workspace invite link create",
},
)
.await?;
.await?
else {
let existing = get_by_key_in_tx(rows, &mut tx, WORKSPACE_INVITE_LINK_WORKSPACE_PURPOSE, &workspace_id).await?;
tx.commit().await.map_err(|err| {
napi_error(format!(
"RuntimeState workspace invite link transaction commit failed: {err}"
))
})?;
return existing.ok_or_else(|| napi_error("RuntimeState workspace invite link active conflict missing row"));
};
rows
.insert_payload_returning_expires_in_tx(
&mut tx,