Skip to content

Commit

Permalink
feat: Security Rules Management API (#645)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
hiranya911 authored Sep 18, 2019
1 parent cf8b2fb commit 0b2082f
Show file tree
Hide file tree
Showing 14 changed files with 2,735 additions and 1 deletion.
14 changes: 14 additions & 0 deletions docgen/content-sources/node/toc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,20 @@ toc:
- title: "ShaCertificate"
path: /docs/reference/admin/node/admin.projectManagement.ShaCertificate

- title: "admin.securityRules"
path: /docs/reference/admin/node/admin.securityRules
section:
- title: "RulesFile"
path: /docs/reference/admin/node/admin.securityRules.RulesFile
- title: "Ruleset"
path: /docs/reference/admin/node/admin.securityRules.Ruleset
- title: "RulesetMetadata"
path: /docs/reference/admin/node/admin.securityRules.RulesetMetadata
- title: "RulesetMetadataList"
path: /docs/reference/admin/node/admin.securityRules.RulesetMetadataList
- title: "SecurityRules"
path: /docs/reference/admin/node/admin.securityRules.SecurityRules

- title: "admin.storage"
path: /docs/reference/admin/node/admin.storage
section:
Expand Down
14 changes: 14 additions & 0 deletions src/firebase-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {Firestore} from '@google-cloud/firestore';
import {FirestoreService} from './firestore/firestore';
import {InstanceId} from './instance-id/instance-id';
import {ProjectManagement} from './project-management/project-management';
import {SecurityRules} from './security-rules/security-rules';

import {Agent} from 'http';

Expand Down Expand Up @@ -366,6 +367,19 @@ export class FirebaseApp {
});
}

/**
* Returns the SecurityRules service instance associated with this app.
*
* @return {SecurityRules} The SecurityRules service instance of this app.
*/
public securityRules(): SecurityRules {
return this.ensureService_('security-rules', () => {
const securityRulesService: typeof SecurityRules =
require('./security-rules/security-rules').SecurityRules;
return new securityRulesService(this);
});
}

/**
* Returns the name of the FirebaseApp instance.
*
Expand Down
13 changes: 13 additions & 0 deletions src/firebase-namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {Database} from '@firebase/database';
import {Firestore} from '@google-cloud/firestore';
import {InstanceId} from './instance-id/instance-id';
import {ProjectManagement} from './project-management/project-management';
import { SecurityRules } from './security-rules/security-rules';

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

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

/**
* Gets the `SecurityRules` service namespace. The returned namespace can be used to get the
* `SecurityRules` service for the default app or an explicitly specified app.
*/
get securityRules(): FirebaseServiceNamespace<SecurityRules> {
const fn: FirebaseServiceNamespace<SecurityRules> = (app?: FirebaseApp) => {
return this.ensureApp(app).securityRules();
};
const securityRules = require('./security-rules/security-rules').SecurityRules;
return Object.assign(fn, {SecurityRules: securityRules});
}

/**
* Initializes the FirebaseApp instance.
*
Expand Down
222 changes: 222 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,37 @@ declare namespace admin {
* `ProjectManagement` service associated with the provided app.
*/
function projectManagement(app?: admin.app.App): admin.projectManagement.ProjectManagement;

/**
* Gets the {@link admin.securityRules.SecurityRules
* `SecurityRules`} service for the default app or a given app.
*
* `admin.securityRules()` can be called with no arguments to access the
* default app's {@link admin.securityRules.SecurityRules
* `SecurityRules`} service, or as `admin.securityRules(app)` to access
* the {@link admin.securityRules.SecurityRules `SecurityRules`}
* service associated with a specific app.
*
* @example
* ```javascript
* // Get the SecurityRules service for the default app
* var defaultSecurityRules = admin.securityRules();
* ```
*
* @example
* ```javascript
* // Get the SecurityRules service for a given app
* var otherSecurityRules = admin.securityRules(otherApp);
* ```
*
* @param app Optional app to return the `SecurityRules` service
* for. If not provided, the default `SecurityRules` service
* is returned.
* @return The default `SecurityRules` service if no app is provided, or the
* `SecurityRules` service associated with the provided app.
*/
function securityRules(app?: admin.app.App): admin.securityRules.SecurityRules;

function initializeApp(options?: admin.AppOptions, name?: string): admin.app.App;
}

