@flink-app/generic-auth-plugin 0.3.0 → 0.3.3

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.
@@ -11,314 +11,289 @@ import { UserPasswordResetCompleteRes } from "./schemas/UserPasswordResetComplet
11
11
 
12
12
  import jsonwebtoken from "jsonwebtoken";
13
13
 
14
- export function getJtwTokenPlugin(
15
- secret: string,
16
- rolePermissions?: { [role: string]: string[] },
17
- passwordPolicy?: RegExp
18
- ) {
19
- if (passwordPolicy == undefined) {
20
- passwordPolicy = /.{1,}$/;
21
- }
22
- if (rolePermissions == undefined) {
23
- rolePermissions = {};
24
- }
25
- if (rolePermissions["user"] == null) {
26
- rolePermissions["user"] = [];
27
- }
28
- if (!rolePermissions["user"].includes("authenticated"))
29
- rolePermissions["user"].push("authenticated");
30
-
31
- return jwtAuthPlugin({
32
- secret,
33
- getUser: (tokenData: any) => {
34
- return new Promise<FlinkAuthUser>((res) => {
35
- res({
36
- username: tokenData.username,
37
- _id: tokenData._id,
38
- });
39
- });
40
- },
41
- passwordPolicy,
42
- rolePermissions,
43
- });
14
+ export function getJtwTokenPlugin(secret: string, rolePermissions?: { [role: string]: string[] }, passwordPolicy?: RegExp) {
15
+ if (passwordPolicy == undefined) {
16
+ passwordPolicy = /.{1,}$/;
17
+ }
18
+ if (rolePermissions == undefined) {
19
+ rolePermissions = {};
20
+ }
21
+ if (rolePermissions["user"] == null) {
22
+ rolePermissions["user"] = [];
23
+ }
24
+ if (!rolePermissions["user"].includes("authenticated")) rolePermissions["user"].push("authenticated");
25
+
26
+ return jwtAuthPlugin({
27
+ secret,
28
+ getUser: (tokenData: any) => {
29
+ return new Promise<FlinkAuthUser>((res) => {
30
+ res({
31
+ username: tokenData.username,
32
+ _id: tokenData._id,
33
+ });
34
+ });
35
+ },
36
+ passwordPolicy,
37
+ rolePermissions,
38
+ });
44
39
  }
45
40
 
46
41
  export async function createUser(
47
- repo: FlinkRepo<any, User>,
48
- auth: JwtAuthPlugin,
49
- username: string,
50
- password: string,
51
- authentificationMethod: "password" | "sms",
52
- roles: string[],
53
- profile: UserProfile,
54
- createPasswordHashAndSaltMethod?: {
55
- (password: string): Promise<{ hash: string; salt: string } | null>;
56
- }
42
+ repo: FlinkRepo<any, User>,
43
+ auth: JwtAuthPlugin,
44
+ username: string,
45
+ password: string,
46
+ authentificationMethod: "password" | "sms",
47
+ roles: string[],
48
+ profile: UserProfile,
49
+ createPasswordHashAndSaltMethod?: {
50
+ (password: string): Promise<{ hash: string; salt: string } | null>;
51
+ }
57
52
  ): Promise<UserCreateRes> {
58
- if (!roles.includes("user")) roles.push("user");
53
+ if (!roles.includes("user")) roles.push("user");
59
54
 
60
- const existingUser = await repo.getOne({ username: username.toLowerCase() });
61
- if (existingUser != null) {
62
- return {
63
- status: "userExists",
64
- };
65
- }
66
- let userData: Omit<User, "_id"> = {
67
- username,
68
- roles,
69
- profile,
70
- authentificationMethod,
71
- pushNotificationTokens: [],
72
- };
73
-
74
- if (authentificationMethod == "password") {
75
- let passwordAndSalt = null;
76
- if (createPasswordHashAndSaltMethod != null) {
77
- passwordAndSalt = await createPasswordHashAndSaltMethod(password);
78
- } else {
79
- passwordAndSalt = await auth.createPasswordHashAndSalt(password);
55
+ const existingUser = await repo.getOne({ username: username.toLowerCase() });
56
+ if (existingUser != null) {
57
+ return {
58
+ status: "userExists",
59
+ };
80
60
  }
61
+ let userData: Omit<User, "_id"> = {
62
+ username: username.toLowerCase(),
63
+ roles,
64
+ profile,
65
+ authentificationMethod,
66
+ pushNotificationTokens: [],
67
+ };
81
68
 
82
- if (passwordAndSalt == null) {
83
- return {
84
- status: "passwordError",
85
- };
69
+ if (authentificationMethod == "password") {
70
+ let passwordAndSalt = null;
71
+ if (createPasswordHashAndSaltMethod != null) {
72
+ passwordAndSalt = await createPasswordHashAndSaltMethod(password);
73
+ } else {
74
+ passwordAndSalt = await auth.createPasswordHashAndSalt(password);
75
+ }
76
+
77
+ if (passwordAndSalt == null) {
78
+ return {
79
+ status: "passwordError",
80
+ };
81
+ }
82
+ userData.password = passwordAndSalt.hash;
83
+ userData.salt = passwordAndSalt.salt;
86
84
  }
87
- userData.password = passwordAndSalt.hash;
88
- userData.salt = passwordAndSalt.salt;
89
- }
90
-
91
- const user = await repo.create(userData);
92
-
93
- const token = await auth.createToken(
94
- { username: username.toLowerCase(), _id: user._id },
95
- roles
96
- );
97
-
98
- return {
99
- status: "success",
100
- user: {
101
- _id: user._id,
102
- token: token,
103
- username: username.toLowerCase(),
104
- },
105
- };
85
+
86
+ const user = await repo.create(userData);
87
+
88
+ const token = await auth.createToken({ username: username.toLowerCase(), _id: user._id }, roles);
89
+
90
+ return {
91
+ status: "success",
92
+ user: {
93
+ _id: user._id,
94
+ token: token,
95
+ username: username.toLowerCase(),
96
+ },
97
+ };
106
98
  }
107
99
 
108
100
  export async function loginUser(
109
- repo: FlinkRepo<any, User>,
110
- auth: JwtAuthPlugin,
111
- username: string,
112
- password: string | undefined,
113
- validatePasswordMethod?: {
114
- (password: string, hash: string, salt: string): Promise<boolean>;
115
- }
101
+ repo: FlinkRepo<any, User>,
102
+ auth: JwtAuthPlugin,
103
+ username: string,
104
+ password: string | undefined,
105
+ validatePasswordMethod?: {
106
+ (password: string, hash: string, salt: string): Promise<boolean>;
107
+ }
116
108
  ): Promise<UserLoginRes> {
117
- const user = await repo.getOne({ username: username.toLowerCase() });
118
- if (user == null) {
119
- return { status: "failed" };
120
- }
121
-
122
- let valid: boolean = false;
123
-
124
- if (user.authentificationMethod == "password") {
125
- if (password == null) password = "";
126
-
127
- if (validatePasswordMethod != null) {
128
- valid = await validatePasswordMethod(
129
- password,
130
- <string>user.password,
131
- <string>user.salt
132
- );
133
-
134
- //If not valid, try to use default auth
135
- if (!valid) {
136
- try {
137
- valid = await auth.validatePassword(
138
- password,
139
- <string>user.password,
140
- <string>user.salt
141
- );
142
- } catch (ex) {}
143
- }
144
- } else {
145
- valid = await auth.validatePassword(
146
- password,
147
- <string>user.password,
148
- <string>user.salt
149
- );
109
+ const user = await repo.getOne({ username: username.toLowerCase() });
110
+ if (user == null) {
111
+ return { status: "failed" };
150
112
  }
151
- }
152
- if (user.authentificationMethod == "sms") {
153
- log.error("SMS login is not yet impleted.");
154
- return { status: "failed" };
155
- }
156
-
157
- if (valid) {
158
- const token = await auth.createToken(
159
- { username: username.toLowerCase(), _id: user._id },
160
- user.roles
161
- );
162
113
 
163
- return {
164
- status: "success",
165
- user: {
166
- _id: user._id,
167
- username: user.username,
168
- token,
169
- profile: user.profile,
170
- },
171
- };
172
- } else {
173
- return { status: "failed" };
174
- }
114
+ let valid: boolean = false;
115
+
116
+ if (user.authentificationMethod == "password") {
117
+ if (password == null) password = "";
118
+
119
+ if (validatePasswordMethod != null) {
120
+ valid = await validatePasswordMethod(password, <string>user.password, <string>user.salt);
121
+
122
+ //If not valid, try to use default auth
123
+ if (!valid) {
124
+ try {
125
+ valid = await auth.validatePassword(password, <string>user.password, <string>user.salt);
126
+ } catch (ex) {}
127
+ }
128
+ } else {
129
+ valid = await auth.validatePassword(password, <string>user.password, <string>user.salt);
130
+ }
131
+ }
132
+ if (user.authentificationMethod == "sms") {
133
+ log.error("SMS login is not yet impleted.");
134
+ return { status: "failed" };
135
+ }
136
+
137
+ if (valid) {
138
+ const token = await auth.createToken({ username: username.toLowerCase(), _id: user._id }, user.roles);
139
+
140
+ return {
141
+ status: "success",
142
+ user: {
143
+ _id: user._id,
144
+ username: user.username,
145
+ token,
146
+ profile: user.profile,
147
+ },
148
+ };
149
+ } else {
150
+ return { status: "failed" };
151
+ }
175
152
  }
176
153
 
177
154
  export async function changePassword(
178
- repo: FlinkRepo<any, User>,
179
- auth: JwtAuthPlugin,
180
- userId: string,
181
- newPassword: string,
182
- createPasswordHashAndSaltMethod?: {
183
- (password: string): Promise<{ hash: string; salt: string } | null>;
184
- }
155
+ repo: FlinkRepo<any, User>,
156
+ auth: JwtAuthPlugin,
157
+ userId: string,
158
+ newPassword: string,
159
+ createPasswordHashAndSaltMethod?: {
160
+ (password: string): Promise<{ hash: string; salt: string } | null>;
161
+ }
185
162
  ): Promise<UserPasswordChangeRes> {
186
- const user = await repo.getById(userId);
187
- if (user == null) {
188
- return { status: "failed" };
189
- }
163
+ const user = await repo.getById(userId);
164
+ if (user == null) {
165
+ return { status: "failed" };
166
+ }
190
167
 
191
- if (user.authentificationMethod != "password") {
192
- return { status: "failed" };
193
- }
168
+ if (user.authentificationMethod != "password") {
169
+ return { status: "failed" };
170
+ }
194
171
 
195
- let passwordAndSalt = null;
172
+ let passwordAndSalt = null;
196
173
 
197
- if (createPasswordHashAndSaltMethod == null) {
198
- passwordAndSalt = await auth.createPasswordHashAndSalt(newPassword);
199
- } else {
200
- passwordAndSalt = await createPasswordHashAndSaltMethod(newPassword);
201
- }
174
+ if (createPasswordHashAndSaltMethod == null) {
175
+ passwordAndSalt = await auth.createPasswordHashAndSalt(newPassword);
176
+ } else {
177
+ passwordAndSalt = await createPasswordHashAndSaltMethod(newPassword);
178
+ }
202
179
 
203
- if (passwordAndSalt == null) {
204
- return {
205
- status: "passwordError",
206
- };
207
- }
180
+ if (passwordAndSalt == null) {
181
+ return {
182
+ status: "passwordError",
183
+ };
184
+ }
208
185
 
209
- await repo.updateOne(userId, {
210
- password: passwordAndSalt.hash,
211
- salt: passwordAndSalt.salt,
212
- });
186
+ await repo.updateOne(userId, {
187
+ password: passwordAndSalt.hash,
188
+ salt: passwordAndSalt.salt,
189
+ });
213
190
 
214
- return { status: "success" };
191
+ return { status: "success" };
215
192
  }
216
193
 
217
194
  export async function passwordResetStart(
218
- repo: FlinkRepo<any, User>,
219
- auth: JwtAuthPlugin,
220
- jwtSecret: string,
221
- username: string,
222
- numberOfDigits?: number,
223
- lifeTime?: string
195
+ repo: FlinkRepo<any, User>,
196
+ auth: JwtAuthPlugin,
197
+ jwtSecret: string,
198
+ username: string,
199
+ numberOfDigits?: number,
200
+ lifeTime?: string
224
201
  ): Promise<UserPasswordResetStartRes> {
225
- const user = await repo.getOne({ username: username.toLowerCase() });
226
- if (user == null) {
227
- return { status: "userNotFound" };
228
- }
229
-
230
- if (user.authentificationMethod != "password") {
231
- return { status: "userNotFound" };
232
- }
233
-
234
- if (numberOfDigits == null) numberOfDigits = 6;
235
- if (lifeTime == null) lifeTime = "1h";
236
-
237
- const payload = {
238
- type: "passwordReset",
239
- username: username.toLocaleLowerCase(),
240
- };
241
- const code = generate(numberOfDigits);
242
-
243
- const secret = jwtSecret + ":" + code;
244
-
245
- const options: jsonwebtoken.SignOptions = {
246
- expiresIn: lifeTime,
247
- };
248
-
249
- const token = jsonwebtoken.sign(payload, secret, options);
250
-
251
- return {
252
- status: "success",
253
- passwordResetToken: token,
254
- code,
255
- profile: user.profile,
256
- };
257
- }
202
+ const user = await repo.getOne({ username: username.toLowerCase() });
203
+ if (user == null) {
204
+ return { status: "userNotFound" };
205
+ }
206
+
207
+ if (user.authentificationMethod != "password") {
208
+ return { status: "userNotFound" };
209
+ }
210
+
211
+ if (numberOfDigits == null) numberOfDigits = 6;
212
+ if (lifeTime == null) lifeTime = "1h";
213
+
214
+ const payload = {
215
+ type: "passwordReset",
216
+ username: username.toLocaleLowerCase(),
217
+ };
218
+ const code = generate(numberOfDigits);
258
219
 
259
- export async function passwordResetComplete(
260
- repo: FlinkRepo<any, User>,
261
- auth: JwtAuthPlugin,
262
- jwtSecret: string,
263
- passwordResetToken: string,
264
- code: string,
265
- newPassword: string,
266
- createPasswordHashAndSaltMethod?: {
267
- (password: string): Promise<{ hash: string; salt: string } | null>;
268
- }
269
- ): Promise<UserPasswordResetCompleteRes> {
270
- let payload: { type: string; username: string } = { type: "", username: "" };
271
- try {
272
220
  const secret = jwtSecret + ":" + code;
273
- payload = <{ type: string; username: string }>(
274
- jsonwebtoken.verify(passwordResetToken, secret)
275
- );
276
- } catch (ex) {
277
- return { status: "invalidCode" };
278
- }
279
-
280
- const user = await repo.getOne({ username: payload.username });
281
- if (user == null) {
282
- return { status: "userNotFound" };
283
- }
284
-
285
- if (user.authentificationMethod != "password") {
286
- return { status: "userNotFound" };
287
- }
288
-
289
- let passwordAndSalt = null;
290
-
291
- if (createPasswordHashAndSaltMethod == null) {
292
- passwordAndSalt = await auth.createPasswordHashAndSalt(newPassword);
293
- } else {
294
- passwordAndSalt = await createPasswordHashAndSaltMethod(newPassword);
295
- }
296
-
297
- if (passwordAndSalt == null) {
221
+
222
+ const options: jsonwebtoken.SignOptions = {
223
+ expiresIn: lifeTime,
224
+ };
225
+
226
+ const token = jsonwebtoken.sign(payload, secret, options);
227
+
298
228
  return {
299
- status: "passwordError",
229
+ status: "success",
230
+ passwordResetToken: token,
231
+ code,
232
+ profile: user.profile,
300
233
  };
301
- }
234
+ }
302
235
 
303
- await repo.updateOne(user._id, {
304
- password: passwordAndSalt.hash,
305
- salt: passwordAndSalt.salt,
306
- });
236
+ export async function passwordResetComplete(
237
+ repo: FlinkRepo<any, User>,
238
+ auth: JwtAuthPlugin,
239
+ jwtSecret: string,
240
+ passwordResetToken: string,
241
+ code: string,
242
+ newPassword: string,
243
+ createPasswordHashAndSaltMethod?: {
244
+ (password: string): Promise<{ hash: string; salt: string } | null>;
245
+ }
246
+ ): Promise<UserPasswordResetCompleteRes> {
247
+ let payload: { type: string; username: string } = { type: "", username: "" };
248
+ try {
249
+ const secret = jwtSecret + ":" + code;
250
+ payload = <{ type: string; username: string }>jsonwebtoken.verify(passwordResetToken, secret);
251
+ } catch (ex) {
252
+ return { status: "invalidCode" };
253
+ }
254
+
255
+ const user = await repo.getOne({ username: payload.username });
256
+ if (user == null) {
257
+ return { status: "userNotFound" };
258
+ }
259
+
260
+ if (user.authentificationMethod != "password") {
261
+ return { status: "userNotFound" };
262
+ }
263
+
264
+ let passwordAndSalt = null;
307
265
 
308
- return { status: "success" };
266
+ if (createPasswordHashAndSaltMethod == null) {
267
+ passwordAndSalt = await auth.createPasswordHashAndSalt(newPassword);
268
+ } else {
269
+ passwordAndSalt = await createPasswordHashAndSaltMethod(newPassword);
270
+ }
271
+
272
+ if (passwordAndSalt == null) {
273
+ return {
274
+ status: "passwordError",
275
+ };
276
+ }
277
+
278
+ await repo.updateOne(user._id, {
279
+ password: passwordAndSalt.hash,
280
+ salt: passwordAndSalt.salt,
281
+ });
282
+
283
+ return { status: "success" };
309
284
  }
310
285
 
311
286
  function generate(n: number): string {
312
- var add = 1,
313
- max = 12 - add;
287
+ var add = 1,
288
+ max = 12 - add;
314
289
 
315
- if (n > max) {
316
- return generate(max) + generate(n - max);
317
- }
290
+ if (n > max) {
291
+ return generate(max) + generate(n - max);
292
+ }
318
293
 
319
- max = Math.pow(10, n + add);
320
- var min = max / 10;
321
- var number = Math.floor(Math.random() * (max - min + 1)) + min;
294
+ max = Math.pow(10, n + add);
295
+ var min = max / 10;
296
+ var number = Math.floor(Math.random() * (max - min + 1)) + min;
322
297
 
323
- return ("" + number).substring(add);
298
+ return ("" + number).substring(add);
324
299
  }
@@ -0,0 +1,38 @@
1
+ import { FlinkContext, Handler, HttpMethod, notFound, RouteProps } from "@flink-app/flink";
2
+ import { User } from "../..";
3
+ import { GetManagementUserViewByUseridReq } from "../../schemas/Management/GetUserViewByUseridReq";
4
+ import { GetManagementUserViewByUseridRes } from "../../schemas/Management/GetUserViewByUseridRes";
5
+
6
+ const GetManagementUserByUserid: Handler<FlinkContext, GetManagementUserViewByUseridReq, GetManagementUserViewByUseridRes> = async ({ ctx, req, origin }) => {
7
+ let pluginName = origin || "genericAuthPlugin";
8
+ let repo = ctx.repos[(<any>ctx.plugins)[pluginName].repoName];
9
+
10
+ const user = await repo.getById(req.params.userid);
11
+ if (user == null) {
12
+ return notFound();
13
+ }
14
+
15
+ const modules = ctx.plugins.managementApi.moduleList.modules as any[];
16
+ const module = modules.find((p) => p.id == origin);
17
+
18
+ let getData = (user: User): GetManagementUserViewByUseridRes => {
19
+ let data = {
20
+ username: user.username,
21
+ };
22
+
23
+ return {
24
+ buttons: [],
25
+ data,
26
+ };
27
+ };
28
+
29
+ if (module?.data.userViewGetData != null) {
30
+ getData = module?.data.userViewGetData as (user: User) => GetManagementUserViewByUseridRes;
31
+ }
32
+
33
+ return {
34
+ data: getData(user),
35
+ status: 200,
36
+ };
37
+ };
38
+ export default GetManagementUserByUserid;