@tomei/sso 0.39.6 → 0.40.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/src/components/api-key/api-key.d.ts +38 -6
- package/dist/src/components/api-key/api-key.js +82 -10
- package/dist/src/components/api-key/api-key.js.map +1 -1
- package/dist/src/enum/api-key.enum.d.ts +1 -1
- package/dist/src/enum/api-key.enum.js +1 -1
- package/dist/src/enum/api-key.enum.js.map +1 -1
- package/dist/src/interfaces/api-key-attr.interface.d.ts +3 -2
- package/dist/src/models/api-key-entity.d.ts +3 -2
- package/dist/src/models/api-key-entity.js +9 -5
- package/dist/src/models/api-key-entity.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/migrations/20240528063108-create-api-key-table.js +6 -9
- package/package.json +1 -1
- package/src/components/api-key/api-key.ts +144 -13
- package/src/enum/api-key.enum.ts +1 -1
- package/src/interfaces/api-key-attr.interface.ts +3 -2
- package/src/models/api-key-entity.ts +8 -5
@@ -49,11 +49,11 @@ module.exports = {
|
|
49
49
|
onDelete: 'CASCADE',
|
50
50
|
onUpdate: 'CASCADE',
|
51
51
|
},
|
52
|
-
|
52
|
+
RevokedAt: {
|
53
53
|
allowNull: true,
|
54
54
|
type: Sequelize.DATE,
|
55
55
|
},
|
56
|
-
|
56
|
+
RevokedById: {
|
57
57
|
type: Sequelize.INTEGER,
|
58
58
|
allowNull: true,
|
59
59
|
references: {
|
@@ -63,13 +63,10 @@ module.exports = {
|
|
63
63
|
onDelete: 'CASCADE',
|
64
64
|
onUpdate: 'CASCADE',
|
65
65
|
},
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
customIndex: true,
|
71
|
-
fields: ['APIKey'],
|
72
|
-
},
|
66
|
+
RevokedReason: {
|
67
|
+
type: Sequelize.TEXT,
|
68
|
+
defaultValue: 'Active',
|
69
|
+
allowNull: true,
|
73
70
|
},
|
74
71
|
},
|
75
72
|
);
|
package/package.json
CHANGED
@@ -4,8 +4,9 @@ import { APIKeyRepository } from './api-key.repository';
|
|
4
4
|
import { IAPIKeyAttr } from '../../interfaces/api-key-attr.interface';
|
5
5
|
import { LoginUser } from '../login-user/login-user';
|
6
6
|
import { ApplicationConfig } from '@tomei/config';
|
7
|
-
import {
|
7
|
+
import { randomBytes } from 'crypto';
|
8
8
|
import { ActionEnum, Activity } from '@tomei/activity-history';
|
9
|
+
import { Op } from 'sequelize';
|
9
10
|
|
10
11
|
export class APIKey extends ObjectBase {
|
11
12
|
ObjectId: string;
|
@@ -18,8 +19,9 @@ export class APIKey extends ObjectBase {
|
|
18
19
|
Description: string;
|
19
20
|
Status: APIKeyStatusEnum;
|
20
21
|
ExpirationDate: Date;
|
21
|
-
|
22
|
-
|
22
|
+
RevokedReason: string;
|
23
|
+
_RevokedById: number;
|
24
|
+
_RevokedAt: Date;
|
23
25
|
_CreatedAt: Date;
|
24
26
|
_CreatedById: number;
|
25
27
|
|
@@ -31,12 +33,12 @@ export class APIKey extends ObjectBase {
|
|
31
33
|
this.ObjectId = value.toString();
|
32
34
|
}
|
33
35
|
|
34
|
-
get
|
35
|
-
return this.
|
36
|
+
get RevokedById(): number {
|
37
|
+
return this._RevokedById;
|
36
38
|
}
|
37
39
|
|
38
|
-
get
|
39
|
-
return this.
|
40
|
+
get RevokedAt(): Date {
|
41
|
+
return this._RevokedAt;
|
40
42
|
}
|
41
43
|
|
42
44
|
get CreatedAt(): Date {
|
@@ -58,8 +60,8 @@ export class APIKey extends ObjectBase {
|
|
58
60
|
this.Description = apiKeyAttr.Description;
|
59
61
|
this.Status = apiKeyAttr.Status;
|
60
62
|
this.ExpirationDate = apiKeyAttr.ExpirationDate;
|
61
|
-
this.
|
62
|
-
this.
|
63
|
+
this._RevokedById = apiKeyAttr.RevokedById;
|
64
|
+
this._RevokedAt = apiKeyAttr.RevokedAt;
|
63
65
|
this._CreatedAt = apiKeyAttr.CreatedAt;
|
64
66
|
this._CreatedById = apiKeyAttr.CreatedById;
|
65
67
|
}
|
@@ -135,8 +137,9 @@ export class APIKey extends ObjectBase {
|
|
135
137
|
ExpirationDate: this.ExpirationDate,
|
136
138
|
CreatedAt: this.CreatedAt,
|
137
139
|
CreatedById: this.CreatedById,
|
138
|
-
|
139
|
-
|
140
|
+
RevokedAt: this.RevokedAt,
|
141
|
+
RevokedById: this.RevokedById,
|
142
|
+
RevokedReason: this.RevokedReason,
|
140
143
|
};
|
141
144
|
|
142
145
|
const data = await APIKey._Repo.create(EntityValueAfter, {
|
@@ -186,8 +189,136 @@ export class APIKey extends ObjectBase {
|
|
186
189
|
ExpirationDate: this.ExpirationDate,
|
187
190
|
CreatedAt: this.CreatedAt,
|
188
191
|
CreatedById: this.CreatedById,
|
189
|
-
|
190
|
-
|
192
|
+
RevokedAt: this.RevokedAt,
|
193
|
+
RevokedById: this.RevokedById,
|
194
|
+
RevokedReason: this.RevokedReason,
|
195
|
+
};
|
196
|
+
} catch (error) {
|
197
|
+
throw error;
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
async findAll(
|
202
|
+
pagination: { page: number; limit: number },
|
203
|
+
loginUser: LoginUser,
|
204
|
+
dbTransaction: any,
|
205
|
+
whereOptions: {
|
206
|
+
Status?: APIKeyStatusEnum;
|
207
|
+
ExpirationDate?: {
|
208
|
+
FromDate: Date;
|
209
|
+
ToDate: Date;
|
210
|
+
};
|
211
|
+
CreatedById?: number;
|
212
|
+
},
|
213
|
+
sortOptions?: {
|
214
|
+
SortBy: string;
|
215
|
+
SortOrder: 'ASC' | 'DESC';
|
216
|
+
},
|
217
|
+
) {
|
218
|
+
try {
|
219
|
+
// Part 1: Privilege Checking
|
220
|
+
// Call the loginUser.checkPrivileges() method by passing:
|
221
|
+
// SystemCode: Retrieved from the application configuration.
|
222
|
+
// PrivilegeCode: 'API_KEY_VIEW'.
|
223
|
+
// Ensure the user has the necessary privileges to view API keys.
|
224
|
+
const systemCode =
|
225
|
+
ApplicationConfig.getComponentConfigValue('system-code');
|
226
|
+
const isPrivileged = await loginUser.checkPrivileges(
|
227
|
+
systemCode,
|
228
|
+
'API_KEY_VIEW',
|
229
|
+
);
|
230
|
+
|
231
|
+
if (!isPrivileged) {
|
232
|
+
throw new ClassError(
|
233
|
+
'APIKey',
|
234
|
+
'APIKeyErrMsgO2',
|
235
|
+
'User does not have privilege to generate API key.',
|
236
|
+
'generate',
|
237
|
+
);
|
238
|
+
}
|
239
|
+
|
240
|
+
// Part 2: Prepare Filters
|
241
|
+
// Ensure that whereOptions includes the necessary filters such as:
|
242
|
+
// Status: Filter for specific API key statuses (e.g., "Active", "Revoked").
|
243
|
+
// ExpirationDate: Filter for expiration date ranges (e.g., { [Op.between]: [fromDate, toDate] }).
|
244
|
+
// CreatedById: Filter by the user who created the API key.
|
245
|
+
const where = {};
|
246
|
+
if (whereOptions) {
|
247
|
+
if (whereOptions.Status) {
|
248
|
+
where['Status'] = whereOptions.Status;
|
249
|
+
}
|
250
|
+
if (whereOptions.ExpirationDate) {
|
251
|
+
where['ExpirationDate'] = {
|
252
|
+
[Op.between]: [
|
253
|
+
whereOptions.ExpirationDate.FromDate,
|
254
|
+
whereOptions.ExpirationDate.ToDate,
|
255
|
+
],
|
256
|
+
};
|
257
|
+
}
|
258
|
+
if (whereOptions.CreatedById) {
|
259
|
+
where['CreatedById'] = whereOptions.CreatedById;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
const order = [];
|
264
|
+
if (sortOptions) {
|
265
|
+
// Sort the results based on the provided SortBy and SortOrder.
|
266
|
+
// Ensure that the SortBy field is valid and that the SortOrder is either "ASC" or "DESC".
|
267
|
+
if (sortOptions.SortBy) {
|
268
|
+
order.push([sortOptions.SortBy, sortOptions.SortOrder]);
|
269
|
+
}
|
270
|
+
} else {
|
271
|
+
order.push(['CreatedAt', 'DESC']);
|
272
|
+
}
|
273
|
+
|
274
|
+
let offset = 0;
|
275
|
+
if (pagination) {
|
276
|
+
offset = (pagination.page - 1) * pagination.limit;
|
277
|
+
}
|
278
|
+
|
279
|
+
// Ensure that the pagination object includes the page and limit values.
|
280
|
+
// Use Sequelize's findAll() method with the provided whereOptions, sortOptions, and pagination to retrieve matching API keys.
|
281
|
+
const data = await APIKey._Repo.findAllWithPagination({
|
282
|
+
where,
|
283
|
+
order,
|
284
|
+
offset,
|
285
|
+
limit: pagination.limit,
|
286
|
+
});
|
287
|
+
|
288
|
+
// Return the list of API keys including:
|
289
|
+
// ApiKeyId
|
290
|
+
// ApiKey
|
291
|
+
// Name
|
292
|
+
// Status
|
293
|
+
// ExpirationDate
|
294
|
+
// CreatedAt
|
295
|
+
// CreatedById
|
296
|
+
// RevokedAt
|
297
|
+
// RevokedById
|
298
|
+
// RevokedReason
|
299
|
+
// Include pagination information such as:
|
300
|
+
// total: Total number of records,
|
301
|
+
// page: Current page,
|
302
|
+
// limit: Number of records per page.
|
303
|
+
|
304
|
+
return {
|
305
|
+
total: data.count,
|
306
|
+
ApiKeys: data.rows.map((row) => {
|
307
|
+
return {
|
308
|
+
ApiKeyId: row.APIKeyId,
|
309
|
+
ApiKey: row.ApiKey,
|
310
|
+
Name: row.Name,
|
311
|
+
Status: row.Status,
|
312
|
+
ExpirationDate: row.ExpirationDate,
|
313
|
+
CreatedAt: row.CreatedAt,
|
314
|
+
CreatedById: row.CreatedById,
|
315
|
+
RevokedAt: row.RevokedAt,
|
316
|
+
RevokedById: row.RevokedById,
|
317
|
+
RevokedReason: row.RevokedReason,
|
318
|
+
};
|
319
|
+
}),
|
320
|
+
page: pagination.page,
|
321
|
+
limit: pagination.limit,
|
191
322
|
};
|
192
323
|
} catch (error) {
|
193
324
|
throw error;
|
package/src/enum/api-key.enum.ts
CHANGED
@@ -29,7 +29,6 @@ export default class APIKeyModel extends Model {
|
|
29
29
|
@Column({
|
30
30
|
type: DataType.STRING(128),
|
31
31
|
})
|
32
|
-
@Index('IDX_ApiKey')
|
33
32
|
ApiKey: string;
|
34
33
|
|
35
34
|
@Column({
|
@@ -60,15 +59,13 @@ export default class APIKeyModel extends Model {
|
|
60
59
|
@Column({
|
61
60
|
type: DataType.INTEGER,
|
62
61
|
})
|
63
|
-
@Index('IDX_CreatedById')
|
64
62
|
CreatedById: number;
|
65
63
|
|
66
64
|
@ForeignKey(() => User)
|
67
65
|
@Column({
|
68
66
|
type: DataType.INTEGER,
|
69
67
|
})
|
70
|
-
|
71
|
-
InvokedById: number;
|
68
|
+
RevokedById: number;
|
72
69
|
|
73
70
|
@CreatedAt
|
74
71
|
CreatedAt: Date;
|
@@ -77,7 +74,13 @@ export default class APIKeyModel extends Model {
|
|
77
74
|
type: DataType.DATE,
|
78
75
|
allowNull: true,
|
79
76
|
})
|
80
|
-
|
77
|
+
RevokedAt: Date;
|
78
|
+
|
79
|
+
@Column({
|
80
|
+
type: DataType.TEXT,
|
81
|
+
allowNull: true,
|
82
|
+
})
|
83
|
+
RevokedReason: string;
|
81
84
|
|
82
85
|
@BelongsTo(() => User, 'CreatedById')
|
83
86
|
CreatedByUser: User;
|