Firebase Update

This commit is contained in:
Lukas Nowy
2018-12-22 23:30:39 +01:00
parent befb44764d
commit acffe619b3
11523 changed files with 1614327 additions and 930246 deletions

544
express-server/node_modules/firebase-admin/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,544 @@
# Unreleased
-
# v6.4.0
- [added] `messaging.Aps` type now supports configuring a critical sound.
A new `messaging.CriticalSound` type has been introduced for this purpose.
- [added] `messaging.AndroidNotification` type now supports `channel_id`.
- [added] `AppOptions` now accepts an optional `http.Agent` object. The
`http.Agent` specified via this API is used when the SDK makes backend
HTTP calls. This can be used when it is required to deploy the Admin SDK
behind a proxy.
- [added] `admin.credential.cert()`, `admin.credential.applicationDefault()`,
and `admin.credential.refreshToken()` methods now accept an `http.Agent`
as an optional argument. If specified, the `http.Agent` will be used
when calling Google backend servers to fetch OAuth2 access tokens.
- [added] `messaging.AndroidNotification`type now supports channel_id.
# v6.3.0
- [added] A new `ProjectManagement` service, which includes the ability to
create, list, and get details about Android and iOS apps associated with your
Firebase Project.
- [added] `messaging.ApsAlert` type now supports subtitle in its payload.
# v6.2.0
- [added] Added the email action link generation APIs for creating links for
password reset, email verification and email link sign-in via
`auth.generatePasswordResetLink()`, `auth.generateEmailVerificationLink()`
and `auth.generateSignInWithEmailLink()`.
- [changed] Upgraded Cloud Firestore client to v0.19.0.
- [added] Exposed the `Transaction` type from the `admin.firestore` namespace.
- [fixed] Fixing error handling in FCM. The SDK now checks the key
`type.googleapis.com/google.firebase.fcm.v1.FcmError` to set error code.
# v6.1.0
- [changed] Upgraded Cloud Firestore client to v0.18.0.
- [added] Exposed the `CollectionReference`, `WriteBatch`, `WriteResult` and
`QueryDocumentSnapshot` types from the `admin.firestore` namespace.
# v6.0.0
- [changed] Upgraded Cloud Firestore client to v0.16.0.
- [changed] Firestore and Storage client libraries are now defined as optional
dependencies.
- [changed] Dropped support for Node.js 4.
# v5.13.1
- [changed] Upgraded Cloud Firestore client to v0.15.4.
- [changed] Exposed the Firestore `Timestamp` type from the `admin.firestore`
namespace.
# v5.13.0
- [changed] Admin SDK can now create custom tokens without being initialized
with service account credentials. When a service account private key is not
available, the SDK uses the remote IAM service to sign JWTs in the cloud.
- [changed] Updated the typings of the `admin.database.Query.once()`
method to return a more specific type.
- [changed] Admin SDK can now read the Firebase/GCP project ID from both
`GCLOUD_PROJECT` and `GOOGLE_CLOUD_PROJECT` environment variables.
- [changed] Updated the `WebpushNotification` typings to match
[the current API](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#webpushconfig).
- [changed] Upgraded Cloud Firestore client to v0.15.2.
# v5.12.1
- [changed] Admin SDK now lazy loads all child namespaces and certain heavy
dependencies for faster load times. This change also ensures that only
the sources for namespaces that are actually used get loaded into the
Node.js process.
- [changed] Upgraded Cloud Firestore client to v0.14.0.
# v5.12.0
- [feature] Added the session cookie management APIs for creating and verifying
session cookies, via `auth.createSessionCookie()` and
`auth.verifySessionCookie()`.
- [added] Added the `mutableContent` optional field to the `Aps` type of
the FCM API.
- [added] Added the support for specifying arbitrary custom key-value
fields in the `Aps` type.
# v5.11.0
- [changed] Added the `auth.importUsers()` method for importing users to
Firebase Auth in bulk.
# v5.10.0
- [changed] Upgraded Realtime Database client to v0.2.0. With this upgrade
developers can call the `admin.database().ref()` method with another
`Reference` instance as the argument.
- [changed] Upgraded Cloud Firestore client to v0.13.0.
# v5.9.1
- [changed] The `admin.initializeApp()` method can now be invoked without an
explicit `credential` option. In that case the SDK will get initialized with
Google application default credentials.
- [changed] Upgraded Realtime Database client to v0.1.11.
- [changed] Modified the Realtime Database client integration to report the
correct user agent header.
- [changed] Upgraded Cloud Firestire client to v0.12.0.
- [changed] Improved error handling in FCM by mapping more server-side errors
to client-side error codes.
# v5.9.0
- [added] Added the `messaging.send()` method and the new `Message` type for
sending Cloud Messaging notifications via the
[new FCM REST endpoint](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages).
# v5.8.2
- [changed] Exposed `admin.firestore.DocumentReference` and
`admin.firestore.DocumentSnapshot` types from the Admin SDK typings.
- [changed] Upgraded Firestore dependency version to
[0.11.2](https://github.com/googleapis/nodejs-firestore/releases/tag/v0.11.2).
# v5.8.1
- [changed] Upgraded Firestore dependency version from 0.10.0 to 0.11.1.
This includes several bug fixes in Cloud Firestore.
# v5.8.0
### Initialization
- [added] The [`admin.initializeApp()`](https://firebase.google.com/docs/reference/admin/node/admin#.initializeApp)
method can now be invoked without any arguments. This initializes an app
using Google Application Default Credentials, and other
[`AppOptions`](https://firebase.google.com/docs/reference/admin/node/admin.app.AppOptions) loaded from
the `FIREBASE_CONFIG` environment variable.
### Authentication
- [changed] Upgraded the `jsonwebtoken` library to 8.1.0.
# v5.7.0
### Authentication
- [added] A new [`revokeRefreshTokens()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#revokeRefreshTokens)
method for revoking refresh tokens issued to a user.
- [added] The [`verifyIdToken()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#verifyIdToken)
method now accepts an optional `checkRevoked` argument, which can be used to
check if a given ID token has been revoked.
# v5.6.0
- [added] A new [`admin.instanceId()`](https://firebase.google.com/docs/reference/admin/node/admin.instanceId)
API that facilitates deleting instance IDs and associated user data from
Firebase projects.
- [changed] Updated the TypeScript typings for `admin.AppOptions` to reflect the
introduction of the `projectId` option.
- [changed] Removed some unused third party dependencies.
# v5.5.1
### Cloud Firestore
- [changed] Upgraded the Cloud Firestore client to the latest available
version, which adds input validation to several operations, and retry logic
to handle network errors.
### Realtime Database
- [changed] Fixed an issue in the TypeScript typings of the Realtime Database API.
# v5.5.0
### Realtime Database
- [added] [`app.database()`](https://firebase.google.com/docs/reference/admin/node/admin.app.App#database)
method now optionally accepts a database URL. This feature can be used to
access multiple Realtime Database instances from the same app.
- [changed] Upgraded the Realtime Database client to the latest available
version.
### Cloud Firestore
- [changed] Upgraded the Cloud Firestore client to the latest available
version.
# v5.4.3
- [changed] Fixed a regression in module loading that prevented using
the Admin SDK in environments like AWS Lambda. This regression was
introduced in the 5.4.0 release, which added a new dependency to Firestore
and gRPC. This fix lazily loads Firestore and gRPC, thus enabling
Admin SDK usage in the affected environments as long as no explicit
attempts are made to use the Firestore API.
# v5.4.2
- [changed] Upgraded the Cloud Firestore client dependency to 0.8.2, which
resolves an issue with saving objects with nested document references.
# v5.4.1
- [changed] Upgraded the Firestore client dependency to 0.8.1, which resolves
the installation issues reported in the Yarn environment.
# v5.4.0
- [added] A new [`admin.firestore()`](https://firebase.google.com/docs/reference/admin/node/admin.firestore)
API that facilitates accessing [Google Cloud Firestore](https://firebase.google.com/docs/firestore)
databases using the
[`@google-cloud/firestore`](https://cloud.google.com/nodejshttps://firebase.google.com/docs/reference/firestore/latest/)
library. See [Set Up Your Node.js App for Cloud Firestore](https://firebase.google.com/docs/firestore/server/setup-node)
to get started.
# v5.3.0
- [changed] SDK now retries outbound HTTP calls on all low-level I/O errors.
### Authentication
- [added] A new [`setCustomUserClaims()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#setCustomUserClaims)
method for setting custom claims on user accounts. Custom claims set via this
method become available on the ID tokens of the corresponding users when they
sign in. To learn how to use this API for controlling access to Firebase
resources, see
[Control Access with Custom Claims and Security Rules](https://firebase.google.com/docs/auth/admin/custom-claims).
- [added] A new [`listUsers()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#listUsers)
method for listing all the users in a Firebase project in batches.
### Storage
- [changed] Declared a more concrete TypeScript return type (`Bucket`) for the
[`bucket()`](https://firebase.google.com/docs/reference/admin/node/admin.storage.Storage#bucket) method
in the Storage API.
# v5.2.1
- [changed] A bug in the TypeScript type declarations that come bundled with the
SDK (`index.d.ts`) has been fixed.
# v5.2.0
- [added] A new [Cloud Storage API](https://firebase.google.com/docs/reference/admin/node/admin.storage)
that facilitates accessing Google Cloud Storage buckets using the
[`@google-cloud/storage`](https://googlecloudplatform.github.io/google-cloud-node/#https://firebase.google.com/docs/storage/latest/storage)
library.
### Authentication
- [changed] New type definitions for the arguments of `createUser()` and
`updateUser()` methods.
### Cloud Messaging
- [changed] Redefined the arguments of `sendToDevice()` using intersection
instead of overloading.
# v5.1.0
### Authentication
- [added] Added the method
[`getUserByPhoneNumber()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getUserByPhoneNumber)
to the [`admin.auth`](https://firebase.google.com/docs/reference/admin/node/admin.auth) interface. This method
enables retrieving user profile information by a phone number.
- [added] [`createUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createUser)
and [`updateUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#updateUser) methods
now accept a `phoneNumber` property, which can be used to create users with a phone
number field and/or update the phone number associated with a user.
- [added] Added the `phoneNumber` field to
[`admin.auth.UserRecord`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserRecord),
which exposes the phone number associated with a user account.
- [added] Added the `phoneNumber` field to
[`admin.auth.UserInfo`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserInfo),
which exposes the phone number associated with a user account by a linked
identity provider.
# v5.0.1
- [changed] Improved the error messages thrown in the case of network and RPC
errors. These errors now include outgoing HTTP request details that make
it easier to localize and debug issues.
### Authentication
- [changed] Implemented support in the user management API for handling photo
URLs with special characters.
# v5.0.0
### Initialization
- [changed] The deprecated `serviceAccount` property in the
[`admin.App.Options`](https://firebase.google.com/docs/reference/admin/node/admin.app.AppOptions)
type has been removed in favor of the `credential` property.
- [changed] Initializing the SDK without setting a credential
results in an exception.
- [changed] Initializing the SDK with a malformed private key string
results in an exception.
### Authentication
- [changed] `createdAt` and `lastSignedInAt` properties in
[`admin.auth.UserMetadata`](https://firebase.google.com/docs/reference/admin/node/admin.auth.UserMetadata)
have been renamed to `creationTime` and `lastSignInTime`. Also these
properties now provide UTC formatted strings instead of `Date` values.
# v4.2.1
- [changed] Updated the SDK to periodically refresh the OAuth access token
internally used by `FirebaseApp`. This reduces the number of authentication
failures encountered at runtime by SDK components like Realtime Database.
# v4.2.0
### Cloud Messaging
- [added] Added the methods
[`subscribeToTopic()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#subscribeToTopic)
and
[`unsubscribeFromTopic()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#unsubscribeFromTopic)
to the [`admin.messaging()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging)
service. The new methods allow subscribing to and unsubscribing from {{messaging}}
topics via registration tokens.
# v4.1.4
### Authentication
- [changed] Cleaned up a number of types to improve the log output, thereby
making debugging easier.
### Realtime Database
- [changed] Fixed an issue which could cause infinite loops when using `push()`
with no arguments.
# v4.1.3
- [changed] Fixed incorrect usage of `undefined` - as opposed to `void` - in
several places in the TypeScript typings.
- [changed] Added missing properties to the TypeScript typings for
[`DecodedIdToken`](https://firebase.google.com/docs/reference/admin/node/admin.auth.DecodedIdToken).
- [changed] Fixed issues when using some types with the TypeScript
`strictNullChecks` option enabled.
- [changed] Removed incorrect `admin.Promise` type from the TypeScript typings
in favor of the Node.js built-in `Promise` type, which the SDK actually uses.
- [changed] Added error codes to all app-level errors. All errors in the SDK
now properly implement the
[`FirebaseError`](https://firebase.google.com/docs/reference/admin/node/admin.FirebaseError) interface.
- [changed] Improved error handling when initializing the SDK with a credential
that cannot generate valid access tokens.
- [added] Added new `admin.database.EventType` to the TypeScript typings.
### Realtime Database
- [changed] Improved how the Realtime Database reports errors when provided with
various types of invalid credentials.
# v4.1.2
### Authentication
- [changed] Improved input validation and error messages for all user
management methods.
- [changed]
[`verifyIdToken()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#verifyIdToken)
now works with non-cert credentials, assuming the `GCLOUD_PROJECT` environment
variable is set to your project ID, which is the case when running on Google
infrastructure such as Google App Engine and Google Compute Engine.
### Realtime Database
- [changed] Added `toJSON()` methods to the `DataSnapshot` and `Query` objects
to make them properly JSON-serializable.
### Cloud Messaging
- [changed] Improved response parsing when
[`sendToDevice()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToDevice)
and
[`sendToDeviceGroup()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToDeviceGroup)
are provided with unexpected inputs.
# v4.1.1
- [changed] Added in missing TypeScript typings for the `FirebaseError.toJSON()`
method.
### Authentication
- [changed] Fixed issue with
[`createUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createUser)
which sometimes caused multiple users to share the same email.
# v4.1.0
- [changed] Added in missing TypeScript typings for the `toJSON()` method off
of several objects.
### Cloud Messaging
- [added] A new
[`admin.messaging()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging) service
allows you to send messages through
[Firebase Cloud Messaging](https://firebase.google.com/docs/cloud-messaging/admin/). The new service
includes the
[`sendToDevice()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToDevice),
[`sendToDeviceGroup()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToDeviceGroup),
[`sendToTopic()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToTopic),
and
[`sendToCondition()`](https://firebase.google.com/docs/reference/admin/node/admin.messaging.Messaging#sendToCondition)
methods.
# v4.0.6
### Initialization
- [changed] Fixed an issue which caused importing the library via the ES2015
import syntax (`import * as admin from "firebase-admin"`) to not work
properly.
# v4.0.5
- [changed] TypeScript support has been greatly improved. Typings for the
Realtime Database are now available and all other known issues with incorrect or
incomplete type information have been resolved.
### Initialization
- [changed] Fixed an issue which caused the SDK to appear to hang when provided
with a credential that generated invalid access tokens. The most common cause
of this was using a credential whose access had been revoked. Now, an error
will be logged to the console in this scenario.
### Authentication
- [added] The error message for an `auth/internal-error` error now includes
the raw server response to more easily debug and track down unhandled errors.
- [changed] Fixed an issue that caused an `auth/internal-error` error to be
thrown when calling
[`getUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getUser) or
[`getUserByEmail()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getUserByEmail)
for a user without a creation date.
- [changed] Fixed an issue which caused an `auth/internal-error` error to be
thrown when calling
[`createUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createUser) with
an email that corresponds to an existing user.
- [changed] Fixed an issue which caused an `auth/internal-error` error to be
thrown when calling Authentication methods with a credential with insufficient
permission. Now, an `auth/insufficient-permission` error will be thrown
instead.
# v4.0.4
### Authentication
- [changed] Fixed an issue that caused several Authentication methods to throw
an error when provided with inputs containing Unicode characters.
# v4.0.3
### Initialization
- [changed] Fixed an issue that caused a `null` value for the
`databaseAuthVariableOverride` property to be ignored when passed as part
of the first argument to
[`initializeApp()`](https://firebase.google.com/docs/reference/admin/node/admin#.initializeApp), which
caused the app to still have full admin access. Now, passing this value has
the expected behavior: the app has unauthenticated access to the
Realtime Database, and behaves as if no user is logged into the app.
### Authentication
- [changed] Fixed an issue that caused an `auth/invalid-uid` error to
be thrown for valid `uid` values passed to several Authentication methods.
# v4.0.2
- [added] Improved error messages throughout the Admin Node.js SDK.
- [changed] Upgraded dependencies so that the Admin Node.js SDK no longer
throws warnings for using deprecated `Buffer` APIs in Node.js `7.x.x`.
# v4.0.1
- [changed] Fixed issue which caused the 4.0.0 release to not
include the `README.md` and `npm-shrinkwrap.json` files.
# v4.0.0
- [added] The Admin Node.js SDK (available on npm as `firebase-admin`) is a
new SDK which replaces and expands the admin capabilities of the standard
`firebase` npm module. See
[Add the Firebase Admin SDK to your Server](https://firebase.google.com/docs/admin/setup/) to get
started.
- [issue] This version does not include the `README.md` and
`npm-shrinkwrap.json` files. This was fixed in version 4.0.1.
### Initialization
- [deprecated] The `serviceAccount` property of the options passed as the
first argument to
[`initializeApp()`](https://firebase.google.com/docs/reference/admin/node/admin#.initializeApp) has been
deprecated in favor of a new `credential` property. See
[Initialize the SDK](https://firebase.google.com/docs/admin/setup/#initialize_the_sdk) for more details.
- [added] The new
[`admin.credential.cert()`](https://firebase.google.com/docs/reference/admin/node/admin.credential#.cert)
method allows you to authenticate the SDK with a service account key file.
- [added] The new
[`admin.credential.refreshToken()`](https://firebase.google.com/docs/reference/admin/node/admin.credential#.refreshToken)
method allows you to authenticate the SDK with a Google OAuth2 refresh token.
- [added] The new
[`admin.credential.applicationDefault()`](https://firebase.google.com/docs/reference/admin/node/admin.credential#.applicationDefault)
method allows you to authenticate the SDK with Google Application Default
Credentials.
### Authentication
- [added] A new Admin API for managing your Firebase Authentication users is now
available. This API lets you manage your users without using their existing
credentials, and without worrying about client-side rate limiting. The new
methods included in this API are
[`getUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getUser),
[`getUserByEmail()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#getUserByEmail),
[`createUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createUser),
[`updateUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#updateUser), and
[`deleteUser()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#deleteUser). See
[Manage Users](https://firebase.google.com/docs/auth/admin/manage-users) for more details.
- [changed] The
[`createCustomToken()`](https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createCustomToken)
method is now asynchronous, returning a `Promise<string>` instead of a
`string`.

201
express-server/node_modules/firebase-admin/LICENSE generated vendored Normal file
View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

88
express-server/node_modules/firebase-admin/README.md generated vendored Normal file
View File

@ -0,0 +1,88 @@
[![Build Status](https://travis-ci.org/firebase/firebase-admin-node.svg?branch=master)](https://travis-ci.org/firebase/firebase-admin-node)
# Firebase Admin Node.js SDK
## Table of Contents
* [Overview](#overview)
* [Installation](#installation)
* [Contributing](#contributing)
* [Documentation](#documentation)
* [Supported Environments](#supported-environments)
* [Acknowledgments](#acknowledgments)
* [License](#license)
## Overview
[Firebase](https://firebase.google.com) provides the tools and infrastructure
you need to develop your app, grow your user base, and earn money. The Firebase
Admin Node.js SDK enables access to Firebase services from privileged environments
(such as servers or cloud) in Node.js.
For more information, visit the
[Firebase Admin SDK setup guide](https://firebase.google.com/docs/admin/setup/).
## Installation
The Firebase Admin Node.js SDK is available on npm as `firebase-admin`:
```bash
$ npm install --save firebase-admin
```
To use the module in your application, `require` it from any JavaScript file:
```js
var admin = require("firebase-admin");
```
If you are using ES2015, you can `import` the module instead:
```js
import * as admin from "firebase-admin";
```
## Contributing
Please refer to the [CONTRIBUTING page](./CONTRIBUTING.md) for more information
about how you can contribute to this project. We welcome bug reports, feature
requests, code review feedback, and also pull requests.
## Supported Environments
We support Node.js 6.0 and higher. Please note that the Admin SDK should only
be used in server-side/back-end environments controlled by the app developer.
This includes most server and serverless platforms (both on-premise and in
the cloud). It is not recommended to use the Admin SDK in client-side
environments.
## Documentation
* [Setup Guide](https://firebase.google.com/docs/admin/setup/)
* [Database Guide](https://firebase.google.com/docs/database/admin/start/)
* [Authentication Guide](https://firebase.google.com/docs/auth/admin/)
* [Cloud Messaging Guide](https://firebase.google.com/docs/cloud-messaging/admin/)
* [API Reference](https://firebase.google.com/docs/reference/admin/node/)
* [Release Notes](https://firebase.google.com/support/release-notes/admin/node/)
## Acknowledgments
Thanks to the team at [Casetext](https://casetext.com/) for transferring
ownership of the `firebase-admin` npm module over to the Firebase team
and for their longtime use and support of the Firebase platform.
## License
Firebase Admin Node.js SDK is licensed under the
[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0).
Your use of Firebase is governed by the
[Terms of Service for Firebase Services](https://firebase.google.com/terms/).

View File

@ -0,0 +1,117 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var validator = require("../utils/validator");
var error_1 = require("../utils/error");
/**
* Defines the ActionCodeSettings builder class used to convert the
* ActionCodeSettings object to its corresponding server request.
*/
var ActionCodeSettingsBuilder = /** @class */ (function () {
/**
* ActionCodeSettingsBuilder constructor.
*
* @param {ActionCodeSettings} actionCodeSettings The ActionCodeSettings
* object used to initiliaze this server request builder.
* @constructor
*/
function ActionCodeSettingsBuilder(actionCodeSettings) {
if (!validator.isNonNullObject(actionCodeSettings)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings" must be a non-null object.');
}
if (typeof actionCodeSettings.url === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_CONTINUE_URI);
}
else if (!validator.isURL(actionCodeSettings.url)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONTINUE_URI);
}
this.continueUrl = actionCodeSettings.url;
if (typeof actionCodeSettings.handleCodeInApp !== 'undefined' &&
!validator.isBoolean(actionCodeSettings.handleCodeInApp)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.handleCodeInApp" must be a boolean.');
}
this.canHandleCodeInApp = actionCodeSettings.handleCodeInApp || false;
if (typeof actionCodeSettings.dynamicLinkDomain !== 'undefined' &&
!validator.isNonEmptyString(actionCodeSettings.dynamicLinkDomain)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DYNAMIC_LINK_DOMAIN);
}
this.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
if (typeof actionCodeSettings.iOS !== 'undefined') {
if (!validator.isNonNullObject(actionCodeSettings.iOS)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS" must be a valid non-null object.');
}
else if (typeof actionCodeSettings.iOS.bundleId === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_IOS_BUNDLE_ID);
}
else if (!validator.isNonEmptyString(actionCodeSettings.iOS.bundleId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS.bundleId" must be a valid non-empty string.');
}
this.ibi = actionCodeSettings.iOS.bundleId;
}
if (typeof actionCodeSettings.android !== 'undefined') {
if (!validator.isNonNullObject(actionCodeSettings.android)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android" must be a valid non-null object.');
}
else if (typeof actionCodeSettings.android.packageName === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME);
}
else if (!validator.isNonEmptyString(actionCodeSettings.android.packageName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.packageName" must be a valid non-empty string.');
}
else if (typeof actionCodeSettings.android.minimumVersion !== 'undefined' &&
!validator.isNonEmptyString(actionCodeSettings.android.minimumVersion)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.minimumVersion" must be a valid non-empty string.');
}
else if (typeof actionCodeSettings.android.installApp !== 'undefined' &&
!validator.isBoolean(actionCodeSettings.android.installApp)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.installApp" must be a valid boolean.');
}
this.apn = actionCodeSettings.android.packageName;
this.amv = actionCodeSettings.android.minimumVersion;
this.installApp = actionCodeSettings.android.installApp || false;
}
}
/**
* Returns the corresponding constructed server request corresponding to the
* current ActionCodeSettings.
*
* @return {EmailActionCodeRequest} The constructed EmailActionCodeRequest request.
*/
ActionCodeSettingsBuilder.prototype.buildRequest = function () {
var request = {
continueUrl: this.continueUrl,
canHandleCodeInApp: this.canHandleCodeInApp,
dynamicLinkDomain: this.dynamicLinkDomain,
androidPackageName: this.apn,
androidMinimumVersion: this.amv,
androidInstallApp: this.installApp,
iOSBundleId: this.ibi,
};
// Remove all null and undefined fields from request.
for (var key in request) {
if (request.hasOwnProperty(key)) {
if (typeof request[key] === 'undefined' || request[key] === null) {
delete request[key];
}
}
}
return request;
};
return ActionCodeSettingsBuilder;
}());
exports.ActionCodeSettingsBuilder = ActionCodeSettingsBuilder;

View File

@ -0,0 +1,825 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var validator = require("../utils/validator");
var deep_copy_1 = require("../utils/deep-copy");
var error_1 = require("../utils/error");
var api_request_1 = require("../utils/api-request");
var user_import_builder_1 = require("./user-import-builder");
var utils = require("../utils/index");
var action_code_settings_builder_1 = require("./action-code-settings-builder");
/** Firebase Auth backend host. */
var FIREBASE_AUTH_HOST = 'www.googleapis.com';
/** Firebase Auth backend port number. */
var FIREBASE_AUTH_PORT = 443;
/** Firebase Auth backend path. */
var FIREBASE_AUTH_PATH = '/identitytoolkit/v3/relyingparty/';
/** Firebase Auth request header. */
var FIREBASE_AUTH_HEADER = {
'X-Client-Version': 'Node/Admin/6.4.0',
};
/** Firebase Auth request timeout duration in milliseconds. */
var FIREBASE_AUTH_TIMEOUT = 25000;
/** List of reserved claims which cannot be provided when creating a custom token. */
exports.RESERVED_CLAIMS = [
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat',
'iss', 'jti', 'nbf', 'nonce', 'sub', 'firebase',
];
/** List of supported email action request types. */
exports.EMAIL_ACTION_REQUEST_TYPES = [
'PASSWORD_RESET', 'VERIFY_EMAIL', 'EMAIL_SIGNIN',
];
/** Maximum allowed number of characters in the custom claims payload. */
var MAX_CLAIMS_PAYLOAD_SIZE = 1000;
/** Maximum allowed number of users to batch download at one time. */
var MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE = 1000;
/** Maximum allowed number of users to batch upload at one time. */
var MAX_UPLOAD_ACCOUNT_BATCH_SIZE = 1000;
/** Minimum allowed session cookie duration in seconds (5 minutes). */
var MIN_SESSION_COOKIE_DURATION_SECS = 5 * 60;
/** Maximum allowed session cookie duration in seconds (2 weeks). */
var MAX_SESSION_COOKIE_DURATION_SECS = 14 * 24 * 60 * 60;
/** The Firebase Auth backend URL format. */
var FIREBASE_AUTH_BASE_URL_FORMAT = 'https://identitytoolkit.googleapis.com/{version}/projects/{projectId}{api}';
/** Defines a base utility to help with resource URL construction. */
var AuthResourceUrlBuilder = /** @class */ (function () {
/**
* The resource URL builder constructor.
*
* @param {string} projectId The resource project ID.
* @param {string} version The endpoint API version.
* @constructor
*/
function AuthResourceUrlBuilder(projectId, version) {
if (version === void 0) { version = 'v1'; }
this.projectId = projectId;
this.version = version;
this.urlFormat = FIREBASE_AUTH_BASE_URL_FORMAT;
}
/**
* Returns the resource URL corresponding to the provided parameters.
*
* @param {string=} api The backend API name.
* @param {object=} params The optional additional parameters to substitute in the
* URL path.
* @return {string} The corresponding resource URL.
*/
AuthResourceUrlBuilder.prototype.getUrl = function (api, params) {
var baseParams = {
version: this.version,
projectId: this.projectId,
api: api || '',
};
var baseUrl = utils.formatString(this.urlFormat, baseParams);
// Substitute additional api related parameters.
return utils.formatString(baseUrl, params || {});
};
return AuthResourceUrlBuilder;
}());
/**
* Validates a providerUserInfo object. All unsupported parameters
* are removed from the original request. If an invalid field is passed
* an error is thrown.
*
* @param {any} request The providerUserInfo request object.
*/
function validateProviderUserInfo(request) {
var validKeys = {
rawId: true,
providerId: true,
email: true,
displayName: true,
photoUrl: true,
};
// Remove invalid keys from original request.
for (var key in request) {
if (!(key in validKeys)) {
delete request[key];
}
}
if (!validator.isNonEmptyString(request.providerId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID);
}
if (typeof request.displayName !== 'undefined' &&
typeof request.displayName !== 'string') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME, "The provider \"displayName\" for \"" + request.providerId + "\" must be a valid string.");
}
if (!validator.isNonEmptyString(request.rawId)) {
// This is called localId on the backend but the developer specifies this as
// uid externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID, "The provider \"uid\" for \"" + request.providerId + "\" must be a valid non-empty string.");
}
// email should be a string and a valid email.
if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL, "The provider \"email\" for \"" + request.providerId + "\" must be a valid email string.");
}
// photoUrl should be a URL.
if (typeof request.photoUrl !== 'undefined' &&
!validator.isURL(request.photoUrl)) {
// This is called photoUrl on the backend but the developer specifies this as
// photoURL externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL, "The provider \"photoURL\" for \"" + request.providerId + "\" must be a valid URL string.");
}
}
/**
* Validates a create/edit request object. All unsupported parameters
* are removed from the original request. If an invalid field is passed
* an error is thrown.
*
* @param {any} request The create/edit request object.
* @param {boolean=} uploadAccountRequest Whether to validate as an uploadAccount request.
*/
function validateCreateEditRequest(request, uploadAccountRequest) {
if (uploadAccountRequest === void 0) { uploadAccountRequest = false; }
// Hash set of whitelisted parameters.
var validKeys = {
displayName: true,
localId: true,
email: true,
password: true,
rawPassword: true,
emailVerified: true,
photoUrl: true,
disabled: true,
disableUser: true,
deleteAttribute: true,
deleteProvider: true,
sanityCheck: true,
phoneNumber: true,
customAttributes: true,
validSince: true,
passwordHash: uploadAccountRequest,
salt: uploadAccountRequest,
createdAt: uploadAccountRequest,
lastLoginAt: uploadAccountRequest,
providerUserInfo: uploadAccountRequest,
};
// Remove invalid keys from original request.
for (var key in request) {
if (!(key in validKeys)) {
delete request[key];
}
}
// For any invalid parameter, use the external key name in the error description.
// displayName should be a string.
if (typeof request.displayName !== 'undefined' &&
!validator.isString(request.displayName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISPLAY_NAME);
}
if ((typeof request.localId !== 'undefined' || uploadAccountRequest) &&
!validator.isUid(request.localId)) {
// This is called localId on the backend but the developer specifies this as
// uid externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID);
}
// email should be a string and a valid email.
if (typeof request.email !== 'undefined' && !validator.isEmail(request.email)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
}
// phoneNumber should be a string and a valid phone number.
if (typeof request.phoneNumber !== 'undefined' &&
!validator.isPhoneNumber(request.phoneNumber)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER);
}
// password should be a string and a minimum of 6 chars.
if (typeof request.password !== 'undefined' &&
!validator.isPassword(request.password)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
}
// rawPassword should be a string and a minimum of 6 chars.
if (typeof request.rawPassword !== 'undefined' &&
!validator.isPassword(request.rawPassword)) {
// This is called rawPassword on the backend but the developer specifies this as
// password externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD);
}
// emailVerified should be a boolean.
if (typeof request.emailVerified !== 'undefined' &&
typeof request.emailVerified !== 'boolean') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL_VERIFIED);
}
// photoUrl should be a URL.
if (typeof request.photoUrl !== 'undefined' &&
!validator.isURL(request.photoUrl)) {
// This is called photoUrl on the backend but the developer specifies this as
// photoURL externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHOTO_URL);
}
// disabled should be a boolean.
if (typeof request.disabled !== 'undefined' &&
typeof request.disabled !== 'boolean') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
}
// validSince should be a number.
if (typeof request.validSince !== 'undefined' &&
!validator.isNumber(request.validSince)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TOKENS_VALID_AFTER_TIME);
}
// createdAt should be a number.
if (typeof request.createdAt !== 'undefined' &&
!validator.isNumber(request.createdAt)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREATION_TIME);
}
// lastSignInAt should be a number.
if (typeof request.lastLoginAt !== 'undefined' &&
!validator.isNumber(request.lastLoginAt)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_LAST_SIGN_IN_TIME);
}
// disableUser should be a boolean.
if (typeof request.disableUser !== 'undefined' &&
typeof request.disableUser !== 'boolean') {
// This is called disableUser on the backend but the developer specifies this as
// disabled externally. So the error message should use the client facing name.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DISABLED_FIELD);
}
// customAttributes should be stringified JSON with no blacklisted claims.
// The payload should not exceed 1KB.
if (typeof request.customAttributes !== 'undefined') {
var developerClaims_1;
try {
developerClaims_1 = JSON.parse(request.customAttributes);
}
catch (error) {
// JSON parsing error. This should never happen as we stringify the claims internally.
// However, we still need to check since setAccountInfo via edit requests could pass
// this field.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CLAIMS, error.message);
}
var invalidClaims_1 = [];
// Check for any invalid claims.
exports.RESERVED_CLAIMS.forEach(function (blacklistedClaim) {
if (developerClaims_1.hasOwnProperty(blacklistedClaim)) {
invalidClaims_1.push(blacklistedClaim);
}
});
// Throw an error if an invalid claim is detected.
if (invalidClaims_1.length > 0) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.FORBIDDEN_CLAIM, invalidClaims_1.length > 1 ?
"Developer claims \"" + invalidClaims_1.join('", "') + "\" are reserved and cannot be specified." :
"Developer claim \"" + invalidClaims_1[0] + "\" is reserved and cannot be specified.");
}
// Check claims payload does not exceed maxmimum size.
if (request.customAttributes.length > MAX_CLAIMS_PAYLOAD_SIZE) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.CLAIMS_TOO_LARGE, "Developer claims payload should not exceed " + MAX_CLAIMS_PAYLOAD_SIZE + " characters.");
}
}
// passwordHash has to be a base64 encoded string.
if (typeof request.passwordHash !== 'undefined' &&
!validator.isString(request.passwordHash)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
}
// salt has to be a base64 encoded string.
if (typeof request.salt !== 'undefined' &&
!validator.isString(request.salt)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
}
// providerUserInfo has to be an array of valid UserInfo requests.
if (typeof request.providerUserInfo !== 'undefined' &&
!validator.isArray(request.providerUserInfo)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_DATA);
}
else if (validator.isArray(request.providerUserInfo)) {
request.providerUserInfo.forEach(function (providerUserInfoEntry) {
validateProviderUserInfo(providerUserInfoEntry);
});
}
}
/** Instantiates the createSessionCookie endpoint settings. */
exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE = new api_request_1.ApiSettings(':createSessionCookie', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
// Validate the ID token is a non-empty string.
if (!validator.isNonEmptyString(request.idToken)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ID_TOKEN);
}
// Validate the custom session cookie duration.
if (!validator.isNumber(request.validDuration) ||
request.validDuration < MIN_SESSION_COOKIE_DURATION_SECS ||
request.validDuration > MAX_SESSION_COOKIE_DURATION_SECS) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION);
}
})
// Set response validator.
.setResponseValidator(function (response) {
// Response should always contain the session cookie.
if (!validator.isNonEmptyString(response.sessionCookie)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR);
}
});
/** Instantiates the uploadAccount endpoint settings. */
exports.FIREBASE_AUTH_UPLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchCreate', 'POST');
/** Instantiates the downloadAccount endpoint settings. */
exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT = new api_request_1.ApiSettings('/accounts:batchGet', 'GET')
// Set request validator.
.setRequestValidator(function (request) {
// Validate next page token.
if (typeof request.nextPageToken !== 'undefined' &&
!validator.isNonEmptyString(request.nextPageToken)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PAGE_TOKEN);
}
// Validate max results.
if (!validator.isNumber(request.maxResults) ||
request.maxResults <= 0 ||
request.maxResults > MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Required \"maxResults\" must be a positive non-zero number that does not exceed " +
("the allowed " + MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE + "."));
}
});
/** Instantiates the getAccountInfo endpoint settings. */
exports.FIREBASE_AUTH_GET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:lookup', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
if (!request.localId && !request.email && !request.phoneNumber) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
}
})
// Set response validator.
.setResponseValidator(function (response) {
if (!response.users) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
}
});
/** Instantiates the deleteAccount endpoint settings. */
exports.FIREBASE_AUTH_DELETE_ACCOUNT = new api_request_1.ApiSettings('/accounts:delete', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
if (!request.localId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
}
});
/** Instantiates the setAccountInfo endpoint settings for updating existing accounts. */
exports.FIREBASE_AUTH_SET_ACCOUNT_INFO = new api_request_1.ApiSettings('/accounts:update', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
// localId is a required parameter.
if (typeof request.localId === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Server request is missing user identifier');
}
validateCreateEditRequest(request);
})
// Set response validator.
.setResponseValidator(function (response) {
// If the localId is not returned, then the request failed.
if (!response.localId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_NOT_FOUND);
}
});
/**
* Instantiates the signupNewUser endpoint settings for creating a new user with or without
* uid being specified. The backend will create a new one if not provided and return it.
*/
exports.FIREBASE_AUTH_SIGN_UP_NEW_USER = new api_request_1.ApiSettings('/accounts', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
// signupNewUser does not support customAttributes.
if (typeof request.customAttributes !== 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"customAttributes\" cannot be set when creating a new user.");
}
// signupNewUser does not support validSince.
if (typeof request.validSince !== 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"validSince\" cannot be set when creating a new user.");
}
validateCreateEditRequest(request);
})
// Set response validator.
.setResponseValidator(function (response) {
// If the localId is not returned, then the request failed.
if (!response.localId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create new user');
}
});
var FIREBASE_AUTH_GET_OOB_CODE = new api_request_1.ApiSettings('/accounts:sendOobCode', 'POST')
// Set request validator.
.setRequestValidator(function (request) {
if (!validator.isEmail(request.email)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL);
}
if (exports.EMAIL_ACTION_REQUEST_TYPES.indexOf(request.requestType) === -1) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "\"" + request.requestType + "\" is not a supported email action request type.");
}
})
// Set response validator.
.setResponseValidator(function (response) {
// If the oobLink is not returned, then the request failed.
if (!response.oobLink) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Unable to create the email action link');
}
});
/**
* Class that provides the mechanism to send requests to the Firebase Auth backend endpoints.
*/
var FirebaseAuthRequestHandler = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
* @constructor
*/
function FirebaseAuthRequestHandler(app) {
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
this.authUrlBuilder = new AuthResourceUrlBuilder(utils.getProjectId(app), 'v1');
}
/**
* @param {any} response The response to check for errors.
* @return {string|null} The error code if present; null otherwise.
*/
FirebaseAuthRequestHandler.getErrorCode = function (response) {
return (validator.isNonNullObject(response) && response.error && response.error.message) || null;
};
/**
* Creates a new Firebase session cookie with the specified duration that can be used for
* session management (set as a server side session cookie with custom cookie policy).
* The session cookie JWT will have the same payload claims as the provided ID token.
*
* @param {string} idToken The Firebase ID token to exchange for a session cookie.
* @param {number} expiresIn The session cookie duration in milliseconds.
*
* @return {Promise<string>} A promise that resolves on success with the created session cookie.
*/
FirebaseAuthRequestHandler.prototype.createSessionCookie = function (idToken, expiresIn) {
var request = {
idToken: idToken,
// Convert to seconds.
validDuration: expiresIn / 1000,
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_CREATE_SESSION_COOKIE, request)
.then(function (response) { return response.sessionCookie; });
};
/**
* Looks up a user by uid.
*
* @param {string} uid The uid of the user to lookup.
* @return {Promise<object>} A promise that resolves with the user information.
*/
FirebaseAuthRequestHandler.prototype.getAccountInfoByUid = function (uid) {
if (!validator.isUid(uid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
}
var request = {
localId: [uid],
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
};
/**
* Looks up a user by email.
*
* @param {string} email The email of the user to lookup.
* @return {Promise<object>} A promise that resolves with the user information.
*/
FirebaseAuthRequestHandler.prototype.getAccountInfoByEmail = function (email) {
if (!validator.isEmail(email)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_EMAIL));
}
var request = {
email: [email],
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
};
/**
* Looks up a user by phone number.
*
* @param {string} phoneNumber The phone number of the user to lookup.
* @return {Promise<object>} A promise that resolves with the user information.
*/
FirebaseAuthRequestHandler.prototype.getAccountInfoByPhoneNumber = function (phoneNumber) {
if (!validator.isPhoneNumber(phoneNumber)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PHONE_NUMBER));
}
var request = {
phoneNumber: [phoneNumber],
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_GET_ACCOUNT_INFO, request);
};
/**
* Exports the users (single batch only) with a size of maxResults and starting from
* the offset as specified by pageToken.
*
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
* allowed limit.
* @param {string=} pageToken The next page token. If not specified, returns users starting
* without any offset. Users are returned in the order they were created from oldest to
* newest, relative to the page token offset.
* @return {Promise<object>} A promise that resolves with the current batch of downloaded
* users and the next page token if available. For the last page, an empty list of users
* and no page token are returned.
*/
FirebaseAuthRequestHandler.prototype.downloadAccount = function (maxResults, pageToken) {
if (maxResults === void 0) { maxResults = MAX_DOWNLOAD_ACCOUNT_PAGE_SIZE; }
// Construct request.
var request = {
maxResults: maxResults,
nextPageToken: pageToken,
};
// Remove next page token if not provided.
if (typeof request.nextPageToken === 'undefined') {
delete request.nextPageToken;
}
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_DOWNLOAD_ACCOUNT, request)
.then(function (response) {
// No more users available.
if (!response.users) {
response.users = [];
}
return response;
});
};
/**
* Imports the list of users provided to Firebase Auth. This is useful when
* migrating from an external authentication system without having to use the Firebase CLI SDK.
* At most, 1000 users are allowed to be imported one at a time.
* When importing a list of password users, UserImportOptions are required to be specified.
*
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
* @param {UserImportOptions=} options The user import options, required when the users provided
* include password credentials.
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
* with the result of the import. This includes the number of successful imports, the number
* of failed uploads and their corresponding errors.
*/
FirebaseAuthRequestHandler.prototype.uploadAccount = function (users, options) {
// This will throw if any error is detected in the hash options.
// For errors in the list of users, this will not throw and will report the errors and the
// corresponding user index in the user import generated response below.
// No need to validate raw request or raw response as this is done in UserImportBuilder.
var userImportBuilder = new user_import_builder_1.UserImportBuilder(users, options, function (userRequest) {
// Pass true to validate the uploadAccount specific fields.
validateCreateEditRequest(userRequest, true);
});
var request = userImportBuilder.buildRequest();
// Fail quickly if more users than allowed are to be imported.
if (validator.isArray(users) && users.length > MAX_UPLOAD_ACCOUNT_BATCH_SIZE) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED, "A maximum of " + MAX_UPLOAD_ACCOUNT_BATCH_SIZE + " users can be imported at once.");
}
// If no remaining user in request after client side processing, there is no need
// to send the request to the server.
if (request.users.length === 0) {
return Promise.resolve(userImportBuilder.buildResponse([]));
}
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_UPLOAD_ACCOUNT, request)
.then(function (response) {
// No error object is returned if no error encountered.
var failedUploads = (response.error || []);
// Rewrite response as UserImportResult and re-insert client previously detected errors.
return userImportBuilder.buildResponse(failedUploads);
});
};
/**
* Deletes an account identified by a uid.
*
* @param {string} uid The uid of the user to delete.
* @return {Promise<object>} A promise that resolves when the user is deleted.
*/
FirebaseAuthRequestHandler.prototype.deleteAccount = function (uid) {
if (!validator.isUid(uid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
}
var request = {
localId: uid,
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_DELETE_ACCOUNT, request);
};
/**
* Sets additional developer claims on an existing user identified by provided UID.
*
* @param {string} uid The user to edit.
* @param {object} customUserClaims The developer claims to set.
* @return {Promise<string>} A promise that resolves when the operation completes
* with the user id that was edited.
*/
FirebaseAuthRequestHandler.prototype.setCustomUserClaims = function (uid, customUserClaims) {
// Validate user UID.
if (!validator.isUid(uid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
}
else if (!validator.isObject(customUserClaims)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'CustomUserClaims argument must be an object or null.'));
}
// Delete operation. Replace null with an empty object.
if (customUserClaims === null) {
customUserClaims = {};
}
// Construct custom user attribute editting request.
var request = {
localId: uid,
customAttributes: JSON.stringify(customUserClaims),
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
.then(function (response) {
return response.localId;
});
};
/**
* Edits an existing user.
*
* @param {string} uid The user to edit.
* @param {object} properties The properties to set on the user.
* @return {Promise<string>} A promise that resolves when the operation completes
* with the user id that was edited.
*/
FirebaseAuthRequestHandler.prototype.updateExistingAccount = function (uid, properties) {
if (!validator.isUid(uid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
}
else if (!validator.isNonNullObject(properties)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
}
// Build the setAccountInfo request.
var request = deep_copy_1.deepCopy(properties);
request.localId = uid;
// For deleting displayName or photoURL, these values must be passed as null.
// They will be removed from the backend request and an additional parameter
// deleteAttribute: ['PHOTO_URL', 'DISPLAY_NAME']
// with an array of the parameter names to delete will be passed.
// Parameters that are deletable and their deleteAttribute names.
// Use client facing names, photoURL instead of photoUrl.
var deletableParams = {
displayName: 'DISPLAY_NAME',
photoURL: 'PHOTO_URL',
};
// Properties to delete if available.
request.deleteAttribute = [];
for (var key in deletableParams) {
if (request[key] === null) {
// Add property identifier to list of attributes to delete.
request.deleteAttribute.push(deletableParams[key]);
// Remove property from request.
delete request[key];
}
}
if (request.deleteAttribute.length === 0) {
delete request.deleteAttribute;
}
// For deleting phoneNumber, this value must be passed as null.
// It will be removed from the backend request and an additional parameter
// deleteProvider: ['phone'] with an array of providerIds (phone in this case),
// will be passed.
// Currently this applies to phone provider only.
if (request.phoneNumber === null) {
request.deleteProvider = ['phone'];
delete request.phoneNumber;
}
else {
// Doesn't apply to other providers in admin SDK.
delete request.deleteProvider;
}
// Rewrite photoURL to photoUrl.
if (typeof request.photoURL !== 'undefined') {
request.photoUrl = request.photoURL;
delete request.photoURL;
}
// Rewrite disabled to disableUser.
if (typeof request.disabled !== 'undefined') {
request.disableUser = request.disabled;
delete request.disabled;
}
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
.then(function (response) {
return response.localId;
});
};
/**
* Revokes all refresh tokens for the specified user identified by the uid provided.
* In addition to revoking all refresh tokens for a user, all ID tokens issued
* before revocation will also be revoked on the Auth backend. Any request with an
* ID token generated before revocation will be rejected with a token expired error.
* Note that due to the fact that the timestamp is stored in seconds, any tokens minted in
* the same second as the revocation will still be valid. If there is a chance that a token
* was minted in the last second, delay for 1 second before revoking.
*
* @param {string} uid The user whose tokens are to be revoked.
* @return {Promise<string>} A promise that resolves when the operation completes
* successfully with the user id of the corresponding user.
*/
FirebaseAuthRequestHandler.prototype.revokeRefreshTokens = function (uid) {
// Validate user UID.
if (!validator.isUid(uid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_UID));
}
var request = {
localId: uid,
// validSince is in UTC seconds.
validSince: Math.ceil(new Date().getTime() / 1000),
};
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SET_ACCOUNT_INFO, request)
.then(function (response) {
return response.localId;
});
};
/**
* Create a new user with the properties supplied.
*
* @param {object} properties The properties to set on the user.
* @return {Promise<string>} A promise that resolves when the operation completes
* with the user id that was created.
*/
FirebaseAuthRequestHandler.prototype.createNewAccount = function (properties) {
if (!validator.isNonNullObject(properties)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'Properties argument must be a non-null object.'));
}
// Build the signupNewUser request.
var request = deep_copy_1.deepCopy(properties);
// Rewrite photoURL to photoUrl.
if (typeof request.photoURL !== 'undefined') {
request.photoUrl = request.photoURL;
delete request.photoURL;
}
// Rewrite uid to localId if it exists.
if (typeof request.uid !== 'undefined') {
request.localId = request.uid;
delete request.uid;
}
return this.invokeRequestHandler(this.authUrlBuilder, exports.FIREBASE_AUTH_SIGN_UP_NEW_USER, request)
.then(function (response) {
// Return the user id.
return response.localId;
});
};
/**
* Generates the out of band email action link for the email specified using the action code settings provided.
* Returns a promise that resolves with the generated link.
*
* @param {string} requestType The request type. This could be either used for password reset,
* email verification, email link sign-in.
* @param {string} email The email of the user the link is being sent to.
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
* the link is to be handled by a mobile app and the additional state information to be passed in the
* deep link, etc.
* @return {Promise<string>} A promise that resolves with the email action link.
*/
FirebaseAuthRequestHandler.prototype.getEmailActionLink = function (requestType, email, actionCodeSettings) {
var request = { requestType: requestType, email: email, returnOobLink: true };
// ActionCodeSettings required for email link sign-in to determine the url where the sign-in will
// be completed.
if (typeof actionCodeSettings !== 'undefined' || requestType === 'EMAIL_SIGNIN') {
try {
var builder = new action_code_settings_builder_1.ActionCodeSettingsBuilder(actionCodeSettings);
request = deep_copy_1.deepExtend(request, builder.buildRequest());
}
catch (e) {
return Promise.reject(e);
}
}
return this.invokeRequestHandler(this.authUrlBuilder, FIREBASE_AUTH_GET_OOB_CODE, request)
.then(function (response) {
// Return the link.
return response.oobLink;
});
};
/**
* Invokes the request handler based on the API settings object passed.
*
* @param {AuthResourceUrlBuilder} urlBuilder The URL builder for Auth endpoints.
* @param {ApiSettings} apiSettings The API endpoint settings to apply to request and response.
* @param {object} requestData The request data.
* @param {object=} additionalResourceParams Additional resource related params if needed.
* @return {Promise<object>} A promise that resolves with the response.
*/
FirebaseAuthRequestHandler.prototype.invokeRequestHandler = function (urlBuilder, apiSettings, requestData, additionalResourceParams) {
var _this = this;
return Promise.resolve()
.then(function () {
// Validate request.
var requestValidator = apiSettings.getRequestValidator();
requestValidator(requestData);
// Process request.
var req = {
method: apiSettings.getHttpMethod(),
url: urlBuilder.getUrl(apiSettings.getEndpoint(), additionalResourceParams),
headers: FIREBASE_AUTH_HEADER,
data: requestData,
timeout: FIREBASE_AUTH_TIMEOUT,
};
return _this.httpClient.send(req);
})
.then(function (response) {
// Validate response.
var responseValidator = apiSettings.getResponseValidator();
responseValidator(response.data);
// Return entire response.
return response.data;
})
.catch(function (err) {
if (err instanceof api_request_1.HttpError) {
var error = err.response.data;
var errorCode = FirebaseAuthRequestHandler.getErrorCode(error);
throw error_1.FirebaseAuthError.fromServerError(errorCode, /* message */ undefined, error);
}
throw err;
});
};
return FirebaseAuthRequestHandler;
}());
exports.FirebaseAuthRequestHandler = FirebaseAuthRequestHandler;

