itlab-internal-services 2.16.5 → 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 -38
- package/dist/classes/task-manager.class.js +0 -58
- 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/modules/services/providers/accounts.service.d.ts +15 -0
- package/dist/modules/services/providers/accounts.service.js +33 -0
- 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,22 +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<FetchMap<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<FetchMap<Account>>;
|
|
36
18
|
/**
|
|
37
19
|
* Adds a new asynchronous task to the queue.
|
|
38
20
|
*
|
|
@@ -53,23 +35,3 @@ export declare class TaskManager {
|
|
|
53
35
|
*/
|
|
54
36
|
clear(): void;
|
|
55
37
|
}
|
|
56
|
-
declare class FetchMap<T extends User | Account> {
|
|
57
|
-
private readonly map;
|
|
58
|
-
constructor(items?: T[]);
|
|
59
|
-
/**
|
|
60
|
-
* Maps a single ID to an user/account object using a user/account Map.
|
|
61
|
-
* @param id ID of user/account to map
|
|
62
|
-
* @param map Map of id -> user/account object
|
|
63
|
-
* @returns user/account object
|
|
64
|
-
*/
|
|
65
|
-
get(id: string): T;
|
|
66
|
-
/**
|
|
67
|
-
* Maps an array of IDs to user/account objects using a user/account Map.
|
|
68
|
-
* Filters out any IDs that don’t have a corresponding entity.
|
|
69
|
-
* @param ids Array of user/account IDs to map
|
|
70
|
-
* @param map Map of id -> user/account object
|
|
71
|
-
* @returns Array of user/account objects
|
|
72
|
-
*/
|
|
73
|
-
getMultiple(ids: string[]): T[];
|
|
74
|
-
}
|
|
75
|
-
export {};
|
|
@@ -20,40 +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 FetchMap();
|
|
35
|
-
// Fetch all users once
|
|
36
|
-
const userCollection = await accountsService.getUserCollection(Array.from(uniqueUserIds));
|
|
37
|
-
// Build a map for quick lookup
|
|
38
|
-
return new FetchMap(userCollection);
|
|
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 FetchMap();
|
|
52
|
-
// Fetch all users once
|
|
53
|
-
const accountCollection = await accountsService.getAccountCollection(Array.from(uniqueAccountIds));
|
|
54
|
-
// Build a map for quick lookup
|
|
55
|
-
return new FetchMap(accountCollection);
|
|
56
|
-
}
|
|
57
23
|
/**
|
|
58
24
|
* Adds a new asynchronous task to the queue.
|
|
59
25
|
*
|
|
@@ -81,27 +47,3 @@ class TaskManager {
|
|
|
81
47
|
}
|
|
82
48
|
}
|
|
83
49
|
exports.TaskManager = TaskManager;
|
|
84
|
-
class FetchMap {
|
|
85
|
-
constructor(items = []) {
|
|
86
|
-
this.map = new Map(items.map((item) => [item.id, item]));
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Maps a single ID to an user/account object using a user/account Map.
|
|
90
|
-
* @param id ID of user/account to map
|
|
91
|
-
* @param map Map of id -> user/account object
|
|
92
|
-
* @returns user/account object
|
|
93
|
-
*/
|
|
94
|
-
get(id) {
|
|
95
|
-
return this.map.get(id);
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Maps an array of IDs to user/account objects using a user/account Map.
|
|
99
|
-
* Filters out any IDs that don’t have a corresponding entity.
|
|
100
|
-
* @param ids Array of user/account IDs to map
|
|
101
|
-
* @param map Map of id -> user/account object
|
|
102
|
-
* @returns Array of user/account objects
|
|
103
|
-
*/
|
|
104
|
-
getMultiple(ids) {
|
|
105
|
-
return ids.map((id) => this.map.get(id)).filter(Boolean);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
@@ -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);
|
|
@@ -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
|
}
|
|
@@ -16,6 +16,7 @@ exports.AccountsService = void 0;
|
|
|
16
16
|
const common_1 = require("@nestjs/common");
|
|
17
17
|
const config_1 = require("@nestjs/config");
|
|
18
18
|
const itlab_functions_1 = require("itlab-functions");
|
|
19
|
+
const classes_1 = require("../../../classes");
|
|
19
20
|
const authentication_1 = require("../../authentication");
|
|
20
21
|
const base_http_service_1 = require("../base-http.service");
|
|
21
22
|
const base_urls_1 = require("../base-urls");
|
|
@@ -65,6 +66,22 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
|
|
|
65
66
|
});
|
|
66
67
|
return (await Promise.all(chunkedAccounts)).flat();
|
|
67
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);
|
|
84
|
+
}
|
|
68
85
|
/**
|
|
69
86
|
* Retrieves a single user entry derived from an account.
|
|
70
87
|
*
|
|
@@ -89,6 +106,22 @@ let AccountsService = class AccountsService extends base_http_service_1.BaseHttp
|
|
|
89
106
|
});
|
|
90
107
|
return (await Promise.all(chunkedUsers)).flat();
|
|
91
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);
|
|
124
|
+
}
|
|
92
125
|
};
|
|
93
126
|
exports.AccountsService = AccountsService;
|
|
94
127
|
exports.AccountsService = AccountsService = __decorate([
|
|
@@ -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);
|
package/package.json
CHANGED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
|
|
2
|
-
import { Observable } from 'rxjs';
|
|
3
|
-
/**
|
|
4
|
-
* AttributeSanitizerInterceptor
|
|
5
|
-
*
|
|
6
|
-
* This interceptor removes specified attributes from response objects.
|
|
7
|
-
* It works with plain objects, arrays, sets, maps and also with Mongoose
|
|
8
|
-
* documents by normalizing them to plain objects before sanitization.
|
|
9
|
-
*
|
|
10
|
-
* This is especially useful for removing sensitive fields (e.g., passwords,
|
|
11
|
-
* tokens, SSNs) consistently across deeply nested response structures.
|
|
12
|
-
*/
|
|
13
|
-
export declare class AttributeSanitizerInterceptor implements NestInterceptor {
|
|
14
|
-
private readonly keys;
|
|
15
|
-
private readonly mongooseToObjectOptions;
|
|
16
|
-
/**
|
|
17
|
-
* @param keys - One or more property names to remove from every object.
|
|
18
|
-
* @param mongooseToObjectOptions - Options forwarded to Mongoose `.toObject()`
|
|
19
|
-
* when normalizing documents.
|
|
20
|
-
*/
|
|
21
|
-
constructor(keys: string | string[], mongooseToObjectOptions?: Record<string, unknown>);
|
|
22
|
-
/**
|
|
23
|
-
* Intercepts the response and removes the targeted attributes.
|
|
24
|
-
*
|
|
25
|
-
* @param _context - Execution context (unused here).
|
|
26
|
-
* @param next - Next handler in the pipeline.
|
|
27
|
-
* @returns Sanitized response data.
|
|
28
|
-
*/
|
|
29
|
-
intercept(_context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
30
|
-
/**
|
|
31
|
-
* Recursively removes targeted keys from objects, arrays, and nested structures.
|
|
32
|
-
*
|
|
33
|
-
* @param value - Any response value.
|
|
34
|
-
* @returns A sanitized value without the targeted attributes.
|
|
35
|
-
*/
|
|
36
|
-
private sanitizeRecursively;
|
|
37
|
-
/**
|
|
38
|
-
* Converts a Mongoose document to a plain object if needed.
|
|
39
|
-
*
|
|
40
|
-
* @param value - Possible Mongoose document.
|
|
41
|
-
* @returns A plain object if conversion is possible, otherwise the value itself.
|
|
42
|
-
*/
|
|
43
|
-
private normalizeIfMongooseDocument;
|
|
44
|
-
/**
|
|
45
|
-
* Checks whether a value is a plain object (and not a class instance, Date, etc.).
|
|
46
|
-
*
|
|
47
|
-
* @param value - Any value.
|
|
48
|
-
* @returns True if the value is a plain object.
|
|
49
|
-
*/
|
|
50
|
-
private isPlainObject;
|
|
51
|
-
/**
|
|
52
|
-
* Converts the user-provided keys into a Set for O(1) lookup.
|
|
53
|
-
*
|
|
54
|
-
* @param keys - String or array of strings.
|
|
55
|
-
* @returns A Set of keys.
|
|
56
|
-
*/
|
|
57
|
-
private ensureKeySet;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* @UseAttributeSanitizer
|
|
61
|
-
*
|
|
62
|
-
* Convenience decorator that applies the AttributeSanitizerInterceptor
|
|
63
|
-
* to a route or controller.
|
|
64
|
-
*
|
|
65
|
-
* @param keys - One or more keys to remove from all response objects.
|
|
66
|
-
* @param mongooseToObjectOptions - Options for Mongoose `.toObject()` normalization.
|
|
67
|
-
*/
|
|
68
|
-
export declare function UseAttributeSanitizer(keys: string | string[], mongooseToObjectOptions?: Record<string, unknown>): MethodDecorator & ClassDecorator;
|