@stevenkellner/team-conduct-api 1.0.27 → 1.0.29
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/Firestore.d.ts +2 -2
- package/lib/src/Firestore.js +2 -2
- package/lib/src/FirestoreScheme.d.ts +3 -3
- package/lib/src/checkAuthentication.d.ts +5 -1
- package/lib/src/checkAuthentication.js +9 -4
- package/lib/src/firebaseFunctionsContext.d.ts +6 -5
- package/lib/src/firebaseFunctionsContext.js +5 -4
- package/lib/src/functions/fine/add.js +3 -1
- package/lib/src/functions/index.d.ts +4 -3
- package/lib/src/functions/index.js +4 -3
- package/lib/src/functions/user/kickout.d.ts +17 -0
- package/lib/src/functions/user/kickout.js +29 -0
- package/lib/src/functions/userInvitation/invite.d.ts +7 -0
- package/lib/src/functions/{invitation → userInvitation}/invite.js +6 -6
- package/lib/src/functions/userInvitation/register.d.ts +7 -0
- package/lib/src/functions/{invitation → userInvitation}/register.js +7 -7
- package/lib/src/functions/userInvitation/withdraw.d.ts +8 -0
- package/lib/src/functions/{invitation → userInvitation}/withdraw.js +6 -6
- package/lib/src/locales/de.d.ts +1 -0
- package/lib/src/locales/de.js +1 -0
- package/lib/src/locales/en.d.ts +1 -0
- package/lib/src/locales/en.js +1 -0
- package/lib/src/types/Localization.d.ts +3 -0
- package/lib/src/types/{Invitation.d.ts → UserInvitation.d.ts} +8 -8
- package/lib/src/types/{Invitation.js → UserInvitation.js} +11 -11
- package/lib/src/types/UserRole.d.ts +1 -1
- package/lib/src/types/UserRole.js +2 -0
- package/lib/src/types/index.d.ts +1 -1
- package/lib/src/types/index.js +1 -1
- package/lib/test/localization.de.test.js +6 -0
- package/lib/test/localization.en.test.js +6 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/Firestore.ts +3 -3
- package/src/FirestoreScheme.ts +3 -3
- package/src/checkAuthentication.ts +17 -4
- package/src/firebaseFunctionsContext.ts +8 -6
- package/src/functions/fine/add.ts +3 -1
- package/src/functions/index.ts +4 -3
- package/src/functions/user/kickout.ts +42 -0
- package/src/functions/user/login.ts +0 -1
- package/src/functions/{invitation → userInvitation}/invite.ts +6 -6
- package/src/functions/{invitation → userInvitation}/register.ts +7 -7
- package/src/functions/{invitation → userInvitation}/withdraw.ts +6 -6
- package/src/locales/de.ts +1 -0
- package/src/locales/en.ts +1 -0
- package/src/types/{Invitation.ts → UserInvitation.ts} +10 -10
- package/src/types/UserRole.ts +3 -0
- package/src/types/index.ts +1 -1
- package/lib/src/functions/invitation/invite.d.ts +0 -7
- package/lib/src/functions/invitation/register.d.ts +0 -7
- package/lib/src/functions/invitation/withdraw.d.ts +0 -8
package/lib/src/Firestore.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FirestoreDocument } from '@stevenkellner/firebase-function';
|
|
2
2
|
import { FirestoreScheme } from './FirestoreScheme';
|
|
3
|
-
import { Fine, FineTemplate,
|
|
3
|
+
import { Fine, FineTemplate, UserInvitation, Person, User, Team } from './types';
|
|
4
4
|
export declare class Firestore {
|
|
5
5
|
protected base: FirestoreScheme;
|
|
6
6
|
protected constructor();
|
|
@@ -8,7 +8,7 @@ export declare class Firestore {
|
|
|
8
8
|
static get shared(): Firestore;
|
|
9
9
|
team(id: Team.Id): FirestoreDocument<Team>;
|
|
10
10
|
user(id: User.Id): FirestoreDocument<User>;
|
|
11
|
-
|
|
11
|
+
userInvitation(id: UserInvitation.Id): FirestoreDocument<UserInvitation>;
|
|
12
12
|
person(teamId: Team.Id, id: Person.Id): FirestoreDocument<Person>;
|
|
13
13
|
fineTemplate(teamId: Team.Id, id: FineTemplate.Id): FirestoreDocument<FineTemplate>;
|
|
14
14
|
fine(teamId: Team.Id, id: Fine.Id): FirestoreDocument<Fine>;
|
package/lib/src/Firestore.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { FirestoreCollection, FirestoreDocument } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Fine, FineTemplate,
|
|
2
|
+
import { Fine, FineTemplate, UserInvitation, Person, Team, User } from './types';
|
|
3
3
|
export type FirestoreScheme = FirestoreDocument<never, {
|
|
4
4
|
users: FirestoreCollection<{
|
|
5
5
|
[UserId in string]: FirestoreDocument<User>;
|
|
6
6
|
}>;
|
|
7
|
-
|
|
8
|
-
[
|
|
7
|
+
userInvitations: FirestoreCollection<{
|
|
8
|
+
[UserInvitationId in string]: FirestoreDocument<UserInvitation>;
|
|
9
9
|
}>;
|
|
10
10
|
teams: FirestoreCollection<{
|
|
11
11
|
[TeamId in string]: FirestoreDocument<Team, {
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
import { Team, User, UserRole } from './types';
|
|
2
|
-
|
|
2
|
+
type ExpectedUserRoles = UserRole | ExpectedUserRoles[] | {
|
|
3
|
+
anyOf: ExpectedUserRoles[];
|
|
4
|
+
};
|
|
5
|
+
export declare function checkAuthentication(rawUserId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id>;
|
|
6
|
+
export {};
|
|
@@ -4,10 +4,15 @@ exports.checkAuthentication = checkAuthentication;
|
|
|
4
4
|
const firebase_function_1 = require("@stevenkellner/firebase-function");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
6
|
const Firestore_1 = require("./Firestore");
|
|
7
|
-
function
|
|
8
|
-
|
|
7
|
+
function hasUserRoles(userRoles, expectedRoles) {
|
|
8
|
+
if (Array.isArray(expectedRoles))
|
|
9
|
+
return expectedRoles.every(expectedRole => hasUserRoles(userRoles, expectedRole));
|
|
10
|
+
else if (typeof expectedRoles === 'object' && 'anyOf' in expectedRoles)
|
|
11
|
+
return expectedRoles.anyOf.some(role => hasUserRoles(userRoles, role));
|
|
12
|
+
else
|
|
13
|
+
return userRoles.includes(expectedRoles);
|
|
9
14
|
}
|
|
10
|
-
async function checkAuthentication(rawUserId, teamId,
|
|
15
|
+
async function checkAuthentication(rawUserId, teamId, roles) {
|
|
11
16
|
if (rawUserId === null)
|
|
12
17
|
throw new firebase_function_1.FunctionsError('unauthenticated', 'User is not authenticated');
|
|
13
18
|
const userId = types_1.User.Id.builder.build(rawUserId);
|
|
@@ -24,7 +29,7 @@ async function checkAuthentication(rawUserId, teamId, ...roles) {
|
|
|
24
29
|
const person = types_1.Person.builder.build(personSnapshot.data);
|
|
25
30
|
if (person.signInProperties === null)
|
|
26
31
|
throw new firebase_function_1.FunctionsError('permission-denied', 'Person is not signed in');
|
|
27
|
-
const userHasRoles =
|
|
32
|
+
const userHasRoles = hasUserRoles(person.signInProperties.roles, roles);
|
|
28
33
|
if (!userHasRoles)
|
|
29
34
|
throw new firebase_function_1.FunctionsError('permission-denied', 'User does not have the required roles');
|
|
30
35
|
return userId;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { TeamNewFunction, UserRoleEditFunction, PaypalMeEditFunction, NotificationRegisterFunction, NotificationSubscribeFunction, PersonAddFunction, PersonDeleteFunction, PersonUpdateFunction, FineTemplateAddFunction, FineTemplateDeleteFunction, FineTemplateUpdateFunction, FineAddFunction, FineDeleteFunction, FineUpdateFunction } from './functions';
|
|
1
|
+
import { TeamNewFunction, UserKickoutFunction, UserRoleEditFunction, PaypalMeEditFunction, NotificationRegisterFunction, NotificationSubscribeFunction, PersonAddFunction, PersonDeleteFunction, PersonUpdateFunction, FineTemplateAddFunction, FineTemplateDeleteFunction, FineTemplateUpdateFunction, FineAddFunction, FineDeleteFunction, FineUpdateFunction } from './functions';
|
|
2
2
|
export declare const firebaseFunctionsContext: {
|
|
3
3
|
team: {
|
|
4
4
|
new: import("@stevenkellner/firebase-function").FirebaseFunctionContext<TeamNewFunction.Parameters, import("./types").User>;
|
|
5
5
|
};
|
|
6
6
|
user: {
|
|
7
|
+
kickout: import("@stevenkellner/firebase-function").FirebaseFunctionContext<UserKickoutFunction.Parameters, void>;
|
|
7
8
|
login: import("@stevenkellner/firebase-function").FirebaseFunctionContext<null, import("./types").User>;
|
|
8
9
|
roleEdit: import("@stevenkellner/firebase-function").FirebaseFunctionContext<UserRoleEditFunction.Parameters, void>;
|
|
9
10
|
};
|
|
@@ -14,10 +15,10 @@ export declare const firebaseFunctionsContext: {
|
|
|
14
15
|
register: import("@stevenkellner/firebase-function").FirebaseFunctionContext<NotificationRegisterFunction.Parameters, void>;
|
|
15
16
|
subscribe: import("@stevenkellner/firebase-function").FirebaseFunctionContext<NotificationSubscribeFunction.Parameters, void>;
|
|
16
17
|
};
|
|
17
|
-
|
|
18
|
-
invite: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").
|
|
19
|
-
withdraw: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").
|
|
20
|
-
register: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").
|
|
18
|
+
userInvitation: {
|
|
19
|
+
invite: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").UserInvitation, import("./types").UserInvitation.Id>;
|
|
20
|
+
withdraw: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").UserInvitation, void>;
|
|
21
|
+
register: import("@stevenkellner/firebase-function").FirebaseFunctionContext<import("./types").UserInvitation.Id, import("./types").User>;
|
|
21
22
|
};
|
|
22
23
|
person: {
|
|
23
24
|
add: import("@stevenkellner/firebase-function").FirebaseFunctionContext<PersonAddFunction.Parameters, void>;
|
|
@@ -8,6 +8,7 @@ exports.firebaseFunctionsContext = firebase_function_1.FirebaseFunctionsContext.
|
|
|
8
8
|
new: builder.function(functions_1.TeamNewFunction)
|
|
9
9
|
},
|
|
10
10
|
user: {
|
|
11
|
+
kickout: builder.function(functions_1.UserKickoutFunction),
|
|
11
12
|
login: builder.function(functions_1.UserLoginFunction),
|
|
12
13
|
roleEdit: builder.function(functions_1.UserRoleEditFunction)
|
|
13
14
|
},
|
|
@@ -18,10 +19,10 @@ exports.firebaseFunctionsContext = firebase_function_1.FirebaseFunctionsContext.
|
|
|
18
19
|
register: builder.function(functions_1.NotificationRegisterFunction),
|
|
19
20
|
subscribe: builder.function(functions_1.NotificationSubscribeFunction)
|
|
20
21
|
},
|
|
21
|
-
|
|
22
|
-
invite: builder.function(functions_1.
|
|
23
|
-
withdraw: builder.function(functions_1.
|
|
24
|
-
register: builder.function(functions_1.
|
|
22
|
+
userInvitation: {
|
|
23
|
+
invite: builder.function(functions_1.UserInvitationInviteFunction),
|
|
24
|
+
withdraw: builder.function(functions_1.UserInvitationWithdrawFunction),
|
|
25
|
+
register: builder.function(functions_1.UserInvitationRegisterFunction)
|
|
25
26
|
},
|
|
26
27
|
person: {
|
|
27
28
|
add: builder.function(functions_1.PersonAddFunction),
|
|
@@ -16,7 +16,9 @@ class FineAddFunction extends firebase_function_1.FirebaseFunction {
|
|
|
16
16
|
});
|
|
17
17
|
returnTypeBuilder = new typescript_common_functionality_1.ValueTypeBuilder();
|
|
18
18
|
async execute(parameters) {
|
|
19
|
-
await (0, checkAuthentication_1.checkAuthentication)(this.userId, parameters.teamId,
|
|
19
|
+
await (0, checkAuthentication_1.checkAuthentication)(this.userId, parameters.teamId, {
|
|
20
|
+
anyOf: ['fine-manager', 'fine-can-add']
|
|
21
|
+
});
|
|
20
22
|
const fineSnapshot = await Firestore_1.Firestore.shared.fine(parameters.teamId, parameters.fine.id).snapshot();
|
|
21
23
|
if (fineSnapshot.exists)
|
|
22
24
|
throw new firebase_function_1.FunctionsError('already-exists', 'Fine already exists');
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export * from './team/new';
|
|
2
2
|
export * from './user/login';
|
|
3
3
|
export * from './user/roleEdit';
|
|
4
|
+
export * from './user/kickout';
|
|
4
5
|
export * from './paypalMe/edit';
|
|
5
6
|
export * from './notification/register';
|
|
6
7
|
export * from './notification/subscribe';
|
|
7
|
-
export * from './
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
8
|
+
export * from './userInvitation/invite';
|
|
9
|
+
export * from './userInvitation/withdraw';
|
|
10
|
+
export * from './userInvitation/register';
|
|
10
11
|
export * from './person/add';
|
|
11
12
|
export * from './person/update';
|
|
12
13
|
export * from './person/delete';
|
|
@@ -17,12 +17,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./team/new"), exports);
|
|
18
18
|
__exportStar(require("./user/login"), exports);
|
|
19
19
|
__exportStar(require("./user/roleEdit"), exports);
|
|
20
|
+
__exportStar(require("./user/kickout"), exports);
|
|
20
21
|
__exportStar(require("./paypalMe/edit"), exports);
|
|
21
22
|
__exportStar(require("./notification/register"), exports);
|
|
22
23
|
__exportStar(require("./notification/subscribe"), exports);
|
|
23
|
-
__exportStar(require("./
|
|
24
|
-
__exportStar(require("./
|
|
25
|
-
__exportStar(require("./
|
|
24
|
+
__exportStar(require("./userInvitation/invite"), exports);
|
|
25
|
+
__exportStar(require("./userInvitation/withdraw"), exports);
|
|
26
|
+
__exportStar(require("./userInvitation/register"), exports);
|
|
26
27
|
__exportStar(require("./person/add"), exports);
|
|
27
28
|
__exportStar(require("./person/update"), exports);
|
|
28
29
|
__exportStar(require("./person/delete"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
+
import { Team, User } from '../../types';
|
|
3
|
+
import { ObjectTypeBuilder, ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
4
|
+
export declare namespace UserKickoutFunction {
|
|
5
|
+
type Parameters = {
|
|
6
|
+
teamId: Team.Id;
|
|
7
|
+
userId: User.Id;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export declare class UserKickoutFunction extends FirebaseFunction<UserKickoutFunction.Parameters, void> {
|
|
11
|
+
parametersBuilder: ObjectTypeBuilder<{
|
|
12
|
+
teamId: string;
|
|
13
|
+
userId: string;
|
|
14
|
+
}, UserKickoutFunction.Parameters>;
|
|
15
|
+
returnTypeBuilder: ValueTypeBuilder<void>;
|
|
16
|
+
execute(parameters: UserKickoutFunction.Parameters): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UserKickoutFunction = void 0;
|
|
4
|
+
const firebase_function_1 = require("@stevenkellner/firebase-function");
|
|
5
|
+
const types_1 = require("../../types");
|
|
6
|
+
const typescript_common_functionality_1 = require("@stevenkellner/typescript-common-functionality");
|
|
7
|
+
const Firestore_1 = require("../../Firestore");
|
|
8
|
+
const checkAuthentication_1 = require("../../checkAuthentication");
|
|
9
|
+
class UserKickoutFunction extends firebase_function_1.FirebaseFunction {
|
|
10
|
+
parametersBuilder = new typescript_common_functionality_1.ObjectTypeBuilder({
|
|
11
|
+
teamId: types_1.Team.Id.builder,
|
|
12
|
+
userId: types_1.User.Id.builder
|
|
13
|
+
});
|
|
14
|
+
returnTypeBuilder = new typescript_common_functionality_1.ValueTypeBuilder();
|
|
15
|
+
async execute(parameters) {
|
|
16
|
+
const userId = await (0, checkAuthentication_1.checkAuthentication)(this.userId, parameters.teamId, 'team-manager');
|
|
17
|
+
if (userId === parameters.userId)
|
|
18
|
+
throw new firebase_function_1.FunctionsError('invalid-argument', 'You cannot kick yourself out of a team.');
|
|
19
|
+
const userSnapshot = await Firestore_1.Firestore.shared.user(parameters.userId).snapshot();
|
|
20
|
+
if (!userSnapshot.exists)
|
|
21
|
+
throw new firebase_function_1.FunctionsError('not-found', 'User not found.');
|
|
22
|
+
const user = types_1.User.builder.build(userSnapshot.data);
|
|
23
|
+
const userTeamProperties = user.teams.getOptional(parameters.teamId);
|
|
24
|
+
if (userTeamProperties === null)
|
|
25
|
+
throw new firebase_function_1.FunctionsError('not-found', 'User is not a member of the team.');
|
|
26
|
+
await Firestore_1.Firestore.shared.person(parameters.teamId, userTeamProperties.personId).remove();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.UserKickoutFunction = UserKickoutFunction;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
+
import { UserInvitation } from '../../types';
|
|
3
|
+
export declare class UserInvitationInviteFunction extends FirebaseFunction<UserInvitation, UserInvitation.Id> {
|
|
4
|
+
parametersBuilder: UserInvitation.TypeBuilder;
|
|
5
|
+
returnTypeBuilder: import("@stevenkellner/typescript-common-functionality").Tagged.TypeBuilder<string, "userInvitation">;
|
|
6
|
+
execute(invitation: UserInvitation): Promise<UserInvitation.Id>;
|
|
7
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.UserInvitationInviteFunction = void 0;
|
|
4
4
|
const firebase_function_1 = require("@stevenkellner/firebase-function");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const checkAuthentication_1 = require("../../checkAuthentication");
|
|
7
7
|
const Firestore_1 = require("../../Firestore");
|
|
8
|
-
class
|
|
9
|
-
parametersBuilder = types_1.
|
|
10
|
-
returnTypeBuilder = types_1.
|
|
8
|
+
class UserInvitationInviteFunction extends firebase_function_1.FirebaseFunction {
|
|
9
|
+
parametersBuilder = types_1.UserInvitation.builder;
|
|
10
|
+
returnTypeBuilder = types_1.UserInvitation.Id.builder;
|
|
11
11
|
async execute(invitation) {
|
|
12
12
|
await (0, checkAuthentication_1.checkAuthentication)(this.userId, invitation.teamId, 'team-manager');
|
|
13
13
|
const personSnapshot = await Firestore_1.Firestore.shared.person(invitation.teamId, invitation.personId).snapshot();
|
|
@@ -16,8 +16,8 @@ class InvitationInviteFunction extends firebase_function_1.FirebaseFunction {
|
|
|
16
16
|
if (personSnapshot.data.signInProperties !== null)
|
|
17
17
|
throw new firebase_function_1.FunctionsError('already-exists', 'Person already has an account');
|
|
18
18
|
const invitationId = invitation.createId();
|
|
19
|
-
await Firestore_1.Firestore.shared.
|
|
19
|
+
await Firestore_1.Firestore.shared.userInvitation(invitationId).set(invitation);
|
|
20
20
|
return invitationId;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
-
exports.
|
|
23
|
+
exports.UserInvitationInviteFunction = UserInvitationInviteFunction;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
+
import { UserInvitation, User } from '../../types';
|
|
3
|
+
export declare class UserInvitationRegisterFunction extends FirebaseFunction<UserInvitation.Id, User> {
|
|
4
|
+
parametersBuilder: import("@stevenkellner/typescript-common-functionality").Tagged.TypeBuilder<string, "userInvitation">;
|
|
5
|
+
returnTypeBuilder: User.TypeBuilder;
|
|
6
|
+
execute(invitationId: UserInvitation.Id): Promise<User>;
|
|
7
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.UserInvitationRegisterFunction = void 0;
|
|
4
4
|
const firebase_function_1 = require("@stevenkellner/firebase-function");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const Firestore_1 = require("../../Firestore");
|
|
7
7
|
const typescript_common_functionality_1 = require("@stevenkellner/typescript-common-functionality");
|
|
8
|
-
class
|
|
9
|
-
parametersBuilder = types_1.
|
|
8
|
+
class UserInvitationRegisterFunction extends firebase_function_1.FirebaseFunction {
|
|
9
|
+
parametersBuilder = types_1.UserInvitation.Id.builder;
|
|
10
10
|
returnTypeBuilder = types_1.User.builder;
|
|
11
11
|
async execute(invitationId) {
|
|
12
12
|
if (this.userId === null)
|
|
13
13
|
throw new firebase_function_1.FunctionsError('unauthenticated', 'User not authenticated');
|
|
14
14
|
const userId = types_1.User.Id.builder.build(this.userId);
|
|
15
|
-
const invitationSnapshot = await Firestore_1.Firestore.shared.
|
|
15
|
+
const invitationSnapshot = await Firestore_1.Firestore.shared.userInvitation(invitationId).snapshot();
|
|
16
16
|
if (!invitationSnapshot.exists)
|
|
17
17
|
throw new firebase_function_1.FunctionsError('not-found', 'Invitation not found');
|
|
18
|
-
const invitation = types_1.
|
|
18
|
+
const invitation = types_1.UserInvitation.builder.build(invitationSnapshot.data);
|
|
19
19
|
const userSnapshot = await Firestore_1.Firestore.shared.user(userId).snapshot();
|
|
20
20
|
let user = new types_1.User(userId);
|
|
21
21
|
if (userSnapshot.exists)
|
|
@@ -32,7 +32,7 @@ class InvitationRegisterFunction extends firebase_function_1.FirebaseFunction {
|
|
|
32
32
|
const person = types_1.Person.builder.build(personSnapshot.data);
|
|
33
33
|
if (person.signInProperties !== null)
|
|
34
34
|
throw new firebase_function_1.FunctionsError('already-exists', 'Person already registered');
|
|
35
|
-
await Firestore_1.Firestore.shared.
|
|
35
|
+
await Firestore_1.Firestore.shared.userInvitation(invitationId).remove();
|
|
36
36
|
user.teams.set(invitation.teamId, new types_1.User.TeamProperties(team.name, invitation.personId));
|
|
37
37
|
await Firestore_1.Firestore.shared.user(userId).set(user);
|
|
38
38
|
person.signInProperties = new types_1.PersonSignInProperties(userId, typescript_common_functionality_1.UtcDate.now);
|
|
@@ -40,4 +40,4 @@ class InvitationRegisterFunction extends firebase_function_1.FirebaseFunction {
|
|
|
40
40
|
return user;
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
-
exports.
|
|
43
|
+
exports.UserInvitationRegisterFunction = UserInvitationRegisterFunction;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
+
import { UserInvitation } from '../../types';
|
|
3
|
+
import { ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
4
|
+
export declare class UserInvitationWithdrawFunction extends FirebaseFunction<UserInvitation, void> {
|
|
5
|
+
parametersBuilder: UserInvitation.TypeBuilder;
|
|
6
|
+
returnTypeBuilder: ValueTypeBuilder<void>;
|
|
7
|
+
execute(invitation: UserInvitation): Promise<void>;
|
|
8
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.UserInvitationWithdrawFunction = void 0;
|
|
4
4
|
const firebase_function_1 = require("@stevenkellner/firebase-function");
|
|
5
5
|
const types_1 = require("../../types");
|
|
6
6
|
const checkAuthentication_1 = require("../../checkAuthentication");
|
|
7
7
|
const Firestore_1 = require("../../Firestore");
|
|
8
8
|
const typescript_common_functionality_1 = require("@stevenkellner/typescript-common-functionality");
|
|
9
|
-
class
|
|
10
|
-
parametersBuilder = types_1.
|
|
9
|
+
class UserInvitationWithdrawFunction extends firebase_function_1.FirebaseFunction {
|
|
10
|
+
parametersBuilder = types_1.UserInvitation.builder;
|
|
11
11
|
returnTypeBuilder = new typescript_common_functionality_1.ValueTypeBuilder();
|
|
12
12
|
async execute(invitation) {
|
|
13
13
|
await (0, checkAuthentication_1.checkAuthentication)(this.userId, invitation.teamId, 'team-manager');
|
|
14
14
|
const invitationId = invitation.createId();
|
|
15
|
-
const invitationSnapshot = await Firestore_1.Firestore.shared.
|
|
15
|
+
const invitationSnapshot = await Firestore_1.Firestore.shared.userInvitation(invitationId).snapshot();
|
|
16
16
|
if (!invitationSnapshot.exists)
|
|
17
17
|
throw new firebase_function_1.FunctionsError('not-found', 'Invitation not found');
|
|
18
|
-
await Firestore_1.Firestore.shared.
|
|
18
|
+
await Firestore_1.Firestore.shared.userInvitation(invitationId).remove();
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
exports.
|
|
21
|
+
exports.UserInvitationWithdrawFunction = UserInvitationWithdrawFunction;
|
package/lib/src/locales/de.d.ts
CHANGED
package/lib/src/locales/de.js
CHANGED
package/lib/src/locales/en.d.ts
CHANGED
package/lib/src/locales/en.js
CHANGED
|
@@ -62,6 +62,7 @@ export declare const localizations: {
|
|
|
62
62
|
personManager: string;
|
|
63
63
|
fineTemplateManager: string;
|
|
64
64
|
fineManager: string;
|
|
65
|
+
fineCanAdd: string;
|
|
65
66
|
teamManager: string;
|
|
66
67
|
};
|
|
67
68
|
};
|
|
@@ -127,6 +128,7 @@ export declare const localizations: {
|
|
|
127
128
|
personManager: string;
|
|
128
129
|
fineTemplateManager: string;
|
|
129
130
|
fineManager: string;
|
|
131
|
+
fineCanAdd: string;
|
|
130
132
|
teamManager: string;
|
|
131
133
|
};
|
|
132
134
|
};
|
|
@@ -213,6 +215,7 @@ export declare class Localization {
|
|
|
213
215
|
personManager: ValueLocalization;
|
|
214
216
|
fineTemplateManager: ValueLocalization;
|
|
215
217
|
fineManager: ValueLocalization;
|
|
218
|
+
fineCanAdd: ValueLocalization;
|
|
216
219
|
teamManager: ValueLocalization;
|
|
217
220
|
};
|
|
218
221
|
};
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import { Flattable, ITypeBuilder, Tagged } from '@stevenkellner/typescript-common-functionality';
|
|
2
2
|
import { Team } from './Team';
|
|
3
3
|
import { Person } from './Person';
|
|
4
|
-
export declare class
|
|
4
|
+
export declare class UserInvitation implements Flattable<UserInvitation.Flatten> {
|
|
5
5
|
teamId: Team.Id;
|
|
6
6
|
personId: Person.Id;
|
|
7
7
|
constructor(teamId: Team.Id, personId: Person.Id);
|
|
8
|
-
createId():
|
|
9
|
-
get flatten():
|
|
8
|
+
createId(): UserInvitation.Id;
|
|
9
|
+
get flatten(): UserInvitation.Flatten;
|
|
10
10
|
}
|
|
11
|
-
export declare namespace
|
|
12
|
-
type Id = Tagged<string, '
|
|
11
|
+
export declare namespace UserInvitation {
|
|
12
|
+
type Id = Tagged<string, 'userInvitation'>;
|
|
13
13
|
namespace Id {
|
|
14
14
|
type Flatten = string;
|
|
15
|
-
const builder: Tagged.TypeBuilder<string, "
|
|
15
|
+
const builder: Tagged.TypeBuilder<string, "userInvitation">;
|
|
16
16
|
}
|
|
17
17
|
type Flatten = {
|
|
18
18
|
teamId: Team.Id.Flatten;
|
|
19
19
|
personId: Person.Id.Flatten;
|
|
20
20
|
};
|
|
21
|
-
class TypeBuilder implements ITypeBuilder<Flatten,
|
|
22
|
-
build(value: Flatten):
|
|
21
|
+
class TypeBuilder implements ITypeBuilder<Flatten, UserInvitation> {
|
|
22
|
+
build(value: Flatten): UserInvitation;
|
|
23
23
|
}
|
|
24
24
|
const builder: TypeBuilder;
|
|
25
25
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.UserInvitation = void 0;
|
|
4
4
|
const typescript_common_functionality_1 = require("@stevenkellner/typescript-common-functionality");
|
|
5
5
|
const Team_1 = require("./Team");
|
|
6
6
|
const Person_1 = require("./Person");
|
|
7
|
-
class
|
|
7
|
+
class UserInvitation {
|
|
8
8
|
teamId;
|
|
9
9
|
personId;
|
|
10
10
|
constructor(teamId, personId) {
|
|
@@ -17,7 +17,7 @@ class Invitation {
|
|
|
17
17
|
const personIdBytes = typescript_common_functionality_1.BytesCoder.fromUtf8(this.personId.guidString);
|
|
18
18
|
const hashedInvitationBytes = hasher.hash(new Uint8Array([...teamIdBytes, ...personIdBytes]));
|
|
19
19
|
const rawId = typescript_common_functionality_1.BytesCoder.toHex(hashedInvitationBytes).slice(0, 12);
|
|
20
|
-
return new typescript_common_functionality_1.Tagged(rawId, '
|
|
20
|
+
return new typescript_common_functionality_1.Tagged(rawId, 'userInvitation');
|
|
21
21
|
}
|
|
22
22
|
get flatten() {
|
|
23
23
|
return {
|
|
@@ -26,17 +26,17 @@ class Invitation {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
exports.
|
|
30
|
-
(function (
|
|
29
|
+
exports.UserInvitation = UserInvitation;
|
|
30
|
+
(function (UserInvitation) {
|
|
31
31
|
let Id;
|
|
32
32
|
(function (Id) {
|
|
33
|
-
Id.builder = typescript_common_functionality_1.Tagged.builder('
|
|
34
|
-
})(Id =
|
|
33
|
+
Id.builder = typescript_common_functionality_1.Tagged.builder('userInvitation', new typescript_common_functionality_1.ValueTypeBuilder());
|
|
34
|
+
})(Id = UserInvitation.Id || (UserInvitation.Id = {}));
|
|
35
35
|
class TypeBuilder {
|
|
36
36
|
build(value) {
|
|
37
|
-
return new
|
|
37
|
+
return new UserInvitation(Team_1.Team.Id.builder.build(value.teamId), Person_1.Person.Id.builder.build(value.personId));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
})(
|
|
40
|
+
UserInvitation.TypeBuilder = TypeBuilder;
|
|
41
|
+
UserInvitation.builder = new TypeBuilder();
|
|
42
|
+
})(UserInvitation || (exports.UserInvitation = UserInvitation = {}));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
2
|
-
export type UserRole = 'person-manager' | 'fineTemplate-manager' | 'fine-manager' | 'team-manager';
|
|
2
|
+
export type UserRole = 'person-manager' | 'fineTemplate-manager' | 'fine-manager' | 'fine-can-add' | 'team-manager';
|
|
3
3
|
export declare namespace UserRole {
|
|
4
4
|
const all: UserRole[];
|
|
5
5
|
function formatted(role: UserRole): string;
|
|
@@ -9,6 +9,7 @@ var UserRole;
|
|
|
9
9
|
'person-manager',
|
|
10
10
|
'fineTemplate-manager',
|
|
11
11
|
'fine-manager',
|
|
12
|
+
'fine-can-add',
|
|
12
13
|
'team-manager'
|
|
13
14
|
];
|
|
14
15
|
function formatted(role) {
|
|
@@ -16,6 +17,7 @@ var UserRole;
|
|
|
16
17
|
'person-manager': 'personManager',
|
|
17
18
|
'fineTemplate-manager': 'fineTemplateManager',
|
|
18
19
|
'fine-manager': 'fineManager',
|
|
20
|
+
'fine-can-add': 'fineCanAdd',
|
|
19
21
|
'team-manager': 'teamManager'
|
|
20
22
|
};
|
|
21
23
|
return Localization_1.Localization.shared.userRole[localizationKeyMap[role]].value();
|
package/lib/src/types/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from './Fine';
|
|
|
3
3
|
export * from './FineAmount';
|
|
4
4
|
export * from './FineTemplate';
|
|
5
5
|
export * from './FineTemplateRepetition';
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './UserInvitation';
|
|
7
7
|
export * from './Localization';
|
|
8
8
|
export * from './MoneyAmount';
|
|
9
9
|
export * from './NotificationProperties';
|
package/lib/src/types/index.js
CHANGED
|
@@ -19,7 +19,7 @@ __exportStar(require("./Fine"), exports);
|
|
|
19
19
|
__exportStar(require("./FineAmount"), exports);
|
|
20
20
|
__exportStar(require("./FineTemplate"), exports);
|
|
21
21
|
__exportStar(require("./FineTemplateRepetition"), exports);
|
|
22
|
-
__exportStar(require("./
|
|
22
|
+
__exportStar(require("./UserInvitation"), exports);
|
|
23
23
|
__exportStar(require("./Localization"), exports);
|
|
24
24
|
__exportStar(require("./MoneyAmount"), exports);
|
|
25
25
|
__exportStar(require("./NotificationProperties"), exports);
|
|
@@ -135,6 +135,12 @@ describe('Localization for de', () => {
|
|
|
135
135
|
it('userRole.fineManager should be formatted correctly', () => {
|
|
136
136
|
(0, core_1.expect)(types_1.UserRole.formatted('fine-manager')).toBeEqual('Strafenmanager');
|
|
137
137
|
});
|
|
138
|
+
it('userRole.fineCanAdd should be tested', () => {
|
|
139
|
+
(0, core_1.expect)(types_1.Localization.shared.userRole.fineCanAdd.value()).toBeEqual('Kann Strafen hinzufügen');
|
|
140
|
+
});
|
|
141
|
+
it('userRole.fineCanAdd should be formatted correctly', () => {
|
|
142
|
+
(0, core_1.expect)(types_1.UserRole.formatted('fine-can-add')).toBeEqual('Kann Strafen hinzufügen');
|
|
143
|
+
});
|
|
138
144
|
it('userRole.teamManager should be tested', () => {
|
|
139
145
|
(0, core_1.expect)(types_1.Localization.shared.userRole.teamManager.value()).toBeEqual('Teammanager');
|
|
140
146
|
});
|
|
@@ -129,6 +129,12 @@ describe('Localization for en', () => {
|
|
|
129
129
|
it('userRole.fineManager should be formatted correctly', () => {
|
|
130
130
|
(0, core_1.expect)(types_1.UserRole.formatted('fine-manager')).toBeEqual('Fine Manager');
|
|
131
131
|
});
|
|
132
|
+
it('userRole.fineCanAdd should be tested', () => {
|
|
133
|
+
(0, core_1.expect)(types_1.Localization.shared.userRole.fineCanAdd.value()).toBeEqual('Can add fines');
|
|
134
|
+
});
|
|
135
|
+
it('userRole.fineCanAdd should be formatted correctly', () => {
|
|
136
|
+
(0, core_1.expect)(types_1.UserRole.formatted('fine-can-add')).toBeEqual('Can add fines');
|
|
137
|
+
});
|
|
132
138
|
it('userRole.teamManager should be tested', () => {
|
|
133
139
|
(0, core_1.expect)(types_1.Localization.shared.userRole.teamManager.value()).toBeEqual('Team Manager');
|
|
134
140
|
});
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../index.ts","../src/Firestore.ts","../src/FirestoreScheme.ts","../src/checkAuthentication.ts","../src/firebaseFunctionsContext.ts","../src/index.ts","../src/pushNotification.ts","../src/firebase/FirebaseConfiguration.ts","../src/firebase/Messaging.ts","../src/firebase/index.ts","../src/functions/index.ts","../src/functions/fine/add.ts","../src/functions/fine/delete.ts","../src/functions/fine/update.ts","../src/functions/fineTemplate/add.ts","../src/functions/fineTemplate/delete.ts","../src/functions/fineTemplate/update.ts","../src/functions/
|
|
1
|
+
{"root":["../index.ts","../src/Firestore.ts","../src/FirestoreScheme.ts","../src/checkAuthentication.ts","../src/firebaseFunctionsContext.ts","../src/index.ts","../src/pushNotification.ts","../src/firebase/FirebaseConfiguration.ts","../src/firebase/Messaging.ts","../src/firebase/index.ts","../src/functions/index.ts","../src/functions/fine/add.ts","../src/functions/fine/delete.ts","../src/functions/fine/update.ts","../src/functions/fineTemplate/add.ts","../src/functions/fineTemplate/delete.ts","../src/functions/fineTemplate/update.ts","../src/functions/notification/register.ts","../src/functions/notification/subscribe.ts","../src/functions/paypalMe/edit.ts","../src/functions/person/add.ts","../src/functions/person/delete.ts","../src/functions/person/update.ts","../src/functions/team/new.ts","../src/functions/user/kickout.ts","../src/functions/user/login.ts","../src/functions/user/roleEdit.ts","../src/functions/userInvitation/invite.ts","../src/functions/userInvitation/register.ts","../src/functions/userInvitation/withdraw.ts","../src/locales/de.ts","../src/locales/en.ts","../src/types/Configuration.ts","../src/types/Fine.ts","../src/types/FineAmount.ts","../src/types/FineTemplate.ts","../src/types/FineTemplateRepetition.ts","../src/types/Localization.ts","../src/types/MoneyAmount.ts","../src/types/NotificationProperties.ts","../src/types/PayedState.ts","../src/types/Person.ts","../src/types/PersonPrivateProperties.ts","../src/types/PersonSignInProperties.ts","../src/types/Pluralization.ts","../src/types/Team.ts","../src/types/User.ts","../src/types/UserInvitation.ts","../src/types/UserRole.ts","../src/types/index.ts","../test/localization-utils.ts","../test/localization.de.test.ts","../test/localization.en.test.ts"],"version":"5.8.3"}
|
package/package.json
CHANGED
package/src/Firestore.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FirestoreDocument } from '@stevenkellner/firebase-function';
|
|
2
2
|
import { FirestoreScheme } from './FirestoreScheme';
|
|
3
|
-
import { Fine, FineTemplate,
|
|
3
|
+
import { Fine, FineTemplate, UserInvitation, Person, User, Team } from './types';
|
|
4
4
|
import { FirebaseConfiguration } from './firebase';
|
|
5
5
|
|
|
6
6
|
export class Firestore {
|
|
@@ -31,9 +31,9 @@ export class Firestore {
|
|
|
31
31
|
.document(id.value);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
public
|
|
34
|
+
public userInvitation(id: UserInvitation.Id): FirestoreDocument<UserInvitation> {
|
|
35
35
|
return this.base
|
|
36
|
-
.collection('
|
|
36
|
+
.collection('userInvitations')
|
|
37
37
|
.document(id.value);
|
|
38
38
|
}
|
|
39
39
|
|
package/src/FirestoreScheme.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { FirestoreCollection, FirestoreDocument } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Fine, FineTemplate,
|
|
2
|
+
import { Fine, FineTemplate, UserInvitation, Person, Team, User } from './types';
|
|
3
3
|
|
|
4
4
|
export type FirestoreScheme = FirestoreDocument<never, {
|
|
5
5
|
users: FirestoreCollection<{
|
|
6
6
|
[UserId in string]: FirestoreDocument<User>
|
|
7
7
|
}>
|
|
8
|
-
|
|
9
|
-
[
|
|
8
|
+
userInvitations: FirestoreCollection<{
|
|
9
|
+
[UserInvitationId in string]: FirestoreDocument<UserInvitation>
|
|
10
10
|
}>
|
|
11
11
|
teams: FirestoreCollection<{
|
|
12
12
|
[TeamId in string]: FirestoreDocument<Team, {
|
|
@@ -2,11 +2,24 @@ import { FunctionsError } from '@stevenkellner/firebase-function';
|
|
|
2
2
|
import { Person, Team, User, UserRole } from './types';
|
|
3
3
|
import { Firestore } from './Firestore';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
type ExpectedUserRoles =
|
|
6
|
+
| UserRole
|
|
7
|
+
| ExpectedUserRoles[]
|
|
8
|
+
| {
|
|
9
|
+
anyOf: ExpectedUserRoles[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function hasUserRoles(userRoles: UserRole[], expectedRoles: ExpectedUserRoles): boolean {
|
|
13
|
+
if (Array.isArray(expectedRoles))
|
|
14
|
+
return expectedRoles.every(expectedRole => hasUserRoles(userRoles, expectedRole));
|
|
15
|
+
else if (typeof expectedRoles === 'object' && 'anyOf' in expectedRoles)
|
|
16
|
+
return expectedRoles.anyOf.some(role => hasUserRoles(userRoles, role));
|
|
17
|
+
else
|
|
18
|
+
return userRoles.includes(expectedRoles);
|
|
19
|
+
|
|
7
20
|
}
|
|
8
21
|
|
|
9
|
-
export async function checkAuthentication(rawUserId: string | null, teamId: Team.Id,
|
|
22
|
+
export async function checkAuthentication(rawUserId: string | null, teamId: Team.Id, roles: ExpectedUserRoles): Promise<User.Id> {
|
|
10
23
|
if (rawUserId === null)
|
|
11
24
|
throw new FunctionsError('unauthenticated', 'User is not authenticated');
|
|
12
25
|
const userId = User.Id.builder.build(rawUserId);
|
|
@@ -28,7 +41,7 @@ export async function checkAuthentication(rawUserId: string | null, teamId: Team
|
|
|
28
41
|
if (person.signInProperties === null)
|
|
29
42
|
throw new FunctionsError('permission-denied', 'Person is not signed in');
|
|
30
43
|
|
|
31
|
-
const userHasRoles =
|
|
44
|
+
const userHasRoles = hasUserRoles(person.signInProperties.roles, roles);
|
|
32
45
|
if (!userHasRoles)
|
|
33
46
|
throw new FunctionsError('permission-denied', 'User does not have the required roles');
|
|
34
47
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { FirebaseFunctionsContext } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { TeamNewFunction,
|
|
2
|
+
import { TeamNewFunction,
|
|
3
|
+
UserKickoutFunction, UserLoginFunction, UserRoleEditFunction,
|
|
3
4
|
PaypalMeEditFunction, NotificationRegisterFunction, NotificationSubscribeFunction,
|
|
4
|
-
|
|
5
|
+
UserInvitationInviteFunction, UserInvitationRegisterFunction, UserInvitationWithdrawFunction,
|
|
5
6
|
PersonAddFunction, PersonDeleteFunction, PersonUpdateFunction,
|
|
6
7
|
FineTemplateAddFunction, FineTemplateDeleteFunction, FineTemplateUpdateFunction,
|
|
7
8
|
FineAddFunction, FineDeleteFunction, FineUpdateFunction
|
|
@@ -12,6 +13,7 @@ export const firebaseFunctionsContext = FirebaseFunctionsContext.build(builder =
|
|
|
12
13
|
new: builder.function(TeamNewFunction)
|
|
13
14
|
},
|
|
14
15
|
user: {
|
|
16
|
+
kickout: builder.function(UserKickoutFunction),
|
|
15
17
|
login: builder.function(UserLoginFunction),
|
|
16
18
|
roleEdit: builder.function(UserRoleEditFunction)
|
|
17
19
|
},
|
|
@@ -22,10 +24,10 @@ export const firebaseFunctionsContext = FirebaseFunctionsContext.build(builder =
|
|
|
22
24
|
register: builder.function(NotificationRegisterFunction),
|
|
23
25
|
subscribe: builder.function(NotificationSubscribeFunction)
|
|
24
26
|
},
|
|
25
|
-
|
|
26
|
-
invite: builder.function(
|
|
27
|
-
withdraw: builder.function(
|
|
28
|
-
register: builder.function(
|
|
27
|
+
userInvitation: {
|
|
28
|
+
invite: builder.function(UserInvitationInviteFunction),
|
|
29
|
+
withdraw: builder.function(UserInvitationWithdrawFunction),
|
|
30
|
+
register: builder.function(UserInvitationRegisterFunction)
|
|
29
31
|
},
|
|
30
32
|
person: {
|
|
31
33
|
add: builder.function(PersonAddFunction),
|
|
@@ -29,7 +29,9 @@ export class FineAddFunction extends FirebaseFunction<FineAddFunction.Parameters
|
|
|
29
29
|
|
|
30
30
|
public async execute(parameters: FineAddFunction.Parameters): Promise<void> {
|
|
31
31
|
|
|
32
|
-
await checkAuthentication(this.userId, parameters.teamId,
|
|
32
|
+
await checkAuthentication(this.userId, parameters.teamId, {
|
|
33
|
+
anyOf: ['fine-manager', 'fine-can-add']
|
|
34
|
+
});
|
|
33
35
|
|
|
34
36
|
const fineSnapshot = await Firestore.shared.fine(parameters.teamId, parameters.fine.id).snapshot();
|
|
35
37
|
if (fineSnapshot.exists)
|
package/src/functions/index.ts
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
export * from './team/new';
|
|
3
3
|
export * from './user/login';
|
|
4
4
|
export * from './user/roleEdit';
|
|
5
|
+
export * from './user/kickout';
|
|
5
6
|
export * from './paypalMe/edit';
|
|
6
7
|
export * from './notification/register';
|
|
7
8
|
export * from './notification/subscribe';
|
|
8
|
-
export * from './
|
|
9
|
-
export * from './
|
|
10
|
-
export * from './
|
|
9
|
+
export * from './userInvitation/invite';
|
|
10
|
+
export * from './userInvitation/withdraw';
|
|
11
|
+
export * from './userInvitation/register';
|
|
11
12
|
export * from './person/add';
|
|
12
13
|
export * from './person/update';
|
|
13
14
|
export * from './person/delete';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FirebaseFunction, FunctionsError } from '@stevenkellner/firebase-function';
|
|
2
|
+
import { Team, User } from '../../types';
|
|
3
|
+
import { Flattable, ObjectTypeBuilder, ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
4
|
+
import { Firestore } from '../../Firestore';
|
|
5
|
+
import { checkAuthentication } from '../../checkAuthentication';
|
|
6
|
+
|
|
7
|
+
export namespace UserKickoutFunction {
|
|
8
|
+
|
|
9
|
+
export type Parameters = {
|
|
10
|
+
teamId: Team.Id
|
|
11
|
+
userId: User.Id
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class UserKickoutFunction extends FirebaseFunction<UserKickoutFunction.Parameters, void> {
|
|
16
|
+
|
|
17
|
+
public parametersBuilder = new ObjectTypeBuilder<Flattable.Flatten<UserKickoutFunction.Parameters>, UserKickoutFunction.Parameters>({
|
|
18
|
+
teamId: Team.Id.builder,
|
|
19
|
+
userId: User.Id.builder
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
public returnTypeBuilder = new ValueTypeBuilder<void>();
|
|
23
|
+
|
|
24
|
+
public async execute(parameters: UserKickoutFunction.Parameters): Promise<void> {
|
|
25
|
+
|
|
26
|
+
const userId = await checkAuthentication(this.userId, parameters.teamId, 'team-manager');
|
|
27
|
+
|
|
28
|
+
if (userId === parameters.userId)
|
|
29
|
+
throw new FunctionsError('invalid-argument', 'You cannot kick yourself out of a team.');
|
|
30
|
+
|
|
31
|
+
const userSnapshot = await Firestore.shared.user(parameters.userId).snapshot();
|
|
32
|
+
if (!userSnapshot.exists)
|
|
33
|
+
throw new FunctionsError('not-found', 'User not found.');
|
|
34
|
+
const user = User.builder.build(userSnapshot.data);
|
|
35
|
+
|
|
36
|
+
const userTeamProperties = user.teams.getOptional(parameters.teamId);
|
|
37
|
+
if (userTeamProperties === null)
|
|
38
|
+
throw new FunctionsError('not-found', 'User is not a member of the team.');
|
|
39
|
+
|
|
40
|
+
await Firestore.shared.person(parameters.teamId, userTeamProperties.personId).remove();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { FirebaseFunction, FunctionsError } from '@stevenkellner/firebase-function';
|
|
2
|
-
import {
|
|
2
|
+
import { UserInvitation } from '../../types';
|
|
3
3
|
import { checkAuthentication } from '../../checkAuthentication';
|
|
4
4
|
import { Firestore } from '../../Firestore';
|
|
5
5
|
|
|
6
|
-
export class
|
|
6
|
+
export class UserInvitationInviteFunction extends FirebaseFunction<UserInvitation, UserInvitation.Id> {
|
|
7
7
|
|
|
8
|
-
public parametersBuilder =
|
|
8
|
+
public parametersBuilder = UserInvitation.builder;
|
|
9
9
|
|
|
10
|
-
public returnTypeBuilder =
|
|
10
|
+
public returnTypeBuilder = UserInvitation.Id.builder;
|
|
11
11
|
|
|
12
|
-
public async execute(invitation:
|
|
12
|
+
public async execute(invitation: UserInvitation): Promise<UserInvitation.Id> {
|
|
13
13
|
|
|
14
14
|
await checkAuthentication(this.userId, invitation.teamId, 'team-manager');
|
|
15
15
|
|
|
@@ -21,7 +21,7 @@ export class InvitationInviteFunction extends FirebaseFunction<Invitation, Invit
|
|
|
21
21
|
throw new FunctionsError('already-exists', 'Person already has an account');
|
|
22
22
|
|
|
23
23
|
const invitationId = invitation.createId();
|
|
24
|
-
await Firestore.shared.
|
|
24
|
+
await Firestore.shared.userInvitation(invitationId).set(invitation);
|
|
25
25
|
|
|
26
26
|
return invitationId;
|
|
27
27
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { FirebaseFunction, FunctionsError } from '@stevenkellner/firebase-function';
|
|
2
|
-
import {
|
|
2
|
+
import { UserInvitation, Person, PersonSignInProperties, Team, User } from '../../types';
|
|
3
3
|
import { Firestore } from '../../Firestore';
|
|
4
4
|
import { UtcDate } from '@stevenkellner/typescript-common-functionality';
|
|
5
5
|
|
|
6
|
-
export class
|
|
6
|
+
export class UserInvitationRegisterFunction extends FirebaseFunction<UserInvitation.Id, User> {
|
|
7
7
|
|
|
8
|
-
public parametersBuilder =
|
|
8
|
+
public parametersBuilder = UserInvitation.Id.builder;
|
|
9
9
|
|
|
10
10
|
public returnTypeBuilder = User.builder;
|
|
11
11
|
|
|
12
|
-
public async execute(invitationId:
|
|
12
|
+
public async execute(invitationId: UserInvitation.Id): Promise<User> {
|
|
13
13
|
|
|
14
14
|
if (this.userId === null)
|
|
15
15
|
throw new FunctionsError('unauthenticated', 'User not authenticated');
|
|
16
16
|
const userId = User.Id.builder.build(this.userId);
|
|
17
17
|
|
|
18
|
-
const invitationSnapshot = await Firestore.shared.
|
|
18
|
+
const invitationSnapshot = await Firestore.shared.userInvitation(invitationId).snapshot();
|
|
19
19
|
if (!invitationSnapshot.exists)
|
|
20
20
|
throw new FunctionsError('not-found', 'Invitation not found');
|
|
21
|
-
const invitation =
|
|
21
|
+
const invitation = UserInvitation.builder.build(invitationSnapshot.data);
|
|
22
22
|
|
|
23
23
|
const userSnapshot = await Firestore.shared.user(userId).snapshot();
|
|
24
24
|
let user = new User(userId);
|
|
@@ -41,7 +41,7 @@ export class InvitationRegisterFunction extends FirebaseFunction<Invitation.Id,
|
|
|
41
41
|
if (person.signInProperties !== null)
|
|
42
42
|
throw new FunctionsError('already-exists', 'Person already registered');
|
|
43
43
|
|
|
44
|
-
await Firestore.shared.
|
|
44
|
+
await Firestore.shared.userInvitation(invitationId).remove();
|
|
45
45
|
|
|
46
46
|
user.teams.set(invitation.teamId, new User.TeamProperties(team.name, invitation.personId));
|
|
47
47
|
await Firestore.shared.user(userId).set(user);
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { FirebaseFunction, FunctionsError } from '@stevenkellner/firebase-function';
|
|
2
|
-
import {
|
|
2
|
+
import { UserInvitation } from '../../types';
|
|
3
3
|
import { checkAuthentication } from '../../checkAuthentication';
|
|
4
4
|
import { Firestore } from '../../Firestore';
|
|
5
5
|
import { ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
6
6
|
|
|
7
|
-
export class
|
|
7
|
+
export class UserInvitationWithdrawFunction extends FirebaseFunction<UserInvitation, void> {
|
|
8
8
|
|
|
9
|
-
public parametersBuilder =
|
|
9
|
+
public parametersBuilder = UserInvitation.builder;
|
|
10
10
|
|
|
11
11
|
public returnTypeBuilder = new ValueTypeBuilder<void>();
|
|
12
12
|
|
|
13
|
-
public async execute(invitation:
|
|
13
|
+
public async execute(invitation: UserInvitation): Promise<void> {
|
|
14
14
|
|
|
15
15
|
await checkAuthentication(this.userId, invitation.teamId, 'team-manager');
|
|
16
16
|
|
|
17
17
|
const invitationId = invitation.createId();
|
|
18
|
-
const invitationSnapshot = await Firestore.shared.
|
|
18
|
+
const invitationSnapshot = await Firestore.shared.userInvitation(invitationId).snapshot();
|
|
19
19
|
if (!invitationSnapshot.exists)
|
|
20
20
|
throw new FunctionsError('not-found', 'Invitation not found');
|
|
21
21
|
|
|
22
|
-
await Firestore.shared.
|
|
22
|
+
await Firestore.shared.userInvitation(invitationId).remove();
|
|
23
23
|
}
|
|
24
24
|
}
|
package/src/locales/de.ts
CHANGED
package/src/locales/en.ts
CHANGED
|
@@ -2,23 +2,23 @@ import { BytesCoder, Flattable, ITypeBuilder, Sha512, Tagged, ValueTypeBuilder }
|
|
|
2
2
|
import { Team } from './Team';
|
|
3
3
|
import { Person } from './Person';
|
|
4
4
|
|
|
5
|
-
export class
|
|
5
|
+
export class UserInvitation implements Flattable<UserInvitation.Flatten> {
|
|
6
6
|
|
|
7
7
|
constructor(
|
|
8
8
|
public teamId: Team.Id,
|
|
9
9
|
public personId: Person.Id
|
|
10
10
|
) {}
|
|
11
11
|
|
|
12
|
-
public createId():
|
|
12
|
+
public createId(): UserInvitation.Id {
|
|
13
13
|
const hasher = new Sha512();
|
|
14
14
|
const teamIdBytes = BytesCoder.fromUtf8(this.teamId.guidString);
|
|
15
15
|
const personIdBytes = BytesCoder.fromUtf8(this.personId.guidString);
|
|
16
16
|
const hashedInvitationBytes = hasher.hash(new Uint8Array([...teamIdBytes, ...personIdBytes]));
|
|
17
17
|
const rawId = BytesCoder.toHex(hashedInvitationBytes).slice(0, 12);
|
|
18
|
-
return new Tagged(rawId, '
|
|
18
|
+
return new Tagged(rawId, 'userInvitation');
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
public get flatten():
|
|
21
|
+
public get flatten(): UserInvitation.Flatten {
|
|
22
22
|
return {
|
|
23
23
|
teamId: this.teamId.flatten,
|
|
24
24
|
personId: this.personId.flatten
|
|
@@ -26,15 +26,15 @@ export class Invitation implements Flattable<Invitation.Flatten> {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export namespace
|
|
29
|
+
export namespace UserInvitation {
|
|
30
30
|
|
|
31
|
-
export type Id = Tagged<string, '
|
|
31
|
+
export type Id = Tagged<string, 'userInvitation'>;
|
|
32
32
|
|
|
33
33
|
export namespace Id {
|
|
34
34
|
|
|
35
35
|
export type Flatten = string;
|
|
36
36
|
|
|
37
|
-
export const builder = Tagged.builder('
|
|
37
|
+
export const builder = Tagged.builder('userInvitation' as const, new ValueTypeBuilder<string>());
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export type Flatten = {
|
|
@@ -42,10 +42,10 @@ export namespace Invitation {
|
|
|
42
42
|
personId: Person.Id.Flatten
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
export class TypeBuilder implements ITypeBuilder<Flatten,
|
|
45
|
+
export class TypeBuilder implements ITypeBuilder<Flatten, UserInvitation> {
|
|
46
46
|
|
|
47
|
-
public build(value: Flatten):
|
|
48
|
-
return new
|
|
47
|
+
public build(value: Flatten): UserInvitation {
|
|
48
|
+
return new UserInvitation(
|
|
49
49
|
Team.Id.builder.build(value.teamId),
|
|
50
50
|
Person.Id.builder.build(value.personId)
|
|
51
51
|
);
|
package/src/types/UserRole.ts
CHANGED
|
@@ -5,6 +5,7 @@ export type UserRole =
|
|
|
5
5
|
| 'person-manager'
|
|
6
6
|
| 'fineTemplate-manager'
|
|
7
7
|
| 'fine-manager'
|
|
8
|
+
| 'fine-can-add'
|
|
8
9
|
| 'team-manager';
|
|
9
10
|
|
|
10
11
|
export namespace UserRole {
|
|
@@ -13,6 +14,7 @@ export namespace UserRole {
|
|
|
13
14
|
'person-manager',
|
|
14
15
|
'fineTemplate-manager',
|
|
15
16
|
'fine-manager',
|
|
17
|
+
'fine-can-add',
|
|
16
18
|
'team-manager'
|
|
17
19
|
];
|
|
18
20
|
|
|
@@ -21,6 +23,7 @@ export namespace UserRole {
|
|
|
21
23
|
'person-manager': 'personManager',
|
|
22
24
|
'fineTemplate-manager': 'fineTemplateManager',
|
|
23
25
|
'fine-manager': 'fineManager',
|
|
26
|
+
'fine-can-add': 'fineCanAdd',
|
|
24
27
|
'team-manager': 'teamManager'
|
|
25
28
|
}
|
|
26
29
|
return Localization.shared.userRole[localizationKeyMap[role]].value();
|
package/src/types/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from './Fine';
|
|
|
3
3
|
export * from './FineAmount';
|
|
4
4
|
export * from './FineTemplate';
|
|
5
5
|
export * from './FineTemplateRepetition';
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './UserInvitation';
|
|
7
7
|
export * from './Localization';
|
|
8
8
|
export * from './MoneyAmount';
|
|
9
9
|
export * from './NotificationProperties';
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Invitation } from '../../types';
|
|
3
|
-
export declare class InvitationInviteFunction extends FirebaseFunction<Invitation, Invitation.Id> {
|
|
4
|
-
parametersBuilder: Invitation.TypeBuilder;
|
|
5
|
-
returnTypeBuilder: import("@stevenkellner/typescript-common-functionality").Tagged.TypeBuilder<string, "invitation">;
|
|
6
|
-
execute(invitation: Invitation): Promise<Invitation.Id>;
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Invitation, User } from '../../types';
|
|
3
|
-
export declare class InvitationRegisterFunction extends FirebaseFunction<Invitation.Id, User> {
|
|
4
|
-
parametersBuilder: import("@stevenkellner/typescript-common-functionality").Tagged.TypeBuilder<string, "invitation">;
|
|
5
|
-
returnTypeBuilder: User.TypeBuilder;
|
|
6
|
-
execute(invitationId: Invitation.Id): Promise<User>;
|
|
7
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { FirebaseFunction } from '@stevenkellner/firebase-function';
|
|
2
|
-
import { Invitation } from '../../types';
|
|
3
|
-
import { ValueTypeBuilder } from '@stevenkellner/typescript-common-functionality';
|
|
4
|
-
export declare class InvitationWithdrawFunction extends FirebaseFunction<Invitation, void> {
|
|
5
|
-
parametersBuilder: Invitation.TypeBuilder;
|
|
6
|
-
returnTypeBuilder: ValueTypeBuilder<void>;
|
|
7
|
-
execute(invitation: Invitation): Promise<void>;
|
|
8
|
-
}
|