View File

@ -0,0 +1,437 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var user_record_1 = require("./user-record");
var token_generator_1 = require("./token-generator");
var auth_api_request_1 = require("./auth-api-request");
var error_1 = require("../utils/error");
var utils = require("../utils/index");
var validator = require("../utils/validator");
var token_verifier_1 = require("./token-verifier");
/**
* Internals of an Auth instance.
*/
var AuthInternals = /** @class */ (function () {
function AuthInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
AuthInternals.prototype.delete = function () {
// There are no resources to clean up
return Promise.resolve(undefined);
};
return AuthInternals;
}());
/**
* Base Auth class. Mainly used for user management APIs.
*/
var BaseAuth = /** @class */ (function () {
/**
* The BaseAuth class constructor.
*
* @param {string} projectId The corresponding project ID.
* @param {FirebaseAuthRequestHandler} authRequestHandler The RPC request handler
* for this instance.
* @param {CryptoSigner} cryptoSigner The instance crypto signer used for custom token
* minting.
* @constructor
*/
function BaseAuth(projectId, authRequestHandler, cryptoSigner) {
this.projectId = projectId;
this.authRequestHandler = authRequestHandler;
this.tokenGenerator = new token_generator_1.FirebaseTokenGenerator(cryptoSigner);
this.sessionCookieVerifier = token_verifier_1.createSessionCookieVerifier(projectId);
this.idTokenVerifier = token_verifier_1.createIdTokenVerifier(projectId);
}
/**
* Creates a new custom token that can be sent back to a client to use with
* signInWithCustomToken().
*
* @param {string} uid The uid to use as the JWT subject.
* @param {object=} developerClaims Optional additional claims to include in the JWT payload.
*
* @return {Promise<string>} A JWT for the provided payload.
*/
BaseAuth.prototype.createCustomToken = function (uid, developerClaims) {
return this.tokenGenerator.createCustomToken(uid, developerClaims);
};
/**
* Verifies a JWT auth token. Returns a Promise with the tokens claims. Rejects
* the promise if the token could not be verified. If checkRevoked is set to true,
* verifies if the session corresponding to the ID token was revoked. If the corresponding
* user's session was invalidated, an auth/id-token-revoked error is thrown. If not specified
* the check is not applied.
*
* @param {string} idToken The JWT to verify.
* @param {boolean=} checkRevoked Whether to check if the ID token is revoked.
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
* verification.
*/
BaseAuth.prototype.verifyIdToken = function (idToken, checkRevoked) {
var _this = this;
if (checkRevoked === void 0) { checkRevoked = false; }
return this.idTokenVerifier.verifyJWT(idToken)
.then(function (decodedIdToken) {
// Whether to check if the token was revoked.
if (!checkRevoked) {
return decodedIdToken;
}
return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.ID_TOKEN_REVOKED);
});
};
/**
* Looks up the user identified by the provided user id and returns a promise that is
* fulfilled with a user record for the given user if that user is found.
*
* @param {string} uid The uid of the user to look up.
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
*/
BaseAuth.prototype.getUser = function (uid) {
return this.authRequestHandler.getAccountInfoByUid(uid)
.then(function (response) {
// Returns the user record populated with server response.
return new user_record_1.UserRecord(response.users[0]);
});
};
/**
* Looks up the user identified by the provided email and returns a promise that is
* fulfilled with a user record for the given user if that user is found.
*
* @param {string} email The email of the user to look up.
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
*/
BaseAuth.prototype.getUserByEmail = function (email) {
return this.authRequestHandler.getAccountInfoByEmail(email)
.then(function (response) {
// Returns the user record populated with server response.
return new user_record_1.UserRecord(response.users[0]);
});
};
/**
* Looks up the user identified by the provided phone number and returns a promise that is
* fulfilled with a user record for the given user if that user is found.
*
* @param {string} phoneNumber The phone number of the user to look up.
* @return {Promise<UserRecord>} A promise that resolves with the corresponding user record.
*/
BaseAuth.prototype.getUserByPhoneNumber = function (phoneNumber) {
return this.authRequestHandler.getAccountInfoByPhoneNumber(phoneNumber)
.then(function (response) {
// Returns the user record populated with server response.
return new user_record_1.UserRecord(response.users[0]);
});
};
/**
* Exports a batch of user accounts. Batch size is determined by the maxResults argument.
* Starting point of the batch is determined by the pageToken argument.
*
* @param {number=} maxResults The page size, 1000 if undefined. This is also the maximum
* allowed limit.
* @param {string=} pageToken The next page token. If not specified, returns users starting
* without any offset.
* @return {Promise<{users: UserRecord[], pageToken?: string}>} A promise that resolves with
* the current batch of downloaded users and the next page token. For the last page, an
* empty list of users and no page token are returned.
*/
BaseAuth.prototype.listUsers = function (maxResults, pageToken) {
return this.authRequestHandler.downloadAccount(maxResults, pageToken)
.then(function (response) {
// List of users to return.
var users = [];
// Convert each user response to a UserRecord.
response.users.forEach(function (userResponse) {
users.push(new user_record_1.UserRecord(userResponse));
});
// Return list of user records and the next page token if available.
var result = {
users: users,
pageToken: response.nextPageToken,
};
// Delete result.pageToken if undefined.
if (typeof result.pageToken === 'undefined') {
delete result.pageToken;
}
return result;
});
};
/**
* Creates a new user with the properties provided.
*
* @param {CreateRequest} properties The properties to set on the new user record to be created.
* @return {Promise<UserRecord>} A promise that resolves with the newly created user record.
*/
BaseAuth.prototype.createUser = function (properties) {
var _this = this;
return this.authRequestHandler.createNewAccount(properties)
.then(function (uid) {
// Return the corresponding user record.
return _this.getUser(uid);
})
.catch(function (error) {
if (error.code === 'auth/user-not-found') {
// Something must have happened after creating the user and then retrieving it.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Unable to create the user record provided.');
}
throw error;
});
};
/**
* Deletes the user identified by the provided user id and returns a promise that is
* fulfilled when the user is found and successfully deleted.
*
* @param {string} uid The uid of the user to delete.
* @return {Promise<void>} A promise that resolves when the user is successfully deleted.
*/
BaseAuth.prototype.deleteUser = function (uid) {
return this.authRequestHandler.deleteAccount(uid)
.then(function (response) {
// Return nothing on success.
});
};
/**
* Updates an existing user with the properties provided.
*
* @param {string} uid The uid identifier of the user to update.
* @param {UpdateRequest} properties The properties to update on the existing user.
* @return {Promise<UserRecord>} A promise that resolves with the modified user record.
*/
BaseAuth.prototype.updateUser = function (uid, properties) {
var _this = this;
return this.authRequestHandler.updateExistingAccount(uid, properties)
.then(function (existingUid) {
// Return the corresponding user record.
return _this.getUser(existingUid);
});
};
/**
* Sets additional developer claims on an existing user identified by the provided UID.
*
* @param {string} uid The user to edit.
* @param {object} customUserClaims The developer claims to set.
* @return {Promise<void>} A promise that resolves when the operation completes
* successfully.
*/
BaseAuth.prototype.setCustomUserClaims = function (uid, customUserClaims) {
return this.authRequestHandler.setCustomUserClaims(uid, customUserClaims)
.then(function (existingUid) {
// Return nothing on success.
});
};
/**
* Revokes all refresh tokens for the specified user identified by the provided UID.
* In addition to revoking all refresh tokens for a user, all ID tokens issued before
* revocation will also be revoked on the Auth backend. Any request with an ID token
* generated before revocation will be rejected with a token expired error.
*
* @param {string} uid The user whose tokens are to be revoked.
* @return {Promise<void>} A promise that resolves when the operation completes
* successfully.
*/
BaseAuth.prototype.revokeRefreshTokens = function (uid) {
return this.authRequestHandler.revokeRefreshTokens(uid)
.then(function (existingUid) {
// Return nothing on success.
});
};
/**
* Imports the list of users provided to Firebase Auth. This is useful when
* migrating from an external authentication system without having to use the Firebase CLI SDK.
* At most, 1000 users are allowed to be imported one at a time.
* When importing a list of password users, UserImportOptions are required to be specified.
*
* @param {UserImportRecord[]} users The list of user records to import to Firebase Auth.
* @param {UserImportOptions=} options The user import options, required when the users provided
* include password credentials.
* @return {Promise<UserImportResult>} A promise that resolves when the operation completes
* with the result of the import. This includes the number of successful imports, the number
* of failed uploads and their corresponding errors.
*/
BaseAuth.prototype.importUsers = function (users, options) {
return this.authRequestHandler.uploadAccount(users, options);
};
/**
* Creates a new Firebase session cookie with the specified options that can be used for
* session management (set as a server side session cookie with custom cookie policy).
* The session cookie JWT will have the same payload claims as the provided ID token.
*
* @param {string} idToken The Firebase ID token to exchange for a session cookie.
* @param {SessionCookieOptions} sessionCookieOptions The session cookie options which includes
* custom session duration.
*
* @return {Promise<string>} A promise that resolves on success with the created session cookie.
*/
BaseAuth.prototype.createSessionCookie = function (idToken, sessionCookieOptions) {
// Return rejected promise if expiresIn is not available.
if (!validator.isNonNullObject(sessionCookieOptions) ||
!validator.isNumber(sessionCookieOptions.expiresIn)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION));
}
return this.authRequestHandler.createSessionCookie(idToken, sessionCookieOptions.expiresIn);
};
/**
* Verifies a Firebase session cookie. Returns a Promise with the tokens claims. Rejects
* the promise if the token could not be verified. If checkRevoked is set to true,
* verifies if the session corresponding to the session cookie was revoked. If the corresponding
* user's session was invalidated, an auth/session-cookie-revoked error is thrown. If not
* specified the check is not performed.
*
* @param {string} sessionCookie The session cookie to verify.
* @param {boolean=} checkRevoked Whether to check if the session cookie is revoked.
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
* verification.
*/
BaseAuth.prototype.verifySessionCookie = function (sessionCookie, checkRevoked) {
var _this = this;
if (checkRevoked === void 0) { checkRevoked = false; }
return this.sessionCookieVerifier.verifyJWT(sessionCookie)
.then(function (decodedIdToken) {
// Whether to check if the token was revoked.
if (!checkRevoked) {
return decodedIdToken;
}
return _this.verifyDecodedJWTNotRevoked(decodedIdToken, error_1.AuthClientErrorCode.SESSION_COOKIE_REVOKED);
});
};
/**
* Generates the out of band email action link for password reset flows for the
* email specified using the action code settings provided.
* Returns a promise that resolves with the generated link.
*
* @param {string} email The email of the user whose password is to be reset.
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
* the link is to be handled by a mobile app and the additional state information to be passed in the
* deep link, etc.
* @return {Promise<string>} A promise that resolves with the password reset link.
*/
BaseAuth.prototype.generatePasswordResetLink = function (email, actionCodeSettings) {
return this.authRequestHandler.getEmailActionLink('PASSWORD_RESET', email, actionCodeSettings);
};
/**
* Generates the out of band email action link for email verification flows for the
* email specified using the action code settings provided.
* Returns a promise that resolves with the generated link.
*
* @param {string} email The email of the user to be verified.
* @param {ActionCodeSettings=} actionCodeSettings The optional action code setings which defines whether
* the link is to be handled by a mobile app and the additional state information to be passed in the
* deep link, etc.
* @return {Promise<string>} A promise that resolves with the email verification link.
*/
BaseAuth.prototype.generateEmailVerificationLink = function (email, actionCodeSettings) {
return this.authRequestHandler.getEmailActionLink('VERIFY_EMAIL', email, actionCodeSettings);
};
/**
* Generates the out of band email action link for email link sign-in flows for the
* email specified using the action code settings provided.
* Returns a promise that resolves with the generated link.
*
* @param {string} email The email of the user signing in.
* @param {ActionCodeSettings} actionCodeSettings The required action code setings which defines whether
* the link is to be handled by a mobile app and the additional state information to be passed in the
* deep link, etc.
* @return {Promise<string>} A promise that resolves with the email sign-in link.
*/
BaseAuth.prototype.generateSignInWithEmailLink = function (email, actionCodeSettings) {
return this.authRequestHandler.getEmailActionLink('EMAIL_SIGNIN', email, actionCodeSettings);
};
/**
* Verifies the decoded Firebase issued JWT is not revoked. Returns a promise that resolves
* with the decoded claims on success. Rejects the promise with revocation error if revoked.
*
* @param {DecodedIdToken} decodedIdToken The JWT's decoded claims.
* @param {ErrorInfo} revocationErrorInfo The revocation error info to throw on revocation
* detection.
* @return {Promise<DecodedIdToken>} A Promise that will be fulfilled after a successful
* verification.
*/
BaseAuth.prototype.verifyDecodedJWTNotRevoked = function (decodedIdToken, revocationErrorInfo) {
// Get tokens valid after time for the corresponding user.
return this.getUser(decodedIdToken.sub)
.then(function (user) {
// If no tokens valid after time available, token is not revoked.
if (user.tokensValidAfterTime) {
// Get the ID token authentication time and convert to milliseconds UTC.
var authTimeUtc = decodedIdToken.auth_time * 1000;
// Get user tokens valid after time in milliseconds UTC.
var validSinceUtc = new Date(user.tokensValidAfterTime).getTime();
// Check if authentication time is older than valid since time.
if (authTimeUtc < validSinceUtc) {
throw new error_1.FirebaseAuthError(revocationErrorInfo);
}
}
// All checks above passed. Return the decoded token.
return decodedIdToken;
});
};
return BaseAuth;
}());
/**
* Auth service bound to the provided app.
*/
var Auth = /** @class */ (function (_super) {
__extends(Auth, _super);
/**
* @param {object} app The app for this Auth service.
* @constructor
*/
function Auth(app) {
var _this = _super.call(this, Auth.getProjectId(app), new auth_api_request_1.FirebaseAuthRequestHandler(app), token_generator_1.cryptoSignerFromApp(app)) || this;
_this.INTERNAL = new AuthInternals();
_this.app_ = app;
return _this;
}
/**
* Returns the FirebaseApp's project ID.
*
* @param {FirebaseApp} app The project ID for an app.
* @return {string} The FirebaseApp's project ID.
*/
Auth.getProjectId = function (app) {
if (typeof app !== 'object' || app === null || !('options' in app)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.auth() must be a valid Firebase app instance.');
}
return utils.getProjectId(app);
};
Object.defineProperty(Auth.prototype, "app", {
/**
* Returns the app associated with this Auth instance.
*
* @return {FirebaseApp} The app associated with this Auth instance.
*/
get: function () {
return this.app_;
},
enumerable: true,
configurable: true
});
return Auth;
}(BaseAuth));
exports.Auth = Auth;

View File

@ -0,0 +1,304 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
// Use untyped import syntax for Node built-ins
var fs = require("fs");
var os = require("os");
var path = require("path");
var error_1 = require("../utils/error");
var api_request_1 = require("../utils/api-request");
var GOOGLE_TOKEN_AUDIENCE = 'https://accounts.google.com/o/oauth2/token';
var GOOGLE_AUTH_TOKEN_HOST = 'accounts.google.com';
var GOOGLE_AUTH_TOKEN_PATH = '/o/oauth2/token';
// NOTE: the Google Metadata Service uses HTTP over a vlan
var GOOGLE_METADATA_SERVICE_HOST = 'metadata.google.internal';
var GOOGLE_METADATA_SERVICE_PATH = '/computeMetadata/v1beta1/instance/service-accounts/default/token';
var configDir = (function () {
// Windows has a dedicated low-rights location for apps at ~/Application Data
var sys = os.platform();
if (sys && sys.length >= 3 && sys.substring(0, 3).toLowerCase() === 'win') {
return process.env.APPDATA;
}
// On *nix the gcloud cli creates a . dir.
return process.env.HOME && path.resolve(process.env.HOME, '.config');
})();
var GCLOUD_CREDENTIAL_SUFFIX = 'gcloud/application_default_credentials.json';
var GCLOUD_CREDENTIAL_PATH = configDir && path.resolve(configDir, GCLOUD_CREDENTIAL_SUFFIX);
var REFRESH_TOKEN_HOST = 'www.googleapis.com';
var REFRESH_TOKEN_PATH = '/oauth2/v4/token';
var ONE_HOUR_IN_SECONDS = 60 * 60;
var JWT_ALGORITHM = 'RS256';
function copyAttr(to, from, key, alt) {
var tmp = from[key] || from[alt];
if (typeof tmp !== 'undefined') {
to[key] = tmp;
}
}
var RefreshToken = /** @class */ (function () {
function RefreshToken(json) {
copyAttr(this, json, 'clientId', 'client_id');
copyAttr(this, json, 'clientSecret', 'client_secret');
copyAttr(this, json, 'refreshToken', 'refresh_token');
copyAttr(this, json, 'type', 'type');
var errorMessage;
if (typeof this.clientId !== 'string' || !this.clientId) {
errorMessage = 'Refresh token must contain a "client_id" property.';
}
else if (typeof this.clientSecret !== 'string' || !this.clientSecret) {
errorMessage = 'Refresh token must contain a "client_secret" property.';
}
else if (typeof this.refreshToken !== 'string' || !this.refreshToken) {
errorMessage = 'Refresh token must contain a "refresh_token" property.';
}
else if (typeof this.type !== 'string' || !this.type) {
errorMessage = 'Refresh token must contain a "type" property.';
}
if (typeof errorMessage !== 'undefined') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
}
}
/*
* Tries to load a RefreshToken from a path. If the path is not present, returns null.
* Throws if data at the path is invalid.
*/
RefreshToken.fromPath = function (filePath) {
var jsonString;
try {
jsonString = fs.readFileSync(filePath, 'utf8');
}
catch (ignored) {
// Ignore errors if the file is not present, as this is sometimes an expected condition
return null;
}
try {
return new RefreshToken(JSON.parse(jsonString));
}
catch (error) {
// Throw a nicely formed error message if the file contents cannot be parsed
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse refresh token file: ' + error);
}
};
return RefreshToken;
}());
exports.RefreshToken = RefreshToken;
/**
* A struct containing the properties necessary to use service-account JSON credentials.
*/
var Certificate = /** @class */ (function () {
function Certificate(json) {
if (typeof json !== 'object' || json === null) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Certificate object must be an object.');
}
copyAttr(this, json, 'projectId', 'project_id');
copyAttr(this, json, 'privateKey', 'private_key');
copyAttr(this, json, 'clientEmail', 'client_email');
var errorMessage;
if (typeof this.privateKey !== 'string' || !this.privateKey) {
errorMessage = 'Certificate object must contain a string "private_key" property.';
}
else if (typeof this.clientEmail !== 'string' || !this.clientEmail) {
errorMessage = 'Certificate object must contain a string "client_email" property.';
}
if (typeof errorMessage !== 'undefined') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
}
var forge = require('node-forge');
try {
forge.pki.privateKeyFromPem(this.privateKey);
}
catch (error) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse private key: ' + error);
}
}
Certificate.fromPath = function (filePath) {
// Node bug encountered in v6.x. fs.readFileSync hangs when path is a 0 or 1.
if (typeof filePath !== 'string') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse certificate key file: TypeError: path must be a string');
}
try {
return new Certificate(JSON.parse(fs.readFileSync(filePath, 'utf8')));
}
catch (error) {
// Throw a nicely formed error message if the file contents cannot be parsed
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, 'Failed to parse certificate key file: ' + error);
}
};
return Certificate;
}());
exports.Certificate = Certificate;
/**
* Obtain a new OAuth2 token by making a remote service call.
*/
function requestAccessToken(client, request) {
return client.send(request).then(function (resp) {
var json = resp.data;
if (json.error) {
var errorMessage = 'Error fetching access token: ' + json.error;
if (json.error_description) {
errorMessage += ' (' + json.error_description + ')';
}
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
}
else if (!json.access_token || !json.expires_in) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, "Unexpected response while fetching access token: " + JSON.stringify(json));
}
else {
return json;
}
}).catch(function (err) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, "Failed to parse access token response: " + err.toString());
});
}
/**
* Implementation of Credential that uses a service account certificate.
*/
var CertCredential = /** @class */ (function () {
function CertCredential(serviceAccountPathOrObject, httpAgent) {
this.certificate = (typeof serviceAccountPathOrObject === 'string') ?
Certificate.fromPath(serviceAccountPathOrObject) : new Certificate(serviceAccountPathOrObject);
this.httpClient = new api_request_1.HttpClient();
this.httpAgent = httpAgent;
}
CertCredential.prototype.getAccessToken = function () {
var token = this.createAuthJwt_();
var postData = 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3A' +
'grant-type%3Ajwt-bearer&assertion=' + token;
var request = {
method: 'POST',
url: "https://" + GOOGLE_AUTH_TOKEN_HOST + GOOGLE_AUTH_TOKEN_PATH,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: postData,
httpAgent: this.httpAgent,
};
return requestAccessToken(this.httpClient, request);
};
CertCredential.prototype.getCertificate = function () {
return this.certificate;
};
CertCredential.prototype.createAuthJwt_ = function () {
var claims = {
scope: [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/firebase.database',
'https://www.googleapis.com/auth/firebase.messaging',
'https://www.googleapis.com/auth/identitytoolkit',
'https://www.googleapis.com/auth/userinfo.email',
].join(' '),
};
var jwt = require('jsonwebtoken');
// This method is actually synchronous so we can capture and return the buffer.
return jwt.sign(claims, this.certificate.privateKey, {
audience: GOOGLE_TOKEN_AUDIENCE,
expiresIn: ONE_HOUR_IN_SECONDS,
issuer: this.certificate.clientEmail,
algorithm: JWT_ALGORITHM,
});
};
return CertCredential;
}());
exports.CertCredential = CertCredential;
/**
* Implementation of Credential that gets access tokens from refresh tokens.
*/
var RefreshTokenCredential = /** @class */ (function () {
function RefreshTokenCredential(refreshTokenPathOrObject, httpAgent) {
this.refreshToken = (typeof refreshTokenPathOrObject === 'string') ?
RefreshToken.fromPath(refreshTokenPathOrObject) : new RefreshToken(refreshTokenPathOrObject);
this.httpClient = new api_request_1.HttpClient();
this.httpAgent = httpAgent;
}
RefreshTokenCredential.prototype.getAccessToken = function () {
var postData = 'client_id=' + this.refreshToken.clientId + '&' +
'client_secret=' + this.refreshToken.clientSecret + '&' +
'refresh_token=' + this.refreshToken.refreshToken + '&' +
'grant_type=refresh_token';
var request = {
method: 'POST',
url: "https://" + REFRESH_TOKEN_HOST + REFRESH_TOKEN_PATH,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
data: postData,
httpAgent: this.httpAgent,
};
return requestAccessToken(this.httpClient, request);
};
RefreshTokenCredential.prototype.getCertificate = function () {
return null;
};
return RefreshTokenCredential;
}());
exports.RefreshTokenCredential = RefreshTokenCredential;
/**
* Implementation of Credential that gets access tokens from the metadata service available
* in the Google Cloud Platform. This authenticates the process as the default service account
* of an App Engine instance or Google Compute Engine machine.
*/
var MetadataServiceCredential = /** @class */ (function () {
function MetadataServiceCredential(httpAgent) {
this.httpClient = new api_request_1.HttpClient();
this.httpAgent = httpAgent;
}
MetadataServiceCredential.prototype.getAccessToken = function () {
var request = {
method: 'GET',
url: "http://" + GOOGLE_METADATA_SERVICE_HOST + GOOGLE_METADATA_SERVICE_PATH,
httpAgent: this.httpAgent,
};
return requestAccessToken(this.httpClient, request);
};
MetadataServiceCredential.prototype.getCertificate = function () {
return null;
};
return MetadataServiceCredential;
}());
exports.MetadataServiceCredential = MetadataServiceCredential;
/**
* ApplicationDefaultCredential implements the process for loading credentials as
* described in https://developers.google.com/identity/protocols/application-default-credentials
*/
var ApplicationDefaultCredential = /** @class */ (function () {
function ApplicationDefaultCredential(httpAgent) {
if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
var serviceAccount = Certificate.fromPath(process.env.GOOGLE_APPLICATION_CREDENTIALS);
this.credential_ = new CertCredential(serviceAccount, httpAgent);
return;
}
// It is OK to not have this file. If it is present, it must be valid.
var refreshToken = RefreshToken.fromPath(GCLOUD_CREDENTIAL_PATH);
if (refreshToken) {
this.credential_ = new RefreshTokenCredential(refreshToken, httpAgent);
return;
}
this.credential_ = new MetadataServiceCredential(httpAgent);
}
ApplicationDefaultCredential.prototype.getAccessToken = function () {
return this.credential_.getAccessToken();
};
ApplicationDefaultCredential.prototype.getCertificate = function () {
return this.credential_.getCertificate();
};
// Used in testing to verify we are delegating to the correct implementation.
ApplicationDefaultCredential.prototype.getCredential = function () {
return this.credential_;
};
return ApplicationDefaultCredential;
}());
exports.ApplicationDefaultCredential = ApplicationDefaultCredential;

