-
Notifications
You must be signed in to change notification settings - Fork 390
Create/Update tenant with ReCAPTCHA Config #1586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1cd6fe5
4bdd00b
f98cd0e
766adc5
930a277
6452fe1
18c2e02
8298b13
9be6dfe
24dad45
bdb0f91
b6bf490
e0c1427
ee241f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1497,22 +1497,156 @@ export interface RecaptchaKey { | |
/** | ||
* The reCAPTCHA site key. | ||
*/ | ||
key: string; | ||
key: string; | ||
} | ||
|
||
/** | ||
* The request interface for updating a reCAPTCHA Config. | ||
*/ | ||
export interface RecaptchaConfig { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
/** | ||
* The enforcement state of email password provider. | ||
*/ | ||
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
lahirumaramba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* The reCAPTCHA managed rules. | ||
*/ | ||
managedRules?: RecaptchaManagedRule[]; | ||
|
||
/** | ||
* The reCAPTCHA managed rules. | ||
*/ | ||
managedRules: RecaptchaManagedRule[]; | ||
/** | ||
* The reCAPTCHA keys. | ||
*/ | ||
recaptchaKeys?: RecaptchaKey[]; | ||
} | ||
|
||
/** | ||
* The reCAPTCHA keys. | ||
*/ | ||
recaptchaKeys?: RecaptchaKey[]; | ||
export class RecaptchaAuthConfig implements RecaptchaConfig { | ||
public readonly emailPasswordEnforcementState?: RecaptchaProviderEnforcementState; | ||
public readonly managedRules?: RecaptchaManagedRule[]; | ||
public readonly recaptchaKeys?: RecaptchaKey[]; | ||
|
||
constructor(recaptchaConfig: RecaptchaConfig) { | ||
this.emailPasswordEnforcementState = recaptchaConfig.emailPasswordEnforcementState; | ||
this.managedRules = recaptchaConfig.managedRules; | ||
this.recaptchaKeys = recaptchaConfig.recaptchaKeys; | ||
} | ||
|
||
/** | ||
* Validates the RecaptchaConfig options object. Throws an error on failure. | ||
* @param options - The options object to validate. | ||
*/ | ||
public static validate(options: RecaptchaConfig): void { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const validKeys = { | ||
emailPasswordEnforcementState: true, | ||
managedRules: true, | ||
recaptchaKeys: true, | ||
}; | ||
|
||
if (!validator.isNonNullObject(options)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig" must be a non-null object.', | ||
); | ||
} | ||
|
||
for (const key in options) { | ||
if (!(key in validKeys)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
`"${key}" is not a valid RecaptchaConfig parameter.`, | ||
); | ||
} | ||
} | ||
|
||
// Validation | ||
if (typeof options.emailPasswordEnforcementState !== undefined) { | ||
if (!validator.isNonEmptyString(options.emailPasswordEnforcementState)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_ARGUMENT, | ||
'"RecaptchaConfig.emailPasswordEnforcementState" must be a valid non-empty string.', | ||
); | ||
} | ||
|
||
if (options.emailPasswordEnforcementState !== 'OFF' && | ||
options.emailPasswordEnforcementState !== 'AUDIT' && | ||
options.emailPasswordEnforcementState !== 'ENFORCE') { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig.emailPasswordEnforcementState" must be either "OFF", "AUDIT" or "ENFORCE".', | ||
); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason for this separation is to align with the backend error-code and keep consistency with the existing error message. E.g. empty string is an INVALID_ARGUMENT but invalid string is an INVALID_CONFIG. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The SDK shouldn't allow empty strings in the request to the BE service so this error technically should not occur (from the backend). I felt like the check is redundant because you check for a restricted set of strings here regardless. Not a big issue so I will leave it up to you to decide the best path here. |
||
|
||
if (typeof options.managedRules !== 'undefined') { | ||
// Validate array | ||
if (!validator.isArray(options.managedRules)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaConfig.managedRules" must be an array of valid "RecaptchaManagedRule".', | ||
); | ||
} | ||
// Validate each rule of the array | ||
options.managedRules.forEach((managedRule) => { | ||
RecaptchaAuthConfig.validateManagedRule(managedRule); | ||
}); | ||
lahirumaramba marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
/** | ||
* Validate each element in ManagedRule array | ||
* @param options - The options object to validate. | ||
*/ | ||
private static validateManagedRule(options: RecaptchaManagedRule): void { | ||
const validKeys = { | ||
endScore: true, | ||
action: true, | ||
} | ||
if (!validator.isNonNullObject(options)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaManagedRule" must be a non-null object.', | ||
); | ||
} | ||
// Check for unsupported top level attributes. | ||
for (const key in options) { | ||
if (!(key in validKeys)) { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
`"${key}" is not a valid RecaptchaManagedRule parameter.`, | ||
); | ||
} | ||
} | ||
|
||
// Validate content. | ||
if (typeof options.action !== 'undefined' && | ||
options.action !== 'BLOCK') { | ||
throw new FirebaseAuthError( | ||
AuthClientErrorCode.INVALID_CONFIG, | ||
'"RecaptchaManagedRule.action" must be "BLOCK".', | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Returns a JSON-serializable representation of this object. | ||
* @returns The JSON-serializable object representation of the ReCaptcha config instance | ||
*/ | ||
public toJSON(): object { | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const json: any = { | ||
emailPasswordEnforcementState: this.emailPasswordEnforcementState, | ||
managedRules: deepCopy(this.managedRules), | ||
recaptchaKeys: deepCopy(this.recaptchaKeys) | ||
} | ||
|
||
if (typeof json.emailPasswordEnforcementState === 'undefined') { | ||
delete json.emailPasswordEnforcementState; | ||
Xiaoshouzi-gh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if (typeof json.managedRules === 'undefined') { | ||
delete json.managedRules; | ||
} | ||
if (typeof json.recaptchaKeys === 'undefined') { | ||
delete json.recaptchaKeys; | ||
} | ||
|
||
return json; | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.