@flink-app/generic-auth-plugin 0.12.1-alpha.7 → 0.13.0
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/.flink/generatedHandlers.ts +1 -1
- package/.flink/generatedJobs.ts +1 -1
- package/.flink/generatedRepos.ts +1 -1
- package/.flink/schemas/schemas.json +1 -643
- package/.flink/schemas/schemas.ts +1 -105
- package/.flink/start.ts +2 -1
- package/CHANGELOG.md +15 -0
- package/dist/.flink/generatedHandlers.js +1 -1
- package/dist/.flink/generatedJobs.js +1 -1
- package/dist/.flink/generatedRepos.js +1 -1
- package/dist/.flink/schemas/schemas.d.ts +0 -104
- package/dist/.flink/schemas/schemas.js +1 -1
- package/dist/.flink/schemas/schemas.json +1 -643
- package/dist/.flink/start.d.ts +2 -0
- package/dist/.flink/start.js +2 -1
- package/dist/src/coreFunctions.d.ts +5 -5
- package/dist/src/coreFunctions.js +31 -14
- package/dist/src/genericAuthContext.d.ts +8 -5
- package/dist/src/genericAuthPluginOptions.d.ts +6 -1
- package/dist/src/handlers/Management/DeleteUserByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/DeleteUserByUserid.js +3 -4
- package/dist/src/handlers/Management/GetSchema.d.ts +0 -1
- package/dist/src/handlers/Management/GetSchema.js +3 -4
- package/dist/src/handlers/Management/GetUser.d.ts +0 -1
- package/dist/src/handlers/Management/GetUser.js +3 -4
- package/dist/src/handlers/Management/GetUserByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/GetUserByUserid.js +3 -4
- package/dist/src/handlers/Management/GetUserViewByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/GetUserViewByUserid.js +3 -4
- package/dist/src/handlers/Management/PutUserPasswordByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/PutUserPasswordByUserid.js +3 -4
- package/dist/src/handlers/Management/PutUserProfileByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/PutUserProfileByUserid.js +16 -9
- package/dist/src/handlers/Management/PutUserProfileByUseridAppend.d.ts +0 -1
- package/dist/src/handlers/Management/PutUserProfileByUseridAppend.js +3 -4
- package/dist/src/handlers/Management/PutUserRolesByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/PutUserRolesByUserid.js +3 -4
- package/dist/src/handlers/Management/PutUserUsernameByUserid.d.ts +0 -1
- package/dist/src/handlers/Management/PutUserUsernameByUserid.js +3 -4
- package/dist/src/handlers/UserCreate.d.ts +0 -1
- package/dist/src/handlers/UserCreate.js +6 -7
- package/dist/src/handlers/UserLogin.d.ts +0 -1
- package/dist/src/handlers/UserLogin.js +42 -11
- package/dist/src/handlers/UserLoginByToken.d.ts +0 -1
- package/dist/src/handlers/UserLoginByToken.js +3 -4
- package/dist/src/handlers/UserPasswordPut.d.ts +0 -1
- package/dist/src/handlers/UserPasswordPut.js +3 -4
- package/dist/src/handlers/UserPasswordResetComplete.d.ts +0 -1
- package/dist/src/handlers/UserPasswordResetComplete.js +3 -4
- package/dist/src/handlers/UserPasswordResetForm.js +6 -6
- package/dist/src/handlers/UserPasswordResetStart.d.ts +0 -1
- package/dist/src/handlers/UserPasswordResetStart.js +3 -4
- package/dist/src/handlers/UserProfileGet.d.ts +0 -1
- package/dist/src/handlers/UserProfileGet.js +3 -4
- package/dist/src/handlers/UserProfilePut.d.ts +0 -1
- package/dist/src/handlers/UserProfilePut.js +11 -7
- package/dist/src/handlers/UserPushRegisterToken.d.ts +0 -1
- package/dist/src/handlers/UserPushRegisterToken.js +4 -5
- package/dist/src/handlers/UserPushRemoveToken.d.ts +0 -1
- package/dist/src/handlers/UserPushRemoveToken.js +3 -4
- package/dist/src/handlers/UserToken.d.ts +0 -1
- package/dist/src/handlers/UserToken.js +3 -4
- package/dist/src/index.js +2 -2
- package/dist/src/init.js +2 -3
- package/dist/src/schemas/User.d.ts +2 -1
- package/dist/src/schemas/UserCreateReq.d.ts +2 -1
- package/dist/src/schemas/UserPasswordResetCompleteRes.d.ts +4 -0
- package/package.json +32 -33
- package/readme.md +584 -570
- package/src/coreFunctions.ts +29 -7
- package/src/genericAuthContext.ts +8 -5
- package/src/genericAuthPluginOptions.ts +6 -1
- package/src/handlers/Management/PutUserProfileByUserid.ts +6 -0
- package/src/handlers/UserCreate.ts +3 -2
- package/src/handlers/UserLogin.ts +56 -31
- package/src/handlers/UserProfilePut.ts +20 -22
- package/src/handlers/UserPushRegisterToken.ts +1 -1
- package/src/index.ts +2 -1
- package/src/init.ts +108 -120
- package/src/schemas/User.ts +2 -1
- package/src/schemas/UserCreateReq.ts +5 -4
- package/src/schemas/UserPasswordResetCompleteRes.ts +8 -3
- package/tsconfig.json +21 -21
- package/CLAUDE.md +0 -32
package/src/coreFunctions.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FlinkRepo, FlinkAuthUser, log } from "@flink-app/flink";
|
|
1
|
+
import { FlinkRepo, FlinkAuthUser, log, FlinkRequest } from "@flink-app/flink";
|
|
2
2
|
import { JwtAuthPlugin, jwtAuthPlugin } from "@flink-app/jwt-auth-plugin";
|
|
3
3
|
|
|
4
4
|
import { User } from "./schemas/User";
|
|
@@ -45,7 +45,7 @@ export async function createUser(
|
|
|
45
45
|
auth: JwtAuthPlugin,
|
|
46
46
|
username: string,
|
|
47
47
|
password: string,
|
|
48
|
-
authentificationMethod: "password" | "sms",
|
|
48
|
+
authentificationMethod: "password" | "sms" | "bankid",
|
|
49
49
|
roles: string[],
|
|
50
50
|
profile: UserProfile,
|
|
51
51
|
createPasswordHashAndSaltMethod?: {
|
|
@@ -53,7 +53,8 @@ export async function createUser(
|
|
|
53
53
|
},
|
|
54
54
|
onUserCreated?: {
|
|
55
55
|
(user: User): Promise<void>;
|
|
56
|
-
}
|
|
56
|
+
},
|
|
57
|
+
personalNumber?: string
|
|
57
58
|
): Promise<UserCreateRes> {
|
|
58
59
|
if (!roles.includes("user")) roles.push("user");
|
|
59
60
|
|
|
@@ -71,6 +72,17 @@ export async function createUser(
|
|
|
71
72
|
pushNotificationTokens: [],
|
|
72
73
|
};
|
|
73
74
|
|
|
75
|
+
if (personalNumber) {
|
|
76
|
+
userData.personalNumber = personalNumber;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (authentificationMethod == "bankid") {
|
|
80
|
+
if (!personalNumber) {
|
|
81
|
+
log.warn("BankID login requested but no personal number found for user");
|
|
82
|
+
return { status: "error" };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
74
86
|
if (authentificationMethod == "password") {
|
|
75
87
|
let passwordAndSalt = null;
|
|
76
88
|
if (createPasswordHashAndSaltMethod != null) {
|
|
@@ -152,8 +164,9 @@ export async function loginUser(
|
|
|
152
164
|
},
|
|
153
165
|
smsOptions?: GenericAuthsmsOptions,
|
|
154
166
|
onSuccessfulLogin?: {
|
|
155
|
-
(user: User): Promise<void>;
|
|
156
|
-
}
|
|
167
|
+
(user: User, req?: FlinkRequest): Promise<void>;
|
|
168
|
+
},
|
|
169
|
+
req?: FlinkRequest
|
|
157
170
|
): Promise<UserLoginRes> {
|
|
158
171
|
const user = await repo.getOne({ username: username.toLowerCase() });
|
|
159
172
|
if (user == null) {
|
|
@@ -205,12 +218,21 @@ export async function loginUser(
|
|
|
205
218
|
validationToken: token,
|
|
206
219
|
};
|
|
207
220
|
}
|
|
221
|
+
if (user.authentificationMethod == "bankid") {
|
|
222
|
+
if (!user.personalNumber) {
|
|
223
|
+
log.warn("BankID login requested but no personal number found for user");
|
|
224
|
+
return { status: "failed" };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
log.warn("BankID login required to be handled in other way, i.e. using flink bankid plugin");
|
|
228
|
+
return { status: "failed" };
|
|
229
|
+
}
|
|
208
230
|
|
|
209
231
|
if (valid) {
|
|
210
232
|
const token = await auth.createToken({ username: username.toLowerCase(), _id: user._id }, user.roles);
|
|
211
233
|
|
|
212
234
|
if (onSuccessfulLogin) {
|
|
213
|
-
await onSuccessfulLogin(user);
|
|
235
|
+
await onSuccessfulLogin(user, req);
|
|
214
236
|
}
|
|
215
237
|
|
|
216
238
|
return {
|
|
@@ -382,7 +404,7 @@ export async function passwordResetComplete(
|
|
|
382
404
|
pwdResetStartedAt: null,
|
|
383
405
|
});
|
|
384
406
|
|
|
385
|
-
return { status: "success" };
|
|
407
|
+
return { status: "success", user };
|
|
386
408
|
}
|
|
387
409
|
|
|
388
410
|
function generate(n: number): string {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FlinkRepo } from "@flink-app/flink";
|
|
1
|
+
import { FlinkRepo, FlinkRequest } from "@flink-app/flink";
|
|
2
2
|
import { JwtAuthPlugin } from "@flink-app/jwt-auth-plugin";
|
|
3
3
|
import { User } from "./schemas/User";
|
|
4
4
|
import { UserCreateRes } from "./schemas/UserCreateRes";
|
|
@@ -19,7 +19,8 @@ export interface genericAuthContext {
|
|
|
19
19
|
password?: string,
|
|
20
20
|
validatePasswordMethod?: { (password: string, hash: string, salt: string): Promise<boolean> },
|
|
21
21
|
smsOptions?: GenericAuthsmsOptions,
|
|
22
|
-
onSuccessfulLogin?: (user: User) => Promise<void
|
|
22
|
+
onSuccessfulLogin?: (user: User, req?: FlinkRequest) => Promise<void>,
|
|
23
|
+
req?: FlinkRequest
|
|
23
24
|
): Promise<UserLoginRes>;
|
|
24
25
|
loginByToken(repo: FlinkRepo<any, User>, auth: JwtAuthPlugin, token: string, code: string, jwtSecret: string): Promise<UserLoginRes>;
|
|
25
26
|
createUser(
|
|
@@ -27,13 +28,14 @@ export interface genericAuthContext {
|
|
|
27
28
|
auth: JwtAuthPlugin,
|
|
28
29
|
username: string,
|
|
29
30
|
password: string,
|
|
30
|
-
authentificationMethod: "password" | "sms",
|
|
31
|
+
authentificationMethod: "password" | "sms" | "bankid",
|
|
31
32
|
roles: string[],
|
|
32
33
|
profile: UserProfile,
|
|
33
34
|
createPasswordHashAndSaltMethod?: {
|
|
34
35
|
(password: string): Promise<{ hash: string; salt: string } | null>;
|
|
35
36
|
},
|
|
36
|
-
onUserCreated?: (user: User) => Promise<void
|
|
37
|
+
onUserCreated?: (user: User) => Promise<void>,
|
|
38
|
+
personalNumber?: string
|
|
37
39
|
): Promise<UserCreateRes>;
|
|
38
40
|
changePassword(
|
|
39
41
|
repo: FlinkRepo<any, User>,
|
|
@@ -67,7 +69,8 @@ export interface genericAuthContext {
|
|
|
67
69
|
validatePasswordMethod?: { (password: string, hash: string, salt: string): Promise<boolean> };
|
|
68
70
|
usernameFormat: RegExp;
|
|
69
71
|
smsOptions?: GenericAuthsmsOptions;
|
|
70
|
-
onSuccessfulLogin?: { (user: User): Promise<void> };
|
|
72
|
+
onSuccessfulLogin?: { (user: User, req?: FlinkRequest): Promise<void> };
|
|
71
73
|
onUserCreated?: { (user: User): Promise<void> };
|
|
74
|
+
onUserUpdated?: { (user: User, updatedData: UserProfile): Promise<void> };
|
|
72
75
|
};
|
|
73
76
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { FlinkRequest } from "@flink-app/flink";
|
|
1
2
|
import { User } from "./schemas/User";
|
|
2
3
|
import { UserPasswordResetSettings } from "./schemas/UserPasswordResetSettings";
|
|
4
|
+
import { UserProfile } from "./schemas/UserProfile";
|
|
3
5
|
import { client as smsClient } from "@flink-app/sms-plugin";
|
|
4
6
|
export interface GenericAuthPluginOptions {
|
|
5
7
|
repoName: string;
|
|
@@ -23,11 +25,14 @@ export interface GenericAuthPluginOptions {
|
|
|
23
25
|
usernameFormat?: RegExp;
|
|
24
26
|
sms?: GenericAuthsmsOptions;
|
|
25
27
|
onSuccessfulLogin?: {
|
|
26
|
-
(user: User): Promise<void>;
|
|
28
|
+
(user: User, req?: FlinkRequest): Promise<void>;
|
|
27
29
|
};
|
|
28
30
|
onUserCreated?: {
|
|
29
31
|
(user: User): Promise<void>;
|
|
30
32
|
};
|
|
33
|
+
onUserUpdated?: {
|
|
34
|
+
(user: User, updatedData: UserProfile): Promise<void>;
|
|
35
|
+
};
|
|
31
36
|
/**
|
|
32
37
|
* If true, when a new device is registered, all other devices identified by `deviceId`
|
|
33
38
|
* will be deregistered to avoid duplicate notifications.
|
|
@@ -23,6 +23,12 @@ const PutManagementUserProfileByUserid: Handler<
|
|
|
23
23
|
|
|
24
24
|
await repo.updateOne(user._id, { profile: req.body });
|
|
25
25
|
|
|
26
|
+
const updatedUser = await repo.getById(req.params.userid);
|
|
27
|
+
|
|
28
|
+
if ((<any>ctx.plugins)[pluginName].onUserUpdated) {
|
|
29
|
+
await (<any>ctx.plugins)[pluginName].onUserUpdated(updatedUser, req.body);
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
return {
|
|
27
33
|
data: {},
|
|
28
34
|
status: 200,
|
|
@@ -5,7 +5,7 @@ import { UserCreateReq } from "../schemas/UserCreateReq";
|
|
|
5
5
|
import { UserCreateRes } from "../schemas/UserCreateRes";
|
|
6
6
|
|
|
7
7
|
const userCreateHandler: Handler<FlinkContext<genericAuthContext>, UserCreateReq, UserCreateRes> = async ({ ctx, req, origin }) => {
|
|
8
|
-
let { password, username, authentificationMethod, profile } = req.body;
|
|
8
|
+
let { password, username, authentificationMethod, profile, personalNumber } = req.body;
|
|
9
9
|
if (authentificationMethod == null) {
|
|
10
10
|
authentificationMethod = "password";
|
|
11
11
|
}
|
|
@@ -36,7 +36,8 @@ const userCreateHandler: Handler<FlinkContext<genericAuthContext>, UserCreateReq
|
|
|
36
36
|
roles,
|
|
37
37
|
profile,
|
|
38
38
|
(<any>ctx.plugins)[pluginName].createPasswordHashAndSaltMethod,
|
|
39
|
-
(<any>ctx.plugins)[pluginName].onUserCreated
|
|
39
|
+
(<any>ctx.plugins)[pluginName].onUserCreated,
|
|
40
|
+
personalNumber
|
|
40
41
|
);
|
|
41
42
|
if (createUserResponse.status != "success") {
|
|
42
43
|
switch (createUserResponse.status) {
|
|
@@ -1,41 +1,66 @@
|
|
|
1
|
-
import { FlinkContext, Handler, unauthorized } from "@flink-app/flink";
|
|
1
|
+
import { FlinkContext, FlinkResponse, Handler, internalServerError, log, unauthorized } from "@flink-app/flink";
|
|
2
|
+
import { JwtAuthPlugin } from "@flink-app/jwt-auth-plugin";
|
|
2
3
|
import { genericAuthContext } from "../genericAuthContext";
|
|
3
4
|
import { UserLoginReq } from "../schemas/UserLoginReq";
|
|
4
5
|
import { UserLoginRes } from "../schemas/UserLoginRes";
|
|
5
|
-
import { JwtAuthPlugin } from "@flink-app/jwt-auth-plugin";
|
|
6
6
|
|
|
7
|
-
const userLoginHandler: Handler<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
if (loginRespons.status != "success") {
|
|
26
|
-
switch (loginRespons.status) {
|
|
27
|
-
case "failed":
|
|
28
|
-
return unauthorized(
|
|
29
|
-
"Invalid username or password",
|
|
30
|
-
loginRespons.status
|
|
7
|
+
const userLoginHandler: Handler<FlinkContext<genericAuthContext>, UserLoginReq, UserLoginRes> = async ({ ctx, req, origin }) => {
|
|
8
|
+
let pluginName = origin || "genericAuthPlugin";
|
|
9
|
+
let repo = ctx.repos[(<any>ctx.plugins)[pluginName].repoName];
|
|
10
|
+
|
|
11
|
+
let loginResponse: UserLoginRes | undefined = undefined;
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
loginResponse = await ctx.plugins.genericAuthPlugin.loginUser(
|
|
15
|
+
repo,
|
|
16
|
+
<JwtAuthPlugin>ctx.auth,
|
|
17
|
+
req.body.username,
|
|
18
|
+
req.body.password,
|
|
19
|
+
ctx.plugins.genericAuthPlugin.validatePasswordMethod,
|
|
20
|
+
(<any>ctx.plugins)[pluginName].smsOptions,
|
|
21
|
+
(<any>ctx.plugins)[pluginName].onSuccessfulLogin,
|
|
22
|
+
req
|
|
31
23
|
);
|
|
24
|
+
} catch (error: any) {
|
|
25
|
+
// Convert any thrown error that conforms to flink error structure to a proper response
|
|
26
|
+
// Note that any auth failures would not have been thrown, but returned as part of loginResponse
|
|
27
|
+
// but with this it is possible to throw errors from callbacks like onSuccessfulLogin
|
|
28
|
+
if (isFlinkError(error)) {
|
|
29
|
+
log.debug("Caught FlinkError in userLoginHandler:", error);
|
|
30
|
+
return {
|
|
31
|
+
status: error.status,
|
|
32
|
+
error: {
|
|
33
|
+
id: error.error.id,
|
|
34
|
+
title: error.error.title,
|
|
35
|
+
code: error.error.code,
|
|
36
|
+
detail: error.error.detail,
|
|
37
|
+
},
|
|
38
|
+
} as FlinkResponse;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// For other errors, return a generic 500 response
|
|
42
|
+
log.error("Error in userLoginHandler:", error);
|
|
43
|
+
return internalServerError();
|
|
32
44
|
}
|
|
33
|
-
}
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
if (loginResponse?.status != "success") {
|
|
47
|
+
switch (loginResponse?.status) {
|
|
48
|
+
case "failed":
|
|
49
|
+
return unauthorized("Invalid username or password", loginResponse.status);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
data: loginResponse,
|
|
55
|
+
status: 200,
|
|
56
|
+
};
|
|
39
57
|
};
|
|
40
58
|
|
|
41
59
|
export default userLoginHandler;
|
|
60
|
+
|
|
61
|
+
function isFlinkError(res: any) {
|
|
62
|
+
if (res && res.status && typeof res.status === "number" && res.error && res.error.id) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
@@ -2,34 +2,32 @@ import { FlinkContext, Handler, notFound } from "@flink-app/flink";
|
|
|
2
2
|
import { genericAuthContext } from "../genericAuthContext";
|
|
3
3
|
import { UserProfile } from "../schemas/UserProfile";
|
|
4
4
|
|
|
5
|
-
const putUserProfileHandler: Handler<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
UserProfile
|
|
9
|
-
> = async ({ ctx, req, origin }) => {
|
|
10
|
-
let pluginName = origin || "genericAuthPlugin";
|
|
11
|
-
let repo = ctx.repos[(<any>ctx.plugins)[pluginName].repoName];
|
|
5
|
+
const putUserProfileHandler: Handler<FlinkContext<genericAuthContext>, UserProfile, UserProfile> = async ({ ctx, req, origin }) => {
|
|
6
|
+
let pluginName = origin || "genericAuthPlugin";
|
|
7
|
+
let repo = ctx.repos[(<any>ctx.plugins)[pluginName].repoName];
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
let userId = req.user._id;
|
|
10
|
+
let user = await repo.getById(userId);
|
|
11
|
+
if (user == null) {
|
|
12
|
+
return notFound();
|
|
13
|
+
}
|
|
18
14
|
|
|
15
|
+
const updatedProfile = {
|
|
16
|
+
...user.profile,
|
|
17
|
+
...req.body,
|
|
18
|
+
};
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
...user.profile,
|
|
22
|
-
...req.body,
|
|
23
|
-
}
|
|
20
|
+
await repo.updateOne(userId, { profile: updatedProfile });
|
|
24
21
|
|
|
22
|
+
user = await repo.getById(userId);
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
if ((<any>ctx.plugins)[pluginName].onUserUpdated) {
|
|
25
|
+
await (<any>ctx.plugins)[pluginName].onUserUpdated(user, req.body);
|
|
26
|
+
}
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
data: user.profile,
|
|
32
|
-
};
|
|
28
|
+
return {
|
|
29
|
+
data: user.profile,
|
|
30
|
+
};
|
|
33
31
|
};
|
|
34
32
|
|
|
35
33
|
export default putUserProfileHandler;
|
|
@@ -43,7 +43,7 @@ const postUserPushRegisterTokenHandler: Handler<FlinkContext<genericAuthContext>
|
|
|
43
43
|
if (deregisterOtherDevices) {
|
|
44
44
|
const otherRegistrations = <User[]>await repo.findAll({
|
|
45
45
|
$or: [{ "pushNotificationTokens.deviceId": req.body.deviceId }, { "pushNotificationTokens.token": req.body.token }],
|
|
46
|
-
_id: { $ne: user._id },
|
|
46
|
+
_id: { $ne: repo.buildId(user._id) },
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
log.debug(`Found ${otherRegistrations.length} other registrations for device ${req.body.deviceId} or token ${req.body.token}`);
|
package/src/index.ts
CHANGED
|
@@ -12,7 +12,7 @@ export * from "./management";
|
|
|
12
12
|
export const genericAuthPlugin = (options: GenericAuthPluginOptions): FlinkPlugin => {
|
|
13
13
|
if (options.pluginId == null) options.pluginId = "genericAuthPlugin";
|
|
14
14
|
|
|
15
|
-
const { sms, usernameFormat, ...restOptions } = options;
|
|
15
|
+
const { sms, usernameFormat, onUserUpdated, ...restOptions } = options;
|
|
16
16
|
|
|
17
17
|
return {
|
|
18
18
|
id: options.pluginId,
|
|
@@ -27,6 +27,7 @@ export const genericAuthPlugin = (options: GenericAuthPluginOptions): FlinkPlugi
|
|
|
27
27
|
passwordResetComplete,
|
|
28
28
|
usernameFormat: usernameFormat || /.{1,}$/,
|
|
29
29
|
smsOptions: sms,
|
|
30
|
+
onUserUpdated,
|
|
30
31
|
},
|
|
31
32
|
};
|
|
32
33
|
};
|
package/src/init.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FlinkApp, HttpMethod } from "@flink-app/flink";
|
|
1
|
+
import { FlinkApp, HttpMethod, ExpressRequest, ExpressResponse } from "@flink-app/flink";
|
|
2
2
|
import * as userLoginHandler from "./handlers/UserLogin";
|
|
3
3
|
import * as userLoginByTokenHandler from "./handlers/UserLoginByToken";
|
|
4
4
|
import * as userCreateHandler from "./handlers/UserCreate";
|
|
@@ -11,140 +11,128 @@ import { GenericAuthPluginOptions } from "./genericAuthPluginOptions";
|
|
|
11
11
|
import * as postUserPushRegisterTokenHandler from "./handlers/UserPushRegisterToken";
|
|
12
12
|
import * as postUserRemoveTokenHandler from "./handlers/UserPushRemoveToken";
|
|
13
13
|
import * as getUserTokenHandler from "./handlers/UserToken";
|
|
14
|
-
import {
|
|
15
|
-
handleUserPasswordResetForm,
|
|
16
|
-
resetPasswordFormCss,
|
|
17
|
-
resetPasswordFormScript,
|
|
18
|
-
} from "./handlers/UserPasswordResetForm";
|
|
14
|
+
import { handleUserPasswordResetForm, resetPasswordFormCss, resetPasswordFormScript } from "./handlers/UserPasswordResetForm";
|
|
19
15
|
|
|
20
16
|
export function init(app: FlinkApp<any>, options: GenericAuthPluginOptions) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (options.baseUrl == null) options.baseUrl = "/user";
|
|
17
|
+
if (options.enableUserCreation == null) options.enableUserCreation = true;
|
|
18
|
+
if (options.enableProfileUpdate == null) options.enableProfileUpdate = true;
|
|
19
|
+
if (options.enablePasswordUpdate == null) options.enablePasswordUpdate = true;
|
|
20
|
+
if (options.enableUserLogin == null) options.enableUserLogin = true;
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
if(options.enableUserLogin){
|
|
30
|
-
app.addHandler(userLoginHandler, {
|
|
31
|
-
method: HttpMethod.post,
|
|
32
|
-
path: options.baseUrl + "/login",
|
|
33
|
-
docs: "Authenticates a user",
|
|
34
|
-
origin: options.pluginId,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
if(options.sms){
|
|
38
|
-
app.addHandler(userLoginByTokenHandler, {
|
|
39
|
-
method: HttpMethod.post,
|
|
40
|
-
path: options.baseUrl + "/login-by-token",
|
|
41
|
-
docs: "Authenticates a user by token",
|
|
42
|
-
origin: options.pluginId,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
if (options.enableUserCreation) {
|
|
46
|
-
app.addHandler(userCreateHandler, {
|
|
47
|
-
method: HttpMethod.post,
|
|
48
|
-
path: options.baseUrl + "/create",
|
|
49
|
-
docs: "Creates a new user",
|
|
50
|
-
origin: options.pluginId,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
22
|
+
if (options.baseUrl == null) options.baseUrl = "/user";
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
24
|
+
if (options.enableRoutes) {
|
|
25
|
+
if (options.enableUserLogin) {
|
|
26
|
+
app.addHandler(userLoginHandler, {
|
|
27
|
+
method: HttpMethod.post,
|
|
28
|
+
path: options.baseUrl + "/login",
|
|
29
|
+
docs: "Authenticates a user",
|
|
30
|
+
origin: options.pluginId,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (options.sms) {
|
|
34
|
+
app.addHandler(userLoginByTokenHandler, {
|
|
35
|
+
method: HttpMethod.post,
|
|
36
|
+
path: options.baseUrl + "/login-by-token",
|
|
37
|
+
docs: "Authenticates a user by token",
|
|
38
|
+
origin: options.pluginId,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (options.enableUserCreation) {
|
|
42
|
+
app.addHandler(userCreateHandler, {
|
|
43
|
+
method: HttpMethod.post,
|
|
44
|
+
path: options.baseUrl + "/create",
|
|
45
|
+
docs: "Creates a new user",
|
|
46
|
+
origin: options.pluginId,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
50
|
+
app.addHandler(getProfileHandler, {
|
|
51
|
+
method: HttpMethod.get,
|
|
52
|
+
path: options.baseUrl + "/profile",
|
|
53
|
+
docs: "Gets the user profile",
|
|
54
|
+
permissions: "authenticated",
|
|
55
|
+
origin: options.pluginId,
|
|
56
|
+
});
|
|
69
57
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
});
|
|
78
|
-
}
|
|
58
|
+
app.addHandler(getUserTokenHandler, {
|
|
59
|
+
method: HttpMethod.get,
|
|
60
|
+
path: options.baseUrl + "/token",
|
|
61
|
+
docs: "Gets a refreshed token for the user",
|
|
62
|
+
permissions: "authenticated",
|
|
63
|
+
origin: options.pluginId,
|
|
64
|
+
});
|
|
79
65
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
66
|
+
if (options.enableProfileUpdate) {
|
|
67
|
+
app.addHandler(putUserProfileHandler, {
|
|
68
|
+
method: HttpMethod.put,
|
|
69
|
+
path: options.baseUrl + "/profile",
|
|
70
|
+
docs: "Updates the user profile",
|
|
71
|
+
permissions: "authenticated",
|
|
72
|
+
origin: options.pluginId,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
89
75
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
if (options.enablePasswordUpdate) {
|
|
77
|
+
app.addHandler(putUserPasswordHandler, {
|
|
78
|
+
method: HttpMethod.put,
|
|
79
|
+
path: options.baseUrl + "/password",
|
|
80
|
+
docs: "Updates the user password",
|
|
81
|
+
permissions: "authenticated",
|
|
82
|
+
origin: options.pluginId,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
97
85
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
86
|
+
if (options.enablePasswordReset) {
|
|
87
|
+
app.addHandler(postPasswordResetStartHandler, {
|
|
88
|
+
method: HttpMethod.post,
|
|
89
|
+
path: options.baseUrl + "/password/reset",
|
|
90
|
+
docs: "Start the password reset process for a user",
|
|
91
|
+
origin: options.pluginId,
|
|
92
|
+
});
|
|
104
93
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
completeUrl: options.baseUrl + "/password/reset/complete",
|
|
112
|
-
})
|
|
113
|
-
);
|
|
114
|
-
app.expressApp?.get(
|
|
115
|
-
options.baseUrl + "/password/reset/form/script.js",
|
|
116
|
-
(req, res) => {
|
|
117
|
-
resetPasswordFormScript(req, res, { completeUrl: options.baseUrl + "/password/reset/complete"});
|
|
118
|
-
}
|
|
119
|
-
);
|
|
94
|
+
app.addHandler(postPasswordResetCompleteHandler, {
|
|
95
|
+
method: HttpMethod.post,
|
|
96
|
+
path: options.baseUrl + "/password/reset/complete",
|
|
97
|
+
docs: "Completes a password reset for a user",
|
|
98
|
+
origin: options.pluginId,
|
|
99
|
+
});
|
|
120
100
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
101
|
+
if (options.passwordResetSettings?.enablePasswordResetForm) {
|
|
102
|
+
app.expressApp?.get(options.baseUrl + "/password/reset/form", (req: ExpressRequest, res: ExpressResponse) =>
|
|
103
|
+
handleUserPasswordResetForm(req, res, {
|
|
104
|
+
templateFile: options.passwordResetSettings?.passwordResetForm,
|
|
105
|
+
completeUrl: options.baseUrl + "/password/reset/complete",
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
app.expressApp?.get(options.baseUrl + "/password/reset/form/script.js", (req: ExpressRequest, res: ExpressResponse) => {
|
|
109
|
+
resetPasswordFormScript(req, res, { completeUrl: options.baseUrl + "/password/reset/complete" });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
app.expressApp?.get(options.baseUrl + "/password/reset/form/style.css", (_req: ExpressRequest, res: ExpressResponse) => {
|
|
113
|
+
resetPasswordFormCss(res);
|
|
114
|
+
});
|
|
125
115
|
}
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
}
|
|
116
|
+
}
|
|
129
117
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
if (options.enablePushNotificationTokens) {
|
|
119
|
+
app.addHandler(postUserPushRegisterTokenHandler, {
|
|
120
|
+
method: HttpMethod.post,
|
|
121
|
+
path: options.baseUrl + "/push",
|
|
122
|
+
docs: "Register a push notification on current user",
|
|
123
|
+
permissions: "authenticated",
|
|
124
|
+
origin: options.pluginId,
|
|
125
|
+
});
|
|
138
126
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
127
|
+
app.addHandler(postUserRemoveTokenHandler, {
|
|
128
|
+
method: HttpMethod.delete,
|
|
129
|
+
path: options.baseUrl + "/push",
|
|
130
|
+
docs: "Removes a push notification token from current user",
|
|
131
|
+
permissions: "authenticated",
|
|
132
|
+
origin: options.pluginId,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
146
135
|
}
|
|
147
|
-
}
|
|
148
136
|
}
|
|
149
137
|
|
|
150
138
|
export {};
|
package/src/schemas/User.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { UserProfile } from "./UserProfile";
|
|
|
4
4
|
export interface User {
|
|
5
5
|
_id: string;
|
|
6
6
|
username: string;
|
|
7
|
+
personalNumber?: string;
|
|
7
8
|
|
|
8
9
|
password?: string;
|
|
9
10
|
salt?: string;
|
|
@@ -11,7 +12,7 @@ export interface User {
|
|
|
11
12
|
pwdResetStartedAt?: string | null;
|
|
12
13
|
roles: string[];
|
|
13
14
|
|
|
14
|
-
authentificationMethod: "password" | "sms";
|
|
15
|
+
authentificationMethod: "password" | "sms" | "bankid";
|
|
15
16
|
profile: UserProfile;
|
|
16
17
|
pushNotificationTokens: Array<PushNotificationToken>;
|
|
17
18
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { UserProfile } from "./UserProfile";
|
|
2
2
|
|
|
3
|
-
export interface UserCreateReq{
|
|
3
|
+
export interface UserCreateReq {
|
|
4
4
|
username: string;
|
|
5
5
|
password?: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
personalNumber?: string;
|
|
7
|
+
authentificationMethod?: "password" | "sms" | "bankid";
|
|
8
|
+
profile?: UserProfile;
|
|
9
|
+
}
|