Skip to content

Commit 302ad03

Browse files
committed
add getBucketPolicyStatus
1 parent 8842e10 commit 302ad03

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

src/client.ts

+46-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import type {
33
CreateBucketOptions,
44
DeleteBucketPolicyOptions,
55
GetBucketPolicyOptions,
6+
GetBucketPolicyStatusOptions,
67
ListBucketsResponses,
78
Policy,
9+
PolicyStatus,
810
PutBucketPolicyOptions,
911
Statement,
1012
} from "./types.ts";
@@ -231,8 +233,42 @@ export class S3 {
231233
await resp.arrayBuffer();
232234
}
233235

234-
#parseListBucketsResponseXml(x: string): ListBucketsResponses {
235-
const doc: Document = parseXML(x);
236+
async getBucketPolicyStatus(
237+
bucket: string,
238+
options?: GetBucketPolicyStatusOptions,
239+
): Promise<PolicyStatus> {
240+
const headers: Params = {};
241+
const params: Params = {};
242+
243+
if (options?.expectedBucketOwner) {
244+
headers["x-amz-expected-bucket-owner"] = options.expectedBucketOwner;
245+
}
246+
247+
params["policyStatus"] = "true";
248+
249+
const resp = await doRequest({
250+
host: this.#host,
251+
signer: this.#signer,
252+
path: bucket,
253+
method: "GET",
254+
headers,
255+
params,
256+
});
257+
258+
if (resp.status !== 200) {
259+
throw new S3Error(
260+
`Failed to get policy status for bucket "${bucket}": ${resp.status} ${resp.statusText}`,
261+
await resp.text(),
262+
);
263+
}
264+
265+
return this.#parseGetBucketPolicyStatusResult(
266+
await resp.text(),
267+
);
268+
}
269+
270+
#parseListBucketsResponseXml(xml: string): ListBucketsResponses {
271+
const doc: Document = parseXML(xml);
236272
const root = extractRoot(doc, "ListAllMyBucketsResult");
237273
const buckets = extractField(root, "Buckets")!;
238274
const owner = extractField(root, "Owner")!;
@@ -281,4 +317,12 @@ export class S3 {
281317
return mapped;
282318
}
283319
}
320+
321+
#parseGetBucketPolicyStatusResult(xml: string): PolicyStatus {
322+
const doc: Document = parseXML(xml);
323+
const root = extractRoot(doc, "PolicyStatus");
324+
const isPublic =
325+
extractContent(root, "IsPublic ")?.toLowerCase() === "true";
326+
return { isPublic };
327+
}
284328
}

src/client_test.ts

+11
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,22 @@ Deno.test({
105105
await s3.putBucketPolicy("test.bucket", { policy });
106106
const resp = await s3.getBucketPolicy("test.bucket");
107107
assert(resp);
108+
109+
// teardown
108110
await s3.deleteBucketPolicy("test.bucket");
111+
109112
await assertThrowsAsync(
110113
() => s3.getBucketPolicy("test.bucket"),
111114
S3Error,
112115
'Failed to get policy for bucket "test.bucket": 404 Not Found',
113116
);
114117
},
115118
});
119+
120+
Deno.test({
121+
name: "[client] should get the bucket policy status",
122+
async fn() {
123+
const resp = await s3.getBucketPolicyStatus("test.bucket");
124+
assertEquals(resp, { isPublic: false });
125+
},
126+
});

src/types.ts

+17
Original file line numberDiff line numberDiff line change
@@ -728,3 +728,20 @@ export interface DeleteBucketPolicyOptions {
728728
*/
729729
expectedBucketOwner?: string;
730730
}
731+
732+
export interface GetBucketPolicyStatusOptions {
733+
/**
734+
* The account ID of the expected bucket owner. If the bucket is owned by a
735+
* different account, the request will fail with an HTTP 403 (Access Denied)
736+
* error.
737+
*/
738+
expectedBucketOwner?: string;
739+
}
740+
741+
export interface PolicyStatus {
742+
/**
743+
* The policy status for this bucket. TRUE indicates that this bucket is
744+
* public. FALSE indicates that the bucket is not public.
745+
*/
746+
isPublic: boolean;
747+
}

0 commit comments

Comments
 (0)