View File

@ -0,0 +1,252 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var api_request_1 = require("../utils/api-request");
var validator = require("../utils/validator");
var utils_1 = require("../utils");
var ALGORITHM_RS256 = 'RS256';
var ONE_HOUR_IN_SECONDS = 60 * 60;
// List of blacklisted claims which cannot be provided when creating a custom token
var BLACKLISTED_CLAIMS = [
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat', 'iss', 'jti',
'nbf', 'nonce',
];
// Audience to use for Firebase Auth Custom tokens
var FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
/**
* A CryptoSigner implementation that uses an explicitly specified service account private key to
* sign data. Performs all operations locally, and does not make any RPC calls.
*/
var ServiceAccountSigner = /** @class */ (function () {
/**
* Creates a new CryptoSigner instance from the given service account certificate.
*
* @param {Certificate} certificate A service account certificate.
*/
function ServiceAccountSigner(certificate) {
if (!certificate) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a certificate to initialize ServiceAccountSigner.');
}
if (!validator.isNonEmptyString(certificate.clientEmail) || !validator.isNonEmptyString(certificate.privateKey)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a certificate with validate clientEmail and privateKey to ' +
'initialize ServiceAccountSigner.');
}
this.certificate = certificate;
}
/**
* @inheritDoc
*/
ServiceAccountSigner.prototype.sign = function (buffer) {
var crypto = require('crypto');
var sign = crypto.createSign('RSA-SHA256');
sign.update(buffer);
return Promise.resolve(sign.sign(this.certificate.privateKey));
};
/**
* @inheritDoc
*/
ServiceAccountSigner.prototype.getAccountId = function () {
return Promise.resolve(this.certificate.clientEmail);
};
return ServiceAccountSigner;
}());
exports.ServiceAccountSigner = ServiceAccountSigner;
/**
* A CryptoSigner implementation that uses the remote IAM service to sign data. If initialized without
* a service account ID, attempts to discover a service account ID by consulting the local Metadata
* service. This will succeed in managed environments like Google Cloud Functions and App Engine.
*
* @see https://cloud.google.com/iam/reference/rest/v1/projects.serviceAccounts/signBlob
* @see https://cloud.google.com/compute/docs/storing-retrieving-metadata
*/
var IAMSigner = /** @class */ (function () {
function IAMSigner(httpClient, serviceAccountId) {
if (!httpClient) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'INTERNAL ASSERT: Must provide a HTTP client to initialize IAMSigner.');
}
if (typeof serviceAccountId !== 'undefined' && !validator.isNonEmptyString(serviceAccountId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'INTERNAL ASSERT: Service account ID must be undefined or a non-empty string.');
}
this.httpClient = httpClient;
this.serviceAccountId = serviceAccountId;
}
/**
* @inheritDoc
*/
IAMSigner.prototype.sign = function (buffer) {
var _this = this;
return this.getAccountId().then(function (serviceAccount) {
var request = {
method: 'POST',
url: "https://iam.googleapis.com/v1/projects/-/serviceAccounts/" + serviceAccount + ":signBlob",
data: { bytesToSign: buffer.toString('base64') },
};
return _this.httpClient.send(request);
}).then(function (response) {
// Response from IAM is base64 encoded. Decode it into a buffer and return.
return Buffer.from(response.data.signature, 'base64');
}).catch(function (err) {
if (err instanceof api_request_1.HttpError) {
var error = err.response.data;
var errorCode = void 0;
var errorMsg = void 0;
if (validator.isNonNullObject(error) && error.error) {
errorCode = error.error.status || null;
var description = 'Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens ' +
'for more details on how to use and troubleshoot this feature.';
errorMsg = error.error.message + "; " + description || null;
}
throw error_1.FirebaseAuthError.fromServerError(errorCode, errorMsg, error);
}
throw err;
});
};
/**
* @inheritDoc
*/
IAMSigner.prototype.getAccountId = function () {
var _this = this;
if (validator.isNonEmptyString(this.serviceAccountId)) {
return Promise.resolve(this.serviceAccountId);
}
var request = {
method: 'GET',
url: 'http://metadata/computeMetadata/v1/instance/service-accounts/default/email',
headers: {
'Metadata-Flavor': 'Google',
},
};
var client = new api_request_1.HttpClient();
return client.send(request).then(function (response) {
_this.serviceAccountId = response.text;
return _this.serviceAccountId;
}).catch(function (err) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, "Failed to determine service account. Make sure to initialize " +
"the SDK with a service account credential. Alternatively specify a service " +
("account with iam.serviceAccounts.signBlob permission. Original error: " + err));
});
};
return IAMSigner;
}());
exports.IAMSigner = IAMSigner;
/**
* Create a new CryptoSigner instance for the given app. If the app has been initialized with a service
* account credential, creates a ServiceAccountSigner. Otherwise creates an IAMSigner.
*
* @param {FirebaseApp} app A FirebaseApp instance.
* @return {CryptoSigner} A CryptoSigner instance.
*/
function cryptoSignerFromApp(app) {
var cert = app.options.credential.getCertificate();
if (cert != null && validator.isNonEmptyString(cert.privateKey) && validator.isNonEmptyString(cert.clientEmail)) {
return new ServiceAccountSigner(cert);
}
return new IAMSigner(new api_request_1.AuthorizedHttpClient(app), app.options.serviceAccountId);
}
exports.cryptoSignerFromApp = cryptoSignerFromApp;
/**
* Class for generating different types of Firebase Auth tokens (JWTs).
*/
var FirebaseTokenGenerator = /** @class */ (function () {
function FirebaseTokenGenerator(signer) {
if (!validator.isNonNullObject(signer)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a CryptoSigner to use FirebaseTokenGenerator.');
}
this.signer = signer;
}
/**
* Creates a new Firebase Auth Custom token.
*
* @param {string} uid The user ID to use for the generated Firebase Auth Custom token.
* @param {object} [developerClaims] Optional developer claims to include in the generated Firebase
* Auth Custom token.
* @return {Promise<string>} A Promise fulfilled with a Firebase Auth Custom token signed with a
* service account key and containing the provided payload.
*/
FirebaseTokenGenerator.prototype.createCustomToken = function (uid, developerClaims) {
var _this = this;
var errorMessage;
if (typeof uid !== 'string' || uid === '') {
errorMessage = 'First argument to createCustomToken() must be a non-empty string uid.';
}
else if (uid.length > 128) {
errorMessage = 'First argument to createCustomToken() must a uid with less than or equal to 128 characters.';
}
else if (!this.isDeveloperClaimsValid_(developerClaims)) {
errorMessage = 'Second argument to createCustomToken() must be an object containing the developer claims.';
}
if (typeof errorMessage !== 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
var claims = {};
if (typeof developerClaims !== 'undefined') {
for (var key in developerClaims) {
/* istanbul ignore else */
if (developerClaims.hasOwnProperty(key)) {
if (BLACKLISTED_CLAIMS.indexOf(key) !== -1) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Developer claim \"" + key + "\" is reserved and cannot be specified.");
}
claims[key] = developerClaims[key];
}
}
}
return this.signer.getAccountId().then(function (account) {
var header = {
alg: ALGORITHM_RS256,
typ: 'JWT',
};
var iat = Math.floor(Date.now() / 1000);
var body = {
aud: FIREBASE_AUDIENCE,
iat: iat,
exp: iat + ONE_HOUR_IN_SECONDS,
iss: account,
sub: account,
uid: uid,
};
if (Object.keys(claims).length > 0) {
body.claims = claims;
}
var token = _this.encodeSegment(header) + "." + _this.encodeSegment(body);
var signPromise = _this.signer.sign(Buffer.from(token));
return Promise.all([token, signPromise]);
}).then(function (_a) {
var token = _a[0], signature = _a[1];
return token + "." + _this.encodeSegment(signature);
});
};
FirebaseTokenGenerator.prototype.encodeSegment = function (segment) {
var buffer = (segment instanceof Buffer) ? segment : Buffer.from(JSON.stringify(segment));
return utils_1.toWebSafeBase64(buffer).replace(/\=+$/, '');
};
/**
* Returns whether or not the provided developer claims are valid.
*
* @param {object} [developerClaims] Optional developer claims to validate.
* @return {boolean} True if the provided claims are valid; otherwise, false.
*/
FirebaseTokenGenerator.prototype.isDeveloperClaimsValid_ = function (developerClaims) {
if (typeof developerClaims === 'undefined') {
return true;
}
return validator.isNonNullObject(developerClaims);
};
return FirebaseTokenGenerator;
}());
exports.FirebaseTokenGenerator = FirebaseTokenGenerator;

View File

@ -0,0 +1,281 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
var jwt = require("jsonwebtoken");
var api_request_1 = require("../utils/api-request");
// Audience to use for Firebase Auth Custom tokens
var FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
exports.ALGORITHM_RS256 = 'RS256';
// URL containing the public keys for the Google certs (whose private keys are used to sign Firebase
// Auth ID tokens)
var CLIENT_CERT_URL = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';
// URL containing the public keys for Firebase session cookies. This will be updated to a different URL soon.
var SESSION_COOKIE_CERT_URL = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys';
/** User facing token information related to the Firebase ID token. */
exports.ID_TOKEN_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/verify-id-tokens',
verifyApiName: 'verifyIdToken()',
jwtName: 'Firebase ID token',
shortName: 'ID token',
expiredErrorCode: 'auth/id-token-expired',
};
/** User facing token information related to the Firebase session cookie. */
exports.SESSION_COOKIE_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/manage-cookies',
verifyApiName: 'verifySessionCookie()',
jwtName: 'Firebase session cookie',
shortName: 'session cookie',
expiredErrorCode: 'auth/session-cookie-expired',
};
/**
* Class for verifying general purpose Firebase JWTs. This verifies ID tokens and session cookies.
*/
var FirebaseTokenVerifier = /** @class */ (function () {
function FirebaseTokenVerifier(clientCertUrl, algorithm, issuer, projectId, tokenInfo) {
this.clientCertUrl = clientCertUrl;
this.algorithm = algorithm;
this.issuer = issuer;
this.projectId = projectId;
this.tokenInfo = tokenInfo;
if (!validator.isURL(clientCertUrl)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided public client certificate URL is an invalid URL.");
}
else if (!validator.isNonEmptyString(algorithm)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT algorithm is an empty string.");
}
else if (!validator.isURL(issuer)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT issuer is an invalid URL.");
}
else if (!validator.isNonNullObject(tokenInfo)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT information is not an object or null.");
}
else if (!validator.isURL(tokenInfo.url)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The provided JWT verification documentation URL is invalid.");
}
else if (!validator.isNonEmptyString(tokenInfo.verifyApiName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT verify API name must be a non-empty string.");
}
else if (!validator.isNonEmptyString(tokenInfo.jwtName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT public full name must be a non-empty string.");
}
else if (!validator.isNonEmptyString(tokenInfo.shortName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT public short name must be a non-empty string.");
}
else if (!validator.isNonEmptyString(tokenInfo.expiredErrorCode)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "The JWT expiration error code must be a non-empty string.");
}
this.shortNameArticle = tokenInfo.shortName.charAt(0).match(/[aeiou]/i) ? 'an' : 'a';
// For backward compatibility, the project ID is validated in the verification call.
}
/**
* Verifies the format and signature of a Firebase Auth JWT token.
*
* @param {string} jwtToken The Firebase Auth JWT token to verify.
* @return {Promise<object>} A promise fulfilled with the decoded claims of the Firebase Auth ID
* token.
*/
FirebaseTokenVerifier.prototype.verifyJWT = function (jwtToken) {
var _this = this;
if (!validator.isString(jwtToken)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "First argument to " + this.tokenInfo.verifyApiName + " must be a " + this.tokenInfo.jwtName + " string.");
}
if (!validator.isNonEmptyString(this.projectId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, "Must initialize app with a cert credential or set your Firebase project ID as the " +
("GOOGLE_CLOUD_PROJECT environment variable to call " + this.tokenInfo.verifyApiName + "."));
}
var fullDecodedToken = jwt.decode(jwtToken, {
complete: true,
});
var header = fullDecodedToken && fullDecodedToken.header;
var payload = fullDecodedToken && fullDecodedToken.payload;
var projectIdMatchMessage = " Make sure the " + this.tokenInfo.shortName + " comes from the same " +
"Firebase project as the service account used to authenticate this SDK.";
var verifyJwtTokenDocsMessage = " See " + this.tokenInfo.url + " " +
("for details on how to retrieve " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".");
var errorMessage;
if (!fullDecodedToken) {
errorMessage = "Decoding " + this.tokenInfo.jwtName + " failed. Make sure you passed the entire string JWT " +
("which represents " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".") + verifyJwtTokenDocsMessage;
}
else if (typeof header.kid === 'undefined') {
var isCustomToken = (payload.aud === FIREBASE_AUDIENCE);
var isLegacyCustomToken = (header.alg === 'HS256' && payload.v === 0 && 'd' in payload && 'uid' in payload.d);
if (isCustomToken) {
errorMessage = this.tokenInfo.verifyApiName + " expects " + this.shortNameArticle + " " +
(this.tokenInfo.shortName + ", but was given a custom token.");
}
else if (isLegacyCustomToken) {
errorMessage = this.tokenInfo.verifyApiName + " expects " + this.shortNameArticle + " " +
(this.tokenInfo.shortName + ", but was given a legacy custom token.");
}
else {
errorMessage = 'Firebase ID token has no "kid" claim.';
}
errorMessage += verifyJwtTokenDocsMessage;
}
else if (header.alg !== this.algorithm) {
errorMessage = this.tokenInfo.jwtName + " has incorrect algorithm. Expected \"" + this.algorithm + "\" but got " +
"\"" + header.alg + "\"." + verifyJwtTokenDocsMessage;
}
else if (payload.aud !== this.projectId) {
errorMessage = this.tokenInfo.jwtName + " has incorrect \"aud\" (audience) claim. Expected \"" +
this.projectId + "\" but got \"" + payload.aud + "\"." + projectIdMatchMessage +
verifyJwtTokenDocsMessage;
}
else if (payload.iss !== this.issuer + this.projectId) {
errorMessage = this.tokenInfo.jwtName + " has incorrect \"iss\" (issuer) claim. Expected " +
("\"" + this.issuer + "\"") + this.projectId + "\" but got \"" +
payload.iss + "\"." + projectIdMatchMessage + verifyJwtTokenDocsMessage;
}
else if (typeof payload.sub !== 'string') {
errorMessage = this.tokenInfo.jwtName + " has no \"sub\" (subject) claim." + verifyJwtTokenDocsMessage;
}
else if (payload.sub === '') {
errorMessage = this.tokenInfo.jwtName + " has an empty string \"sub\" (subject) claim." + verifyJwtTokenDocsMessage;
}
else if (payload.sub.length > 128) {
errorMessage = this.tokenInfo.jwtName + " has \"sub\" (subject) claim longer than 128 characters." +
verifyJwtTokenDocsMessage;
}
if (typeof errorMessage !== 'undefined') {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage));
}
return this.fetchPublicKeys().then(function (publicKeys) {
if (!publicKeys.hasOwnProperty(header.kid)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, _this.tokenInfo.jwtName + " has \"kid\" claim which does not correspond to a known public key. " +
("Most likely the " + _this.tokenInfo.shortName + " is expired, so get a fresh token from your ") +
"client app and try again."));
}
else {
return _this.verifyJwtSignatureWithKey(jwtToken, publicKeys[header.kid]);
}
});
};
/**
* Verifies the JWT signature using the provided public key.
* @param {string} jwtToken The JWT token to verify.
* @param {string} publicKey The public key certificate.
* @return {Promise<object>} A promise that resolves with the decoded JWT claims on successful
* verification.
*/
FirebaseTokenVerifier.prototype.verifyJwtSignatureWithKey = function (jwtToken, publicKey) {
var _this = this;
var errorMessage;
var verifyJwtTokenDocsMessage = " See " + this.tokenInfo.url + " " +
("for details on how to retrieve " + this.shortNameArticle + " " + this.tokenInfo.shortName + ".");
return new Promise(function (resolve, reject) {
jwt.verify(jwtToken, publicKey, {
algorithms: [_this.algorithm],
}, function (error, decodedToken) {
if (error) {
if (error.name === 'TokenExpiredError') {
errorMessage = _this.tokenInfo.jwtName + " has expired. Get a fresh token from your client " +
("app and try again (" + _this.tokenInfo.expiredErrorCode + ").") + verifyJwtTokenDocsMessage;
}
else if (error.name === 'JsonWebTokenError') {
errorMessage = _this.tokenInfo.jwtName + " has invalid signature." + verifyJwtTokenDocsMessage;
}
return reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage));
}
else {
decodedToken.uid = decodedToken.sub;
resolve(decodedToken);
}
});
});
};
/**
* Fetches the public keys for the Google certs.
*
* @return {Promise<object>} A promise fulfilled with public keys for the Google certs.
*/
FirebaseTokenVerifier.prototype.fetchPublicKeys = function () {
var _this = this;
var publicKeysExist = (typeof this.publicKeys !== 'undefined');
var publicKeysExpiredExists = (typeof this.publicKeysExpireAt !== 'undefined');
var publicKeysStillValid = (publicKeysExpiredExists && Date.now() < this.publicKeysExpireAt);
if (publicKeysExist && publicKeysStillValid) {
return Promise.resolve(this.publicKeys);
}
var client = new api_request_1.HttpClient();
var request = {
method: 'GET',
url: this.clientCertUrl,
};
return client.send(request).then(function (resp) {
if (!resp.isJson() || resp.data.error) {
// Treat all non-json messages and messages with an 'error' field as
// error responses.
throw new api_request_1.HttpError(resp);
}
if (resp.headers.hasOwnProperty('cache-control')) {
var cacheControlHeader = resp.headers['cache-control'];
var parts = cacheControlHeader.split(',');
parts.forEach(function (part) {
var subParts = part.trim().split('=');
if (subParts[0] === 'max-age') {
var maxAge = +subParts[1];
_this.publicKeysExpireAt = Date.now() + (maxAge * 1000);
}
});
}
_this.publicKeys = resp.data;
return resp.data;
}).catch(function (err) {
if (err instanceof api_request_1.HttpError) {
var errorMessage = 'Error fetching public keys for Google certs: ';
var resp = err.response;
if (resp.isJson() && resp.data.error) {
errorMessage += "" + resp.data.error;
if (resp.data.error_description) {
errorMessage += ' (' + resp.data.error_description + ')';
}
}
else {
errorMessage += "" + resp.text;
}
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, errorMessage);
}
throw err;
});
};
return FirebaseTokenVerifier;
}());
exports.FirebaseTokenVerifier = FirebaseTokenVerifier;
/**
* Creates a new FirebaseTokenVerifier to verify Firebase ID tokens.
*
* @param {string} projectId Project ID string.
* @return {FirebaseTokenVerifier}
*/
function createIdTokenVerifier(projectId) {
return new FirebaseTokenVerifier(CLIENT_CERT_URL, exports.ALGORITHM_RS256, 'https://securetoken.google.com/', projectId, exports.ID_TOKEN_INFO);
}
exports.createIdTokenVerifier = createIdTokenVerifier;
/**
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
*
* @param {string} projectId Project ID string.
* @return {FirebaseTokenVerifier}
*/
function createSessionCookieVerifier(projectId) {
return new FirebaseTokenVerifier(SESSION_COOKIE_CERT_URL, exports.ALGORITHM_RS256, 'https://session.firebase.google.com/', projectId, exports.SESSION_COOKIE_INFO);
}
exports.createSessionCookieVerifier = createSessionCookieVerifier;

View File

@ -0,0 +1,316 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var deep_copy_1 = require("../utils/deep-copy");
var utils = require("../utils");
var validator = require("../utils/validator");
var error_1 = require("../utils/error");
/**
* @param {any} obj The object to check for number field within.
* @param {string} key The entry key.
* @return {number|undefined} The corresponding number if available.
*/
function getNumberField(obj, key) {
if (typeof obj[key] !== 'undefined' && obj[key] !== null) {
return parseInt(obj[key].toString(), 10);
}
return undefined;
}
/**
* Converts a UserImportRecord to a UploadAccountUser object. Throws an error when invalid
* fields are provided.
* @param {UserImportRecord} user The UserImportRecord to conver to UploadAccountUser.
* @param {ValidatorFunction=} userValidator The user validator function.
* @return {UploadAccountUser} The corresponding UploadAccountUser to return.
*/
function populateUploadAccountUser(user, userValidator) {
var result = {
localId: user.uid,
email: user.email,
emailVerified: user.emailVerified,
displayName: user.displayName,
disabled: user.disabled,
photoUrl: user.photoURL,
phoneNumber: user.phoneNumber,
providerUserInfo: [],
customAttributes: user.customClaims && JSON.stringify(user.customClaims),
};
if (typeof user.passwordHash !== 'undefined') {
if (!validator.isBuffer(user.passwordHash)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
}
result.passwordHash = utils.toWebSafeBase64(user.passwordHash);
}
if (typeof user.passwordSalt !== 'undefined') {
if (!validator.isBuffer(user.passwordSalt)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
}
result.salt = utils.toWebSafeBase64(user.passwordSalt);
}
if (validator.isNonNullObject(user.metadata)) {
if (validator.isNonEmptyString(user.metadata.creationTime)) {
result.createdAt = new Date(user.metadata.creationTime).getTime();
}
if (validator.isNonEmptyString(user.metadata.lastSignInTime)) {
result.lastLoginAt = new Date(user.metadata.lastSignInTime).getTime();
}
}
if (validator.isArray(user.providerData)) {
user.providerData.forEach(function (providerData) {
result.providerUserInfo.push({
providerId: providerData.providerId,
rawId: providerData.uid,
email: providerData.email,
displayName: providerData.displayName,
photoUrl: providerData.photoURL,
});
});
}
// Remove blank fields.
var key;
for (key in result) {
if (typeof result[key] === 'undefined') {
delete result[key];
}
}
if (result.providerUserInfo.length === 0) {
delete result.providerUserInfo;
}
// Validate the constructured user individual request. This will throw if an error
// is detected.
if (typeof userValidator === 'function') {
userValidator(result);
}
return result;
}
/**
* Class that provides a helper for building/validating uploadAccount requests and
* UserImportResult responses.
*/
var UserImportBuilder = /** @class */ (function () {
/**
* @param {UserImportRecord[]} users The list of user records to import.
* @param {UserImportOptions=} options The import options which includes hashing
* algorithm details.
* @param {ValidatorFunction=} userRequestValidator The user request validator function.
* @constructor
*/
function UserImportBuilder(users, options, userRequestValidator) {
this.users = users;
this.options = options;
this.userRequestValidator = userRequestValidator;
this.requiresHashOptions = false;
this.validatedUsers = [];
this.userImportResultErrors = [];
this.indexMap = {};
this.validatedUsers = this.populateUsers(this.users, this.userRequestValidator);
this.validatedOptions = this.populateOptions(this.options, this.requiresHashOptions);
}
/**
* Returns the corresponding constructed uploadAccount request.
* @return {UploadAccountRequest} The constructed uploadAccount request.
*/
UserImportBuilder.prototype.buildRequest = function () {
var users = this.validatedUsers.map(function (user) {
return deep_copy_1.deepCopy(user);
});
return deep_copy_1.deepExtend({ users: users }, deep_copy_1.deepCopy(this.validatedOptions));
};
/**
* Populates the UserImportResult using the client side detected errors and the server
* side returned errors.
* @return {UserImportResult} The user import result based on the returned failed
* uploadAccount response.
*/
UserImportBuilder.prototype.buildResponse = function (failedUploads) {
var _this = this;
// Initialize user import result.
var importResult = {
successCount: this.users.length - this.userImportResultErrors.length,
failureCount: this.userImportResultErrors.length,
errors: deep_copy_1.deepCopy(this.userImportResultErrors),
};
importResult.failureCount += failedUploads.length;
importResult.successCount -= failedUploads.length;
failedUploads.forEach(function (failedUpload) {
importResult.errors.push({
// Map backend request index to original developer provided array index.
index: _this.indexMap[failedUpload.index],
error: new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_USER_IMPORT, failedUpload.message),
});
});
// Sort errors by index.
importResult.errors.sort(function (a, b) {
return a.index - b.index;
});
// Return sorted result.
return importResult;
};
/**
* Validates and returns the hashing options of the uploadAccount request.
* Throws an error whenever an invalid or missing options is detected.
* @param {UserImportOptions} options The UserImportOptions.
* @param {boolean} requiresHashOptions Whether to require hash options.
* @return {UploadAccountOptions} The populated UploadAccount options.
*/
UserImportBuilder.prototype.populateOptions = function (options, requiresHashOptions) {
var populatedOptions;
if (!requiresHashOptions) {
return {};
}
if (!validator.isNonNullObject(options.hash)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_HASH_ALGORITHM, "\"hash.algorithm\" is missing from the provided \"UserImportOptions\".");
}
if (typeof options.hash.algorithm === 'undefined' ||
!validator.isNonEmptyString(options.hash.algorithm)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, "\"hash.algorithm\" must be a string matching the list of supported algorithms.");
}
var rounds;
switch (options.hash.algorithm) {
case 'HMAC_SHA512':
case 'HMAC_SHA256':
case 'HMAC_SHA1':
case 'HMAC_MD5':
if (!validator.isBuffer(options.hash.key)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, "A non-empty \"hash.key\" byte buffer must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
signerKey: utils.toWebSafeBase64(options.hash.key),
};
break;
case 'MD5':
case 'SHA1':
case 'SHA256':
case 'SHA512':
case 'PBKDF_SHA1':
case 'PBKDF2_SHA256':
rounds = getNumberField(options.hash, 'rounds');
if (isNaN(rounds) || rounds < 0 || rounds > 120000) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, "A valid \"hash.rounds\" number between 0 and 120000 must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
rounds: rounds,
};
break;
case 'SCRYPT':
if (!validator.isBuffer(options.hash.key)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, "A \"hash.key\" byte buffer must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
rounds = getNumberField(options.hash, 'rounds');
if (isNaN(rounds) || rounds <= 0 || rounds > 8) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, "A valid \"hash.rounds\" number between 1 and 8 must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
var memoryCost = getNumberField(options.hash, 'memoryCost');
if (isNaN(memoryCost) || memoryCost <= 0 || memoryCost > 14) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, "A valid \"hash.memoryCost\" number between 1 and 14 must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
if (typeof options.hash.saltSeparator !== 'undefined' &&
!validator.isBuffer(options.hash.saltSeparator)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR, "\"hash.saltSeparator\" must be a byte buffer.");
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
signerKey: utils.toWebSafeBase64(options.hash.key),
rounds: rounds,
memoryCost: memoryCost,
saltSeparator: utils.toWebSafeBase64(options.hash.saltSeparator || Buffer.from('')),
};
break;
case 'BCRYPT':
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
};
break;
case 'STANDARD_SCRYPT':
var cpuMemCost = getNumberField(options.hash, 'memoryCost');
if (isNaN(cpuMemCost)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, "A valid \"hash.memoryCost\" number must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
var parallelization = getNumberField(options.hash, 'parallelization');
if (isNaN(parallelization)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_PARALLELIZATION, "A valid \"hash.parallelization\" number must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
var blockSize = getNumberField(options.hash, 'blockSize');
if (isNaN(blockSize)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE, "A valid \"hash.blockSize\" number must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
var dkLen = getNumberField(options.hash, 'derivedKeyLength');
if (isNaN(dkLen)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH, "A valid \"hash.derivedKeyLength\" number must be provided for " +
("hash algorithm " + options.hash.algorithm + "."));
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
cpuMemCost: cpuMemCost,
parallelization: parallelization,
blockSize: blockSize,
dkLen: dkLen,
};
break;
default:
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, "Unsupported hash algorithm provider \"" + options.hash.algorithm + "\".");
}
return populatedOptions;
};
/**
* Validates and returns the users list of the uploadAccount request.
* Whenever a user with an error is detected, the error is cached and will later be
* merged into the user import result. This allows the processing of valid users without
* failing early on the first error detected.
* @param {UserImportRecord[]} users The UserImportRecords to convert to UnploadAccountUser
* objects.
* @param {ValidatorFunction=} userValidator The user validator function.
* @return {UploadAccountUser[]} The populated uploadAccount users.
*/
UserImportBuilder.prototype.populateUsers = function (users, userValidator) {
var _this = this;
var populatedUsers = [];
users.forEach(function (user, index) {
try {
var result = populateUploadAccountUser(user, userValidator);
if (typeof result.passwordHash !== 'undefined') {
_this.requiresHashOptions = true;
}
// Only users that pass client screening will be passed to backend for processing.
populatedUsers.push(result);
// Map user's index (the one to be sent to backend) to original developer provided array.
_this.indexMap[populatedUsers.length - 1] = index;
}
catch (error) {
// Save the client side error with respect to the developer provided array.
_this.userImportResultErrors.push({
index: index,
error: error,
});
}
});
return populatedUsers;
};
return UserImportBuilder;
}());
exports.UserImportBuilder = UserImportBuilder;

View File

@ -0,0 +1,174 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var deep_copy_1 = require("../utils/deep-copy");
var utils = require("../utils");
var error_1 = require("../utils/error");
/**
* Parses a time stamp string or number and returns the corresponding date if valid.
*
* @param {any} time The unix timestamp string or number in milliseconds.
* @return {string} The corresponding date as a UTC string, if valid.
*/
function parseDate(time) {
try {
var date = new Date(parseInt(time, 10));
if (!isNaN(date.getTime())) {
return date.toUTCString();
}
}
catch (e) {
// Do nothing. null will be returned.
}
return null;
}
/**
* User metadata class that provides metadata information like user account creation
* and last sign in time.
*
* @param {object} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
var UserMetadata = /** @class */ (function () {
function UserMetadata(response) {
// Creation date should always be available but due to some backend bugs there
// were cases in the past where users did not have creation date properly set.
// This included legacy Firebase migrating project users and some anonymous users.
// These bugs have already been addressed since then.
utils.addReadonlyGetter(this, 'creationTime', parseDate(response.createdAt));
utils.addReadonlyGetter(this, 'lastSignInTime', parseDate(response.lastLoginAt));
}
/** @return {object} The plain object representation of the user's metadata. */
UserMetadata.prototype.toJSON = function () {
return {
lastSignInTime: this.lastSignInTime,
creationTime: this.creationTime,
};
};
return UserMetadata;
}());
exports.UserMetadata = UserMetadata;
/**
* User info class that provides provider user information for different
* Firebase providers like google.com, facebook.com, password, etc.
*
* @param {object} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
var UserInfo = /** @class */ (function () {
function UserInfo(response) {
// Provider user id and provider id are required.
if (!response.rawId || !response.providerId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user info response');
}
utils.addReadonlyGetter(this, 'uid', response.rawId);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'providerId', response.providerId);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
}
/** @return {object} The plain object representation of the current provider data. */
UserInfo.prototype.toJSON = function () {
return {
uid: this.uid,
displayName: this.displayName,
email: this.email,
photoURL: this.photoURL,
providerId: this.providerId,
phoneNumber: this.phoneNumber,
};
};
return UserInfo;
}());
exports.UserInfo = UserInfo;
/**
* User record class that defines the Firebase user object populated from
* the Firebase Auth getAccountInfo response.
*
* @param {any} response The server side response returned from the getAccountInfo
* endpoint.
* @constructor
*/
var UserRecord = /** @class */ (function () {
function UserRecord(response) {
// The Firebase user id is required.
if (!response.localId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user response');
}
utils.addReadonlyGetter(this, 'uid', response.localId);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'emailVerified', !!response.emailVerified);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
// If disabled is not provided, the account is enabled by default.
utils.addReadonlyGetter(this, 'disabled', response.disabled || false);
utils.addReadonlyGetter(this, 'metadata', new UserMetadata(response));
var providerData = [];
for (var _i = 0, _a = (response.providerUserInfo || []); _i < _a.length; _i++) {
var entry = _a[_i];
providerData.push(new UserInfo(entry));
}
utils.addReadonlyGetter(this, 'providerData', providerData);
utils.addReadonlyGetter(this, 'passwordHash', response.passwordHash);
utils.addReadonlyGetter(this, 'passwordSalt', response.salt);
try {
utils.addReadonlyGetter(this, 'customClaims', JSON.parse(response.customAttributes));
}
catch (e) {
// Ignore error.
utils.addReadonlyGetter(this, 'customClaims', undefined);
}
var validAfterTime = null;
// Convert validSince first to UTC milliseconds and then to UTC date string.
if (typeof response.validSince !== 'undefined') {
validAfterTime = parseDate(response.validSince * 1000);
}
utils.addReadonlyGetter(this, 'tokensValidAfterTime', validAfterTime);
}
/** @return {object} The plain object representation of the user record. */
UserRecord.prototype.toJSON = function () {
var json = {
uid: this.uid,
email: this.email,
emailVerified: this.emailVerified,
displayName: this.displayName,
photoURL: this.photoURL,
phoneNumber: this.phoneNumber,
disabled: this.disabled,
// Convert metadata to json.
metadata: this.metadata.toJSON(),
passwordHash: this.passwordHash,
passwordSalt: this.passwordSalt,
customClaims: deep_copy_1.deepCopy(this.customClaims),
tokensValidAfterTime: this.tokensValidAfterTime,
};
json.providerData = [];
for (var _i = 0, _a = this.providerData; _i < _a.length; _i++) {
var entry = _a[_i];
// Convert each provider data to json.
json.providerData.push(entry.toJSON());
}
return json;
};
return UserRecord;
}());
exports.UserRecord = UserRecord;