Expand Down Expand Up @@ -423,6 +454,7 @@ declare namespace admin.app {
instanceId(): admin.instanceId.InstanceId;
messaging(): admin.messaging.Messaging;
projectManagement(): admin.projectManagement.ProjectManagement;
securityRules(): admin.securityRules.SecurityRules;
storage(): admin.storage.Storage;

/**
Expand Down Expand Up @@ -5460,6 +5492,196 @@ declare namespace admin.projectManagement {
}
}

declare namespace admin.securityRules {
/**
* A source file containing some Firebase security rules. The content includes raw
* source code including text formatting, indentation and comments. Use the
* [`securityRules.createRulesFileFromSource()`](admin.securityRules.SecurityRules#createRulesFileFromSource)
* method to create new instances of this type.
*/
interface RulesFile {
readonly name: string;
readonly content: string;
}

/**
* Required metadata associated with a ruleset.
*/
interface RulesetMetadata {
/**
* Name of the `Ruleset` as a short string. This can be directly passed into APIs
* like [`securityRules.getRuleset()`](admin.securityRules.SecurityRules#getRuleset)
* and [`securityRules.deleteRuleset()`](admin.securityRules.SecurityRules#deleteRuleset).
*/
readonly name: string;

/**
* Creation time of the `Ruleset` as a UTC timestamp string.
*/
readonly createTime: string;
}

/**
* A set of Firebase security rules.
*/
interface Ruleset extends RulesetMetadata {
readonly source: RulesFile[];
}

interface RulesetMetadataList {
/**
* A batch of ruleset metadata.
*/
readonly rulesets: RulesetMetadata[];

/**
* The next page token if available. This is needed to retrieve the next batch.
*/
readonly nextPageToken?: string;
}

/**
* The Firebase `SecurityRules` service interface.
*
* Do not call this constructor directly. Instead, use
* [`admin.securityRules()`](admin.securityRules#securityRules).
*/
interface SecurityRules {
app: admin.app.App;

/**
* Creates a {@link admin.securityRules.RulesFile `RuleFile`} with the given name
* and source. Throws an error if any of the arguments are invalid. This is a local
* operation, and does not involve any network API calls.
*
* @example
* ```javascript
* const source = '// Some rules source';
* const rulesFile = admin.securityRules().createRulesFileFromSource(
* 'firestore.rules', source);
* ```
*
* @param name Name to assign to the rules file. This is usually a short file name that
* helps identify the file in a ruleset.
* @param source Contents of the rules file.
* @return A new rules file instance.
*/
createRulesFileFromSource(name: string, source: string | Buffer): RulesFile;

/**
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
* {@link admin.securityRules.RulesFile `RuleFile`}.
*
* @param file Rules file to include in the new `Ruleset`.
* @returns A promise that fulfills with the newly created `Ruleset`.
*/
createRuleset(file: RulesFile): Promise<Ruleset>;

/**
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} identified by the given
* name. The input name should be the short name string without the project ID
* prefix. For example, to retrieve the `projects/project-id/rulesets/my-ruleset`,
* pass the short name "my-ruleset". Rejects with a `not-found` error if the
* specified `Ruleset` cannot be found.
*
* @param name Name of the `Ruleset` to retrieve.
* @return A promise that fulfills with the specified `Ruleset`.
*/
getRuleset(name: string): Promise<Ruleset>;

/**
* Deletes the {@link admin.securityRules.Ruleset `Ruleset`} identified by the given
* name. The input name should be the short name string without the project ID
* prefix. For example, to delete the `projects/project-id/rulesets/my-ruleset`,
* pass the short name "my-ruleset". Rejects with a `not-found` error if the
* specified `Ruleset` cannot be found.
*
* @param name Name of the `Ruleset` to delete.
* @return A promise that fulfills when the `Ruleset` is deleted.
*/
deleteRuleset(name: string): Promise<void>;

/**
* Retrieves a page of ruleset metadata.
*
* @param pageSize The page size, 100 if undefined. This is also the maximum allowed
* limit.
* @param nextPageToken The next page token. If not specified, returns rulesets
* starting without any offset.
* @return A promise that fulfills with a page of rulesets.
*/
listRulesetMetadata(
pageSize?: number, nextPageToken?: string): Promise<RulesetMetadataList>;

/**
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} currently applied to
* Cloud Firestore. Rejects with a `not-found` error if no ruleset is applied
* on Firestore.
*
* @return A promise that fulfills with the Firestore ruleset.
*/
getFirestoreRuleset(): Promise<Ruleset>;

/**
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
* source, and applies it to Cloud Firestore.
*
* @param source Rules source to apply.
* @return A promise that fulfills when the ruleset is created and released.
*/
releaseFirestoreRulesetFromSource(source: string | Buffer): Promise<Ruleset>;

/**
* Applies the specified {@link admin.securityRules.Ruleset `Ruleset`} ruleset
* to Cloud Firestore.
*
* @param ruleset Name of the ruleset to apply or a `RulesetMetadata` object
* containing the name.
* @return A promise that fulfills when the ruleset is released.
*/
releaseFirestoreRuleset(ruleset: string | RulesetMetadata): Promise<void>;

/**
* Gets the {@link admin.securityRules.Ruleset `Ruleset`} currently applied to a
* Cloud Storage bucket. Rejects with a `not-found` error if no ruleset is applied
* on the bucket.
*
* @param bucket Optional name of the Cloud Storage bucket to be retrieved. If not
* specified, retrieves the ruleset applied on the default bucket configured via
* `AppOptions`.
* @return A promise that fulfills with the Cloud Storage ruleset.
*/
getStorageRuleset(bucket?: string): Promise<Ruleset>;

/**
* Creates a new {@link admin.securityRules.Ruleset `Ruleset`} from the given
* source, and applies it to a Cloud Storage bucket.
*
* @param source Rules source to apply.
* @param bucket Optional name of the Cloud Storage bucket to apply the rules on. If
* not specified, applies the ruleset on the default bucket configured via
* {@link admin.AppOptions `AppOptions`}.
* @return A promise that fulfills when the ruleset is created and released.
*/
releaseStorageRulesetFromSource(
source: string | Buffer, bucket?: string): Promise<Ruleset>;

/**
* Applies the specified {@link admin.securityRules.Ruleset `Ruleset`} ruleset
* to a Cloud Storage bucket.
*
* @param ruleset Name of the ruleset to apply or a `RulesetMetadata` object
* containing the name.
* @param bucket Optional name of the Cloud Storage bucket to apply the rules on. If
* not specified, applies the ruleset on the default bucket configured via
* {@link admin.AppOptions `AppOptions`}.
* @return A promise that fulfills when the ruleset is released.
*/
releaseStorageRuleset(
ruleset: string | RulesetMetadata, bucket?: string): Promise<void>;
}
}

declare module 'firebase-admin' {
}

Expand Down
Loading

0 comments on commit 0b2082f

Please sign in to comment.