Skip to content

Commit

Permalink
Project config - Recaptcha config (#1595)
Browse files Browse the repository at this point in the history
* Recaptcha config changes in project config.
- Implemented getProjectConfig.
- Implemented updateProjectConfig.
- Updated error code.
- Add Term of Service consents.
  • Loading branch information
Xiaoshouzi-gh committed Mar 8, 2022
1 parent 0d1a56f commit c01f7fb
Show file tree
Hide file tree
Showing 11 changed files with 730 additions and 13 deletions.
18 changes: 18 additions & 0 deletions etc/firebase-admin.auth.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ActionCodeSettings {
export class Auth extends BaseAuth {
// Warning: (ae-forgotten-export) The symbol "App" needs to be exported by the entry point index.d.ts
get app(): App;
projectConfigManager(): ProjectConfigManager;
tenantManager(): TenantManager;
}

Expand Down Expand Up @@ -256,6 +257,18 @@ export class PhoneMultiFactorInfo extends MultiFactorInfo {
toJSON(): object;
}

// @public
export class ProjectConfig {
get recaptchaConfig(): RecaptchaConfig | undefined;
toJSON(): object;
}

// @public
export class ProjectConfigManager {
getProjectConfig(): Promise<ProjectConfig>;
updateProjectConfig(projectConfigOptions: UpdateProjectConfigRequest): Promise<ProjectConfig>;
}

// @public
export interface ProviderIdentifier {
// (undocumented)
Expand Down Expand Up @@ -367,6 +380,11 @@ export interface UpdatePhoneMultiFactorInfoRequest extends BaseUpdateMultiFactor
phoneNumber: string;
}

// @public
export interface UpdateProjectConfigRequest {
recaptchaConfig?: RecaptchaConfig;
}

// @public
export interface UpdateRequest {
disabled?: boolean;
Expand Down
72 changes: 62 additions & 10 deletions src/auth/auth-api-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
OIDCAuthProviderConfig, SAMLAuthProviderConfig, OIDCUpdateAuthProviderRequest,
SAMLUpdateAuthProviderRequest
} from './auth-config';
import { ProjectConfig, ProjectConfigServerResponse, UpdateProjectConfigRequest } from './project-config';

/** Firebase Auth request header. */
const FIREBASE_AUTH_HEADER = {
Expand Down Expand Up @@ -102,7 +103,6 @@ const FIREBASE_AUTH_TENANT_URL_FORMAT = FIREBASE_AUTH_BASE_URL_FORMAT.replace(
const FIREBASE_AUTH_EMULATOR_TENANT_URL_FORMAT = FIREBASE_AUTH_EMULATOR_BASE_URL_FORMAT.replace(
'projects/{projectId}', 'projects/{projectId}/tenants/{tenantId}');


/** Maximum allowed number of tenants to download at one time. */
const MAX_LIST_TENANT_PAGE_SIZE = 1000;

Expand Down Expand Up @@ -1961,6 +1961,29 @@ export abstract class AbstractAuthRequestHandler {
}
}

/** Instantiates the getConfig endpoint settings. */
const GET_PROJECT_CONFIG = new ApiSettings('/config', 'GET')
.setResponseValidator((response: any) => {
// Response should always contain at least the config name.
if (!validator.isNonEmptyString(response.name)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INTERNAL_ERROR,
'INTERNAL ASSERT FAILED: Unable to get project config',
);
}
});

/** Instantiates the updateConfig endpoint settings. */
const UPDATE_PROJECT_CONFIG = new ApiSettings('/config?updateMask={updateMask}', 'PATCH')
.setResponseValidator((response: any) => {
// Response should always contain at least the config name.
if (!validator.isNonEmptyString(response.name)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INTERNAL_ERROR,
'INTERNAL ASSERT FAILED: Unable to update project config',
);
}
});

/** Instantiates the getTenant endpoint settings. */
const GET_TENANT = new ApiSettings('/tenants/{tenantId}', 'GET')
Expand Down Expand Up @@ -2029,13 +2052,13 @@ const CREATE_TENANT = new ApiSettings('/tenants', 'POST')


/**
* Utility for sending requests to Auth server that are Auth instance related. This includes user and
* tenant management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
* Utility for sending requests to Auth server that are Auth instance related. This includes user, tenant,
* and project config management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
* additional tenant management related APIs.
*/
export class AuthRequestHandler extends AbstractAuthRequestHandler {

protected readonly tenantMgmtResourceBuilder: AuthResourceUrlBuilder;
protected readonly authResourceUrlBuilder: AuthResourceUrlBuilder;

/**
* The FirebaseAuthRequestHandler constructor used to initialize an instance using a FirebaseApp.
Expand All @@ -2045,7 +2068,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
*/
constructor(app: App) {
super(app);
this.tenantMgmtResourceBuilder = new AuthResourceUrlBuilder(app, 'v2');
this.authResourceUrlBuilder = new AuthResourceUrlBuilder(app, 'v2');
}

/**
Expand All @@ -2062,6 +2085,35 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
return new AuthResourceUrlBuilder(this.app, 'v2');
}

/**
* Get the current project's config
* @returns A promise that resolves with the project config information.
*/
public getProjectConfig(): Promise<ProjectConfigServerResponse> {
return this.invokeRequestHandler(this.authResourceUrlBuilder, GET_PROJECT_CONFIG, {}, {})
.then((response: any) => {
return response as ProjectConfigServerResponse;
});
}

/**
* Update the current project's config.
* @returns A promise that resolves with the project config information.
*/
public updateProjectConfig(recaptchaOptions: UpdateProjectConfigRequest): Promise<ProjectConfigServerResponse> {
try {
const request = ProjectConfig.buildServerRequest(recaptchaOptions);
const updateMask = utils.generateUpdateMask(request);
return this.invokeRequestHandler(
this.authResourceUrlBuilder, UPDATE_PROJECT_CONFIG, request, { updateMask: updateMask.join(',') })
.then((response: any) => {
return response as ProjectConfigServerResponse;
});
} catch (e) {
return Promise.reject(e);
}
}

/**
* Looks up a tenant by tenant ID.
*
Expand All @@ -2072,7 +2124,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
if (!validator.isNonEmptyString(tenantId)) {
return Promise.reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_TENANT_ID));
}
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, GET_TENANT, {}, { tenantId })
return this.invokeRequestHandler(this.authResourceUrlBuilder, GET_TENANT, {}, { tenantId })
.then((response: any) => {
return response as TenantServerResponse;
});
Expand Down Expand Up @@ -2102,7 +2154,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
if (typeof request.pageToken === 'undefined') {
delete request.pageToken;
}
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, LIST_TENANTS, request)
return this.invokeRequestHandler(this.authResourceUrlBuilder, LIST_TENANTS, request)
.then((response: any) => {
if (!response.tenants) {
response.tenants = [];
Expand All @@ -2122,7 +2174,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
if (!validator.isNonEmptyString(tenantId)) {
return Promise.reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_TENANT_ID));
}
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, DELETE_TENANT, undefined, { tenantId })
return this.invokeRequestHandler(this.authResourceUrlBuilder, DELETE_TENANT, undefined, { tenantId })
.then(() => {
// Return nothing.
});
Expand All @@ -2138,7 +2190,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
try {
// Construct backend request.
const request = Tenant.buildServerRequest(tenantOptions, true);
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, CREATE_TENANT, request)
return this.invokeRequestHandler(this.authResourceUrlBuilder, CREATE_TENANT, request)
.then((response: any) => {
return response as TenantServerResponse;
});
Expand All @@ -2164,7 +2216,7 @@ export class AuthRequestHandler extends AbstractAuthRequestHandler {
// Do not traverse deep into testPhoneNumbers. The entire content should be replaced
// and not just specific phone numbers.
const updateMask = utils.generateUpdateMask(request, ['testPhoneNumbers']);
return this.invokeRequestHandler(this.tenantMgmtResourceBuilder, UPDATE_TENANT, request,
return this.invokeRequestHandler(this.authResourceUrlBuilder, UPDATE_TENANT, request,
{ tenantId, updateMask: updateMask.join(',') })
.then((response: any) => {
return response as TenantServerResponse;
Expand Down
3 changes: 3 additions & 0 deletions src/auth/auth-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1502,6 +1502,9 @@ export interface RecaptchaKey {

/**
* The request interface for updating a reCAPTCHA Config.
* By enabling reCAPTCHA Enterprise Integration you are
* agreeing to reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
export interface RecaptchaConfig {
/**
Expand Down
12 changes: 12 additions & 0 deletions src/auth/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { App } from '../app/index';
import { AuthRequestHandler } from './auth-api-request';
import { TenantManager } from './tenant-manager';
import { BaseAuth } from './base-auth';
import { ProjectConfigManager } from './project-config-manager';

/**
* Auth service bound to the provided app.
Expand All @@ -27,6 +28,7 @@ import { BaseAuth } from './base-auth';
export class Auth extends BaseAuth {

private readonly tenantManager_: TenantManager;
private readonly projectConfigManager_: ProjectConfigManager;
private readonly app_: App;

/**
Expand All @@ -38,6 +40,7 @@ export class Auth extends BaseAuth {
super(app, new AuthRequestHandler(app));
this.app_ = app;
this.tenantManager_ = new TenantManager(app);
this.projectConfigManager_ = new ProjectConfigManager(app);
}

/**
Expand All @@ -57,4 +60,13 @@ export class Auth extends BaseAuth {
public tenantManager(): TenantManager {
return this.tenantManager_;
}

/**
* Returns the project config manager instance associated with the current project.
*
* @returns The project config manager instance associated with the current project.
*/
public projectConfigManager(): ProjectConfigManager {
return this.projectConfigManager_;
}
}
9 changes: 9 additions & 0 deletions src/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ export {
TenantManager,
} from './tenant-manager';

export {
UpdateProjectConfigRequest,
ProjectConfig,
} from './project-config';

export {
ProjectConfigManager,
} from './project-config-manager';

export { DecodedIdToken } from './token-verifier';

export {
Expand Down
67 changes: 67 additions & 0 deletions src/auth/project-config-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*!
* Copyright 2022 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { App } from '../app';
import { ProjectConfig, ProjectConfigServerResponse, UpdateProjectConfigRequest } from './project-config';
import {
AuthRequestHandler,
} from './auth-api-request';

/**
* Defines the project config manager used to help manage project config related operations.
* This includes:
* <ul>
* <li>The ability to update and get project config.</li>
*/
export class ProjectConfigManager {
private readonly authRequestHandler: AuthRequestHandler;

/**
* Initializes a ProjectConfigManager instance for a specified FirebaseApp.
*
* @param app - The app for this ProjectConfigManager instance.
*
* @constructor
* @internal
*/
constructor(app: App) {
this.authRequestHandler = new AuthRequestHandler(app);
}

/**
* Get the project configuration.
*
* @returns A promise fulfilled with the project configuration.
*/
public getProjectConfig(): Promise<ProjectConfig> {
return this.authRequestHandler.getProjectConfig()
.then((response: ProjectConfigServerResponse) => {
return new ProjectConfig(response);
})
}
/**
* Updates an existing project configuration.
*
* @param projectConfigOptions - The properties to update on the project.
*
* @returns A promise fulfilled with the update project config.
*/
public updateProjectConfig(projectConfigOptions: UpdateProjectConfigRequest): Promise<ProjectConfig> {
return this.authRequestHandler.updateProjectConfig(projectConfigOptions)
.then((response: ProjectConfigServerResponse) => {
return new ProjectConfig(response);
})
}
}
Loading

0 comments on commit c01f7fb

Please sign in to comment.