View File

@ -0,0 +1,82 @@
/*! firebase-admin v6.4.0 */
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
/**
* Internals of a Database instance.
*/
var DatabaseInternals = /** @class */ (function () {
function DatabaseInternals() {
this.databases = {};
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
DatabaseInternals.prototype.delete = function () {
for (var _i = 0, _a = Object.keys(this.databases); _i < _a.length; _i++) {
var dbUrl = _a[_i];
var db = this.databases[dbUrl];
db.INTERNAL.delete();
}
return Promise.resolve(undefined);
};
return DatabaseInternals;
}());
var DatabaseService = /** @class */ (function () {
function DatabaseService(app) {
this.INTERNAL = new DatabaseInternals();
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseDatabaseError({
code: 'invalid-argument',
message: 'First argument passed to admin.database() must be a valid Firebase app instance.',
});
}
this.appInternal = app;
}
Object.defineProperty(DatabaseService.prototype, "app", {
/**
* Returns the app associated with this DatabaseService instance.
*
* @return {FirebaseApp} The app associated with this DatabaseService instance.
*/
get: function () {
return this.appInternal;
},
enumerable: true,
configurable: true
});
DatabaseService.prototype.getDatabase = function (url) {
var dbUrl = this.ensureUrl(url);
if (!validator.isNonEmptyString(dbUrl)) {
throw new error_1.FirebaseDatabaseError({
code: 'invalid-argument',
message: 'Database URL must be a valid, non-empty URL string.',
});
}
var db = this.INTERNAL.databases[dbUrl];
if (typeof db === 'undefined') {
var rtdb = require('@firebase/database');
var version = require('../../package.json').version;
db = rtdb.initStandalone(this.appInternal, dbUrl, version).instance;
this.INTERNAL.databases[dbUrl] = db;
}
return db;
};
DatabaseService.prototype.ensureUrl = function (url) {
if (typeof url !== 'undefined') {
return url;
}
else if (typeof this.appInternal.options.databaseURL !== 'undefined') {
return this.appInternal.options.databaseURL;
}
throw new error_1.FirebaseDatabaseError({
code: 'invalid-argument',
message: 'Can\'t determine Firebase Database URL.',
});
};
return DatabaseService;
}());
exports.DatabaseService = DatabaseService;

View File

@ -0,0 +1,30 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
var firebase_namespace_1 = require("./firebase-namespace");
var firebaseAdmin = new firebase_namespace_1.FirebaseNamespace();
// Inject a circular default export to allow users to use both:
//
// import firebaseAdmin from 'firebase-admin';
// which becomes: var firebaseAdmin = require('firebase-admin').default;
//
// as well as the more correct:
//
// import * as firebaseAdmin from 'firebase-admin';
// which becomes: var firebaseAdmin = require('firebase-admin');
firebaseAdmin.default = firebaseAdmin;
module.exports = firebaseAdmin;

View File

@ -0,0 +1,374 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var credential_1 = require("./auth/credential");
var validator = require("./utils/validator");
var deep_copy_1 = require("./utils/deep-copy");
var error_1 = require("./utils/error");
/**
* Internals of a FirebaseApp instance.
*/
var FirebaseAppInternals = /** @class */ (function () {
function FirebaseAppInternals(credential_) {
this.credential_ = credential_;
this.isDeleted_ = false;
this.tokenListeners_ = [];
}
/**
* Gets an auth token for the associated app.
*
* @param {boolean} forceRefresh Whether or not to force a token refresh.
* @return {Promise<FirebaseAccessToken>} A Promise that will be fulfilled with the current or
* new token.
*/
FirebaseAppInternals.prototype.getToken = function (forceRefresh) {
var _this = this;
var expired = this.cachedToken_ && this.cachedToken_.expirationTime < Date.now();
if (this.cachedTokenPromise_ && !forceRefresh && !expired) {
return this.cachedTokenPromise_
.catch(function (error) {
// Update the cached token promise to avoid caching errors. Set it to resolve with the
// cached token if we have one (and return that promise since the token has still not
// expired).
if (_this.cachedToken_) {
_this.cachedTokenPromise_ = Promise.resolve(_this.cachedToken_);
return _this.cachedTokenPromise_;
}
// Otherwise, set the cached token promise to null so that it will force a refresh next
// time getToken() is called.
_this.cachedTokenPromise_ = null;
// And re-throw the caught error.
throw error;
});
}
else {
// Clear the outstanding token refresh timeout. This is a noop if the timeout is undefined.
clearTimeout(this.tokenRefreshTimeout_);
// this.credential_ may be an external class; resolving it in a promise helps us
// protect against exceptions and upgrades the result to a promise in all cases.
this.cachedTokenPromise_ = Promise.resolve(this.credential_.getAccessToken())
.then(function (result) {
// Since the developer can provide the credential implementation, we want to weakly verify
// the return type until the type is properly exported.
if (!validator.isNonNullObject(result) ||
typeof result.expires_in !== 'number' ||
typeof result.access_token !== 'string') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, "Invalid access token generated: \"" + JSON.stringify(result) + "\". Valid access " +
'tokens must be an object with the "expires_in" (number) and "access_token" ' +
'(string) properties.');
}
var token = {
accessToken: result.access_token,
expirationTime: Date.now() + (result.expires_in * 1000),
};
var hasAccessTokenChanged = (_this.cachedToken_ && _this.cachedToken_.accessToken !== token.accessToken);
var hasExpirationChanged = (_this.cachedToken_ && _this.cachedToken_.expirationTime !== token.expirationTime);
if (!_this.cachedToken_ || hasAccessTokenChanged || hasExpirationChanged) {
_this.cachedToken_ = token;
_this.tokenListeners_.forEach(function (listener) {
listener(token.accessToken);
});
}
// Establish a timeout to proactively refresh the token every minute starting at five
// minutes before it expires. Once a token refresh succeeds, no further retries are
// needed; if it fails, retry every minute until the token expires (resulting in a total
// of four retries: at 4, 3, 2, and 1 minutes).
var refreshTimeInSeconds = (result.expires_in - (5 * 60));
var numRetries = 4;
// In the rare cases the token is short-lived (that is, it expires in less than five
// minutes from when it was fetched), establish the timeout to refresh it after the
// current minute ends and update the number of retries that should be attempted before
// the token expires.
if (refreshTimeInSeconds <= 0) {
refreshTimeInSeconds = result.expires_in % 60;
numRetries = Math.floor(result.expires_in / 60) - 1;
}
// The token refresh timeout keeps the Node.js process alive, so only create it if this
// instance has not already been deleted.
if (numRetries && !_this.isDeleted_) {
_this.setTokenRefreshTimeout(refreshTimeInSeconds * 1000, numRetries);
}
return token;
})
.catch(function (error) {
var errorMessage = (typeof error === 'string') ? error : error.message;
errorMessage = 'Credential implementation provided to initializeApp() via the ' +
'"credential" property failed to fetch a valid Google OAuth2 access token with the ' +
("following error: \"" + errorMessage + "\".");
if (errorMessage.indexOf('invalid_grant') !== -1) {
errorMessage += ' There are two likely causes: (1) your server time is not properly ' +
'synced or (2) your certificate key file has been revoked. To solve (1), re-sync the ' +
'time on your server. To solve (2), make sure the key ID for your key file is still ' +
'present at https://console.firebase.google.com/iam-admin/serviceaccounts/project. If ' +
'not, generate a new key file at ' +
'https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk.';
}
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_CREDENTIAL, errorMessage);
});
return this.cachedTokenPromise_;
}
};
/**
* Adds a listener that is called each time a token changes.
*
* @param {function(string)} listener The listener that will be called with each new token.
*/
FirebaseAppInternals.prototype.addAuthTokenListener = function (listener) {
this.tokenListeners_.push(listener);
if (this.cachedToken_) {
listener(this.cachedToken_.accessToken);
}
};
/**
* Removes a token listener.
*
* @param {function(string)} listener The listener to remove.
*/
FirebaseAppInternals.prototype.removeAuthTokenListener = function (listener) {
this.tokenListeners_ = this.tokenListeners_.filter(function (other) { return other !== listener; });
};
/**
* Deletes the FirebaseAppInternals instance.
*/
FirebaseAppInternals.prototype.delete = function () {
this.isDeleted_ = true;
// Clear the token refresh timeout so it doesn't keep the Node.js process alive.
clearTimeout(this.tokenRefreshTimeout_);
};
/**
* Establishes timeout to refresh the Google OAuth2 access token used by the SDK.
*
* @param {number} delayInMilliseconds The delay to use for the timeout.
* @param {number} numRetries The number of times to retry fetching a new token if the prior fetch
* failed.
*/
FirebaseAppInternals.prototype.setTokenRefreshTimeout = function (delayInMilliseconds, numRetries) {
var _this = this;
this.tokenRefreshTimeout_ = setTimeout(function () {
_this.getToken(/* forceRefresh */ true)
.catch(function (error) {
// Ignore the error since this might just be an intermittent failure. If we really cannot
// refresh the token, an error will be logged once the existing token expires and we try
// to fetch a fresh one.
if (numRetries > 0) {
_this.setTokenRefreshTimeout(60 * 1000, numRetries - 1);
}
});
}, delayInMilliseconds);
};
return FirebaseAppInternals;
}());
exports.FirebaseAppInternals = FirebaseAppInternals;
/**
* Global context object for a collection of services using a shared authentication state.
*/
var FirebaseApp = /** @class */ (function () {
function FirebaseApp(options, name, firebaseInternals_) {
var _this = this;
this.firebaseInternals_ = firebaseInternals_;
this.services_ = {};
this.isDeleted_ = false;
this.name_ = name;
this.options_ = deep_copy_1.deepCopy(options);
if (!validator.isNonNullObject(this.options_)) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_OPTIONS, "Invalid Firebase app options passed as the first argument to initializeApp() for the " +
("app named \"" + this.name_ + "\". Options must be a non-null object."));
}
var hasCredential = ('credential' in this.options_);
if (!hasCredential) {
this.options_.credential = new credential_1.ApplicationDefaultCredential();
}
var credential = this.options_.credential;
if (typeof credential !== 'object' || credential === null || typeof credential.getAccessToken !== 'function') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_OPTIONS, "Invalid Firebase app options passed as the first argument to initializeApp() for the " +
("app named \"" + this.name_ + "\". The \"credential\" property must be an object which implements ") +
"the Credential interface.");
}
Object.keys(firebaseInternals_.serviceFactories).forEach(function (serviceName) {
// Defer calling createService() until the service is accessed
_this[serviceName] = _this.getService_.bind(_this, serviceName);
});
this.INTERNAL = new FirebaseAppInternals(this.options_.credential);
}
/**
* Returns the Auth service instance associated with this app.
*
* @return {Auth} The Auth service instance of this app.
*/
FirebaseApp.prototype.auth = function () {
var _this = this;
return this.ensureService_('auth', function () {
var authService = require('./auth/auth').Auth;
return new authService(_this);
});
};
/**
* Returns the Database service for the specified URL, and the current app.
*
* @return {Database} The Database service instance of this app.
*/
FirebaseApp.prototype.database = function (url) {
var _this = this;
var service = this.ensureService_('database', function () {
var dbService = require('./database/database').DatabaseService;
return new dbService(_this);
});
return service.getDatabase(url);
};
/**
* Returns the Messaging service instance associated with this app.
*
* @return {Messaging} The Messaging service instance of this app.
*/
FirebaseApp.prototype.messaging = function () {
var _this = this;
return this.ensureService_('messaging', function () {
var messagingService = require('./messaging/messaging').Messaging;
return new messagingService(_this);
});
};
/**
* Returns the Storage service instance associated with this app.
*
* @return {Storage} The Storage service instance of this app.
*/
FirebaseApp.prototype.storage = function () {
var _this = this;
return this.ensureService_('storage', function () {
var storageService = require('./storage/storage').Storage;
return new storageService(_this);
});
};
FirebaseApp.prototype.firestore = function () {
var _this = this;
var service = this.ensureService_('firestore', function () {
var firestoreService = require('./firestore/firestore').FirestoreService;
return new firestoreService(_this);
});
return service.client;
};
/**
* Returns the InstanceId service instance associated with this app.
*
* @return {InstanceId} The InstanceId service instance of this app.
*/
FirebaseApp.prototype.instanceId = function () {
var _this = this;
return this.ensureService_('iid', function () {
var iidService = require('./instance-id/instance-id').InstanceId;
return new iidService(_this);
});
};
/**
* Returns the ProjectManagement service instance associated with this app.
*
* @return {ProjectManagement} The ProjectManagement service instance of this app.
*/
FirebaseApp.prototype.projectManagement = function () {
var _this = this;
return this.ensureService_('project-management', function () {
var projectManagementService = require('./project-management/project-management').ProjectManagement;
return new projectManagementService(_this);
});
};
Object.defineProperty(FirebaseApp.prototype, "name", {
/**
* Returns the name of the FirebaseApp instance.
*
* @return {string} The name of the FirebaseApp instance.
*/
get: function () {
this.checkDestroyed_();
return this.name_;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseApp.prototype, "options", {
/**
* Returns the options for the FirebaseApp instance.
*
* @return {FirebaseAppOptions} The options for the FirebaseApp instance.
*/
get: function () {
this.checkDestroyed_();
return deep_copy_1.deepCopy(this.options_);
},
enumerable: true,
configurable: true
});
/**
* Deletes the FirebaseApp instance.
*
* @return {Promise<void>} An empty Promise fulfilled once the FirebaseApp instance is deleted.
*/
FirebaseApp.prototype.delete = function () {
var _this = this;
this.checkDestroyed_();
this.firebaseInternals_.removeApp(this.name_);
this.INTERNAL.delete();
return Promise.all(Object.keys(this.services_).map(function (serviceName) {
return _this.services_[serviceName].INTERNAL.delete();
})).then(function () {
_this.services_ = {};
_this.isDeleted_ = true;
});
};
FirebaseApp.prototype.ensureService_ = function (serviceName, initializer) {
this.checkDestroyed_();
var service;
if (serviceName in this.services_) {
service = this.services_[serviceName];
}
else {
service = initializer();
this.services_[serviceName] = service;
}
return service;
};
/**
* Returns the service instance associated with this FirebaseApp instance (creating it on demand
* if needed). This is used for looking up monkeypatched service instances.
*
* @param {string} serviceName The name of the service instance to return.
* @return {FirebaseServiceInterface} The service instance with the provided name.
*/
FirebaseApp.prototype.getService_ = function (serviceName) {
this.checkDestroyed_();
if (!(serviceName in this.services_)) {
this.services_[serviceName] = this.firebaseInternals_.serviceFactories[serviceName](this, this.extendApp_.bind(this));
}
return this.services_[serviceName];
};
/**
* Callback function used to extend an App instance at the time of service instance creation.
*/
FirebaseApp.prototype.extendApp_ = function (props) {
deep_copy_1.deepExtend(this, props);
};
/**
* Throws an Error if the FirebaseApp instance has already been deleted.
*/
FirebaseApp.prototype.checkDestroyed_ = function () {
if (this.isDeleted_) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.APP_DELETED, "Firebase app named \"" + this.name_ + "\" has already been deleted.");
}
};
return FirebaseApp;
}());
exports.FirebaseApp = FirebaseApp;

View File

@ -0,0 +1,410 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var fs = require("fs");
var deep_copy_1 = require("./utils/deep-copy");
var error_1 = require("./utils/error");
var firebase_app_1 = require("./firebase-app");
var credential_1 = require("./auth/credential");
var validator = require("./utils/validator");
var DEFAULT_APP_NAME = '[DEFAULT]';
/**
* Constant holding the environment variable name with the default config.
* If the environment variable contains a string that starts with '{' it will be parsed as JSON,
* otherwise it will be assumed to be pointing to a file.
*/
exports.FIREBASE_CONFIG_VAR = 'FIREBASE_CONFIG';
var globalAppDefaultCred;
var globalCertCreds = {};
var globalRefreshTokenCreds = {};
/**
* Internals of a FirebaseNamespace instance.
*/
var FirebaseNamespaceInternals = /** @class */ (function () {
function FirebaseNamespaceInternals(firebase_) {
this.firebase_ = firebase_;
this.serviceFactories = {};
this.apps_ = {};
this.appHooks_ = {};
}
/**
* Initializes the FirebaseApp instance.
*
* @param {FirebaseAppOptions} options Optional options for the FirebaseApp instance. If none present
* will try to initialize from the FIREBASE_CONFIG environment variable.
* If the environment variable contains a string that starts with '{'
* it will be parsed as JSON,
* otherwise it will be assumed to be pointing to a file.
* @param {string} [appName] Optional name of the FirebaseApp instance.
*
* @return {FirebaseApp} A new FirebaseApp instance.
*/
FirebaseNamespaceInternals.prototype.initializeApp = function (options, appName) {
if (appName === void 0) { appName = DEFAULT_APP_NAME; }
if (typeof options === 'undefined') {
options = this.loadOptionsFromEnvVar();
options.credential = new credential_1.ApplicationDefaultCredential();
}
if (typeof appName !== 'string' || appName === '') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "Invalid Firebase app name \"" + appName + "\" provided. App name must be a non-empty string.");
}
else if (appName in this.apps_) {
if (appName === DEFAULT_APP_NAME) {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.DUPLICATE_APP, 'The default Firebase app already exists. This means you called initializeApp() ' +
'more than once without providing an app name as the second argument. In most cases ' +
'you only need to call initializeApp() once. But if you do want to initialize ' +
'multiple apps, pass a second argument to initializeApp() to give each app a unique ' +
'name.');
}
else {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.DUPLICATE_APP, "Firebase app named \"" + appName + "\" already exists. This means you called initializeApp() " +
'more than once with the same app name as the second argument. Make sure you provide a ' +
'unique name every time you call initializeApp().');
}
}
var app = new firebase_app_1.FirebaseApp(options, appName, this);
this.apps_[appName] = app;
this.callAppHooks_(app, 'create');
return app;
};
/**
* Returns the FirebaseApp instance with the provided name (or the default FirebaseApp instance
* if no name is provided).
*
* @param {string} [appName=DEFAULT_APP_NAME] Optional name of the FirebaseApp instance to return.
* @return {FirebaseApp} The FirebaseApp instance which has the provided name.
*/
FirebaseNamespaceInternals.prototype.app = function (appName) {
if (appName === void 0) { appName = DEFAULT_APP_NAME; }
if (typeof appName !== 'string' || appName === '') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "Invalid Firebase app name \"" + appName + "\" provided. App name must be a non-empty string.");
}
else if (!(appName in this.apps_)) {
var errorMessage = (appName === DEFAULT_APP_NAME)
? 'The default Firebase app does not exist. ' : "Firebase app named \"" + appName + "\" does not exist. ";
errorMessage += 'Make sure you call initializeApp() before using any of the Firebase services.';
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NO_APP, errorMessage);
}
return this.apps_[appName];
};
Object.defineProperty(FirebaseNamespaceInternals.prototype, "apps", {
/*
* Returns an array of all the non-deleted FirebaseApp instances.
*
* @return {Array<FirebaseApp>} An array of all the non-deleted FirebaseApp instances
*/
get: function () {
var _this = this;
// Return a copy so the caller cannot mutate the array
return Object.keys(this.apps_).map(function (appName) { return _this.apps_[appName]; });
},
enumerable: true,
configurable: true
});
/*
* Removes the specified FirebaseApp instance.
*
* @param {string} appName The name of the FirebaseApp instance to remove.
*/
FirebaseNamespaceInternals.prototype.removeApp = function (appName) {
if (typeof appName === 'undefined') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_NAME, "No Firebase app name provided. App name must be a non-empty string.");
}
var appToRemove = this.app(appName);
this.callAppHooks_(appToRemove, 'delete');
delete this.apps_[appName];
};
/*
* Registers a new service on this Firebase namespace.
*
* @param {string} serviceName The name of the Firebase service to register.
* @param {FirebaseServiceFactory} createService A factory method to generate an instance of the Firebase service.
* @param {object} [serviceProperties] Optional properties to extend this Firebase namespace with.
* @param {AppHook} [appHook] Optional callback that handles app-related events like app creation and deletion.
* @return {FirebaseServiceNamespace<FirebaseServiceInterface>} The Firebase service's namespace.
*/
FirebaseNamespaceInternals.prototype.registerService = function (serviceName, createService, serviceProperties, appHook) {
var _this = this;
var errorMessage;
if (typeof serviceName === 'undefined') {
errorMessage = "No service name provided. Service name must be a non-empty string.";
}
else if (typeof serviceName !== 'string' || serviceName === '') {
errorMessage = "Invalid service name \"" + serviceName + "\" provided. Service name must be a non-empty string.";
}
else if (serviceName in this.serviceFactories) {
errorMessage = "Firebase service named \"" + serviceName + "\" has already been registered.";
}
if (typeof errorMessage !== 'undefined') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INTERNAL_ERROR, "INTERNAL ASSERT FAILED: " + errorMessage);
}
this.serviceFactories[serviceName] = createService;
if (appHook) {
this.appHooks_[serviceName] = appHook;
}
var serviceNamespace;
// The service namespace is an accessor function which takes a FirebaseApp instance
// or uses the default app if no FirebaseApp instance is provided
serviceNamespace = function (appArg) {
if (typeof appArg === 'undefined') {
appArg = _this.app();
}
// Forward service instance lookup to the FirebaseApp
return appArg[serviceName]();
};
// ... and a container for service-level properties.
if (serviceProperties !== undefined) {
deep_copy_1.deepExtend(serviceNamespace, serviceProperties);
}
// Monkey-patch the service namespace onto the Firebase namespace
this.firebase_[serviceName] = serviceNamespace;
return serviceNamespace;
};
/**
* Calls the app hooks corresponding to the provided event name for each service within the
* provided FirebaseApp instance.
*
* @param {FirebaseApp} app The FirebaseApp instance whose app hooks to call.
* @param {string} eventName The event name representing which app hooks to call.
*/
FirebaseNamespaceInternals.prototype.callAppHooks_ = function (app, eventName) {
var _this = this;
Object.keys(this.serviceFactories).forEach(function (serviceName) {
if (_this.appHooks_[serviceName]) {
_this.appHooks_[serviceName](eventName, app);
}
});
};
/**
* Parse the file pointed to by the FIREBASE_CONFIG_VAR, if it exists.
* Or if the FIREBASE_CONFIG_ENV contains a valid JSON object, parse it directly.
* If the environment variable contains a string that starts with '{' it will be parsed as JSON,
* otherwise it will be assumed to be pointing to a file.
*/
FirebaseNamespaceInternals.prototype.loadOptionsFromEnvVar = function () {
var config = process.env[exports.FIREBASE_CONFIG_VAR];
if (!validator.isNonEmptyString(config)) {
return {};
}
try {
var contents = config.startsWith('{') ? config : fs.readFileSync(config, 'utf8');
return JSON.parse(contents);
}
catch (error) {
// Throw a nicely formed error message if the file contents cannot be parsed
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.INVALID_APP_OPTIONS, 'Failed to parse app options file: ' + error);
}
};
return FirebaseNamespaceInternals;
}());
exports.FirebaseNamespaceInternals = FirebaseNamespaceInternals;
var firebaseCredential = {
cert: function (serviceAccountPathOrObject, httpAgent) {
var stringifiedServiceAccount = JSON.stringify(serviceAccountPathOrObject);
if (!(stringifiedServiceAccount in globalCertCreds)) {
globalCertCreds[stringifiedServiceAccount] = new credential_1.CertCredential(serviceAccountPathOrObject, httpAgent);
}
return globalCertCreds[stringifiedServiceAccount];
},
refreshToken: function (refreshTokenPathOrObject, httpAgent) {
var stringifiedRefreshToken = JSON.stringify(refreshTokenPathOrObject);
if (!(stringifiedRefreshToken in globalRefreshTokenCreds)) {
globalRefreshTokenCreds[stringifiedRefreshToken] = new credential_1.RefreshTokenCredential(refreshTokenPathOrObject, httpAgent);
}
return globalRefreshTokenCreds[stringifiedRefreshToken];
},
applicationDefault: function (httpAgent) {
if (typeof globalAppDefaultCred === 'undefined') {
globalAppDefaultCred = new credential_1.ApplicationDefaultCredential(httpAgent);
}
return globalAppDefaultCred;
},
};
/**
* Global Firebase context object.
*/
var FirebaseNamespace = /** @class */ (function () {
/* tslint:enable */
function FirebaseNamespace() {
// Hack to prevent Babel from modifying the object returned as the default admin namespace.
/* tslint:disable:variable-name */
this.__esModule = true;
/* tslint:enable:variable-name */
this.credential = firebaseCredential;
this.SDK_VERSION = '6.4.0';
/* tslint:disable */
// TODO(jwenger): Database is the only consumer of firebase.Promise. We should update it to use
// use the native Promise and then remove this.
this.Promise = Promise;
this.INTERNAL = new FirebaseNamespaceInternals(this);
}
Object.defineProperty(FirebaseNamespace.prototype, "auth", {
/**
* Gets the `Auth` service namespace. The returned namespace can be used to get the
* `Auth` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).auth();
};
var auth = require('./auth/auth').Auth;
return Object.assign(fn, { Auth: auth });
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "database", {
/**
* Gets the `Database` service namespace. The returned namespace can be used to get the
* `Database` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).database();
};
return Object.assign(fn, require('@firebase/database'));
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "messaging", {
/**
* Gets the `Messaging` service namespace. The returned namespace can be used to get the
* `Messaging` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).messaging();
};
var messaging = require('./messaging/messaging').Messaging;
return Object.assign(fn, { Messaging: messaging });
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "storage", {
/**
* Gets the `Storage` service namespace. The returned namespace can be used to get the
* `Storage` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).storage();
};
var storage = require('./storage/storage').Storage;
return Object.assign(fn, { Storage: storage });
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "firestore", {
/**
* Gets the `Firestore` service namespace. The returned namespace can be used to get the
* `Firestore` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).firestore();
};
return Object.assign(fn, require('@google-cloud/firestore'));
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "instanceId", {
/**
* Gets the `InstanceId` service namespace. The returned namespace can be used to get the
* `Instance` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).instanceId();
};
var instanceId = require('./instance-id/instance-id').InstanceId;
return Object.assign(fn, { InstanceId: instanceId });
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseNamespace.prototype, "projectManagement", {
/**
* Gets the `ProjectManagement` service namespace. The returned namespace can be used to get the
* `ProjectManagement` service for the default app or an explicitly specified app.
*/
get: function () {
var _this = this;
var fn = function (app) {
return _this.ensureApp(app).projectManagement();
};
var projectManagement = require('./project-management/project-management').ProjectManagement;
return Object.assign(fn, { ProjectManagement: projectManagement });
},
enumerable: true,
configurable: true
});
/**
* Initializes the FirebaseApp instance.
*
* @param {FirebaseAppOptions} [options] Optional options for the FirebaseApp instance.
* If none present will try to initialize from the FIREBASE_CONFIG environment variable.
* If the environment variable contains a string that starts with '{' it will be parsed as JSON,
* otherwise it will be assumed to be pointing to a file.
* @param {string} [appName] Optional name of the FirebaseApp instance.
*
* @return {FirebaseApp} A new FirebaseApp instance.
*/
FirebaseNamespace.prototype.initializeApp = function (options, appName) {
return this.INTERNAL.initializeApp(options, appName);
};
/**
* Returns the FirebaseApp instance with the provided name (or the default FirebaseApp instance
* if no name is provided).
*
* @param {string} [appName] Optional name of the FirebaseApp instance to return.
* @return {FirebaseApp} The FirebaseApp instance which has the provided name.
*/
FirebaseNamespace.prototype.app = function (appName) {
return this.INTERNAL.app(appName);
};
Object.defineProperty(FirebaseNamespace.prototype, "apps", {
/*
* Returns an array of all the non-deleted FirebaseApp instances.
*
* @return {Array<FirebaseApp>} An array of all the non-deleted FirebaseApp instances
*/
get: function () {
return this.INTERNAL.apps;
},
enumerable: true,
configurable: true
});
FirebaseNamespace.prototype.ensureApp = function (app) {
if (typeof app === 'undefined') {
app = this.app();
}
return app;
};
return FirebaseNamespace;
}());
exports.FirebaseNamespace = FirebaseNamespace;

View File

@ -0,0 +1,18 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });

View File

