itlab-internal-services 2.16.4 → 2.16.6
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/dist/classes/document/index.d.ts +1 -0
- package/dist/classes/document/index.js +3 -1
- package/dist/classes/document/likeable-document.class.d.ts +3 -1
- package/dist/classes/document/likeable-document.class.js +5 -1
- package/dist/classes/document/timestamps-document.class.d.ts +200 -0
- package/dist/classes/document/timestamps-document.class.js +27 -0
- package/dist/classes/document/viewable-document.class.d.ts +3 -1
- package/dist/classes/document/viewable-document.class.js +5 -1
- package/dist/classes/entity-map.class.d.ts +21 -0
- package/dist/classes/entity-map.class.js +28 -0
- package/dist/classes/fetch-options/base-options.class.d.ts +2 -0
- package/dist/classes/fetch-options/base-options.class.js +17 -0
- package/dist/classes/fetch-options/comments-options.class.d.ts +8 -0
- package/dist/classes/fetch-options/comments-options.class.js +14 -0
- package/dist/classes/fetch-options/content-options.class.d.ts +8 -1
- package/dist/classes/fetch-options/content-options.class.js +14 -0
- package/dist/classes/fetch-options/drafted-options.class.d.ts +7 -2
- package/dist/classes/fetch-options/drafted-options.class.js +12 -1
- package/dist/classes/fetch-options/index.d.ts +7 -6
- package/dist/classes/fetch-options/index.js +21 -13
- package/dist/classes/fetch-options/liked-by-options.class.d.ts +7 -0
- package/dist/classes/fetch-options/liked-by-options.class.js +27 -0
- package/dist/classes/fetch-options/timestamps-options.class.d.ts +12 -0
- package/dist/classes/fetch-options/timestamps-options.class.js +38 -0
- package/dist/classes/fetch-options/viewed-by-options.class.d.ts +10 -2
- package/dist/classes/fetch-options/viewed-by-options.class.js +35 -1
- package/dist/classes/index.d.ts +1 -0
- package/dist/classes/index.js +3 -1
- package/dist/classes/task-manager.class.d.ts +0 -34
- package/dist/classes/task-manager.class.js +0 -54
- package/dist/decorators/authenticated-account.decorator.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/middleware/http-logging.middleware.js +1 -11
- package/dist/modules/services/providers/accounts.service.d.ts +15 -0
- package/dist/modules/services/providers/accounts.service.js +45 -2
- package/dist/modules/services/providers/mail/dtos/event-cancel-mail.dto.d.ts +4 -0
- package/dist/pipes/restricted-fields.pipe.d.ts +1 -24
- package/dist/pipes/restricted-fields.pipe.js +22 -20
- package/dist/types/has-timestamps.type.d.ts +4 -0
- package/dist/types/has-timestamps.type.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/package.json +1 -1
- package/dist/interceptors/attribute-sanitizer.interceptor.d.ts +0 -68
- package/dist/interceptors/attribute-sanitizer.interceptor.js +0 -154
- package/dist/interceptors/index.d.ts +0 -1
- package/dist/interceptors/index.js +0 -17
|
@@ -10,6 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.LikedByOptions = LikedByOptions;
|
|
13
|
+
exports.populateLikedBy = populateLikedBy;
|
|
13
14
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
15
|
const class_validator_1 = require("class-validator");
|
|
15
16
|
const transform_1 = require("../../transform");
|
|
@@ -22,5 +23,31 @@ function LikedByOptions(Base) {
|
|
|
22
23
|
(0, class_validator_1.IsOptional)(),
|
|
23
24
|
__metadata("design:type", Boolean)
|
|
24
25
|
], LikedByOptions.prototype, "includeLikedBy", void 0);
|
|
26
|
+
__decorate([
|
|
27
|
+
(0, swagger_1.ApiPropertyOptional)({}),
|
|
28
|
+
(0, transform_1.BooleanTransform)(),
|
|
29
|
+
(0, class_validator_1.IsOptional)(),
|
|
30
|
+
__metadata("design:type", Boolean)
|
|
31
|
+
], LikedByOptions.prototype, "includeLikedByIds", void 0);
|
|
25
32
|
return LikedByOptions;
|
|
26
33
|
}
|
|
34
|
+
async function populateLikedBy(options, items, accountsService) {
|
|
35
|
+
if (options.includeLikedBy) {
|
|
36
|
+
const userMap = await accountsService.getUserMap(items.map((item) => item._likedBy));
|
|
37
|
+
items.forEach((item) => {
|
|
38
|
+
item.likedBy = userMap.getMultiple(item._likedBy);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
items.forEach((item) => {
|
|
42
|
+
item.likes = Math.max(item._likedBy.length, item.likes); // TODO: Tmp Fix
|
|
43
|
+
if (!options.includeLikedBy) {
|
|
44
|
+
delete item.likedBy;
|
|
45
|
+
}
|
|
46
|
+
if (!options.includeLikedByIds) {
|
|
47
|
+
delete item._likedBy;
|
|
48
|
+
}
|
|
49
|
+
if (!(options.includeLikedBy || options.includeLikedByIds)) {
|
|
50
|
+
delete item.likes;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { HasTimestamps } from '../../types';
|
|
2
|
+
export declare function TimestampsOptions<TBase extends new (...args: any[]) => any>(Base: TBase, options: {
|
|
3
|
+
requiredPermissions: string[];
|
|
4
|
+
}): {
|
|
5
|
+
new (...args: any[]): {
|
|
6
|
+
[x: string]: any;
|
|
7
|
+
includeTimestamps?: boolean;
|
|
8
|
+
};
|
|
9
|
+
} & TBase;
|
|
10
|
+
export declare function populateTimestamps<TOptions extends {
|
|
11
|
+
includeTimestamps?: boolean;
|
|
12
|
+
}, TItems extends HasTimestamps>(options: TOptions, items: TItems[], additionalKeys?: (keyof TItems)[]): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TimestampsOptions = TimestampsOptions;
|
|
13
|
+
exports.populateTimestamps = populateTimestamps;
|
|
14
|
+
const swagger_1 = require("@nestjs/swagger");
|
|
15
|
+
const class_validator_1 = require("class-validator");
|
|
16
|
+
const pipes_1 = require("../../pipes");
|
|
17
|
+
const transform_1 = require("../../transform");
|
|
18
|
+
function TimestampsOptions(Base, options) {
|
|
19
|
+
class TimestampsOptions extends Base {
|
|
20
|
+
}
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, swagger_1.ApiPropertyOptional)({}),
|
|
23
|
+
(0, transform_1.BooleanTransform)(),
|
|
24
|
+
(0, class_validator_1.IsOptional)(),
|
|
25
|
+
(0, pipes_1.Restricted)(options.requiredPermissions),
|
|
26
|
+
__metadata("design:type", Boolean)
|
|
27
|
+
], TimestampsOptions.prototype, "includeTimestamps", void 0);
|
|
28
|
+
return TimestampsOptions;
|
|
29
|
+
}
|
|
30
|
+
function populateTimestamps(options, items, additionalKeys = []) {
|
|
31
|
+
if (!options.includeTimestamps) {
|
|
32
|
+
items.forEach((item) => {
|
|
33
|
+
delete item.createdAt;
|
|
34
|
+
delete item.updatedAt;
|
|
35
|
+
additionalKeys.forEach((key) => delete item[key]);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { AccountsService } from '../../modules';
|
|
2
|
+
import { IsViewable } from '../../types';
|
|
3
|
+
export declare function ViewedByOptions<TBase extends new (...args: any[]) => any>(Base: TBase, options: {
|
|
4
|
+
requiredPermissions: string[];
|
|
3
5
|
}): {
|
|
4
6
|
new (...args: any[]): {
|
|
5
7
|
[x: string]: any;
|
|
6
8
|
includeViewedBy?: boolean;
|
|
9
|
+
includeViewedByIds?: boolean;
|
|
7
10
|
viewedBy?: string;
|
|
8
11
|
};
|
|
9
12
|
} & TBase;
|
|
13
|
+
export declare function populateViewedBy(options: {
|
|
14
|
+
includeViewedBy?: boolean;
|
|
15
|
+
includeViewedByIds?: boolean;
|
|
16
|
+
viewedBy?: string;
|
|
17
|
+
}, items: IsViewable[], accountsService: AccountsService): Promise<void>;
|
|
@@ -10,8 +10,10 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.ViewedByOptions = ViewedByOptions;
|
|
13
|
+
exports.populateViewedBy = populateViewedBy;
|
|
13
14
|
const swagger_1 = require("@nestjs/swagger");
|
|
14
15
|
const class_validator_1 = require("class-validator");
|
|
16
|
+
const rxjs_1 = require("rxjs");
|
|
15
17
|
const pipes_1 = require("../../pipes");
|
|
16
18
|
const transform_1 = require("../../transform");
|
|
17
19
|
function ViewedByOptions(Base, options) {
|
|
@@ -21,8 +23,40 @@ function ViewedByOptions(Base, options) {
|
|
|
21
23
|
(0, swagger_1.ApiPropertyOptional)({}),
|
|
22
24
|
(0, transform_1.BooleanTransform)(),
|
|
23
25
|
(0, class_validator_1.IsOptional)(),
|
|
24
|
-
(0, pipes_1.Restricted)(options
|
|
26
|
+
(0, pipes_1.Restricted)(options.requiredPermissions),
|
|
25
27
|
__metadata("design:type", Boolean)
|
|
26
28
|
], ViewedByOptions.prototype, "includeViewedBy", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, swagger_1.ApiPropertyOptional)({}),
|
|
31
|
+
(0, transform_1.BooleanTransform)(),
|
|
32
|
+
(0, class_validator_1.IsOptional)(),
|
|
33
|
+
(0, pipes_1.Restricted)(options.requiredPermissions),
|
|
34
|
+
__metadata("design:type", Boolean)
|
|
35
|
+
], ViewedByOptions.prototype, "includeViewedByIds", void 0);
|
|
27
36
|
return ViewedByOptions;
|
|
28
37
|
}
|
|
38
|
+
async function populateViewedBy(options, items, accountsService) {
|
|
39
|
+
if (options.viewedBy) {
|
|
40
|
+
items.forEach((item) => {
|
|
41
|
+
item.addView(options.viewedBy).then(rxjs_1.noop);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (options.includeViewedBy) {
|
|
45
|
+
const userMap = await accountsService.getUserMap(items.map((item) => item._viewedBy));
|
|
46
|
+
items.forEach((item) => {
|
|
47
|
+
item.viewedBy = userMap.getMultiple(item._viewedBy);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
items.forEach((item) => {
|
|
51
|
+
item.views = Math.max(item._viewedBy.length, item.views); // TODO: Tmp Fix
|
|
52
|
+
if (!options.includeViewedBy) {
|
|
53
|
+
delete item.viewedBy;
|
|
54
|
+
}
|
|
55
|
+
if (!options.includeViewedByIds) {
|
|
56
|
+
delete item._viewedBy;
|
|
57
|
+
}
|
|
58
|
+
if (!(options.includeViewedBy || options.includeViewedByIds)) {
|
|
59
|
+
delete item.views;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
package/dist/classes/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './document';
|
|
2
2
|
export * from './fetch-options';
|
|
3
3
|
export { DocumentMerger } from './document-merger.class';
|
|
4
|
+
export { EntityMap } from './entity-map.class';
|
|
4
5
|
export { ReportCategory } from './report-category.class';
|
|
5
6
|
export { TaskManager } from './task-manager.class';
|
package/dist/classes/index.js
CHANGED
|
@@ -14,11 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.TaskManager = exports.ReportCategory = exports.DocumentMerger = void 0;
|
|
17
|
+
exports.TaskManager = exports.ReportCategory = exports.EntityMap = exports.DocumentMerger = void 0;
|
|
18
18
|
__exportStar(require("./document"), exports);
|
|
19
19
|
__exportStar(require("./fetch-options"), exports);
|
|
20
20
|
var document_merger_class_1 = require("./document-merger.class");
|
|
21
21
|
Object.defineProperty(exports, "DocumentMerger", { enumerable: true, get: function () { return document_merger_class_1.DocumentMerger; } });
|
|
22
|
+
var entity_map_class_1 = require("./entity-map.class");
|
|
23
|
+
Object.defineProperty(exports, "EntityMap", { enumerable: true, get: function () { return entity_map_class_1.EntityMap; } });
|
|
22
24
|
var report_category_class_1 = require("./report-category.class");
|
|
23
25
|
Object.defineProperty(exports, "ReportCategory", { enumerable: true, get: function () { return report_category_class_1.ReportCategory; } });
|
|
24
26
|
var task_manager_class_1 = require("./task-manager.class");
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { Account, User } from '../models';
|
|
2
|
-
import { AccountsService } from '../modules';
|
|
3
1
|
/**
|
|
4
2
|
* TaskManager is a utility class that collects asynchronous tasks
|
|
5
3
|
* and executes them in parallel.
|
|
@@ -17,38 +15,6 @@ import { AccountsService } from '../modules';
|
|
|
17
15
|
*/
|
|
18
16
|
export declare class TaskManager {
|
|
19
17
|
private tasks;
|
|
20
|
-
/**
|
|
21
|
-
* Fetches all users for the given ID groups and returns a mapping.
|
|
22
|
-
* Ensures each user is fetched only once.
|
|
23
|
-
* @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
24
|
-
* @param accountsService Service responsible for fetching users
|
|
25
|
-
* @returns Map of userId -> user
|
|
26
|
-
*/
|
|
27
|
-
static fetchAndMapUsers(userIdGroups: string[][], accountsService: AccountsService): Promise<Map<string, User>>;
|
|
28
|
-
/**
|
|
29
|
-
* Fetches all users for the given ID groups and returns a mapping.
|
|
30
|
-
* Ensures each user is fetched only once.
|
|
31
|
-
* @param accountIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
32
|
-
* @param accountsService Service responsible for fetching users
|
|
33
|
-
* @returns Map of userId -> user
|
|
34
|
-
*/
|
|
35
|
-
static fetchAndMapAccounts(accountIdGroups: string[][], accountsService: AccountsService): Promise<Map<string, Account>>;
|
|
36
|
-
/**
|
|
37
|
-
* Maps an array of IDs to user objects using a userMap.
|
|
38
|
-
* Filters out any IDs that don’t have a corresponding user.
|
|
39
|
-
* @param userIds Array of user IDs to map
|
|
40
|
-
* @param userMap Map of userId -> user object
|
|
41
|
-
* @returns Array of user objects
|
|
42
|
-
*/
|
|
43
|
-
static mapIdsToUsers(userIds: string[], userMap: Map<string, User>): User[];
|
|
44
|
-
/**
|
|
45
|
-
* Maps an array of IDs to user objects using a userMap.
|
|
46
|
-
* Filters out any IDs that don’t have a corresponding user.
|
|
47
|
-
* @param accountIds Array of user IDs to map
|
|
48
|
-
* @param accountMap Map of userId -> user object
|
|
49
|
-
* @returns Array of user objects
|
|
50
|
-
*/
|
|
51
|
-
static mapIdsToAccounts(accountIds: string[], accountMap: Map<string, Account>): Account[];
|
|
52
18
|
/**
|
|
53
19
|
* Adds a new asynchronous task to the queue.
|
|
54
20
|
*
|
|
@@ -20,60 +20,6 @@ class TaskManager {
|
|
|
20
20
|
constructor() {
|
|
21
21
|
this.tasks = [];
|
|
22
22
|
}
|
|
23
|
-
/**
|
|
24
|
-
* Fetches all users for the given ID groups and returns a mapping.
|
|
25
|
-
* Ensures each user is fetched only once.
|
|
26
|
-
* @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
27
|
-
* @param accountsService Service responsible for fetching users
|
|
28
|
-
* @returns Map of userId -> user
|
|
29
|
-
*/
|
|
30
|
-
static async fetchAndMapUsers(userIdGroups, accountsService) {
|
|
31
|
-
// Collect all unique user IDs across all groups
|
|
32
|
-
const uniqueUserIds = new Set(userIdGroups.flat());
|
|
33
|
-
if (uniqueUserIds.size === 0)
|
|
34
|
-
return new Map();
|
|
35
|
-
// Fetch all users once
|
|
36
|
-
const userCollection = await accountsService.getUserCollection(Array.from(uniqueUserIds));
|
|
37
|
-
// Build a map for quick lookup
|
|
38
|
-
return new Map(userCollection.map((user) => [user.id, user]));
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Fetches all users for the given ID groups and returns a mapping.
|
|
42
|
-
* Ensures each user is fetched only once.
|
|
43
|
-
* @param accountIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
44
|
-
* @param accountsService Service responsible for fetching users
|
|
45
|
-
* @returns Map of userId -> user
|
|
46
|
-
*/
|
|
47
|
-
static async fetchAndMapAccounts(accountIdGroups, accountsService) {
|
|
48
|
-
// Collect all unique user IDs across all groups
|
|
49
|
-
const uniqueAccountIds = new Set(accountIdGroups.flat());
|
|
50
|
-
if (uniqueAccountIds.size === 0)
|
|
51
|
-
return new Map();
|
|
52
|
-
// Fetch all users once
|
|
53
|
-
const accountCollection = await accountsService.getAccountCollection(Array.from(uniqueAccountIds));
|
|
54
|
-
// Build a map for quick lookup
|
|
55
|
-
return new Map(accountCollection.map((account) => [account.id, account]));
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Maps an array of IDs to user objects using a userMap.
|
|
59
|
-
* Filters out any IDs that don’t have a corresponding user.
|
|
60
|
-
* @param userIds Array of user IDs to map
|
|
61
|
-
* @param userMap Map of userId -> user object
|
|
62
|
-
* @returns Array of user objects
|
|
63
|
-
*/
|
|
64
|
-
static mapIdsToUsers(userIds, userMap) {
|
|
65
|
-
return userIds.map((userId) => userMap.get(userId)).filter(Boolean);
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Maps an array of IDs to user objects using a userMap.
|
|
69
|
-
* Filters out any IDs that don’t have a corresponding user.
|
|
70
|
-
* @param accountIds Array of user IDs to map
|
|
71
|
-
* @param accountMap Map of userId -> user object
|
|
72
|
-
* @returns Array of user objects
|
|
73
|
-
*/
|
|
74
|
-
static mapIdsToAccounts(accountIds, accountMap) {
|
|
75
|
-
return accountIds.map((accountId) => accountMap.get(accountId)).filter(Boolean);
|
|
76
|
-
}
|
|
77
23
|
/**
|
|
78
24
|
* Adds a new asynchronous task to the queue.
|
|
79
25
|
*
|
|
@@ -14,4 +14,4 @@ import { Account } from '../models';
|
|
|
14
14
|
* @param {ExecutionContext} executionContext - The context of the current request.
|
|
15
15
|
* @returns {Account[keyof Account] | Account} The requested account attribute or full account object.
|
|
16
16
|
*/
|
|
17
|
-
export declare const AuthenticatedAccount: (...dataOrPipes: (
|
|
17
|
+
export declare const AuthenticatedAccount: (...dataOrPipes: (import("@nestjs/common").PipeTransform<any, any> | import("@nestjs/common").Type<import("@nestjs/common").PipeTransform<any, any>> | keyof Account)[]) => ParameterDecorator;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -20,7 +20,6 @@ __exportStar(require("./controllers"), exports);
|
|
|
20
20
|
__exportStar(require("./decorators"), exports);
|
|
21
21
|
__exportStar(require("./exceptions"), exports);
|
|
22
22
|
__exportStar(require("./functions"), exports);
|
|
23
|
-
__exportStar(require("./interceptors"), exports);
|
|
24
23
|
__exportStar(require("./middleware"), exports);
|
|
25
24
|
__exportStar(require("./models"), exports);
|
|
26
25
|
__exportStar(require("./modules"), exports);
|
|
@@ -33,17 +33,7 @@ const HttpLoggingMiddleware = (req, res, next) => {
|
|
|
33
33
|
next();
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
|
-
|
|
37
|
-
// ensuring accurate status information
|
|
38
|
-
res.on('finish', () => {
|
|
39
|
-
const { statusCode, statusMessage } = res;
|
|
40
|
-
// Construct a standardized log message
|
|
41
|
-
const logMessage = `${method} ${url} - ${statusCode} (${statusMessage})`;
|
|
42
|
-
// Client errors (4xx) are logged at warn level for visibility
|
|
43
|
-
// All other responses use standard log level
|
|
44
|
-
const logLevel = statusCode >= 400 && statusCode < 500 ? 'warn' : 'log';
|
|
45
|
-
logger[logLevel](logMessage);
|
|
46
|
-
});
|
|
36
|
+
logger.log(`Handle ${method} ${url}`);
|
|
47
37
|
// Continue to next middleware or request handler
|
|
48
38
|
next();
|
|
49
39
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConfigService } from '@nestjs/config';
|
|
2
|
+
import { EntityMap } from '../../../classes';
|
|
2
3
|
import { Account, User } from '../../../models';
|
|
3
4
|
import { AuthenticationModuleOptions } from '../../authentication';
|
|
4
5
|
import { BaseHttpService } from '../base-http.service';
|
|
@@ -35,6 +36,13 @@ export declare class AccountsService extends BaseHttpService {
|
|
|
35
36
|
* @returns {Promise<Account[]>} Resolves to an array of account objects (empty if none found).
|
|
36
37
|
*/
|
|
37
38
|
getAccountCollection(accountIds: string[]): Promise<Account[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Fetches all accounts for the given ID groups and returns a mapping.
|
|
41
|
+
* Ensures each account is fetched only once.
|
|
42
|
+
* @param accountIdGroups Array of arrays of account IDs (e.g., authors, likedBy, viewedBy)
|
|
43
|
+
* @returns Map of accountId -> Account
|
|
44
|
+
*/
|
|
45
|
+
getAccountMap(accountIdGroups: string[][]): Promise<EntityMap<Account>>;
|
|
38
46
|
/**
|
|
39
47
|
* Retrieves a single user entry derived from an account.
|
|
40
48
|
*
|
|
@@ -49,4 +57,11 @@ export declare class AccountsService extends BaseHttpService {
|
|
|
49
57
|
* @returns {Promise<User[]>} Resolves to a list of users (empty array if none found).
|
|
50
58
|
*/
|
|
51
59
|
getUserCollection(userIds: string[]): Promise<User[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Fetches all users for the given ID groups and returns a mapping.
|
|
62
|
+
* Ensures each user is fetched only once.
|
|
63
|
+
* @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
64
|
+
* @returns Map of userId -> user
|
|
65
|
+
*/
|
|
66
|
+
getUserMap(userIdGroups: string[][]): Promise<EntityMap<User>>;
|
|
52
67
|
}
|
|
@@ -15,9 +15,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
exports.AccountsService = void 0;
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const config_1 = require("@nestjs/config");
|
|
18
|
+
const itlab_functions_1 = require("itlab-functions");
|
|
19
|
+
const classes_1 = require("../../../classes");
|
|
18
20
|
const authentication_1 = require("../../authentication");
|
|
19
21
|
const base_http_service_1 = require("../base-http.service");
|
|
20
22
|
const base_urls_1 = require("../base-urls");
|
|
23
|
+
const chunkSize = 100;
|
|
21
24
|
/**
|
|
22
25
|
* AccountsService
|
|
23
26
|
*
|
|
@@ -57,7 +60,27 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
|
|
|
57
60
|
async getAccountCollection(accountIds) {
|
|
58
61
|
if (accountIds.length === 0)
|
|
59
62
|
return [];
|
|
60
|
-
|
|
63
|
+
const chunkedAccountIds = (0, itlab_functions_1.createChunks)(accountIds, chunkSize);
|
|
64
|
+
const chunkedAccounts = chunkedAccountIds.map((accountIds) => {
|
|
65
|
+
return this.fetchResourceCollection(`internal/accounts`, { params: { ids: accountIds } });
|
|
66
|
+
});
|
|
67
|
+
return (await Promise.all(chunkedAccounts)).flat();
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Fetches all accounts for the given ID groups and returns a mapping.
|
|
71
|
+
* Ensures each account is fetched only once.
|
|
72
|
+
* @param accountIdGroups Array of arrays of account IDs (e.g., authors, likedBy, viewedBy)
|
|
73
|
+
* @returns Map of accountId -> Account
|
|
74
|
+
*/
|
|
75
|
+
async getAccountMap(accountIdGroups) {
|
|
76
|
+
// Collect all unique account IDs across all groups
|
|
77
|
+
const uniqueAccountIds = new Set(accountIdGroups.flat());
|
|
78
|
+
if (uniqueAccountIds.size === 0)
|
|
79
|
+
return new classes_1.EntityMap();
|
|
80
|
+
// Fetch all accounts once
|
|
81
|
+
const accountCollection = await this.getAccountCollection(Array.from(uniqueAccountIds));
|
|
82
|
+
// Build a map for quick lookup
|
|
83
|
+
return new classes_1.EntityMap(accountCollection);
|
|
61
84
|
}
|
|
62
85
|
/**
|
|
63
86
|
* Retrieves a single user entry derived from an account.
|
|
@@ -77,7 +100,27 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
|
|
|
77
100
|
async getUserCollection(userIds) {
|
|
78
101
|
if (userIds.length === 0)
|
|
79
102
|
return [];
|
|
80
|
-
|
|
103
|
+
const chunkedUserIds = (0, itlab_functions_1.createChunks)(userIds, chunkSize);
|
|
104
|
+
const chunkedUsers = chunkedUserIds.map((userIds) => {
|
|
105
|
+
return this.fetchResourceCollection(`internal/users`, { params: { ids: userIds } });
|
|
106
|
+
});
|
|
107
|
+
return (await Promise.all(chunkedUsers)).flat();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Fetches all users for the given ID groups and returns a mapping.
|
|
111
|
+
* Ensures each user is fetched only once.
|
|
112
|
+
* @param userIdGroups Array of arrays of user IDs (e.g., authors, likedBy, viewedBy)
|
|
113
|
+
* @returns Map of userId -> user
|
|
114
|
+
*/
|
|
115
|
+
async getUserMap(userIdGroups) {
|
|
116
|
+
// Collect all unique user IDs across all groups
|
|
117
|
+
const uniqueUserIds = new Set(userIdGroups.flat());
|
|
118
|
+
if (uniqueUserIds.size === 0)
|
|
119
|
+
return new classes_1.EntityMap();
|
|
120
|
+
// Fetch all users once
|
|
121
|
+
const userCollection = await this.getUserCollection(Array.from(uniqueUserIds));
|
|
122
|
+
// Build a map for quick lookup
|
|
123
|
+
return new classes_1.EntityMap(userCollection);
|
|
81
124
|
}
|
|
82
125
|
};
|
|
83
126
|
exports.AccountsService = AccountsService;
|
|
@@ -4,6 +4,10 @@ import { MailRecipient } from '../models';
|
|
|
4
4
|
*/
|
|
5
5
|
export type EventCancelMailDto = {
|
|
6
6
|
recipient: MailRecipient;
|
|
7
|
+
/**
|
|
8
|
+
* Mode of participation (e.g., in person, online).
|
|
9
|
+
*/
|
|
10
|
+
participation?: string;
|
|
7
11
|
/**
|
|
8
12
|
* Title of the event that has been cancelled.
|
|
9
13
|
* @example "Meetup"
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { ArgumentMetadata, PipeTransform } from '@nestjs/common';
|
|
2
|
-
import { Reflector } from '@nestjs/core';
|
|
3
|
-
import { Request } from 'express';
|
|
4
|
-
import { Account } from '../models';
|
|
5
|
-
import { AuthenticationModuleOptions } from '../modules';
|
|
6
1
|
/**
|
|
7
2
|
* @Restricted Decorator
|
|
8
3
|
*
|
|
@@ -14,22 +9,4 @@ import { AuthenticationModuleOptions } from '../modules';
|
|
|
14
9
|
* @param {...string[]} perms - One or more permissions required to retain this field.
|
|
15
10
|
*/
|
|
16
11
|
export declare function Restricted(perms?: string | string[]): PropertyDecorator;
|
|
17
|
-
|
|
18
|
-
* RestrictedFieldsPipe
|
|
19
|
-
*
|
|
20
|
-
* Global pipe that inspects incoming DTOs for properties decorated with `@Restricted`.
|
|
21
|
-
* If the current request's account lacks the required permissions,
|
|
22
|
-
* the corresponding properties are stripped from the DTO.
|
|
23
|
-
*
|
|
24
|
-
* This ensures that sensitive fields are never accidentally
|
|
25
|
-
* processed further down the request lifecycle.
|
|
26
|
-
*/
|
|
27
|
-
export declare class RestrictedFieldsPipe implements PipeTransform {
|
|
28
|
-
private readonly request;
|
|
29
|
-
private readonly authenticationOptions;
|
|
30
|
-
private readonly reflector;
|
|
31
|
-
constructor(request: Request & {
|
|
32
|
-
account?: Account;
|
|
33
|
-
}, authenticationOptions: AuthenticationModuleOptions, reflector: Reflector);
|
|
34
|
-
transform(value: unknown, metadata: ArgumentMetadata): any;
|
|
35
|
-
}
|
|
12
|
+
export declare function UseRestricted(): ClassDecorator;
|
|
@@ -12,8 +12,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.RestrictedFieldsPipe = void 0;
|
|
16
15
|
exports.Restricted = Restricted;
|
|
16
|
+
exports.UseRestricted = UseRestricted;
|
|
17
17
|
const common_1 = require("@nestjs/common");
|
|
18
18
|
const core_1 = require("@nestjs/core");
|
|
19
19
|
const class_validator_1 = require("class-validator");
|
|
@@ -21,23 +21,6 @@ const itlab_functions_1 = require("itlab-functions");
|
|
|
21
21
|
const modules_1 = require("../modules");
|
|
22
22
|
const service_auth_guard_1 = require("../modules/authentication/guards/service-auth.guard");
|
|
23
23
|
const RESTRICTED_METADATA_KEY = Symbol('itlab-restricted-metadata');
|
|
24
|
-
/**
|
|
25
|
-
* @Restricted Decorator
|
|
26
|
-
*
|
|
27
|
-
* Marks a DTO property as restricted to specific permissions.
|
|
28
|
-
* When a request passes through the global `RestrictedFieldsPipe`,
|
|
29
|
-
* these properties will be removed if the requesting account does not
|
|
30
|
-
* have all required permissions.
|
|
31
|
-
*
|
|
32
|
-
* @param {...string[]} perms - One or more permissions required to retain this field.
|
|
33
|
-
*/
|
|
34
|
-
function Restricted(perms) {
|
|
35
|
-
return (target, propertyKey) => {
|
|
36
|
-
// Store metadata without touching the property descriptor
|
|
37
|
-
const existingMetadata = Reflect.getMetadata(RESTRICTED_METADATA_KEY, target) || {};
|
|
38
|
-
Reflect.defineMetadata(RESTRICTED_METADATA_KEY, Object.assign(Object.assign({}, existingMetadata), { [propertyKey.toString()]: [perms !== null && perms !== void 0 ? perms : []].flat() }), target);
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
24
|
/**
|
|
42
25
|
* RestrictedFieldsPipe
|
|
43
26
|
*
|
|
@@ -76,10 +59,29 @@ let RestrictedFieldsPipe = class RestrictedFieldsPipe {
|
|
|
76
59
|
return value;
|
|
77
60
|
}
|
|
78
61
|
};
|
|
79
|
-
|
|
80
|
-
exports.RestrictedFieldsPipe = RestrictedFieldsPipe = __decorate([
|
|
62
|
+
RestrictedFieldsPipe = __decorate([
|
|
81
63
|
(0, common_1.Injectable)({ scope: common_1.Scope.REQUEST }),
|
|
82
64
|
__param(0, (0, common_1.Inject)(core_1.REQUEST)),
|
|
83
65
|
__param(1, (0, modules_1.InjectAuthenticationOptions)()),
|
|
84
66
|
__metadata("design:paramtypes", [Object, Object, core_1.Reflector])
|
|
85
67
|
], RestrictedFieldsPipe);
|
|
68
|
+
/**
|
|
69
|
+
* @Restricted Decorator
|
|
70
|
+
*
|
|
71
|
+
* Marks a DTO property as restricted to specific permissions.
|
|
72
|
+
* When a request passes through the global `RestrictedFieldsPipe`,
|
|
73
|
+
* these properties will be removed if the requesting account does not
|
|
74
|
+
* have all required permissions.
|
|
75
|
+
*
|
|
76
|
+
* @param {...string[]} perms - One or more permissions required to retain this field.
|
|
77
|
+
*/
|
|
78
|
+
function Restricted(perms) {
|
|
79
|
+
return (target, propertyKey) => {
|
|
80
|
+
// Store metadata without touching the property descriptor
|
|
81
|
+
const existingMetadata = Reflect.getMetadata(RESTRICTED_METADATA_KEY, target) || {};
|
|
82
|
+
Reflect.defineMetadata(RESTRICTED_METADATA_KEY, Object.assign(Object.assign({}, existingMetadata), { [propertyKey.toString()]: [perms !== null && perms !== void 0 ? perms : []].flat() }), target);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function UseRestricted() {
|
|
86
|
+
return (0, common_1.applyDecorators)((0, common_1.UsePipes)(RestrictedFieldsPipe));
|
|
87
|
+
}
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -15,5 +15,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./duplicable-model.type"), exports);
|
|
18
|
+
__exportStar(require("./has-timestamps.type"), exports);
|
|
18
19
|
__exportStar(require("./likeable.type"), exports);
|
|
19
20
|
__exportStar(require("./viewable.type"), exports);
|