From 161c37c3a857907d0bcf1513d175f8d52034f11a Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 5 Aug 2024 16:17:42 -0700 Subject: [PATCH 1/6] Add beforeSmsSent blocking functions trigger --- src/common/providers/identity.ts | 22 ++++++++++++++++++- src/v1/providers/auth.ts | 7 +++++++ src/v2/providers/identity.ts | 36 ++++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/common/providers/identity.ts b/src/common/providers/identity.ts index bac3cb52e..913670b92 100644 --- a/src/common/providers/identity.ts +++ b/src/common/providers/identity.ts @@ -55,12 +55,13 @@ const CLAIMS_MAX_PAYLOAD_SIZE = 1000; * @hidden * @alpha */ -export type AuthBlockingEventType = "beforeCreate" | "beforeSignIn" | "beforeSendEmail"; +export type AuthBlockingEventType = "beforeCreate" | "beforeSignIn" | "beforeSendEmail" | "beforeSendSms"; const EVENT_MAPPING: Record = { beforeCreate: "providers/cloud.auth/eventTypes/user.beforeCreate", beforeSignIn: "providers/cloud.auth/eventTypes/user.beforeSignIn", beforeSendEmail: "providers/cloud.auth/eventTypes/user.beforeSendEmail", + beforeSendSms: "providers/cloud.auth/eventTypes/user.beforeSendSms", }; /** @@ -314,6 +315,7 @@ export interface AdditionalUserInfo { isNewUser: boolean; recaptchaScore?: number; email?: string; + phoneNumber?: string; } /** The credential component of the auth event context */ @@ -331,6 +333,14 @@ export interface Credential { /** Possible types of emails as described by the GCIP backend. */ export type EmailType = "EMAIL_SIGNIN" | "PASSWORD_RESET"; +/** + * The type of SMS message + */ +export type SmsType = + | "SIGN_IN_OR_SIGN_UP" // A sign-in or sign up SMS message + | "MULTI_FACTOR_SIGN_IN" // A multi-factor sign-in SMS message + | "MULTI_FACTOR_ENROLLMENT"; // A multi-factor enrollment SMS message + /** Defines the auth event context for blocking events */ export interface AuthEventContext extends EventContext { locale?: string; @@ -339,6 +349,7 @@ export interface AuthEventContext extends EventContext { additionalUserInfo?: AdditionalUserInfo; credential?: Credential; emailType?: EmailType; + smsType?: SmsType; } /** Defines the auth event for 2nd gen blocking events */ @@ -354,6 +365,11 @@ export interface BeforeEmailResponse { recaptchaActionOverride?: RecaptchaActionOptions; } +/** The handler response type for `beforeSmsSent` blocking events */ +export interface BeforeSmsResponse { + recaptchaActionOverride?: RecaptchaActionOptions; +} + /** The handler response type for beforeCreate blocking events */ export interface BeforeCreateResponse { displayName?: string; @@ -443,6 +459,8 @@ export interface DecodedPayload { recaptcha_score?: number; email?: string; email_type?: string; + phone_number?: string; + sms_type?: string; [key: string]: any; } @@ -676,6 +694,7 @@ function parseAdditionalUserInfo(decodedJWT: DecodedPayload): AdditionalUserInfo isNewUser: decodedJWT.event_type === "beforeCreate" ? true : false, recaptchaScore: decodedJWT.recaptcha_score, email: decodedJWT.email, + phoneNumber: decodedJWT.phone_number, }; } @@ -763,6 +782,7 @@ export function parseAuthEventContext( additionalUserInfo: parseAdditionalUserInfo(decodedJWT), credential: parseAuthCredential(decodedJWT, time), emailType: decodedJWT.email_type as EmailType, + smsType: decodedJWT.sms_type as SmsType, params: {}, }; } diff --git a/src/v1/providers/auth.ts b/src/v1/providers/auth.ts index efab2f488..6eaf3f563 100644 --- a/src/v1/providers/auth.ts +++ b/src/v1/providers/auth.ts @@ -27,6 +27,7 @@ import { BeforeCreateResponse, BeforeEmailResponse, BeforeSignInResponse, + BeforeSmsResponse, HandlerV1, HttpsError, MaybeAsync, @@ -180,6 +181,12 @@ export class UserBuilder { ): BlockingFunction { return this.beforeOperation(handler, "beforeSendEmail"); } + + beforeSms( + handler: (context: AuthEventContext) => MaybeAsync + ): BlockingFunction { + return this.beforeOperation(handler, "beforeSendSms"); + } private onOperation( handler: (user: UserRecord, context: EventContext) => PromiseLike | any, diff --git a/src/v2/providers/identity.ts b/src/v2/providers/identity.ts index 2829cd349..42b66d050 100644 --- a/src/v2/providers/identity.ts +++ b/src/v2/providers/identity.ts @@ -32,6 +32,7 @@ import { BeforeCreateResponse, BeforeSignInResponse, BeforeEmailResponse, + BeforeSmsResponse, HandlerV2, HttpsError, wrapHandler, @@ -259,6 +260,37 @@ export function beforeEmailSent( ): BlockingFunction { return beforeOperation("beforeSendEmail", optsOrHandler, handler); } +/** + * Handles an event that is triggered before an SMS is sent to a user. + * @param handler - Event handler that is run before an SMS is sent to a user. + */ +export function beforeSmsSent( + handler: (event: AuthBlockingEvent) => MaybeAsync +): BlockingFunction; + +/** + * Handles an event that is triggered before an SMS is sent to a user. + * @param opts - Object containing function options + * @param handler - Event handler that is run before an SMS is sent to a user. + */ +export function beforeSmsSent( + opts: Omit, + handler: (event: AuthBlockingEvent) => MaybeAsync +): BlockingFunction; + +/** + * Handles an event that is triggered before an SMS is sent to a user. + * @param optsOrHandler - Either an object containing function options, or an event handler that is run before an SMS is sent to a user. + * @param handler - Event handler that is run before an SMS is sent to a user. + */ +export function beforeSmsSent( + optsOrHandler: + | Omit + | ((event: AuthBlockingEvent) => MaybeAsync), + handler?: (event: AuthBlockingEvent) => MaybeAsync +): BlockingFunction { + return beforeOperation("beforeSendSms", optsOrHandler, handler); +} /** @hidden */ export function beforeOperation( @@ -267,13 +299,13 @@ export function beforeOperation( | BlockingOptions | (( event: AuthBlockingEvent - ) => MaybeAsync), + ) => MaybeAsync), handler: HandlerV2 ): BlockingFunction { if (!handler || typeof optsOrHandler === "function") { handler = optsOrHandler as ( event: AuthBlockingEvent - ) => MaybeAsync; + ) => MaybeAsync; optsOrHandler = {}; } From 6bc1c6baf1e9eba2a28829e11500afa087a808ae Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 19 Aug 2024 17:14:27 -0700 Subject: [PATCH 2/6] adding spec.ts changes --- spec/common/providers/identity.spec.ts | 56 +++++++++++++++- spec/v1/providers/auth.spec.ts | 90 ++++++++++++++++++++++++++ spec/v2/providers/identity.spec.ts | 49 ++++++++++++++ src/common/providers/identity.ts | 4 +- 4 files changed, 196 insertions(+), 3 deletions(-) diff --git a/spec/common/providers/identity.spec.ts b/spec/common/providers/identity.spec.ts index 167befff3..db82468b9 100644 --- a/spec/common/providers/identity.spec.ts +++ b/spec/common/providers/identity.spec.ts @@ -529,6 +529,7 @@ describe("identity", () => { eventId: "EVENT_ID", eventType: EVENT, emailType: undefined, + smsType: undefined, authType: "UNAUTHENTICATED", resource: { service: "identitytoolkit.googleapis.com", @@ -542,6 +543,7 @@ describe("identity", () => { isNewUser: false, recaptchaScore: TEST_RECAPTCHA_SCORE, email: undefined, + phoneNumber: undefined, }, credential: null, params: {}, @@ -580,6 +582,7 @@ describe("identity", () => { eventId: "EVENT_ID", eventType: "providers/cloud.auth/eventTypes/user.beforeSignIn:password", emailType: undefined, + smsType: undefined, authType: "UNAUTHENTICATED", resource: { service: "identitytoolkit.googleapis.com", @@ -593,6 +596,7 @@ describe("identity", () => { isNewUser: false, recaptchaScore: TEST_RECAPTCHA_SCORE, email: undefined, + phoneNumber: undefined, }, credential: { claims: undefined, @@ -668,6 +672,7 @@ describe("identity", () => { eventId: "EVENT_ID", eventType: "providers/cloud.auth/eventTypes/user.beforeCreate:oidc.provider", emailType: undefined, + smsType: undefined, authType: "USER", resource: { service: "identitytoolkit.googleapis.com", @@ -681,6 +686,7 @@ describe("identity", () => { isNewUser: true, recaptchaScore: TEST_RECAPTCHA_SCORE, email: undefined, + phoneNumber: undefined, }, credential: { claims: undefined, @@ -721,6 +727,7 @@ describe("identity", () => { eventId: "EVENT_ID", eventType: "providers/cloud.auth/eventTypes/user.beforeSendEmail", emailType: "RESET_PASSWORD", + smsType: undefined, authType: "UNAUTHENTICATED", resource: { service: "identitytoolkit.googleapis.com", @@ -734,6 +741,7 @@ describe("identity", () => { username: undefined, recaptchaScore: TEST_RECAPTCHA_SCORE, email: "johndoe@gmail.com", + phoneNumber: undefined, }, credential: null, params: {}, @@ -741,7 +749,53 @@ describe("identity", () => { expect(identity.parseAuthEventContext(decodedJwt, "project-id", time)).to.deep.equal(context); }); - }); + + it("should parse a beforeSendSms event", () => { + const time = now.getTime(); + const decodedJwt = { + iss: "https://securetoken.google.com/project_id", + aud: "https://us-east1-project_id.cloudfunctions.net/function-1", + iat: 1, + exp: 60 * 60 + 1, + event_id: "EVENT_ID", + event_type: "beforeSendSms", + user_agent: "USER_AGENT", + ip_address: "1.2.3.4", + locale: "en", + recaptcha_score: TEST_RECAPTCHA_SCORE, + sms_type: "SIGN_IN_OR_SIGN_UP", + phone_number: "+11234567890", + }; + const context = { + locale: "en", + ipAddress: "1.2.3.4", + userAgent: "USER_AGENT", + eventId: "EVENT_ID", + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + emailType: undefined, + smsType: "SIGN_IN_OR_SIGN_UP", + authType: "UNAUTHENTICATED", + resource: { + service: "identitytoolkit.googleapis.com", + name: "projects/project-id", + }, + timestamp: new Date(1000).toUTCString(), + additionalUserInfo: { + isNewUser: false, + profile: undefined, + providerId: undefined, + username: undefined, + recaptchaScore: TEST_RECAPTCHA_SCORE, + email: undefined, + phoneNumber: "+11234567890", + }, + credential: null, + params: {}, + }; + + expect(identity.parseAuthEventContext(decodedJwt, "project-id", time)).to.deep.equal(context); + }); +}); describe("validateAuthResponse", () => { it("should not throw on undefined request", () => { diff --git a/spec/v1/providers/auth.spec.ts b/spec/v1/providers/auth.spec.ts index 6901e3fdf..e2c21a690 100644 --- a/spec/v1/providers/auth.spec.ts +++ b/spec/v1/providers/auth.spec.ts @@ -394,6 +394,96 @@ describe("Auth Functions", () => { ]); }); }); + + describe("beforeSms", () => { + it("should create function without options", () => { + const fn = auth.user().beforeSms(() => Promise.resolve()); + + expect(fn.__trigger).to.deep.equal({ + labels: {}, + blockingTrigger: { + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + options: { + accessToken: false, + idToken: false, + refreshToken: false, + }, + }, + }); + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V1_ENDPOINT, + platform: "gcfv1", + labels: {}, + blockingTrigger: { + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + options: { + accessToken: false, + idToken: false, + refreshToken: false, + }, + }, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: "identitytoolkit.googleapis.com", + reason: "Needed for auth blocking functions", + }, + ]); + }); + + it("should create the function with options", () => { + const fn = functions + .region("us-east1") + .runWith({ + timeoutSeconds: 90, + memory: "256MB", + }) + .auth.user({ + blockingOptions: { + accessToken: true, + refreshToken: false, + }, + }) + .beforeSms(() => Promise.resolve()); + + expect(fn.__trigger).to.deep.equal({ + labels: {}, + regions: ["us-east1"], + availableMemoryMb: 256, + timeout: "90s", + blockingTrigger: { + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + options: { + accessToken: true, + idToken: false, + refreshToken: false, + }, + }, + }); + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V1_ENDPOINT, + platform: "gcfv1", + labels: {}, + region: ["us-east1"], + availableMemoryMb: 256, + timeoutSeconds: 90, + blockingTrigger: { + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + options: { + accessToken: true, + idToken: false, + refreshToken: false, + }, + }, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: "identitytoolkit.googleapis.com", + reason: "Needed for auth blocking functions", + }, + ]); + }); + }); describe("#_dataConstructor", () => { let cloudFunctionDelete: CloudFunction; diff --git a/spec/v2/providers/identity.spec.ts b/spec/v2/providers/identity.spec.ts index 5d1a7aee0..b74f6a851 100644 --- a/spec/v2/providers/identity.spec.ts +++ b/spec/v2/providers/identity.spec.ts @@ -52,6 +52,12 @@ const BEFORE_EMAIL_TRIGGER = { options: {}, }; + +const BEFORE_SMS_TRIGGER = { + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + options: {}, +}; + const opts: identity.BlockingOptions = { accessToken: true, refreshToken: false, @@ -232,6 +238,49 @@ describe("identity", () => { ]); }); }); + + describe("beforeSmsSent", () => { + it("should accept a handler", () => { + const fn = identity.beforeSmsSent(() => Promise.resolve()); + + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V2_ENDPOINT, + platform: "gcfv2", + labels: {}, + blockingTrigger: BEFORE_SMS_TRIGGER, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: IDENTITY_TOOLKIT_API, + reason: "Needed for auth blocking functions", + }, + ]); + }); + + it("should accept options and a handler", () => { + const fn = identity.beforeSmsSent( + { region: opts.region, minInstances: opts.minInstances }, + () => Promise.resolve() + ); + + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V2_ENDPOINT, + platform: "gcfv2", + labels: {}, + minInstances: 1, + region: [REGION], + blockingTrigger: { + ...BEFORE_SMS_TRIGGER, + }, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: IDENTITY_TOOLKIT_API, + reason: "Needed for auth blocking functions", + }, + ]); + }); + }); describe("beforeOperation", () => { it("should handle eventType and handler for before create events", () => { diff --git a/src/common/providers/identity.ts b/src/common/providers/identity.ts index 913670b92..fe89d0e8a 100644 --- a/src/common/providers/identity.ts +++ b/src/common/providers/identity.ts @@ -488,11 +488,11 @@ export type MaybeAsync = T | Promise; export type HandlerV1 = ( userOrContext: AuthUserRecord | AuthEventContext, context?: AuthEventContext -) => MaybeAsync; +) => MaybeAsync; export type HandlerV2 = ( event: AuthBlockingEvent -) => MaybeAsync; +) => MaybeAsync; export type AuthBlockingEventHandler = (HandlerV1 | HandlerV2) & { // Specify the GCF gen of the trigger that the auth blocking event handler was written for From 6b4e59d69975a390256a582de9bdb45bf9f6a0df Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 19 Aug 2024 17:18:09 -0700 Subject: [PATCH 3/6] lint --- spec/common/providers/identity.spec.ts | 94 +++++++++++++------------- spec/v1/providers/auth.spec.ts | 10 +-- spec/v2/providers/identity.spec.ts | 11 ++- src/common/providers/identity.ts | 14 +++- src/v1/providers/auth.ts | 2 +- src/v2/providers/identity.ts | 8 ++- 6 files changed, 75 insertions(+), 64 deletions(-) diff --git a/spec/common/providers/identity.spec.ts b/spec/common/providers/identity.spec.ts index db82468b9..253a337b2 100644 --- a/spec/common/providers/identity.spec.ts +++ b/spec/common/providers/identity.spec.ts @@ -749,53 +749,53 @@ describe("identity", () => { expect(identity.parseAuthEventContext(decodedJwt, "project-id", time)).to.deep.equal(context); }); - - it("should parse a beforeSendSms event", () => { - const time = now.getTime(); - const decodedJwt = { - iss: "https://securetoken.google.com/project_id", - aud: "https://us-east1-project_id.cloudfunctions.net/function-1", - iat: 1, - exp: 60 * 60 + 1, - event_id: "EVENT_ID", - event_type: "beforeSendSms", - user_agent: "USER_AGENT", - ip_address: "1.2.3.4", - locale: "en", - recaptcha_score: TEST_RECAPTCHA_SCORE, - sms_type: "SIGN_IN_OR_SIGN_UP", - phone_number: "+11234567890", - }; - const context = { - locale: "en", - ipAddress: "1.2.3.4", - userAgent: "USER_AGENT", - eventId: "EVENT_ID", - eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", - emailType: undefined, - smsType: "SIGN_IN_OR_SIGN_UP", - authType: "UNAUTHENTICATED", - resource: { - service: "identitytoolkit.googleapis.com", - name: "projects/project-id", - }, - timestamp: new Date(1000).toUTCString(), - additionalUserInfo: { - isNewUser: false, - profile: undefined, - providerId: undefined, - username: undefined, - recaptchaScore: TEST_RECAPTCHA_SCORE, - email: undefined, - phoneNumber: "+11234567890", - }, - credential: null, - params: {}, - }; - - expect(identity.parseAuthEventContext(decodedJwt, "project-id", time)).to.deep.equal(context); - }); -}); + + it("should parse a beforeSendSms event", () => { + const time = now.getTime(); + const decodedJwt = { + iss: "https://securetoken.google.com/project_id", + aud: "https://us-east1-project_id.cloudfunctions.net/function-1", + iat: 1, + exp: 60 * 60 + 1, + event_id: "EVENT_ID", + event_type: "beforeSendSms", + user_agent: "USER_AGENT", + ip_address: "1.2.3.4", + locale: "en", + recaptcha_score: TEST_RECAPTCHA_SCORE, + sms_type: "SIGN_IN_OR_SIGN_UP", + phone_number: "+11234567890", + }; + const context = { + locale: "en", + ipAddress: "1.2.3.4", + userAgent: "USER_AGENT", + eventId: "EVENT_ID", + eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", + emailType: undefined, + smsType: "SIGN_IN_OR_SIGN_UP", + authType: "UNAUTHENTICATED", + resource: { + service: "identitytoolkit.googleapis.com", + name: "projects/project-id", + }, + timestamp: new Date(1000).toUTCString(), + additionalUserInfo: { + isNewUser: false, + profile: undefined, + providerId: undefined, + username: undefined, + recaptchaScore: TEST_RECAPTCHA_SCORE, + email: undefined, + phoneNumber: "+11234567890", + }, + credential: null, + params: {}, + }; + + expect(identity.parseAuthEventContext(decodedJwt, "project-id", time)).to.deep.equal(context); + }); + }); describe("validateAuthResponse", () => { it("should not throw on undefined request", () => { diff --git a/spec/v1/providers/auth.spec.ts b/spec/v1/providers/auth.spec.ts index e2c21a690..ec1a793f5 100644 --- a/spec/v1/providers/auth.spec.ts +++ b/spec/v1/providers/auth.spec.ts @@ -394,11 +394,11 @@ describe("Auth Functions", () => { ]); }); }); - + describe("beforeSms", () => { it("should create function without options", () => { const fn = auth.user().beforeSms(() => Promise.resolve()); - + expect(fn.__trigger).to.deep.equal({ labels: {}, blockingTrigger: { @@ -430,7 +430,7 @@ describe("Auth Functions", () => { }, ]); }); - + it("should create the function with options", () => { const fn = functions .region("us-east1") @@ -445,7 +445,7 @@ describe("Auth Functions", () => { }, }) .beforeSms(() => Promise.resolve()); - + expect(fn.__trigger).to.deep.equal({ labels: {}, regions: ["us-east1"], @@ -483,7 +483,7 @@ describe("Auth Functions", () => { }, ]); }); - }); + }); describe("#_dataConstructor", () => { let cloudFunctionDelete: CloudFunction; diff --git a/spec/v2/providers/identity.spec.ts b/spec/v2/providers/identity.spec.ts index b74f6a851..758c34289 100644 --- a/spec/v2/providers/identity.spec.ts +++ b/spec/v2/providers/identity.spec.ts @@ -52,7 +52,6 @@ const BEFORE_EMAIL_TRIGGER = { options: {}, }; - const BEFORE_SMS_TRIGGER = { eventType: "providers/cloud.auth/eventTypes/user.beforeSendSms", options: {}, @@ -238,11 +237,11 @@ describe("identity", () => { ]); }); }); - + describe("beforeSmsSent", () => { it("should accept a handler", () => { const fn = identity.beforeSmsSent(() => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -256,13 +255,13 @@ describe("identity", () => { }, ]); }); - + it("should accept options and a handler", () => { const fn = identity.beforeSmsSent( { region: opts.region, minInstances: opts.minInstances }, () => Promise.resolve() ); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -280,7 +279,7 @@ describe("identity", () => { }, ]); }); - }); + }); describe("beforeOperation", () => { it("should handle eventType and handler for before create events", () => { diff --git a/src/common/providers/identity.ts b/src/common/providers/identity.ts index fe89d0e8a..ee51a5dce 100644 --- a/src/common/providers/identity.ts +++ b/src/common/providers/identity.ts @@ -55,7 +55,11 @@ const CLAIMS_MAX_PAYLOAD_SIZE = 1000; * @hidden * @alpha */ -export type AuthBlockingEventType = "beforeCreate" | "beforeSignIn" | "beforeSendEmail" | "beforeSendSms"; +export type AuthBlockingEventType = + | "beforeCreate" + | "beforeSignIn" + | "beforeSendEmail" + | "beforeSendSms"; const EVENT_MAPPING: Record = { beforeCreate: "providers/cloud.auth/eventTypes/user.beforeCreate", @@ -488,11 +492,15 @@ export type MaybeAsync = T | Promise; export type HandlerV1 = ( userOrContext: AuthUserRecord | AuthEventContext, context?: AuthEventContext -) => MaybeAsync; +) => MaybeAsync< + BeforeCreateResponse | BeforeSignInResponse | BeforeEmailResponse | BeforeSmsResponse | void +>; export type HandlerV2 = ( event: AuthBlockingEvent -) => MaybeAsync; +) => MaybeAsync< + BeforeCreateResponse | BeforeSignInResponse | BeforeEmailResponse | BeforeSmsResponse | void +>; export type AuthBlockingEventHandler = (HandlerV1 | HandlerV2) & { // Specify the GCF gen of the trigger that the auth blocking event handler was written for diff --git a/src/v1/providers/auth.ts b/src/v1/providers/auth.ts index 6eaf3f563..2a88cd41a 100644 --- a/src/v1/providers/auth.ts +++ b/src/v1/providers/auth.ts @@ -181,7 +181,7 @@ export class UserBuilder { ): BlockingFunction { return this.beforeOperation(handler, "beforeSendEmail"); } - + beforeSms( handler: (context: AuthEventContext) => MaybeAsync ): BlockingFunction { diff --git a/src/v2/providers/identity.ts b/src/v2/providers/identity.ts index 42b66d050..01ece673b 100644 --- a/src/v2/providers/identity.ts +++ b/src/v2/providers/identity.ts @@ -299,13 +299,17 @@ export function beforeOperation( | BlockingOptions | (( event: AuthBlockingEvent - ) => MaybeAsync), + ) => MaybeAsync< + BeforeCreateResponse | BeforeSignInResponse | BeforeEmailResponse | BeforeSmsResponse | void + >), handler: HandlerV2 ): BlockingFunction { if (!handler || typeof optsOrHandler === "function") { handler = optsOrHandler as ( event: AuthBlockingEvent - ) => MaybeAsync; + ) => MaybeAsync< + BeforeCreateResponse | BeforeSignInResponse | BeforeEmailResponse | BeforeSmsResponse | void + >; optsOrHandler = {}; } From 5f77c8bc2b401206153fb2efb0da72022797d5b3 Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 19 Aug 2024 17:35:02 -0700 Subject: [PATCH 4/6] add missing tests --- spec/v2/providers/identity.spec.ts | 62 ++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/spec/v2/providers/identity.spec.ts b/spec/v2/providers/identity.spec.ts index 758c34289..87b20bdc9 100644 --- a/spec/v2/providers/identity.spec.ts +++ b/spec/v2/providers/identity.spec.ts @@ -284,7 +284,7 @@ describe("identity", () => { describe("beforeOperation", () => { it("should handle eventType and handler for before create events", () => { const fn = identity.beforeOperation("beforeCreate", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -298,10 +298,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType and handler for before sign in events", () => { const fn = identity.beforeOperation("beforeSignIn", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -315,10 +315,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType and handler for before email events", () => { const fn = identity.beforeOperation("beforeSendEmail", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -332,10 +332,27 @@ describe("identity", () => { }, ]); }); - + + it("should handle eventType and handler for before SMS events", () => { + const fn = identity.beforeOperation("beforeSendSms", () => Promise.resolve(), undefined); + + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V2_ENDPOINT, + platform: "gcfv2", + labels: {}, + blockingTrigger: BEFORE_SMS_TRIGGER, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: IDENTITY_TOOLKIT_API, + reason: "Needed for auth blocking functions", + }, + ]); + }); + it("should handle eventType, options, and handler for before create events", () => { const fn = identity.beforeOperation("beforeCreate", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -357,10 +374,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before sign in events", () => { const fn = identity.beforeOperation("beforeSignIn", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -382,10 +399,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before send email events", () => { const fn = identity.beforeOperation("beforeSendEmail", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -403,7 +420,28 @@ describe("identity", () => { }, ]); }); - }); + + it("should handle eventType, options, and handler for before send SMS events", () => { + const fn = identity.beforeOperation("beforeSendSms", opts, () => Promise.resolve()); + + expect(fn.__endpoint).to.deep.equal({ + ...MINIMAL_V2_ENDPOINT, + platform: "gcfv2", + labels: {}, + minInstances: 1, + region: [REGION], + blockingTrigger: { + ...BEFORE_SMS_TRIGGER, + }, + }); + expect(fn.__requiredAPIs).to.deep.equal([ + { + api: IDENTITY_TOOLKIT_API, + reason: "Needed for auth blocking functions", + }, + ]); + }); + }); describe("getOpts", () => { it("should parse an empty object", () => { From 24e280375613885e1e399531ba87361170293ab2 Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 19 Aug 2024 17:43:52 -0700 Subject: [PATCH 5/6] lint --- spec/v2/providers/identity.spec.ts | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/spec/v2/providers/identity.spec.ts b/spec/v2/providers/identity.spec.ts index 87b20bdc9..7984d085f 100644 --- a/spec/v2/providers/identity.spec.ts +++ b/spec/v2/providers/identity.spec.ts @@ -284,7 +284,7 @@ describe("identity", () => { describe("beforeOperation", () => { it("should handle eventType and handler for before create events", () => { const fn = identity.beforeOperation("beforeCreate", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -298,10 +298,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType and handler for before sign in events", () => { const fn = identity.beforeOperation("beforeSignIn", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -315,10 +315,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType and handler for before email events", () => { const fn = identity.beforeOperation("beforeSendEmail", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -332,10 +332,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType and handler for before SMS events", () => { const fn = identity.beforeOperation("beforeSendSms", () => Promise.resolve(), undefined); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -349,10 +349,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before create events", () => { const fn = identity.beforeOperation("beforeCreate", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -374,10 +374,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before sign in events", () => { const fn = identity.beforeOperation("beforeSignIn", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -399,10 +399,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before send email events", () => { const fn = identity.beforeOperation("beforeSendEmail", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -420,10 +420,10 @@ describe("identity", () => { }, ]); }); - + it("should handle eventType, options, and handler for before send SMS events", () => { const fn = identity.beforeOperation("beforeSendSms", opts, () => Promise.resolve()); - + expect(fn.__endpoint).to.deep.equal({ ...MINIMAL_V2_ENDPOINT, platform: "gcfv2", @@ -441,7 +441,7 @@ describe("identity", () => { }, ]); }); - }); + }); describe("getOpts", () => { it("should parse an empty object", () => { From da30675b75a4b1de0ec8cb9df45b2f768ad01962 Mon Sep 17 00:00:00 2001 From: Pragati Date: Mon, 19 Aug 2024 17:47:12 -0700 Subject: [PATCH 6/6] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fc76447f..51926d296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1 @@ -- Add support for beforeEmailSent auth blocking triggers. (#1492) +- Add support for beforeSmsSent auth blocking triggers. (#1589)