@ -0,0 +1,129 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var credential_1 = require("../auth/credential");
var validator = require("../utils/validator");
var utils = require("../utils/index");
/**
* Internals of a Firestore instance.
*/
var FirestoreInternals = /** @class */ (function () {
function FirestoreInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
FirestoreInternals.prototype.delete = function () {
// There are no resources to clean up.
return Promise.resolve();
};
return FirestoreInternals;
}());
var FirestoreService = /** @class */ (function () {
function FirestoreService(app) {
this.INTERNAL = new FirestoreInternals();
this.firestoreClient = initFirestore(app);
this.appInternal = app;
}
Object.defineProperty(FirestoreService.prototype, "app", {
/**
* Returns the app associated with this Storage instance.
*
* @return {FirebaseApp} The app associated with this Storage instance.
*/
get: function () {
return this.appInternal;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirestoreService.prototype, "client", {
get: function () {
return this.firestoreClient;
},
enumerable: true,
configurable: true
});
return FirestoreService;
}());
exports.FirestoreService = FirestoreService;
function getFirestoreOptions(app) {
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseFirestoreError({
code: 'invalid-argument',
message: 'First argument passed to admin.firestore() must be a valid Firebase app instance.',
});
}
var projectId = utils.getProjectId(app);
var cert = app.options.credential.getCertificate();
var firebaseVersion = require('../../package.json').version;
if (cert != null) {
// cert is available when the SDK has been initialized with a service account JSON file,
// or by setting the GOOGLE_APPLICATION_CREDENTIALS envrionment variable.
if (!validator.isNonEmptyString(projectId)) {
// Assert for an explicit projct ID (either via AppOptions or the cert itself).
throw new error_1.FirebaseFirestoreError({
code: 'no-project-id',
message: 'Failed to determine project ID for Firestore. Initialize the '
+ 'SDK with service account credentials or set project ID as an app option. '
+ 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.',
});
}
return {
credentials: {
private_key: cert.privateKey,
client_email: cert.clientEmail,
},
projectId: projectId,
firebaseVersion: firebaseVersion,
};
}
else if (app.options.credential instanceof credential_1.ApplicationDefaultCredential) {
// Try to use the Google application default credentials.
// If an explicit project ID is not available, let Firestore client discover one from the
// environment. This prevents the users from having to set GOOGLE_CLOUD_PROJECT in GCP runtimes.
return validator.isNonEmptyString(projectId) ? { projectId: projectId, firebaseVersion: firebaseVersion } : { firebaseVersion: firebaseVersion };
}
throw new error_1.FirebaseFirestoreError({
code: 'invalid-credential',
message: 'Failed to initialize Google Cloud Firestore client with the available credentials. ' +
'Must initialize the SDK with a certificate credential or application default credentials ' +
'to use Cloud Firestore API.',
});
}
exports.getFirestoreOptions = getFirestoreOptions;
function initFirestore(app) {
var options = getFirestoreOptions(app);
var firestoreDatabase;
try {
// Lazy-load the Firestore implementation here, which in turns loads gRPC.
firestoreDatabase = require('@google-cloud/firestore');
}
catch (err) {
throw new error_1.FirebaseFirestoreError({
code: 'missing-dependencies',
message: 'Failed to import the Cloud Firestore client library for Node.js. '
+ 'Make sure to install the "@google-cloud/firestore" npm package. '
+ ("Original error: " + err),
});
}
return new firestoreDatabase(options);
}

View File

@ -0,0 +1,726 @@
/*! firebase-admin v6.4.0 */
/*!
* Copyright 2017 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 {Bucket} from '@google-cloud/storage';
import * as _firestore from '@google-cloud/firestore';
import {Agent} from 'http';
declare namespace admin {
interface FirebaseError {
code: string;
message: string;
stack: string;
toJSON(): Object;
}
type FirebaseArrayIndexError = {
index: number;
error: FirebaseError;
}
interface ServiceAccount {
projectId?: string;
clientEmail?: string;
privateKey?: string;
}
interface GoogleOAuthAccessToken {
access_token: string;
expires_in: number;
}
interface AppOptions {
credential?: admin.credential.Credential;
databaseAuthVariableOverride?: Object;
databaseURL?: string;
serviceAccountId?: string;
storageBucket?: string;
projectId?: string;
httpAgent?: Agent;
}
var SDK_VERSION: string;
var apps: (admin.app.App|null)[];
function app(name?: string): admin.app.App;
function auth(app?: admin.app.App): admin.auth.Auth;
function database(app?: admin.app.App): admin.database.Database;
function messaging(app?: admin.app.App): admin.messaging.Messaging;
function storage(app?: admin.app.App): admin.storage.Storage;
function firestore(app?: admin.app.App): admin.firestore.Firestore;
function instanceId(app?: admin.app.App): admin.instanceId.InstanceId;
function projectManagement(app?: admin.app.App): admin.projectManagement.ProjectManagement;
function initializeApp(options?: admin.AppOptions, name?: string): admin.app.App;
}
declare namespace admin.app {
interface App {
name: string;
options: admin.AppOptions;
auth(): admin.auth.Auth;
database(url?: string): admin.database.Database;
firestore(): admin.firestore.Firestore;
instanceId(): admin.instanceId.InstanceId;
messaging(): admin.messaging.Messaging;
projectManagement(): admin.projectManagement.ProjectManagement;
storage(): admin.storage.Storage;
delete(): Promise<void>;
}
}
declare namespace admin.auth {
interface UserMetadata {
lastSignInTime: string;
creationTime: string;
toJSON(): Object;
}
interface UserInfo {
uid: string;
displayName: string;
email: string;
phoneNumber: string;
photoURL: string;
providerId: string;
toJSON(): Object;
}
interface UserRecord {
uid: string;
email: string;
emailVerified: boolean;
displayName: string;
phoneNumber: string;
photoURL: string;
disabled: boolean;
metadata: admin.auth.UserMetadata;
providerData: admin.auth.UserInfo[];
passwordHash?: string;
passwordSalt?: string;
customClaims?: Object;
tokensValidAfterTime?: string;
toJSON(): Object;
}
interface UpdateRequest {
displayName?: string;
email?: string;
emailVerified?: boolean;
phoneNumber?: string;
photoURL?: string;
disabled?: boolean;
password?: string;
}
interface CreateRequest extends UpdateRequest {
uid?: string;
}
interface DecodedIdToken {
aud: string;
auth_time: number;
exp: number;
firebase: {
identities: {
[key: string]: any;
};
sign_in_provider: string;
[key: string]: any;
};
iat: number;
iss: string;
sub: string;
uid: string;
[key: string]: any;
}
interface ListUsersResult {
users: admin.auth.UserRecord[];
pageToken?: string;
}
type HashAlgorithmType = 'SCRYPT' | 'STANDARD_SCRYPT' | 'HMAC_SHA512' |
'HMAC_SHA256' | 'HMAC_SHA1' | 'HMAC_MD5' | 'MD5' | 'PBKDF_SHA1' | 'BCRYPT' |
'PBKDF2_SHA256' | 'SHA512' | 'SHA256' | 'SHA1';
interface UserImportOptions {
hash: {
algorithm: HashAlgorithmType;
key?: Buffer;
saltSeparator?: string;
rounds?: number;
memoryCost?: number;
parallelization?: number;
blockSize?: number;
derivedKeyLength?: number;
};
}
interface UserImportResult {
failureCount: number;
successCount: number;
errors: admin.FirebaseArrayIndexError[];
}
interface UserImportRecord {
uid: string;
email?: string;
emailVerified?: boolean;
displayName?: string;
phoneNumber?: string;
photoURL?: string;
disabled?: boolean;
metadata?: {
lastSignInTime?: string;
creationTime?: string;
};
providerData?: {
uid: string,
displayName?: string,
email?: string,
photoURL?: string,
providerId: string,
}[];
customClaims?: Object;
passwordHash?: Buffer;
passwordSalt?: Buffer;
}
interface SessionCookieOptions {
expiresIn: number;
}
interface ActionCodeSettings {
url: string;
handleCodeInApp?: boolean;
iOS?: {
bundleId: string;
};
android?: {
packageName: string;
installApp?: boolean;
minimumVersion?: string;
};
dynamicLinkDomain?: string;
}
interface BaseAuth {
createCustomToken(uid: string, developerClaims?: Object): Promise<string>;
createUser(properties: admin.auth.CreateRequest): Promise<admin.auth.UserRecord>;
deleteUser(uid: string): Promise<void>;
getUser(uid: string): Promise<admin.auth.UserRecord>;
getUserByEmail(email: string): Promise<admin.auth.UserRecord>;
getUserByPhoneNumber(phoneNumber: string): Promise<admin.auth.UserRecord>;
listUsers(maxResults?: number, pageToken?: string): Promise<admin.auth.ListUsersResult>;
updateUser(uid: string, properties: admin.auth.UpdateRequest): Promise<admin.auth.UserRecord>;
verifyIdToken(idToken: string, checkRevoked?: boolean): Promise<admin.auth.DecodedIdToken>;
setCustomUserClaims(uid: string, customUserClaims: Object): Promise<void>;
revokeRefreshTokens(uid: string): Promise<void>;
importUsers(
users: admin.auth.UserImportRecord[],
options?: admin.auth.UserImportOptions,
): Promise<admin.auth.UserImportResult>
createSessionCookie(
idToken: string,
sessionCookieOptions: admin.auth.SessionCookieOptions,
): Promise<string>;
verifySessionCookie(
sessionCookie: string,
checkForRevocation?: boolean,
): Promise<admin.auth.DecodedIdToken>;
generatePasswordResetLink(
email: string,
actionCodeSettings?: admin.auth.ActionCodeSettings,
): Promise<string>;
generateEmailVerificationLink(
email: string,
actionCodeSettings?: admin.auth.ActionCodeSettings,
): Promise<string>;
generateSignInWithEmailLink(
email: string,
actionCodeSettings: admin.auth.ActionCodeSettings,
): Promise<string>;
}
interface Auth extends admin.auth.BaseAuth {
app: admin.app.App;
}
}
declare namespace admin.credential {
interface Credential {
getAccessToken(): Promise<admin.GoogleOAuthAccessToken>;
}
function applicationDefault(httpAgent?: Agent): admin.credential.Credential;
function cert(serviceAccountPathOrObject: string|admin.ServiceAccount, httpAgent?: Agent): admin.credential.Credential;
function refreshToken(refreshTokenPathOrObject: string|Object, httpAgent?: Agent): admin.credential.Credential;
}
declare namespace admin.database {
interface Database {
app: admin.app.App;
goOffline(): void;
goOnline(): void;
ref(path?: string | admin.database.Reference): admin.database.Reference;
refFromURL(url: string): admin.database.Reference;
}
interface DataSnapshot {
key: string|null;
ref: admin.database.Reference;
child(path: string): admin.database.DataSnapshot;
exists(): boolean;
exportVal(): any;
forEach(action: (a: admin.database.DataSnapshot) => boolean | void): boolean;
getPriority(): string|number|null;
hasChild(path: string): boolean;
hasChildren(): boolean;
numChildren(): number;
toJSON(): Object | null;
val(): any;
}
interface OnDisconnect {
cancel(onComplete?: (a: Error|null) => any): Promise<void>;
remove(onComplete?: (a: Error|null) => any): Promise<void>;
set(value: any, onComplete?: (a: Error|null) => any): Promise<void>;
setWithPriority(
value: any,
priority: number|string|null,
onComplete?: (a: Error|null) => any
): Promise<void>;
update(values: Object, onComplete?: (a: Error|null) => any): Promise<void>;
}
type EventType = 'value' | 'child_added' | 'child_changed' | 'child_moved' | 'child_removed';
interface Query {
ref: admin.database.Reference;
endAt(value: number|string|boolean|null, key?: string): admin.database.Query;
equalTo(value: number|string|boolean|null, key?: string): admin.database.Query;
isEqual(other: admin.database.Query|null): boolean;
limitToFirst(limit: number): admin.database.Query;
limitToLast(limit: number): admin.database.Query;
off(
eventType?: admin.database.EventType,
callback?: (a: admin.database.DataSnapshot, b?: string|null) => any,
context?: Object|null
): void;
on(
eventType: admin.database.EventType,
callback: (a: admin.database.DataSnapshot|null, b?: string) => any,
cancelCallbackOrContext?: Object|null,
context?: Object|null
): (a: admin.database.DataSnapshot|null, b?: string) => any;
once(
eventType: admin.database.EventType,
successCallback?: (a: admin.database.DataSnapshot, b?: string) => any,
failureCallbackOrContext?: Object|null,
context?: Object|null
): Promise<admin.database.DataSnapshot>;
orderByChild(path: string): admin.database.Query;
orderByKey(): admin.database.Query;
orderByPriority(): admin.database.Query;
orderByValue(): admin.database.Query;
startAt(value: number|string|boolean|null, key?: string): admin.database.Query;
toJSON(): Object;
toString(): string;
}
interface Reference extends admin.database.Query {
key: string|null;
parent: admin.database.Reference|null;
root: admin.database.Reference;
path: string;
child(path: string): admin.database.Reference;
onDisconnect(): admin.database.OnDisconnect;
push(value?: any, onComplete?: (a: Error|null) => any): admin.database.ThenableReference;
remove(onComplete?: (a: Error|null) => any): Promise<void>;
set(value: any, onComplete?: (a: Error|null) => any): Promise<void>;
setPriority(
priority: string|number|null,
onComplete: (a: Error|null) => any
): Promise<void>;
setWithPriority(
newVal: any, newPriority: string|number|null,
onComplete?: (a: Error|null) => any
): Promise<void>;
transaction(
transactionUpdate: (a: any) => any,
onComplete?: (a: Error|null, b: boolean, c: admin.database.DataSnapshot|null) => any,
applyLocally?: boolean
): Promise<{
committed: boolean,
snapshot: admin.database.DataSnapshot|null
}>;
update(values: Object, onComplete?: (a: Error|null) => any): Promise<void>;
}
interface ThenableReference extends admin.database.Reference, PromiseLike<any> {}
function enableLogging(logger?: boolean|((message: string) => any), persistent?: boolean): any;
}
declare namespace admin.database.ServerValue {
var TIMESTAMP: number;
}
type BaseMessage = {
data?: {[key: string]: string};
notification?: admin.messaging.Notification;
android?: admin.messaging.AndroidConfig;
webpush?: admin.messaging.WebpushConfig;
apns?: admin.messaging.ApnsConfig;
};
interface TokenMessage extends BaseMessage {
token: string;
}
interface TopicMessage extends BaseMessage {
topic: string;
}
interface ConditionMessage extends BaseMessage {
condition: string;
}
declare namespace admin.messaging {
type Message = TokenMessage | TopicMessage | ConditionMessage;
type AndroidConfig = {
collapseKey?: string;
priority?: ('high'|'normal');
ttl?: number;
restrictedPackageName?: string;
data?: {[key: string]: string};
notification?: AndroidNotification;
};
type AndroidNotification = {
title?: string;
body?: string;
icon?: string;
color?: string;
sound?: string;
tag?: string;
clickAction?: string;
bodyLocKey?: string;
bodyLocArgs?: string[];
titleLocKey?: string;
titleLocArgs?: string[];
channelId?: string;
};
type ApnsConfig = {
headers?: {[key: string]: string};
payload?: ApnsPayload;
};
type ApnsPayload = {
aps: Aps;
[customData: string]: object;
};
type Aps = {
alert?: string | ApsAlert;
badge?: number;
sound?: string | CriticalSound;
contentAvailable?: boolean;
mutableContent?: boolean;
category?: string;
threadId?: string;
[customData: string]: any;
};
type ApsAlert = {
title?: string;
subtitle?: string;
body?: string;
locKey?: string;
locArgs?: string[];
titleLocKey?: string;
titleLocArgs?: string[];
subtitleLocKey?: string;
subtitleLocArgs?: string[];
actionLocKey?: string;
launchImage?: string;
};
type CriticalSound = {
critical?: boolean;
name?: string;
volume?: number;
}
type Notification = {
title?: string;
body?: string;
};
type WebpushConfig = {
headers?: {[key: string]: string};
data?: {[key: string]: string};
notification?: WebpushNotification;
fcmOptions?: WebpushFcmOptions;
};
interface WebpushFcmOptions {
link?: string;
}
interface WebpushNotification {
title?: string;
actions?: Array<{
action: string;
icon?: string;
title: string;
}>;
badge?: string;
body?: string;
data?: any;
dir?: 'auto' | 'ltr' | 'rtl';
icon?: string;
image?: string;
lang?: string;
renotify?: boolean;
requireInteraction?: boolean;
silent?: boolean;
tag?: string;
timestamp?: number;
vibrate?: number | number[];
[key: string]: any;
}
type DataMessagePayload = {
[key: string]: string;
};
type NotificationMessagePayload = {
tag?: string;
body?: string;
icon?: string;
badge?: string;
color?: string;
sound?: string;
title?: string;
bodyLocKey?: string;
bodyLocArgs?: string;
clickAction?: string;
titleLocKey?: string;
titleLocArgs?: string;
[key: string]: string | undefined;
};
type MessagingPayload = {
data?: admin.messaging.DataMessagePayload;
notification?: admin.messaging.NotificationMessagePayload;
};
type MessagingOptions = {
dryRun?: boolean;
priority?: string;
timeToLive?: number;
collapseKey?: string;
mutableContent?: boolean;
contentAvailable?: boolean;
restrictedPackageName?: string;
[key: string]: any | undefined;
};
type MessagingDeviceResult = {
error?: admin.FirebaseError;
messageId?: string;
canonicalRegistrationToken?: string;
};
type MessagingDevicesResponse = {
canonicalRegistrationTokenCount: number;
failureCount: number;
multicastId: number;
results: admin.messaging.MessagingDeviceResult[];
successCount: number;
};
type MessagingDeviceGroupResponse = {
successCount: number;
failureCount: number;
failedRegistrationTokens: string[];
};
type MessagingTopicResponse = {
messageId: number;
};
type MessagingConditionResponse = {
messageId: number;
};
type MessagingTopicManagementResponse = {
failureCount: number;
successCount: number;
errors: admin.FirebaseArrayIndexError[];
};
interface Messaging {
app: admin.app.App;
send(message: admin.messaging.Message, dryRun?: boolean): Promise<string>;
sendToDevice(
registrationToken: string | string[],
payload: admin.messaging.MessagingPayload,
options?: admin.messaging.MessagingOptions
): Promise<admin.messaging.MessagingDevicesResponse>;
sendToDeviceGroup(
notificationKey: string,
payload: admin.messaging.MessagingPayload,
options?: admin.messaging.MessagingOptions
): Promise<admin.messaging.MessagingDeviceGroupResponse>;
sendToTopic(
topic: string,
payload: admin.messaging.MessagingPayload,
options?: admin.messaging.MessagingOptions
): Promise<admin.messaging.MessagingTopicResponse>;
sendToCondition(
condition: string,
payload: admin.messaging.MessagingPayload,
options?: admin.messaging.MessagingOptions
): Promise<admin.messaging.MessagingConditionResponse>;
subscribeToTopic(
registrationToken: string,
topic: string
): Promise<admin.messaging.MessagingTopicManagementResponse>;
subscribeToTopic(
registrationTokens: string[],
topic: string
): Promise<admin.messaging.MessagingTopicManagementResponse>;
unsubscribeFromTopic(
registrationToken: string,
topic: string
): Promise<admin.messaging.MessagingTopicManagementResponse>;
unsubscribeFromTopic(
registrationTokens: string[],
topic: string
): Promise<admin.messaging.MessagingTopicManagementResponse>;
}
}
declare namespace admin.storage {
interface Storage {
app: admin.app.App;
bucket(name?: string): Bucket;
}
}
declare namespace admin.firestore {
export import CollectionReference = _firestore.CollectionReference;
export import DocumentData = _firestore.DocumentData;
export import DocumentReference = _firestore.DocumentReference;
export import DocumentSnapshot = _firestore.DocumentSnapshot;
export import FieldPath = _firestore.FieldPath;
export import FieldValue = _firestore.FieldValue;
export import Firestore = _firestore.Firestore;
export import GeoPoint = _firestore.GeoPoint;
export import Query = _firestore.Query;
export import QueryDocumentSnapshot = _firestore.QueryDocumentSnapshot;
export import QuerySnapshot = _firestore.QuerySnapshot;
export import Timestamp = _firestore.Timestamp;
export import Transaction = _firestore.Transaction;
export import WriteBatch = _firestore.WriteBatch;
export import WriteResult = _firestore.WriteResult;
export import setLogFunction = _firestore.setLogFunction;
}
declare namespace admin.instanceId {
interface InstanceId {
app: admin.app.App;
deleteInstanceId(instanceId: string): Promise<void>;
}
}
declare namespace admin.projectManagement {
interface ShaCertificate {
certType: ('sha1' | 'sha256');
shaHash: string;
resourceName?: string;
}
interface AndroidAppMetadata {
resourceName: string;
appId: string;
displayName: string | null;
projectId: string;
packageName: string;
}
interface AndroidApp {
appId: string;
getMetadata(): Promise<admin.projectManagement.AndroidAppMetadata>;
setDisplayName(newDisplayName: string): Promise<void>;
getShaCertificates(): Promise<admin.projectManagement.ShaCertificate[]>;
addShaCertificate(certificateToAdd: ShaCertificate): Promise<void>;
deleteShaCertificate(certificateToRemove: ShaCertificate): Promise<void>;
getConfig(): Promise<string>;
}
interface IosAppMetadata {
resourceName: string;
appId: string;
displayName: string;
projectId: string;
bundleId: string;
}
interface IosApp {
appId: string;
getMetadata(): Promise<admin.projectManagement.IosAppMetadata>;
setDisplayName(newDisplayName: string): Promise<void>;
getConfig(): Promise<string>;
}
interface ProjectManagement {
app: admin.app.App;
listAndroidApps(): Promise<admin.projectManagement.AndroidApp[]>;
listIosApps(): Promise<admin.projectManagement.IosApp[]>;
androidApp(appId: string): admin.projectManagement.AndroidApp;
iosApp(appId: string): admin.projectManagement.IosApp;
createAndroidApp(
packageName: string, displayName?: string): Promise<admin.projectManagement.AndroidApp>;
createIosApp(bundleId: string, displayName?: string): Promise<admin.projectManagement.IosApp>;
}
}
declare module 'firebase-admin' {
}
export = admin;

View File

@ -0,0 +1,19 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
var firebase = require("./default-namespace");
module.exports = firebase;

View File

@ -0,0 +1,102 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var api_request_1 = require("../utils/api-request");
var validator = require("../utils/validator");
/** Firebase IID backend host. */
var FIREBASE_IID_HOST = 'console.firebase.google.com';
/** Firebase IID backend port number. */
var FIREBASE_IID_PORT = 443;
/** Firebase IID backend path. */
var FIREBASE_IID_PATH = '/v1/';
/** Firebase IID request timeout duration in milliseconds. */
var FIREBASE_IID_TIMEOUT = 10000;
/** HTTP error codes raised by the backend server. */
var ERROR_CODES = {
400: 'Malformed instance ID argument.',
401: 'Request not authorized.',
403: 'Project does not match instance ID or the client does not have sufficient privileges.',
404: 'Failed to find the instance ID.',
409: 'Already deleted.',
429: 'Request throttled out by the backend server.',
500: 'Internal server error.',
503: 'Backend servers are over capacity. Try again later.',
};
/**
* Class that provides mechanism to send requests to the Firebase Instance ID backend endpoints.
*/
var FirebaseInstanceIdRequestHandler = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
* @param {string} projectId A Firebase project ID string.
*
* @constructor
*/
function FirebaseInstanceIdRequestHandler(app, projectId) {
this.host = FIREBASE_IID_HOST;
this.port = FIREBASE_IID_PORT;
this.timeout = FIREBASE_IID_TIMEOUT;
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
this.path = FIREBASE_IID_PATH + ("project/" + projectId + "/instanceId/");
}
FirebaseInstanceIdRequestHandler.prototype.deleteInstanceId = function (instanceId) {
if (!validator.isNonEmptyString(instanceId)) {
return Promise.reject(new error_1.FirebaseInstanceIdError(error_1.InstanceIdClientErrorCode.INVALID_INSTANCE_ID, 'Instance ID must be a non-empty string.'));
}
return this.invokeRequestHandler(new api_request_1.ApiSettings(instanceId, 'DELETE'));
};
/**
* Invokes the request handler based on the API settings object passed.
*
* @param {ApiSettings} apiSettings The API endpoint settings to apply to request and response.
* @return {Promise<object>} A promise that resolves with the response.
*/
FirebaseInstanceIdRequestHandler.prototype.invokeRequestHandler = function (apiSettings) {
var _this = this;
var path = this.path + apiSettings.getEndpoint();
return Promise.resolve()
.then(function () {
var req = {
url: "https://" + _this.host + path,
method: apiSettings.getHttpMethod(),
timeout: _this.timeout,
};
return _this.httpClient.send(req);
})
.then(function (response) {
return response.data;
})
.catch(function (err) {
if (err instanceof api_request_1.HttpError) {
var response = err.response;
var errorMessage = (response.isJson() && 'error' in response.data) ?
response.data.error : response.text;
var template = ERROR_CODES[response.status];
var message = template ?
"Instance ID \"" + apiSettings.getEndpoint() + "\": " + template : errorMessage;
throw new error_1.FirebaseInstanceIdError(error_1.InstanceIdClientErrorCode.API_ERROR, message);
}
// In case of timeouts and other network errors, the HttpClient returns a
// FirebaseError wrapped in the response. Simply throw it here.
throw err;
});
};
return FirebaseInstanceIdRequestHandler;
}());
exports.FirebaseInstanceIdRequestHandler = FirebaseInstanceIdRequestHandler;

View File

@ -0,0 +1,88 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var instance_id_request_1 = require("./instance-id-request");
var utils = require("../utils/index");
var validator = require("../utils/validator");
/**
* Internals of an InstanceId service instance.
*/
var InstanceIdInternals = /** @class */ (function () {
function InstanceIdInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
InstanceIdInternals.prototype.delete = function () {
// There are no resources to clean up
return Promise.resolve(undefined);
};
return InstanceIdInternals;
}());
var InstanceId = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app for this InstanceId service.
* @constructor
*/
function InstanceId(app) {
this.INTERNAL = new InstanceIdInternals();
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseInstanceIdError(error_1.InstanceIdClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.instanceId() must be a valid Firebase app instance.');
}
var projectId = utils.getProjectId(app);
if (!validator.isNonEmptyString(projectId)) {
// Assert for an explicit projct ID (either via AppOptions or the cert itself).
throw new error_1.FirebaseInstanceIdError(error_1.InstanceIdClientErrorCode.INVALID_PROJECT_ID, 'Failed to determine project ID for InstanceId. Initialize the '
+ 'SDK with service account credentials or set project ID as an app option. '
+ 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.');
}
this.app_ = app;
this.requestHandler = new instance_id_request_1.FirebaseInstanceIdRequestHandler(app, projectId);
}
/**
* Deletes the specified instance ID from Firebase. This can be used to delete an instance ID
* and associated user data from a Firebase project, pursuant to the General Data Protection
* Regulation (GDPR).
*
* @param {string} instanceId The instance ID to be deleted
* @return {Promise<void>} A promise that resolves when the instance ID is successfully deleted.
*/
InstanceId.prototype.deleteInstanceId = function (instanceId) {
return this.requestHandler.deleteInstanceId(instanceId)
.then(function (result) {
// Return nothing on success
});
};
Object.defineProperty(InstanceId.prototype, "app", {
/**
* Returns the app associated with this InstanceId instance.
*
* @return {FirebaseApp} The app associated with this InstanceId instance.
*/
get: function () {
return this.app_;
},
enumerable: true,
configurable: true
});
return InstanceId;
}());
exports.InstanceId = InstanceId;

View File

@ -0,0 +1,155 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var api_request_1 = require("../utils/api-request");
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
// FCM backend constants
var FIREBASE_MESSAGING_TIMEOUT = 10000;
var FIREBASE_MESSAGING_HTTP_METHOD = 'POST';
var FIREBASE_MESSAGING_HEADERS = {
'Sdk-Version': 'Node/Admin/6.4.0',
'access_token_auth': 'true',
};
/**
* Class that provides a mechanism to send requests to the Firebase Cloud Messaging backend.
*/
var FirebaseMessagingRequestHandler = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
* @constructor
*/
function FirebaseMessagingRequestHandler(app) {
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
}
/**
* @param {object} response The response to check for errors.
* @return {string|null} The error code if present; null otherwise.
*/
FirebaseMessagingRequestHandler.getErrorCode = function (response) {
if (validator.isNonNullObject(response) && 'error' in response) {
if (validator.isString(response.error)) {
return response.error;
}
if (validator.isArray(response.error.details)) {
var fcmErrorType = 'type.googleapis.com/google.firebase.fcm.v1.FcmError';
for (var _i = 0, _a = response.error.details; _i < _a.length; _i++) {
var element = _a[_i];
if (element['@type'] === fcmErrorType) {
return element.errorCode;
}
}
}
if ('status' in response.error) {
return response.error.status;
}
else {
return response.error.message;
}
}
return null;
};
/**
* Extracts error message from the given response object.
*
* @param {object} response The response to check for errors.
* @return {string|null} The error message if present; null otherwise.
*/
FirebaseMessagingRequestHandler.getErrorMessage = function (response) {
if (validator.isNonNullObject(response) &&
'error' in response &&
validator.isNonEmptyString(response.error.message)) {
return response.error.message;
}
return null;
};
/**
* Invokes the request handler with the provided request data.
*
* @param {string} host The host to which to send the request.
* @param {string} path The path to which to send the request.
* @param {object} requestData The request data.
* @return {Promise<object>} A promise that resolves with the response.
*/
FirebaseMessagingRequestHandler.prototype.invokeRequestHandler = function (host, path, requestData) {
var _this = this;
var request = {
method: FIREBASE_MESSAGING_HTTP_METHOD,
url: "https://" + host + path,
data: requestData,
headers: FIREBASE_MESSAGING_HEADERS,
timeout: FIREBASE_MESSAGING_TIMEOUT,
};
return this.httpClient.send(request).then(function (response) {
// Send non-JSON responses to the catch() below where they will be treated as errors.
if (!response.isJson()) {
throw new api_request_1.HttpError(response);
}
// Check for backend errors in the response.
var errorCode = FirebaseMessagingRequestHandler.getErrorCode(response.data);
if (errorCode) {
throw new api_request_1.HttpError(response);
}
// Return entire response.
return response.data;
})
.catch(function (err) {
if (err instanceof api_request_1.HttpError) {
_this.handleHttpError(err);
}
// Re-throw the error if it already has the proper format.
throw err;
});
};
FirebaseMessagingRequestHandler.prototype.handleHttpError = function (err) {
if (err.response.isJson()) {
// For JSON responses, map the server response to a client-side error.
var json = err.response.data;
var errorCode = FirebaseMessagingRequestHandler.getErrorCode(json);
var errorMessage = FirebaseMessagingRequestHandler.getErrorMessage(json);
throw error_1.FirebaseMessagingError.fromServerError(errorCode, errorMessage, json);
}
// Non-JSON response
var error;
switch (err.response.status) {
case 400:
error = error_1.MessagingClientErrorCode.INVALID_ARGUMENT;
break;
case 401:
case 403:
error = error_1.MessagingClientErrorCode.AUTHENTICATION_ERROR;
break;
case 500:
error = error_1.MessagingClientErrorCode.INTERNAL_ERROR;
break;
case 503:
error = error_1.MessagingClientErrorCode.SERVER_UNAVAILABLE;
break;
default:
// Treat non-JSON responses with unexpected status codes as unknown errors.
error = error_1.MessagingClientErrorCode.UNKNOWN_ERROR;
}
throw new error_1.FirebaseMessagingError({
code: error.code,
message: error.message + " Raw server response: \"" + err.response.text + "\". Status code: " +
(err.response.status + "."),
});
};
return FirebaseMessagingRequestHandler;
}());
exports.FirebaseMessagingRequestHandler = FirebaseMessagingRequestHandler;

View File

