@tomei/sso 0.39.6 → 0.40.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -49,11 +49,11 @@ module.exports = {
49
49
  onDelete: 'CASCADE',
50
50
  onUpdate: 'CASCADE',
51
51
  },
52
- InvokedAt: {
52
+ RevokedAt: {
53
53
  allowNull: true,
54
54
  type: Sequelize.DATE,
55
55
  },
56
- InvokedById: {
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
- uniqueKeys: {
69
- IDX_ApiKey: {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomei/sso",
3
- "version": "0.39.6",
3
+ "version": "0.40.1",
4
4
  "description": "Tomei SSO Package",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -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 { randomUUID, randomBytes } from 'crypto';
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
- _InvokedById: number;
22
- _InvokedAt: Date;
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 InvokedById(): number {
35
- return this._InvokedById;
36
+ get RevokedById(): number {
37
+ return this._RevokedById;
36
38
  }
37
39
 
38
- get InvokedAt(): Date {
39
- return this._InvokedAt;
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._InvokedById = apiKeyAttr.InvokedById;
62
- this._InvokedAt = apiKeyAttr.InvokedAt;
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
- InvokedAt: this.InvokedAt,
139
- InvokedById: this.InvokedById,
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,137 @@ export class APIKey extends ObjectBase {
186
189
  ExpirationDate: this.ExpirationDate,
187
190
  CreatedAt: this.CreatedAt,
188
191
  CreatedById: this.CreatedById,
189
- InvokedAt: this.InvokedAt,
190
- InvokedById: this.InvokedById,
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
+ transaction: dbTransaction,
287
+ });
288
+
289
+ // Return the list of API keys including:
290
+ // ApiKeyId
291
+ // ApiKey
292
+ // Name
293
+ // Status
294
+ // ExpirationDate
295
+ // CreatedAt
296
+ // CreatedById
297
+ // RevokedAt
298
+ // RevokedById
299
+ // RevokedReason
300
+ // Include pagination information such as:
301
+ // total: Total number of records,
302
+ // page: Current page,
303
+ // limit: Number of records per page.
304
+
305
+ return {
306
+ total: data.count,
307
+ ApiKeys: data.rows.map((row) => {
308
+ return {
309
+ ApiKeyId: row.APIKeyId,
310
+ ApiKey: row.ApiKey,
311
+ Name: row.Name,
312
+ Status: row.Status,
313
+ ExpirationDate: row.ExpirationDate,
314
+ CreatedAt: row.CreatedAt,
315
+ CreatedById: row.CreatedById,
316
+ RevokedAt: row.RevokedAt,
317
+ RevokedById: row.RevokedById,
318
+ RevokedReason: row.RevokedReason,
319
+ };
320
+ }),
321
+ page: pagination.page,
322
+ limit: pagination.limit,
191
323
  };
192
324
  } catch (error) {
193
325
  throw error;
@@ -1,5 +1,5 @@
1
1
  export enum APIKeyStatusEnum {
2
2
  ACTIVE = 'Active',
3
- INACTIVE = 'Inactive',
3
+ REVOKED = 'Revoked',
4
4
  EXPIRED = 'Expired',
5
5
  }
@@ -8,7 +8,8 @@ export interface IAPIKeyAttr {
8
8
  Status: APIKeyStatusEnum;
9
9
  ExpirationDate: Date;
10
10
  CreatedById: number;
11
- InvokedById: number;
11
+ RevokedById: number;
12
12
  CreatedAt: Date;
13
- InvokedAt: Date;
13
+ RevokedAt: Date;
14
+ RevokedReason: string;
14
15
  }
@@ -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
- @Index('IDX_InvokedById')
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
- InvokedAt: Date;
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;