@stevenkellner/team-conduct-api 2.0.17 → 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/src/functions/fine/add.d.ts +3 -8
- package/lib/src/functions/fine/add.js +1 -2
- package/lib/src/functions/fine/delete.d.ts +1 -6
- package/lib/src/functions/fine/delete.js +2 -3
- package/lib/src/functions/fine/update.d.ts +2 -8
- package/lib/src/functions/fine/update.js +1 -3
- package/lib/src/functions/fineTemplate/add.d.ts +3 -3
- package/lib/src/functions/fineTemplate/update.d.ts +3 -3
- package/lib/src/functions/firebaseFunctionsContext.d.ts +34 -1
- package/lib/src/functions/firebaseFunctionsContext.js +33 -33
- package/lib/src/functions/index.d.ts +10 -8
- package/lib/src/functions/index.js +11 -8
- package/lib/src/functions/notification/markNotificationAsRead.d.ts +14 -0
- package/lib/src/functions/notification/{subscribe.js → markNotificationAsRead.js} +5 -7
- package/lib/src/functions/person/kickout.d.ts +6 -6
- package/lib/src/functions/person/kickout.js +4 -4
- package/lib/src/functions/person/roleEdit.d.ts +5 -5
- package/lib/src/functions/person/roleEdit.js +3 -3
- package/lib/src/functions/{paypalMe/edit.d.ts → team/delete.d.ts} +5 -7
- package/lib/src/functions/{paypalMe/edit.js → team/delete.js} +4 -5
- package/lib/src/functions/team/new.d.ts +18 -18
- package/lib/src/functions/team/new.js +8 -4
- package/lib/src/functions/team/update.d.ts +34 -0
- package/lib/src/functions/team/update.js +23 -0
- package/lib/src/functions/user/register.d.ts +4 -0
- package/lib/src/functions/user/register.js +3 -1
- package/lib/src/functions/user/update.d.ts +26 -0
- package/lib/src/functions/user/update.js +15 -0
- package/lib/src/index.d.ts +1 -1
- package/lib/src/index.js +1 -1
- package/lib/src/locales/de.d.ts +1 -1
- package/lib/src/locales/de.js +6 -2
- package/lib/src/locales/en.d.ts +6 -2
- package/lib/src/locales/en.js +6 -2
- package/lib/src/types/{MoneyAmount.d.ts → Money.d.ts} +23 -23
- package/lib/src/types/{MoneyAmount.js → Money.js} +25 -25
- package/lib/src/types/fine/Fine.d.ts +275 -0
- package/lib/src/types/fine/Fine.js +318 -0
- package/lib/src/types/fine/FineTemplate.d.ts +154 -0
- package/lib/src/types/fine/FineTemplate.js +170 -0
- package/lib/src/types/{PayedState.d.ts → fine/PayedState.d.ts} +1 -1
- package/lib/src/types/{PayedState.js → fine/PayedState.js} +1 -1
- package/lib/src/types/fine/index.d.ts +3 -0
- package/lib/src/{firebase → types/fine}/index.js +3 -6
- package/lib/src/types/index.d.ts +7 -18
- package/lib/src/types/index.js +7 -18
- package/lib/src/types/{Localization.d.ts → localization/Localization.d.ts} +15 -43
- package/lib/src/types/localization/Localization.js +54 -0
- package/lib/src/types/localization/PluralLocalization.d.ts +23 -0
- package/lib/src/types/localization/PluralLocalization.js +35 -0
- package/lib/src/types/{Pluralization.d.ts → localization/Pluralization.d.ts} +1 -0
- package/lib/src/types/{Pluralization.js → localization/Pluralization.js} +1 -0
- package/lib/src/types/localization/ValueLocalization.d.ts +22 -0
- package/lib/src/types/localization/ValueLocalization.js +41 -0
- package/lib/src/types/localization/index.d.ts +5 -0
- package/lib/src/types/localization/index.js +21 -0
- package/lib/src/types/notification/InAppNotification.d.ts +152 -0
- package/lib/src/types/notification/InAppNotification.js +136 -0
- package/lib/src/types/notification/index.d.ts +1 -0
- package/lib/src/types/notification/index.js +17 -0
- package/lib/src/types/{Person.d.ts → person/Person.d.ts} +3 -3
- package/lib/src/types/{Person.js → person/Person.js} +3 -3
- package/lib/src/types/{PersonProperties.d.ts → person/PersonProperties.d.ts} +8 -7
- package/lib/src/types/{PersonProperties.js → person/PersonProperties.js} +7 -6
- package/lib/src/types/{PersonSignInProperties.d.ts → person/PersonSignInProperties.d.ts} +9 -11
- package/lib/src/types/{PersonSignInProperties.js → person/PersonSignInProperties.js} +7 -10
- package/lib/src/types/person/index.d.ts +3 -0
- package/lib/src/types/person/index.js +19 -0
- package/lib/src/types/{Invitation.d.ts → team/Invitation.d.ts} +1 -1
- package/lib/src/types/{Invitation.js → team/Invitation.js} +1 -1
- package/lib/src/types/team/Team.d.ts +144 -0
- package/lib/src/types/team/Team.js +141 -0
- package/lib/src/types/team/TeamRole.d.ts +30 -0
- package/lib/src/types/{UserRole.js → team/TeamRole.js} +16 -15
- package/lib/src/types/team/index.d.ts +3 -0
- package/lib/src/types/team/index.js +19 -0
- package/lib/src/types/{NotificationProperties.d.ts → user/NotificationProperties.d.ts} +8 -3
- package/lib/src/types/{NotificationProperties.js → user/NotificationProperties.js} +4 -0
- package/lib/src/types/user/User.d.ts +328 -0
- package/lib/src/types/user/User.js +355 -0
- package/lib/src/types/user/index.d.ts +2 -0
- package/lib/src/types/user/index.js +18 -0
- package/lib/src/utils/StaticUnionTypeBuilder.d.ts +9 -0
- package/lib/src/utils/StaticUnionTypeBuilder.js +23 -0
- package/lib/src/utils/index.d.ts +1 -0
- package/lib/src/utils/index.js +17 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/functions/fine/add.ts +3 -5
- package/src/functions/fine/delete.ts +3 -5
- package/src/functions/fine/update.ts +2 -5
- package/src/functions/firebaseFunctionsContext.ts +40 -40
- package/src/functions/index.ts +11 -9
- package/src/functions/notification/markNotificationAsRead.ts +19 -0
- package/src/functions/person/add.ts +1 -1
- package/src/functions/person/kickout.ts +6 -6
- package/src/functions/person/roleEdit.ts +5 -5
- package/src/functions/{paypalMe/edit.ts → team/delete.ts} +5 -7
- package/src/functions/team/new.ts +19 -11
- package/src/functions/team/update.ts +40 -0
- package/src/functions/user/register.ts +7 -3
- package/src/functions/user/update.ts +29 -0
- package/src/index.ts +1 -1
- package/src/locales/de.ts +7 -3
- package/src/locales/en.ts +7 -3
- package/src/types/{MoneyAmount.ts → Money.ts} +29 -29
- package/src/types/fine/Fine.ts +399 -0
- package/src/types/fine/FineTemplate.ts +219 -0
- package/src/types/{PayedState.ts → fine/PayedState.ts} +2 -2
- package/src/types/fine/index.ts +3 -0
- package/src/types/index.ts +7 -18
- package/src/types/{Localization.ts → localization/Localization.ts} +7 -64
- package/src/types/localization/PluralLocalization.ts +32 -0
- package/src/types/{Pluralization.ts → localization/Pluralization.ts} +1 -0
- package/src/types/localization/ValueLocalization.ts +36 -0
- package/src/types/localization/index.ts +5 -0
- package/src/types/notification/InAppNotification.ts +184 -0
- package/src/types/notification/index.ts +1 -0
- package/src/types/{Person.ts → person/Person.ts} +3 -3
- package/src/types/{PersonProperties.ts → person/PersonProperties.ts} +8 -7
- package/src/types/{PersonSignInProperties.ts → person/PersonSignInProperties.ts} +13 -12
- package/src/types/person/index.ts +3 -0
- package/src/types/{Invitation.ts → team/Invitation.ts} +1 -1
- package/src/types/team/Team.ts +204 -0
- package/src/types/{UserRole.ts → team/TeamRole.ts} +19 -17
- package/src/types/team/index.ts +3 -0
- package/src/types/{NotificationProperties.ts → user/NotificationProperties.ts} +12 -3
- package/src/types/user/User.ts +451 -0
- package/src/types/user/index.ts +2 -0
- package/src/utils/StaticUnionTypeBuilder.ts +23 -0
- package/src/utils/index.ts +1 -0
- package/lib/src/firebase/FirebaseConfiguration.d.ts +0 -64
- package/lib/src/firebase/FirebaseConfiguration.js +0 -79
- package/lib/src/firebase/Firestore.d.ts +0 -201
- package/lib/src/firebase/Firestore.js +0 -244
- package/lib/src/firebase/FirestoreScheme.d.ts +0 -42
- package/lib/src/firebase/FirestoreScheme.js +0 -2
- package/lib/src/firebase/Messaging.d.ts +0 -90
- package/lib/src/firebase/Messaging.js +0 -2
- package/lib/src/firebase/checkAuthentication.d.ts +0 -38
- package/lib/src/firebase/checkAuthentication.js +0 -64
- package/lib/src/firebase/index.d.ts +0 -6
- package/lib/src/firebase/pushNotification.d.ts +0 -39
- package/lib/src/firebase/pushNotification.js +0 -88
- package/lib/src/functions/notification/subscribe.d.ts +0 -18
- package/lib/src/types/Configuration.d.ts +0 -46
- package/lib/src/types/Configuration.js +0 -51
- package/lib/src/types/Fine.d.ts +0 -71
- package/lib/src/types/Fine.js +0 -74
- package/lib/src/types/FineAmount.d.ts +0 -207
- package/lib/src/types/FineAmount.js +0 -238
- package/lib/src/types/FineTemplate.d.ts +0 -69
- package/lib/src/types/FineTemplate.js +0 -72
- package/lib/src/types/FineTemplateRepetition.d.ts +0 -87
- package/lib/src/types/FineTemplateRepetition.js +0 -103
- package/lib/src/types/Localization.js +0 -115
- package/lib/src/types/Team.d.ts +0 -62
- package/lib/src/types/Team.js +0 -64
- package/lib/src/types/User.d.ts +0 -221
- package/lib/src/types/User.js +0 -235
- package/lib/src/types/UserRole.d.ts +0 -29
- package/lib/test/firebase/FirebaseConfiguration.test.d.ts +0 -1
- package/lib/test/firebase/FirebaseConfiguration.test.js +0 -158
- package/lib/test/firebase/Firestore.test.d.ts +0 -1
- package/lib/test/firebase/Firestore.test.js +0 -46
- package/lib/test/firebase/checkAuthentication.test.d.ts +0 -1
- package/lib/test/firebase/checkAuthentication.test.js +0 -356
- package/lib/test/firebase/firebase-utils.d.ts +0 -32
- package/lib/test/firebase/firebase-utils.js +0 -134
- package/lib/test/firebase/pushNotification.test.d.ts +0 -1
- package/lib/test/firebase/pushNotification.test.js +0 -300
- package/lib/test/locales/localization.de.test.d.ts +0 -1
- package/lib/test/locales/localization.de.test.js +0 -144
- package/lib/test/locales/localization.en.test.d.ts +0 -1
- package/lib/test/locales/localization.en.test.js +0 -144
- package/lib/test/types/Configuration.test.d.ts +0 -1
- package/lib/test/types/Configuration.test.js +0 -84
- package/lib/test/types/Currency.test.d.ts +0 -1
- package/lib/test/types/Currency.test.js +0 -41
- package/lib/test/types/Fine.test.d.ts +0 -1
- package/lib/test/types/Fine.test.js +0 -265
- package/lib/test/types/FineAmount.test.d.ts +0 -1
- package/lib/test/types/FineAmount.test.js +0 -445
- package/lib/test/types/FineTemplate.test.d.ts +0 -1
- package/lib/test/types/FineTemplate.test.js +0 -271
- package/lib/test/types/FineTemplateRepetition.test.d.ts +0 -1
- package/lib/test/types/FineTemplateRepetition.test.js +0 -361
- package/lib/test/types/Invitation.test.d.ts +0 -1
- package/lib/test/types/Invitation.test.js +0 -269
- package/lib/test/types/Locale.test.d.ts +0 -1
- package/lib/test/types/Locale.test.js +0 -46
- package/lib/test/types/Localization.test.d.ts +0 -1
- package/lib/test/types/Localization.test.js +0 -241
- package/lib/test/types/MoneyAmount.test.d.ts +0 -1
- package/lib/test/types/MoneyAmount.test.js +0 -276
- package/lib/test/types/NotificationProperties.test.d.ts +0 -1
- package/lib/test/types/NotificationProperties.test.js +0 -258
- package/lib/test/types/PayedState.test.d.ts +0 -1
- package/lib/test/types/PayedState.test.js +0 -136
- package/lib/test/types/Person.test.d.ts +0 -1
- package/lib/test/types/Person.test.js +0 -266
- package/lib/test/types/PersonProperties.test.d.ts +0 -1
- package/lib/test/types/PersonProperties.test.js +0 -155
- package/lib/test/types/PersonSignInProperties.test.d.ts +0 -1
- package/lib/test/types/PersonSignInProperties.test.js +0 -208
- package/lib/test/types/Pluralization.test.d.ts +0 -1
- package/lib/test/types/Pluralization.test.js +0 -206
- package/lib/test/types/Team.test.d.ts +0 -1
- package/lib/test/types/Team.test.js +0 -145
- package/lib/test/types/User.test.d.ts +0 -1
- package/lib/test/types/User.test.js +0 -450
- package/lib/test/types/UserRole.test.d.ts +0 -1
- package/lib/test/types/UserRole.test.js +0 -140
- package/src/firebase/FirebaseConfiguration.ts +0 -99
- package/src/firebase/Firestore.ts +0 -258
- package/src/firebase/FirestoreScheme.ts +0 -41
- package/src/firebase/Messaging.ts +0 -93
- package/src/firebase/checkAuthentication.ts +0 -91
- package/src/firebase/index.ts +0 -7
- package/src/firebase/pushNotification.ts +0 -90
- package/src/functions/notification/subscribe.ts +0 -23
- package/src/types/Configuration.ts +0 -65
- package/src/types/Fine.ts +0 -100
- package/src/types/FineAmount.ts +0 -303
- package/src/types/FineTemplate.ts +0 -96
- package/src/types/FineTemplateRepetition.ts +0 -125
- package/src/types/Team.ts +0 -87
- package/src/types/User.ts +0 -302
- /package/lib/src/types/{Locale.d.ts → localization/Locale.d.ts} +0 -0
- /package/lib/src/types/{Locale.js → localization/Locale.js} +0 -0
- /package/src/types/{Locale.ts → localization/Locale.ts} +0 -0
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import { FirestoreScheme } from './FirestoreScheme';
|
|
2
|
-
import { Messaging } from './Messaging';
|
|
3
|
-
import { Firestore as FirebaseFirestore } from 'firebase-admin/firestore';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Singleton configuration manager for Firebase services.
|
|
7
|
-
*
|
|
8
|
-
* Provides centralized access to Firestore document reference and Firebase Cloud Messaging.
|
|
9
|
-
* Must be configured once before accessing services.
|
|
10
|
-
*/
|
|
11
|
-
export class FirebaseConfiguration {
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Singleton instance of FirebaseConfiguration.
|
|
15
|
-
*/
|
|
16
|
-
public static readonly shared = new FirebaseConfiguration();
|
|
17
|
-
|
|
18
|
-
private configured: boolean = false;
|
|
19
|
-
|
|
20
|
-
private _firebaseFirestore: FirebaseFirestore | null = null;
|
|
21
|
-
|
|
22
|
-
private _baseFirestoreDocument: FirestoreScheme | null = null;
|
|
23
|
-
|
|
24
|
-
private _messaging: Messaging | null = null;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Private constructor to enforce singleton pattern.
|
|
28
|
-
*/
|
|
29
|
-
private constructor() {}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Configures the Firebase services.
|
|
33
|
-
*
|
|
34
|
-
* Must be called exactly once before accessing any Firebase services.
|
|
35
|
-
* Subsequent calls will throw an error.
|
|
36
|
-
*
|
|
37
|
-
* @param configuration - Configuration object containing Firestore and Messaging services
|
|
38
|
-
* @throws Error if already configured
|
|
39
|
-
*/
|
|
40
|
-
public configure(configuration: {
|
|
41
|
-
firebaseFirestore: FirebaseFirestore,
|
|
42
|
-
baseFirestoreDocument: FirestoreScheme,
|
|
43
|
-
messaging: Messaging
|
|
44
|
-
}) {
|
|
45
|
-
if (this.configured)
|
|
46
|
-
throw new Error('Configuration is already configured');
|
|
47
|
-
this._firebaseFirestore = configuration.firebaseFirestore;
|
|
48
|
-
this._baseFirestoreDocument = configuration.baseFirestoreDocument;
|
|
49
|
-
this._messaging = configuration.messaging;
|
|
50
|
-
this.configured = true;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Reconfigures the Firebase services.
|
|
55
|
-
*
|
|
56
|
-
* Allows updating the configuration with new services.
|
|
57
|
-
*
|
|
58
|
-
* @param configuration - New configuration object containing Firestore and Messaging services
|
|
59
|
-
*/
|
|
60
|
-
public reconfigure(configuration: {
|
|
61
|
-
firebaseFirestore: FirebaseFirestore,
|
|
62
|
-
baseFirestoreDocument: FirestoreScheme,
|
|
63
|
-
messaging: Messaging
|
|
64
|
-
}) {
|
|
65
|
-
this.configured = false;
|
|
66
|
-
this.configure(configuration);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
public get firebaseFirestore(): FirebaseFirestore {
|
|
70
|
-
if (!this.configured || !this._firebaseFirestore)
|
|
71
|
-
throw new Error('Configuration.firebaseFirestore is not configured');
|
|
72
|
-
return this._firebaseFirestore;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Gets the base Firestore document reference.
|
|
77
|
-
*
|
|
78
|
-
* @returns The configured Firestore document scheme
|
|
79
|
-
* @throws Error if not yet configured
|
|
80
|
-
*/
|
|
81
|
-
public get baseFirestoreDocument(): FirestoreScheme {
|
|
82
|
-
if (!this.configured || !this._baseFirestoreDocument)
|
|
83
|
-
throw new Error('Configuration.baseFirestoreDocument is not configured');
|
|
84
|
-
return this._baseFirestoreDocument;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Gets the Firebase Cloud Messaging service.
|
|
89
|
-
*
|
|
90
|
-
* @returns The configured Messaging service
|
|
91
|
-
* @throws Error if not yet configured
|
|
92
|
-
*/
|
|
93
|
-
public get messaging(): Messaging {
|
|
94
|
-
if (!this.configured || !this._messaging)
|
|
95
|
-
throw new Error('Configuration.messaging is not configured');
|
|
96
|
-
return this._messaging;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import { FirestoreBatch, FirestoreCollection, FirestoreDocument, UserAuthId } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { FirestoreScheme } from './FirestoreScheme';
|
|
3
|
-
import { Fine, FineTemplate, Invitation, Person, User, Team } from '../types';
|
|
4
|
-
import { FirebaseConfiguration } from '.';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Accessor class for Firestore documents and collections.
|
|
8
|
-
*
|
|
9
|
-
* Provides type-safe access to Firestore database documents and collections
|
|
10
|
-
* following the schema defined in {@link FirestoreScheme}.
|
|
11
|
-
*
|
|
12
|
-
* Uses a singleton pattern to ensure consistent access to the Firestore instance.
|
|
13
|
-
* All methods return strongly-typed Firestore references that can be used for
|
|
14
|
-
* database operations.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* // Access a team document
|
|
19
|
-
* const teamDoc = Firestore.shared.team(teamId);
|
|
20
|
-
*
|
|
21
|
-
* // Access a person in a team
|
|
22
|
-
* const personDoc = Firestore.shared.person(teamId, personId);
|
|
23
|
-
*
|
|
24
|
-
* // Access all fines in a team
|
|
25
|
-
* const finesCollection = Firestore.shared.fines(teamId);
|
|
26
|
-
* ```
|
|
27
|
-
*
|
|
28
|
-
* @remarks
|
|
29
|
-
* Requires {@link FirebaseConfiguration} to be configured before use.
|
|
30
|
-
* All document and collection references are lazy and don't perform any
|
|
31
|
-
* database operations until explicitly called.
|
|
32
|
-
*/
|
|
33
|
-
export class Firestore {
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Protected constructor to enforce singleton pattern.
|
|
37
|
-
* Use {@link Firestore.shared} to get an instance.
|
|
38
|
-
*/
|
|
39
|
-
protected constructor() {}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* The singleton instance of the Firestore accessor.
|
|
43
|
-
*
|
|
44
|
-
* @private
|
|
45
|
-
*/
|
|
46
|
-
private static sharedInstance: Firestore | null = null;
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Gets the singleton instance of the Firestore accessor.
|
|
50
|
-
*
|
|
51
|
-
* Creates the instance on first access and returns the same instance
|
|
52
|
-
* on subsequent calls.
|
|
53
|
-
*
|
|
54
|
-
* @returns The singleton Firestore accessor instance
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```typescript
|
|
58
|
-
* const firestore = Firestore.shared;
|
|
59
|
-
* const teamDoc = firestore.team(teamId);
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
public static get shared(): Firestore {
|
|
63
|
-
if (!Firestore.sharedInstance)
|
|
64
|
-
Firestore.sharedInstance = new Firestore();
|
|
65
|
-
return Firestore.sharedInstance;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Gets the base Firestore schema from the configured Firebase instance.
|
|
70
|
-
*
|
|
71
|
-
* Accesses the global FirebaseConfiguration to retrieve the root document
|
|
72
|
-
* reference for all database operations.
|
|
73
|
-
*
|
|
74
|
-
* @returns The base Firestore schema with typed collections
|
|
75
|
-
*
|
|
76
|
-
* @throws {Error} If FirebaseConfiguration has not been configured
|
|
77
|
-
*
|
|
78
|
-
* @private
|
|
79
|
-
*/
|
|
80
|
-
protected get base(): FirestoreScheme {
|
|
81
|
-
return FirebaseConfiguration.shared.baseFirestoreDocument;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
public batch(): FirestoreBatch {
|
|
85
|
-
return new FirestoreBatch(FirebaseConfiguration.shared.firebaseFirestore);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Gets a reference to a team document.
|
|
90
|
-
*
|
|
91
|
-
* @param id - The unique identifier of the team
|
|
92
|
-
* @returns A typed Firestore document reference for the team
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* ```typescript
|
|
96
|
-
* const teamDoc = Firestore.shared.team(teamId);
|
|
97
|
-
* const teamData = await teamDoc.get();
|
|
98
|
-
* ```
|
|
99
|
-
*/
|
|
100
|
-
public team(id: Team.Id): FirestoreDocument<Team> {
|
|
101
|
-
return this.base
|
|
102
|
-
.collection('teams')
|
|
103
|
-
.document(id.guidString) as FirestoreDocument<Team>;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public userAuth(userAuthId: UserAuthId): FirestoreDocument<{ userId: User.Id }> {
|
|
107
|
-
return this.base
|
|
108
|
-
.collection('userAuthIdDict')
|
|
109
|
-
.document(userAuthId.value);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Gets a reference to a user document.
|
|
114
|
-
*
|
|
115
|
-
* @param id - The unique identifier of the user
|
|
116
|
-
* @returns A typed Firestore document reference for the user
|
|
117
|
-
*
|
|
118
|
-
* @example
|
|
119
|
-
* ```typescript
|
|
120
|
-
* const userDoc = Firestore.shared.user(userId);
|
|
121
|
-
* const userData = await userDoc.get();
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
public user(id: User.Id): FirestoreDocument<User> {
|
|
125
|
-
return this.base
|
|
126
|
-
.collection('users')
|
|
127
|
-
.document(id.value);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Gets a reference to an invitation document.
|
|
132
|
-
*
|
|
133
|
-
* @param id - The unique identifier of the invitation
|
|
134
|
-
* @returns A typed Firestore document reference for the invitation
|
|
135
|
-
*
|
|
136
|
-
* @example
|
|
137
|
-
* ```typescript
|
|
138
|
-
* const invitationDoc = Firestore.shared.invitation(invitationId);
|
|
139
|
-
* const invitationData = await invitationDoc.get();
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
public invitation(id: Invitation.Id): FirestoreDocument<Invitation> {
|
|
143
|
-
return this.base
|
|
144
|
-
.collection('invitations')
|
|
145
|
-
.document(id.value);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Gets a reference to the persons collection within a team.
|
|
150
|
-
*
|
|
151
|
-
* @param teamId - The unique identifier of the team
|
|
152
|
-
* @returns A typed Firestore collection reference for persons in the team
|
|
153
|
-
*
|
|
154
|
-
* @example
|
|
155
|
-
* ```typescript
|
|
156
|
-
* const personsCollection = Firestore.shared.persons(teamId);
|
|
157
|
-
* const allPersons = await personsCollection.getAll();
|
|
158
|
-
* ```
|
|
159
|
-
*/
|
|
160
|
-
public persons(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<Person, never>; }> {
|
|
161
|
-
return this.base
|
|
162
|
-
.collection('teams')
|
|
163
|
-
.document(teamId.guidString)
|
|
164
|
-
.collection('persons');
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Gets a reference to a specific person document within a team.
|
|
169
|
-
*
|
|
170
|
-
* @param teamId - The unique identifier of the team
|
|
171
|
-
* @param id - The unique identifier of the person
|
|
172
|
-
* @returns A typed Firestore document reference for the person
|
|
173
|
-
*
|
|
174
|
-
* @example
|
|
175
|
-
* ```typescript
|
|
176
|
-
* const personDoc = Firestore.shared.person(teamId, personId);
|
|
177
|
-
* const personData = await personDoc.get();
|
|
178
|
-
* ```
|
|
179
|
-
*/
|
|
180
|
-
public person(teamId: Team.Id, id: Person.Id): FirestoreDocument<Person> {
|
|
181
|
-
return this.persons(teamId)
|
|
182
|
-
.document(id.guidString);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Gets a reference to the fine templates collection within a team.
|
|
187
|
-
*
|
|
188
|
-
* @param teamId - The unique identifier of the team
|
|
189
|
-
* @returns A typed Firestore collection reference for fine templates in the team
|
|
190
|
-
*
|
|
191
|
-
* @example
|
|
192
|
-
* ```typescript
|
|
193
|
-
* const templatesCollection = Firestore.shared.fineTemplates(teamId);
|
|
194
|
-
* const allTemplates = await templatesCollection.getAll();
|
|
195
|
-
* ```
|
|
196
|
-
*/
|
|
197
|
-
public fineTemplates(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<FineTemplate, never>; }> {
|
|
198
|
-
return this.base
|
|
199
|
-
.collection('teams')
|
|
200
|
-
.document(teamId.guidString)
|
|
201
|
-
.collection('fineTemplates');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Gets a reference to a specific fine template document within a team.
|
|
206
|
-
*
|
|
207
|
-
* @param teamId - The unique identifier of the team
|
|
208
|
-
* @param id - The unique identifier of the fine template
|
|
209
|
-
* @returns A typed Firestore document reference for the fine template
|
|
210
|
-
*
|
|
211
|
-
* @example
|
|
212
|
-
* ```typescript
|
|
213
|
-
* const templateDoc = Firestore.shared.fineTemplate(teamId, templateId);
|
|
214
|
-
* const templateData = await templateDoc.get();
|
|
215
|
-
* ```
|
|
216
|
-
*/
|
|
217
|
-
public fineTemplate(teamId: Team.Id, id: FineTemplate.Id): FirestoreDocument<FineTemplate> {
|
|
218
|
-
return this.fineTemplates(teamId)
|
|
219
|
-
.document(id.guidString);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Gets a reference to the fines collection within a team.
|
|
224
|
-
*
|
|
225
|
-
* @param teamId - The unique identifier of the team
|
|
226
|
-
* @returns A typed Firestore collection reference for fines in the team
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* ```typescript
|
|
230
|
-
* const finesCollection = Firestore.shared.fines(teamId);
|
|
231
|
-
* const allFines = await finesCollection.getAll();
|
|
232
|
-
* ```
|
|
233
|
-
*/
|
|
234
|
-
public fines(teamId: Team.Id): FirestoreCollection<{ [x: string]: FirestoreDocument<Fine, never>; }> {
|
|
235
|
-
return this.base
|
|
236
|
-
.collection('teams')
|
|
237
|
-
.document(teamId.guidString)
|
|
238
|
-
.collection('fines');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Gets a reference to a specific fine document within a team.
|
|
243
|
-
*
|
|
244
|
-
* @param teamId - The unique identifier of the team
|
|
245
|
-
* @param id - The unique identifier of the fine
|
|
246
|
-
* @returns A typed Firestore document reference for the fine
|
|
247
|
-
*
|
|
248
|
-
* @example
|
|
249
|
-
* ```typescript
|
|
250
|
-
* const fineDoc = Firestore.shared.fine(teamId, fineId);
|
|
251
|
-
* const fineData = await fineDoc.get();
|
|
252
|
-
* ```
|
|
253
|
-
*/
|
|
254
|
-
public fine(teamId: Team.Id, id: Fine.Id): FirestoreDocument<Fine> {
|
|
255
|
-
return this.fines(teamId)
|
|
256
|
-
.document(id.guidString);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { FirestoreCollection, FirestoreDocument } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Fine, FineTemplate, Invitation, Person, Team, User } from '../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Type definition for the Firestore database schema.
|
|
6
|
-
*
|
|
7
|
-
* Defines the hierarchical structure of the Firestore database:
|
|
8
|
-
* - **users**: Collection of user documents indexed by User.Id
|
|
9
|
-
* - **invitations**: Collection of invitation documents indexed by Invitation.Id
|
|
10
|
-
* - **teams**: Collection of team documents indexed by Team.Id, each containing:
|
|
11
|
-
* - **persons**: Subcollection of person documents indexed by Person.Id
|
|
12
|
-
* - **fineTemplates**: Subcollection of fine template documents indexed by FineTemplate.Id
|
|
13
|
-
* - **fines**: Subcollection of fine documents indexed by Fine.Id
|
|
14
|
-
*
|
|
15
|
-
* This type ensures type-safe access to Firestore collections and documents
|
|
16
|
-
* throughout the application.
|
|
17
|
-
*/
|
|
18
|
-
export type FirestoreScheme = FirestoreDocument<never, {
|
|
19
|
-
userAuthIdDict: FirestoreCollection<{
|
|
20
|
-
[UserAuthId in string]: FirestoreDocument<{ userId: User.Id }>
|
|
21
|
-
}>,
|
|
22
|
-
users: FirestoreCollection<{
|
|
23
|
-
[UserId in string]: FirestoreDocument<User>
|
|
24
|
-
}>
|
|
25
|
-
invitations: FirestoreCollection<{
|
|
26
|
-
[InvitationId in string]: FirestoreDocument<Invitation>
|
|
27
|
-
}>
|
|
28
|
-
teams: FirestoreCollection<{
|
|
29
|
-
[TeamId in string]: FirestoreDocument<Team, {
|
|
30
|
-
persons: FirestoreCollection<{
|
|
31
|
-
[PersonId in string]: FirestoreDocument<Person>
|
|
32
|
-
}>
|
|
33
|
-
fineTemplates: FirestoreCollection<{
|
|
34
|
-
[PersonId in string]: FirestoreDocument<FineTemplate>
|
|
35
|
-
}>
|
|
36
|
-
fines: FirestoreCollection<{
|
|
37
|
-
[PersonId in string]: FirestoreDocument<Fine>
|
|
38
|
-
}>
|
|
39
|
-
}>
|
|
40
|
-
}>
|
|
41
|
-
}>;
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents a notification payload for Firebase Cloud Messaging.
|
|
3
|
-
*/
|
|
4
|
-
export interface Notification {
|
|
5
|
-
/**
|
|
6
|
-
* The notification title.
|
|
7
|
-
*/
|
|
8
|
-
title?: string;
|
|
9
|
-
/**
|
|
10
|
-
* The notification body text.
|
|
11
|
-
*/
|
|
12
|
-
body?: string;
|
|
13
|
-
/**
|
|
14
|
-
* URL of an image to be displayed in the notification.
|
|
15
|
-
*/
|
|
16
|
-
imageUrl?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Response from sending batch messages to multiple devices.
|
|
21
|
-
*/
|
|
22
|
-
export interface BatchResponse {
|
|
23
|
-
/**
|
|
24
|
-
* Array of individual message responses.
|
|
25
|
-
*/
|
|
26
|
-
responses: {
|
|
27
|
-
/**
|
|
28
|
-
* Whether the message was sent successfully.
|
|
29
|
-
*/
|
|
30
|
-
success: boolean;
|
|
31
|
-
/**
|
|
32
|
-
* The message ID if successful.
|
|
33
|
-
*/
|
|
34
|
-
messageId?: string;
|
|
35
|
-
/**
|
|
36
|
-
* Error information if the message failed to send.
|
|
37
|
-
*/
|
|
38
|
-
error?: {
|
|
39
|
-
/**
|
|
40
|
-
* Error code identifier.
|
|
41
|
-
*/
|
|
42
|
-
code: string;
|
|
43
|
-
/**
|
|
44
|
-
* Human-readable error message.
|
|
45
|
-
*/
|
|
46
|
-
message: string;
|
|
47
|
-
/**
|
|
48
|
-
* Optional stack trace for debugging.
|
|
49
|
-
*/
|
|
50
|
-
stack?: string;
|
|
51
|
-
/**
|
|
52
|
-
* Converts the error to a JSON object.
|
|
53
|
-
*/
|
|
54
|
-
toJSON(): object;
|
|
55
|
-
};
|
|
56
|
-
}[];
|
|
57
|
-
/**
|
|
58
|
-
* Number of messages sent successfully.
|
|
59
|
-
*/
|
|
60
|
-
successCount: number;
|
|
61
|
-
/**
|
|
62
|
-
* Number of messages that failed to send.
|
|
63
|
-
*/
|
|
64
|
-
failureCount: number;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Message to be sent to multiple device tokens.
|
|
69
|
-
*/
|
|
70
|
-
export interface MulticastMessage {
|
|
71
|
-
/**
|
|
72
|
-
* Array of device registration tokens to send the message to.
|
|
73
|
-
*/
|
|
74
|
-
tokens: string[];
|
|
75
|
-
/**
|
|
76
|
-
* Optional notification payload to include in the message.
|
|
77
|
-
*/
|
|
78
|
-
notification?: Notification;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Firebase Cloud Messaging service interface.
|
|
83
|
-
*/
|
|
84
|
-
export interface Messaging {
|
|
85
|
-
/**
|
|
86
|
-
* Sends a multicast message to multiple devices.
|
|
87
|
-
*
|
|
88
|
-
* @param message - The multicast message containing tokens and notification
|
|
89
|
-
* @param dryRun - If true, validates the message without actually sending it
|
|
90
|
-
* @returns Promise resolving to batch response with success/failure details
|
|
91
|
-
*/
|
|
92
|
-
sendEachForMulticast(message: MulticastMessage, dryRun?: boolean): Promise<BatchResponse>;
|
|
93
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { FunctionsError, UserAuthId } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Person, Team, User, UserRole } from '../types';
|
|
3
|
-
import { Firestore } from './Firestore';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Type representing expected user role requirements.
|
|
7
|
-
*
|
|
8
|
-
* Can be:
|
|
9
|
-
* - A single `UserRole` (user must have this role)
|
|
10
|
-
* - An array of `ExpectedUserRoles` (user must satisfy ALL requirements - logical AND)
|
|
11
|
-
* - An object with `anyOf` property (user must satisfy AT LEAST ONE requirement - logical OR)
|
|
12
|
-
*
|
|
13
|
-
* Examples:
|
|
14
|
-
* - `'admin'` - User must be admin
|
|
15
|
-
* - `['member', 'treasurer']` - User must be both member AND treasurer
|
|
16
|
-
* - `{ anyOf: ['admin', 'treasurer'] }` - User must be admin OR treasurer
|
|
17
|
-
*/
|
|
18
|
-
type ExpectedUserRoles =
|
|
19
|
-
| UserRole
|
|
20
|
-
| ExpectedUserRoles[]
|
|
21
|
-
| {
|
|
22
|
-
anyOf: ExpectedUserRoles[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Checks if the user has the required roles according to the expected role requirements.
|
|
27
|
-
*
|
|
28
|
-
* @param userRoles - Array of roles the user currently has
|
|
29
|
-
* @param expectedRoles - The role requirements to check against (supports AND/OR logic)
|
|
30
|
-
* @returns `true` if the user satisfies the role requirements, `false` otherwise
|
|
31
|
-
*/
|
|
32
|
-
function hasUserRoles(userRoles: UserRole[], expectedRoles: ExpectedUserRoles): boolean {
|
|
33
|
-
if (Array.isArray(expectedRoles))
|
|
34
|
-
return expectedRoles.every(expectedRole => hasUserRoles(userRoles, expectedRole));
|
|
35
|
-
else if (typeof expectedRoles === 'object' && 'anyOf' in expectedRoles)
|
|
36
|
-
return expectedRoles.anyOf.some(role => hasUserRoles(userRoles, role));
|
|
37
|
-
else
|
|
38
|
-
return userRoles.includes(expectedRoles);
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Validates that a user is authenticated and has the required roles for a specific team.
|
|
44
|
-
*
|
|
45
|
-
* Performs comprehensive authentication checks:
|
|
46
|
-
* 1. Verifies the user is authenticated (rawUserId is not null)
|
|
47
|
-
* 2. Checks that the user exists in the database
|
|
48
|
-
* 3. Confirms the user is a member of the specified team
|
|
49
|
-
* 4. Validates that the person associated with the user exists
|
|
50
|
-
* 5. Ensures the person is signed in (has signInProperties)
|
|
51
|
-
* 6. Verifies the person has the required roles
|
|
52
|
-
*
|
|
53
|
-
* @param userAuthId - The raw user authentication ID string from authentication context (null if not authenticated)
|
|
54
|
-
* @param teamId - The ID of the team to check membership and roles for
|
|
55
|
-
* @param roles - The expected role requirements (supports AND/OR logic via ExpectedUserRoles)
|
|
56
|
-
* @returns The validated User.Id if all checks pass
|
|
57
|
-
* @throws {FunctionsError} 'unauthenticated' - If rawUserId is null
|
|
58
|
-
* @throws {FunctionsError} 'permission-denied' - If any validation check fails
|
|
59
|
-
*/
|
|
60
|
-
export async function checkAuthentication(userAuthId: UserAuthId | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id> {
|
|
61
|
-
if (userAuthId === null)
|
|
62
|
-
throw new FunctionsError('unauthenticated', 'User is not authenticated');
|
|
63
|
-
|
|
64
|
-
const userAuthSnapshot = await Firestore.shared.userAuth(userAuthId).snapshot();
|
|
65
|
-
if (!userAuthSnapshot.exists)
|
|
66
|
-
throw new FunctionsError('permission-denied', 'User authentication does not exist');
|
|
67
|
-
const userId = User.Id.builder.build(userAuthSnapshot.data.userId);
|
|
68
|
-
|
|
69
|
-
const userSnapshot = await Firestore.shared.user(userId).snapshot();
|
|
70
|
-
if (!userSnapshot.exists)
|
|
71
|
-
throw new FunctionsError('permission-denied', 'User does not exist');
|
|
72
|
-
const user = User.builder.build(userSnapshot.data);
|
|
73
|
-
|
|
74
|
-
if (!user.teams.has(teamId))
|
|
75
|
-
throw new FunctionsError('permission-denied', 'User is not a member of the team');
|
|
76
|
-
const team = user.teams.get(teamId);
|
|
77
|
-
|
|
78
|
-
const personSnapshot = await Firestore.shared.person(teamId, team.personId).snapshot();
|
|
79
|
-
if (!personSnapshot.exists)
|
|
80
|
-
throw new FunctionsError('permission-denied', 'Person does not exist');
|
|
81
|
-
const person = Person.builder.build(personSnapshot.data);
|
|
82
|
-
|
|
83
|
-
if (person.signInProperties === null)
|
|
84
|
-
throw new FunctionsError('permission-denied', 'Person is not signed in');
|
|
85
|
-
|
|
86
|
-
const userHasRoles = hasUserRoles(person.signInProperties.roles, roles);
|
|
87
|
-
if (!userHasRoles)
|
|
88
|
-
throw new FunctionsError('permission-denied', 'User does not have the required roles');
|
|
89
|
-
|
|
90
|
-
return userId;
|
|
91
|
-
}
|
package/src/firebase/index.ts
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { Dictionary } from '@stevenkellner/typescript-common-functionality';
|
|
2
|
-
import { Firestore } from './Firestore';
|
|
3
|
-
import { NotificationProperties, Person, Team } from '../types';
|
|
4
|
-
import { FirebaseConfiguration, BatchResponse, Notification } from '.';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Filters successful tokens from a Firebase Cloud Messaging batch response.
|
|
8
|
-
*
|
|
9
|
-
* Removes tokens that failed due to invalid or unregistered registration tokens,
|
|
10
|
-
* keeping only the tokens that successfully received the notification.
|
|
11
|
-
*
|
|
12
|
-
* @param response - The batch response from Firebase Cloud Messaging
|
|
13
|
-
* @param tokens - The array of device tokens that were sent the notification
|
|
14
|
-
* @returns A dictionary mapping token IDs to their corresponding device tokens for successful deliveries
|
|
15
|
-
*
|
|
16
|
-
* @remarks
|
|
17
|
-
* Filters out tokens with the following error codes:
|
|
18
|
-
* - `messaging/invalid-registration-token`: The token format is invalid
|
|
19
|
-
* - `messaging/registration-token-not-registered`: The token is no longer registered
|
|
20
|
-
*
|
|
21
|
-
* @private
|
|
22
|
-
*/
|
|
23
|
-
function successfulTokens(response: BatchResponse, tokens: string[]): Dictionary<NotificationProperties.TokenId, string> {
|
|
24
|
-
const successfulTokens = response.responses
|
|
25
|
-
.map((response, index) => ({
|
|
26
|
-
failed: response.error?.code ==='messaging/invalid-registration-token' || response.error?.code === 'messaging/registration-token-not-registered',
|
|
27
|
-
token: tokens[index]
|
|
28
|
-
}))
|
|
29
|
-
.filter(response => !response.failed)
|
|
30
|
-
.map(response => response.token);
|
|
31
|
-
const tokenDict = new Dictionary<NotificationProperties.TokenId, string>(NotificationProperties.TokenId.builder);
|
|
32
|
-
for (const token of successfulTokens)
|
|
33
|
-
tokenDict.set(NotificationProperties.TokenId.create(token), token);
|
|
34
|
-
return tokenDict;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Sends a push notification to a person if they are subscribed to the topic.
|
|
39
|
-
*
|
|
40
|
-
* Retrieves the person's notification properties, checks their subscription status,
|
|
41
|
-
* sends the notification to all their registered device tokens, and updates their
|
|
42
|
-
* token list to remove any failed tokens.
|
|
43
|
-
*
|
|
44
|
-
* @param teamId - The unique identifier of the team
|
|
45
|
-
* @param personId - The unique identifier of the person
|
|
46
|
-
* @param topic - The notification subscription topic (e.g., 'new-fine', 'fine-reminder', 'fine-state-change')
|
|
47
|
-
* @param notification - The notification content to send
|
|
48
|
-
*
|
|
49
|
-
* @returns A promise that resolves when the notification is sent and person data is updated
|
|
50
|
-
*
|
|
51
|
-
* @remarks
|
|
52
|
-
* The function will silently return without sending if:
|
|
53
|
-
* - The person does not exist in the database
|
|
54
|
-
* - The person is not signed in (signInProperties is null)
|
|
55
|
-
* - The person is not subscribed to the specified topic
|
|
56
|
-
*
|
|
57
|
-
* After sending, the person's token list is automatically updated to remove
|
|
58
|
-
* any tokens that are invalid or unregistered, maintaining clean notification data.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```typescript
|
|
62
|
-
* await pushNotification(
|
|
63
|
-
* teamId,
|
|
64
|
-
* personId,
|
|
65
|
-
* 'new-fine',
|
|
66
|
-
* {
|
|
67
|
-
* title: 'New Fine',
|
|
68
|
-
* body: 'You have received a new fine'
|
|
69
|
-
* }
|
|
70
|
-
* );
|
|
71
|
-
* ```
|
|
72
|
-
*/
|
|
73
|
-
export async function pushNotification(teamId: Team.Id, personId: Person.Id, topic: NotificationProperties.Subscription, notification: Notification): Promise<void> {
|
|
74
|
-
|
|
75
|
-
const personSnapshot = await Firestore.shared.person(teamId, personId).snapshot();
|
|
76
|
-
if (!personSnapshot.exists)
|
|
77
|
-
return;
|
|
78
|
-
const person = Person.builder.build(personSnapshot.data);
|
|
79
|
-
|
|
80
|
-
if (person.signInProperties === null || !person.signInProperties.notificationProperties.subscriptions.includes(topic))
|
|
81
|
-
return;
|
|
82
|
-
|
|
83
|
-
const tokens = person.signInProperties.notificationProperties.tokens.values;
|
|
84
|
-
const response = await FirebaseConfiguration.shared.messaging.sendEachForMulticast({
|
|
85
|
-
tokens: tokens,
|
|
86
|
-
notification: notification
|
|
87
|
-
});
|
|
88
|
-
person.signInProperties.notificationProperties.tokens = successfulTokens(response, tokens);
|
|
89
|
-
await Firestore.shared.person(teamId, personId).set(person);
|
|
90
|
-
}
|