feat(server): grant-scope org attachment write paths in pre-receive hook
This commit is contained in:
@@ -79,3 +79,43 @@ fn extract_schema_version_errors_on_missing_field() {
|
||||
fn extract_schema_version_errors_on_garbage() {
|
||||
assert!(extract_schema_version("not json").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_path_is_collection_scoped() {
|
||||
assert_eq!(
|
||||
classify_path("attachments/prod/a1b2c3d4e5f6a1b2/0011223344556677.enc"),
|
||||
PathClass::Item { collection: "prod".to_string() }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_wrong_segment_count_is_rejected() {
|
||||
assert_eq!(
|
||||
classify_path("attachments/prod/onlytwo.enc"),
|
||||
PathClass::Rejected("attachments path must be attachments/<slug>/<item-id>/<att-id>.enc".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_empty_or_dotted_slug_is_rejected() {
|
||||
assert!(matches!(classify_path("attachments//item/att.enc"), PathClass::Rejected(_)));
|
||||
assert!(matches!(classify_path("attachments/../item/att.enc"), PathClass::Rejected(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachments_prefix_alone_is_rejected_not_unrestricted() {
|
||||
// `attachments/` with no slug/item/att segments must be Rejected, NOT fall
|
||||
// through to Unrestricted — that fall-through was the authz gap this closes.
|
||||
assert!(matches!(classify_path("attachments/"), PathClass::Rejected(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_att_id_segment_may_contain_dots() {
|
||||
// The `.`-free guard applies to the slug (segment[0]) ONLY; the att-id segment
|
||||
// legitimately carries `.enc` and is unharmed by additional dots — proving the
|
||||
// guard is not a blanket "reject any dotted segment".
|
||||
assert_eq!(
|
||||
classify_path("attachments/eng/a1b2c3d4e5f6a1b2/00112233.aux.enc"),
|
||||
PathClass::Item { collection: "eng".to_string() }
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user