@@ -20,18 +20,26 @@ import * as fs from 'fs';
20
20
import { FirebaseApp , FirebaseOptions } from '@firebase/app-types' ;
21
21
import { base64 } from '@firebase/util' ;
22
22
23
+ /** The default url for the local database emulator. */
23
24
const DBURL = 'http://localhost:9000' ;
24
-
25
- class FakeCredentials {
26
- getAccessToken ( ) {
27
- return Promise . resolve ( {
28
- expires_in : 1000000 ,
29
- access_token : 'owner'
30
- } ) ;
31
- }
32
- getCertificate ( ) {
33
- return null ;
34
- }
25
+ /** Passing this in tells the emulator to treat you as an admin. */
26
+ const ADMIN_TOKEN = 'owner' ;
27
+ /** Create an unsecured JWT for the given auth payload. See https://tools.ietf.org/html/rfc7519#section-6. */
28
+ function createUnsecuredJwt ( auth : object ) : string {
29
+ // Unsecured JWTs use "none" as the algorithm.
30
+ const header = {
31
+ alg : 'none' ,
32
+ kid : 'fakekid'
33
+ } ;
34
+ // Ensure that the auth payload has a value for 'iat'.
35
+ ( auth as any ) . iat = ( auth as any ) . iat || 0 ;
36
+ // Unsecured JWTs use the empty string as a signature.
37
+ const signature = '' ;
38
+ return [
39
+ base64 . encodeString ( JSON . stringify ( header ) , /*webSafe=*/ false ) ,
40
+ base64 . encodeString ( JSON . stringify ( auth ) , /*webSafe=*/ false ) ,
41
+ signature
42
+ ] . join ( '.' ) ;
35
43
}
36
44
37
45
export function apps ( ) : ( FirebaseApp | null ) [ ] {
@@ -41,41 +49,56 @@ export function apps(): (FirebaseApp | null)[] {
41
49
export type AppOptions = {
42
50
databaseName ?: string ;
43
51
projectId ?: string ;
44
- auth : object ;
52
+ auth ? : object ;
45
53
} ;
54
+ /** Construct a FirebaseApp authenticated with options.auth. */
46
55
export function initializeTestApp ( options : AppOptions ) : FirebaseApp {
47
- let appOptions : FirebaseOptions ;
48
- if ( 'databaseName' in options ) {
56
+ return initializeApp (
57
+ options . auth ? createUnsecuredJwt ( options . auth ) : null ,
58
+ options . databaseName ,
59
+ options . projectId
60
+ ) ;
61
+ }
62
+
63
+ export type AdminAppOptions = {
64
+ databaseName ?: string ;
65
+ projectId ?: string ;
66
+ } ;
67
+ /** Construct a FirebaseApp authenticated as an admin user. */
68
+ export function initializeAdminApp ( options : AdminAppOptions ) : FirebaseApp {
69
+ return initializeApp ( ADMIN_TOKEN , options . databaseName , options . projectId ) ;
70
+ }
71
+
72
+ function initializeApp (
73
+ accessToken ?: string ,
74
+ databaseName ?: string ,
75
+ projectId ?: string
76
+ ) : FirebaseApp {
77
+ let appOptions : FirebaseOptions = { } ;
78
+ if ( databaseName ) {
49
79
appOptions = {
50
- databaseURL : DBURL + '?ns=' + options . databaseName
80
+ databaseURL : DBURL + '?ns=' + databaseName
51
81
} ;
52
- } else if ( ' projectId' in options ) {
82
+ } else if ( projectId ) {
53
83
appOptions = {
54
- projectId : options . projectId
84
+ projectId : projectId
55
85
} ;
56
86
} else {
57
87
throw new Error ( 'neither databaseName or projectId were specified' ) ;
58
88
}
59
- const header = {
60
- alg : 'RS256' ,
61
- kid : 'fakekid'
62
- } ;
63
- const fakeToken = [
64
- base64 . encodeString ( JSON . stringify ( header ) , /*webSafe=*/ false ) ,
65
- base64 . encodeString ( JSON . stringify ( options . auth ) , /*webSafe=*/ false ) ,
66
- 'fakesignature'
67
- ] . join ( '.' ) ;
68
89
const appName = 'app-' + new Date ( ) . getTime ( ) + '-' + Math . random ( ) ;
69
- const app = firebase . initializeApp ( appOptions , appName ) ;
90
+ let app = firebase . initializeApp ( appOptions , appName ) ;
70
91
// hijacking INTERNAL.getToken to bypass FirebaseAuth and allows specifying of auth headers
71
- ( app as any ) . INTERNAL . getToken = ( ) =>
72
- Promise . resolve ( { accessToken : fakeToken } ) ;
92
+ if ( accessToken ) {
93
+ ( app as any ) . INTERNAL . getToken = ( ) =>
94
+ Promise . resolve ( { accessToken : accessToken } ) ;
95
+ }
73
96
return app ;
74
97
}
75
98
76
99
export type LoadDatabaseRulesOptions = {
77
- databaseName : String ;
78
- rules : String ;
100
+ databaseName : string ;
101
+ rules : string ;
79
102
rulesPath : fs . PathLike ;
80
103
} ;
81
104
export function loadDatabaseRules ( options : LoadDatabaseRulesOptions ) : void {
0 commit comments