@hed-hog/lms 0.0.358 → 0.0.361
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/course/course.module.d.ts.map +1 -1
- package/dist/course/course.module.js +13 -3
- package/dist/course/course.module.js.map +1 -1
- package/dist/course/lms-bulk-upload.controller.d.ts +37 -0
- package/dist/course/lms-bulk-upload.controller.d.ts.map +1 -0
- package/dist/course/lms-bulk-upload.controller.js +60 -0
- package/dist/course/lms-bulk-upload.controller.js.map +1 -0
- package/dist/course/lms-bulk-upload.service.d.ts +42 -0
- package/dist/course/lms-bulk-upload.service.d.ts.map +1 -0
- package/dist/course/lms-bulk-upload.service.js +169 -0
- package/dist/course/lms-bulk-upload.service.js.map +1 -0
- package/dist/course/lms-setting.controller.d.ts +3 -0
- package/dist/course/lms-setting.controller.d.ts.map +1 -1
- package/dist/course/lms-setting.controller.js +9 -1
- package/dist/course/lms-setting.controller.js.map +1 -1
- package/dist/platforma/platforma.controller.d.ts +9 -9
- package/hedhog/data/role.yaml +8 -0
- package/hedhog/data/route.yaml +35 -0
- package/hedhog/data/setting_group.yaml +33 -0
- package/package.json +8 -8
- package/src/course/course.module.ts +13 -3
- package/src/course/lms-bulk-upload.controller.ts +27 -0
- package/src/course/lms-bulk-upload.service.ts +204 -0
- package/src/course/lms-setting.controller.ts +12 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"course.module.d.ts","sourceRoot":"","sources":["../../src/course/course.module.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"course.module.d.ts","sourceRoot":"","sources":["../../src/course/course.module.ts"],"names":[],"mappings":"AAmBA,qBA8Ba,YAAY;CAAG"}
|
|
@@ -13,16 +13,18 @@ const queue_1 = require("@hed-hog/queue");
|
|
|
13
13
|
const common_1 = require("@nestjs/common");
|
|
14
14
|
const instructor_module_1 = require("../instructor/instructor.module");
|
|
15
15
|
const course_lesson_controller_1 = require("./course-lesson.controller");
|
|
16
|
-
const course_operations_controller_1 = require("./course-operations.controller");
|
|
17
16
|
const course_operations_integration_service_1 = require("./course-operations-integration.service");
|
|
17
|
+
const course_operations_controller_1 = require("./course-operations.controller");
|
|
18
18
|
const course_structure_controller_1 = require("./course-structure.controller");
|
|
19
|
-
const lms_setting_controller_1 = require("./lms-setting.controller");
|
|
20
19
|
const course_structure_service_1 = require("./course-structure.service");
|
|
21
20
|
const course_video_conversion_service_1 = require("./course-video-conversion.service");
|
|
22
21
|
const course_controller_1 = require("./course.controller");
|
|
23
22
|
const course_mcp_tools_1 = require("./course.mcp-tools");
|
|
24
23
|
const course_service_1 = require("./course.service");
|
|
24
|
+
const lms_bulk_upload_controller_1 = require("./lms-bulk-upload.controller");
|
|
25
|
+
const lms_bulk_upload_service_1 = require("./lms-bulk-upload.service");
|
|
25
26
|
const lms_operations_task_subscriber_1 = require("./lms-operations-task.subscriber");
|
|
27
|
+
const lms_setting_controller_1 = require("./lms-setting.controller");
|
|
26
28
|
let CourseModule = class CourseModule {
|
|
27
29
|
};
|
|
28
30
|
exports.CourseModule = CourseModule;
|
|
@@ -34,12 +36,20 @@ exports.CourseModule = CourseModule = __decorate([
|
|
|
34
36
|
(0, common_1.forwardRef)(() => core_1.CoreModule),
|
|
35
37
|
(0, common_1.forwardRef)(() => queue_1.QueueModule),
|
|
36
38
|
],
|
|
37
|
-
controllers: [
|
|
39
|
+
controllers: [
|
|
40
|
+
course_controller_1.CourseController,
|
|
41
|
+
course_structure_controller_1.CourseStructureController,
|
|
42
|
+
course_lesson_controller_1.CourseLessonController,
|
|
43
|
+
lms_setting_controller_1.LmsSettingController,
|
|
44
|
+
course_operations_controller_1.CourseOperationsController,
|
|
45
|
+
lms_bulk_upload_controller_1.LmsBulkUploadController,
|
|
46
|
+
],
|
|
38
47
|
providers: [
|
|
39
48
|
course_operations_integration_service_1.CourseOperationsIntegrationService,
|
|
40
49
|
course_service_1.CourseService,
|
|
41
50
|
course_structure_service_1.CourseStructureService,
|
|
42
51
|
course_video_conversion_service_1.CourseVideoConversionService,
|
|
52
|
+
lms_bulk_upload_service_1.LmsBulkUploadService,
|
|
43
53
|
course_mcp_tools_1.LmsCoursesMcpTools,
|
|
44
54
|
lms_operations_task_subscriber_1.LmsOperationsTaskSubscriber,
|
|
45
55
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"course.module.js","sourceRoot":"","sources":["../../src/course/course.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAmD;AACnD,wCAA2C;AAC3C,0CAA6C;AAC7C,2CAAoD;AACpD,uEAAmE;AACnE,yEAAoE;AACpE,iFAA4E;AAC5E
|
|
1
|
+
{"version":3,"file":"course.module.js","sourceRoot":"","sources":["../../src/course/course.module.ts"],"names":[],"mappings":";;;;;;;;;AAAA,oDAAmD;AACnD,wCAA2C;AAC3C,0CAA6C;AAC7C,2CAAoD;AACpD,uEAAmE;AACnE,yEAAoE;AACpE,mGAA6F;AAC7F,iFAA4E;AAC5E,+EAA0E;AAC1E,yEAAoE;AACpE,uFAAiF;AACjF,2DAAuD;AACvD,yDAAwD;AACxD,qDAAiD;AACjD,6EAAuE;AACvE,uEAAiE;AACjE,qFAA+E;AAC/E,qEAAgE;AAgCzD,IAAM,YAAY,GAAlB,MAAM,YAAY;CAAG,CAAA;AAAf,oCAAY;uBAAZ,YAAY;IA9BxB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,yBAAY,CAAC;YAC9B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,oCAAgB,CAAC;YAClC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,iBAAU,CAAC;YAC5B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,mBAAW,CAAC;SAC9B;QACD,WAAW,EAAE;YACX,oCAAgB;YAChB,uDAAyB;YACzB,iDAAsB;YACtB,6CAAoB;YACpB,yDAA0B;YAC1B,oDAAuB;SACxB;QACD,SAAS,EAAE;YACT,0EAAkC;YAClC,8BAAa;YACb,iDAAsB;YACtB,8DAA4B;YAC5B,8CAAoB;YACpB,qCAAkB;YAClB,4DAA2B;SAC5B;QACD,OAAO,EAAE;YACP,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,8BAAa,CAAC;YAC/B,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,iDAAsB,CAAC;YACxC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,8DAA4B,CAAC;SAC/C;KACF,CAAC;GACW,YAAY,CAAG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { LmsBulkUploadService } from './lms-bulk-upload.service';
|
|
2
|
+
export declare class LmsBulkUploadController {
|
|
3
|
+
private readonly bulkUploadService;
|
|
4
|
+
constructor(bulkUploadService: LmsBulkUploadService);
|
|
5
|
+
getSettings(): Promise<{
|
|
6
|
+
storageProfileId: number;
|
|
7
|
+
bucketName: string;
|
|
8
|
+
sessionDurationSeconds: number;
|
|
9
|
+
}>;
|
|
10
|
+
getTemporaryCredentials(userId: number): Promise<{
|
|
11
|
+
provider: string;
|
|
12
|
+
bucket: string;
|
|
13
|
+
region: string;
|
|
14
|
+
keyPrefix: string;
|
|
15
|
+
credentials: {
|
|
16
|
+
accessKeyId: string;
|
|
17
|
+
secretAccessKey: string;
|
|
18
|
+
sessionToken: string;
|
|
19
|
+
expiresAt: string;
|
|
20
|
+
};
|
|
21
|
+
}>;
|
|
22
|
+
verifyFile(userId: number, payload: {
|
|
23
|
+
key?: string;
|
|
24
|
+
fileName?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
isValid: boolean;
|
|
27
|
+
key: string;
|
|
28
|
+
sizeBytes: number;
|
|
29
|
+
etag: string;
|
|
30
|
+
} | {
|
|
31
|
+
isValid: boolean;
|
|
32
|
+
key: string;
|
|
33
|
+
sizeBytes?: undefined;
|
|
34
|
+
etag?: undefined;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=lms-bulk-upload.controller.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lms-bulk-upload.controller.d.ts","sourceRoot":"","sources":["../../src/course/lms-bulk-upload.controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,qBAEa,uBAAuB;IACtB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;gBAAjB,iBAAiB,EAAE,oBAAoB;IAGpE,WAAW;;;;;IAKX,uBAAuB,CAAa,MAAM,EAAE,MAAM;;;;;;;;;;;;IAKlD,UAAU,CACI,MAAM,EAAE,MAAM,EAClB,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;CAIvD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.LmsBulkUploadController = void 0;
|
|
16
|
+
const api_1 = require("@hed-hog/api");
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const lms_bulk_upload_service_1 = require("./lms-bulk-upload.service");
|
|
19
|
+
let LmsBulkUploadController = class LmsBulkUploadController {
|
|
20
|
+
constructor(bulkUploadService) {
|
|
21
|
+
this.bulkUploadService = bulkUploadService;
|
|
22
|
+
}
|
|
23
|
+
getSettings() {
|
|
24
|
+
return this.bulkUploadService.getBulkUploadSettings();
|
|
25
|
+
}
|
|
26
|
+
getTemporaryCredentials(userId) {
|
|
27
|
+
return this.bulkUploadService.getTemporaryCredentials(userId);
|
|
28
|
+
}
|
|
29
|
+
verifyFile(userId, payload) {
|
|
30
|
+
return this.bulkUploadService.verifyFileOnS3(userId, payload !== null && payload !== void 0 ? payload : {});
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
exports.LmsBulkUploadController = LmsBulkUploadController;
|
|
34
|
+
__decorate([
|
|
35
|
+
(0, common_1.Get)('settings'),
|
|
36
|
+
__metadata("design:type", Function),
|
|
37
|
+
__metadata("design:paramtypes", []),
|
|
38
|
+
__metadata("design:returntype", void 0)
|
|
39
|
+
], LmsBulkUploadController.prototype, "getSettings", null);
|
|
40
|
+
__decorate([
|
|
41
|
+
(0, common_1.Post)('temporary-credentials'),
|
|
42
|
+
__param(0, (0, api_1.User)('id')),
|
|
43
|
+
__metadata("design:type", Function),
|
|
44
|
+
__metadata("design:paramtypes", [Number]),
|
|
45
|
+
__metadata("design:returntype", void 0)
|
|
46
|
+
], LmsBulkUploadController.prototype, "getTemporaryCredentials", null);
|
|
47
|
+
__decorate([
|
|
48
|
+
(0, common_1.Post)('verify'),
|
|
49
|
+
__param(0, (0, api_1.User)('id')),
|
|
50
|
+
__param(1, (0, common_1.Body)()),
|
|
51
|
+
__metadata("design:type", Function),
|
|
52
|
+
__metadata("design:paramtypes", [Number, Object]),
|
|
53
|
+
__metadata("design:returntype", void 0)
|
|
54
|
+
], LmsBulkUploadController.prototype, "verifyFile", null);
|
|
55
|
+
exports.LmsBulkUploadController = LmsBulkUploadController = __decorate([
|
|
56
|
+
(0, api_1.Role)(),
|
|
57
|
+
(0, common_1.Controller)('lms/bulk-upload'),
|
|
58
|
+
__metadata("design:paramtypes", [lms_bulk_upload_service_1.LmsBulkUploadService])
|
|
59
|
+
], LmsBulkUploadController);
|
|
60
|
+
//# sourceMappingURL=lms-bulk-upload.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lms-bulk-upload.controller.js","sourceRoot":"","sources":["../../src/course/lms-bulk-upload.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,sCAA0C;AAC1C,2CAA6D;AAC7D,uEAAiE;AAI1D,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAClC,YAA6B,iBAAuC;QAAvC,sBAAiB,GAAjB,iBAAiB,CAAsB;IAAG,CAAC;IAGxE,WAAW;QACT,OAAO,IAAI,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC;IACxD,CAAC;IAGD,uBAAuB,CAAa,MAAc;QAChD,OAAO,IAAI,CAAC,iBAAiB,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IAGD,UAAU,CACI,MAAc,EAClB,OAA4C;QAEpD,OAAO,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC;IACtE,CAAC;CACF,CAAA;AApBY,0DAAuB;AAIlC;IADC,IAAA,YAAG,EAAC,UAAU,CAAC;;;;0DAGf;AAGD;IADC,IAAA,aAAI,EAAC,uBAAuB,CAAC;IACL,WAAA,IAAA,UAAI,EAAC,IAAI,CAAC,CAAA;;;;sEAElC;AAGD;IADC,IAAA,aAAI,EAAC,QAAQ,CAAC;IAEZ,WAAA,IAAA,UAAI,EAAC,IAAI,CAAC,CAAA;IACV,WAAA,IAAA,aAAI,GAAE,CAAA;;;;yDAGR;kCAnBU,uBAAuB;IAFnC,IAAA,UAAI,GAAE;IACN,IAAA,mBAAU,EAAC,iBAAiB,CAAC;qCAEoB,8CAAoB;GADzD,uBAAuB,CAoBnC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { FileService } from '@hed-hog/core';
|
|
2
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
3
|
+
import { SettingService } from '@hed-hog/core';
|
|
4
|
+
export declare class LmsBulkUploadService {
|
|
5
|
+
private readonly settingService;
|
|
6
|
+
private readonly prismaService;
|
|
7
|
+
private readonly fileService;
|
|
8
|
+
constructor(settingService: SettingService, prismaService: PrismaService, fileService: FileService);
|
|
9
|
+
getBulkUploadSettings(): Promise<{
|
|
10
|
+
storageProfileId: number;
|
|
11
|
+
bucketName: string;
|
|
12
|
+
sessionDurationSeconds: number;
|
|
13
|
+
}>;
|
|
14
|
+
getTemporaryCredentials(userId: number): Promise<{
|
|
15
|
+
provider: string;
|
|
16
|
+
bucket: string;
|
|
17
|
+
region: string;
|
|
18
|
+
keyPrefix: string;
|
|
19
|
+
credentials: {
|
|
20
|
+
accessKeyId: string;
|
|
21
|
+
secretAccessKey: string;
|
|
22
|
+
sessionToken: string;
|
|
23
|
+
expiresAt: string;
|
|
24
|
+
};
|
|
25
|
+
}>;
|
|
26
|
+
verifyFileOnS3(userId: number, payload: {
|
|
27
|
+
key?: string;
|
|
28
|
+
fileName?: string;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
isValid: boolean;
|
|
31
|
+
key: string;
|
|
32
|
+
sizeBytes: number;
|
|
33
|
+
etag: string;
|
|
34
|
+
} | {
|
|
35
|
+
isValid: boolean;
|
|
36
|
+
key: string;
|
|
37
|
+
sizeBytes?: undefined;
|
|
38
|
+
etag?: undefined;
|
|
39
|
+
}>;
|
|
40
|
+
private resolveStorageProfileAndBucket;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=lms-bulk-upload.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lms-bulk-upload.service.d.ts","sourceRoot":"","sources":["../../src/course/lms-bulk-upload.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAmB/C,qBACa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAE/B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAJX,cAAc,EAAE,cAAc,EAE9B,aAAa,EAAE,aAAa,EAE5B,WAAW,EAAE,WAAW;IAGrC,qBAAqB;;;;;IAkBrB,uBAAuB,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;IA2CtC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;;;;;;;;;;;YA2CnE,8BAA8B;CAmE7C"}
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.LmsBulkUploadService = void 0;
|
|
16
|
+
const core_1 = require("@hed-hog/core");
|
|
17
|
+
const api_prisma_1 = require("@hed-hog/api-prisma");
|
|
18
|
+
const core_2 = require("@hed-hog/core");
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
let LmsBulkUploadService = class LmsBulkUploadService {
|
|
21
|
+
constructor(settingService, prismaService, fileService) {
|
|
22
|
+
this.settingService = settingService;
|
|
23
|
+
this.prismaService = prismaService;
|
|
24
|
+
this.fileService = fileService;
|
|
25
|
+
}
|
|
26
|
+
async getBulkUploadSettings() {
|
|
27
|
+
const settings = await this.settingService.getSettingValues([
|
|
28
|
+
'lms-bulk-upload-storage-profile-id',
|
|
29
|
+
'lms-bulk-upload-s3-bucket',
|
|
30
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
31
|
+
]);
|
|
32
|
+
return {
|
|
33
|
+
storageProfileId: Number(settings['lms-bulk-upload-storage-profile-id'] || 0) || null,
|
|
34
|
+
bucketName: typeof settings['lms-bulk-upload-s3-bucket'] === 'string'
|
|
35
|
+
? settings['lms-bulk-upload-s3-bucket'].trim()
|
|
36
|
+
: '',
|
|
37
|
+
sessionDurationSeconds: Number(settings['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
async getTemporaryCredentials(userId) {
|
|
41
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
42
|
+
const { profile, region, bucket, durationSeconds, prefix } = await this.resolveStorageProfileAndBucket(userId);
|
|
43
|
+
const credentials = profile.config;
|
|
44
|
+
const accessKeyId = String((_a = credentials.access_key_id) !== null && _a !== void 0 ? _a : '').trim();
|
|
45
|
+
const secretAccessKey = String((_b = credentials.secret_access_key) !== null && _b !== void 0 ? _b : '').trim();
|
|
46
|
+
const sessionToken = String((_c = credentials.session_token) !== null && _c !== void 0 ? _c : '').trim() || undefined;
|
|
47
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
48
|
+
throw new common_1.BadRequestException('Storage profile does not contain AWS credentials (access_key_id/secret_access_key).');
|
|
49
|
+
}
|
|
50
|
+
const roleArn = String((_d = credentials.role_arn) !== null && _d !== void 0 ? _d : '').trim();
|
|
51
|
+
const externalId = String((_e = credentials.external_id) !== null && _e !== void 0 ? _e : '').trim();
|
|
52
|
+
const tempCredentials = await this.fileService.getTemporaryCredentials({
|
|
53
|
+
accessKeyId,
|
|
54
|
+
secretAccessKey,
|
|
55
|
+
sessionToken,
|
|
56
|
+
region,
|
|
57
|
+
roleArn: roleArn || undefined,
|
|
58
|
+
externalId: externalId || undefined,
|
|
59
|
+
durationSeconds,
|
|
60
|
+
sessionName: `hedhog-desktop-u${userId}-${Date.now()}`,
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
provider: 'aws-s3',
|
|
64
|
+
bucket,
|
|
65
|
+
region,
|
|
66
|
+
keyPrefix: prefix,
|
|
67
|
+
credentials: {
|
|
68
|
+
accessKeyId: tempCredentials.AccessKeyId,
|
|
69
|
+
secretAccessKey: tempCredentials.SecretAccessKey,
|
|
70
|
+
sessionToken: tempCredentials.SessionToken,
|
|
71
|
+
expiresAt: (_g = (_f = tempCredentials.Expiration) === null || _f === void 0 ? void 0 : _f.toISOString()) !== null && _g !== void 0 ? _g : null,
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async verifyFileOnS3(userId, payload) {
|
|
76
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
77
|
+
const { profile, region, bucket, prefix } = await this.resolveStorageProfileAndBucket(userId);
|
|
78
|
+
const credentials = profile.config;
|
|
79
|
+
const accessKeyId = String((_a = credentials.access_key_id) !== null && _a !== void 0 ? _a : '').trim();
|
|
80
|
+
const secretAccessKey = String((_b = credentials.secret_access_key) !== null && _b !== void 0 ? _b : '').trim();
|
|
81
|
+
const sessionToken = String((_c = credentials.session_token) !== null && _c !== void 0 ? _c : '').trim() || undefined;
|
|
82
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
83
|
+
throw new common_1.BadRequestException('Storage profile does not contain AWS credentials (access_key_id/secret_access_key).');
|
|
84
|
+
}
|
|
85
|
+
const objectKey = String((_d = payload.key) !== null && _d !== void 0 ? _d : '').trim() || `${prefix}${String((_e = payload.fileName) !== null && _e !== void 0 ? _e : '').trim()}`;
|
|
86
|
+
if (!objectKey) {
|
|
87
|
+
throw new common_1.BadRequestException('Provide file key or fileName to verify on S3.');
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const result = await this.fileService.headS3Object({
|
|
91
|
+
accessKeyId,
|
|
92
|
+
secretAccessKey,
|
|
93
|
+
sessionToken,
|
|
94
|
+
region,
|
|
95
|
+
bucket,
|
|
96
|
+
key: objectKey,
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
isValid: true,
|
|
100
|
+
key: objectKey,
|
|
101
|
+
sizeBytes: (_f = result.ContentLength) !== null && _f !== void 0 ? _f : null,
|
|
102
|
+
etag: (_g = result.ETag) !== null && _g !== void 0 ? _g : null,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch (_h) {
|
|
106
|
+
return {
|
|
107
|
+
isValid: false,
|
|
108
|
+
key: objectKey,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async resolveStorageProfileAndBucket(userId) {
|
|
113
|
+
var _a, _b, _c, _d, _e;
|
|
114
|
+
const settings = await this.settingService.getSettingValues([
|
|
115
|
+
'lms-bulk-upload-storage-profile-id',
|
|
116
|
+
'lms-bulk-upload-s3-bucket',
|
|
117
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
118
|
+
]);
|
|
119
|
+
const profileId = Number(settings['lms-bulk-upload-storage-profile-id'] || 0);
|
|
120
|
+
if (!Number.isFinite(profileId) || profileId <= 0) {
|
|
121
|
+
throw new common_1.BadRequestException('LMS bulk upload storage profile is not configured (lms-bulk-upload-storage-profile-id).');
|
|
122
|
+
}
|
|
123
|
+
const profile = await this.prismaService.integration_profile.findUnique({
|
|
124
|
+
where: { id: profileId },
|
|
125
|
+
include: {
|
|
126
|
+
integration_type: { select: { slug: true } },
|
|
127
|
+
integration_provider: { select: { slug: true } },
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
if (!profile) {
|
|
131
|
+
throw new common_1.NotFoundException(`Storage integration profile ${profileId} was not found.`);
|
|
132
|
+
}
|
|
133
|
+
if (profile.integration_type.slug !== 'storage') {
|
|
134
|
+
throw new common_1.BadRequestException(`Integration profile ${profileId} is not a storage profile.`);
|
|
135
|
+
}
|
|
136
|
+
const providerSlug = String((_a = profile.integration_provider.slug) !== null && _a !== void 0 ? _a : '').toLowerCase();
|
|
137
|
+
if (providerSlug !== 's3') {
|
|
138
|
+
throw new common_1.BadRequestException(`Integration provider ${providerSlug} is not supported for desktop bulk upload. Use AWS S3 profile.`);
|
|
139
|
+
}
|
|
140
|
+
const config = (_b = profile.config) !== null && _b !== void 0 ? _b : {};
|
|
141
|
+
const region = String((_c = config.region) !== null && _c !== void 0 ? _c : '').trim() || 'us-east-1';
|
|
142
|
+
const bucketFromSettings = String((_d = settings['lms-bulk-upload-s3-bucket']) !== null && _d !== void 0 ? _d : '').trim();
|
|
143
|
+
const bucketFromProfile = String((_e = config.bucket) !== null && _e !== void 0 ? _e : '').trim();
|
|
144
|
+
const bucket = bucketFromSettings || bucketFromProfile;
|
|
145
|
+
if (!bucket) {
|
|
146
|
+
throw new common_1.BadRequestException('LMS bulk upload bucket is not configured. Set lms-bulk-upload-s3-bucket or profile bucket.');
|
|
147
|
+
}
|
|
148
|
+
const durationSeconds = Math.max(900, Math.min(43200, Number(settings['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600));
|
|
149
|
+
const prefix = `desktop/lms/u${userId}/`;
|
|
150
|
+
return {
|
|
151
|
+
profile,
|
|
152
|
+
region,
|
|
153
|
+
bucket,
|
|
154
|
+
durationSeconds,
|
|
155
|
+
prefix,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
exports.LmsBulkUploadService = LmsBulkUploadService;
|
|
160
|
+
exports.LmsBulkUploadService = LmsBulkUploadService = __decorate([
|
|
161
|
+
(0, common_1.Injectable)(),
|
|
162
|
+
__param(0, (0, common_1.Inject)((0, common_1.forwardRef)(() => core_2.SettingService))),
|
|
163
|
+
__param(1, (0, common_1.Inject)((0, common_1.forwardRef)(() => api_prisma_1.PrismaService))),
|
|
164
|
+
__param(2, (0, common_1.Inject)((0, common_1.forwardRef)(() => core_1.FileService))),
|
|
165
|
+
__metadata("design:paramtypes", [core_2.SettingService,
|
|
166
|
+
api_prisma_1.PrismaService,
|
|
167
|
+
core_1.FileService])
|
|
168
|
+
], LmsBulkUploadService);
|
|
169
|
+
//# sourceMappingURL=lms-bulk-upload.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lms-bulk-upload.service.js","sourceRoot":"","sources":["../../src/course/lms-bulk-upload.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAA4C;AAC5C,oDAAoD;AACpD,wCAA+C;AAC/C,2CAMwB;AAajB,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC/B,YAEmB,cAA8B,EAE9B,aAA4B,EAE5B,WAAwB;QAJxB,mBAAc,GAAd,cAAc,CAAgB;QAE9B,kBAAa,GAAb,aAAa,CAAe;QAE5B,gBAAW,GAAX,WAAW,CAAa;IACxC,CAAC;IAEJ,KAAK,CAAC,qBAAqB;QACzB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC;YAC1D,oCAAoC;YACpC,2BAA2B;YAC3B,sCAAsC;SACvC,CAAC,CAAC;QAEH,OAAO;YACL,gBAAgB,EAAE,MAAM,CAAC,QAAQ,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI;YACrF,UAAU,EACR,OAAO,QAAQ,CAAC,2BAA2B,CAAC,KAAK,QAAQ;gBACvD,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC,CAAC,IAAI,EAAE;gBAC9C,CAAC,CAAC,EAAE;YACR,sBAAsB,EACpB,MAAM,CAAC,QAAQ,CAAC,sCAAsC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI;SAC3E,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,MAAc;;QAC1C,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GACxD,MAAM,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC;QAEpD,MAAM,WAAW,GAAG,OAAO,CAAC,MAAkC,CAAC;QAC/D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnE,MAAM,eAAe,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,iBAAiB,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3E,MAAM,YAAY,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QAEjF,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;YACrC,MAAM,IAAI,4BAAmB,CAC3B,qFAAqF,CACtF,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAEhE,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,uBAAuB,CAAC;YACrE,WAAW;YACX,eAAe;YACf,YAAY;YACZ,MAAM;YACN,OAAO,EAAE,OAAO,IAAI,SAAS;YAC7B,UAAU,EAAE,UAAU,IAAI,SAAS;YACnC,eAAe;YACf,WAAW,EAAE,mBAAmB,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE;SACvD,CAAC,CAAC;QAEH,OAAO;YACL,QAAQ,EAAE,QAAQ;YAClB,MAAM;YACN,MAAM;YACN,SAAS,EAAE,MAAM;YACjB,WAAW,EAAE;gBACX,WAAW,EAAE,eAAe,CAAC,WAAW;gBACxC,eAAe,EAAE,eAAe,CAAC,eAAe;gBAChD,YAAY,EAAE,eAAe,CAAC,YAAY;gBAC1C,SAAS,EAAE,MAAA,MAAA,eAAe,CAAC,UAAU,0CAAE,WAAW,EAAE,mCAAI,IAAI;aAC7D;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc,EAAE,OAA4C;;QAC/E,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,8BAA8B,CAAC,MAAM,CAAC,CAAC;QAE9F,MAAM,WAAW,GAAG,OAAO,CAAC,MAAkC,CAAC;QAC/D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACnE,MAAM,eAAe,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,iBAAiB,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3E,MAAM,YAAY,GAAG,MAAM,CAAC,MAAA,WAAW,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,SAAS,CAAC;QAEjF,IAAI,CAAC,WAAW,IAAI,CAAC,eAAe,EAAE,CAAC;YACrC,MAAM,IAAI,4BAAmB,CAC3B,qFAAqF,CACtF,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,MAAA,OAAO,CAAC,GAAG,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,MAAA,OAAO,CAAC,QAAQ,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1G,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,4BAAmB,CAAC,+CAA+C,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;gBACjD,WAAW;gBACX,eAAe;gBACf,YAAY;gBACZ,MAAM;gBACN,MAAM;gBACN,GAAG,EAAE,SAAS;aACf,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,GAAG,EAAE,SAAS;gBACd,SAAS,EAAE,MAAA,MAAM,CAAC,aAAa,mCAAI,IAAI;gBACvC,IAAI,EAAE,MAAA,MAAM,CAAC,IAAI,mCAAI,IAAI;aAC1B,CAAC;QACJ,CAAC;QAAC,WAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,GAAG,EAAE,SAAS;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,8BAA8B,CAAC,MAAc;;QACzD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC;YAC1D,oCAAoC;YACpC,2BAA2B;YAC3B,sCAAsC;SACvC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,4BAAmB,CAC3B,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,UAAU,CAAC;YACtE,KAAK,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE;YACxB,OAAO,EAAE;gBACP,gBAAgB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;gBAC5C,oBAAoB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;aACjD;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,0BAAiB,CAAC,+BAA+B,SAAS,iBAAiB,CAAC,CAAC;QACzF,CAAC;QAED,IAAI,OAAO,CAAC,gBAAgB,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChD,MAAM,IAAI,4BAAmB,CAC3B,uBAAuB,SAAS,4BAA4B,CAC7D,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,CAAC,MAAA,OAAO,CAAC,oBAAoB,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QACnF,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,4BAAmB,CAC3B,wBAAwB,YAAY,gEAAgE,CACrG,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,MAAC,OAAO,CAAC,MAAmC,mCAAI,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAA,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,WAAW,CAAC;QAEjE,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAA,QAAQ,CAAC,2BAA2B,CAAC,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACtF,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAA,MAAM,CAAC,MAAM,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,kBAAkB,IAAI,iBAAiB,CAAC;QAEvD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,4BAAmB,CAC3B,4FAA4F,CAC7F,CAAC;QACJ,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAC9B,GAAG,EACH,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,sCAAsC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,CAC1F,CAAC;QAEF,MAAM,MAAM,GAAG,gBAAgB,MAAM,GAAG,CAAC;QAEzC,OAAO;YACL,OAAO;YACP,MAAM;YACN,MAAM;YACN,eAAe;YACf,MAAM;SACP,CAAC;IACJ,CAAC;CACF,CAAA;AArLY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAGR,WAAA,IAAA,eAAM,EAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,qBAAc,CAAC,CAAC,CAAA;IAExC,WAAA,IAAA,eAAM,EAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,0BAAa,CAAC,CAAC,CAAA;IAEvC,WAAA,IAAA,eAAM,EAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,kBAAW,CAAC,CAAC,CAAA;qCAHL,qBAAc;QAEf,0BAAa;QAEf,kBAAW;GAPhC,oBAAoB,CAqLhC"}
|
|
@@ -8,6 +8,9 @@ export declare class LmsSettingController {
|
|
|
8
8
|
transcriptionEnabled: boolean;
|
|
9
9
|
youtubeEnabled: boolean;
|
|
10
10
|
vimeoEnabled: boolean;
|
|
11
|
+
bulkUploadStorageProfileId: number;
|
|
12
|
+
bulkUploadBucketName: string;
|
|
13
|
+
bulkUploadStsDurationSeconds: number;
|
|
11
14
|
}>;
|
|
12
15
|
}
|
|
13
16
|
//# sourceMappingURL=lms-setting.controller.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lms-setting.controller.d.ts","sourceRoot":"","sources":["../../src/course/lms-setting.controller.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lms-setting.controller.d.ts","sourceRoot":"","sources":["../../src/course/lms-setting.controller.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,qBAEa,oBAAoB;IAG7B,OAAO,CAAC,QAAQ,CAAC,cAAc;gBAAd,cAAc,EAAE,cAAc;IAI3C,eAAe;;;;;;;;;;CA2BtB"}
|
|
@@ -13,9 +13,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.LmsSettingController = void 0;
|
|
16
|
+
const api_1 = require("@hed-hog/api");
|
|
16
17
|
const core_1 = require("@hed-hog/core");
|
|
17
18
|
const common_1 = require("@nestjs/common");
|
|
18
|
-
const api_1 = require("@hed-hog/api");
|
|
19
19
|
let LmsSettingController = class LmsSettingController {
|
|
20
20
|
constructor(settingService) {
|
|
21
21
|
this.settingService = settingService;
|
|
@@ -27,6 +27,9 @@ let LmsSettingController = class LmsSettingController {
|
|
|
27
27
|
'lms-audio-transcription-enabled',
|
|
28
28
|
'lms-youtube-provider-enabled',
|
|
29
29
|
'lms-vimeo-provider-enabled',
|
|
30
|
+
'lms-bulk-upload-storage-profile-id',
|
|
31
|
+
'lms-bulk-upload-s3-bucket',
|
|
32
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
30
33
|
]);
|
|
31
34
|
return {
|
|
32
35
|
videoConversionEnabled: v['lms-video-conversion-enabled'] !== false,
|
|
@@ -34,6 +37,11 @@ let LmsSettingController = class LmsSettingController {
|
|
|
34
37
|
transcriptionEnabled: v['lms-audio-transcription-enabled'] !== false,
|
|
35
38
|
youtubeEnabled: v['lms-youtube-provider-enabled'] !== false,
|
|
36
39
|
vimeoEnabled: v['lms-vimeo-provider-enabled'] !== false,
|
|
40
|
+
bulkUploadStorageProfileId: Number(v['lms-bulk-upload-storage-profile-id'] || 0) || null,
|
|
41
|
+
bulkUploadBucketName: typeof v['lms-bulk-upload-s3-bucket'] === 'string'
|
|
42
|
+
? v['lms-bulk-upload-s3-bucket']
|
|
43
|
+
: '',
|
|
44
|
+
bulkUploadStsDurationSeconds: Number(v['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600,
|
|
37
45
|
};
|
|
38
46
|
}
|
|
39
47
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lms-setting.controller.js","sourceRoot":"","sources":["../../src/course/lms-setting.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wCAA+C;AAC/C,2CAAqE;
|
|
1
|
+
{"version":3,"file":"lms-setting.controller.js","sourceRoot":"","sources":["../../src/course/lms-setting.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,sCAAoC;AACpC,wCAA+C;AAC/C,2CAAqE;AAI9D,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAC/B,YAEmB,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;IAC9C,CAAC;IAGE,AAAN,KAAK,CAAC,eAAe;QACnB,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC;YACnD,8BAA8B;YAC9B,8BAA8B;YAC9B,iCAAiC;YACjC,8BAA8B;YAC9B,4BAA4B;YAC5B,oCAAoC;YACpC,2BAA2B;YAC3B,sCAAsC;SACvC,CAAC,CAAC;QACH,OAAO;YACL,sBAAsB,EAAE,CAAC,CAAC,8BAA8B,CAAC,KAAK,KAAK;YACnE,sBAAsB,EAAE,CAAC,CAAC,8BAA8B,CAAC,KAAK,KAAK;YACnE,oBAAoB,EAAE,CAAC,CAAC,iCAAiC,CAAC,KAAK,KAAK;YACpE,cAAc,EAAE,CAAC,CAAC,8BAA8B,CAAC,KAAK,KAAK;YAC3D,YAAY,EAAE,CAAC,CAAC,4BAA4B,CAAC,KAAK,KAAK;YACvD,0BAA0B,EACxB,MAAM,CAAC,CAAC,CAAC,oCAAoC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI;YAC9D,oBAAoB,EAClB,OAAO,CAAC,CAAC,2BAA2B,CAAC,KAAK,QAAQ;gBAChD,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC;gBAChC,CAAC,CAAC,EAAE;YACR,4BAA4B,EAC1B,MAAM,CAAC,CAAC,CAAC,sCAAsC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI;SACpE,CAAC;IACJ,CAAC;CACF,CAAA;AAlCY,oDAAoB;AAOzB;IADL,IAAA,YAAG,GAAE;;;;2DA2BL;+BAjCU,oBAAoB;IAFhC,IAAA,UAAI,GAAE;IACN,IAAA,mBAAU,EAAC,cAAc,CAAC;IAGtB,WAAA,IAAA,eAAM,EAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,CAAC,qBAAc,CAAC,CAAC,CAAA;qCACR,qBAAc;GAHtC,oBAAoB,CAkChC"}
|
|
@@ -242,22 +242,22 @@ export declare class PlataformaController {
|
|
|
242
242
|
}>;
|
|
243
243
|
markAllNotificationsRead(userId: number): Promise<import("@prisma/client").Prisma.BatchPayload>;
|
|
244
244
|
markNotificationRead(userId: number, id: number): Promise<{
|
|
245
|
-
type: import("@prisma/client").$Enums.notification_type_enum;
|
|
246
|
-
progress: number | null;
|
|
247
245
|
id: number;
|
|
248
|
-
body: string | null;
|
|
249
|
-
title: string;
|
|
250
|
-
status: import("@prisma/client").$Enums.notification_status_enum;
|
|
251
|
-
icon: string | null;
|
|
252
246
|
user_id: number;
|
|
253
247
|
created_at: Date;
|
|
254
248
|
updated_at: Date;
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
249
|
+
type: import("@prisma/client").$Enums.notification_type_enum;
|
|
250
|
+
body: string | null;
|
|
251
|
+
status: import("@prisma/client").$Enums.notification_status_enum;
|
|
252
|
+
icon: string | null;
|
|
253
|
+
title: string;
|
|
254
|
+
progress: number | null;
|
|
258
255
|
action_type: import("@prisma/client").$Enums.notification_action_type_enum | null;
|
|
259
256
|
action_data: import("@prisma/client/runtime/library").JsonValue | null;
|
|
257
|
+
action_url: string | null;
|
|
260
258
|
auto_remove: boolean;
|
|
259
|
+
started_at: Date | null;
|
|
260
|
+
finished_at: Date | null;
|
|
261
261
|
}>;
|
|
262
262
|
getStreak(userId: number, days?: number): Promise<{
|
|
263
263
|
currentStreak: number;
|
package/hedhog/data/role.yaml
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
en: Administrator with full access to LMS management.
|
|
7
7
|
pt: Administrador com acesso total à gestão de LMS.
|
|
8
8
|
|
|
9
|
+
- slug: lms-bulk-upload
|
|
10
|
+
name:
|
|
11
|
+
en: LMS Bulk Upload
|
|
12
|
+
pt: Upload em Massa LMS
|
|
13
|
+
description:
|
|
14
|
+
en: Allows access to temporary AWS credentials and desktop bulk video upload workflows.
|
|
15
|
+
pt: Permite acesso às credenciais temporárias da AWS e aos fluxos de upload em massa no desktop.
|
|
16
|
+
|
|
9
17
|
- slug: lms-student
|
|
10
18
|
name:
|
|
11
19
|
en: LMS Student
|
package/hedhog/data/route.yaml
CHANGED
|
@@ -6,6 +6,41 @@
|
|
|
6
6
|
slug: admin
|
|
7
7
|
- where:
|
|
8
8
|
slug: admin-lms
|
|
9
|
+
- where:
|
|
10
|
+
slug: lms-bulk-upload
|
|
11
|
+
|
|
12
|
+
- url: /lms/bulk-upload/settings
|
|
13
|
+
method: GET
|
|
14
|
+
relations:
|
|
15
|
+
role:
|
|
16
|
+
- where:
|
|
17
|
+
slug: admin
|
|
18
|
+
- where:
|
|
19
|
+
slug: admin-lms
|
|
20
|
+
- where:
|
|
21
|
+
slug: lms-bulk-upload
|
|
22
|
+
|
|
23
|
+
- url: /lms/bulk-upload/temporary-credentials
|
|
24
|
+
method: POST
|
|
25
|
+
relations:
|
|
26
|
+
role:
|
|
27
|
+
- where:
|
|
28
|
+
slug: admin
|
|
29
|
+
- where:
|
|
30
|
+
slug: admin-lms
|
|
31
|
+
- where:
|
|
32
|
+
slug: lms-bulk-upload
|
|
33
|
+
|
|
34
|
+
- url: /lms/bulk-upload/verify
|
|
35
|
+
method: POST
|
|
36
|
+
relations:
|
|
37
|
+
role:
|
|
38
|
+
- where:
|
|
39
|
+
slug: admin
|
|
40
|
+
- where:
|
|
41
|
+
slug: admin-lms
|
|
42
|
+
- where:
|
|
43
|
+
slug: lms-bulk-upload
|
|
9
44
|
|
|
10
45
|
- url: /lms/evaluations
|
|
11
46
|
method: GET
|
|
@@ -74,3 +74,36 @@
|
|
|
74
74
|
pt: Quando habilitado, instrutores podem usar links do Vimeo como fonte de video nas aulas.
|
|
75
75
|
value: true
|
|
76
76
|
user_override: false
|
|
77
|
+
- slug: lms-bulk-upload-storage-profile-id
|
|
78
|
+
type: number
|
|
79
|
+
component: input-number
|
|
80
|
+
name:
|
|
81
|
+
en: Bulk Upload Storage Profile ID
|
|
82
|
+
pt: ID do perfil de armazenamento para Upload em Massa
|
|
83
|
+
description:
|
|
84
|
+
en: Integration profile id (storage/S3) used to generate temporary credentials for desktop bulk upload.
|
|
85
|
+
pt: ID do perfil de integração (armazenamento/S3) usado para gerar credenciais temporárias no upload em massa do desktop.
|
|
86
|
+
value: 0
|
|
87
|
+
user_override: false
|
|
88
|
+
- slug: lms-bulk-upload-s3-bucket
|
|
89
|
+
type: string
|
|
90
|
+
component: input-text
|
|
91
|
+
name:
|
|
92
|
+
en: Bulk Upload Bucket Name
|
|
93
|
+
pt: Nome do bucket de Upload em Massa
|
|
94
|
+
description:
|
|
95
|
+
en: Target S3 bucket for desktop bulk upload. If empty, uses bucket from the selected profile.
|
|
96
|
+
pt: Bucket S3 de destino para upload em massa no desktop. Se vazio, usa o bucket do perfil selecionado.
|
|
97
|
+
value: ''
|
|
98
|
+
user_override: false
|
|
99
|
+
- slug: lms-bulk-upload-sts-duration-seconds
|
|
100
|
+
type: number
|
|
101
|
+
component: input-number
|
|
102
|
+
name:
|
|
103
|
+
en: Temporary Credential Duration (seconds)
|
|
104
|
+
pt: Duracao da credencial temporaria (segundos)
|
|
105
|
+
description:
|
|
106
|
+
en: Expiration time in seconds for temporary AWS credentials used by desktop bulk upload.
|
|
107
|
+
pt: Tempo de expiracao em segundos para as credenciais temporarias da AWS usadas no upload em massa do desktop.
|
|
108
|
+
value: 3600
|
|
109
|
+
user_override: false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/lms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.361",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -9,16 +9,16 @@
|
|
|
9
9
|
"@nestjs/core": "^11",
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
|
-
"@hed-hog/api": "0.0.
|
|
12
|
+
"@hed-hog/api-types": "0.0.1",
|
|
13
13
|
"@hed-hog/api-prisma": "0.0.6",
|
|
14
|
+
"@hed-hog/api": "0.0.8",
|
|
14
15
|
"@hed-hog/api-locale": "0.0.14",
|
|
15
|
-
"@hed-hog/
|
|
16
|
+
"@hed-hog/category": "0.0.361",
|
|
16
17
|
"@hed-hog/api-pagination": "0.0.7",
|
|
17
|
-
"@hed-hog/crm": "0.0.
|
|
18
|
-
"@hed-hog/
|
|
19
|
-
"@hed-hog/
|
|
20
|
-
"@hed-hog/finance": "0.0.
|
|
21
|
-
"@hed-hog/core": "0.0.358"
|
|
18
|
+
"@hed-hog/crm": "0.0.361",
|
|
19
|
+
"@hed-hog/queue": "0.0.361",
|
|
20
|
+
"@hed-hog/core": "0.0.361",
|
|
21
|
+
"@hed-hog/finance": "0.0.361"
|
|
22
22
|
},
|
|
23
23
|
"exports": {
|
|
24
24
|
".": {
|
|
@@ -4,16 +4,18 @@ import { QueueModule } from '@hed-hog/queue';
|
|
|
4
4
|
import { forwardRef, Module } from '@nestjs/common';
|
|
5
5
|
import { InstructorModule } from '../instructor/instructor.module';
|
|
6
6
|
import { CourseLessonController } from './course-lesson.controller';
|
|
7
|
-
import { CourseOperationsController } from './course-operations.controller';
|
|
8
7
|
import { CourseOperationsIntegrationService } from './course-operations-integration.service';
|
|
8
|
+
import { CourseOperationsController } from './course-operations.controller';
|
|
9
9
|
import { CourseStructureController } from './course-structure.controller';
|
|
10
|
-
import { LmsSettingController } from './lms-setting.controller';
|
|
11
10
|
import { CourseStructureService } from './course-structure.service';
|
|
12
11
|
import { CourseVideoConversionService } from './course-video-conversion.service';
|
|
13
12
|
import { CourseController } from './course.controller';
|
|
14
13
|
import { LmsCoursesMcpTools } from './course.mcp-tools';
|
|
15
14
|
import { CourseService } from './course.service';
|
|
15
|
+
import { LmsBulkUploadController } from './lms-bulk-upload.controller';
|
|
16
|
+
import { LmsBulkUploadService } from './lms-bulk-upload.service';
|
|
16
17
|
import { LmsOperationsTaskSubscriber } from './lms-operations-task.subscriber';
|
|
18
|
+
import { LmsSettingController } from './lms-setting.controller';
|
|
17
19
|
|
|
18
20
|
@Module({
|
|
19
21
|
imports: [
|
|
@@ -22,12 +24,20 @@ import { LmsOperationsTaskSubscriber } from './lms-operations-task.subscriber';
|
|
|
22
24
|
forwardRef(() => CoreModule),
|
|
23
25
|
forwardRef(() => QueueModule),
|
|
24
26
|
],
|
|
25
|
-
controllers: [
|
|
27
|
+
controllers: [
|
|
28
|
+
CourseController,
|
|
29
|
+
CourseStructureController,
|
|
30
|
+
CourseLessonController,
|
|
31
|
+
LmsSettingController,
|
|
32
|
+
CourseOperationsController,
|
|
33
|
+
LmsBulkUploadController,
|
|
34
|
+
],
|
|
26
35
|
providers: [
|
|
27
36
|
CourseOperationsIntegrationService,
|
|
28
37
|
CourseService,
|
|
29
38
|
CourseStructureService,
|
|
30
39
|
CourseVideoConversionService,
|
|
40
|
+
LmsBulkUploadService,
|
|
31
41
|
LmsCoursesMcpTools,
|
|
32
42
|
LmsOperationsTaskSubscriber,
|
|
33
43
|
],
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Role, User } from '@hed-hog/api';
|
|
2
|
+
import { Body, Controller, Get, Post } from '@nestjs/common';
|
|
3
|
+
import { LmsBulkUploadService } from './lms-bulk-upload.service';
|
|
4
|
+
|
|
5
|
+
@Role()
|
|
6
|
+
@Controller('lms/bulk-upload')
|
|
7
|
+
export class LmsBulkUploadController {
|
|
8
|
+
constructor(private readonly bulkUploadService: LmsBulkUploadService) {}
|
|
9
|
+
|
|
10
|
+
@Get('settings')
|
|
11
|
+
getSettings() {
|
|
12
|
+
return this.bulkUploadService.getBulkUploadSettings();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@Post('temporary-credentials')
|
|
16
|
+
getTemporaryCredentials(@User('id') userId: number) {
|
|
17
|
+
return this.bulkUploadService.getTemporaryCredentials(userId);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Post('verify')
|
|
21
|
+
verifyFile(
|
|
22
|
+
@User('id') userId: number,
|
|
23
|
+
@Body() payload: { key?: string; fileName?: string },
|
|
24
|
+
) {
|
|
25
|
+
return this.bulkUploadService.verifyFileOnS3(userId, payload ?? {});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { FileService } from '@hed-hog/core';
|
|
2
|
+
import { PrismaService } from '@hed-hog/api-prisma';
|
|
3
|
+
import { SettingService } from '@hed-hog/core';
|
|
4
|
+
import {
|
|
5
|
+
BadRequestException,
|
|
6
|
+
Inject,
|
|
7
|
+
Injectable,
|
|
8
|
+
NotFoundException,
|
|
9
|
+
forwardRef,
|
|
10
|
+
} from '@nestjs/common';
|
|
11
|
+
|
|
12
|
+
type IntegrationProfileConfig = {
|
|
13
|
+
access_key_id?: string;
|
|
14
|
+
secret_access_key?: string;
|
|
15
|
+
session_token?: string;
|
|
16
|
+
region?: string;
|
|
17
|
+
bucket?: string;
|
|
18
|
+
role_arn?: string;
|
|
19
|
+
external_id?: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
@Injectable()
|
|
23
|
+
export class LmsBulkUploadService {
|
|
24
|
+
constructor(
|
|
25
|
+
@Inject(forwardRef(() => SettingService))
|
|
26
|
+
private readonly settingService: SettingService,
|
|
27
|
+
@Inject(forwardRef(() => PrismaService))
|
|
28
|
+
private readonly prismaService: PrismaService,
|
|
29
|
+
@Inject(forwardRef(() => FileService))
|
|
30
|
+
private readonly fileService: FileService,
|
|
31
|
+
) {}
|
|
32
|
+
|
|
33
|
+
async getBulkUploadSettings() {
|
|
34
|
+
const settings = await this.settingService.getSettingValues([
|
|
35
|
+
'lms-bulk-upload-storage-profile-id',
|
|
36
|
+
'lms-bulk-upload-s3-bucket',
|
|
37
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
storageProfileId: Number(settings['lms-bulk-upload-storage-profile-id'] || 0) || null,
|
|
42
|
+
bucketName:
|
|
43
|
+
typeof settings['lms-bulk-upload-s3-bucket'] === 'string'
|
|
44
|
+
? settings['lms-bulk-upload-s3-bucket'].trim()
|
|
45
|
+
: '',
|
|
46
|
+
sessionDurationSeconds:
|
|
47
|
+
Number(settings['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async getTemporaryCredentials(userId: number) {
|
|
52
|
+
const { profile, region, bucket, durationSeconds, prefix } =
|
|
53
|
+
await this.resolveStorageProfileAndBucket(userId);
|
|
54
|
+
|
|
55
|
+
const credentials = profile.config as IntegrationProfileConfig;
|
|
56
|
+
const accessKeyId = String(credentials.access_key_id ?? '').trim();
|
|
57
|
+
const secretAccessKey = String(credentials.secret_access_key ?? '').trim();
|
|
58
|
+
const sessionToken = String(credentials.session_token ?? '').trim() || undefined;
|
|
59
|
+
|
|
60
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
61
|
+
throw new BadRequestException(
|
|
62
|
+
'Storage profile does not contain AWS credentials (access_key_id/secret_access_key).',
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const roleArn = String(credentials.role_arn ?? '').trim();
|
|
67
|
+
const externalId = String(credentials.external_id ?? '').trim();
|
|
68
|
+
|
|
69
|
+
const tempCredentials = await this.fileService.getTemporaryCredentials({
|
|
70
|
+
accessKeyId,
|
|
71
|
+
secretAccessKey,
|
|
72
|
+
sessionToken,
|
|
73
|
+
region,
|
|
74
|
+
roleArn: roleArn || undefined,
|
|
75
|
+
externalId: externalId || undefined,
|
|
76
|
+
durationSeconds,
|
|
77
|
+
sessionName: `hedhog-desktop-u${userId}-${Date.now()}`,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
provider: 'aws-s3',
|
|
82
|
+
bucket,
|
|
83
|
+
region,
|
|
84
|
+
keyPrefix: prefix,
|
|
85
|
+
credentials: {
|
|
86
|
+
accessKeyId: tempCredentials.AccessKeyId,
|
|
87
|
+
secretAccessKey: tempCredentials.SecretAccessKey,
|
|
88
|
+
sessionToken: tempCredentials.SessionToken,
|
|
89
|
+
expiresAt: tempCredentials.Expiration?.toISOString() ?? null,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async verifyFileOnS3(userId: number, payload: { key?: string; fileName?: string }) {
|
|
95
|
+
const { profile, region, bucket, prefix } = await this.resolveStorageProfileAndBucket(userId);
|
|
96
|
+
|
|
97
|
+
const credentials = profile.config as IntegrationProfileConfig;
|
|
98
|
+
const accessKeyId = String(credentials.access_key_id ?? '').trim();
|
|
99
|
+
const secretAccessKey = String(credentials.secret_access_key ?? '').trim();
|
|
100
|
+
const sessionToken = String(credentials.session_token ?? '').trim() || undefined;
|
|
101
|
+
|
|
102
|
+
if (!accessKeyId || !secretAccessKey) {
|
|
103
|
+
throw new BadRequestException(
|
|
104
|
+
'Storage profile does not contain AWS credentials (access_key_id/secret_access_key).',
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const objectKey = String(payload.key ?? '').trim() || `${prefix}${String(payload.fileName ?? '').trim()}`;
|
|
109
|
+
if (!objectKey) {
|
|
110
|
+
throw new BadRequestException('Provide file key or fileName to verify on S3.');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const result = await this.fileService.headS3Object({
|
|
115
|
+
accessKeyId,
|
|
116
|
+
secretAccessKey,
|
|
117
|
+
sessionToken,
|
|
118
|
+
region,
|
|
119
|
+
bucket,
|
|
120
|
+
key: objectKey,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
isValid: true,
|
|
125
|
+
key: objectKey,
|
|
126
|
+
sizeBytes: result.ContentLength ?? null,
|
|
127
|
+
etag: result.ETag ?? null,
|
|
128
|
+
};
|
|
129
|
+
} catch {
|
|
130
|
+
return {
|
|
131
|
+
isValid: false,
|
|
132
|
+
key: objectKey,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
private async resolveStorageProfileAndBucket(userId: number) {
|
|
138
|
+
const settings = await this.settingService.getSettingValues([
|
|
139
|
+
'lms-bulk-upload-storage-profile-id',
|
|
140
|
+
'lms-bulk-upload-s3-bucket',
|
|
141
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const profileId = Number(settings['lms-bulk-upload-storage-profile-id'] || 0);
|
|
145
|
+
if (!Number.isFinite(profileId) || profileId <= 0) {
|
|
146
|
+
throw new BadRequestException(
|
|
147
|
+
'LMS bulk upload storage profile is not configured (lms-bulk-upload-storage-profile-id).',
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const profile = await this.prismaService.integration_profile.findUnique({
|
|
152
|
+
where: { id: profileId },
|
|
153
|
+
include: {
|
|
154
|
+
integration_type: { select: { slug: true } },
|
|
155
|
+
integration_provider: { select: { slug: true } },
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (!profile) {
|
|
160
|
+
throw new NotFoundException(`Storage integration profile ${profileId} was not found.`);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (profile.integration_type.slug !== 'storage') {
|
|
164
|
+
throw new BadRequestException(
|
|
165
|
+
`Integration profile ${profileId} is not a storage profile.`,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const providerSlug = String(profile.integration_provider.slug ?? '').toLowerCase();
|
|
170
|
+
if (providerSlug !== 's3') {
|
|
171
|
+
throw new BadRequestException(
|
|
172
|
+
`Integration provider ${providerSlug} is not supported for desktop bulk upload. Use AWS S3 profile.`,
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const config = (profile.config as IntegrationProfileConfig) ?? {};
|
|
177
|
+
const region = String(config.region ?? '').trim() || 'us-east-1';
|
|
178
|
+
|
|
179
|
+
const bucketFromSettings = String(settings['lms-bulk-upload-s3-bucket'] ?? '').trim();
|
|
180
|
+
const bucketFromProfile = String(config.bucket ?? '').trim();
|
|
181
|
+
const bucket = bucketFromSettings || bucketFromProfile;
|
|
182
|
+
|
|
183
|
+
if (!bucket) {
|
|
184
|
+
throw new BadRequestException(
|
|
185
|
+
'LMS bulk upload bucket is not configured. Set lms-bulk-upload-s3-bucket or profile bucket.',
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const durationSeconds = Math.max(
|
|
190
|
+
900,
|
|
191
|
+
Math.min(43200, Number(settings['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600),
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const prefix = `desktop/lms/u${userId}/`;
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
profile,
|
|
198
|
+
region,
|
|
199
|
+
bucket,
|
|
200
|
+
durationSeconds,
|
|
201
|
+
prefix,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { Role } from '@hed-hog/api';
|
|
1
2
|
import { SettingService } from '@hed-hog/core';
|
|
2
3
|
import { Controller, forwardRef, Get, Inject } from '@nestjs/common';
|
|
3
|
-
import { Role } from '@hed-hog/api';
|
|
4
4
|
|
|
5
5
|
@Role()
|
|
6
6
|
@Controller('lms/settings')
|
|
@@ -18,6 +18,9 @@ export class LmsSettingController {
|
|
|
18
18
|
'lms-audio-transcription-enabled',
|
|
19
19
|
'lms-youtube-provider-enabled',
|
|
20
20
|
'lms-vimeo-provider-enabled',
|
|
21
|
+
'lms-bulk-upload-storage-profile-id',
|
|
22
|
+
'lms-bulk-upload-s3-bucket',
|
|
23
|
+
'lms-bulk-upload-sts-duration-seconds',
|
|
21
24
|
]);
|
|
22
25
|
return {
|
|
23
26
|
videoConversionEnabled: v['lms-video-conversion-enabled'] !== false,
|
|
@@ -25,6 +28,14 @@ export class LmsSettingController {
|
|
|
25
28
|
transcriptionEnabled: v['lms-audio-transcription-enabled'] !== false,
|
|
26
29
|
youtubeEnabled: v['lms-youtube-provider-enabled'] !== false,
|
|
27
30
|
vimeoEnabled: v['lms-vimeo-provider-enabled'] !== false,
|
|
31
|
+
bulkUploadStorageProfileId:
|
|
32
|
+
Number(v['lms-bulk-upload-storage-profile-id'] || 0) || null,
|
|
33
|
+
bulkUploadBucketName:
|
|
34
|
+
typeof v['lms-bulk-upload-s3-bucket'] === 'string'
|
|
35
|
+
? v['lms-bulk-upload-s3-bucket']
|
|
36
|
+
: '',
|
|
37
|
+
bulkUploadStsDurationSeconds:
|
|
38
|
+
Number(v['lms-bulk-upload-sts-duration-seconds'] || 3600) || 3600,
|
|
28
39
|
};
|
|
29
40
|
}
|
|
30
41
|
}
|