itlab-internal-services 2.15.4 → 2.15.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-merger.class.js +27 -37
- package/dist/classes/document-updater.class.js +2 -2
- package/dist/factories/virtuals.factory.js +2 -2
- package/dist/functions/create-duplicate-checker.function.js +3 -12
- package/dist/functions/create-internal-axios-client.function.d.ts +0 -1
- package/dist/functions/create-schema-transformer.function.js +1 -1
- package/dist/models/thumbnail/thumbnail.model.js +1 -0
- package/dist/modules/cache/cache.service.js +50 -71
- package/dist/modules/comment/comment.controller.js +3 -13
- package/dist/modules/comment/comment.module.js +5 -1
- package/dist/modules/comment/comment.service.js +31 -41
- package/dist/modules/content/content.module.js +4 -1
- package/dist/modules/content/content.property.js +1 -0
- package/dist/modules/content/content.service.js +56 -68
- package/dist/modules/database/database.liveness-controller.js +19 -30
- package/dist/modules/database/database.module.js +4 -12
- package/dist/modules/database/lock-service/lock.service.js +22 -35
- package/dist/modules/database/model-service/dbs/hub-account.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-account.db.js +1 -1
- package/dist/modules/database/model-service/dbs/hub-books.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-comments.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-content.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-demo-hive.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-events.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-hackschool.db.d.ts +6 -6
- package/dist/modules/database/model-service/dbs/hub-newsroom.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-podcasts.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-team.db.d.ts +2 -2
- package/dist/modules/database/model-service/dbs/hub-tech-radar.db.d.ts +4 -4
- package/dist/modules/database/model-service/model.service.d.ts +392 -224
- package/dist/modules/database/model-service/model.service.js +4 -17
- package/dist/modules/fetch/fetch.module.js +4 -1
- package/dist/modules/fetch/fetch.service.js +56 -94
- package/dist/modules/like/like.controller.js +7 -21
- package/dist/modules/like/like.module.js +5 -1
- package/dist/modules/like/like.service.js +13 -28
- package/dist/modules/mail/mail.module.js +4 -1
- package/dist/modules/mail/mail.service.d.ts +5 -5
- package/dist/modules/mail/mail.service.js +10 -9
- package/dist/modules/notification/notification.module.js +4 -1
- package/dist/modules/notification/notification.service.js +2 -2
- package/dist/modules/pass/pass.module.js +4 -1
- package/dist/modules/pass/pass.service.js +41 -63
- package/dist/modules/search/search.module.js +4 -1
- package/dist/modules/search/search.service.js +13 -24
- package/dist/transform/boolean.transform.js +3 -2
- package/dist/transform/image-url.transform.js +1 -1
- package/dist/transform/number.transform.js +2 -1
- package/dist/transform/string-array.transform.js +1 -1
- package/dist/transform/string.transform.js +1 -1
- package/dist/transform/timestamp.transform.js +2 -1
- package/package.json +54 -24
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.DocumentMerger = void 0;
|
|
13
4
|
const common_1 = require("@nestjs/common");
|
|
@@ -57,37 +48,36 @@ class DocumentMerger {
|
|
|
57
48
|
* @param transform - Optional callback to modify each document before merging fields
|
|
58
49
|
* @returns Promise resolving when all documents have been processed and saved
|
|
59
50
|
*/
|
|
60
|
-
merge(transform) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
51
|
+
async merge(transform) {
|
|
52
|
+
const startTime = Date.now();
|
|
53
|
+
const cursor = this.model.find().cursor();
|
|
54
|
+
// Process documents one by one to handle large collections efficiently
|
|
55
|
+
for (let doc = await cursor.next(); doc != null; doc = await cursor.next()) {
|
|
56
|
+
// Apply user-defined transformation if provided
|
|
57
|
+
if (transform) {
|
|
58
|
+
doc = transform(doc);
|
|
59
|
+
}
|
|
60
|
+
// Iterate through each target field and perform replacements as needed
|
|
61
|
+
for (const field of this.fields) {
|
|
62
|
+
const fieldValue = doc[field];
|
|
63
|
+
// Replace string fields equal to oldId with newId
|
|
64
|
+
if (typeof fieldValue === 'string' && fieldValue === this.oldId) {
|
|
65
|
+
doc[field] = this.newId;
|
|
66
|
+
continue;
|
|
69
67
|
}
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
doc[field] = this.newId;
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
// Replace oldId occurrences in array fields and remove duplicates
|
|
79
|
-
if (Array.isArray(fieldValue)) {
|
|
80
|
-
doc[field] = [...new Set(fieldValue.map((id) => (id === this.oldId ? this.newId : id)))];
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
68
|
+
// Replace oldId occurrences in array fields and remove duplicates
|
|
69
|
+
if (Array.isArray(fieldValue)) {
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
71
|
+
doc[field] = [...new Set(fieldValue.map((id) => (id === this.oldId ? this.newId : id)))];
|
|
72
|
+
continue;
|
|
83
73
|
}
|
|
84
|
-
// Save changes to the database without updating timestamps
|
|
85
|
-
yield doc.save({ timestamps: false });
|
|
86
74
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
75
|
+
// Save changes to the database without updating timestamps
|
|
76
|
+
await doc.save({ timestamps: false });
|
|
77
|
+
}
|
|
78
|
+
const elapsedTime = Date.now() - startTime;
|
|
79
|
+
// Log completion with fields merged and time taken
|
|
80
|
+
this.logger.log(`Successfully merged fields: ${(0, itlab_functions_1.formatList)(this.fields)} (took ${elapsedTime} ms)`);
|
|
91
81
|
}
|
|
92
82
|
}
|
|
93
83
|
exports.DocumentMerger = DocumentMerger;
|
|
@@ -32,11 +32,11 @@ class DocumentUpdater {
|
|
|
32
32
|
document
|
|
33
33
|
.updateOne({ $addToSet: { [String(attribute)]: accountId } }, { timestamps: false })
|
|
34
34
|
.then(() => {
|
|
35
|
-
this.logger.log(`Added unique accountId '${accountId}' to attribute '${String(attribute)}' for document ${document._id}`);
|
|
35
|
+
this.logger.log(`Added unique accountId '${accountId}' to attribute '${String(attribute)}' for document ${document._id.toString()}`);
|
|
36
36
|
})
|
|
37
37
|
.catch((error) => {
|
|
38
38
|
// Log any errors during the update operation for debugging and audit.
|
|
39
|
-
this.logger.error(`Failed to add accountId '${accountId}' to attribute '${String(attribute)}' for document ${document._id}: ${error.stack}`);
|
|
39
|
+
this.logger.error(`Failed to add accountId '${accountId}' to attribute '${String(attribute)}' for document ${document._id.toString()}: ${error.stack}`);
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
42
|
/**
|
|
@@ -98,7 +98,7 @@ class VirtualsFactory {
|
|
|
98
98
|
get views() {
|
|
99
99
|
this.virtualMultipleAccounts('viewedBy', '_viewedBy');
|
|
100
100
|
this.schema.virtual('views').get(function () {
|
|
101
|
-
return (0, class_validator_1.isArray)(this._viewedBy) ? this._viewedBy.length : 0;
|
|
101
|
+
return (0, class_validator_1.isArray)(this._viewedBy) ? Array(this._viewedBy).length : 0;
|
|
102
102
|
});
|
|
103
103
|
return this;
|
|
104
104
|
}
|
|
@@ -106,7 +106,7 @@ class VirtualsFactory {
|
|
|
106
106
|
get likes() {
|
|
107
107
|
this.virtualMultipleAccounts('likedBy', '_likedBy');
|
|
108
108
|
this.schema.virtual('likes').get(function () {
|
|
109
|
-
return (0, class_validator_1.isArray)(this._likedBy) ? this._likedBy.length : 0;
|
|
109
|
+
return (0, class_validator_1.isArray)(this._likedBy) ? Array(this._likedBy).length : 0;
|
|
110
110
|
});
|
|
111
111
|
return this;
|
|
112
112
|
}
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.createDuplicateChecker = createDuplicateChecker;
|
|
13
4
|
/**
|
|
@@ -37,7 +28,7 @@ exports.createDuplicateChecker = createDuplicateChecker;
|
|
|
37
28
|
* A function that checks for duplicates and throws an error if a different record matches.
|
|
38
29
|
*/
|
|
39
30
|
function createDuplicateChecker(model, criticalKeys, DuplicateError) {
|
|
40
|
-
return (dto, existingResource) =>
|
|
31
|
+
return async (dto, existingResource) => {
|
|
41
32
|
const filterQuery = {};
|
|
42
33
|
// Populate filterQuery with key-value pairs from the DTO or the existing document.
|
|
43
34
|
// Priority is given to the DTO values since those represent the intended update/create.
|
|
@@ -50,12 +41,12 @@ function createDuplicateChecker(model, criticalKeys, DuplicateError) {
|
|
|
50
41
|
}
|
|
51
42
|
}
|
|
52
43
|
// Attempt to find an existing document with matching critical fields.
|
|
53
|
-
const potentialDuplicate =
|
|
44
|
+
const potentialDuplicate = await model.findOne(filterQuery);
|
|
54
45
|
// Convert existing resource ID to lowercase string for safe comparison.
|
|
55
46
|
const currentResourceId = existingResource ? String(existingResource._id).toLowerCase() : undefined;
|
|
56
47
|
// If a duplicate exists and it's not the same as the current resource, throw the error.
|
|
57
48
|
if (potentialDuplicate && String(potentialDuplicate._id).toLowerCase() !== currentResourceId) {
|
|
58
49
|
throw new DuplicateError();
|
|
59
50
|
}
|
|
60
|
-
}
|
|
51
|
+
};
|
|
61
52
|
}
|
|
@@ -10,7 +10,6 @@ import { AxiosInstance } from 'axios';
|
|
|
10
10
|
* header to authenticate internal service-to-service requests.
|
|
11
11
|
*/
|
|
12
12
|
/**
|
|
13
|
-
* @typedef {Object} AxiosConfigurationOptions
|
|
14
13
|
* @property {string} [baseUrl] - Optional base URL to be used for HTTP requests.
|
|
15
14
|
* @property {string} k8sToken - Kubernetes service account token used for internal authentication.
|
|
16
15
|
*/
|
|
@@ -26,7 +26,7 @@ const createSchemaTransformer = (transformDocument) => {
|
|
|
26
26
|
return {
|
|
27
27
|
virtuals: true, // Include virtual fields like computed properties in the output
|
|
28
28
|
// Apply the provided transformation function to the document before returning it
|
|
29
|
-
transform: (
|
|
29
|
+
transform: (_doc, ret) => transformDocument(ret),
|
|
30
30
|
};
|
|
31
31
|
};
|
|
32
32
|
exports.createSchemaTransformer = createSchemaTransformer;
|
|
@@ -59,6 +59,7 @@ __decorate([
|
|
|
59
59
|
* @param {ApiPropertyOptions & { type?: Function }} options - Swagger API property options.
|
|
60
60
|
* @returns {PropertyDecorator} Composite decorator applying nested validation and type transformation.
|
|
61
61
|
*/
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
62
63
|
function PropertyThumbnail(options = {}) {
|
|
63
64
|
var _a, _b, _c, _d;
|
|
64
65
|
const TargetClass = (_a = options.type) !== null && _a !== void 0 ? _a : Thumbnail;
|
|
@@ -11,15 +11,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
15
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
17
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
18
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
19
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
20
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
14
|
var CacheService_1;
|
|
24
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
16
|
exports.CacheService = void 0;
|
|
@@ -66,48 +57,46 @@ let CacheService = CacheService_1 = class CacheService {
|
|
|
66
57
|
*
|
|
67
58
|
* If Redis config is incomplete or connection fails, falls back to empty store.
|
|
68
59
|
*/
|
|
69
|
-
initializeCacheStore() {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
});
|
|
60
|
+
async initializeCacheStore() {
|
|
61
|
+
var _a;
|
|
62
|
+
const { username, host, port } = this.options;
|
|
63
|
+
// Validate Redis connection settings to avoid unnecessary attempts
|
|
64
|
+
if (![username, host, port].every(class_validator_1.isDefined)) {
|
|
65
|
+
this.logger.warn('Incomplete Redis configuration. Cache store setup skipped.');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
const credential = new identity_1.WorkloadIdentityCredential();
|
|
70
|
+
const redisScope = 'https://redis.azure.com/.default';
|
|
71
|
+
this.logger.log('Requesting new Redis access token...');
|
|
72
|
+
const accessToken = await credential.getToken(redisScope);
|
|
73
|
+
const { token: password, refreshAfterTimestamp } = accessToken;
|
|
74
|
+
this.logger.log(`Received token, scheduling refresh at ${new Date(refreshAfterTimestamp).toISOString()}`);
|
|
75
|
+
// Create Redis store instance with authentication and TLS enabled
|
|
76
|
+
const redisStore = (0, redis_1.createKeyv)({ username, password, socket: { host, port, tls: true, timeout: 5000 }, pingInterval: 60000 }, { namespace: (_a = this.namespace) !== null && _a !== void 0 ? _a : this.options.namespace });
|
|
77
|
+
// Verify Redis server availability by pinging
|
|
78
|
+
await redisStore.get('ping');
|
|
79
|
+
this.logger.log('Connected to Redis. Using Redis as cache store.');
|
|
80
|
+
// Calculate delay for token refresh ensuring non-negative timeout
|
|
81
|
+
const refreshDelay = Math.max(refreshAfterTimestamp - Date.now(), 0);
|
|
82
|
+
// Convert delay to human-readable hours and minutes for logging
|
|
83
|
+
const totalMinutes = refreshDelay / 1000 / 60;
|
|
84
|
+
const hours = Math.floor(totalMinutes / 60).toString();
|
|
85
|
+
const minutes = Math.floor(totalMinutes % 60).toString();
|
|
86
|
+
this.logger.log(`Scheduling token refresh in ${hours.padStart(2, '0')}h ${minutes.padStart(2, '0')}m.`);
|
|
87
|
+
// Schedule automatic refresh of Redis token before expiration
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
this.initializeCacheStore().then(() => {
|
|
90
|
+
this.logger.log('Redis access token refreshed successfully.');
|
|
91
|
+
});
|
|
92
|
+
}, refreshDelay);
|
|
93
|
+
// Assign Redis store to cache manager stores for usage
|
|
94
|
+
this.cache.stores = [redisStore];
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
this.logger.error(`Redis connection failed: ${error.message || error}`);
|
|
98
|
+
this.cache.stores = [];
|
|
99
|
+
}
|
|
111
100
|
}
|
|
112
101
|
/**
|
|
113
102
|
* Retrieves the cached value by key.
|
|
@@ -115,10 +104,8 @@ let CacheService = CacheService_1 = class CacheService {
|
|
|
115
104
|
* @param key Cache key.
|
|
116
105
|
* @returns The cached value or null if not found.
|
|
117
106
|
*/
|
|
118
|
-
fetch(key) {
|
|
119
|
-
return
|
|
120
|
-
return this.cache.get(key);
|
|
121
|
-
});
|
|
107
|
+
async fetch(key) {
|
|
108
|
+
return this.cache.get(key);
|
|
122
109
|
}
|
|
123
110
|
/**
|
|
124
111
|
* Stores a value in the cache under the given key with optional TTL.
|
|
@@ -127,28 +114,22 @@ let CacheService = CacheService_1 = class CacheService {
|
|
|
127
114
|
* @param value Value to store.
|
|
128
115
|
* @param expiration Optional time to live in seconds.
|
|
129
116
|
*/
|
|
130
|
-
store(key, value, expiration) {
|
|
131
|
-
|
|
132
|
-
yield this.cache.set(key, value, expiration);
|
|
133
|
-
});
|
|
117
|
+
async store(key, value, expiration) {
|
|
118
|
+
await this.cache.set(key, value, expiration);
|
|
134
119
|
}
|
|
135
120
|
/**
|
|
136
121
|
* Removes a cached value by key.
|
|
137
122
|
*
|
|
138
123
|
* @param key Cache key to delete.
|
|
139
124
|
*/
|
|
140
|
-
remove(key) {
|
|
141
|
-
|
|
142
|
-
yield this.cache.del(key);
|
|
143
|
-
});
|
|
125
|
+
async remove(key) {
|
|
126
|
+
await this.cache.del(key);
|
|
144
127
|
}
|
|
145
128
|
/**
|
|
146
129
|
* Clears all cached entries.
|
|
147
130
|
*/
|
|
148
|
-
clearAll() {
|
|
149
|
-
|
|
150
|
-
yield this.cache.clear();
|
|
151
|
-
});
|
|
131
|
+
async clearAll() {
|
|
132
|
+
await this.cache.clear();
|
|
152
133
|
}
|
|
153
134
|
/**
|
|
154
135
|
* Retrieves a value from the cache or fetches it using the provided function
|
|
@@ -159,10 +140,8 @@ let CacheService = CacheService_1 = class CacheService {
|
|
|
159
140
|
* @param expiration Optional TTL in seconds.
|
|
160
141
|
* @returns Cached or freshly fetched value.
|
|
161
142
|
*/
|
|
162
|
-
fetchOrStore(key, fetcher, expiration) {
|
|
163
|
-
return
|
|
164
|
-
return this.cache.wrap(key, fetcher, { ttl: expiration });
|
|
165
|
-
});
|
|
143
|
+
async fetchOrStore(key, fetcher, expiration) {
|
|
144
|
+
return this.cache.wrap(key, fetcher, { ttl: expiration });
|
|
166
145
|
}
|
|
167
146
|
};
|
|
168
147
|
exports.CacheService = CacheService;
|
|
@@ -11,15 +11,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
15
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
17
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
18
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
19
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
20
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
15
|
exports.CommentController = void 0;
|
|
25
16
|
const common_1 = require("@nestjs/common");
|
|
@@ -61,10 +52,8 @@ let CommentController = class CommentController {
|
|
|
61
52
|
* @param {LabContentRichtext} comment - The comment content (rich text format)
|
|
62
53
|
* @returns {Promise<Comment>} - The saved comment returned by the comment service
|
|
63
54
|
*/
|
|
64
|
-
postComment(resourceId, accountId, comment) {
|
|
65
|
-
return
|
|
66
|
-
return this.commentService.postComment(resourceId, accountId, comment);
|
|
67
|
-
});
|
|
55
|
+
async postComment(resourceId, accountId, comment) {
|
|
56
|
+
return this.commentService.postComment(resourceId, accountId, comment);
|
|
68
57
|
}
|
|
69
58
|
};
|
|
70
59
|
exports.CommentController = CommentController;
|
|
@@ -92,5 +81,6 @@ __decorate([
|
|
|
92
81
|
], CommentController.prototype, "postComment", null);
|
|
93
82
|
exports.CommentController = CommentController = __decorate([
|
|
94
83
|
(0, authentication_1.RequireJwtAuth)(),
|
|
84
|
+
(0, common_1.Controller)(),
|
|
95
85
|
__metadata("design:paramtypes", [comment_service_1.CommentService])
|
|
96
86
|
], CommentController);
|
|
@@ -63,5 +63,9 @@ let CommentModule = CommentModule_1 = class CommentModule {
|
|
|
63
63
|
};
|
|
64
64
|
exports.CommentModule = CommentModule;
|
|
65
65
|
exports.CommentModule = CommentModule = CommentModule_1 = __decorate([
|
|
66
|
-
(0, common_1.Module)({
|
|
66
|
+
(0, common_1.Module)({
|
|
67
|
+
controllers: [comment_controller_1.CommentController],
|
|
68
|
+
providers: [comment_service_1.CommentService],
|
|
69
|
+
exports: [comment_service_1.CommentService],
|
|
70
|
+
})
|
|
67
71
|
], CommentModule);
|
|
@@ -11,15 +11,6 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
12
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
13
|
};
|
|
14
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
15
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
16
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
17
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
18
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
19
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
20
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
21
|
-
});
|
|
22
|
-
};
|
|
23
14
|
var CommentService_1;
|
|
24
15
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
16
|
exports.CommentService = void 0;
|
|
@@ -80,37 +71,36 @@ let CommentService = CommentService_1 = class CommentService {
|
|
|
80
71
|
* @param {LabContentRichtext} comment - Comment content in rich-text format
|
|
81
72
|
* @returns {Promise<Comment>} - Resolves with the saved comment or throws an HTTP exception
|
|
82
73
|
*/
|
|
83
|
-
postComment(resourceId, accountId, comment) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
});
|
|
74
|
+
async postComment(resourceId, accountId, comment) {
|
|
75
|
+
var _a, _b, _c;
|
|
76
|
+
// Exit early if no model is defined (e.g., management context)
|
|
77
|
+
if (!(0, class_validator_1.isDefined)(this.commentModel)) {
|
|
78
|
+
this.logger.error('Kommentare können nicht vom Management aus erstellt werden');
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Ensure the referenced resource exists before allowing comments
|
|
82
|
+
const resourceDoc = await this.commentModel.findOne({ _id: resourceId });
|
|
83
|
+
if (!resourceDoc) {
|
|
84
|
+
throw new common_1.NotFoundException('Kommentar konnte nicht erstellt werden');
|
|
85
|
+
}
|
|
86
|
+
// Optionally extract ownerId or ownerIds from the resource document
|
|
87
|
+
const { ownerIdField, ownerIdsField } = this.moduleOptions;
|
|
88
|
+
const ownerId = ownerIdField ? resourceDoc[ownerIdField] : undefined;
|
|
89
|
+
const ownerIds = ownerIdsField ? resourceDoc[ownerIdsField] : undefined;
|
|
90
|
+
this.logger.log(`Posting comment for ${this.resource} (${resourceId}) by account ${accountId}`);
|
|
91
|
+
try {
|
|
92
|
+
const response = await this.axiosInstance.post(`${resourceId}/${accountId}`, comment, {
|
|
93
|
+
params: { ownerId, ownerIds },
|
|
94
|
+
});
|
|
95
|
+
this.logger.log(`Comment for ${this.resource} (${resourceId}) posted`);
|
|
96
|
+
return response.data;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const axiosError = error;
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
101
|
+
this.logger.error(`Couldn't post comment for ${this.resource} (${resourceId}): ${(_a = axiosError.response) === null || _a === void 0 ? void 0 : _a.data}`);
|
|
102
|
+
throw new common_1.HttpException(((_b = axiosError.response) === null || _b === void 0 ? void 0 : _b.data) || 'Internal error', ((_c = axiosError.response) === null || _c === void 0 ? void 0 : _c.status) || 500);
|
|
103
|
+
}
|
|
114
104
|
}
|
|
115
105
|
/**
|
|
116
106
|
* Deletes all comments associated with the specified resource.
|
|
@@ -129,7 +119,7 @@ let CommentService = CommentService_1 = class CommentService {
|
|
|
129
119
|
this.logger.log(`All comments for ${this.resource} (${resourceId}) deleted`);
|
|
130
120
|
})
|
|
131
121
|
.catch(({ response }) => {
|
|
132
|
-
this.logger.error(`Couldn't delete all comments for ${this.resource} (${resourceId}): ${response === null || response === void 0 ? void 0 : response.data}`);
|
|
122
|
+
this.logger.error(`Couldn't delete all comments for ${this.resource} (${resourceId}): ${JSON.stringify(response === null || response === void 0 ? void 0 : response.data)}`);
|
|
133
123
|
});
|
|
134
124
|
}
|
|
135
125
|
};
|
|
@@ -53,5 +53,8 @@ let ContentModule = ContentModule_1 = class ContentModule {
|
|
|
53
53
|
};
|
|
54
54
|
exports.ContentModule = ContentModule;
|
|
55
55
|
exports.ContentModule = ContentModule = ContentModule_1 = __decorate([
|
|
56
|
-
(0, common_1.Module)({
|
|
56
|
+
(0, common_1.Module)({
|
|
57
|
+
providers: [content_service_1.ContentService],
|
|
58
|
+
exports: [content_service_1.ContentService],
|
|
59
|
+
})
|
|
57
60
|
], ContentModule);
|
|
@@ -19,6 +19,7 @@ const class_validator_1 = require("class-validator");
|
|
|
19
19
|
function PropertyContent(options = {}) {
|
|
20
20
|
return (0, common_1.applyDecorators)((0, swagger_1.ApiProperty)(Object.assign({ example: [] }, options)),
|
|
21
21
|
// Transforms values: ensures empty or invalid arrays are sanitized to undefined
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
22
23
|
(0, class_transformer_1.Transform)(({ value }) => ((0, class_validator_1.arrayMinSize)(value, 1) ? value : undefined)),
|
|
23
24
|
// Enforces array to contain at least one element
|
|
24
25
|
(0, class_validator_1.ArrayMinSize)(1, {
|