Skip to content

Commit 0b2082f

Browse files
authored
feat: Security Rules Management API (#645)
* Implementing the Firebase Security Rules API (#604) * Implementing the Firebase Security Rules API * More argument validation and assertions * Cleaning up the rules impl * Internal API renamed * Fixing a typo in a comment * Implemented createRulesFileFromSource() and createRuleset() APIs (#607) * Implementing the Firebase Security Rules API * More argument validation and assertions * Adding the rest of the CRUD operations for rulesets * Cleaning up the rules impl * Cleaned up tests * Adding some missing comments * Removing support for multiple rules files in create() * Implemented the deleteRuleset() API (#609) * Added deleteRuleset API * Merged with source * Implemented the API for releasing rulesets (#610) * Implemented the API for releasing rulesets * Removed createRelease logic * Updated comment * Added the getStorageRuleset() API (#613) * Implemented the API for releasing rulesets * Removed createRelease logic * Added getStorageRules() API * Removed some redundant tests * Implementing the remaining releaseRuleset APIs (#616) * Implemented the listRulesetMetadata() API (#622) * Adding the rules API to the public API surface (#625) * Added rules API to the public admin namespace * Updated docs * Addressing comments regarding the d.ts file * Updated App typings * Rules integration tests (#633) * Rules integration tests * Refactored by adding some helper methods * Cleaned up some conditionals * Added verification for deleteRuleset test * Renamed tempRulesets * Handling ruleset limit exceeded error (#636) * Fixing alignment of an annotation * Updated comments
1 parent cf8b2fb commit 0b2082f

14 files changed

+2735
-1
lines changed

docgen/content-sources/node/toc.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,20 @@ toc:
196196
- title: "ShaCertificate"
197197
path: /docs/reference/admin/node/admin.projectManagement.ShaCertificate
198198

199+
- title: "admin.securityRules"
200+
path: /docs/reference/admin/node/admin.securityRules
201+
section:
202+
- title: "RulesFile"
203+
path: /docs/reference/admin/node/admin.securityRules.RulesFile
204+
- title: "Ruleset"
205+
path: /docs/reference/admin/node/admin.securityRules.Ruleset
206+
- title: "RulesetMetadata"
207+
path: /docs/reference/admin/node/admin.securityRules.RulesetMetadata
208+
- title: "RulesetMetadataList"
209+
path: /docs/reference/admin/node/admin.securityRules.RulesetMetadataList
210+
- title: "SecurityRules"
211+
path: /docs/reference/admin/node/admin.securityRules.SecurityRules
212+
199213
- title: "admin.storage"
200214
path: /docs/reference/admin/node/admin.storage
201215
section:

src/firebase-app.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {Firestore} from '@google-cloud/firestore';
3030
import {FirestoreService} from './firestore/firestore';
3131
import {InstanceId} from './instance-id/instance-id';
3232
import {ProjectManagement} from './project-management/project-management';
33+
import {SecurityRules} from './security-rules/security-rules';
3334

3435
import {Agent} from 'http';
3536

@@ -366,6 +367,19 @@ export class FirebaseApp {
366367
});
367368
}
368369

370+
/**
371+
* Returns the SecurityRules service instance associated with this app.
372+
*
373+
* @return {SecurityRules} The SecurityRules service instance of this app.
374+
*/
375+
public securityRules(): SecurityRules {
376+
return this.ensureService_('security-rules', () => {
377+
const securityRulesService: typeof SecurityRules =
378+
require('./security-rules/security-rules').SecurityRules;
379+
return new securityRulesService(this);
380+
});
381+
}
382+
369383
/**
370384
* Returns the name of the FirebaseApp instance.
371385
*

src/firebase-namespace.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {Database} from '@firebase/database';
3434
import {Firestore} from '@google-cloud/firestore';
3535
import {InstanceId} from './instance-id/instance-id';
3636
import {ProjectManagement} from './project-management/project-management';
37+
import { SecurityRules } from './security-rules/security-rules';
3738

3839
import * as validator from './utils/validator';
3940

@@ -419,6 +420,18 @@ export class FirebaseNamespace {
419420
return Object.assign(fn, {ProjectManagement: projectManagement});
420421
}
421422

423+
/**
424+
* Gets the `SecurityRules` service namespace. The returned namespace can be used to get the
425+
* `SecurityRules` service for the default app or an explicitly specified app.
426+
*/
427+
get securityRules(): FirebaseServiceNamespace<SecurityRules> {
428+
const fn: FirebaseServiceNamespace<SecurityRules> = (app?: FirebaseApp) => {
429+
return this.ensureApp(app).securityRules();
430+
};
431+
const securityRules = require('./security-rules/security-rules').SecurityRules;
432+
return Object.assign(fn, {SecurityRules: securityRules});
433+
}
434+
422435
/**
423436
* Initializes the FirebaseApp instance.
424437
*

src/index.d.ts

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,37 @@ declare namespace admin {
363363
* `ProjectManagement` service associated with the provided app.
364364
*/
365365
function projectManagement(app?: admin.app.App): admin.projectManagement.ProjectManagement;
366+
367+
/**
368+
* Gets the {@link admin.securityRules.SecurityRules
369+
* `SecurityRules`} service for the default app or a given app.
370+
*
371+
* `admin.securityRules()` can be called with no arguments to access the
372+
* default app's {@link admin.securityRules.SecurityRules
373+
* `SecurityRules`} service, or as `admin.securityRules(app)` to access
374+
* the {@link admin.securityRules.SecurityRules `SecurityRules`}
375+
* service associated with a specific app.
376+
*
377+
* @example
378+
* ```javascript
379+
* // Get the SecurityRules service for the default app
380+
* var defaultSecurityRules = admin.securityRules();
381+
* ```
382+
*
383+
* @example
384+
* ```javascript
385+
* // Get the SecurityRules service for a given app
386+
* var otherSecurityRules = admin.securityRules(otherApp);
387+
* ```
388+
*
389+
* @param app Optional app to return the `SecurityRules` service
390+
* for. If not provided, the default `SecurityRules` service
391+
* is returned.
392+
* @return The default `SecurityRules` service if no app is provided, or the
393+
* `SecurityRules` service associated with the provided app.
394+
*/
395+
function securityRules(app?: admin.app.App): admin.securityRules.SecurityRules;
396+
366397
function initializeApp(options?: admin.AppOptions, name?: string): admin.app.App;
367398
}
368399

