diff --git a/docs/articles/auth/firebase-authentication.md b/docs/articles/auth/firebase-authentication.md
new file mode 100644
index 0000000000..e24a2a878d
--- /dev/null
+++ b/docs/articles/auth/firebase-authentication.md
@@ -0,0 +1,190 @@
+## Firebase authentication with Nebular Auth
+
+`@nebualar/firebase-auth` allows authentication in firebase applications with `@nebular/auth`.
+The package provides the following strategies:
+ - `NbFirebasePasswordStrategy` - authentication with email/password
+ - `NbFirebaseGoogleStrategy` - authentication with google accounts
+ - `NbFirebaseFacebookStrategy` - authentication with facebook accounts
+ - `NbFirebaseTwitteStrategy` - authentication with twitter accounts
+
+`@nebular/auth` package is sponsored by [GO-ER](www.go-er.com) and What Now Travel.
+
+## Installation
+
+
+
Note
+
+ The package connects firebase auth with nebular/auth so you need `firebase` and `@angular/fire` installed
+ and configured for your application. For more instructions please see [@angular/fire docs](https://github.com/akveo/nebular/tree/master/src/playground/without-layout/azure).
+ Also make sure you import AngularFireAuthModule.
+
+
+
+
+Install Nebular Auth and Nebular Firebase Auth.
+
+ ```sh
+ npm i @nebular/auth @angular\firebase-auth
+ ```
+
+Import the NbAuthModule with some firebase strategies, in that example we use NbFirebasePasswordStrategy.
+
+```ts
+import { NbAuthModule } from '@nebular/auth';
+import { NbFirebasePasswordStrategy } from '@nebular/firebase-auth';
+
+
+@NgModule({
+ imports: [
+ // ...
+
+ NbAuthModule.forRoot({
+ strategies: [
+ NbFirebasePasswordStrategy.setup({
+ name: 'password',
+ }),
+ ],
+ forms: {},
+ }),
+ ],
+});
+```
+
+
+## Authentication with email and password
+
+Nebular Firebase Auth provides NbFirebasePassword strategy for authentication with email and password.
+
+Strategy settings:
+
+
Note
+
+ There is no need to copy over the whole object to change the settings you need.
+ Also, this.getOption call won't work outside of the default options declaration (which is inside of the NbPasswordAuthStrategy class),
+ so you have to replace it with a custom helper function if you need it.
+
+
+
+```ts
+export class NbFirebasePasswordStrategyOptions extends NbAuthStrategyOptions {
+ name: string;
+ token = {
+ class: NbAuthJWTToken,
+ };
+ register?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully registered.'],
+ };
+ login?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Login/Email combination is not correct, please try again.'],
+ defaultMessages: ['You have been successfully logged in.'],
+ };
+ logout?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully logged out.'],
+ };
+ refreshToken?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: null,
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Your token has been successfully refreshed.'],
+ };
+ requestPassword?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Reset password instructions have been sent to your email.'],
+ };
+ resetPassword?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Your password has been successfully changed.'],
+ };
+ errors?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebasePasswordStrategyOptions) => getDeepFromObject(
+ res,
+ options.errors.key,
+ options[module].defaultErrors,
+ ),
+ };
+ messages?: NbPasswordStrategyMessage = {
+ key: 'messages',
+ getter: (module: string, res, options: NbFirebasePasswordStrategyOptions) => getDeepFromObject(
+ res.body,
+ options.messages.key,
+ options[module].defaultMessages,
+ ),
+ };
+}
+```
+
+
+## Social Authentication providers
+
+Nebular Firebase Auth for now provides strategies for authentication with Google, Facebook and Twitter.
+These strategies share the same settings structure and default settings value.
+
+Strategies settings:
+
+```ts
+export class NbFirebaseIdentityProviderStrategyOptions extends NbAuthStrategyOptions {
+ name: string;
+ logout?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully logged out.'],
+ };
+ authenticate?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully authenticated.'],
+ };
+ errors?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebaseIdentityProviderStrategyOptions) => options[module].defaultErrors,
+ };
+ messages?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebaseIdentityProviderStrategyOptions) => options[module].defaultMessages,
+ };
+ scopes?: string[] = [];
+ customParameters?: { [key: string]: string } = {};
+ }
+};
+```
+
+
+## Complete example
+
+A complete code example could be found on [GitHub](https://github.com/akveo/nebular/tree/master/src/playground/with-layout/firebase).
+
+And here the playground examples available to play around with
+ - [Firebase Nebular Password Example](/example/firebase/password-showcase)
+ - [Firebase Nebular Social Authentication Providers Example](/example/firebase/social-auth-showcase)
+
diff --git a/docs/articles/getting-started/what-is-nebular.md b/docs/articles/getting-started/what-is-nebular.md
index e3f8f83f58..dd4bdfff92 100644
--- a/docs/articles/getting-started/what-is-nebular.md
+++ b/docs/articles/getting-started/what-is-nebular.md
@@ -16,6 +16,8 @@ Nebular modules are distributed as separated `npm` packages:
- Authentication components (login/register/reset password/restore password).
- Multiple configurable authentication Strategies (backend connectors).
- Helpers for token management (storing, passing with HTTP requests, etc).
+- Nebular Auth for Firebase `@nebular/firebase-auth
+ - module for authentication in firebase applications with nebular/auth
- Nebular Security `@nebular/security`
- roles and permissions management.
- Nebular Moment `@nebular/moment`
diff --git a/docs/structure.ts b/docs/structure.ts
index 03832e576a..3373c6c787 100644
--- a/docs/structure.ts
+++ b/docs/structure.ts
@@ -915,6 +915,17 @@ export const structure = [
},
],
},
+ {
+ type: 'page',
+ name: 'Firebase Authentication',
+ children: [
+ {
+ type: 'block',
+ block: 'markdown',
+ source: 'auth/firebase-authentication.md',
+ },
+ ],
+ },
{
type: 'page',
name: 'NbAuthService',
diff --git a/docs/tsconfig.app.json b/docs/tsconfig.app.json
index 15ffc4f06c..86841ae302 100644
--- a/docs/tsconfig.app.json
+++ b/docs/tsconfig.app.json
@@ -18,7 +18,8 @@
"@nebular/theme": ["../src/framework/theme/public_api.ts"],
"@nebular/auth": ["../src/framework/auth/public_api.ts"],
"@nebular/security": ["../src/framework/security/public_api.ts"],
- "@nebular/eva-icons": ["../src/framework/eva-icons/public_api.ts"]
+ "@nebular/eva-icons": ["../src/framework/eva-icons/public_api.ts"],
+ "@nebular/firebase-auth": ["../src/framework/firebase-auth/public_api.ts"]
}
},
"files": [
diff --git a/package-lock.json b/package-lock.json
index 3f1c075cd8..3273823321 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -937,6 +937,11 @@
"resolved": "https://registry.npmjs.org/@angular/core/-/core-9.0.4.tgz",
"integrity": "sha512-6RqQb1GO2uglSlgiGbxhvy8plztZtABCWLRn0X+T1PnrxoqgxqA5WkKJjGxao+1M/ECW1V0fw4Xy7DE6KvAJwQ=="
},
+ "@angular/fire": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@angular/fire/-/fire-6.0.0.tgz",
+ "integrity": "sha512-zWhaJaZPtfJKiNSb1I3WqqvopW0fN3S61w4PjPdsm5WME+9M9alP0zpRVclpbCU26LpBSLhrRrSLyn3ROlAOIw=="
+ },
"@angular/forms": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-9.0.4.tgz",
@@ -2187,6 +2192,348 @@
}
}
},
+ "@firebase/analytics": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.3.5.tgz",
+ "integrity": "sha512-p+h1s9A8EjGWfjAObu8ei46JoN2Ogbtl1RzqW7HjcPuclOIOmPTXKEXXCEXgO79OLxnzzezVeBtHPSx6r6gxJA==",
+ "requires": {
+ "@firebase/analytics-types": "0.3.1",
+ "@firebase/component": "0.1.12",
+ "@firebase/installations": "0.4.10",
+ "@firebase/logger": "0.2.4",
+ "@firebase/util": "0.2.47",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/analytics-types": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.3.1.tgz",
+ "integrity": "sha512-63vVJ5NIBh/JF8l9LuPrQYSzFimk7zYHySQB4Dk9rVdJ8kV/vGQoVTvRu1UW05sEc2Ug5PqtEChtTHU+9hvPcA=="
+ },
+ "@firebase/app": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.6.4.tgz",
+ "integrity": "sha512-E1Zw6yeZYdYYFurMnklKPvE+q/xleHXs7bmcVgyhgAEg3Gv6/qXI4+4GdWh+iF7wmQ3Liesh51xqfdpvHBwAMQ==",
+ "requires": {
+ "@firebase/app-types": "0.6.1",
+ "@firebase/component": "0.1.12",
+ "@firebase/logger": "0.2.4",
+ "@firebase/util": "0.2.47",
+ "dom-storage": "2.1.0",
+ "tslib": "1.11.1",
+ "xmlhttprequest": "1.8.0"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/app-types": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.6.1.tgz",
+ "integrity": "sha512-L/ZnJRAq7F++utfuoTKX4CLBG5YR7tFO3PLzG1/oXXKEezJ0kRL3CMRoueBEmTCzVb/6SIs2Qlaw++uDgi5Xyg=="
+ },
+ "@firebase/auth": {
+ "version": "0.14.6",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-0.14.6.tgz",
+ "integrity": "sha512-7gaEUWhUubWBGfOXAZvpTpJqBJT9KyG83RXC6VnjSQIfNUaarHZ485WkzERil43A6KvIl+f4kHxfZShE6ZCK3A==",
+ "requires": {
+ "@firebase/auth-types": "0.10.1"
+ }
+ },
+ "@firebase/auth-interop-types": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz",
+ "integrity": "sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw=="
+ },
+ "@firebase/auth-types": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.10.1.tgz",
+ "integrity": "sha512-/+gBHb1O9x/YlG7inXfxff/6X3BPZt4zgBv4kql6HEmdzNQCodIRlEYnI+/da+lN+dha7PjaFH7C7ewMmfV7rw=="
+ },
+ "@firebase/component": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.1.12.tgz",
+ "integrity": "sha512-03w800MxR/EW1m7N0Q46WNcngwdDIHDWpFPHTdbZEI6U/HuLks5RJQlBxWqb1P73nYPkN8YP3U8gTdqrDpqY3Q==",
+ "requires": {
+ "@firebase/util": "0.2.47",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/database": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/@firebase/database/-/database-0.6.3.tgz",
+ "integrity": "sha512-gHoCISHQVLoq+rGu+PorYxMkhsjhXov3ocBxz/0uVdznNhrbKkAZaEKF+dIAsUPDlwSYeZuwWuik7xcV3DtRaw==",
+ "requires": {
+ "@firebase/auth-interop-types": "0.1.5",
+ "@firebase/component": "0.1.12",
+ "@firebase/database-types": "0.5.1",
+ "@firebase/logger": "0.2.4",
+ "@firebase/util": "0.2.47",
+ "faye-websocket": "0.11.3",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "faye-websocket": {
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz",
+ "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==",
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ }
+ },
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/database-types": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-0.5.1.tgz",
+ "integrity": "sha512-onQxom1ZBYBJ648w/VNRzUewovEDAH7lvnrrpCd69ukkyrMk6rGEO/PQ9BcNEbhlNtukpsqRS0oNOFlHs0FaSA==",
+ "requires": {
+ "@firebase/app-types": "0.6.1"
+ }
+ },
+ "@firebase/firestore": {
+ "version": "1.14.5",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-1.14.5.tgz",
+ "integrity": "sha512-BZD3RqlAEnq15i8Y53VUFsuWkbujslGaQIcuEnt6bOENzlKiLBwESmt/uGKRIsdQjc1krG2qdoPmaSMqULR0dA==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/firestore-types": "1.10.2",
+ "@firebase/logger": "0.2.4",
+ "@firebase/util": "0.2.47",
+ "@firebase/webchannel-wrapper": "0.2.41",
+ "@grpc/grpc-js": "0.8.1",
+ "@grpc/proto-loader": "^0.5.0",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/firestore-types": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-1.10.2.tgz",
+ "integrity": "sha512-T1GttZezQ+gUpdDgLeLOvgS3KMeeIuodQ+JBBEd6M11zdilfTHsEHhmli15c6V3g/PfuFzyKDKExe05lPuYe4w=="
+ },
+ "@firebase/functions": {
+ "version": "0.4.44",
+ "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.4.44.tgz",
+ "integrity": "sha512-Nbw+V/jYqfgq7wscsSDidqIzx8TrnmA2wRD1auCFNmf+gSJg8o+gNyCDdNHZI407jvrZcxp3nG1eMbqwmmnp7Q==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/functions-types": "0.3.17",
+ "@firebase/messaging-types": "0.4.5",
+ "isomorphic-fetch": "2.2.1",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/functions-types": {
+ "version": "0.3.17",
+ "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.3.17.tgz",
+ "integrity": "sha512-DGR4i3VI55KnYk4IxrIw7+VG7Q3gA65azHnZxo98Il8IvYLr2UTBlSh72dTLlDf25NW51HqvJgYJDKvSaAeyHQ=="
+ },
+ "@firebase/installations": {
+ "version": "0.4.10",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.4.10.tgz",
+ "integrity": "sha512-Nf7VK9++0eQzjdvBkBNNaOdxPjFiKD0EllLCIQycHozF97BmuFUqb2Ik5L2JaWspWg7vxLNacLHvW48nPGx4Zw==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/installations-types": "0.3.4",
+ "@firebase/util": "0.2.47",
+ "idb": "3.0.2",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/installations-types": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.3.4.tgz",
+ "integrity": "sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q=="
+ },
+ "@firebase/logger": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.2.4.tgz",
+ "integrity": "sha512-akHkOU7izYB1okp/B5sxClGjjw6KvZdSHyjNM5pKd67Zg5W6PsbkI/GFNv21+y6LkUkJwDRbdeDgJoYXWT3mMA=="
+ },
+ "@firebase/messaging": {
+ "version": "0.6.16",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.6.16.tgz",
+ "integrity": "sha512-TAPISK5y3xbxUw81HxLDP6YPsRryU6Nl8Z7AjNnem13BoN9LJ2/wCi9RDMfPnQhAn0h0N+mpxy/GB+0IlEARlg==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/installations": "0.4.10",
+ "@firebase/messaging-types": "0.4.5",
+ "@firebase/util": "0.2.47",
+ "idb": "3.0.2",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/messaging-types": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-types/-/messaging-types-0.4.5.tgz",
+ "integrity": "sha512-sux4fgqr/0KyIxqzHlatI04Ajs5rc3WM+WmtCpxrKP1E5Bke8xu/0M+2oy4lK/sQ7nov9z15n3iltAHCgTRU3Q=="
+ },
+ "@firebase/performance": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.3.4.tgz",
+ "integrity": "sha512-VDoqJSB+2RuXlyyP7oSvBPEmoznG84HmEtb8DQWsAHeVkf+qlec1OTZR8IjktlIv+8Pg8MMuYoB0crx5g7xU5A==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/installations": "0.4.10",
+ "@firebase/logger": "0.2.4",
+ "@firebase/performance-types": "0.0.13",
+ "@firebase/util": "0.2.47",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/performance-types": {
+ "version": "0.0.13",
+ "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.0.13.tgz",
+ "integrity": "sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA=="
+ },
+ "@firebase/polyfill": {
+ "version": "0.3.36",
+ "resolved": "https://registry.npmjs.org/@firebase/polyfill/-/polyfill-0.3.36.tgz",
+ "integrity": "sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg==",
+ "requires": {
+ "core-js": "3.6.5",
+ "promise-polyfill": "8.1.3",
+ "whatwg-fetch": "2.0.4"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
+ "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
+ },
+ "whatwg-fetch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+ "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
+ }
+ }
+ },
+ "@firebase/remote-config": {
+ "version": "0.1.21",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.1.21.tgz",
+ "integrity": "sha512-EwDNU1mT+8Jn66IUwwNP5SM8AbaI7wmCXjp7djZtTXNrpPoh3xqzSRM1vTgp4Uu/mHffEDfbydsoJAIftADIfQ==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/installations": "0.4.10",
+ "@firebase/logger": "0.2.4",
+ "@firebase/remote-config-types": "0.1.9",
+ "@firebase/util": "0.2.47",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/remote-config-types": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz",
+ "integrity": "sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA=="
+ },
+ "@firebase/storage": {
+ "version": "0.3.34",
+ "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.3.34.tgz",
+ "integrity": "sha512-vuR1PpGdaCk25D2dT2trfmZZjpdfOn0rPTksvoqg7TAPLeoVsVoDyT2LgF3Arna/jqx52sAIRx1HLrlvzE1pgA==",
+ "requires": {
+ "@firebase/component": "0.1.12",
+ "@firebase/storage-types": "0.3.12",
+ "@firebase/util": "0.2.47",
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/storage-types": {
+ "version": "0.3.12",
+ "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.3.12.tgz",
+ "integrity": "sha512-DDV6Fs6aYoGw3w/zZZTkqiipxihnsvHf6znbeZYjIIHit3tr1uLJdGPDPiCTfZcTGPpg2ux6ZmvNDvVgJdHALw=="
+ },
+ "@firebase/util": {
+ "version": "0.2.47",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-0.2.47.tgz",
+ "integrity": "sha512-RjcIvcfswyxYhf0OMXod+qeI/933wl9FGLIszf0/O1yMZ/s8moXcse7xnOpMjmQPRLB9vHzCMoxW5X90kKg/bQ==",
+ "requires": {
+ "tslib": "1.11.1"
+ },
+ "dependencies": {
+ "tslib": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
+ "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
+ }
+ }
+ },
+ "@firebase/webchannel-wrapper": {
+ "version": "0.2.41",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.2.41.tgz",
+ "integrity": "sha512-XcdMT5PSZHiuf7LJIhzKIe+RyYa25S3LHRRvLnZc6iFjwXkrSDJ8J/HWO6VT8d2ZTbawp3VcLEjRF/VN8glCrA=="
+ },
"@google-cloud/common": {
"version": "0.17.0",
"resolved": "http://registry.npmjs.org/@google-cloud/common/-/common-0.17.0.tgz",
@@ -2620,6 +2967,30 @@
}
}
},
+ "@grpc/grpc-js": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-0.8.1.tgz",
+ "integrity": "sha512-e8gSjRZnOUefsR3obOgxG9RtYW2Mw83hh7ogE2ByCdgRhoX0mdnJwBcZOami3E0l643KCTZvORFwfSEi48KFIQ==",
+ "requires": {
+ "semver": "^6.2.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ }
+ }
+ },
+ "@grpc/proto-loader": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.4.tgz",
+ "integrity": "sha512-HTM4QpI9B2XFkPz7pjwMyMgZchJ93TVkL3kWPW8GDMDKYxsMnmf4w2TNMJK7+KNiYHS5cJrCEAFlF+AwtXWVPA==",
+ "requires": {
+ "lodash.camelcase": "^4.3.0",
+ "protobufjs": "^6.8.6"
+ }
+ },
"@gulp-sourcemaps/identity-map": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz",
@@ -2740,6 +3111,60 @@
"esquery": "^1.0.1"
}
},
+ "@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78="
+ },
+ "@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="
+ },
+ "@protobufjs/codegen": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
+ "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="
+ },
+ "@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
+ "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A="
+ },
+ "@protobufjs/fetch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
+ "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E="
+ },
+ "@protobufjs/inquire": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
+ "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik="
+ },
+ "@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0="
+ },
+ "@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q="
+ },
+ "@protobufjs/utf8": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
+ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA="
+ },
"@schematics/angular": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-9.0.1.tgz",
@@ -3045,6 +3470,11 @@
"integrity": "sha512-ogI4g9W5qIQQUhXAclq6zhqgqNUr7UlFaqDHbch7WLSLeeM/7d3CRaw7GLajxvyFvhJqw4Rpcz5bhoaYtIx6Tg==",
"dev": true
},
+ "@types/long": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz",
+ "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w=="
+ },
"@types/marked": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz",
@@ -8230,6 +8660,11 @@
}
}
},
+ "dom-storage": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.1.0.tgz",
+ "integrity": "sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q=="
+ },
"dom-walk": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
@@ -8408,7 +8843,6 @@
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
"integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=",
- "dev": true,
"requires": {
"iconv-lite": "~0.4.13"
}
@@ -9418,42 +9852,24 @@
}
},
"firebase": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/firebase/-/firebase-2.4.2.tgz",
- "integrity": "sha1-ThEZ7AOWylYdinrL/xYw/qxsCjE=",
- "dev": true,
- "requires": {
- "faye-websocket": ">=0.6.0"
- },
- "dependencies": {
- "faye-websocket": {
- "version": "0.9.3",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz",
- "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=",
- "dev": true,
- "requires": {
- "websocket-driver": ">=0.5.1"
- },
- "dependencies": {
- "websocket-driver": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.2.tgz",
- "integrity": "sha1-jHyF2gcTtAYFVrTXHAF3XuEmnrk=",
- "dev": true,
- "requires": {
- "websocket-extensions": ">=0.1.1"
- },
- "dependencies": {
- "websocket-extensions": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
- "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=",
- "dev": true
- }
- }
- }
- }
- }
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-7.14.5.tgz",
+ "integrity": "sha512-1vrC1UZIVhaT7owaElQoEseP81xqRt6tHQmxRJRojn0yI3JNXrdWCFsD+26xA1eQQCwodJuMsYJLzQSScgjHuQ==",
+ "requires": {
+ "@firebase/analytics": "0.3.5",
+ "@firebase/app": "0.6.4",
+ "@firebase/app-types": "0.6.1",
+ "@firebase/auth": "0.14.6",
+ "@firebase/database": "0.6.3",
+ "@firebase/firestore": "1.14.5",
+ "@firebase/functions": "0.4.44",
+ "@firebase/installations": "0.4.10",
+ "@firebase/messaging": "0.6.16",
+ "@firebase/performance": "0.3.4",
+ "@firebase/polyfill": "0.3.36",
+ "@firebase/remote-config": "0.1.21",
+ "@firebase/storage": "0.3.34",
+ "@firebase/util": "0.2.47"
}
},
"firebase-tools": {
@@ -9538,6 +9954,45 @@
"object-assign": "^4.1.0"
}
},
+ "firebase": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/firebase/-/firebase-2.4.2.tgz",
+ "integrity": "sha1-ThEZ7AOWylYdinrL/xYw/qxsCjE=",
+ "dev": true,
+ "requires": {
+ "faye-websocket": ">=0.6.0"
+ },
+ "dependencies": {
+ "faye-websocket": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz",
+ "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=",
+ "dev": true,
+ "requires": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "dependencies": {
+ "websocket-driver": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.5.2.tgz",
+ "integrity": "sha1-jHyF2gcTtAYFVrTXHAF3XuEmnrk=",
+ "dev": true,
+ "requires": {
+ "websocket-extensions": ">=0.1.1"
+ },
+ "dependencies": {
+ "websocket-extensions": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz",
+ "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=",
+ "dev": true
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"fs-extra": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.23.1.tgz",
@@ -12476,8 +12931,7 @@
"http-parser-js": {
"version": "0.4.10",
"resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz",
- "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=",
- "dev": true
+ "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q="
},
"http-proxy": {
"version": "1.17.0",
@@ -12614,11 +13068,15 @@
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
- "dev": true,
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
+ "idb": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/idb/-/idb-3.0.2.tgz",
+ "integrity": "sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw=="
+ },
"ieee754": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
@@ -13474,6 +13932,26 @@
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
"dev": true
},
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=",
+ "requires": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ },
+ "dependencies": {
+ "node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "requires": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ }
+ }
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -14735,6 +15213,11 @@
"lodash._objecttypes": "~2.4.1"
}
},
+ "lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
+ },
"lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
@@ -14953,6 +15436,11 @@
"integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=",
"dev": true
},
+ "long": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
+ "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
+ },
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -18385,6 +18873,11 @@
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=",
"dev": true
},
+ "promise-polyfill": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
+ "integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g=="
+ },
"promise-retry": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz",
@@ -18459,6 +18952,33 @@
}
}
},
+ "protobufjs": {
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.9.0.tgz",
+ "integrity": "sha512-LlGVfEWDXoI/STstRDdZZKb/qusoAWUnmLg9R8OLSO473mBLWHowx8clbX5/+mKDEI+v7GzjoK9tRPZMMcoTrg==",
+ "requires": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.1",
+ "@types/node": "^13.7.0",
+ "long": "^4.0.0"
+ },
+ "dependencies": {
+ "@types/node": {
+ "version": "13.13.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.9.tgz",
+ "integrity": "sha512-EPZBIGed5gNnfWCiwEIwTE2Jdg4813odnG8iNPMQGrqVxrI+wL68SPtPeCX+ZxGBaA6pKAVc6jaKgP/Q0QzfdQ=="
+ }
+ }
+ },
"protochain": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/protochain/-/protochain-1.0.5.tgz",
@@ -24576,7 +25096,6 @@
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz",
"integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==",
- "dev": true,
"requires": {
"http-parser-js": ">=0.4.0 <0.4.11",
"safe-buffer": ">=5.1.0",
@@ -24586,8 +25105,12 @@
"websocket-extensions": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz",
- "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
- "dev": true
+ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg=="
+ },
+ "whatwg-fetch": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
+ "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
},
"when": {
"version": "3.6.4",
@@ -24815,6 +25338,11 @@
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
"dev": true
},
+ "xmlhttprequest": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+ "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw="
+ },
"xmlhttprequest-ssl": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.3.tgz",
diff --git a/package.json b/package.json
index 33e6198de2..079a637d90 100644
--- a/package.json
+++ b/package.json
@@ -90,6 +90,7 @@
"@angular/common": "^9.0.4",
"@angular/compiler": "^9.0.4",
"@angular/core": "^9.0.4",
+ "@angular/fire": "^6.0.0",
"@angular/forms": "^9.0.4",
"@angular/localize": "^9.0.4",
"@angular/platform-browser": "^9.0.4",
@@ -101,6 +102,7 @@
"date-fns": "2",
"docsearch.js": "^2.5.2",
"eva-icons": "^1.1.2",
+ "firebase": "^7.14.5",
"gulp-bump": "2.7.0",
"highlight.js": "9.12.0",
"intersection-observer": "0.7.0",
diff --git a/scripts/gulp/tasks/build/bundle/rollup-config.ts b/scripts/gulp/tasks/build/bundle/rollup-config.ts
index 155ee45c11..24914654e2 100644
--- a/scripts/gulp/tasks/build/bundle/rollup-config.ts
+++ b/scripts/gulp/tasks/build/bundle/rollup-config.ts
@@ -25,6 +25,8 @@ const ROLLUP_GLOBALS = {
'@angular/cdk/table': 'ng.cdk.table',
'@angular/cdk/bidi': 'ng.cdk.bidi',
'@angular/cdk/keycodes': 'ng.cdk.keycodes',
+ '@angular/fire': 'ng.fire',
+ '@angular/fire/auth': 'ng.fire.auth',
// RxJS dependencies
@@ -33,6 +35,9 @@ const ROLLUP_GLOBALS = {
// 3rd party dependencies
'intersection-observer': 'intersection-observer',
+ 'firebase': 'firebase',
+ 'firebase/app': 'firebase.app',
+ 'firebase/auth': 'firebase.auth',
// date libs for date service
'moment': 'moment',
@@ -47,6 +52,7 @@ const ROLLUP_GLOBALS = {
'@nebular/moment': 'nb.moment',
'@nebular/date-fns': 'nb.date-fns',
'@nebular/eva-icons': 'nb.eva-icons',
+ '@nebular/firebase-auth': 'nb.firebase-auth',
'eva-icons': 'eva-icons',
};
diff --git a/scripts/gulp/tasks/change-prefix.ts b/scripts/gulp/tasks/change-prefix.ts
index d0277119bf..77b9993e53 100644
--- a/scripts/gulp/tasks/change-prefix.ts
+++ b/scripts/gulp/tasks/change-prefix.ts
@@ -8,7 +8,7 @@ import { capitalize, dasherize } from '@angular-devkit/core/src/utils/strings';
import { BUILD_DIR } from './config';
-type NebularPackage = 'auth' | 'bootstrap' | 'dateFns' | 'evaIcons' | 'moment' | 'theme' | 'security';
+type NebularPackage = 'auth' | 'bootstrap' | 'dateFns' | 'evaIcons' | 'moment' | 'theme' | 'security' | 'firebase-auth';
interface PackagePrefix {
prefix: string;
@@ -26,7 +26,16 @@ interface StringReplacement {
const ROLLUP_CONFIG_DIR = './scripts/gulp/tasks/bundle';
const ROLLUP_CONFIG_PATH = `${ROLLUP_CONFIG_DIR}/rollup-config.ts`;
-const NEBULAR_PACKAGES: NebularPackage[] = ['auth', 'bootstrap', 'dateFns', 'evaIcons', 'moment', 'theme', 'security'];
+const NEBULAR_PACKAGES: NebularPackage[] = [
+ 'auth',
+ 'bootstrap',
+ 'dateFns',
+ 'evaIcons',
+ 'moment',
+ 'theme',
+ 'security',
+ 'firebase-auth',
+];
/**
* Reads package prefix and all package names passed as command line arguments.
diff --git a/scripts/gulp/tasks/config.ts b/scripts/gulp/tasks/config.ts
index 70e670d756..a27914c898 100644
--- a/scripts/gulp/tasks/config.ts
+++ b/scripts/gulp/tasks/config.ts
@@ -12,4 +12,5 @@ export const JS_PACKAGES = [
'moment',
'security',
'theme',
+ 'firebase-auth',
];
diff --git a/src/app/playground-components.ts b/src/app/playground-components.ts
index 039204222f..a857d146e7 100644
--- a/src/app/playground-components.ts
+++ b/src/app/playground-components.ts
@@ -1797,6 +1797,53 @@ export const PLAYGROUND_COMPONENTS: ComponentLink[] = [
},
],
},
+ {
+ path: 'firebase',
+ children: [
+ {
+ path: 'login',
+ link: '/firebase/login',
+ component: 'NbLoginComponent',
+ name: 'Nb Login',
+ },
+ {
+ path: 'register',
+ link: '/firebase/register',
+ component: 'NbRegisterComponent',
+ name: 'Nb Register',
+ },
+ {
+ path: 'logout',
+ link: '/firebase/logout',
+ component: 'NbLogoutComponent',
+ name: 'Nb Logout',
+ },
+ {
+ path: 'request-password',
+ link: '/firebase/request-password',
+ component: 'NbRequestPasswordComponent',
+ name: 'Nb Request Password',
+ },
+ {
+ path: 'reset-password',
+ link: '/firebase/reset-password',
+ component: 'NbResetPasswordComponent',
+ name: 'Nb Reset Password',
+ },
+ {
+ path: 'password-showcase',
+ link: '/firebase/password-showcase',
+ component: 'PasswordAuthShowcaseComponent',
+ name: 'Password Auth Showcase',
+ },
+ {
+ path: 'social-auth-showcase',
+ link: '/firebase/social-auth-showcase',
+ component: 'IdentityProvidersAuthShowcaseComponent',
+ name: 'Identity Providers Auth Showcase',
+ },
+ ],
+ },
{
path: 'smart-home',
children: [
diff --git a/src/framework/firebase-auth/LICENSE.txt b/src/framework/firebase-auth/LICENSE.txt
new file mode 100644
index 0000000000..031c83cb11
--- /dev/null
+++ b/src/framework/firebase-auth/LICENSE.txt
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2017 Akveo.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/src/framework/firebase-auth/README.md b/src/framework/firebase-auth/README.md
new file mode 100644
index 0000000000..6cb1e27bed
--- /dev/null
+++ b/src/framework/firebase-auth/README.md
@@ -0,0 +1 @@
+### @nebular/firebase-auth module, more details https://akveo.github.io/nebular/
diff --git a/src/framework/firebase-auth/firebase-auth.module.ts b/src/framework/firebase-auth/firebase-auth.module.ts
new file mode 100644
index 0000000000..910d78c318
--- /dev/null
+++ b/src/framework/firebase-auth/firebase-auth.module.ts
@@ -0,0 +1,24 @@
+/*
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+
+import { NgModule } from '@angular/core';
+
+import { NbFirebasePasswordStrategy } from './strategies/password/firebase-password.strategy';
+import { NbFirebaseGoogleStrategy } from './strategies/google/firebase-google.strategy';
+import { NbFirebaseFacebookStrategy } from './strategies/facebook/firebase-facebook.strategy';
+import { NbFirebaseTwitteStrategy } from './strategies/twitter/firebase-twitter.strategy';
+
+
+@NgModule({
+ providers: [
+ NbFirebasePasswordStrategy,
+ NbFirebaseGoogleStrategy,
+ NbFirebaseFacebookStrategy,
+ NbFirebaseTwitteStrategy,
+ ],
+})
+export class NbFirebaseAuthModule { }
diff --git a/src/framework/firebase-auth/package.json b/src/framework/firebase-auth/package.json
new file mode 100644
index 0000000000..9f332b6723
--- /dev/null
+++ b/src/framework/firebase-auth/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "@nebular/firebase-auth",
+ "version": "5.0.0",
+ "description": "@nebular/firebase-auth",
+ "author": "akveo",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/akveo/nebular.git"
+ },
+ "bugs": {
+ "url": "https://github.com/akveo/nebular/issues"
+ },
+ "homepage": "https://github.com/akveo/nebular#readme",
+ "keywords": [
+ "angular",
+ "typescript",
+ "ng2-admin",
+ "ngx-admin",
+ "theme",
+ "auth",
+ "login",
+ "register",
+ "nebular",
+ "firebase"
+ ],
+ "peerDependencies": {
+ "@angular/core": "^9.0.0",
+ "@nebular/auth": "^5.0.0",
+ "rxjs": "^6.5.1",
+ "firebase": "^7.14.5",
+ "@angular/fire": "^6.0.0"
+ },
+ "sideEffects": false
+}
diff --git a/src/framework/firebase-auth/public_api.ts b/src/framework/firebase-auth/public_api.ts
new file mode 100644
index 0000000000..205dea594d
--- /dev/null
+++ b/src/framework/firebase-auth/public_api.ts
@@ -0,0 +1,15 @@
+/*
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+
+export * from './strategies/base/firebase-base.strategy';
+export * from './strategies/password/firebase-password.strategy';
+export * from './strategies/password/firebase-password-strategy.options';
+export * from './strategies/base/firebase-identity-provider-strategy.options';
+export * from './strategies/google/firebase-google.strategy';
+export * from './strategies/facebook/firebase-facebook.strategy';
+export * from './strategies/twitter/firebase-twitter.strategy';
+export * from './firebase-auth.module';
diff --git a/src/framework/firebase-auth/strategies/base/firebase-base.strategy.ts b/src/framework/firebase-auth/strategies/base/firebase-base.strategy.ts
new file mode 100644
index 0000000000..b9340824f4
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/base/firebase-base.strategy.ts
@@ -0,0 +1,87 @@
+/*
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { Injectable } from '@angular/core';
+import { AngularFireAuth } from '@angular/fire/auth';
+import { Observable, of as observableOf, from } from 'rxjs';
+import { catchError, map } from 'rxjs/operators';
+import { NbAuthResult, NbAuthIllegalTokenError, NbAuthStrategy } from '@nebular/auth';
+
+import UserCredential = firebase.auth.UserCredential;
+
+
+@Injectable()
+export abstract class NbFirebaseBaseStrategy extends NbAuthStrategy {
+
+ constructor(protected afAuth: AngularFireAuth) {
+ super();
+ }
+
+ logout(): Observable {
+ const module = 'logout';
+ return from(this.afAuth.signOut())
+ .pipe(
+ map(() => {
+ return new NbAuthResult(
+ true,
+ null,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption(`${module}.defaultMessages`),
+ )
+ }),
+ catchError((error) => this.processFailure(error, module)),
+ );
+ }
+
+ register(data?: any): Observable {
+ throw new Error(`'register' is not supported by '${this.constructor.name}', use 'authenticate'.`);
+ }
+
+ requestPassword(data?: any): Observable {
+ throw new Error(`'requestPassword' is not supported by '${this.constructor.name}', use 'authenticate'.`);
+ }
+
+ resetPassword(data: any = {}): Observable {
+ throw new Error(`'resetPassword' is not supported by '${this.constructor.name}', use 'authenticate'.`);
+ }
+
+ refreshToken(data: any = {}): Observable {
+ throw new Error(`'refreshToken' is not supported by '${this.constructor.name}', use 'authenticate'.`);
+ }
+
+ protected processFailure(error: any, module: string): Observable {
+ const errorMessages = [];
+
+ if (error instanceof NbAuthIllegalTokenError) {
+ errorMessages.push(error.message)
+ } else {
+ errorMessages.push(this.getOption('errors.getter')(module, error, this.options));
+ }
+
+ return observableOf(new NbAuthResult(
+ false,
+ error,
+ this.getOption(`${module}.redirect.failure`),
+ errorMessages,
+ [],
+ ));
+ }
+
+ protected processSuccess(res: UserCredential | null, module: string): Observable {
+ return this.afAuth.idToken
+ .pipe(map(token => {
+ return new NbAuthResult(
+ true,
+ res,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption('messages.getter')(module, res, this.options),
+ this.createToken(token),
+ );
+ }));
+ }
+}
diff --git a/src/framework/firebase-auth/strategies/base/firebase-identity-provider-strategy.options.ts b/src/framework/firebase-auth/strategies/base/firebase-identity-provider-strategy.options.ts
new file mode 100644
index 0000000000..d72235981e
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/base/firebase-identity-provider-strategy.options.ts
@@ -0,0 +1,46 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import {
+ NbPasswordStrategyMessage,
+ NbPasswordStrategyModule,
+ NbAuthJWTToken,
+ NbAuthStrategyOptions,
+} from '@nebular/auth';
+
+export class NbFirebaseIdentityProviderStrategyOptions extends NbAuthStrategyOptions {
+ token? = {
+ class: NbAuthJWTToken,
+ };
+ logout?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully logged out.'],
+ };
+ authenticate?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully authenticated.'],
+ };
+ errors?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebaseIdentityProviderStrategyOptions) => options[module].defaultErrors,
+ };
+ messages?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebaseIdentityProviderStrategyOptions) => {
+ return options[module].defaultMessages;
+ },
+ };
+ scopes?: string[] = [];
+ customParameters?: { [key: string]: string } = {};
+};
diff --git a/src/framework/firebase-auth/strategies/facebook/firebase-facebook.strategy.ts b/src/framework/firebase-auth/strategies/facebook/firebase-facebook.strategy.ts
new file mode 100644
index 0000000000..886c34a734
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/facebook/firebase-facebook.strategy.ts
@@ -0,0 +1,42 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+
+import { Injectable } from '@angular/core';
+import { NbAuthResult, NbAuthStrategyClass, NbAuthStrategyOptions } from '@nebular/auth';
+import { from, Observable } from 'rxjs';
+import { catchError, switchMap } from 'rxjs/operators';
+
+import { NbFirebaseBaseStrategy } from '../base/firebase-base.strategy';
+import { NbFirebaseIdentityProviderStrategyOptions } from '../base/firebase-identity-provider-strategy.options';
+
+import * as firebase from 'firebase/app';
+import 'firebase/auth';
+
+
+@Injectable()
+export class NbFirebaseFacebookStrategy extends NbFirebaseBaseStrategy {
+
+ protected defaultOptions: NbFirebaseIdentityProviderStrategyOptions = new NbFirebaseIdentityProviderStrategyOptions();
+
+ static setup(options: NbFirebaseIdentityProviderStrategyOptions): [NbAuthStrategyClass, NbAuthStrategyOptions] {
+ return [NbFirebaseFacebookStrategy, options];
+ }
+
+ authenticate(data?: any): Observable {
+ const module = 'authenticate';
+ const provider = new firebase.auth.FacebookAuthProvider();
+ const scopes = this.getOption('scopes');
+ scopes.forEach((scope) => provider.addScope(scope));
+ provider.setCustomParameters(this.getOption('customParameters'));
+
+ return from(this.afAuth.signInWithPopup(provider))
+ .pipe(
+ switchMap((res) => this.processSuccess(res, module)),
+ catchError(error => this.processFailure(error, module)),
+ );
+ }
+}
diff --git a/src/framework/firebase-auth/strategies/google/firebase-google.strategy.ts b/src/framework/firebase-auth/strategies/google/firebase-google.strategy.ts
new file mode 100644
index 0000000000..d7c5b72f1a
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/google/firebase-google.strategy.ts
@@ -0,0 +1,40 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { Injectable } from '@angular/core';
+import { from, Observable } from 'rxjs';
+import { catchError, switchMap } from 'rxjs/operators';
+import { NbAuthStrategyClass, NbAuthResult, NbAuthStrategyOptions } from '@nebular/auth';
+
+import { NbFirebaseBaseStrategy } from '../base/firebase-base.strategy';
+import { NbFirebaseIdentityProviderStrategyOptions } from '../base/firebase-identity-provider-strategy.options';
+
+import * as firebase from 'firebase/app';
+import 'firebase/auth';
+
+@Injectable()
+export class NbFirebaseGoogleStrategy extends NbFirebaseBaseStrategy {
+
+ protected defaultOptions: NbFirebaseIdentityProviderStrategyOptions = new NbFirebaseIdentityProviderStrategyOptions();
+
+ static setup(options: NbFirebaseIdentityProviderStrategyOptions): [NbAuthStrategyClass, NbAuthStrategyOptions] {
+ return [NbFirebaseGoogleStrategy, options];
+ }
+
+ authenticate(data?: any): Observable {
+ const module = 'authenticate';
+ const provider = new firebase.auth.GoogleAuthProvider();
+ const scopes = this.getOption('scopes');
+ scopes.forEach((scope) => provider.addScope(scope));
+ provider.setCustomParameters(this.getOption('customParameters'));
+
+ return from(this.afAuth.signInWithPopup(provider))
+ .pipe(
+ switchMap((res) => this.processSuccess(res, module)),
+ catchError(error => this.processFailure(error, module)),
+ );
+ }
+}
diff --git a/src/framework/firebase-auth/strategies/password/firebase-password-strategy.options.ts b/src/framework/firebase-auth/strategies/password/firebase-password-strategy.options.ts
new file mode 100644
index 0000000000..553ca1446c
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/password/firebase-password-strategy.options.ts
@@ -0,0 +1,86 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import {
+ getDeepFromObject,
+ NbAuthJWTToken,
+ NbAuthStrategyOptions,
+ NbPasswordStrategyMessage,
+ NbPasswordStrategyModule,
+} from '@nebular/auth';
+
+export class NbFirebasePasswordStrategyOptions extends NbAuthStrategyOptions {
+ token? = {
+ class: NbAuthJWTToken,
+ };
+ register?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully registered.'],
+ };
+ login?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Login/Email combination is not correct, please try again.'],
+ defaultMessages: ['You have been successfully logged in.'],
+ };
+ logout?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['You have been successfully logged out.'],
+ };
+ refreshToken?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: null,
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Your token has been successfully refreshed.'],
+ };
+ requestPassword?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Reset password instructions have been sent to your email.'],
+ };
+ resetPassword?: boolean | NbPasswordStrategyModule = {
+ redirect: {
+ success: '/',
+ failure: null,
+ },
+ defaultErrors: ['Something went wrong, please try again.'],
+ defaultMessages: ['Your password has been successfully changed.'],
+ };
+ errors?: NbPasswordStrategyMessage = {
+ key: 'message',
+ getter: (module: string, res, options: NbFirebasePasswordStrategyOptions) => getDeepFromObject(
+ res,
+ options.errors.key,
+ options[module].defaultErrors,
+ ),
+ };
+ messages?: NbPasswordStrategyMessage = {
+ key: 'messages',
+ getter: (module: string, res, options: NbFirebasePasswordStrategyOptions) => getDeepFromObject(
+ res.body,
+ options.messages.key,
+ options[module].defaultMessages,
+ ),
+ };
+}
+
+// tslint:disable-next-line:max-line-length
+export const firebasePasswordStrategyOptions: NbFirebasePasswordStrategyOptions = new NbFirebasePasswordStrategyOptions();
diff --git a/src/framework/firebase-auth/strategies/password/firebase-password.strategy.ts b/src/framework/firebase-auth/strategies/password/firebase-password.strategy.ts
new file mode 100644
index 0000000000..48c6570465
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/password/firebase-password.strategy.ts
@@ -0,0 +1,133 @@
+/*
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { Injectable } from '@angular/core';
+import { User } from 'firebase';
+import { Observable, of as observableOf, from } from 'rxjs';
+import { catchError, map, switchMap, take } from 'rxjs/operators';
+import { NbAuthStrategyOptions, NbAuthStrategyClass, NbAuthResult } from '@nebular/auth';
+
+import { NbFirebaseBaseStrategy } from '../base/firebase-base.strategy';
+import {
+ firebasePasswordStrategyOptions,
+ NbFirebasePasswordStrategyOptions,
+} from './firebase-password-strategy.options';
+
+
+@Injectable()
+export class NbFirebasePasswordStrategy extends NbFirebaseBaseStrategy {
+
+ protected defaultOptions: NbFirebasePasswordStrategyOptions = firebasePasswordStrategyOptions;
+
+ static setup(options: NbFirebasePasswordStrategyOptions): [NbAuthStrategyClass, NbAuthStrategyOptions] {
+ return [NbFirebasePasswordStrategy, options];
+ }
+
+ authenticate({ email, password }: any): Observable {
+ const module = 'login';
+ return from(this.afAuth.signInWithEmailAndPassword(email, password))
+ .pipe(
+ switchMap((res) => this.processSuccess(res, module)),
+ catchError((error) => this.processFailure(error, module)),
+ );
+ }
+
+ refreshToken(data?: any): Observable {
+ const module = 'refreshToken';
+ return this.afAuth.authState
+ .pipe(
+ take(1),
+ switchMap(user => {
+ if (user == null) {
+ return observableOf(new NbAuthResult(
+ false,
+ null,
+ this.getOption(`${module}.redirect.failure`),
+ ['There is no logged in user so refresh of id token isn\'t possible'],
+ ));
+ }
+ return this.refreshIdToken(user, module);
+ }),
+ );
+ }
+
+ register({ email, password }: any): Observable {
+ const module = 'register';
+ return from(this.afAuth.createUserWithEmailAndPassword(email, password))
+ .pipe(
+ switchMap((res) => this.processSuccess(res, module)),
+ catchError((error) => this.processFailure(error, module)),
+ );
+ }
+
+ requestPassword({ email }: any): Observable {
+ const module = 'requestPassword';
+ return from(this.afAuth.sendPasswordResetEmail(email))
+ .pipe(
+ map(() => {
+ return new NbAuthResult(
+ true,
+ null,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption(`${module}.defaultMessages`),
+ );
+ }),
+ catchError((error) => this.processFailure(error, module)),
+ );
+ }
+
+ resetPassword({ code, password }): Observable {
+ const module = 'resetPassword';
+ return from(this.afAuth.confirmPasswordReset(code, password))
+ .pipe(
+ map(() => {
+ return new NbAuthResult(
+ true,
+ null,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption(`${module}.defaultMessages`),
+ );
+ }),
+ catchError((error) => this.processFailure(error, module)),
+ );
+ }
+
+ protected updatePassword(user, password, module) {
+ return from(user.updatePassword(password))
+ .pipe(
+ map(token => {
+ return new NbAuthResult(
+ true,
+ null,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption(`${module}.defaultMessages`),
+ this.createToken(token),
+ );
+ }),
+ catchError(error => this.processFailure(error, module)),
+ );
+ }
+
+ protected refreshIdToken(user: User, module): Observable {
+ return from(user.getIdToken(true))
+ .pipe(
+ map(token => {
+ return new NbAuthResult(
+ true,
+ null,
+ this.getOption(`${module}.redirect.success`),
+ [],
+ this.getOption(`${module}.defaultMessages`),
+ this.createToken(token),
+ );
+ }),
+ catchError(error => this.processFailure(error, module)),
+ );
+ }
+}
diff --git a/src/framework/firebase-auth/strategies/twitter/firebase-twitter.strategy.ts b/src/framework/firebase-auth/strategies/twitter/firebase-twitter.strategy.ts
new file mode 100644
index 0000000000..365c9c501b
--- /dev/null
+++ b/src/framework/firebase-auth/strategies/twitter/firebase-twitter.strategy.ts
@@ -0,0 +1,38 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { Injectable } from '@angular/core';
+import { Observable, from } from 'rxjs';
+import { catchError, switchMap } from 'rxjs/operators';
+import { NbAuthStrategyClass, NbAuthResult, NbAuthStrategyOptions } from '@nebular/auth';
+
+import { NbFirebaseBaseStrategy } from '../base/firebase-base.strategy';
+import { NbFirebaseIdentityProviderStrategyOptions } from '../base/firebase-identity-provider-strategy.options';
+
+import * as firebase from 'firebase/app';
+import 'firebase/auth';
+
+@Injectable()
+export class NbFirebaseTwitteStrategy extends NbFirebaseBaseStrategy {
+
+ protected defaultOptions: NbFirebaseIdentityProviderStrategyOptions = new NbFirebaseIdentityProviderStrategyOptions();
+
+ static setup(options: NbFirebaseIdentityProviderStrategyOptions): [NbAuthStrategyClass, NbAuthStrategyOptions] {
+ return [NbFirebaseTwitteStrategy, options];
+ }
+
+ authenticate(data?: any): Observable {
+ const module = 'authenticate';
+ const provider = new firebase.auth.TwitterAuthProvider();
+ provider.setCustomParameters(this.getOption('customParameters'));
+
+ return from(this.afAuth.signInWithPopup(provider))
+ .pipe(
+ switchMap((res) => this.processSuccess(res, module)),
+ catchError(error => this.processFailure(error, module)),
+ );
+ }
+}
diff --git a/src/playground/without-layout/firebase/firebase-api.service.ts b/src/playground/without-layout/firebase/firebase-api.service.ts
new file mode 100644
index 0000000000..02a8adfa5c
--- /dev/null
+++ b/src/playground/without-layout/firebase/firebase-api.service.ts
@@ -0,0 +1,12 @@
+import { Injectable } from '@angular/core';
+import { AngularFireDatabase } from '@angular/fire/database';
+
+@Injectable()
+export class FirebaseAPIService {
+
+ constructor(private db: AngularFireDatabase) { }
+
+ getGreeting() {
+ return this.db.object('/greeting/').valueChanges();
+ }
+}
diff --git a/src/playground/without-layout/firebase/firebase-playground.component.ts b/src/playground/without-layout/firebase/firebase-playground.component.ts
new file mode 100644
index 0000000000..cfd2315915
--- /dev/null
+++ b/src/playground/without-layout/firebase/firebase-playground.component.ts
@@ -0,0 +1,16 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'nb-firebase-playground',
+ template: `
+
+ `,
+})
+export class FirebasePlaygroundComponent {
+}
diff --git a/src/playground/without-layout/firebase/firebase-routing.module.ts b/src/playground/without-layout/firebase/firebase-routing.module.ts
new file mode 100644
index 0000000000..6db5319b04
--- /dev/null
+++ b/src/playground/without-layout/firebase/firebase-routing.module.ts
@@ -0,0 +1,79 @@
+/**
+ * @license
+ * Copyright Akveo. All Rights Reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ */
+
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+import {
+ NbAuthComponent,
+ NbLoginComponent,
+ NbLogoutComponent,
+ NbRegisterComponent,
+ NbRequestPasswordComponent,
+ NbResetPasswordComponent,
+} from '@nebular/auth';
+
+import { FirebasePlaygroundComponent } from './firebase-playground.component';
+import { PasswordAuthShowcaseComponent } from './password-auth-showcase/password-auth-showcase.component';
+import {
+ IdentityProvidersAuthShowcaseComponent,
+} from './identity-proders-auth-showcase/identity-providers-auth-showcase.component';
+
+
+export const routes: Routes = [
+ {
+ path: '',
+ component: FirebasePlaygroundComponent,
+ children: [
+ {
+ path: '',
+ component: NbAuthComponent,
+ children: [
+ {
+ path: '',
+ redirectTo: 'login',
+ pathMatch: 'full',
+ },
+ {
+ path: 'login',
+ component: NbLoginComponent,
+ },
+ {
+ path: 'register',
+ component: NbRegisterComponent,
+ },
+ {
+ path: 'logout',
+ component: NbLogoutComponent,
+ },
+ {
+ path: 'request-password',
+ component: NbRequestPasswordComponent,
+ },
+ {
+ path: 'reset-password',
+ component: NbResetPasswordComponent,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ path: 'password-showcase',
+ component: PasswordAuthShowcaseComponent,
+ },
+ {
+ path: 'social-auth-showcase',
+ component: IdentityProvidersAuthShowcaseComponent,
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class FirebasePlaygroundRoutingModule {
+}
diff --git a/src/playground/without-layout/firebase/firebase.module.ts b/src/playground/without-layout/firebase/firebase.module.ts
new file mode 100644
index 0000000000..9e24ffae9e
--- /dev/null
+++ b/src/playground/without-layout/firebase/firebase.module.ts
@@ -0,0 +1,117 @@
+import { CommonModule } from '@angular/common';
+import { NgModule } from '@angular/core';
+import { AngularFireModule } from '@angular/fire';
+import { AngularFireAuthModule } from '@angular/fire/auth';
+import { AngularFireDatabaseModule } from '@angular/fire/database';
+import { NbAuthModule } from '@nebular/auth';
+import { NbFirebaseAuthModule, NbFirebasePasswordStrategy, NbFirebaseGoogleStrategy } from '@nebular/firebase-auth';
+
+import { FirebaseAPIService } from './firebase-api.service';
+import { FirebasePlaygroundComponent } from './firebase-playground.component';
+import { FirebasePlaygroundRoutingModule } from './firebase-routing.module';
+import {
+ IdentityProvidersAuthShowcaseComponent,
+} from './identity-proders-auth-showcase/identity-providers-auth-showcase.component';
+import { PasswordAuthShowcaseComponent } from './password-auth-showcase/password-auth-showcase.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ AngularFireModule.initializeApp({
+ apiKey: 'AIzaSyBEvySH74-sISCTkCC6lXUd3zzYj26GjRk',
+ authDomain: 'auth-sample-f48f1.firebaseapp.com',
+ databaseURL: 'https://auth-sample-f48f1.firebaseio.com',
+ projectId: 'auth-sample-f48f1',
+ storageBucket: 'auth-sample-f48f1.appspot.com',
+ messagingSenderId: '246754092661',
+ appId: '1:246754092661:web:c2606b9ecdbed579673a3c',
+ }),
+ AngularFireAuthModule,
+ AngularFireDatabaseModule,
+ FirebasePlaygroundRoutingModule,
+ NbFirebaseAuthModule,
+ NbAuthModule.forRoot({
+ forms: {
+ login: {
+ strategy: 'password',
+ rememberMe: true,
+ socialLinks: [],
+ },
+ register: {
+ strategy: 'password',
+ terms: true,
+ socialLinks: [],
+ },
+ logout: {
+ strategy: 'password',
+ },
+ requestPassword: {
+ strategy: 'password',
+ socialLinks: [],
+ },
+ resetPassword: {
+ strategy: 'password',
+ socialLinks: [],
+ },
+ validation: {
+ password: {
+ required: true,
+ minLength: 6,
+ maxLength: 50,
+ },
+ email: {
+ required: true,
+ },
+ fullName: {
+ required: false,
+ minLength: 4,
+ maxLength: 50,
+ },
+ },
+ },
+ strategies: [
+ NbFirebasePasswordStrategy.setup({
+ name: 'password',
+ login: {
+ redirect: {
+ success: 'example/firebase/password-showcase',
+ },
+ },
+ register: {
+ redirect: {
+ success: 'example/firebase/password-showcase',
+ },
+ },
+ logout: {
+ redirect: {
+ success: 'example/firebase/login',
+ },
+ },
+ requestPassword: {
+ redirect: {
+ success: 'example/firebase/login',
+ },
+ },
+ resetPassword: {
+ redirect: {
+ success: 'example/firebase/login',
+ },
+ },
+ }),
+ NbFirebaseGoogleStrategy.setup({
+ name: 'google',
+ }),
+ ],
+ }),
+ ],
+ declarations: [
+ FirebasePlaygroundComponent,
+ PasswordAuthShowcaseComponent,
+ IdentityProvidersAuthShowcaseComponent,
+ ],
+ providers: [
+ FirebaseAPIService,
+ ],
+})
+export class FirebasePlaygroundModule {
+}
diff --git a/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.html b/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.html
new file mode 100644
index 0000000000..bbb3fb6e2a
--- /dev/null
+++ b/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.html
@@ -0,0 +1,25 @@
+Authenticated: {{ isAuthenticated$ | async }}
+
+
+ Current User Token:
+
{{ userToken$ | async | json }}
+
+
+
+ Data from backend
+
{{ data$ | async | json }}
+
+
+
+ Logout
+
+
+
+ Login with google
+
+
+Get data from Firebase
diff --git a/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.scss b/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.ts b/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.ts
new file mode 100644
index 0000000000..78681a8db9
--- /dev/null
+++ b/src/playground/without-layout/firebase/identity-proders-auth-showcase/identity-providers-auth-showcase.component.ts
@@ -0,0 +1,47 @@
+import { Component } from '@angular/core';
+import { Observable, of } from 'rxjs';
+import { catchError, share, take } from 'rxjs/operators';
+import { NbAuthResult, NbAuthService, NbAuthToken } from '@nebular/auth';
+
+import { FirebaseAPIService } from '../firebase-api.service';
+
+@Component({
+ selector: 'app-google-auth-showcase',
+ templateUrl: './identity-providers-auth-showcase.component.html',
+ styleUrls: ['./identity-providers-auth-showcase.component.scss'],
+})
+export class IdentityProvidersAuthShowcaseComponent {
+
+ userToken$: Observable;
+ isAuthenticated$: Observable;
+ data$: Observable;
+
+ constructor(
+ private firebaseApi: FirebaseAPIService,
+ private authService: NbAuthService,
+ ) {
+ this.userToken$ = this.authService.onTokenChange();
+ this.isAuthenticated$ = this.authService.onAuthenticationChange();
+ }
+
+ logout() {
+ this.authService.logout('google')
+ .pipe(take(1))
+ .subscribe((authResult: NbAuthResult) => {});
+ }
+
+ loginWithGoogle() {
+ this.authService.authenticate('google')
+ .pipe(take(1))
+ .subscribe((authResult: NbAuthResult) => {});
+ }
+
+ getData() {
+ this.data$ = this.firebaseApi.getGreeting()
+ .pipe(
+ take(1),
+ catchError((error) => of(error)),
+ share(),
+ );
+ }
+}
diff --git a/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.html b/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.html
new file mode 100644
index 0000000000..726740315b
--- /dev/null
+++ b/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.html
@@ -0,0 +1,27 @@
+Authenticated: {{ isAuthenticated$ | async }}
+
+
+ Current User Token:
+
{{ userToken$ | async | json }}
+
+
+
+ Data from backend
+
{{ data$ | async | json }}
+
+
+
+ Logout
+
+
+
+ Login
+
+
+Reset password
+
+Get data from Firebase
diff --git a/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.scss b/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.ts b/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.ts
new file mode 100644
index 0000000000..50d680e257
--- /dev/null
+++ b/src/playground/without-layout/firebase/password-auth-showcase/password-auth-showcase.component.ts
@@ -0,0 +1,50 @@
+import { Component } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { Observable, of } from 'rxjs';
+import { catchError, share, take } from 'rxjs/operators';
+import { NbAuthService, NbAuthToken } from '@nebular/auth';
+
+import { FirebaseAPIService } from '../firebase-api.service';
+
+@Component({
+ selector: 'nb-password-auth-showcase',
+ templateUrl: './password-auth-showcase.component.html',
+ styleUrls: ['./password-auth-showcase.component.scss'],
+})
+export class PasswordAuthShowcaseComponent {
+
+ userToken$: Observable;
+ isAuthenticated$: Observable;
+ data$: Observable;
+
+ constructor(
+ private authService: NbAuthService,
+ private router: Router,
+ private firebaseApi: FirebaseAPIService,
+ private route: ActivatedRoute,
+ ) {
+ this.userToken$ = this.authService.onTokenChange();
+ this.isAuthenticated$ = this.authService.isAuthenticated();
+ }
+
+ logout() {
+ this.router.navigate(['../logout'], { relativeTo: this.route });
+ }
+
+ login() {
+ this.router.navigate(['../login'], { relativeTo: this.route });
+ }
+
+ resetPassword() {
+ this.router.navigate(['../reset-password'], { relativeTo: this.route });
+ }
+
+ getData() {
+ this.data$ = this.firebaseApi.getGreeting()
+ .pipe(
+ take(1),
+ catchError((error) => of(error)),
+ share(),
+ );
+ }
+}
diff --git a/src/playground/without-layout/without-layout-routing.module.ts b/src/playground/without-layout/without-layout-routing.module.ts
index a45d2a9ac3..43d35da7c3 100644
--- a/src/playground/without-layout/without-layout-routing.module.ts
+++ b/src/playground/without-layout/without-layout-routing.module.ts
@@ -49,6 +49,10 @@ const routes: Route[] = [
path: 'auth',
loadChildren: () => import('./auth/auth.module').then(m => m.AuthPlaygroundModule),
},
+ {
+ path: 'firebase',
+ loadChildren: () => import('./firebase/firebase.module').then(m => m.FirebasePlaygroundModule),
+ },
{
path: 'smart-home',
loadChildren: () => import('./smart-home/app.module').then(m => m.AppModule),
diff --git a/tsconfig.publish.json b/tsconfig.publish.json
index a7c49fbbbb..50cb76ee20 100644
--- a/tsconfig.publish.json
+++ b/tsconfig.publish.json
@@ -18,7 +18,8 @@
"importHelpers": true,
"baseUrl": ".",
"paths": {
- "@nebular/theme": ["./src/.lib/theme"]
+ "@nebular/theme": ["./src/.lib/theme"],
+ "@nebular/auth": ["./src/.lib/auth"]
},
"skipLibCheck": true,
"typeRoots": [