@ -0,0 +1,980 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var index_1 = require("../utils/index");
var deep_copy_1 = require("../utils/deep-copy");
var messaging_api_request_1 = require("./messaging-api-request");
var error_1 = require("../utils/error");
var utils = require("../utils");
var validator = require("../utils/validator");
// FCM endpoints
var FCM_SEND_HOST = 'fcm.googleapis.com';
var FCM_SEND_PATH = '/fcm/send';
var FCM_TOPIC_MANAGEMENT_HOST = 'iid.googleapis.com';
var FCM_TOPIC_MANAGEMENT_ADD_PATH = '/iid/v1:batchAdd';
var FCM_TOPIC_MANAGEMENT_REMOVE_PATH = '/iid/v1:batchRemove';
// Key renames for the messaging notification payload object.
var CAMELCASED_NOTIFICATION_PAYLOAD_KEYS_MAP = {
bodyLocArgs: 'body_loc_args',
bodyLocKey: 'body_loc_key',
clickAction: 'click_action',
titleLocArgs: 'title_loc_args',
titleLocKey: 'title_loc_key',
};
// Key renames for the messaging options object.
var CAMELCASE_OPTIONS_KEYS_MAP = {
dryRun: 'dry_run',
timeToLive: 'time_to_live',
collapseKey: 'collapse_key',
mutableContent: 'mutable_content',
contentAvailable: 'content_available',
restrictedPackageName: 'restricted_package_name',
};
// Key renames for the MessagingDeviceResult object.
var MESSAGING_DEVICE_RESULT_KEYS_MAP = {
message_id: 'messageId',
registration_id: 'canonicalRegistrationToken',
};
// Key renames for the MessagingDevicesResponse object.
var MESSAGING_DEVICES_RESPONSE_KEYS_MAP = {
canonical_ids: 'canonicalRegistrationTokenCount',
failure: 'failureCount',
success: 'successCount',
multicast_id: 'multicastId',
};
// Key renames for the MessagingDeviceGroupResponse object.
var MESSAGING_DEVICE_GROUP_RESPONSE_KEYS_MAP = {
success: 'successCount',
failure: 'failureCount',
failed_registration_ids: 'failedRegistrationTokens',
};
// Key renames for the MessagingTopicResponse object.
var MESSAGING_TOPIC_RESPONSE_KEYS_MAP = {
message_id: 'messageId',
};
// Key renames for the MessagingConditionResponse object.
var MESSAGING_CONDITION_RESPONSE_KEYS_MAP = {
message_id: 'messageId',
};
// Keys which are not allowed in the messaging data payload object.
exports.BLACKLISTED_DATA_PAYLOAD_KEYS = ['from'];
// Keys which are not allowed in the messaging options object.
exports.BLACKLISTED_OPTIONS_KEYS = [
'condition', 'data', 'notification', 'registrationIds', 'registration_ids', 'to',
];
/**
* Checks if the given object only contains strings as child values.
*
* @param {object} map An object to be validated.
* @param {string} label A label to be included in the errors thrown.
*/
function validateStringMap(map, label) {
if (typeof map === 'undefined') {
return;
}
else if (!validator.isNonNullObject(map)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, label + " must be a non-null object");
}
Object.keys(map).forEach(function (key) {
if (!validator.isString(map[key])) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, label + " must only contain string values");
}
});
}
/**
* Checks if the given WebpushConfig object is valid. The object must have valid headers and data.
*
* @param {WebpushConfig} config An object to be validated.
*/
function validateWebpushConfig(config) {
if (typeof config === 'undefined') {
return;
}
else if (!validator.isNonNullObject(config)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'webpush must be a non-null object');
}
validateStringMap(config.headers, 'webpush.headers');
validateStringMap(config.data, 'webpush.data');
}
/**
* Checks if the given ApnsConfig object is valid. The object must have valid headers and a
* payload.
*
* @param {ApnsConfig} config An object to be validated.
*/
function validateApnsConfig(config) {
if (typeof config === 'undefined') {
return;
}
else if (!validator.isNonNullObject(config)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns must be a non-null object');
}
validateStringMap(config.headers, 'apns.headers');
validateApnsPayload(config.payload);
}
/**
* Checks if the given ApnsPayload object is valid. The object must have a valid aps value.
*
* @param {ApnsPayload} payload An object to be validated.
*/
function validateApnsPayload(payload) {
if (typeof payload === 'undefined') {
return;
}
else if (!validator.isNonNullObject(payload)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload must be a non-null object');
}
validateAps(payload.aps);
}
/**
* Checks if the given Aps object is valid. The object must have a valid alert. If the validation
* is successful, transforms the input object by renaming the keys to valid APNS payload keys.
*
* @param {Aps} aps An object to be validated.
*/
function validateAps(aps) {
if (typeof aps === 'undefined') {
return;
}
else if (!validator.isNonNullObject(aps)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps must be a non-null object');
}
validateApsAlert(aps.alert);
validateApsSound(aps.sound);
var propertyMappings = {
contentAvailable: 'content-available',
mutableContent: 'mutable-content',
threadId: 'thread-id',
};
Object.keys(propertyMappings).forEach(function (key) {
if (key in aps && propertyMappings[key] in aps) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Multiple specifications for " + key + " in Aps");
}
});
index_1.renameProperties(aps, propertyMappings);
var contentAvailable = aps['content-available'];
if (typeof contentAvailable !== 'undefined' && contentAvailable !== 1) {
if (contentAvailable === true) {
aps['content-available'] = 1;
}
else {
delete aps['content-available'];
}
}
var mutableContent = aps['mutable-content'];
if (typeof mutableContent !== 'undefined' && mutableContent !== 1) {
if (mutableContent === true) {
aps['mutable-content'] = 1;
}
else {
delete aps['mutable-content'];
}
}
}
function validateApsSound(sound) {
if (typeof sound === 'undefined' || validator.isString(sound)) {
return;
}
else if (!validator.isNonNullObject(sound)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound must be a string or a non-null object');
}
var volume = sound.volume;
if (typeof volume !== 'undefined') {
if (!validator.isNumber(volume)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound.volume must be a number');
}
if (volume < 0 || volume > 1) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.sound.volume must be in the interval [0, 1]');
}
}
var soundObject = sound;
var key = 'critical';
var critical = soundObject[key];
if (typeof critical !== 'undefined' && critical !== 1) {
if (critical === true) {
soundObject[key] = 1;
}
else {
delete soundObject[key];
}
}
}
/**
* Checks if the given alert object is valid. Alert could be a string or a complex object.
* If specified as an object, it must have valid localization parameters. If successful, transforms
* the input object by renaming the keys to valid APNS payload keys.
*
* @param {string | ApsAlert} alert An alert string or an object to be validated.
*/
function validateApsAlert(alert) {
if (typeof alert === 'undefined' || validator.isString(alert)) {
return;
}
else if (!validator.isNonNullObject(alert)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert must be a string or a non-null object');
}
var apsAlert = alert;
if (validator.isNonEmptyArray(apsAlert.locArgs) &&
!validator.isNonEmptyString(apsAlert.locKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.locKey is required when specifying locArgs');
}
if (validator.isNonEmptyArray(apsAlert.titleLocArgs) &&
!validator.isNonEmptyString(apsAlert.titleLocKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.titleLocKey is required when specifying titleLocArgs');
}
if (validator.isNonEmptyArray(apsAlert.subtitleLocArgs) &&
!validator.isNonEmptyString(apsAlert.subtitleLocKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'apns.payload.aps.alert.subtitleLocKey is required when specifying subtitleLocArgs');
}
var propertyMappings = {
locKey: 'loc-key',
locArgs: 'loc-args',
titleLocKey: 'title-loc-key',
titleLocArgs: 'title-loc-args',
subtitleLocKey: 'subtitle-loc-key',
subtitleLocArgs: 'subtitle-loc-args',
actionLocKey: 'action-loc-key',
launchImage: 'launch-image',
};
index_1.renameProperties(apsAlert, propertyMappings);
}
/**
* Checks if the given AndroidConfig object is valid. The object must have valid ttl, data,
* and notification fields. If successful, transforms the input object by renaming keys to valid
* Android keys. Also transforms the ttl value to the format expected by FCM service.
*
* @param {AndroidConfig} config An object to be validated.
*/
function validateAndroidConfig(config) {
if (typeof config === 'undefined') {
return;
}
else if (!validator.isNonNullObject(config)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android must be a non-null object');
}
if (typeof config.ttl !== 'undefined') {
if (!validator.isNumber(config.ttl) || config.ttl < 0) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'TTL must be a non-negative duration in milliseconds');
}
var seconds = Math.floor(config.ttl / 1000);
var nanos = (config.ttl - seconds * 1000) * 1000000;
var duration = void 0;
if (nanos > 0) {
var nanoString = nanos.toString();
while (nanoString.length < 9) {
nanoString = '0' + nanoString;
}
duration = seconds + "." + nanoString + "s";
}
else {
duration = seconds + "s";
}
config.ttl = duration;
}
validateStringMap(config.data, 'android.data');
validateAndroidNotification(config.notification);
var propertyMappings = {
collapseKey: 'collapse_key',
restrictedPackageName: 'restricted_package_name',
};
index_1.renameProperties(config, propertyMappings);
}
/**
* Checks if the given AndroidNotification object is valid. The object must have valid color and
* localization parameters. If successful, transforms the input object by renaming keys to valid
* Android keys.
*
* @param {AndroidNotification} notification An object to be validated.
*/
function validateAndroidNotification(notification) {
if (typeof notification === 'undefined') {
return;
}
else if (!validator.isNonNullObject(notification)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification must be a non-null object');
}
if (typeof notification.color !== 'undefined' && !/^#[0-9a-fA-F]{6}$/.test(notification.color)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.color must be in the form #RRGGBB');
}
if (validator.isNonEmptyArray(notification.bodyLocArgs) &&
!validator.isNonEmptyString(notification.bodyLocKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.bodyLocKey is required when specifying bodyLocArgs');
}
if (validator.isNonEmptyArray(notification.titleLocArgs) &&
!validator.isNonEmptyString(notification.titleLocKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'android.notification.titleLocKey is required when specifying titleLocArgs');
}
var propertyMappings = {
clickAction: 'click_action',
bodyLocKey: 'body_loc_key',
bodyLocArgs: 'body_loc_args',
titleLocKey: 'title_loc_key',
titleLocArgs: 'title_loc_args',
channelId: 'channel_id',
};
index_1.renameProperties(notification, propertyMappings);
}
/**
* Checks if the given Message object is valid. Recursively validates all the child objects
* included in the message (android, apns, data etc.). If successful, transforms the message
* in place by renaming the keys to what's expected by the remote FCM service.
*
* @param {Message} Message An object to be validated.
*/
function validateMessage(message) {
if (!validator.isNonNullObject(message)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Message must be a non-null object');
}
var anyMessage = message;
if (anyMessage.topic) {
// If the topic name is prefixed, remove it.
if (anyMessage.topic.startsWith('/topics/')) {
anyMessage.topic = anyMessage.topic.replace(/^\/topics\//, '');
}
// Checks for illegal characters and empty string.
if (!/^[a-zA-Z0-9-_.~%]+$/.test(anyMessage.topic)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Malformed topic name');
}
}
var targets = [anyMessage.token, anyMessage.topic, anyMessage.condition];
if (targets.filter(function (v) { return validator.isNonEmptyString(v); }).length !== 1) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Exactly one of topic, token or condition is required');
}
validateStringMap(message.data, 'data');
validateAndroidConfig(message.android);
validateWebpushConfig(message.webpush);
validateApnsConfig(message.apns);
}
/**
* Maps a raw FCM server response to a MessagingDevicesResponse object.
*
* @param {object} response The raw FCM server response to map.
*
* @return {MessagingDeviceGroupResponse} The mapped MessagingDevicesResponse object.
*/
function mapRawResponseToDevicesResponse(response) {
// Rename properties on the server response
utils.renameProperties(response, MESSAGING_DEVICES_RESPONSE_KEYS_MAP);
if ('results' in response) {
response.results.forEach(function (messagingDeviceResult) {
utils.renameProperties(messagingDeviceResult, MESSAGING_DEVICE_RESULT_KEYS_MAP);
// Map the FCM server's error strings to actual error objects.
if ('error' in messagingDeviceResult) {
var newError = error_1.FirebaseMessagingError.fromServerError(messagingDeviceResult.error, /* message */ undefined, messagingDeviceResult.error);
messagingDeviceResult.error = newError;
}
});
}
return response;
}
/**
* Maps a raw FCM server response to a MessagingDeviceGroupResponse object.
*
* @param {object} response The raw FCM server response to map.
*
* @return {MessagingDeviceGroupResponse} The mapped MessagingDeviceGroupResponse object.
*/
function mapRawResponseToDeviceGroupResponse(response) {
// Rename properties on the server response
utils.renameProperties(response, MESSAGING_DEVICE_GROUP_RESPONSE_KEYS_MAP);
// Add the 'failedRegistrationTokens' property if it does not exist on the response, which
// it won't when the 'failureCount' property has a value of 0)
response.failedRegistrationTokens = response.failedRegistrationTokens || [];
return response;
}
/**
* Maps a raw FCM server response to a MessagingTopicManagementResponse object.
*
* @param {object} response The raw FCM server response to map.
*
* @return {MessagingTopicManagementResponse} The mapped MessagingTopicManagementResponse object.
*/
function mapRawResponseToTopicManagementResponse(response) {
// Add the success and failure counts.
var result = {
successCount: 0,
failureCount: 0,
errors: [],
};
var errors = [];
if ('results' in response) {
response.results.forEach(function (tokenManagementResult, index) {
// Map the FCM server's error strings to actual error objects.
if ('error' in tokenManagementResult) {
result.failureCount += 1;
var newError = error_1.FirebaseMessagingError.fromTopicManagementServerError(tokenManagementResult.error, /* message */ undefined, tokenManagementResult.error);
result.errors.push({
index: index,
error: newError,
});
}
else {
result.successCount += 1;
}
});
}
return result;
}
/**
* Internals of a Messaging instance.
*/
var MessagingInternals = /** @class */ (function () {
function MessagingInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
MessagingInternals.prototype.delete = function () {
// There are no resources to clean up.
return Promise.resolve(undefined);
};
return MessagingInternals;
}());
/**
* Messaging service bound to the provided app.
*/
var Messaging = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app for this Messaging service.
* @constructor
*/
function Messaging(app) {
this.INTERNAL = new MessagingInternals();
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_ARGUMENT, 'First argument passed to admin.messaging() must be a valid Firebase app instance.');
}
var projectId = utils.getProjectId(app);
if (!validator.isNonEmptyString(projectId)) {
// Assert for an explicit projct ID (either via AppOptions or the cert itself).
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_ARGUMENT, 'Failed to determine project ID for Messaging. Initialize the '
+ 'SDK with service account credentials or set project ID as an app option. '
+ 'Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.');
}
this.urlPath = "/v1/projects/" + projectId + "/messages:send";
this.appInternal = app;
this.messagingRequestHandler = new messaging_api_request_1.FirebaseMessagingRequestHandler(app);
}
Object.defineProperty(Messaging.prototype, "app", {
/**
* Returns the app associated with this Messaging instance.
*
* @return {FirebaseApp} The app associated with this Messaging instance.
*/
get: function () {
return this.appInternal;
},
enumerable: true,
configurable: true
});
/**
* Sends a message via Firebase Cloud Messaging (FCM).
*
* @param {Message} message The message to be sent.
* @param {boolean=} dryRun Whether to send the message in the dry-run (validation only) mode.
*
* @return {Promise<string>} A Promise fulfilled with a message ID string.
*/
Messaging.prototype.send = function (message, dryRun) {
var _this = this;
var copy = deep_copy_1.deepCopy(message);
validateMessage(copy);
if (typeof dryRun !== 'undefined' && !validator.isBoolean(dryRun)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_ARGUMENT, 'dryRun must be a boolean');
}
return Promise.resolve()
.then(function () {
var request = { message: copy };
if (dryRun) {
request.validate_only = true;
}
return _this.messagingRequestHandler.invokeRequestHandler(FCM_SEND_HOST, _this.urlPath, request);
})
.then(function (response) {
return response.name;
});
};
/**
* Sends an FCM message to a single device or an array of devices.
*
* @param {string|string[]} registrationTokenOrTokens The registration token or an array of
* registration tokens for the device(s) to which to send the message.
* @param {MessagingPayload} payload The message payload.
* @param {MessagingOptions} [options = {}] Optional options to alter the message.
*
* @return {Promise<MessagingDevicesResponse|MessagingDeviceGroupResponse>} A Promise fulfilled
* with the server's response after the message has been sent.
*/
Messaging.prototype.sendToDevice = function (registrationTokenOrTokens, payload, options) {
var _this = this;
if (options === void 0) { options = {}; }
// Validate the input argument types. Since these are common developer errors when getting
// started, throw an error instead of returning a rejected promise.
this.validateRegistrationTokensType(registrationTokenOrTokens, 'sendToDevice', error_1.MessagingClientErrorCode.INVALID_RECIPIENT);
this.validateMessagingPayloadAndOptionsTypes(payload, options);
return Promise.resolve()
.then(function () {
// Validate the contents of the input arguments. Because we are now in a promise, any thrown
// error will cause this method to return a rejected promise.
_this.validateRegistrationTokens(registrationTokenOrTokens, 'sendToDevice', error_1.MessagingClientErrorCode.INVALID_RECIPIENT);
var payloadCopy = _this.validateMessagingPayload(payload);
var optionsCopy = _this.validateMessagingOptions(options);
var request = deep_copy_1.deepCopy(payloadCopy);
deep_copy_1.deepExtend(request, optionsCopy);
if (validator.isString(registrationTokenOrTokens)) {
request.to = registrationTokenOrTokens;
}
else {
request.registration_ids = registrationTokenOrTokens;
}
return _this.messagingRequestHandler.invokeRequestHandler(FCM_SEND_HOST, FCM_SEND_PATH, request);
})
.then(function (response) {
// The sendToDevice() and sendToDeviceGroup() methods both set the `to` query parameter in
// the underlying FCM request. If the provided registration token argument is actually a
// valid notification key, the response from the FCM server will be a device group response.
// If that is the case, we map the response to a MessagingDeviceGroupResponse.
// See b/35394951 for more context.
if ('multicast_id' in response) {
return mapRawResponseToDevicesResponse(response);
}
else {
return mapRawResponseToDeviceGroupResponse(response);
}
});
};
/**
* Sends an FCM message to a device group.
*
* @param {string} notificationKey The notification key representing the device group to which to
* send the message.
* @param {MessagingPayload} payload The message payload.
* @param {MessagingOptions} [options = {}] Optional options to alter the message.
*
* @return {Promise<MessagingDeviceGroupResponse|MessagingDevicesResponse>} A Promise fulfilled
* with the server's response after the message has been sent.
*/
Messaging.prototype.sendToDeviceGroup = function (notificationKey, payload, options) {
var _this = this;
if (options === void 0) { options = {}; }
if (!validator.isNonEmptyString(notificationKey)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_RECIPIENT, 'Notification key provided to sendToDeviceGroup() must be a non-empty string.');
}
else if (notificationKey.indexOf(':') !== -1) {
// It is possible the developer provides a registration token instead of a notification key
// to this method. We can detect some of those cases by checking to see if the string contains
// a colon. Not all registration tokens will contain a colon (only newer ones will), but no
// notification keys will contain a colon, so we can use it as a rough heuristic.
// See b/35394951 for more context.
return Promise.reject(new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_RECIPIENT, 'Notification key provided to sendToDeviceGroup() has the format of a registration token. ' +
'You should use sendToDevice() instead.'));
}
// Validate the types of the payload and options arguments. Since these are common developer
// errors, throw an error instead of returning a rejected promise.
this.validateMessagingPayloadAndOptionsTypes(payload, options);
return Promise.resolve()
.then(function () {
// Validate the contents of the payload and options objects. Because we are now in a
// promise, any thrown error will cause this method to return a rejected promise.
var payloadCopy = _this.validateMessagingPayload(payload);
var optionsCopy = _this.validateMessagingOptions(options);
var request = deep_copy_1.deepCopy(payloadCopy);
deep_copy_1.deepExtend(request, optionsCopy);
request.to = notificationKey;
return _this.messagingRequestHandler.invokeRequestHandler(FCM_SEND_HOST, FCM_SEND_PATH, request);
})
.then(function (response) {
// The sendToDevice() and sendToDeviceGroup() methods both set the `to` query parameter in
// the underlying FCM request. If the provided notification key argument has an invalid
// format (that is, it is either a registration token or some random string), the response
// from the FCM server will default to a devices response (which we detect by looking for
// the `multicast_id` property). If that is the case, we either throw an error saying the
// provided notification key is invalid (if the message failed to send) or map the response
// to a MessagingDevicesResponse (if the message succeeded).
// See b/35394951 for more context.
if ('multicast_id' in response) {
if (response.success === 0) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_RECIPIENT, 'Notification key provided to sendToDeviceGroup() is invalid.');
}
else {
return mapRawResponseToDevicesResponse(response);
}
}
return mapRawResponseToDeviceGroupResponse(response);
});
};
/**
* Sends an FCM message to a topic.
*
* @param {string} topic The name of the topic to which to send the message.
* @param {MessagingPayload} payload The message payload.
* @param {MessagingOptions} [options = {}] Optional options to alter the message.
*
* @return {Promise<MessagingTopicResponse>} A Promise fulfilled with the server's response after
* the message has been sent.
*/
Messaging.prototype.sendToTopic = function (topic, payload, options) {
var _this = this;
if (options === void 0) { options = {}; }
// Validate the input argument types. Since these are common developer errors when getting
// started, throw an error instead of returning a rejected promise.
this.validateTopicType(topic, 'sendToTopic', error_1.MessagingClientErrorCode.INVALID_RECIPIENT);
this.validateMessagingPayloadAndOptionsTypes(payload, options);
// Prepend the topic with /topics/ if necessary.
topic = this.normalizeTopic(topic);
return Promise.resolve()
.then(function () {
// Validate the contents of the payload and options objects. Because we are now in a
// promise, any thrown error will cause this method to return a rejected promise.
var payloadCopy = _this.validateMessagingPayload(payload);
var optionsCopy = _this.validateMessagingOptions(options);
_this.validateTopic(topic, 'sendToTopic', error_1.MessagingClientErrorCode.INVALID_RECIPIENT);
var request = deep_copy_1.deepCopy(payloadCopy);
deep_copy_1.deepExtend(request, optionsCopy);
request.to = topic;
return _this.messagingRequestHandler.invokeRequestHandler(FCM_SEND_HOST, FCM_SEND_PATH, request);
})
.then(function (response) {
// Rename properties on the server response
utils.renameProperties(response, MESSAGING_TOPIC_RESPONSE_KEYS_MAP);
return response;
});
};
/**
* Sends an FCM message to a condition.
*
* @param {string} condition The condition to which to send the message.
* @param {MessagingPayload} payload The message payload.
* @param {MessagingOptions} [options = {}] Optional options to alter the message.
*
* @return {Promise<MessagingConditionResponse>} A Promise fulfilled with the server's response
* after the message has been sent.
*/
Messaging.prototype.sendToCondition = function (condition, payload, options) {
var _this = this;
if (options === void 0) { options = {}; }
if (!validator.isNonEmptyString(condition)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_RECIPIENT, 'Condition provided to sendToCondition() must be a non-empty string.');
}
// Validate the types of the payload and options arguments. Since these are common developer
// errors, throw an error instead of returning a rejected promise.
this.validateMessagingPayloadAndOptionsTypes(payload, options);
// The FCM server rejects conditions which are surrounded in single quotes. When the condition
// is stringified over the wire, double quotes in it get converted to \" which the FCM server
// does not properly handle. We can get around this by replacing internal double quotes with
// single quotes.
condition = condition.replace(/"/g, '\'');
return Promise.resolve()
.then(function () {
// Validate the contents of the payload and options objects. Because we are now in a
// promise, any thrown error will cause this method to return a rejected promise.
var payloadCopy = _this.validateMessagingPayload(payload);
var optionsCopy = _this.validateMessagingOptions(options);
var request = deep_copy_1.deepCopy(payloadCopy);
deep_copy_1.deepExtend(request, optionsCopy);
request.condition = condition;
return _this.messagingRequestHandler.invokeRequestHandler(FCM_SEND_HOST, FCM_SEND_PATH, request);
})
.then(function (response) {
// Rename properties on the server response
utils.renameProperties(response, MESSAGING_CONDITION_RESPONSE_KEYS_MAP);
return response;
});
};
/**
* Subscribes a single device or an array of devices to a topic.
*
* @param {string|string[]} registrationTokenOrTokens The registration token or an array of
* registration tokens to subscribe to the topic.
* @param {string} topic The topic to which to subscribe.
*
* @return {Promise<MessagingTopicManagementResponse>} A Promise fulfilled with the parsed FCM
* server response.
*/
Messaging.prototype.subscribeToTopic = function (registrationTokenOrTokens, topic) {
return this.sendTopicManagementRequest(registrationTokenOrTokens, topic, 'subscribeToTopic', FCM_TOPIC_MANAGEMENT_ADD_PATH);
};
/**
* Unsubscribes a single device or an array of devices from a topic.
*
* @param {string|string[]} registrationTokenOrTokens The registration token or an array of
* registration tokens to unsubscribe from the topic.
* @param {string} topic The topic to which to subscribe.
*
* @return {Promise<MessagingTopicManagementResponse>} A Promise fulfilled with the parsed FCM
* server response.
*/
Messaging.prototype.unsubscribeFromTopic = function (registrationTokenOrTokens, topic) {
return this.sendTopicManagementRequest(registrationTokenOrTokens, topic, 'unsubscribeFromTopic', FCM_TOPIC_MANAGEMENT_REMOVE_PATH);
};
/**
* Helper method which sends and handles topic subscription management requests.
*
* @param {string|string[]} registrationTokenOrTokens The registration token or an array of
* registration tokens to unsubscribe from the topic.
* @param {string} topic The topic to which to subscribe.
* @param {string} methodName The name of the original method called.
* @param {string} path The endpoint path to use for the request.
*
* @return {Promise<MessagingTopicManagementResponse>} A Promise fulfilled with the parsed server
* response.
*/
Messaging.prototype.sendTopicManagementRequest = function (registrationTokenOrTokens, topic, methodName, path) {
var _this = this;
this.validateRegistrationTokensType(registrationTokenOrTokens, methodName);
this.validateTopicType(topic, methodName);
// Prepend the topic with /topics/ if necessary.
topic = this.normalizeTopic(topic);
return Promise.resolve()
.then(function () {
// Validate the contents of the input arguments. Because we are now in a promise, any thrown
// error will cause this method to return a rejected promise.
_this.validateRegistrationTokens(registrationTokenOrTokens, methodName);
_this.validateTopic(topic, methodName);
// Ensure the registration token(s) input argument is an array.
var registrationTokensArray = registrationTokenOrTokens;
if (validator.isString(registrationTokenOrTokens)) {
registrationTokensArray = [registrationTokenOrTokens];
}
var request = {
to: topic,
registration_tokens: registrationTokensArray,
};
return _this.messagingRequestHandler.invokeRequestHandler(FCM_TOPIC_MANAGEMENT_HOST, path, request);
})
.then(function (response) {
return mapRawResponseToTopicManagementResponse(response);
});
};
/**
* Validates the types of the messaging payload and options. If invalid, an error will be thrown.
*
* @param {MessagingPayload} payload The messaging payload to validate.
* @param {MessagingOptions} options The messaging options to validate.
*/
Messaging.prototype.validateMessagingPayloadAndOptionsTypes = function (payload, options) {
// Validate the payload is an object
if (!validator.isNonNullObject(payload)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Messaging payload must be an object with at least one of the "data" or "notification" properties.');
}
// Validate the options argument is an object
if (!validator.isNonNullObject(options)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, 'Messaging options must be an object.');
}
};
/**
* Validates the messaging payload. If invalid, an error will be thrown.
*
* @param {MessagingPayload} payload The messaging payload to validate.
*
* @return {MessagingPayload} A copy of the provided payload with whitelisted properties switched
* from camelCase to underscore_case.
*/
Messaging.prototype.validateMessagingPayload = function (payload) {
var payloadCopy = deep_copy_1.deepCopy(payload);
var payloadKeys = Object.keys(payloadCopy);
var validPayloadKeys = ['data', 'notification'];
var containsDataOrNotificationKey = false;
payloadKeys.forEach(function (payloadKey) {
// Validate the payload does not contain any invalid keys
if (validPayloadKeys.indexOf(payloadKey) === -1) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Messaging payload contains an invalid \"" + payloadKey + "\" property. Valid properties are " +
"\"data\" and \"notification\".");
}
else {
containsDataOrNotificationKey = true;
}
});
// Validate the payload contains at least one of the "data" and "notification" keys
if (!containsDataOrNotificationKey) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, 'Messaging payload must contain at least one of the "data" or "notification" properties.');
}
payloadKeys.forEach(function (payloadKey) {
var value = payloadCopy[payloadKey];
// Validate each top-level key in the payload is an object
if (!validator.isNonNullObject(value)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Messaging payload contains an invalid value for the \"" + payloadKey + "\" property. " +
"Value must be an object.");
}
Object.keys(value).forEach(function (subKey) {
if (!validator.isString(value[subKey])) {
// Validate all sub-keys have a string value
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Messaging payload contains an invalid value for the \"" + payloadKey + "." + subKey + "\" " +
"property. Values must be strings.");
}
else if (payloadKey === 'data' && /^google\./.test(subKey)) {
// Validate the data payload does not contain keys which start with 'google.'.
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Messaging payload contains the blacklisted \"data." + subKey + "\" property.");
}
});
});
// Validate the data payload object does not contain blacklisted properties
if ('data' in payloadCopy) {
exports.BLACKLISTED_DATA_PAYLOAD_KEYS.forEach(function (blacklistedKey) {
if (blacklistedKey in payloadCopy.data) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_PAYLOAD, "Messaging payload contains the blacklisted \"data." + blacklistedKey + "\" property.");
}
});
}
// Convert whitelisted camelCase keys to underscore_case
if ('notification' in payloadCopy) {
utils.renameProperties(payloadCopy.notification, CAMELCASED_NOTIFICATION_PAYLOAD_KEYS_MAP);
}
return payloadCopy;
};
/**
* Validates the messaging options. If invalid, an error will be thrown.
*
* @param {MessagingOptions} options The messaging options to validate.
*
* @return {MessagingOptions} A copy of the provided options with whitelisted properties switched
* from camelCase to underscore_case.
*/
Messaging.prototype.validateMessagingOptions = function (options) {
var optionsCopy = deep_copy_1.deepCopy(options);
// Validate the options object does not contain blacklisted properties
exports.BLACKLISTED_OPTIONS_KEYS.forEach(function (blacklistedKey) {
if (blacklistedKey in optionsCopy) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains the blacklisted \"" + blacklistedKey + "\" property.");
}
});
// Convert whitelisted camelCase keys to underscore_case
utils.renameProperties(optionsCopy, CAMELCASE_OPTIONS_KEYS_MAP);
// Validate the options object contains valid values for whitelisted properties
if ('collapse_key' in optionsCopy && !validator.isNonEmptyString(optionsCopy.collapse_key)) {
var keyName = ('collapseKey' in options) ? 'collapseKey' : 'collapse_key';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a non-empty string.');
}
else if ('dry_run' in optionsCopy && !validator.isBoolean(optionsCopy.dry_run)) {
var keyName = ('dryRun' in options) ? 'dryRun' : 'dry_run';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a boolean.');
}
else if ('priority' in optionsCopy && !validator.isNonEmptyString(optionsCopy.priority)) {
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, 'Messaging options contains an invalid value for the "priority" property. Value must ' +
'be a non-empty string.');
}
else if ('restricted_package_name' in optionsCopy &&
!validator.isNonEmptyString(optionsCopy.restricted_package_name)) {
var keyName = ('restrictedPackageName' in options) ? 'restrictedPackageName' : 'restricted_package_name';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a non-empty string.');
}
else if ('time_to_live' in optionsCopy && !validator.isNumber(optionsCopy.time_to_live)) {
var keyName = ('timeToLive' in options) ? 'timeToLive' : 'time_to_live';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a number.');
}
else if ('content_available' in optionsCopy && !validator.isBoolean(optionsCopy.content_available)) {
var keyName = ('contentAvailable' in options) ? 'contentAvailable' : 'content_available';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a boolean.');
}
else if ('mutable_content' in optionsCopy && !validator.isBoolean(optionsCopy.mutable_content)) {
var keyName = ('mutableContent' in options) ? 'mutableContent' : 'mutable_content';
throw new error_1.FirebaseMessagingError(error_1.MessagingClientErrorCode.INVALID_OPTIONS, "Messaging options contains an invalid value for the \"" + keyName + "\" property. Value must " +
'be a boolean.');
}
return optionsCopy;
};
/**
* Validates the type of the provided registration token(s). If invalid, an error will be thrown.
*
* @param {string|string[]} registrationTokenOrTokens The registration token(s) to validate.
* @param {string} method The method name to use in error messages.
* @param {ErrorInfo?} [errorInfo] The error info to use if the registration tokens are invalid.
*/
Messaging.prototype.validateRegistrationTokensType = function (registrationTokenOrTokens, methodName, errorInfo) {
if (errorInfo === void 0) { errorInfo = error_1.MessagingClientErrorCode.INVALID_ARGUMENT; }
if (!validator.isNonEmptyArray(registrationTokenOrTokens) &&
!validator.isNonEmptyString(registrationTokenOrTokens)) {
throw new error_1.FirebaseMessagingError(errorInfo, "Registration token(s) provided to " + methodName + "() must be a non-empty string or a " +
'non-empty array.');
}
};
/**
* Validates the provided registration tokens. If invalid, an error will be thrown.
*
* @param {string|string[]} registrationTokenOrTokens The registration token or an array of
* registration tokens to validate.
* @param {string} method The method name to use in error messages.
* @param {errorInfo?} [ErrorInfo] The error info to use if the registration tokens are invalid.
*/
Messaging.prototype.validateRegistrationTokens = function (registrationTokenOrTokens, methodName, errorInfo) {
if (errorInfo === void 0) { errorInfo = error_1.MessagingClientErrorCode.INVALID_ARGUMENT; }
if (validator.isArray(registrationTokenOrTokens)) {
// Validate the array contains no more than 1,000 registration tokens.
if (registrationTokenOrTokens.length > 1000) {
throw new error_1.FirebaseMessagingError(errorInfo, "Too many registration tokens provided in a single request to " + methodName + "(). Batch " +
'your requests to contain no more than 1,000 registration tokens per request.');
}
// Validate the array contains registration tokens which are non-empty strings.
registrationTokenOrTokens.forEach(function (registrationToken, index) {
if (!validator.isNonEmptyString(registrationToken)) {
throw new error_1.FirebaseMessagingError(errorInfo, "Registration token provided to " + methodName + "() at index " + index + " must be a " +
'non-empty string.');
}
});
}
};
/**
* Validates the type of the provided topic. If invalid, an error will be thrown.
*
* @param {string} topic The topic to validate.
* @param {string} method The method name to use in error messages.
* @param {ErrorInfo?} [errorInfo] The error info to use if the topic is invalid.
*/
Messaging.prototype.validateTopicType = function (topic, methodName, errorInfo) {
if (errorInfo === void 0) { errorInfo = error_1.MessagingClientErrorCode.INVALID_ARGUMENT; }
if (!validator.isNonEmptyString(topic)) {
throw new error_1.FirebaseMessagingError(errorInfo, "Topic provided to " + methodName + "() must be a string which matches the format " +
'"/topics/[a-zA-Z0-9-_.~%]+".');
}
};
/**
* Validates the provided topic. If invalid, an error will be thrown.
*
* @param {string} topic The topic to validate.
* @param {string} method The method name to use in error messages.
* @param {ErrorInfo?} [errorInfo] The error info to use if the topic is invalid.
*/
Messaging.prototype.validateTopic = function (topic, methodName, errorInfo) {
if (errorInfo === void 0) { errorInfo = error_1.MessagingClientErrorCode.INVALID_ARGUMENT; }
if (!validator.isTopic(topic)) {
throw new error_1.FirebaseMessagingError(errorInfo, "Topic provided to " + methodName + "() must be a string which matches the format " +
'"/topics/[a-zA-Z0-9-_.~%]+".');
}
};
/**
* Normalizes the provided topic name by prepending it with '/topics/', if necessary.
*
* @param {string} topic The topic name to normalize.
*
* @return {string} The normalized topic name.
*/
Messaging.prototype.normalizeTopic = function (topic) {
if (!/^\/topics\//.test(topic)) {
topic = "/topics/" + topic;
}
return topic;
};
return Messaging;
}());
exports.Messaging = Messaging;

View File

@ -0,0 +1,116 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
var project_management_api_request_1 = require("./project-management-api-request");
var AndroidApp = /** @class */ (function () {
function AndroidApp(appId, requestHandler) {
this.appId = appId;
this.requestHandler = requestHandler;
if (!validator.isNonEmptyString(appId)) {
throw new error_1.FirebaseProjectManagementError('invalid-argument', 'appId must be a non-empty string.');
}
this.resourceName = "projects/-/androidApps/" + appId;
}
AndroidApp.prototype.getMetadata = function () {
return this.requestHandler.getResource(this.resourceName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'getMetadata()\'s responseData must be a non-null object.');
var requiredFieldsList = ['name', 'appId', 'projectId', 'packageName'];
requiredFieldsList.forEach(function (requiredField) {
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(responseData[requiredField]), responseData, "getMetadata()'s responseData." + requiredField + " must be a non-empty string.");
});
var metadata = {
resourceName: responseData.name,
appId: responseData.appId,
displayName: responseData.displayName || null,
projectId: responseData.projectId,
packageName: responseData.packageName,
};
return metadata;
});
};
AndroidApp.prototype.setDisplayName = function (newDisplayName) {
return this.requestHandler.setDisplayName(this.resourceName, newDisplayName);
};
AndroidApp.prototype.getShaCertificates = function () {
return this.requestHandler.getAndroidShaCertificates(this.resourceName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'getShaCertificates()\'s responseData must be a non-null object.');
if (!responseData.certificates) {
return [];
}
project_management_api_request_1.assertServerResponse(validator.isArray(responseData.certificates), responseData, '"certificates" field must be present in the getShaCertificates() response data.');
var requiredFieldsList = ['name', 'shaHash'];
return responseData.certificates.map(function (certificateJson) {
requiredFieldsList.forEach(function (requiredField) {
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(certificateJson[requiredField]), responseData, "getShaCertificates()'s responseData.certificates[]." + requiredField + " must be a "
+ "non-empty string.");
});
return new ShaCertificate(certificateJson.shaHash, certificateJson.name);
});
});
};
AndroidApp.prototype.addShaCertificate = function (certificateToAdd) {
return this.requestHandler.addAndroidShaCertificate(this.resourceName, certificateToAdd);
};
AndroidApp.prototype.deleteShaCertificate = function (certificateToDelete) {
return this.requestHandler.deleteResource(certificateToDelete.resourceName);
};
/**
* @return {Promise<string>} A promise that resolves to a UTF-8 JSON string, typically intended to
* be written to a JSON file.
*/
AndroidApp.prototype.getConfig = function () {
return this.requestHandler.getConfig(this.resourceName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'getConfig()\'s responseData must be a non-null object.');
var base64ConfigFileContents = responseData.configFileContents;
project_management_api_request_1.assertServerResponse(validator.isBase64String(base64ConfigFileContents), responseData, "getConfig()'s responseData.configFileContents must be a base64 string.");
return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8');
});
};
return AndroidApp;
}());
exports.AndroidApp = AndroidApp;
var ShaCertificate = /** @class */ (function () {
/**
* Creates a ShaCertificate using the given hash. The ShaCertificate's type (eg. 'sha256') is
* automatically determined from the hash itself.
*
* @param shaHash The sha256 or sha1 hash for this certificate.
* @param resourceName The Firebase resource name for this certificate. This does not need to be
* set when creating a new certificate.
*/
function ShaCertificate(shaHash, resourceName) {
this.shaHash = shaHash;
this.resourceName = resourceName;
if (/^[a-fA-F0-9]{40}$/.test(shaHash)) {
this.certType = 'sha1';
}
else if (/^[a-fA-F0-9]{64}$/.test(shaHash)) {
this.certType = 'sha256';
}
else {
throw new error_1.FirebaseProjectManagementError('invalid-argument', 'shaHash must be either a sha256 hash or a sha1 hash.');
}
}
return ShaCertificate;
}());
exports.ShaCertificate = ShaCertificate;

View File

@ -0,0 +1,67 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
var project_management_api_request_1 = require("./project-management-api-request");
var IosApp = /** @class */ (function () {
function IosApp(appId, requestHandler) {
this.appId = appId;
this.requestHandler = requestHandler;
if (!validator.isNonEmptyString(appId)) {
throw new error_1.FirebaseProjectManagementError('invalid-argument', 'appId must be a non-empty string.');
}
this.resourceName = "projects/-/iosApps/" + appId;
}
IosApp.prototype.getMetadata = function () {
return this.requestHandler.getResource(this.resourceName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'getMetadata()\'s responseData must be a non-null object.');
var requiredFieldsList = ['name', 'appId', 'projectId', 'bundleId'];
requiredFieldsList.forEach(function (requiredField) {
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(responseData[requiredField]), responseData, "getMetadata()'s responseData." + requiredField + " must be a non-empty string.");
});
var metadata = {
resourceName: responseData.name,
appId: responseData.appId,
displayName: responseData.displayName || null,
projectId: responseData.projectId,
bundleId: responseData.bundleId,
};
return metadata;
});
};
IosApp.prototype.setDisplayName = function (newDisplayName) {
return this.requestHandler.setDisplayName(this.resourceName, newDisplayName);
};
/**
* @return {Promise<string>} A promise that resolves to a UTF-8 XML string, typically intended to
* be written to a plist file.
*/
IosApp.prototype.getConfig = function () {
return this.requestHandler.getConfig(this.resourceName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'getConfig()\'s responseData must be a non-null object.');
var base64ConfigFileContents = responseData.configFileContents;
project_management_api_request_1.assertServerResponse(validator.isBase64String(base64ConfigFileContents), responseData, "getConfig()'s responseData.configFileContents must be a base64 string.");
return Buffer.from(base64ConfigFileContents, 'base64').toString('utf8');
});
};
return IosApp;
}());
exports.IosApp = IosApp;

View File