@@ -423,6 +454,7 @@ declare namespace admin.app {
423454
instanceId(): admin.instanceId.InstanceId;
424455
messaging(): admin.messaging.Messaging;
425456
projectManagement(): admin.projectManagement.ProjectManagement;
457+
securityRules(): admin.securityRules.SecurityRules;
426458
storage(): admin.storage.Storage;
427459

428460
/**
@@ -5460,6 +5492,196 @@ declare namespace admin.projectManagement {
54605492
}
54615493
}
54625494

5495+
declare namespace admin.securityRules {
5496+
/**
5497+
* A source file containing some Firebase security rules. The content includes raw
5498+
* source code including text formatting, indentation and comments. Use the
5499+
* [`securityRules.createRulesFileFromSource()`](admin.securityRules.SecurityRules#createRulesFileFromSource)
5500+
* method to create new instances of this type.
5501+
*/
5502+
interface RulesFile {
5503+
readonly name: string;
5504+
readonly content: string;
5505+
}
5506+
5507+
/**
5508+
* Required metadata associated with a ruleset.
5509+
*/
5510+
interface RulesetMetadata {
5511+
/**
5512+
* Name of the `Ruleset` as a short string. This can be directly passed into APIs
5513+
* like [`securityRules.getRuleset()`](admin.securityRules.SecurityRules#getRuleset)
5514+
* and [`securityRules.deleteRuleset()`](admin.securityRules.SecurityRules#deleteRuleset).
5515+
*/
5516+
readonly name: string;
5517+
5518+
/**
5519+
* Creation time of the `Ruleset` as a UTC timestamp string.
5520+
*/
5521+
readonly createTime: string;
5522+
}
5523+
5524+
/**
5525+
* A set of Firebase security rules.
5526+
*/
5527+
interface Ruleset extends RulesetMetadata {
5528+
readonly source: RulesFile[];
5529+
}
5530+
5531+
interface RulesetMetadataList {
5532+
/**
5533+
* A batch of ruleset metadata.
5534+
*/
5535+
readonly rulesets: RulesetMetadata[];
5536+
5537+
/**
5538+
* The next page token if available. This is needed to retrieve the next batch.
5539+
*/
5540+
readonly nextPageToken?: string;
5541+
}
5542+
5543+
/**
5544+
* The Firebase `SecurityRules` service interface.
5545+
*
5546+
* Do not call this constructor directly. Instead, use
5547+
* [`admin.securityRules()`](admin.securityRules#securityRules).
5548+
*/
5549+
interface SecurityRules {
5550+
app: admin.app.App;
5551+
5552+
/**
5553+
* Creates a {@link admin.securityRules.RulesFile `RuleFile`} with the given name
5554+
* and source. Throws an error if any of the arguments are invalid. This is a local
5555+
* operation, and does not involve any network API calls.
5556+
*
5557+
* @example
5558+
* ```javascript
5559+
* const source = '// Some rules source';
5560+
* const rulesFile = admin.securityRules().createRulesFileFromSource(
5561+
* 'firestore.rules', source);
5562+
* ```
5563+
*
5564+
* @param name Name to assign to the rules file. This is usually a short file name that
5565+
* helps identify the file in a ruleset.
5566+
* @param source Contents of the rules file.
5567+
* @return A new rules file instance.
5568+
*/
5569+
createRulesFileFromSource(name: string, source: string | Buffer): RulesFile;
5570+
5571+
/**
5572+
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
5573+
* {@link admin.securityRules.RulesFile `RuleFile`}.
5574+
*
5575+
* @param file Rules file to include in the new `Ruleset`.
5576+
* @returns A promise that fulfills with the newly created `Ruleset`.
5577+
*/
5578+
createRuleset(file: RulesFile): Promise<Ruleset>;
5579+
5580+
/**
5581+
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} identified by the given
5582+
* name. The input name should be the short name string without the project ID
5583+
* prefix. For example, to retrieve the `projects/project-id/rulesets/my-ruleset`,
5584+
* pass the short name "my-ruleset". Rejects with a `not-found` error if the
5585+
* specified `Ruleset` cannot be found.
5586+
*
5587+
* @param name Name of the `Ruleset` to retrieve.
5588+
* @return A promise that fulfills with the specified `Ruleset`.
5589+
*/
5590+
getRuleset(name: string): Promise<Ruleset>;
5591+
5592+
/**
5593+
* Deletes the {@link admin.securityRules.Ruleset `Ruleset`} identified by the given
5594+
* name. The input name should be the short name string without the project ID
5595+
* prefix. For example, to delete the `projects/project-id/rulesets/my-ruleset`,
5596+
* pass the short name "my-ruleset". Rejects with a `not-found` error if the
5597+
* specified `Ruleset` cannot be found.
5598+
*
5599+
* @param name Name of the `Ruleset` to delete.
5600+
* @return A promise that fulfills when the `Ruleset` is deleted.
5601+
*/
5602+
deleteRuleset(name: string): Promise<void>;
5603+
5604+
/**
5605+
* Retrieves a page of ruleset metadata.
5606+
*
5607+
* @param pageSize The page size, 100 if undefined. This is also the maximum allowed
5608+
* limit.
5609+
* @param nextPageToken The next page token. If not specified, returns rulesets
5610+
* starting without any offset.
5611+
* @return A promise that fulfills with a page of rulesets.
5612+
*/
5613+
listRulesetMetadata(
5614+
pageSize?: number, nextPageToken?: string): Promise<RulesetMetadataList>;
5615+
5616+
/**
5617+
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} currently applied to
5618+
* Cloud Firestore. Rejects with a `not-found` error if no ruleset is applied
5619+
* on Firestore.
5620+
*
5621+
* @return A promise that fulfills with the Firestore ruleset.
5622+
*/
5623+
getFirestoreRuleset(): Promise<Ruleset>;
5624+
5625+
/**
5626+
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
5627+
* source, and applies it to Cloud Firestore.
5628+
*
5629+
* @param source Rules source to apply.
5630+
* @return A promise that fulfills when the ruleset is created and released.
5631+
*/
5632+
releaseFirestoreRulesetFromSource(source: string | Buffer): Promise<Ruleset>;
5633+
5634+
/**
5635+
* Applies the specified {@link admin.securityRules.Ruleset `Ruleset`} ruleset
5636+
* to Cloud Firestore.
5637+
*
5638+
* @param ruleset Name of the ruleset to apply or a `RulesetMetadata` object
5639+
* containing the name.
5640+
* @return A promise that fulfills when the ruleset is released.
5641+
*/
5642+
releaseFirestoreRuleset(ruleset: string | RulesetMetadata): Promise<void>;
5643+
5644+
/**
5645+
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} currently applied to a
5646+
* Cloud Storage bucket. Rejects with a `not-found` error if no ruleset is applied
5647+
* on the bucket.
5648+
*
5649+
* @param bucket Optional name of the Cloud Storage bucket to be retrieved. If not
5650+
* specified, retrieves the ruleset applied on the default bucket configured via
5651+
* `AppOptions`.
5652+
* @return A promise that fulfills with the Cloud Storage ruleset.
5653+
*/
5654+
getStorageRuleset(bucket?: string): Promise<Ruleset>;
5655+
5656+
/**
5657+
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
5658+
* source, and applies it to a Cloud Storage bucket.
5659+
*
5660+
* @param source Rules source to apply.
5661+
* @param bucket Optional name of the Cloud Storage bucket to apply the rules on. If
5662+
* not specified, applies the ruleset on the default bucket configured via
5663+
* {@link admin.AppOptions `AppOptions`}.
5664+
* @return A promise that fulfills when the ruleset is created and released.
5665+
*/
5666+
releaseStorageRulesetFromSource(
5667+
source: string | Buffer, bucket?: string): Promise<Ruleset>;
5668+
5669+
/**
5670+
* Applies the specified {@link admin.securityRules.Ruleset `Ruleset`} ruleset
5671+
* to a Cloud Storage bucket.
5672+
*
5673+
* @param ruleset Name of the ruleset to apply or a `RulesetMetadata` object
5674+
* containing the name.
5675+
* @param bucket Optional name of the Cloud Storage bucket to apply the rules on. If
5676+
* not specified, applies the ruleset on the default bucket configured via
5677+
* {@link admin.AppOptions `AppOptions`}.
5678+
* @return A promise that fulfills when the ruleset is released.
5679+
*/
5680+
releaseStorageRuleset(
5681+
ruleset: string | RulesetMetadata, bucket?: string): Promise<void>;
5682+
}
5683+
}
5684+
54635685
declare module 'firebase-admin' {
54645686
}
54655687

0 commit comments

Comments
 (0)