1import * as ci from "@distilled.cloud/aws/cognito-identity";
2import * as Effect from "effect/Effect";
3import * as Layer from "effect/Layer";
4import * as Binding from "../../Binding.ts";
5import { isBindingHost } from "../Lambda/Function.ts";
6import { cognitoMethods } from "./BindingHttp.ts";
7import type { IdentityPool } from "./IdentityPool.ts";
8import {
9 IdentityPoolAdmin,
10 type IdentityPoolAdminClient,
11} from "./IdentityPoolAdmin.ts";
12
13/** The injected identifier field, in the distilled wire type. */
14type IdentityPoolIdField = Pick<ci.ListIdentitiesInput, "IdentityPoolId">;
15
16/**
17 * HTTP implementation of {@link IdentityPoolAdmin}: grants the
18 * `cognito-identity:*` identity-management actions on the bound pool's ARN
19 * and calls the Cognito Identity HTTP API with the function's IAM
20 * credentials.
21 */
22export const IdentityPoolAdminHttp = Layer.effect(
23 IdentityPoolAdmin,
24 Effect.gen(function* () {
25 const describeIdentity = yield* ci.describeIdentity;
26 const listIdentities = yield* ci.listIdentities;
27 const deleteIdentities = yield* ci.deleteIdentities;
28 const lookupDeveloperIdentity = yield* ci.lookupDeveloperIdentity;
29 const mergeDeveloperIdentities = yield* ci.mergeDeveloperIdentities;
30 const unlinkDeveloperIdentity = yield* ci.unlinkDeveloperIdentity;
31 const getOpenIdTokenForDeveloperIdentity =
32 yield* ci.getOpenIdTokenForDeveloperIdentity;
33
34 return Effect.fn(function* <P extends IdentityPool>(pool: P) {
35 const IdentityPoolId = yield* pool.identityPoolId;
36 if (!globalThis.__ALCHEMY_RUNTIME__) {
37 const host = yield* Binding.Host;
38 if (isBindingHost(host)) {
39 yield* host.bind`Allow(${host}, AWS.Cognito.IdentityPoolAdmin(${pool}))`(
40 {
41 policyStatements: [
42 {
43 Effect: "Allow",
44 Action: [
45 "cognito-identity:GetOpenIdTokenForDeveloperIdentity",
46 "cognito-identity:ListIdentities",
47 "cognito-identity:LookupDeveloperIdentity",
48 "cognito-identity:MergeDeveloperIdentities",
49 "cognito-identity:UnlinkDeveloperIdentity",
50 ],
51 Resource: [pool.identityPoolArn],
52 },
53 {
54 Effect: "Allow",
55 // These act on identity IDs, which have no ARN form —
56 // Cognito Identity does not support resource-level
57 // scoping for them.
58 Action: [
59 "cognito-identity:DeleteIdentities",
60 "cognito-identity:DescribeIdentity",
61 ],
62 Resource: ["*"],
63 },
64 ],
65 },
66 );
67 }
68 }
69 const methods = cognitoMethods(
70 "AWS.Cognito.IdentityPoolAdmin",
71 pool.LogicalId,
72 );
73 const withPool = methods.injecting(
74 Effect.map(IdentityPoolId, (id): IdentityPoolIdField => ({
75 IdentityPoolId: id,
76 })),
77 );
78 const adminClient: IdentityPoolAdminClient = {
79 describeIdentity: methods.plain("describeIdentity", describeIdentity),
80 deleteIdentities: methods.plain("deleteIdentities", deleteIdentities),
81 listIdentities: withPool("listIdentities", listIdentities),
82 lookupDeveloperIdentity: withPool(
83 "lookupDeveloperIdentity",
84 lookupDeveloperIdentity,
85 ),
86 mergeDeveloperIdentities: withPool(
87 "mergeDeveloperIdentities",
88 mergeDeveloperIdentities,
89 ),
90 unlinkDeveloperIdentity: withPool(
91 "unlinkDeveloperIdentity",
92 unlinkDeveloperIdentity,
93 ),
94 getOpenIdTokenForDeveloperIdentity: withPool(
95 "getOpenIdTokenForDeveloperIdentity",
96 getOpenIdTokenForDeveloperIdentity,
97 ),
98 };
99 return adminClient;
100 });
101 }),
102);