@ -0,0 +1,260 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var api_request_1 = require("../utils/api-request");
var error_1 = require("../utils/error");
var validator = require("../utils/validator");
/** Project management backend host and port. */
var PROJECT_MANAGEMENT_HOST_AND_PORT = 'firebase.googleapis.com:443';
/** Project management backend path. */
var PROJECT_MANAGEMENT_PATH = '/v1/';
/** Project management beta backend path. */
var PROJECT_MANAGEMENT_BETA_PATH = '/v1beta1/';
/** Project management request header. */
var PROJECT_MANAGEMENT_HEADERS = {
'X-Client-Version': 'Node/Admin/6.4.0',
};
/** Project management request timeout duration in milliseconds. */
var PROJECT_MANAGEMENT_TIMEOUT_MILLIS = 10000;
var LIST_APPS_MAX_PAGE_SIZE = 100;
var CERT_TYPE_API_MAP = {
sha1: 'SHA_1',
sha256: 'SHA_256',
};
function assertServerResponse(condition, responseData, message) {
if (!condition) {
throw new error_1.FirebaseProjectManagementError('invalid-server-response', message + " Response data: " + JSON.stringify(responseData, null, 2));
}
}
exports.assertServerResponse = assertServerResponse;
/**
* Class that provides mechanism to send requests to the Firebase project management backend
* endpoints.
*
* @private
*/
var ProjectManagementRequestHandler = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app used to fetch access tokens to sign API requests.
* @constructor
*/
function ProjectManagementRequestHandler(app) {
this.baseUrl = "https://" + PROJECT_MANAGEMENT_HOST_AND_PORT + PROJECT_MANAGEMENT_PATH;
this.baseBetaUrl = "https://" + PROJECT_MANAGEMENT_HOST_AND_PORT + PROJECT_MANAGEMENT_BETA_PATH;
this.httpClient = new api_request_1.AuthorizedHttpClient(app);
}
ProjectManagementRequestHandler.wrapAndRethrowHttpError = function (errStatusCode, errText) {
var errorCode;
var errorMessage;
switch (errStatusCode) {
case 400:
errorCode = 'invalid-argument';
errorMessage = 'Invalid argument provided.';
break;
case 401:
case 403:
errorCode = 'authentication-error';
errorMessage = 'An error occurred when trying to authenticate. Make sure the credential '
+ 'used to authenticate this SDK has the proper permissions. See '
+ 'https://firebase.google.com/docs/admin/setup for setup instructions.';
break;
case 404:
errorCode = 'not-found';
errorMessage = 'The specified entity could not be found.';
break;
case 409:
errorCode = 'already-exists';
errorMessage = 'The specified entity already exists.';
break;
case 500:
errorCode = 'internal-error';
errorMessage = 'An internal error has occurred. Please retry the request.';
break;
case 503:
errorCode = 'service-unavailable';
errorMessage = 'The server could not process the request in time. See the error '
+ 'documentation for more details.';
break;
default:
errorCode = 'unknown-error';
errorMessage = 'An unknown server error was returned.';
}
throw new error_1.FirebaseProjectManagementError(errorCode, errorMessage + " Status code: " + errStatusCode + ". Raw server response: \"" + errText + "\".");
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the project whose Android
* apps you want to list.
*/
ProjectManagementRequestHandler.prototype.listAndroidApps = function (parentResourceName) {
return this.invokeRequestHandler('GET', parentResourceName + "/androidApps?page_size=" + LIST_APPS_MAX_PAGE_SIZE,
/* requestData */ null, 'v1beta1');
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the project whose iOS apps
* you want to list.
*/
ProjectManagementRequestHandler.prototype.listIosApps = function (parentResourceName) {
return this.invokeRequestHandler('GET', parentResourceName + "/iosApps?page_size=" + LIST_APPS_MAX_PAGE_SIZE,
/* requestData */ null, 'v1beta1');
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the project that you want
* to create the Android app within.
*/
ProjectManagementRequestHandler.prototype.createAndroidApp = function (parentResourceName, packageName, displayName) {
var _this = this;
var requestData = {
packageName: packageName,
};
if (validator.isNonEmptyString(displayName)) {
requestData.displayName = displayName;
}
return this
.invokeRequestHandler('POST', parentResourceName + "/androidApps", requestData, 'v1beta1')
.then(function (responseData) {
assertServerResponse(validator.isNonNullObject(responseData), responseData, "createAndroidApp's responseData must be a non-null object.");
assertServerResponse(validator.isNonEmptyString(responseData.name), responseData, "createAndroidApp's responseData.name must be a non-empty string.");
return _this.pollRemoteOperationWithExponentialBackoff(responseData.name);
});
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the project that you want
* to create the iOS app within.
*/
ProjectManagementRequestHandler.prototype.createIosApp = function (parentResourceName, bundleId, displayName) {
var _this = this;
var requestData = {
bundleId: bundleId,
};
if (validator.isNonEmptyString(displayName)) {
requestData.displayName = displayName;
}
return this
.invokeRequestHandler('POST', parentResourceName + "/iosApps", requestData, 'v1beta1')
.then(function (responseData) {
assertServerResponse(validator.isNonNullObject(responseData), responseData, "createIosApp's responseData must be a non-null object.");
assertServerResponse(validator.isNonEmptyString(responseData.name), responseData, "createIosApp's responseData.name must be a non-empty string.");
return _this.pollRemoteOperationWithExponentialBackoff(responseData.name);
});
};
/**
* @param {string} resourceName Fully-qualified resource name of the entity whose display name you
* want to set.
*/
ProjectManagementRequestHandler.prototype.setDisplayName = function (resourceName, newDisplayName) {
var requestData = {
displayName: newDisplayName,
};
return this
.invokeRequestHandler('PATCH', resourceName + "?update_mask=display_name", requestData, 'v1beta1')
.then(function () { return null; });
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the Android app whose SHA
* certificates you want to get.
*/
ProjectManagementRequestHandler.prototype.getAndroidShaCertificates = function (parentResourceName) {
return this.invokeRequestHandler('GET', parentResourceName + "/sha", /* requestData */ null, 'v1beta1');
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the Android app that you
* want to add the given SHA certificate to.
*/
ProjectManagementRequestHandler.prototype.addAndroidShaCertificate = function (parentResourceName, certificate) {
var requestData = {
shaHash: certificate.shaHash,
certType: CERT_TYPE_API_MAP[certificate.certType],
};
return this
.invokeRequestHandler('POST', parentResourceName + "/sha", requestData, 'v1beta1')
.then(function () { return null; });
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the app whose config you
* want to get.
*/
ProjectManagementRequestHandler.prototype.getConfig = function (parentResourceName) {
return this.invokeRequestHandler('GET', parentResourceName + "/config", /* requestData */ null, 'v1beta1');
};
/**
* @param {string} parentResourceName Fully-qualified resource name of the entity that you want to
* get.
*/
ProjectManagementRequestHandler.prototype.getResource = function (parentResourceName) {
return this.invokeRequestHandler('GET', parentResourceName, /* requestData */ null, 'v1beta1');
};
/**
* @param {string} resourceName Fully-qualified resource name of the entity that you want to
* delete.
*/
ProjectManagementRequestHandler.prototype.deleteResource = function (resourceName) {
return this
.invokeRequestHandler('DELETE', resourceName, /* requestData */ null, 'v1beta1')
.then(function () { return null; });
};
ProjectManagementRequestHandler.prototype.pollRemoteOperationWithExponentialBackoff = function (operationResourceName) {
var _this = this;
var poller = new api_request_1.ExponentialBackoffPoller();
return poller.poll(function () {
return _this.invokeRequestHandler('GET', operationResourceName, /* requestData */ null)
.then(function (responseData) {
if (responseData.error) {
var errStatusCode = responseData.error.code || 500;
var errText = responseData.error.message || JSON.stringify(responseData.error);
ProjectManagementRequestHandler.wrapAndRethrowHttpError(errStatusCode, errText);
}
if (!responseData.done) {
// Continue polling.
return null;
}
// Polling complete. Resolve with operation response JSON.
return responseData.response;
});
});
};
/**
* Invokes the request handler with the provided request data.
*/
ProjectManagementRequestHandler.prototype.invokeRequestHandler = function (method, path, requestData, apiVersion) {
if (apiVersion === void 0) { apiVersion = 'v1'; }
var baseUrlToUse = (apiVersion === 'v1') ? this.baseUrl : this.baseBetaUrl;
var request = {
method: method,
url: "" + baseUrlToUse + path,
headers: PROJECT_MANAGEMENT_HEADERS,
data: requestData,
timeout: PROJECT_MANAGEMENT_TIMEOUT_MILLIS,
};
return this.httpClient.send(request)
.then(function (response) {
// Send non-JSON responses to the catch() below, where they will be treated as errors.
if (!response.isJson()) {
throw new api_request_1.HttpError(response);
}
return response.data;
})
.catch(function (err) {
if (err instanceof api_request_1.HttpError) {
ProjectManagementRequestHandler.wrapAndRethrowHttpError(err.response.status, err.response.text);
}
throw err;
});
};
return ProjectManagementRequestHandler;
}());
exports.ProjectManagementRequestHandler = ProjectManagementRequestHandler;

View File

@ -0,0 +1,143 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2018 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var utils = require("../utils/index");
var validator = require("../utils/validator");
var android_app_1 = require("./android-app");
var ios_app_1 = require("./ios-app");
var project_management_api_request_1 = require("./project-management-api-request");
/**
* Internals of a Project Management instance.
*/
var ProjectManagementInternals = /** @class */ (function () {
function ProjectManagementInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<void>} An empty Promise that will be resolved when the service is deleted.
*/
ProjectManagementInternals.prototype.delete = function () {
// There are no resources to clean up.
return Promise.resolve();
};
return ProjectManagementInternals;
}());
/**
* ProjectManagement service bound to the provided app.
*/
var ProjectManagement = /** @class */ (function () {
/**
* @param {object} app The app for this ProjectManagement service.
* @constructor
*/
function ProjectManagement(app) {
this.app = app;
this.INTERNAL = new ProjectManagementInternals();
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseProjectManagementError('invalid-argument', 'First argument passed to admin.projectManagement() must be a valid Firebase app '
+ 'instance.');
}
// Assert that a specific project ID was provided within the app.
this.projectId = utils.getProjectId(app);
if (!validator.isNonEmptyString(this.projectId)) {
throw new error_1.FirebaseProjectManagementError('invalid-project-id', 'Failed to determine project ID. Initialize the SDK with service account credentials, or '
+ 'set project ID as an app option. Alternatively, set the GOOGLE_CLOUD_PROJECT '
+ 'environment variable.');
}
this.resourceName = "projects/" + this.projectId;
this.requestHandler = new project_management_api_request_1.ProjectManagementRequestHandler(app);
}
/**
* Lists up to 100 Firebase Android apps associated with this Firebase project.
*/
ProjectManagement.prototype.listAndroidApps = function () {
return this.listPlatformApps('android', 'listAndroidApps()');
};
/**
* Lists up to 100 Firebase iOS apps associated with this Firebase project.
*/
ProjectManagement.prototype.listIosApps = function () {
return this.listPlatformApps('ios', 'listIosApps()');
};
/**
* Returns an AndroidApp object for the given appId. No RPC is made.
*/
ProjectManagement.prototype.androidApp = function (appId) {
return new android_app_1.AndroidApp(appId, this.requestHandler);
};
/**
* Returns an IosApp object for the given appId. No RPC is made.
*/
ProjectManagement.prototype.iosApp = function (appId) {
return new ios_app_1.IosApp(appId, this.requestHandler);
};
/**
* Creates a new Firebase Android app, associated with this Firebase project.
*/
ProjectManagement.prototype.createAndroidApp = function (packageName, displayName) {
var _this = this;
return this.requestHandler.createAndroidApp(this.resourceName, packageName, displayName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'createAndroidApp()\'s responseData must be a non-null object.');
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(responseData.appId), responseData, "\"responseData.appId\" field must be present in createAndroidApp()'s response data.");
return new android_app_1.AndroidApp(responseData.appId, _this.requestHandler);
});
};
/**
* Creates a new Firebase iOS app, associated with this Firebase project.
*/
ProjectManagement.prototype.createIosApp = function (bundleId, displayName) {
var _this = this;
return this.requestHandler.createIosApp(this.resourceName, bundleId, displayName)
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, 'createIosApp()\'s responseData must be a non-null object.');
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(responseData.appId), responseData, "\"responseData.appId\" field must be present in createIosApp()'s response data.");
return new ios_app_1.IosApp(responseData.appId, _this.requestHandler);
});
};
/**
* Lists up to 100 Firebase apps for a specified platform, associated with this Firebase project.
*/
ProjectManagement.prototype.listPlatformApps = function (platform, callerName) {
var _this = this;
var listPromise = (platform === 'android') ?
this.requestHandler.listAndroidApps(this.resourceName)
: this.requestHandler.listIosApps(this.resourceName);
return listPromise
.then(function (responseData) {
project_management_api_request_1.assertServerResponse(validator.isNonNullObject(responseData), responseData, callerName + "'s responseData must be a non-null object.");
if (!responseData.apps) {
return [];
}
project_management_api_request_1.assertServerResponse(validator.isArray(responseData.apps), responseData, "\"apps\" field must be present in the " + callerName + " response data.");
return responseData.apps.map(function (appJson) {
project_management_api_request_1.assertServerResponse(validator.isNonEmptyString(appJson.appId), responseData, "\"apps[].appId\" field must be present in the " + callerName + " response data.");
if (platform === 'android') {
return new android_app_1.AndroidApp(appJson.appId, _this.requestHandler);
}
else {
return new ios_app_1.IosApp(appJson.appId, _this.requestHandler);
}
});
});
};
return ProjectManagement;
}());
exports.ProjectManagement = ProjectManagement;

View File

@ -0,0 +1,128 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var error_1 = require("../utils/error");
var credential_1 = require("../auth/credential");
var validator = require("../utils/validator");
/**
* Internals of a Storage instance.
*/
var StorageInternals = /** @class */ (function () {
function StorageInternals() {
}
/**
* Deletes the service and its associated resources.
*
* @return {Promise<()>} An empty Promise that will be fulfilled when the service is deleted.
*/
StorageInternals.prototype.delete = function () {
// There are no resources to clean up.
return Promise.resolve();
};
return StorageInternals;
}());
/**
* Storage service bound to the provided app.
*/
var Storage = /** @class */ (function () {
/**
* @param {FirebaseApp} app The app for this Storage service.
* @constructor
*/
function Storage(app) {
this.INTERNAL = new StorageInternals();
if (!validator.isNonNullObject(app) || !('options' in app)) {
throw new error_1.FirebaseError({
code: 'storage/invalid-argument',
message: 'First argument passed to admin.storage() must be a valid Firebase app instance.',
});
}
var storage;
try {
storage = require('@google-cloud/storage');
}
catch (err) {
throw new error_1.FirebaseError({
code: 'storage/missing-dependencies',
message: 'Failed to import the Cloud Storage client library for Node.js. '
+ 'Make sure to install the "@google-cloud/storage" npm package. '
+ ("Original error: " + err),
});
}
var cert = app.options.credential.getCertificate();
if (cert != null) {
// cert is available when the SDK has been initialized with a service account JSON file,
// or by setting the GOOGLE_APPLICATION_CREDENTIALS envrionment variable.
this.storageClient = new storage({
projectId: cert.projectId,
credentials: {
private_key: cert.privateKey,
client_email: cert.clientEmail,
},
});
}
else if (app.options.credential instanceof credential_1.ApplicationDefaultCredential) {
// Try to use the Google application default credentials.
this.storageClient = new storage();
}
else {
throw new error_1.FirebaseError({
code: 'storage/invalid-credential',
message: 'Failed to initialize Google Cloud Storage client with the available credential. ' +
'Must initialize the SDK with a certificate credential or application default credentials ' +
'to use Cloud Storage API.',
});
}
this.appInternal = app;
}
/**
* Returns a reference to a Google Cloud Storage bucket. Returned reference can be used to upload
* and download content from Google Cloud Storage.
*
* @param {string=} name Optional name of the bucket to be retrieved. If name is not specified,
* retrieves a reference to the default bucket.
* @return {Bucket} A Bucket object from the @google-cloud/storage library.
*/
Storage.prototype.bucket = function (name) {
var bucketName = (typeof name !== 'undefined')
? name : this.appInternal.options.storageBucket;
if (validator.isNonEmptyString(bucketName)) {
return this.storageClient.bucket(bucketName);
}
throw new error_1.FirebaseError({
code: 'storage/invalid-argument',
message: 'Bucket name not specified or invalid. Specify a valid bucket name via the ' +
'storageBucket option when initializing the app, or specify the bucket name ' +
'explicitly when calling the getBucket() method.',
});
};
Object.defineProperty(Storage.prototype, "app", {
/**
* Returns the app associated with this Storage instance.
*
* @return {FirebaseApp} The app associated with this Storage instance.
*/
get: function () {
return this.appInternal;
},
enumerable: true,
configurable: true
});
return Storage;
}());
exports.Storage = Storage;

View File

@ -0,0 +1,458 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var deep_copy_1 = require("./deep-copy");
var error_1 = require("./error");
var validator = require("./validator");
var http = require("http");
var https = require("https");
var url = require("url");
var events_1 = require("events");
var DefaultHttpResponse = /** @class */ (function () {
/**
* Constructs a new HttpResponse from the given LowLevelResponse.
*/
function DefaultHttpResponse(resp) {
this.status = resp.status;
this.headers = resp.headers;
this.text = resp.data;
try {
this.parsedData = JSON.parse(resp.data);
}
catch (err) {
this.parsedData = undefined;
this.parseError = err;
}
this.request = resp.config.method + " " + resp.config.url;
}
Object.defineProperty(DefaultHttpResponse.prototype, "data", {
get: function () {
if (this.isJson()) {
return this.parsedData;
}
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.UNABLE_TO_PARSE_RESPONSE, "Error while parsing response data: \"" + this.parseError.toString() + "\". Raw server " +
("response: \"" + this.text + "\". Status code: \"" + this.status + "\". Outgoing ") +
("request: \"" + this.request + ".\""));
},
enumerable: true,
configurable: true
});
DefaultHttpResponse.prototype.isJson = function () {
return typeof this.parsedData !== 'undefined';
};
return DefaultHttpResponse;
}());
var HttpError = /** @class */ (function (_super) {
__extends(HttpError, _super);
function HttpError(response) {
var _this = _super.call(this, "Server responded with status " + response.status + ".") || this;
_this.response = response;
// Set the prototype so that instanceof checks will work correctly.
// See: https://github.com/Microsoft/TypeScript/issues/13965
Object.setPrototypeOf(_this, HttpError.prototype);
return _this;
}
return HttpError;
}(Error));
exports.HttpError = HttpError;
var HttpClient = /** @class */ (function () {
function HttpClient() {
}
/**
* Sends an HTTP request to a remote server. If the server responds with a successful response (2xx), the returned
* promise resolves with an HttpResponse. If the server responds with an error (3xx, 4xx, 5xx), the promise rejects
* with an HttpError. In case of all other errors, the promise rejects with a FirebaseAppError. If a request fails
* due to a low-level network error, transparently retries the request once before rejecting the promise.
*
* If the request data is specified as an object, it will be serialized into a JSON string. The application/json
* content-type header will also be automatically set in this case. For all other payload types, the content-type
* header should be explicitly set by the caller. To send a JSON leaf value (e.g. "foo", 5), parse it into JSON,
* and pass as a string or a Buffer along with the appropriate content-type header.
*
* @param {HttpRequest} request HTTP request to be sent.
* @return {Promise<HttpResponse>} A promise that resolves with the response details.
*/
HttpClient.prototype.send = function (config) {
return this.sendWithRetry(config);
};
/**
* Sends an HTTP request, and retries it once in case of low-level network errors.
*/
HttpClient.prototype.sendWithRetry = function (config, attempts) {
var _this = this;
if (attempts === void 0) { attempts = 0; }
return sendRequest(config)
.then(function (resp) {
return new DefaultHttpResponse(resp);
}).catch(function (err) {
var retryCodes = ['ECONNRESET', 'ETIMEDOUT'];
if (retryCodes.indexOf(err.code) !== -1 && attempts === 0) {
return _this.sendWithRetry(config, attempts + 1);
}
if (err.response) {
throw new HttpError(new DefaultHttpResponse(err.response));
}
if (err.code === 'ETIMEDOUT') {
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NETWORK_TIMEOUT, "Error while making request: " + err.message + ".");
}
throw new error_1.FirebaseAppError(error_1.AppErrorCodes.NETWORK_ERROR, "Error while making request: " + err.message + ". Error code: " + err.code);
});
};
return HttpClient;
}());
exports.HttpClient = HttpClient;
/**
* Sends an HTTP request based on the provided configuration. This is a wrapper around the http and https
* packages of Node.js, providing content processing, timeouts and error handling.
*/
function sendRequest(httpRequestConfig) {
var config = deep_copy_1.deepCopy(httpRequestConfig);
return new Promise(function (resolve, reject) {
var data;
var headers = config.headers || {};
var fullUrl = config.url;
if (config.data) {
// GET and HEAD do not support body in request.
if (config.method === 'GET' || config.method === 'HEAD') {
if (!validator.isObject(config.data)) {
return reject(createError(config.method + " requests cannot have a body", config));
}
// Parse URL and append data to query string.
var configUrl = new url.URL(fullUrl);
for (var key in config.data) {
if (config.data.hasOwnProperty(key)) {
configUrl.searchParams.append(key, config.data[key]);
}
}
fullUrl = configUrl.toString();
}
else if (validator.isObject(config.data)) {
data = Buffer.from(JSON.stringify(config.data), 'utf-8');
if (typeof headers['Content-Type'] === 'undefined') {
headers['Content-Type'] = 'application/json;charset=utf-8';
}
}
else if (validator.isString(config.data)) {
data = Buffer.from(config.data, 'utf-8');
}
else if (validator.isBuffer(config.data)) {
data = config.data;
}
else {
return reject(createError('Request data must be a string, a Buffer or a json serializable object', config));
}
// Add Content-Length header if data exists
if (data) {
headers['Content-Length'] = data.length.toString();
}
}
var parsed = url.parse(fullUrl);
var protocol = parsed.protocol || 'https:';
var isHttps = protocol === 'https:';
var port = parsed.port;
if (!port) {
port = isHttps ? '443' : '80';
}
var options = {
hostname: parsed.hostname,
port: port,
path: parsed.path,
method: config.method,
agent: config.httpAgent,
headers: headers,
};
var transport = isHttps ? https : http;
var req = transport.request(options, function (res) {
if (req.aborted) {
return;
}
// Uncompress the response body transparently if required.
var respStream = res;
var encodings = ['gzip', 'compress', 'deflate'];
if (encodings.indexOf(res.headers['content-encoding']) !== -1) {
// Add the unzipper to the body stream processing pipeline.
var zlib = require('zlib');
respStream = respStream.pipe(zlib.createUnzip());
// Remove the content-encoding in order to not confuse downstream operations.
delete res.headers['content-encoding'];
}
var response = {
status: res.statusCode,
headers: res.headers,
request: req,
data: undefined,
config: config,
};
var responseBuffer = [];
respStream.on('data', function (chunk) {
responseBuffer.push(chunk);
});
respStream.on('error', function (err) {
if (req.aborted) {
return;
}
reject(enhanceError(err, config, null, req));
});
respStream.on('end', function () {
var responseData = Buffer.concat(responseBuffer).toString();
response.data = responseData;
finalizeRequest(resolve, reject, response);
});
});
// Handle errors
req.on('error', function (err) {
if (req.aborted) {
return;
}
reject(enhanceError(err, config, null, req));
});
if (config.timeout) {
// Listen to timeouts and throw an error.
req.setTimeout(config.timeout, function () {
req.abort();
reject(createError("timeout of " + config.timeout + "ms exceeded", config, 'ETIMEDOUT', req));
});
}
// Send the request
req.end(data);
});
}
/**
* Creates a new error from the given message, and enhances it with other information available.
*/
function createError(message, config, code, request, response) {
var error = new Error(message);
return enhanceError(error, config, code, request, response);
}
/**
* Enhances the given error by adding more information to it. Specifically, the HttpRequestConfig,
* the underlying request and response will be attached to the error.
*/
function enhanceError(error, config, code, request, response) {
error.config = config;
if (code) {
error.code = code;
}
error.request = request;
error.response = response;
return error;
}
/**
* Finalizes the current request in-flight by either resolving or rejecting the associated promise. In the event
* of an error, adds additional useful information to the returned error.
*/
function finalizeRequest(resolve, reject, response) {
if (response.status >= 200 && response.status < 300) {
resolve(response);
}
else {
reject(createError('Request failed with status code ' + response.status, response.config, null, response.request, response));
}
}
var AuthorizedHttpClient = /** @class */ (function (_super) {
__extends(AuthorizedHttpClient, _super);
function AuthorizedHttpClient(app) {
var _this = _super.call(this) || this;
_this.app = app;
return _this;
}
AuthorizedHttpClient.prototype.send = function (request) {
var _this = this;
return this.app.INTERNAL.getToken().then(function (accessTokenObj) {
var requestCopy = deep_copy_1.deepCopy(request);
requestCopy.headers = requestCopy.headers || {};
var authHeader = 'Authorization';
requestCopy.headers[authHeader] = "Bearer " + accessTokenObj.accessToken;
if (!requestCopy.httpAgent && _this.app.options.httpAgent) {
requestCopy.httpAgent = _this.app.options.httpAgent;
}
return _super.prototype.send.call(_this, requestCopy);
});
};
return AuthorizedHttpClient;
}(HttpClient));
exports.AuthorizedHttpClient = AuthorizedHttpClient;
/**
* Class that defines all the settings for the backend API endpoint.
*
* @param {string} endpoint The Firebase Auth backend endpoint.
* @param {HttpMethod} httpMethod The http method for that endpoint.
* @constructor
*/
var ApiSettings = /** @class */ (function () {
function ApiSettings(endpoint, httpMethod) {
if (httpMethod === void 0) { httpMethod = 'POST'; }
this.endpoint = endpoint;
this.httpMethod = httpMethod;
this.setRequestValidator(null)
.setResponseValidator(null);
}
/** @return {string} The backend API endpoint. */
ApiSettings.prototype.getEndpoint = function () {
return this.endpoint;
};
/** @return {HttpMethod} The request HTTP method. */
ApiSettings.prototype.getHttpMethod = function () {
return this.httpMethod;
};
/**
* @param {ApiCallbackFunction} requestValidator The request validator.
* @return {ApiSettings} The current API settings instance.
*/
ApiSettings.prototype.setRequestValidator = function (requestValidator) {
var nullFunction = function (_) { return undefined; };
this.requestValidator = requestValidator || nullFunction;
return this;
};
/** @return {ApiCallbackFunction} The request validator. */
ApiSettings.prototype.getRequestValidator = function () {
return this.requestValidator;
};
/**
* @param {ApiCallbackFunction} responseValidator The response validator.
* @return {ApiSettings} The current API settings instance.
*/
ApiSettings.prototype.setResponseValidator = function (responseValidator) {
var nullFunction = function (_) { return undefined; };
this.responseValidator = responseValidator || nullFunction;
return this;
};
/** @return {ApiCallbackFunction} The response validator. */
ApiSettings.prototype.getResponseValidator = function () {
return this.responseValidator;
};
return ApiSettings;
}());
exports.ApiSettings = ApiSettings;
/**
* Class used for polling an endpoint with exponential backoff.
*
* Example usage:
* ```
* const poller = new ExponentialBackoffPoller();
* poller
* .poll(() => {
* return myRequestToPoll()
* .then((responseData: any) => {
* if (!isValid(responseData)) {
* // Continue polling.
* return null;
* }
*
* // Polling complete. Resolve promise with final response data.
* return responseData;
* });
* })
* .then((responseData: any) => {
* console.log(`Final response: ${responseData}`);
* });
* ```
*/
var ExponentialBackoffPoller = /** @class */ (function (_super) {
__extends(ExponentialBackoffPoller, _super);
function ExponentialBackoffPoller(initialPollingDelayMillis, maxPollingDelayMillis, masterTimeoutMillis) {
if (initialPollingDelayMillis === void 0) { initialPollingDelayMillis = 1000; }
if (maxPollingDelayMillis === void 0) { maxPollingDelayMillis = 10000; }
if (masterTimeoutMillis === void 0) { masterTimeoutMillis = 60000; }
var _this = _super.call(this) || this;
_this.initialPollingDelayMillis = initialPollingDelayMillis;
_this.maxPollingDelayMillis = maxPollingDelayMillis;
_this.masterTimeoutMillis = masterTimeoutMillis;
_this.numTries = 0;
_this.completed = false;
return _this;
}
/**
* Poll the provided callback with exponential backoff.
*
* @param {() => Promise<object>} callback The callback to be called for each poll. If the
* callback resolves to a falsey value, polling will continue. Otherwise, the truthy
* resolution will be used to resolve the promise returned by this method.
* @return {Promise<object>} A Promise which resolves to the truthy value returned by the provided
* callback when polling is complete.
*/
ExponentialBackoffPoller.prototype.poll = function (callback) {
var _this = this;
if (this.pollCallback) {
throw new Error('poll() can only be called once per instance of ExponentialBackoffPoller');
}
this.pollCallback = callback;
this.on('poll', this.repoll);
this.masterTimer = setTimeout(function () {
if (_this.completed) {
return;
}
_this.markCompleted();
_this.reject(new Error('ExponentialBackoffPoller deadline exceeded - Master timeout reached'));
}, this.masterTimeoutMillis);
return new Promise(function (resolve, reject) {
_this.resolve = resolve;
_this.reject = reject;
_this.repoll();
});
};
ExponentialBackoffPoller.prototype.repoll = function () {
var _this = this;
this.pollCallback()
.then(function (result) {
if (_this.completed) {
return;
}
if (!result) {
_this.repollTimer =
setTimeout(function () { return _this.emit('poll'); }, _this.getPollingDelayMillis());
_this.numTries++;
return;
}
_this.markCompleted();
_this.resolve(result);
})
.catch(function (err) {
if (_this.completed) {
return;
}
_this.markCompleted();
_this.reject(err);
});
};
ExponentialBackoffPoller.prototype.getPollingDelayMillis = function () {
var increasedPollingDelay = Math.pow(2, this.numTries) * this.initialPollingDelayMillis;
return Math.min(increasedPollingDelay, this.maxPollingDelayMillis);
};
ExponentialBackoffPoller.prototype.markCompleted = function () {
this.completed = true;
if (this.masterTimer) {
clearTimeout(this.masterTimer);
}
if (this.repollTimer) {
clearTimeout(this.repollTimer);
}
};
return ExponentialBackoffPoller;
}(events_1.EventEmitter));
exports.ExponentialBackoffPoller = ExponentialBackoffPoller;

View File

@ -0,0 +1,75 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Returns a deep copy of an object or array.
*
* @param {object|array} value The object or array to deep copy.
* @return {object|array} A deep copy of the provided object or array.
*/
function deepCopy(value) {
return deepExtend(undefined, value);
}
exports.deepCopy = deepCopy;
/**
* Copies properties from source to target (recursively allows extension of objects and arrays).
* Scalar values in the target are over-written. If target is undefined, an object of the
* appropriate type will be created (and returned).
*
* We recursively copy all child properties of plain objects in the source - so that namespace-like
* objects are merged.
*
* Note that the target can be a function, in which case the properties in the source object are
* copied onto it as static properties of the function.
*
* @param {any} target The value which is being extended.
* @param {any} source The value whose properties are extending the target.
* @return {any} The target value.
*/
function deepExtend(target, source) {
if (!(source instanceof Object)) {
return source;
}
switch (source.constructor) {
case Date:
// Treat Dates like scalars; if the target date object had any child
// properties - they will be lost!
var dateValue = source;
return new Date(dateValue.getTime());
case Object:
if (target === undefined) {
target = {};
}
break;
case Array:
// Always copy the array source and overwrite the target.
target = [];
break;
default:
// Not a plain Object - treat it as a scalar.
return source;
}
for (var prop in source) {
if (!source.hasOwnProperty(prop)) {
continue;
}
target[prop] = deepExtend(target[prop], source[prop]);
}
return target;
}
exports.deepExtend = deepExtend;

View File

@ -0,0 +1,792 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var deep_copy_1 = require("../utils/deep-copy");
/**
* Firebase error code structure. This extends Error.
*
* @param {ErrorInfo} errorInfo The error information (code and message).
* @constructor
*/
var FirebaseError = /** @class */ (function (_super) {
__extends(FirebaseError, _super);
function FirebaseError(errorInfo) {
var _this = _super.call(this, errorInfo.message) || this;
_this.errorInfo = errorInfo;
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
_this.__proto__ = FirebaseError.prototype;
return _this;
}
Object.defineProperty(FirebaseError.prototype, "code", {
/** @return {string} The error code. */
get: function () {
return this.errorInfo.code;
},
enumerable: true,
configurable: true
});
Object.defineProperty(FirebaseError.prototype, "message", {
/** @return {string} The error message. */
get: function () {
return this.errorInfo.message;
},
enumerable: true,
configurable: true
});
/** @return {object} The object representation of the error. */
FirebaseError.prototype.toJSON = function () {
return {
code: this.code,
message: this.message,
};
};
return FirebaseError;
}(Error));
exports.FirebaseError = FirebaseError;
/**
* A FirebaseError with a prefix in front of the error code.
*
* @param {string} codePrefix The prefix to apply to the error code.
* @param {string} code The error code.
* @param {string} message The error message.
* @constructor
*/
var PrefixedFirebaseError = /** @class */ (function (_super) {
__extends(PrefixedFirebaseError, _super);
function PrefixedFirebaseError(codePrefix, code, message) {
var _this = _super.call(this, {
code: codePrefix + "/" + code,
message: message,
}) || this;
_this.codePrefix = codePrefix;
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
_this.__proto__ = PrefixedFirebaseError.prototype;
return _this;
}
/**
* Allows the error type to be checked without needing to know implementation details
* of the code prefixing.
*
* @param {string} code The non-prefixed error code to test against.
* @return {boolean} True if the code matches, false otherwise.
*/
PrefixedFirebaseError.prototype.hasCode = function (code) {
return this.codePrefix + "/" + code === this.code;
};
return PrefixedFirebaseError;
}(FirebaseError));
/**
* Firebase App error code structure. This extends PrefixedFirebaseError.
*
* @param {string} code The error code.
* @param {string} message The error message.
* @constructor
*/
var FirebaseAppError = /** @class */ (function (_super) {
__extends(FirebaseAppError, _super);
function FirebaseAppError(code, message) {
var _this = _super.call(this, 'app', code, message) || this;
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
_this.__proto__ = FirebaseAppError.prototype;
return _this;
}
return FirebaseAppError;
}(PrefixedFirebaseError));
exports.FirebaseAppError = FirebaseAppError;
/**
* Firebase Auth error code structure. This extends PrefixedFirebaseError.
*
* @param {ErrorInfo} info The error code info.
* @param {string} [message] The error message. This will override the default
* message if provided.
* @constructor
*/
var FirebaseAuthError = /** @class */ (function (_super) {
__extends(FirebaseAuthError, _super);
function FirebaseAuthError(info, message) {
var _this =
// Override default message if custom message provided.
_super.call(this, 'auth', info.code, message || info.message) || this;
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
_this.__proto__ = FirebaseAuthError.prototype;
return _this;
}
/**
* Creates the developer-facing error corresponding to the backend error code.
*
* @param {string} serverErrorCode The server error code.
* @param {string} [message] The error message. The default message is used
* if not provided.
* @param {object} [rawServerResponse] The error's raw server response.
* @return {FirebaseAuthError} The corresponding developer-facing error.
*/
FirebaseAuthError.fromServerError = function (serverErrorCode, message, rawServerResponse) {
// If not found, default to internal error.
var clientCodeKey = AUTH_SERVER_TO_CLIENT_CODE[serverErrorCode] || 'INTERNAL_ERROR';
var error = deep_copy_1.deepCopy(AuthClientErrorCode[clientCodeKey]);
error.message = message || error.message;
if (clientCodeKey === 'INTERNAL_ERROR' && typeof rawServerResponse !== 'undefined') {
try {
error.message += " Raw server response: \"" + JSON.stringify(rawServerResponse) + "\"";
}
catch (e) {
// Ignore JSON parsing error.
}
}
return new FirebaseAuthError(error);
};
return FirebaseAuthError;
}(PrefixedFirebaseError));
exports.FirebaseAuthError = FirebaseAuthError;
/**
* Firebase Database error code structure. This extends FirebaseError.
*
* @param {ErrorInfo} info The error code info.
* @param {string} [message] The error message. This will override the default
* message if provided.
* @constructor
*/
var FirebaseDatabaseError = /** @class */ (function (_super) {
__extends(FirebaseDatabaseError, _super);
function FirebaseDatabaseError(info, message) {
// Override default message if custom message provided.
return _super.call(this, { code: 'database/' + info.code, message: message || info.message }) || this;
}
return FirebaseDatabaseError;
}(FirebaseError));
exports.FirebaseDatabaseError = FirebaseDatabaseError;
/**
* Firebase Firestore error code structure. This extends FirebaseError.
*
* @param {ErrorInfo} info The error code info.
* @param {string} [message] The error message. This will override the default
* message if provided.
* @constructor
*/
var FirebaseFirestoreError = /** @class */ (function (_super) {
__extends(FirebaseFirestoreError, _super);
function FirebaseFirestoreError(info, message) {
// Override default message if custom message provided.
return _super.call(this, { code: 'firestore/' + info.code, message: message || info.message }) || this;
}
return FirebaseFirestoreError;
}(FirebaseError));
exports.FirebaseFirestoreError = FirebaseFirestoreError;
/**
* Firebase instance ID error code structure. This extends FirebaseError.
*
* @param {ErrorInfo} info The error code info.
* @param {string} [message] The error message. This will override the default
* message if provided.
* @constructor
*/
var FirebaseInstanceIdError = /** @class */ (function (_super) {
__extends(FirebaseInstanceIdError, _super);
function FirebaseInstanceIdError(info, message) {
// Override default message if custom message provided.
return _super.call(this, { code: 'instance-id/' + info.code, message: message || info.message }) || this;
}
return FirebaseInstanceIdError;
}(FirebaseError));
exports.FirebaseInstanceIdError = FirebaseInstanceIdError;
/**
* Firebase Messaging error code structure. This extends PrefixedFirebaseError.
*
* @param {ErrorInfo} info The error code info.
* @param {string} [message] The error message. This will override the default message if provided.
* @constructor
*/
var FirebaseMessagingError = /** @class */ (function (_super) {
__extends(FirebaseMessagingError, _super);
function FirebaseMessagingError(info, message) {
var _this =
// Override default message if custom message provided.
_super.call(this, 'messaging', info.code, message || info.message) || this;
/* tslint:disable:max-line-length */
// Set the prototype explicitly. See the following link for more details:
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
/* tslint:enable:max-line-length */
_this.__proto__ = FirebaseMessagingError.prototype;
return _this;
}
/**
* Creates the developer-facing error corresponding to the backend error code.
*
* @param {string} serverErrorCode The server error code.
* @param {string} [message] The error message. The default message is used
* if not provided.
* @param {object} [rawServerResponse] The error's raw server response.
* @return {FirebaseMessagingError} The corresponding developer-facing error.
*/
FirebaseMessagingError.fromServerError = function (serverErrorCode, message, rawServerResponse) {
// If not found, default to unknown error.
var clientCodeKey = MESSAGING_SERVER_TO_CLIENT_CODE[serverErrorCode] || 'UNKNOWN_ERROR';
var error = deep_copy_1.deepCopy(MessagingClientErrorCode[clientCodeKey]);
error.message = message || error.message;
if (clientCodeKey === 'UNKNOWN_ERROR' && typeof rawServerResponse !== 'undefined') {
try {
error.message += " Raw server response: \"" + JSON.stringify(rawServerResponse) + "\"";
}
catch (e) {
// Ignore JSON parsing error.
}
}
return new FirebaseMessagingError(error);
};
FirebaseMessagingError.fromTopicManagementServerError = function (serverErrorCode, message, rawServerResponse) {
// If not found, default to unknown error.
var clientCodeKey = TOPIC_MGT_SERVER_TO_CLIENT_CODE[serverErrorCode] || 'UNKNOWN_ERROR';
var error = deep_copy_1.deepCopy(MessagingClientErrorCode[clientCodeKey]);
error.message = message || error.message;
if (clientCodeKey === 'UNKNOWN_ERROR' && typeof rawServerResponse !== 'undefined') {
try {
error.message += " Raw server response: \"" + JSON.stringify(rawServerResponse) + "\"";
}
catch (e) {
// Ignore JSON parsing error.
}
}
return new FirebaseMessagingError(error);
};
return FirebaseMessagingError;
}(PrefixedFirebaseError));
exports.FirebaseMessagingError = FirebaseMessagingError;
/**
* Firebase project management error code structure. This extends PrefixedFirebaseError.
*
* @param {ProjectManagementErrorCode} code The error code.
* @param {string} message The error message.
* @constructor
*/
var FirebaseProjectManagementError = /** @class */ (function (_super) {
__extends(FirebaseProjectManagementError, _super);
function FirebaseProjectManagementError(code, message) {
return _super.call(this, 'project-management', code, message) || this;
}
return FirebaseProjectManagementError;
}(PrefixedFirebaseError));
exports.FirebaseProjectManagementError = FirebaseProjectManagementError;
/**
* App client error codes and their default messages.
*/
var AppErrorCodes = /** @class */ (function () {
function AppErrorCodes() {
}
AppErrorCodes.APP_DELETED = 'app-deleted';
AppErrorCodes.DUPLICATE_APP = 'duplicate-app';
AppErrorCodes.INTERNAL_ERROR = 'internal-error';
AppErrorCodes.INVALID_APP_NAME = 'invalid-app-name';
AppErrorCodes.INVALID_APP_OPTIONS = 'invalid-app-options';
AppErrorCodes.INVALID_CREDENTIAL = 'invalid-credential';
AppErrorCodes.NETWORK_ERROR = 'network-error';
AppErrorCodes.NETWORK_TIMEOUT = 'network-timeout';
AppErrorCodes.NO_APP = 'no-app';
AppErrorCodes.UNABLE_TO_PARSE_RESPONSE = 'unable-to-parse-response';
return AppErrorCodes;
}());
exports.AppErrorCodes = AppErrorCodes;
/**
* Auth client error codes and their default messages.
*/
var AuthClientErrorCode = /** @class */ (function () {
function AuthClientErrorCode() {
}
AuthClientErrorCode.CLAIMS_TOO_LARGE = {
code: 'claims-too-large',
message: 'Developer claims maximum payload size exceeded.',
};
AuthClientErrorCode.ID_TOKEN_EXPIRED = {
code: 'id-token-expired',
message: 'The provided Firebase ID token is expired.',
};
AuthClientErrorCode.INVALID_ARGUMENT = {
code: 'argument-error',
message: 'Invalid argument provided.',
};
AuthClientErrorCode.EMAIL_ALREADY_EXISTS = {
code: 'email-already-exists',
message: 'The email address is already in use by another account.',
};
AuthClientErrorCode.FORBIDDEN_CLAIM = {
code: 'reserved-claim',
message: 'The specified developer claim is reserved and cannot be specified.',
};
AuthClientErrorCode.INVALID_ID_TOKEN = {
code: 'invalid-id-token',
message: 'The provided ID token is not a valid Firebase ID token.',
};
AuthClientErrorCode.ID_TOKEN_REVOKED = {
code: 'id-token-revoked',
message: 'The Firebase ID token has been revoked.',
};
AuthClientErrorCode.INTERNAL_ERROR = {
code: 'internal-error',
message: 'An internal error has occurred.',
};
AuthClientErrorCode.INVALID_CLAIMS = {
code: 'invalid-claims',
message: 'The provided custom claim attributes are invalid.',
};
AuthClientErrorCode.INVALID_CONTINUE_URI = {
code: 'invalid-continue-uri',
message: 'The continue URL must be a valid URL string.',
};
AuthClientErrorCode.INVALID_CREATION_TIME = {
code: 'invalid-creation-time',
message: 'The creation time must be a valid UTC date string.',
};
AuthClientErrorCode.INVALID_CREDENTIAL = {
code: 'invalid-credential',
message: 'Invalid credential object provided.',
};
AuthClientErrorCode.INVALID_DISABLED_FIELD = {
code: 'invalid-disabled-field',
message: 'The disabled field must be a boolean.',
};
AuthClientErrorCode.INVALID_DISPLAY_NAME = {
code: 'invalid-display-name',
message: 'The displayName field must be a valid string.',
};
AuthClientErrorCode.INVALID_DYNAMIC_LINK_DOMAIN = {
code: 'invalid-dynamic-link-domain',
message: 'The provided dynamic link domain is not configured or authorized ' +
'for the current project.',
};
AuthClientErrorCode.INVALID_EMAIL_VERIFIED = {
code: 'invalid-email-verified',
message: 'The emailVerified field must be a boolean.',
};
AuthClientErrorCode.INVALID_EMAIL = {
code: 'invalid-email',
message: 'The email address is improperly formatted.',
};
AuthClientErrorCode.INVALID_HASH_ALGORITHM = {
code: 'invalid-hash-algorithm',
message: 'The hash algorithm must match one of the strings in the list of ' +
'supported algorithms.',
};
AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE = {
code: 'invalid-hash-block-size',
message: 'The hash block size must be a valid number.',
};
AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH = {
code: 'invalid-hash-derived-key-length',
message: 'The hash derived key length must be a valid number.',
};
AuthClientErrorCode.INVALID_HASH_KEY = {
code: 'invalid-hash-key',
message: 'The hash key must a valid byte buffer.',
};
AuthClientErrorCode.INVALID_HASH_MEMORY_COST = {
code: 'invalid-hash-memory-cost',
message: 'The hash memory cost must be a valid number.',
};
AuthClientErrorCode.INVALID_HASH_PARALLELIZATION = {
code: 'invalid-hash-parallelization',
message: 'The hash parallelization must be a valid number.',
};
AuthClientErrorCode.INVALID_HASH_ROUNDS = {
code: 'invalid-hash-rounds',
message: 'The hash rounds must be a valid number.',
};
AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR = {
code: 'invalid-hash-salt-separator',
message: 'The hashing algorithm salt separator field must be a valid byte buffer.',
};
AuthClientErrorCode.INVALID_LAST_SIGN_IN_TIME = {
code: 'invalid-last-sign-in-time',
message: 'The last sign-in time must be a valid UTC date string.',
};
AuthClientErrorCode.INVALID_PAGE_TOKEN = {
code: 'invalid-page-token',
message: 'The page token must be a valid non-empty string.',
};
AuthClientErrorCode.INVALID_PASSWORD = {
code: 'invalid-password',
message: 'The password must be a string with at least 6 characters.',
};
AuthClientErrorCode.INVALID_PASSWORD_HASH = {
code: 'invalid-password-hash',
message: 'The password hash must be a valid byte buffer.',
};
AuthClientErrorCode.INVALID_PASSWORD_SALT = {
code: 'invalid-password-salt',
message: 'The password salt must be a valid byte buffer.',
};
AuthClientErrorCode.INVALID_PHONE_NUMBER = {
code: 'invalid-phone-number',
message: 'The phone number must be a non-empty E.164 standard compliant identifier ' +
'string.',
};
AuthClientErrorCode.INVALID_PHOTO_URL = {
code: 'invalid-photo-url',
message: 'The photoURL field must be a valid URL.',
};
AuthClientErrorCode.INVALID_PROVIDER_DATA = {
code: 'invalid-provider-data',
message: 'The providerData must be a valid array of UserInfo objects.',
};
AuthClientErrorCode.INVALID_PROVIDER_ID = {
code: 'invalid-provider-id',
message: 'The providerId must be a valid supported provider identifier string.',
};
AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION = {
code: 'invalid-session-cookie-duration',
message: 'The session cookie duration must be a valid number in milliseconds ' +
'between 5 minutes and 2 weeks.',
};
AuthClientErrorCode.INVALID_UID = {
code: 'invalid-uid',
message: 'The uid must be a non-empty string with at most 128 characters.',
};
AuthClientErrorCode.INVALID_USER_IMPORT = {
code: 'invalid-user-import',
message: 'The user record to import is invalid.',
};
AuthClientErrorCode.INVALID_TOKENS_VALID_AFTER_TIME = {
code: 'invalid-tokens-valid-after-time',
message: 'The tokensValidAfterTime must be a valid UTC number in seconds.',
};
AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME = {
code: 'missing-android-pkg-name',
message: 'An Android Package Name must be provided if the Android App is ' +
'required to be installed.',
};
AuthClientErrorCode.MISSING_CONTINUE_URI = {
code: 'missing-continue-uri',
message: 'A valid continue URL must be provided in the request.',
};
AuthClientErrorCode.MISSING_IOS_BUNDLE_ID = {
code: 'missing-ios-bundle-id',
message: 'The request is missing an iOS Bundle ID.',
};
AuthClientErrorCode.MISSING_HASH_ALGORITHM = {
code: 'missing-hash-algorithm',
message: 'Importing users with password hashes requires that the hashing ' +
'algorithm and its parameters be provided.',
};
AuthClientErrorCode.MAXIMUM_USER_COUNT_EXCEEDED = {
code: 'maximum-user-count-exceeded',
message: 'The maximum allowed number of users to import has been exceeded.',
};
AuthClientErrorCode.MISSING_UID = {
code: 'missing-uid',
message: 'A uid identifier is required for the current operation.',
};
AuthClientErrorCode.OPERATION_NOT_ALLOWED = {
code: 'operation-not-allowed',
message: 'The given sign-in provider is disabled for this Firebase project. ' +
'Enable it in the Firebase console, under the sign-in method tab of the ' +
'Auth section.',
};
AuthClientErrorCode.PHONE_NUMBER_ALREADY_EXISTS = {
code: 'phone-number-already-exists',
message: 'The user with the provided phone number already exists.',
};
AuthClientErrorCode.PROJECT_NOT_FOUND = {
code: 'project-not-found',
message: 'No Firebase project was found for the provided credential.',
};
AuthClientErrorCode.INSUFFICIENT_PERMISSION = {
code: 'insufficient-permission',
message: 'Credential implementation provided to initializeApp() via the "credential" property ' +
'has insufficient permission to access the requested resource. See ' +
'https://firebase.google.com/docs/admin/setup for details on how to authenticate this SDK ' +
'with appropriate permissions.',
};
AuthClientErrorCode.SESSION_COOKIE_REVOKED = {
code: 'session-cookie-revoked',
message: 'The Firebase session cookie has been revoked.',
};
AuthClientErrorCode.UID_ALREADY_EXISTS = {
code: 'uid-already-exists',
message: 'The user with the provided uid already exists.',
};
AuthClientErrorCode.UNAUTHORIZED_DOMAIN = {
code: 'unauthorized-continue-uri',
message: 'The domain of the continue URL is not whitelisted. Whitelist the domain in the ' +
'Firebase console.',
};
AuthClientErrorCode.USER_NOT_FOUND = {
code: 'user-not-found',
message: 'There is no user record corresponding to the provided identifier.',
};
return AuthClientErrorCode;
}());
exports.AuthClientErrorCode = AuthClientErrorCode;
/**
* Messaging client error codes and their default messages.
*/
var MessagingClientErrorCode = /** @class */ (function () {
function MessagingClientErrorCode() {
}
MessagingClientErrorCode.INVALID_ARGUMENT = {
code: 'invalid-argument',
message: 'Invalid argument provided.',
};
MessagingClientErrorCode.INVALID_RECIPIENT = {
code: 'invalid-recipient',
message: 'Invalid message recipient provided.',
};
MessagingClientErrorCode.INVALID_PAYLOAD = {
code: 'invalid-payload',
message: 'Invalid message payload provided.',
};
MessagingClientErrorCode.INVALID_DATA_PAYLOAD_KEY = {
code: 'invalid-data-payload-key',
message: 'The data message payload contains an invalid key. See the reference documentation ' +
'for the DataMessagePayload type for restricted keys.',
};
MessagingClientErrorCode.PAYLOAD_SIZE_LIMIT_EXCEEDED = {
code: 'payload-size-limit-exceeded',
message: 'The provided message payload exceeds the FCM size limits. See the error documentation ' +
'for more details.',
};
MessagingClientErrorCode.INVALID_OPTIONS = {
code: 'invalid-options',
message: 'Invalid message options provided.',
};
MessagingClientErrorCode.INVALID_REGISTRATION_TOKEN = {
code: 'invalid-registration-token',
message: 'Invalid registration token provided. Make sure it matches the registration token ' +
'the client app receives from registering with FCM.',
};
MessagingClientErrorCode.REGISTRATION_TOKEN_NOT_REGISTERED = {
code: 'registration-token-not-registered',
message: 'The provided registration token is not registered. A previously valid registration ' +
'token can be unregistered for a variety of reasons. See the error documentation for more ' +
'details. Remove this registration token and stop using it to send messages.',
};
MessagingClientErrorCode.MISMATCHED_CREDENTIAL = {
code: 'mismatched-credential',
message: 'The credential used to authenticate this SDK does not have permission to send ' +
'messages to the device corresponding to the provided registration token. Make sure the ' +
'credential and registration token both belong to the same Firebase project.',
};
MessagingClientErrorCode.INVALID_PACKAGE_NAME = {
code: 'invalid-package-name',
message: 'The message was addressed to a registration token whose package name does not match ' +
'the provided "restrictedPackageName" option.',
};
MessagingClientErrorCode.DEVICE_MESSAGE_RATE_EXCEEDED = {
code: 'device-message-rate-exceeded',
message: 'The rate of messages to a particular device is too high. Reduce the number of ' +
'messages sent to this device and do not immediately retry sending to this device.',
};
MessagingClientErrorCode.TOPICS_MESSAGE_RATE_EXCEEDED = {
code: 'topics-message-rate-exceeded',
message: 'The rate of messages to subscribers to a particular topic is too high. Reduce the ' +
'number of messages sent for this topic, and do not immediately retry sending to this topic.',
};
MessagingClientErrorCode.MESSAGE_RATE_EXCEEDED = {
code: 'message-rate-exceeded',
message: 'Sending limit exceeded for the message target.',
};
MessagingClientErrorCode.INVALID_APNS_CREDENTIALS = {
code: 'invalid-apns-credentials',
message: 'A message targeted to an iOS device could not be sent because the required APNs ' +
'SSL certificate was not uploaded or has expired. Check the validity of your development ' +
'and production certificates.',
};
MessagingClientErrorCode.TOO_MANY_TOPICS = {
code: 'too-many-topics',
message: 'The maximum number of topics the provided registration token can be subscribed to ' +
'has been exceeded.',
};
MessagingClientErrorCode.AUTHENTICATION_ERROR = {
code: 'authentication-error',
message: 'An error occurred when trying to authenticate to the FCM servers. Make sure the ' +
'credential used to authenticate this SDK has the proper permissions. See ' +
'https://firebase.google.com/docs/admin/setup for setup instructions.',
};
MessagingClientErrorCode.SERVER_UNAVAILABLE = {
code: 'server-unavailable',
message: 'The FCM server could not process the request in time. See the error documentation ' +
'for more details.',
};
MessagingClientErrorCode.INTERNAL_ERROR = {
code: 'internal-error',
message: 'An internal error has occurred. Please retry the request.',
};
MessagingClientErrorCode.UNKNOWN_ERROR = {
code: 'unknown-error',
message: 'An unknown server error was returned.',
};
return MessagingClientErrorCode;
}());
exports.MessagingClientErrorCode = MessagingClientErrorCode;
var InstanceIdClientErrorCode = /** @class */ (function () {
function InstanceIdClientErrorCode() {
}
InstanceIdClientErrorCode.INVALID_ARGUMENT = {
code: 'invalid-argument',
message: 'Invalid argument provided.',
};
InstanceIdClientErrorCode.INVALID_PROJECT_ID = {
code: 'invalid-project-id',
message: 'Invalid project ID provided.',
};
InstanceIdClientErrorCode.INVALID_INSTANCE_ID = {
code: 'invalid-instance-id',
message: 'Invalid instance ID provided.',
};
InstanceIdClientErrorCode.API_ERROR = {
code: 'api-error',
message: 'Instance ID API call failed.',
};
return InstanceIdClientErrorCode;
}());
exports.InstanceIdClientErrorCode = InstanceIdClientErrorCode;
/** @const {ServerToClientCode} Auth server to client enum error codes. */
var AUTH_SERVER_TO_CLIENT_CODE = {
// Claims payload is too large.
CLAIMS_TOO_LARGE: 'CLAIMS_TOO_LARGE',
// Project not found.
CONFIGURATION_NOT_FOUND: 'PROJECT_NOT_FOUND',
// Provided credential has insufficient permissions.
INSUFFICIENT_PERMISSION: 'INSUFFICIENT_PERMISSION',
// ActionCodeSettings missing continue URL.
INVALID_CONTINUE_URI: 'INVALID_CONTINUE_URI',
// Dynamic link domain in provided ActionCodeSettings is not authorized.
INVALID_DYNAMIC_LINK_DOMAIN: 'INVALID_DYNAMIC_LINK_DOMAIN',
// uploadAccount provides an email that already exists.
DUPLICATE_EMAIL: 'EMAIL_ALREADY_EXISTS',
// uploadAccount provides a localId that already exists.
DUPLICATE_LOCAL_ID: 'UID_ALREADY_EXISTS',
// setAccountInfo email already exists.
EMAIL_EXISTS: 'EMAIL_ALREADY_EXISTS',
// Reserved claim name.
FORBIDDEN_CLAIM: 'FORBIDDEN_CLAIM',
// Invalid claims provided.
INVALID_CLAIMS: 'INVALID_CLAIMS',
// Invalid session cookie duration.
INVALID_DURATION: 'INVALID_SESSION_COOKIE_DURATION',
// Invalid email provided.
INVALID_EMAIL: 'INVALID_EMAIL',
// Invalid ID token provided.
INVALID_ID_TOKEN: 'INVALID_ID_TOKEN',
// Invalid page token.
INVALID_PAGE_SELECTION: 'INVALID_PAGE_TOKEN',
// Invalid phone number.
INVALID_PHONE_NUMBER: 'INVALID_PHONE_NUMBER',
// Invalid service account.
INVALID_SERVICE_ACCOUNT: 'INVALID_SERVICE_ACCOUNT',
// Missing Android package name.
MISSING_ANDROID_PACKAGE_NAME: 'MISSING_ANDROID_PACKAGE_NAME',
// Missing iOS bundle ID.
MISSING_IOS_BUNDLE_ID: 'MISSING_IOS_BUNDLE_ID',
// No localId provided (deleteAccount missing localId).
MISSING_LOCAL_ID: 'MISSING_UID',
// Empty user list in uploadAccount.
MISSING_USER_ACCOUNT: 'MISSING_UID',
// Password auth disabled in console.
OPERATION_NOT_ALLOWED: 'OPERATION_NOT_ALLOWED',
// Provided credential has insufficient permissions.
PERMISSION_DENIED: 'INSUFFICIENT_PERMISSION',
// Phone number already exists.
PHONE_NUMBER_EXISTS: 'PHONE_NUMBER_ALREADY_EXISTS',
// Project not found.
PROJECT_NOT_FOUND: 'PROJECT_NOT_FOUND',
// Token expired error.
TOKEN_EXPIRED: 'ID_TOKEN_EXPIRED',
// Continue URL provided in ActionCodeSettings has a domain that is not whitelisted.
UNAUTHORIZED_DOMAIN: 'UNAUTHORIZED_DOMAIN',
// User on which action is to be performed is not found.
USER_NOT_FOUND: 'USER_NOT_FOUND',
// Password provided is too weak.
WEAK_PASSWORD: 'INVALID_PASSWORD',
};
/** @const {ServerToClientCode} Messaging server to client enum error codes. */
var MESSAGING_SERVER_TO_CLIENT_CODE = {
/* GENERIC ERRORS */
// Generic invalid message parameter provided.
InvalidParameters: 'INVALID_ARGUMENT',
// Mismatched sender ID.
MismatchSenderId: 'MISMATCHED_CREDENTIAL',
// FCM server unavailable.
Unavailable: 'SERVER_UNAVAILABLE',
// FCM server internal error.
InternalServerError: 'INTERNAL_ERROR',
/* SEND ERRORS */
// Invalid registration token format.
InvalidRegistration: 'INVALID_REGISTRATION_TOKEN',
// Registration token is not registered.
NotRegistered: 'REGISTRATION_TOKEN_NOT_REGISTERED',
// Registration token does not match restricted package name.
InvalidPackageName: 'INVALID_PACKAGE_NAME',
// Message payload size limit exceeded.
MessageTooBig: 'PAYLOAD_SIZE_LIMIT_EXCEEDED',
// Invalid key in the data message payload.
InvalidDataKey: 'INVALID_DATA_PAYLOAD_KEY',
// Invalid time to live option.
InvalidTtl: 'INVALID_OPTIONS',
// Device message rate exceeded.
DeviceMessageRateExceeded: 'DEVICE_MESSAGE_RATE_EXCEEDED',
// Topics message rate exceeded.
TopicsMessageRateExceeded: 'TOPICS_MESSAGE_RATE_EXCEEDED',
// Invalid APNs credentials.
InvalidApnsCredential: 'INVALID_APNS_CREDENTIALS',
/* FCM v1 canonical error codes */
NOT_FOUND: 'REGISTRATION_TOKEN_NOT_REGISTERED',
PERMISSION_DENIED: 'MISMATCHED_CREDENTIAL',
RESOURCE_EXHAUSTED: 'MESSAGE_RATE_EXCEEDED',
UNAUTHENTICATED: 'INVALID_APNS_CREDENTIALS',
/* FCM v1 new error codes */
APNS_AUTH_ERROR: 'INVALID_APNS_CREDENTIALS',
INTERNAL: 'INTERNAL_ERROR',
INVALID_ARGUMENT: 'INVALID_ARGUMENT',
QUOTA_EXCEEDED: 'MESSAGE_RATE_EXCEEDED',
SENDER_ID_MISMATCH: 'MISMATCHED_CREDENTIAL',
UNAVAILABLE: 'SERVER_UNAVAILABLE',
UNREGISTERED: 'REGISTRATION_TOKEN_NOT_REGISTERED',
UNSPECIFIED_ERROR: 'UNKNOWN_ERROR',
};
/** @const {ServerToClientCode} Topic management (IID) server to client enum error codes. */
var TOPIC_MGT_SERVER_TO_CLIENT_CODE = {
/* TOPIC SUBSCRIPTION MANAGEMENT ERRORS */
NOT_FOUND: 'REGISTRATION_TOKEN_NOT_REGISTERED',
INVALID_ARGUMENT: 'INVALID_REGISTRATION_TOKEN',
TOO_MANY_TOPICS: 'TOO_MANY_TOPICS',
RESOURCE_EXHAUSTED: 'TOO_MANY_TOPICS',
PERMISSION_DENIED: 'AUTHENTICATION_ERROR',
DEADLINE_EXCEEDED: 'SERVER_UNAVAILABLE',
INTERNAL: 'INTERNAL_ERROR',
UNKNOWN: 'UNKNOWN_ERROR',
};

View File

@ -0,0 +1,108 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var validator = require("./validator");
/**
* Renames properties on an object given a mapping from old to new property names.
*
* For example, this can be used to map underscore_cased properties to camelCase.
*
* @param {object} obj The object whose properties to rename.
* @param {object} keyMap The mapping from old to new property names.
*/
function renameProperties(obj, keyMap) {
Object.keys(keyMap).forEach(function (oldKey) {
if (oldKey in obj) {
var newKey = keyMap[oldKey];
// The old key's value takes precedence over the new key's value.
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
});
}
exports.renameProperties = renameProperties;
/**
* Defines a new read-only property directly on an object and returns the object.
*
* @param {object} obj The object on which to define the property.
* @param {string} prop The name of the property to be defined or modified.
* @param {any} value The value associated with the property.
*/
function addReadonlyGetter(obj, prop, value) {
Object.defineProperty(obj, prop, {
value: value,
// Make this property read-only.
writable: false,
// Include this property during enumeration of obj's properties.
enumerable: true,
});
}
exports.addReadonlyGetter = addReadonlyGetter;
/**
* Determines the Google Cloud project ID associated with a Firebase app by examining
* the Firebase app options, credentials and the local environment in that order.
*
* @param {FirebaseApp} app A Firebase app to get the project ID from.
*
* @return {string} A project ID string or null.
*/
function getProjectId(app) {
var options = app.options;
if (validator.isNonEmptyString(options.projectId)) {
return options.projectId;
}
var cert = options.credential.getCertificate();
if (cert != null && validator.isNonEmptyString(cert.projectId)) {
return cert.projectId;
}
var projectId = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
if (validator.isNonEmptyString(projectId)) {
return projectId;
}
return null;
}
exports.getProjectId = getProjectId;
/**
* Encodes data using web-safe-base64.
*
* @param {Buffer} data The raw data byte input.
* @return {string} The base64-encoded result.
*/
function toWebSafeBase64(data) {
return data.toString('base64').replace(/\//g, '_').replace(/\+/g, '-');
}
exports.toWebSafeBase64 = toWebSafeBase64;
/**
* Formats a string of form 'project/{projectId}/{api}' and replaces
* with corresponding arguments {projectId: '1234', api: 'resource'}
* and returns output: 'project/1234/resource'.
*
* @param {string} str The original string where the param need to be
* replaced.
* @param {object=} params The optional parameters to replace in the
* string.
* @return {string} The resulting formatted string.
*/
function formatString(str, params) {
var formatted = str;
Object.keys(params || {}).forEach(function (key) {
formatted = formatted.replace(new RegExp('{' + key + '}', 'g'), params[key]);
});
return formatted;
}
exports.formatString = formatString;

View File

@ -0,0 +1,237 @@
/*! firebase-admin v6.4.0 */
"use strict";
/*!
* Copyright 2017 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.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var url = require("url");
/**
* Validates that a value is a byte buffer.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is byte buffer or not.
*/
function isBuffer(value) {
return value instanceof Buffer;
}
exports.isBuffer = isBuffer;
/**
* Validates that a value is an array.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is an array or not.
*/
function isArray(value) {
return Array.isArray(value);
}
exports.isArray = isArray;
/**
* Validates that a value is a non-empty array.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a non-empty array or not.
*/
function isNonEmptyArray(value) {
return isArray(value) && value.length !== 0;
}
exports.isNonEmptyArray = isNonEmptyArray;
/**
* Validates that a value is a boolean.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a boolean or not.
*/
function isBoolean(value) {
return typeof value === 'boolean';
}
exports.isBoolean = isBoolean;
/**
* Validates that a value is a number.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a number or not.
*/
function isNumber(value) {
return typeof value === 'number' && !isNaN(value);
}
exports.isNumber = isNumber;
/**
* Validates that a value is a string.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a string or not.
*/
function isString(value) {
return typeof value === 'string';
}
exports.isString = isString;
/**
* Validates that a value is a base64 string.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a base64 string or not.
*/
function isBase64String(value) {
if (!isString(value)) {
return false;
}
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value);
}
exports.isBase64String = isBase64String;
/**
* Validates that a value is a non-empty string.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a non-empty string or not.
*/
function isNonEmptyString(value) {
return isString(value) && value !== '';
}
exports.isNonEmptyString = isNonEmptyString;
/**
* Validates that a value is a nullable object.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is an object or not.
*/
function isObject(value) {
return typeof value === 'object' && !isArray(value);
}
exports.isObject = isObject;
/**
* Validates that a value is a non-null object.
*
* @param {any} value The value to validate.
* @return {boolean} Whether the value is a non-null object or not.
*/
function isNonNullObject(value) {
return isObject(value) && value !== null;
}
exports.isNonNullObject = isNonNullObject;
/**
* Validates that a string is a valid Firebase Auth uid.
*
* @param {any} uid The string to validate.
* @return {boolean} Whether the string is a valid Firebase Auth uid.
*/
function isUid(uid) {
return typeof uid === 'string' && uid.length > 0 && uid.length <= 128;
}
exports.isUid = isUid;
/**
* Validates that a string is a valid Firebase Auth password.
*
* @param {any} password The password string to validate.
* @return {boolean} Whether the string is a valid Firebase Auth password.
*/
function isPassword(password) {
// A password must be a string of at least 6 characters.
return typeof password === 'string' && password.length >= 6;
}
exports.isPassword = isPassword;
/**
* Validates that a string is a valid email.
*
* @param {any} email The string to validate.
* @return {boolean} Whether the string is valid email or not.
*/
function isEmail(email) {
if (typeof email !== 'string') {
return false;
}
// There must at least one character before the @ symbol and another after.
var re = /^[^@]+@[^@]+$/;
return re.test(email);
}
exports.isEmail = isEmail;
/**
* Validates that a string is a valid phone number.
*
* @param {any} phoneNumber The string to validate.
* @return {boolean} Whether the string is a valid phone number or not.
*/
function isPhoneNumber(phoneNumber) {
if (typeof phoneNumber !== 'string') {
return false;
}
// Phone number validation is very lax here. Backend will enforce E.164
// spec compliance and will normalize accordingly.
// The phone number string must be non-empty and starts with a plus sign.
var re1 = /^\+/;
// The phone number string must contain at least one alphanumeric character.
var re2 = /[\da-zA-Z]+/;
return re1.test(phoneNumber) && re2.test(phoneNumber);
}
exports.isPhoneNumber = isPhoneNumber;
/**
* Validates that a string is a valid web URL.
*
* @param {any} urlStr The string to validate.
* @return {boolean} Whether the string is valid web URL or not.
*/
function isURL(urlStr) {
if (typeof urlStr !== 'string') {
return false;
}
// Lookup illegal characters.
var re = /[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i;
if (re.test(urlStr)) {
return false;
}
try {
var uri = url.parse(urlStr);
var scheme = uri.protocol;
var slashes = uri.slashes;
var hostname = uri.hostname;
var pathname = uri.pathname;
if ((scheme !== 'http:' && scheme !== 'https:') || !slashes) {
return false;
}
// Validate hostname: Can contain letters, numbers, underscore and dashes separated by a dot.
// Each zone must not start with a hyphen or underscore.
if (!/^[a-zA-Z0-9]+[\w\-]*([\.]?[a-zA-Z0-9]+[\w\-]*)*$/.test(hostname)) {
return false;
}
// Allow for pathnames: (/chars+)*/?
// Where chars can be a combination of: a-z A-Z 0-9 - _ . ~ ! $ & ' ( ) * + , ; = : @ %
var pathnameRe = /^(\/[\w\-\.\~\!\$\'\(\)\*\+\,\;\=\:\@\%]+)*\/?$/;
// Validate pathname.
if (pathname &&
pathname !== '/' &&
!pathnameRe.test(pathname)) {
return false;
}
// Allow any query string and hash as long as no invalid character is used.
}
catch (e) {
return false;
}
return true;
}
exports.isURL = isURL;
/**
* Validates that the provided topic is a valid FCM topic name.
*
* @param {any} topic The topic to validate.
* @return {boolean} Whether the provided topic is a valid FCM topic name.
*/
function isTopic(topic) {
if (typeof topic !== 'string') {
return false;
}
var VALID_TOPIC_REGEX = /^(\/topics\/)?(private\/)?[a-zA-Z0-9-_.~%]+$/;
return VALID_TOPIC_REGEX.test(topic);
}
exports.isTopic = isTopic;

146
express-server/node_modules/firebase-admin/package.json generated vendored Normal file
View File

@ -0,0 +1,146 @@
{
"_from": "firebase-admin",
"_id": "firebase-admin@6.4.0",
"_inBundle": false,
"_integrity": "sha512-sqRfD4UbDA9r1tX/TPbtpYhcajLr+APqlNps7HrFfrqYBfNXLkkZbnx6Bbbbii3XPJZ5Dcwfl9saxHahsLkpCw==",
"_location": "/firebase-admin",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "firebase-admin",
"name": "firebase-admin",
"escapedName": "firebase-admin",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-6.4.0.tgz",
"_shasum": "55c288f4e324bc89174bad39735c78475eae7235",
"_spec": "firebase-admin",
"_where": "D:\\Desktop\\Git\\Firebase\\SmartShopperFirebase",
"author": {
"name": "Firebase",
"email": "firebase-support@google.com",
"url": "https://firebase.google.com/"
},
"bugs": {
"url": "https://github.com/firebase/firebase-admin-node/issues"
},
"bundleDependencies": false,
"dependencies": {
"@firebase/app": "^0.3.4",
"@firebase/database": "^0.3.6",
"@google-cloud/firestore": "^0.19.0",
"@google-cloud/storage": "^1.6.0",
"@types/google-cloud__storage": "^1.7.1",
"@types/node": "^8.0.53",
"jsonwebtoken": "8.1.0",
"node-forge": "0.7.4"
},
"deprecated": false,
"description": "Firebase admin SDK for Node.js",
"devDependencies": {
"@firebase/auth": "0.5.2",
"@types/bcrypt": "^2.0.0",
"@types/chai": "^3.4.34",
"@types/chai-as-promised": "0.0.29",
"@types/firebase-token-generator": "^2.0.28",
"@types/jsonwebtoken": "^7.2.8",
"@types/lodash": "^4.14.104",
"@types/minimist": "^1.2.0",
"@types/mocha": "^2.2.48",
"@types/nock": "^9.1.0",
"@types/request": "^2.47.0",
"@types/request-promise": "^4.1.41",
"@types/scrypt": "^6.0.0",
"@types/sinon": "^4.1.3",
"@types/sinon-chai": "^2.7.27",
"bcrypt": "^3.0.0",
"chai": "^3.5.0",
"chai-as-promised": "^6.0.0",
"chalk": "^1.1.3",
"del": "^2.2.1",
"firebase-token-generator": "^2.0.0",
"gulp": "^3.9.1",
"gulp-exit": "0.0.2",
"gulp-header": "^1.8.8",
"gulp-replace": "^0.5.4",
"gulp-typescript": "^3.2.4",
"lodash": "^4.17.5",
"merge2": "^1.2.1",
"minimist": "^1.2.0",
"mocha": "^5.2.0",
"nock": "^9.6.0",
"npm-run-all": "^4.1.5",
"nyc": "^11.5.0",
"request": "^2.75.0",
"request-promise": "^4.1.1",
"run-sequence": "^1.1.5",
"scrypt": "^6.0.3",
"sinon": "^4.4.5",
"sinon-chai": "^2.8.0",
"ts-node": "^3.3.0",
"tslint": "^5.9.0",
"typescript": "^2.7.2"
},
"engines": {
"node": ">=6.0.0"
},
"files": [
"lib/",
"LICENSE",
"README.md",
"package.json"
],
"homepage": "https://firebase.google.com/",
"keywords": [
"admin",
"database",
"Firebase",
"realtime",
"authentication"
],
"license": "Apache-2.0",
"main": "lib/index.js",
"name": "firebase-admin",
"nyc": {
"extension": [
".ts"
],
"include": [
"src"
],
"exclude": [
"**/*.d.ts"
],
"all": true
},
"optionalDependencies": {
"@google-cloud/firestore": "^0.19.0",
"@google-cloud/storage": "^1.6.0",
"@types/google-cloud__storage": "^1.7.1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/firebase/firebase-admin-node.git"
},
"scripts": {
"build": "gulp build",
"integration": "run-s build test:integration",
"lint": "run-p lint:src lint:unit lint:integration",
"lint:integration": "tslint -c tslint-test.json --format stylish test/integration/*.ts",
"lint:src": "tslint --format stylish -p tsconfig.json",
"lint:unit": "tslint -c tslint-test.json --format stylish test/unit/*.ts test/unit/**/*.ts",
"test": "run-s lint test:unit",
"test:coverage": "nyc npm run test:unit",
"test:integration": "mocha test/integration/*.ts --slow 5000 --timeout 20000 --require ts-node/register",
"test:unit": "mocha test/unit/*.spec.ts --require ts-node/register"
},
"types": "./lib/index.d.ts",
"version": "6.4.0"
}