First version for working parallel
Some checks are pending
CI Pipeline / changes (push) Waiting to run
CI Pipeline / core (push) Blocked by required conditions
CI Pipeline / trading-backend (push) Blocked by required conditions
CI Pipeline / trading-data-service (push) Blocked by required conditions
CI Pipeline / trading-frontend (push) Blocked by required conditions
CI Pipeline / erp-core (push) Blocked by required conditions
CI Pipeline / erp-mecanicas (push) Blocked by required conditions
CI Pipeline / gamilit-backend (push) Blocked by required conditions
CI Pipeline / gamilit-frontend (push) Blocked by required conditions
Some checks are pending
CI Pipeline / changes (push) Waiting to run
CI Pipeline / core (push) Blocked by required conditions
CI Pipeline / trading-backend (push) Blocked by required conditions
CI Pipeline / trading-data-service (push) Blocked by required conditions
CI Pipeline / trading-frontend (push) Blocked by required conditions
CI Pipeline / erp-core (push) Blocked by required conditions
CI Pipeline / erp-mecanicas (push) Blocked by required conditions
CI Pipeline / gamilit-backend (push) Blocked by required conditions
CI Pipeline / gamilit-frontend (push) Blocked by required conditions
This commit is contained in:
parent
789d1ab46b
commit
48e7235e79
@ -152,7 +152,7 @@ export class AdminAlertsController {
|
|||||||
@ApiResponse({ status: 403, description: 'Forbidden - Admin role required' })
|
@ApiResponse({ status: 403, description: 'Forbidden - Admin role required' })
|
||||||
async createAlert(
|
async createAlert(
|
||||||
@Body() createDto: CreateAlertDto,
|
@Body() createDto: CreateAlertDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<AlertResponseDto> {
|
): Promise<AlertResponseDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.alertsService.createAlert(createDto, userId);
|
return this.alertsService.createAlert(createDto, userId);
|
||||||
@ -184,7 +184,7 @@ export class AdminAlertsController {
|
|||||||
async acknowledgeAlert(
|
async acknowledgeAlert(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: AcknowledgeAlertDto,
|
@Body() dto: AcknowledgeAlertDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<AlertResponseDto> {
|
): Promise<AlertResponseDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.alertsService.acknowledgeAlert(id, dto.acknowledgment_note, userId);
|
return this.alertsService.acknowledgeAlert(id, dto.acknowledgment_note, userId);
|
||||||
@ -216,7 +216,7 @@ export class AdminAlertsController {
|
|||||||
async resolveAlert(
|
async resolveAlert(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: ResolveAlertDto,
|
@Body() dto: ResolveAlertDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<AlertResponseDto> {
|
): Promise<AlertResponseDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.alertsService.resolveAlert(id, dto.resolution_note, userId);
|
return this.alertsService.resolveAlert(id, dto.resolution_note, userId);
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export class AdminBulkOperationsController {
|
|||||||
@ApiResponse({ status: 403, description: 'Forbidden - Admin access required' })
|
@ApiResponse({ status: 403, description: 'Forbidden - Admin access required' })
|
||||||
async bulkSuspendUsers(
|
async bulkSuspendUsers(
|
||||||
@Body() dto: BulkSuspendUsersDto,
|
@Body() dto: BulkSuspendUsersDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user.sub; // JWT payload contiene sub = user.id
|
const adminId = req.user.sub; // JWT payload contiene sub = user.id
|
||||||
return this.bulkOpsService.bulkSuspendUsers(dto, adminId);
|
return this.bulkOpsService.bulkSuspendUsers(dto, adminId);
|
||||||
@ -82,7 +82,7 @@ export class AdminBulkOperationsController {
|
|||||||
})
|
})
|
||||||
async bulkActivateUsers(
|
async bulkActivateUsers(
|
||||||
@Body() dto: BulkActivateUsersDto,
|
@Body() dto: BulkActivateUsersDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.bulkOpsService.bulkActivateUsers(dto, adminId);
|
return this.bulkOpsService.bulkActivateUsers(dto, adminId);
|
||||||
@ -104,7 +104,7 @@ export class AdminBulkOperationsController {
|
|||||||
})
|
})
|
||||||
async bulkUpdateRole(
|
async bulkUpdateRole(
|
||||||
@Body() dto: BulkUpdateRoleDto,
|
@Body() dto: BulkUpdateRoleDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.bulkOpsService.bulkUpdateRole(dto, adminId);
|
return this.bulkOpsService.bulkUpdateRole(dto, adminId);
|
||||||
@ -126,7 +126,7 @@ export class AdminBulkOperationsController {
|
|||||||
})
|
})
|
||||||
async bulkDeleteUsers(
|
async bulkDeleteUsers(
|
||||||
@Body() dto: BulkDeleteUsersDto,
|
@Body() dto: BulkDeleteUsersDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.bulkOpsService.bulkDeleteUsers(dto, adminId);
|
return this.bulkOpsService.bulkDeleteUsers(dto, adminId);
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export class AdminContentController {
|
|||||||
async approveContent(
|
async approveContent(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() approvalDto: ApproveContentDto,
|
@Body() approvalDto: ApproveContentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<ContentDto> {
|
): Promise<ContentDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminContentService.approveContent(
|
return this.adminContentService.approveContent(
|
||||||
@ -87,7 +87,7 @@ export class AdminContentController {
|
|||||||
async approveExercise(
|
async approveExercise(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() approvalDto: ApproveContentDto,
|
@Body() approvalDto: ApproveContentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<ContentDto> {
|
): Promise<ContentDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminContentService.approveContent(
|
return this.adminContentService.approveContent(
|
||||||
@ -106,7 +106,7 @@ export class AdminContentController {
|
|||||||
async rejectContent(
|
async rejectContent(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() rejectionDto: RejectContentDto,
|
@Body() rejectionDto: RejectContentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<ContentDto> {
|
): Promise<ContentDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminContentService.rejectContent(
|
return this.adminContentService.rejectContent(
|
||||||
@ -124,7 +124,7 @@ export class AdminContentController {
|
|||||||
async rejectExercise(
|
async rejectExercise(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() rejectionDto: RejectContentDto,
|
@Body() rejectionDto: RejectContentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<ContentDto> {
|
): Promise<ContentDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminContentService.rejectContent(
|
return this.adminContentService.rejectContent(
|
||||||
@ -157,7 +157,7 @@ export class AdminContentController {
|
|||||||
})
|
})
|
||||||
async createVersion(
|
async createVersion(
|
||||||
@Body() dto: CreateVersionDto,
|
@Body() dto: CreateVersionDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<VersionResponseDto> {
|
): Promise<VersionResponseDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminContentService.createVersion(dto, adminId);
|
return this.adminContentService.createVersion(dto, adminId);
|
||||||
|
|||||||
@ -175,7 +175,7 @@ export class AdminGamificationConfigController {
|
|||||||
})
|
})
|
||||||
async updateGamificationSettings(
|
async updateGamificationSettings(
|
||||||
@Body() dto: UpdateGamificationSettingsDto,
|
@Body() dto: UpdateGamificationSettingsDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<GamificationSettingsResponseDto> {
|
): Promise<GamificationSettingsResponseDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.gamificationConfigService.updateGamificationSettings(
|
return this.gamificationConfigService.updateGamificationSettings(
|
||||||
@ -282,7 +282,7 @@ export class AdminGamificationConfigController {
|
|||||||
description: 'Forbidden - User is not an admin',
|
description: 'Forbidden - User is not an admin',
|
||||||
})
|
})
|
||||||
async restoreDefaults(
|
async restoreDefaults(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<RestoreDefaultsResultDto> {
|
): Promise<RestoreDefaultsResultDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.gamificationConfigService.restoreDefaults(adminId);
|
return this.gamificationConfigService.restoreDefaults(adminId);
|
||||||
@ -323,7 +323,7 @@ export class AdminGamificationConfigController {
|
|||||||
description: 'Forbidden - User is not an admin',
|
description: 'Forbidden - User is not an admin',
|
||||||
})
|
})
|
||||||
async restoreDefaultsAlternative(
|
async restoreDefaultsAlternative(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<RestoreDefaultsResultDto> {
|
): Promise<RestoreDefaultsResultDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.gamificationConfigService.restoreDefaults(adminId);
|
return this.gamificationConfigService.restoreDefaults(adminId);
|
||||||
@ -503,7 +503,7 @@ export class AdminGamificationConfigController {
|
|||||||
async updateParameterById(
|
async updateParameterById(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: UpdateParameterDto,
|
@Body() dto: UpdateParameterDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<UpdateParameterResponseDto> {
|
): Promise<UpdateParameterResponseDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.gamificationConfigService.updateParameterById(
|
return this.gamificationConfigService.updateParameterById(
|
||||||
@ -635,7 +635,7 @@ export class AdminGamificationConfigController {
|
|||||||
async updateMayaRank(
|
async updateMayaRank(
|
||||||
@Param('rankName') rankName: string,
|
@Param('rankName') rankName: string,
|
||||||
@Body() dto: UpdateMayaRankDto,
|
@Body() dto: UpdateMayaRankDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<UpdateMayaRankResponseDto> {
|
): Promise<UpdateMayaRankResponseDto> {
|
||||||
const adminId = req.user.sub;
|
const adminId = req.user.sub;
|
||||||
return this.gamificationConfigService.updateMayaRank(
|
return this.gamificationConfigService.updateMayaRank(
|
||||||
|
|||||||
@ -163,7 +163,7 @@ export class AdminInterventionsController {
|
|||||||
async acknowledgeIntervention(
|
async acknowledgeIntervention(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: AcknowledgeInterventionDto,
|
@Body() dto: AcknowledgeInterventionDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<InterventionAlertDto> {
|
): Promise<InterventionAlertDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.interventionsService.acknowledgeIntervention(id, dto.acknowledgment_note, userId);
|
return this.interventionsService.acknowledgeIntervention(id, dto.acknowledgment_note, userId);
|
||||||
@ -211,7 +211,7 @@ export class AdminInterventionsController {
|
|||||||
async resolveIntervention(
|
async resolveIntervention(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: ResolveInterventionDto,
|
@Body() dto: ResolveInterventionDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<InterventionAlertDto> {
|
): Promise<InterventionAlertDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.interventionsService.resolveIntervention(id, dto.resolution_notes, userId);
|
return this.interventionsService.resolveIntervention(id, dto.resolution_notes, userId);
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export class AdminReportsController {
|
|||||||
})
|
})
|
||||||
async generateReport(
|
async generateReport(
|
||||||
@Body() generateDto: GenerateReportDto,
|
@Body() generateDto: GenerateReportDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<ReportDto> {
|
): Promise<ReportDto> {
|
||||||
const userId = req.user?.id || req.user?.sub;
|
const userId = req.user?.id || req.user?.sub;
|
||||||
return this.adminReportsService.generateReport(generateDto, userId);
|
return this.adminReportsService.generateReport(generateDto, userId);
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export class AdminSystemController {
|
|||||||
})
|
})
|
||||||
async updateSystemConfig(
|
async updateSystemConfig(
|
||||||
@Body() configDto: UpdateSystemConfigDto,
|
@Body() configDto: UpdateSystemConfigDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<SystemConfigDto> {
|
): Promise<SystemConfigDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminSystemService.updateSystemConfig(configDto, adminId);
|
return this.adminSystemService.updateSystemConfig(configDto, adminId);
|
||||||
@ -94,7 +94,7 @@ export class AdminSystemController {
|
|||||||
})
|
})
|
||||||
async getConfigByCategory(
|
async getConfigByCategory(
|
||||||
@Param('category') category: string,
|
@Param('category') category: string,
|
||||||
): Promise<Record<string, any>> {
|
): Promise<Record<string, unknown>> {
|
||||||
return this.adminSystemService.getConfigByCategory(category);
|
return this.adminSystemService.getConfigByCategory(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +106,9 @@ export class AdminSystemController {
|
|||||||
})
|
})
|
||||||
async updateConfigByCategory(
|
async updateConfigByCategory(
|
||||||
@Param('category') category: string,
|
@Param('category') category: string,
|
||||||
@Body() configDto: Record<string, any>,
|
@Body() configDto: Record<string, unknown>,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<Record<string, any>> {
|
): Promise<Record<string, unknown>> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminSystemService.updateConfigByCategory(
|
return this.adminSystemService.updateConfigByCategory(
|
||||||
category,
|
category,
|
||||||
@ -125,7 +125,7 @@ export class AdminSystemController {
|
|||||||
})
|
})
|
||||||
async toggleMaintenance(
|
async toggleMaintenance(
|
||||||
@Body() toggleDto: ToggleMaintenanceDto,
|
@Body() toggleDto: ToggleMaintenanceDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<MaintenanceStatusDto> {
|
): Promise<MaintenanceStatusDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.adminSystemService.toggleMaintenance(
|
return this.adminSystemService.toggleMaintenance(
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export class AdminUsersController {
|
|||||||
})
|
})
|
||||||
async bulkSuspend(
|
async bulkSuspend(
|
||||||
@Body() dto: BulkSuspendUsersDto,
|
@Body() dto: BulkSuspendUsersDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.bulkOpsService.bulkSuspendUsers(dto, adminId);
|
return this.bulkOpsService.bulkSuspendUsers(dto, adminId);
|
||||||
@ -151,7 +151,7 @@ export class AdminUsersController {
|
|||||||
})
|
})
|
||||||
async bulkDelete(
|
async bulkDelete(
|
||||||
@Body() dto: BulkDeleteUsersDto,
|
@Body() dto: BulkDeleteUsersDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.bulkOpsService.bulkDeleteUsers(dto, adminId);
|
return this.bulkOpsService.bulkDeleteUsers(dto, adminId);
|
||||||
@ -165,7 +165,7 @@ export class AdminUsersController {
|
|||||||
})
|
})
|
||||||
async bulkUpdateRole(
|
async bulkUpdateRole(
|
||||||
@Body() dto: BulkUpdateRoleDto,
|
@Body() dto: BulkUpdateRoleDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<BulkOperationStatusDto> {
|
): Promise<BulkOperationStatusDto> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.bulkOpsService.bulkUpdateRole(dto, adminId);
|
return this.bulkOpsService.bulkUpdateRole(dto, adminId);
|
||||||
|
|||||||
@ -114,7 +114,7 @@ export class FeatureFlagsController {
|
|||||||
})
|
})
|
||||||
async create(
|
async create(
|
||||||
@Body() dto: CreateFeatureFlagDto,
|
@Body() dto: CreateFeatureFlagDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<FeatureFlag> {
|
): Promise<FeatureFlag> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.featureFlagsService.create(dto, adminId);
|
return this.featureFlagsService.create(dto, adminId);
|
||||||
@ -140,7 +140,7 @@ export class FeatureFlagsController {
|
|||||||
async update(
|
async update(
|
||||||
@Param('key') key: string,
|
@Param('key') key: string,
|
||||||
@Body() dto: UpdateFeatureFlagDto,
|
@Body() dto: UpdateFeatureFlagDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<FeatureFlag> {
|
): Promise<FeatureFlag> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.featureFlagsService.update(key, dto, adminId);
|
return this.featureFlagsService.update(key, dto, adminId);
|
||||||
@ -161,7 +161,7 @@ export class FeatureFlagsController {
|
|||||||
})
|
})
|
||||||
async enable(
|
async enable(
|
||||||
@Param('key') key: string,
|
@Param('key') key: string,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<FeatureFlag> {
|
): Promise<FeatureFlag> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.featureFlagsService.enable(key, adminId);
|
return this.featureFlagsService.enable(key, adminId);
|
||||||
@ -182,7 +182,7 @@ export class FeatureFlagsController {
|
|||||||
})
|
})
|
||||||
async disable(
|
async disable(
|
||||||
@Param('key') key: string,
|
@Param('key') key: string,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<FeatureFlag> {
|
): Promise<FeatureFlag> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.featureFlagsService.disable(key, adminId);
|
return this.featureFlagsService.disable(key, adminId);
|
||||||
@ -204,7 +204,7 @@ export class FeatureFlagsController {
|
|||||||
async updateRollout(
|
async updateRollout(
|
||||||
@Param('key') key: string,
|
@Param('key') key: string,
|
||||||
@Body('percentage') percentage: number,
|
@Body('percentage') percentage: number,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<FeatureFlag> {
|
): Promise<FeatureFlag> {
|
||||||
const adminId = req.user?.id || req.user?.sub;
|
const adminId = req.user?.id || req.user?.sub;
|
||||||
return this.featureFlagsService.updateRollout(key, percentage, adminId);
|
return this.featureFlagsService.updateRollout(key, percentage, adminId);
|
||||||
|
|||||||
@ -75,10 +75,10 @@ export class AlertResponseDto {
|
|||||||
suppress_similar!: boolean;
|
suppress_similar!: boolean;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Additional context data' })
|
@ApiPropertyOptional({ description: 'Additional context data' })
|
||||||
context_data?: Record<string, any>;
|
context_data?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Metrics data' })
|
@ApiPropertyOptional({ description: 'Metrics data' })
|
||||||
metrics?: Record<string, any>;
|
metrics?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Related alert IDs', type: [String] })
|
@ApiPropertyOptional({ description: 'Related alert IDs', type: [String] })
|
||||||
related_alerts?: string[];
|
related_alerts?: string[];
|
||||||
|
|||||||
@ -45,10 +45,10 @@ export class CreateAlertDto {
|
|||||||
@ApiPropertyOptional({ description: 'Additional context data (JSON)' })
|
@ApiPropertyOptional({ description: 'Additional context data (JSON)' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
context_data?: Record<string, any>;
|
context_data?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Metrics data (JSON)' })
|
@ApiPropertyOptional({ description: 'Metrics data (JSON)' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metrics?: Record<string, any>;
|
metrics?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,5 +61,5 @@ export class ContentDto {
|
|||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Additional metadata' })
|
@ApiPropertyOptional({ description: 'Additional metadata' })
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,5 +65,5 @@ export class VersionResponseDto {
|
|||||||
is_published: true,
|
is_published: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
snapshot!: Record<string, any>;
|
snapshot!: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ export class AdminActionDto {
|
|||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Additional metadata in JSON format',
|
description: 'Additional metadata in JSON format',
|
||||||
})
|
})
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Timestamp when the action occurred',
|
description: 'Timestamp when the action occurred',
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export class CreateFeatureFlagDto {
|
|||||||
})
|
})
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
targetConditions?: Record<string, any>;
|
targetConditions?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Categoría de la feature flag',
|
description: 'Categoría de la feature flag',
|
||||||
@ -106,5 +106,5 @@ export class CreateFeatureFlagDto {
|
|||||||
})
|
})
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ export class GamificationSettingsResponseDto {
|
|||||||
perfect_score_bonus: 2.0,
|
perfect_score_bonus: 2.0,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
xp!: Record<string, any>;
|
xp!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Rank thresholds',
|
description: 'Rank thresholds',
|
||||||
@ -27,7 +27,7 @@ export class GamificationSettingsResponseDto {
|
|||||||
expert: 5000,
|
expert: 5000,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
ranks!: Record<string, any>;
|
ranks!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'ML Coins rewards',
|
description: 'ML Coins rewards',
|
||||||
@ -37,13 +37,13 @@ export class GamificationSettingsResponseDto {
|
|||||||
exercise_completion_reward: 100,
|
exercise_completion_reward: 100,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
coins!: Record<string, any>;
|
coins!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Achievement criteria',
|
description: 'Achievement criteria',
|
||||||
example: { criteria: [] },
|
example: { criteria: [] },
|
||||||
})
|
})
|
||||||
achievements?: Record<string, any>;
|
achievements?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Default values from system',
|
description: 'Default values from system',
|
||||||
@ -52,7 +52,7 @@ export class GamificationSettingsResponseDto {
|
|||||||
'gamification.xp.completion_multiplier': 1.5,
|
'gamification.xp.completion_multiplier': 1.5,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
defaults!: Record<string, any>;
|
defaults!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Timestamp of last update',
|
description: 'Timestamp of last update',
|
||||||
|
|||||||
@ -109,13 +109,13 @@ export class ParameterResponseDto {
|
|||||||
description: 'Validation rules in JSON format',
|
description: 'Validation rules in JSON format',
|
||||||
example: { regex: '^[0-9]+$' },
|
example: { regex: '^[0-9]+$' },
|
||||||
})
|
})
|
||||||
validation_rules?: Record<string, any>;
|
validation_rules?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Additional metadata',
|
description: 'Additional metadata',
|
||||||
example: { unit: 'points', category_order: 1 },
|
example: { unit: 'points', category_order: 1 },
|
||||||
})
|
})
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Timestamp when parameter was created',
|
description: 'Timestamp when parameter was created',
|
||||||
|
|||||||
@ -182,5 +182,5 @@ export class UpdateGamificationSettingsDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
achievements?: Record<string, any>;
|
achievements?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export class InterventionAlertDto {
|
|||||||
description: 'Additional metrics and context data',
|
description: 'Additional metrics and context data',
|
||||||
example: { average_score: 45, exercises_failed: 3 },
|
example: { average_score: 45, exercises_failed: 3 },
|
||||||
})
|
})
|
||||||
metrics?: Record<string, any>;
|
metrics?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
enum: InterventionStatus,
|
enum: InterventionStatus,
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export class RecentErrorDto {
|
|||||||
nullable: true,
|
nullable: true,
|
||||||
example: { stack: '...', code: 'ECONNREFUSED' },
|
example: { stack: '...', code: 'ECONNREFUSED' },
|
||||||
})
|
})
|
||||||
context!: Record<string, any> | null;
|
context!: Record<string, unknown> | null;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Source of the error',
|
description: 'Source of the error',
|
||||||
|
|||||||
@ -91,7 +91,7 @@ export class CreateOrganizationDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
settings?: Record<string, any>;
|
settings?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Organization metadata (JSONB)',
|
description: 'Organization metadata (JSONB)',
|
||||||
@ -99,5 +99,5 @@ export class CreateOrganizationDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,11 +49,11 @@ export class OrganizationDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Organization settings', example: { theme: 'detective' } })
|
@ApiProperty({ description: 'Organization settings', example: { theme: 'detective' } })
|
||||||
@Expose()
|
@Expose()
|
||||||
settings!: Record<string, any>;
|
settings!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Organization metadata', example: { notes: '...' } })
|
@ApiProperty({ description: 'Organization metadata', example: { notes: '...' } })
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Creation date', example: '2025-01-15T10:00:00Z' })
|
@ApiProperty({ description: 'Creation date', example: '2025-01-15T10:00:00Z' })
|
||||||
@Expose()
|
@Expose()
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export class UpdateOrganizationDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
settings?: Record<string, any>;
|
settings?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Organization metadata (JSONB)',
|
description: 'Organization metadata (JSONB)',
|
||||||
@ -91,5 +91,5 @@ export class UpdateOrganizationDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,7 @@ export class ReportDto {
|
|||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description: 'Report metadata',
|
description: 'Report metadata',
|
||||||
})
|
})
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'Report creation timestamp',
|
description: 'Report creation timestamp',
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export class MaintenanceOperationResultDto {
|
|||||||
description: 'Additional metadata about the operation',
|
description: 'Additional metadata about the operation',
|
||||||
example: { execution_time_ms: 1523 },
|
example: { execution_time_ms: 1523 },
|
||||||
})
|
})
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export class SystemConfigDto {
|
|||||||
session_timeout_minutes!: number;
|
session_timeout_minutes!: number;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Custom settings' })
|
@ApiPropertyOptional({ description: 'Custom settings' })
|
||||||
custom_settings?: Record<string, any>;
|
custom_settings?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Last updated timestamp', example: '2025-11-02T18:00:00Z' })
|
@ApiProperty({ description: 'Last updated timestamp', example: '2025-11-02T18:00:00Z' })
|
||||||
updated_at!: string;
|
updated_at!: string;
|
||||||
|
|||||||
@ -61,5 +61,5 @@ export class UpdateSystemConfigDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
custom_settings?: Record<string, any>;
|
custom_settings?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,5 +24,5 @@ export class UpdateUserDto {
|
|||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
raw_user_meta_data?: Record<string, any>;
|
raw_user_meta_data?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export class UserDetailsDto {
|
|||||||
last_sign_in_at?: Date;
|
last_sign_in_at?: Date;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
raw_user_meta_data!: Record<string, any>;
|
raw_user_meta_data!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
created_at!: Date;
|
created_at!: Date;
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export class AdminReport {
|
|||||||
* Formato: { startDate: '2025-01-01', endDate: '2025-12-31', classroomId: 'abc', ... }
|
* Formato: { startDate: '2025-01-01', endDate: '2025-12-31', classroomId: 'abc', ... }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mensaje de error si la generación falla
|
* Mensaje de error si la generación falla
|
||||||
|
|||||||
@ -101,7 +101,7 @@ export class FeatureFlag {
|
|||||||
* @example { "min_level": 5, "schools": ["uuid1", "uuid2"] }
|
* @example { "min_level": 5, "schools": ["uuid1", "uuid2"] }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
target_conditions!: Record<string, any>;
|
target_conditions!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de inicio de la feature
|
* Fecha y hora de inicio de la feature
|
||||||
@ -122,7 +122,7 @@ export class FeatureFlag {
|
|||||||
* @example { "ab_test_group": "A", "tracking_id": "GA-123" }
|
* @example { "ab_test_group": "A", "tracking_id": "GA-123" }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que creó la feature flag
|
* ID del usuario que creó la feature flag
|
||||||
|
|||||||
@ -121,20 +121,20 @@ export class NotificationSettings {
|
|||||||
* @example { "max_retries": 3, "backoff": "exponential" }
|
* @example { "max_retries": 3, "backoff": "exponential" }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
retry_policy!: Record<string, any>;
|
retry_policy!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuraciones específicas del canal de entrega
|
* Configuraciones específicas del canal de entrega
|
||||||
* @example { "email_format": "html", "reply_to": "support@example.com" }
|
* @example { "email_format": "html", "reply_to": "support@example.com" }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
delivery_settings!: Record<string, any>;
|
delivery_settings!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadatos adicionales
|
* Metadatos adicionales
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que creó el setting
|
* ID del usuario que creó el setting
|
||||||
|
|||||||
@ -176,14 +176,14 @@ export class SystemAlert {
|
|||||||
* @example { "endpoint": "/api/users", "statusCode": 500, "requestId": "abc123" }
|
* @example { "endpoint": "/api/users", "statusCode": 500, "requestId": "abc123" }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
context_data!: Record<string, any>;
|
context_data!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Métricas asociadas en formato JSONB
|
* Métricas asociadas en formato JSONB
|
||||||
* @example { "responseTime": 5000, "errorRate": 0.15, "cpuUsage": 0.95 }
|
* @example { "responseTime": 5000, "errorRate": 0.15, "cpuUsage": 0.95 }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metrics!: Record<string, any>;
|
metrics!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array de IDs de alertas relacionadas
|
* Array de IDs de alertas relacionadas
|
||||||
|
|||||||
@ -133,7 +133,7 @@ export class SystemSetting {
|
|||||||
* @example { "regex": "^[a-z]+$", "minLength": 3 }
|
* @example { "regex": "^[a-z]+$", "minLength": 3 }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
validation_rules!: Record<string, any>;
|
validation_rules!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valores permitidos para el setting (array de strings)
|
* Valores permitidos para el setting (array de strings)
|
||||||
@ -158,7 +158,7 @@ export class SystemSetting {
|
|||||||
* Metadatos adicionales en formato JSONB
|
* Metadatos adicionales en formato JSONB
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que creó el setting
|
* ID del usuario que creó el setting
|
||||||
|
|||||||
@ -194,7 +194,7 @@ export class AdminAlertsService {
|
|||||||
* @param userId - ID del usuario que crea la alerta (para auditoría)
|
* @param userId - ID del usuario que crea la alerta (para auditoría)
|
||||||
* @returns Alerta creada
|
* @returns Alerta creada
|
||||||
*/
|
*/
|
||||||
async createAlert(createDto: CreateAlertDto: string): Promise<AlertResponseDto> {
|
async createAlert(createDto: CreateAlertDto, _userId: string): Promise<AlertResponseDto> {
|
||||||
const alert = this.alertRepo.create({
|
const alert = this.alertRepo.create({
|
||||||
alert_type: createDto.alert_type,
|
alert_type: createDto.alert_type,
|
||||||
severity: createDto.severity,
|
severity: createDto.severity,
|
||||||
|
|||||||
@ -577,7 +577,7 @@ export class AdminContentService {
|
|||||||
private createSnapshot(
|
private createSnapshot(
|
||||||
content: any,
|
content: any,
|
||||||
content_type: string,
|
content_type: string,
|
||||||
): Record<string, any> {
|
): Record<string, unknown> {
|
||||||
switch (content_type) {
|
switch (content_type) {
|
||||||
case 'module':
|
case 'module':
|
||||||
return {
|
return {
|
||||||
@ -804,7 +804,7 @@ export class AdminContentService {
|
|||||||
});
|
});
|
||||||
content_title = template?.name;
|
content_title = template?.name;
|
||||||
}
|
}
|
||||||
} catch (_error) {
|
} catch {
|
||||||
// Content might have been deleted, just leave title as undefined
|
// Content might have been deleted, just leave title as undefined
|
||||||
content_title = undefined;
|
content_title = undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -279,7 +279,7 @@ export class AdminSystemService {
|
|||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<SystemConfigDto> {
|
): Promise<SystemConfigDto> {
|
||||||
// Update settings in database
|
// Update settings in database
|
||||||
const settingsToUpdate: Record<string, any> = {
|
const settingsToUpdate: Record<string, unknown> = {
|
||||||
maintenance_mode: updateDto.maintenance_mode,
|
maintenance_mode: updateDto.maintenance_mode,
|
||||||
maintenance_message: updateDto.maintenance_message,
|
maintenance_message: updateDto.maintenance_message,
|
||||||
allow_registrations: updateDto.allow_registrations,
|
allow_registrations: updateDto.allow_registrations,
|
||||||
@ -360,7 +360,7 @@ export class AdminSystemService {
|
|||||||
/**
|
/**
|
||||||
* Get system configuration by category
|
* Get system configuration by category
|
||||||
*/
|
*/
|
||||||
async getConfigByCategory(category: string): Promise<Record<string, any>> {
|
async getConfigByCategory(category: string): Promise<Record<string, unknown>> {
|
||||||
// Validate category
|
// Validate category
|
||||||
const validCategories = ['general', 'email', 'notifications', 'security', 'maintenance'];
|
const validCategories = ['general', 'email', 'notifications', 'security', 'maintenance'];
|
||||||
if (!validCategories.includes(category)) {
|
if (!validCategories.includes(category)) {
|
||||||
@ -387,7 +387,7 @@ export class AdminSystemService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Build config object for this category
|
// Build config object for this category
|
||||||
const config: Record<string, any> = {};
|
const config: Record<string, unknown> = {};
|
||||||
settings.forEach((setting) => {
|
settings.forEach((setting) => {
|
||||||
config[setting.setting_key] = this.parseValue(setting);
|
config[setting.setting_key] = this.parseValue(setting);
|
||||||
});
|
});
|
||||||
@ -400,9 +400,9 @@ export class AdminSystemService {
|
|||||||
*/
|
*/
|
||||||
async updateConfigByCategory(
|
async updateConfigByCategory(
|
||||||
category: string,
|
category: string,
|
||||||
configDto: Record<string, any>,
|
configDto: Record<string, unknown>,
|
||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<Record<string, any>> {
|
): Promise<Record<string, unknown>> {
|
||||||
// Validate category
|
// Validate category
|
||||||
const validCategories = ['general', 'email', 'notifications', 'security', 'maintenance'];
|
const validCategories = ['general', 'email', 'notifications', 'security', 'maintenance'];
|
||||||
if (!validCategories.includes(category)) {
|
if (!validCategories.includes(category)) {
|
||||||
@ -744,7 +744,8 @@ export class AdminSystemService {
|
|||||||
pool_size: poolSize,
|
pool_size: poolSize,
|
||||||
active_connections: activeConnections,
|
active_connections: activeConnections,
|
||||||
};
|
};
|
||||||
} catch () {
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
} catch (_error) {
|
||||||
return {
|
return {
|
||||||
status: 'down',
|
status: 'down',
|
||||||
response_time_ms: -1,
|
response_time_ms: -1,
|
||||||
|
|||||||
@ -425,8 +425,8 @@ export class GamificationConfigService {
|
|||||||
* Parse settings array into structured config
|
* Parse settings array into structured config
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private parseSettings(settings: SystemSetting[]): Record<string, any> {
|
private parseSettings(settings: SystemSetting[]): Record<string, unknown> {
|
||||||
const config: Record<string, any> = {
|
const config: Record<string, unknown> = {
|
||||||
xp: {},
|
xp: {},
|
||||||
ranks: {},
|
ranks: {},
|
||||||
coins: {},
|
coins: {},
|
||||||
@ -446,7 +446,7 @@ export class GamificationConfigService {
|
|||||||
} else if (setting.value_type === 'json') {
|
} else if (setting.value_type === 'json') {
|
||||||
try {
|
try {
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
} catch (_error) {
|
} catch {
|
||||||
this.logger.warn(`Failed to parse JSON for ${setting.setting_key}`);
|
this.logger.warn(`Failed to parse JSON for ${setting.setting_key}`);
|
||||||
value = {};
|
value = {};
|
||||||
}
|
}
|
||||||
@ -471,8 +471,8 @@ export class GamificationConfigService {
|
|||||||
* Parse default values from settings
|
* Parse default values from settings
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private parseDefaults(settings: SystemSetting[]): Record<string, any> {
|
private parseDefaults(settings: SystemSetting[]): Record<string, unknown> {
|
||||||
const defaults: Record<string, any> = {};
|
const defaults: Record<string, unknown> = {};
|
||||||
|
|
||||||
for (const setting of settings) {
|
for (const setting of settings) {
|
||||||
if (setting.default_value) {
|
if (setting.default_value) {
|
||||||
@ -484,7 +484,7 @@ export class GamificationConfigService {
|
|||||||
} else if (setting.value_type === 'json') {
|
} else if (setting.value_type === 'json') {
|
||||||
try {
|
try {
|
||||||
value = JSON.parse(value);
|
value = JSON.parse(value);
|
||||||
} catch (_error) {
|
} catch {
|
||||||
this.logger.warn(
|
this.logger.warn(
|
||||||
`Failed to parse default JSON for ${setting.setting_key}`,
|
`Failed to parse default JSON for ${setting.setting_key}`,
|
||||||
);
|
);
|
||||||
@ -542,7 +542,7 @@ export class GamificationConfigService {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async updateXpSettings(
|
private async updateXpSettings(
|
||||||
xp: Record<string, any>,
|
xp: Record<string, unknown>,
|
||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const [key, value] of Object.entries(xp)) {
|
for (const [key, value] of Object.entries(xp)) {
|
||||||
@ -556,7 +556,7 @@ export class GamificationConfigService {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async updateRankSettings(
|
private async updateRankSettings(
|
||||||
ranks: Record<string, any>,
|
ranks: Record<string, unknown>,
|
||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const settingKey = 'gamification.ranks.thresholds';
|
const settingKey = 'gamification.ranks.thresholds';
|
||||||
@ -568,7 +568,7 @@ export class GamificationConfigService {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async updateCoinsSettings(
|
private async updateCoinsSettings(
|
||||||
coins: Record<string, any>,
|
coins: Record<string, unknown>,
|
||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
for (const [key, value] of Object.entries(coins)) {
|
for (const [key, value] of Object.entries(coins)) {
|
||||||
@ -582,7 +582,7 @@ export class GamificationConfigService {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
private async updateAchievementSettings(
|
private async updateAchievementSettings(
|
||||||
achievements: Record<string, any>,
|
achievements: Record<string, unknown>,
|
||||||
adminId: string,
|
adminId: string,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const settingKey = 'gamification.achievements.criteria';
|
const settingKey = 'gamification.achievements.criteria';
|
||||||
@ -992,7 +992,7 @@ export class GamificationConfigService {
|
|||||||
if (parameter.value_type === 'json') {
|
if (parameter.value_type === 'json') {
|
||||||
try {
|
try {
|
||||||
JSON.parse(value);
|
JSON.parse(value);
|
||||||
} catch (_error) {
|
} catch {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
`Invalid JSON value for ${parameter.setting_key}`,
|
`Invalid JSON value for ${parameter.setting_key}`,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export class AssignmentsController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
||||||
async create(@Body() createDto: CreateAssignmentDto, @Request() req: any) {
|
async create(@Body() createDto: CreateAssignmentDto, @Request() req: AuthRequest) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.create(createDto, teacherId);
|
return this.assignmentsService.create(createDto, teacherId);
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ export class AssignmentsController {
|
|||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async findAll(@Query() query: any, @Request() req: any) {
|
async findAll(@Query() query: any, @Request() req: AuthRequest) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.findAll(teacherId, {
|
return this.assignmentsService.findAll(teacherId, {
|
||||||
isPublished: query.isPublished !== undefined ? query.isPublished === 'true' : undefined,
|
isPublished: query.isPublished !== undefined ? query.isPublished === 'true' : undefined,
|
||||||
@ -164,7 +164,7 @@ export class AssignmentsController {
|
|||||||
status: 404,
|
status: 404,
|
||||||
description: 'Asignación no encontrada o acceso denegado',
|
description: 'Asignación no encontrada o acceso denegado',
|
||||||
})
|
})
|
||||||
async findOne(@Param('id') id: string, @Request() req: any) {
|
async findOne(@Param('id') id: string, @Request() req: AuthRequest) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.findOne(id, teacherId);
|
return this.assignmentsService.findOne(id, teacherId);
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ export class AssignmentsController {
|
|||||||
async update(
|
async update(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() updateDto: UpdateAssignmentDto,
|
@Body() updateDto: UpdateAssignmentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.update(id, updateDto, teacherId);
|
return this.assignmentsService.update(id, updateDto, teacherId);
|
||||||
@ -228,7 +228,7 @@ export class AssignmentsController {
|
|||||||
status: 404,
|
status: 404,
|
||||||
description: 'Asignación no encontrada o acceso denegado',
|
description: 'Asignación no encontrada o acceso denegado',
|
||||||
})
|
})
|
||||||
async remove(@Param('id') id: string, @Request() req: any) {
|
async remove(@Param('id') id: string, @Request() req: AuthRequest) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
await this.assignmentsService.remove(id, teacherId);
|
await this.assignmentsService.remove(id, teacherId);
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ export class AssignmentsController {
|
|||||||
async assignToClassrooms(
|
async assignToClassrooms(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: AssignToClassroomsDto,
|
@Body() dto: AssignToClassroomsDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.assignToClassrooms(id, dto, teacherId);
|
return this.assignmentsService.assignToClassrooms(id, dto, teacherId);
|
||||||
@ -320,7 +320,7 @@ export class AssignmentsController {
|
|||||||
async getSubmissions(
|
async getSubmissions(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Query() query: any,
|
@Query() query: any,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.getSubmissions(id, teacherId, {
|
return this.assignmentsService.getSubmissions(id, teacherId, {
|
||||||
@ -373,7 +373,7 @@ export class AssignmentsController {
|
|||||||
async gradeSubmission(
|
async gradeSubmission(
|
||||||
@Param('submissionId') submissionId: string,
|
@Param('submissionId') submissionId: string,
|
||||||
@Body() dto: AssignmentGradeDto,
|
@Body() dto: AssignmentGradeDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.gradeSubmission(submissionId, dto, teacherId);
|
return this.assignmentsService.gradeSubmission(submissionId, dto, teacherId);
|
||||||
@ -407,7 +407,7 @@ export class AssignmentsController {
|
|||||||
async patch(
|
async patch(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() patchDto: PatchAssignmentDto,
|
@Body() patchDto: PatchAssignmentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.patchAssignment(id, patchDto, teacherId);
|
return this.assignmentsService.patchAssignment(id, patchDto, teacherId);
|
||||||
@ -441,7 +441,7 @@ export class AssignmentsController {
|
|||||||
async distribute(
|
async distribute(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() distributeDto: DistributeAssignmentDto,
|
@Body() distributeDto: DistributeAssignmentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.distributeAssignment(id, distributeDto, teacherId);
|
return this.assignmentsService.distributeAssignment(id, distributeDto, teacherId);
|
||||||
@ -472,7 +472,7 @@ export class AssignmentsController {
|
|||||||
async duplicate(
|
async duplicate(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() duplicateDto: DuplicateAssignmentDto,
|
@Body() duplicateDto: DuplicateAssignmentDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.duplicateAssignment(id, duplicateDto, teacherId);
|
return this.assignmentsService.duplicateAssignment(id, duplicateDto, teacherId);
|
||||||
@ -528,7 +528,7 @@ export class AssignmentsController {
|
|||||||
async publish(
|
async publish(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body('notifyStudents') notifyStudents: boolean = false,
|
@Body('notifyStudents') notifyStudents: boolean = false,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.publishAssignment(id, teacherId, notifyStudents);
|
return this.assignmentsService.publishAssignment(id, teacherId, notifyStudents);
|
||||||
@ -569,7 +569,7 @@ export class AssignmentsController {
|
|||||||
status: 404,
|
status: 404,
|
||||||
description: 'Assignment not found or access denied',
|
description: 'Assignment not found or access denied',
|
||||||
})
|
})
|
||||||
async close(@Param('id') id: string, @Request() req: any) {
|
async close(@Param('id') id: string, @Request() req: AuthRequest) {
|
||||||
const teacherId = req.user?.userId || req.user?.sub;
|
const teacherId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.closeAssignment(id, teacherId);
|
return this.assignmentsService.closeAssignment(id, teacherId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export class StudentAssignmentsController {
|
|||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async getMyAssignments(@Query() query: any, @Request() req: any) {
|
async getMyAssignments(@Query() query: any, @Request() req: AuthRequest) {
|
||||||
const studentId = req.user?.userId || req.user?.sub;
|
const studentId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.findStudentAssignments(studentId, {
|
return this.assignmentsService.findStudentAssignments(studentId, {
|
||||||
status: query.status,
|
status: query.status,
|
||||||
@ -104,7 +104,7 @@ export class StudentAssignmentsController {
|
|||||||
status: 404,
|
status: 404,
|
||||||
description: 'Tarea no encontrada o no asignada a este estudiante',
|
description: 'Tarea no encontrada o no asignada a este estudiante',
|
||||||
})
|
})
|
||||||
async getAssignmentDetails(@Param('id') id: string, @Request() req: any) {
|
async getAssignmentDetails(@Param('id') id: string, @Request() req: AuthRequest) {
|
||||||
const studentId = req.user?.userId || req.user?.sub;
|
const studentId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.findStudentAssignmentById(id, studentId);
|
return this.assignmentsService.findStudentAssignmentById(id, studentId);
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ export class StudentAssignmentsController {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async getGradesSummary(@Request() req: any) {
|
async getGradesSummary(@Request() req: AuthRequest) {
|
||||||
const studentId = req.user?.userId || req.user?.sub;
|
const studentId = req.user?.userId || req.user?.sub;
|
||||||
return this.assignmentsService.getStudentGradesSummary(studentId);
|
return this.assignmentsService.getStudentGradesSummary(studentId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -859,7 +859,7 @@ export class AssignmentsService {
|
|||||||
*/
|
*/
|
||||||
async findStudentAssignments(
|
async findStudentAssignments(
|
||||||
studentId: string,
|
studentId: string,
|
||||||
filters?: { status?: string; classroomId?: string },
|
_filters?: { status?: string; classroomId?: string },
|
||||||
): Promise<any[]> {
|
): Promise<any[]> {
|
||||||
// Get direct student assignments (without relation join - relations commented out)
|
// Get direct student assignments (without relation join - relations commented out)
|
||||||
const studentAssignments = await this.assignmentStudentRepository.find({
|
const studentAssignments = await this.assignmentStudentRepository.find({
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export class AuditInterceptor implements NestInterceptor {
|
|||||||
|
|
||||||
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
|
||||||
const request = context.switchToHttp().getRequest<Request>();
|
const request = context.switchToHttp().getRequest<Request>();
|
||||||
const { method, url, _body, _user} = request;
|
const { method, url, body: _body, user: _user} = request;
|
||||||
|
|
||||||
// Skip audit logging for certain endpoints
|
// Skip audit logging for certain endpoints
|
||||||
if (this.shouldSkipAudit(url)) {
|
if (this.shouldSkipAudit(url)) {
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class AuthService {
|
|||||||
* 4. Generate JWT tokens
|
* 4. Generate JWT tokens
|
||||||
* 5. Return sanitized user + tokens
|
* 5. Return sanitized user + tokens
|
||||||
*/
|
*/
|
||||||
async register(dto: any): Promise<AuthResponse> {
|
async register(_dto: any): Promise<AuthResponse> {
|
||||||
throw new Error('Register method not implemented - UsersService required');
|
throw new Error('Register method not implemented - UsersService required');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export class AuthService {
|
|||||||
* 4. Generate JWT tokens
|
* 4. Generate JWT tokens
|
||||||
* 5. Return sanitized user + tokens
|
* 5. Return sanitized user + tokens
|
||||||
*/
|
*/
|
||||||
async login(dto: LoginDto): Promise<AuthResponse> {
|
async login(_dto: LoginDto): Promise<AuthResponse> {
|
||||||
throw new Error('Login method not implemented - UsersService required');
|
throw new Error('Login method not implemented - UsersService required');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,14 +76,14 @@ export class AuthService {
|
|||||||
* 3. Validate user is active
|
* 3. Validate user is active
|
||||||
* 4. Generate new access + refresh tokens
|
* 4. Generate new access + refresh tokens
|
||||||
*/
|
*/
|
||||||
async refreshToken(dto: RefreshTokenDto): Promise<TokenResponse> {
|
async refreshToken(_dto: RefreshTokenDto): Promise<TokenResponse> {
|
||||||
throw new Error('RefreshToken method not implemented - UsersService required');
|
throw new Error('RefreshToken method not implemented - UsersService required');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logout - Invalida tokens (client-side)
|
* Logout - Invalida tokens (client-side)
|
||||||
*/
|
*/
|
||||||
async logout(userId: string): Promise<{ message: string }> {
|
async logout(_userId: string): Promise<{ message: string }> {
|
||||||
// TODO: Implementar blacklist de tokens en Redis (opcional)
|
// TODO: Implementar blacklist de tokens en Redis (opcional)
|
||||||
// Por ahora, el logout es client-side (eliminar tokens de localStorage)
|
// Por ahora, el logout es client-side (eliminar tokens de localStorage)
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ export class AuthService {
|
|||||||
* 2. Check if user exists and is active
|
* 2. Check if user exists and is active
|
||||||
* 3. Return sanitized user (without password)
|
* 3. Return sanitized user (without password)
|
||||||
*/
|
*/
|
||||||
async validateUser(userId: string) {
|
async validateUser(_userId: string) {
|
||||||
throw new Error('ValidateUser method not implemented - UsersService required');
|
throw new Error('ValidateUser method not implemented - UsersService required');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,7 +72,7 @@ export class AuthController {
|
|||||||
@ApiBody({ type: RegisterUserDto })
|
@ApiBody({ type: RegisterUserDto })
|
||||||
async register(
|
async register(
|
||||||
@Body() dto: RegisterUserDto,
|
@Body() dto: RegisterUserDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<{ user: UserResponseDto; accessToken: string; refreshToken: string }> {
|
): Promise<{ user: UserResponseDto; accessToken: string; refreshToken: string }> {
|
||||||
const ip = req.ip;
|
const ip = req.ip;
|
||||||
const userAgent = req.headers['user-agent'];
|
const userAgent = req.headers['user-agent'];
|
||||||
@ -104,7 +104,7 @@ export class AuthController {
|
|||||||
@ApiBody({ type: LoginDto })
|
@ApiBody({ type: LoginDto })
|
||||||
async login(
|
async login(
|
||||||
@Body() dto: LoginDto,
|
@Body() dto: LoginDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<{ user: UserResponseDto; accessToken: string; refreshToken: string }> {
|
): Promise<{ user: UserResponseDto; accessToken: string; refreshToken: string }> {
|
||||||
const ip = req.ip;
|
const ip = req.ip;
|
||||||
const userAgent = req.headers['user-agent'];
|
const userAgent = req.headers['user-agent'];
|
||||||
@ -129,7 +129,7 @@ export class AuthController {
|
|||||||
@ApiOperation({ summary: 'Cerrar sesión de usuario' })
|
@ApiOperation({ summary: 'Cerrar sesión de usuario' })
|
||||||
@ApiResponse({ status: 200, description: 'Sesión cerrada exitosamente' })
|
@ApiResponse({ status: 200, description: 'Sesión cerrada exitosamente' })
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async logout(@Request() req: any): Promise<{ message: string }> {
|
async logout(@Request() req: AuthRequest): Promise<{ message: string }> {
|
||||||
// Extraer userId y sessionId del token JWT
|
// Extraer userId y sessionId del token JWT
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const sessionId = req.user?.sessionId || 'current-session';
|
const sessionId = req.user?.sessionId || 'current-session';
|
||||||
@ -175,7 +175,7 @@ export class AuthController {
|
|||||||
type: UserResponseDto,
|
type: UserResponseDto,
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async getProfile(@Request() req: any): Promise<UserResponseDto> {
|
async getProfile(@Request() req: AuthRequest): Promise<UserResponseDto> {
|
||||||
// Extraer userId del token JWT
|
// Extraer userId del token JWT
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const user = await this.authService.validateUser(userId);
|
const user = await this.authService.validateUser(userId);
|
||||||
@ -185,7 +185,7 @@ export class AuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convertir a UserResponseDto (sin password)
|
// Convertir a UserResponseDto (sin password)
|
||||||
const { _encrypted_password, ...userResponse } = user;
|
const { encrypted_password: _encrypted_password, ...userResponse } = user;
|
||||||
return userResponse as UserResponseDto;
|
return userResponse as UserResponseDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ export class AuthController {
|
|||||||
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
||||||
@ApiBody({ type: UpdateProfileDto })
|
@ApiBody({ type: UpdateProfileDto })
|
||||||
async updateProfile(
|
async updateProfile(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Body() dto: UpdateProfileDto,
|
@Body() dto: UpdateProfileDto,
|
||||||
): Promise<UserResponseDto> {
|
): Promise<UserResponseDto> {
|
||||||
// Extraer userId del token JWT
|
// Extraer userId del token JWT
|
||||||
@ -220,7 +220,7 @@ export class AuthController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convertir a UserResponseDto (sin password)
|
// Convertir a UserResponseDto (sin password)
|
||||||
const { _encrypted_password, ...userResponse } = updatedUser;
|
const { encrypted_password: _encrypted_password, ...userResponse } = updatedUser;
|
||||||
return userResponse as UserResponseDto;
|
return userResponse as UserResponseDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,7 +247,7 @@ export class AuthController {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async verifyEmail(@Body('token') token: string): Promise<{ message: string }> {
|
async verifyEmail(@Body('token') _token: string): Promise<{ message: string }> {
|
||||||
// TODO: Implementar lógica de verificación de email
|
// TODO: Implementar lógica de verificación de email
|
||||||
// Por ahora retornamos éxito
|
// Por ahora retornamos éxito
|
||||||
return { message: 'Email verificado exitosamente' };
|
return { message: 'Email verificado exitosamente' };
|
||||||
@ -275,7 +275,7 @@ export class AuthController {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async forgotPassword(@Body('email') email: string): Promise<{ message: string }> {
|
async forgotPassword(@Body('email') _email: string): Promise<{ message: string }> {
|
||||||
// TODO: Implementar lógica de forgot password
|
// TODO: Implementar lógica de forgot password
|
||||||
return { message: 'Si el email existe, recibirás instrucciones para resetear tu contraseña' };
|
return { message: 'Si el email existe, recibirás instrucciones para resetear tu contraseña' };
|
||||||
}
|
}
|
||||||
@ -305,8 +305,8 @@ export class AuthController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
async resetPassword(
|
async resetPassword(
|
||||||
@Body('token') token: string,
|
@Body('token') _token: string,
|
||||||
@Body('newPassword') newPassword: string,
|
@Body('newPassword') _newPassword: string,
|
||||||
): Promise<{ message: string }> {
|
): Promise<{ message: string }> {
|
||||||
// TODO: Implementar lógica de reset password
|
// TODO: Implementar lógica de reset password
|
||||||
return { message: 'Contraseña reseteada exitosamente' };
|
return { message: 'Contraseña reseteada exitosamente' };
|
||||||
@ -340,9 +340,9 @@ export class AuthController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
async changePassword(
|
async changePassword(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Body('currentPassword') currentPassword: string,
|
@Body('currentPassword') _currentPassword: string,
|
||||||
@Body('newPassword') newPassword: string,
|
@Body('newPassword') _newPassword: string,
|
||||||
): Promise<{ message: string }> {
|
): Promise<{ message: string }> {
|
||||||
const _userId = req.user?.id;
|
const _userId = req.user?.id;
|
||||||
// TODO: Implementar lógica de cambio de contraseña
|
// TODO: Implementar lógica de cambio de contraseña
|
||||||
@ -363,7 +363,7 @@ export class AuthController {
|
|||||||
isArray: true,
|
isArray: true,
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async getSessions(@Request() req: any): Promise<UserSessionResponseDto[]> {
|
async getSessions(@Request() req: AuthRequest): Promise<UserSessionResponseDto[]> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
return this.sessionService.getSessions(userId);
|
return this.sessionService.getSessions(userId);
|
||||||
}
|
}
|
||||||
@ -391,7 +391,7 @@ export class AuthController {
|
|||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
@ApiResponse({ status: 404, description: 'Sesión no encontrada o no pertenece al usuario' })
|
@ApiResponse({ status: 404, description: 'Sesión no encontrada o no pertenece al usuario' })
|
||||||
async revokeSession(
|
async revokeSession(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Param('sessionId') sessionId: string,
|
@Param('sessionId') sessionId: string,
|
||||||
): Promise<{ message: string }> {
|
): Promise<{ message: string }> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
@ -420,7 +420,7 @@ export class AuthController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async revokeAllSessions(@Request() req: any): Promise<{ message: string; count: number }> {
|
async revokeAllSessions(@Request() req: AuthRequest): Promise<{ message: string; count: number }> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const currentSessionId = req.user?.sessionId || 'unknown';
|
const currentSessionId = req.user?.sessionId || 'unknown';
|
||||||
return this.sessionService.revokeAllSessions(userId, currentSessionId);
|
return this.sessionService.revokeAllSessions(userId, currentSessionId);
|
||||||
|
|||||||
@ -140,7 +140,7 @@ export class PasswordController {
|
|||||||
@ApiResponse({ status: 404, description: 'Usuario no encontrado' })
|
@ApiResponse({ status: 404, description: 'Usuario no encontrado' })
|
||||||
@ApiBody({ type: ChangePasswordDto })
|
@ApiBody({ type: ChangePasswordDto })
|
||||||
async changePassword(
|
async changePassword(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Body() dto: ChangePasswordDto,
|
@Body() dto: ChangePasswordDto,
|
||||||
): Promise<{ message: string }> {
|
): Promise<{ message: string }> {
|
||||||
// Extraer userId del token JWT
|
// Extraer userId del token JWT
|
||||||
@ -201,7 +201,7 @@ export class PasswordController {
|
|||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
@ApiResponse({ status: 409, description: 'Email ya verificado' })
|
@ApiResponse({ status: 409, description: 'Email ya verificado' })
|
||||||
async resendVerification(@Request() req: any): Promise<{ message: string }> {
|
async resendVerification(@Request() req: AuthRequest): Promise<{ message: string }> {
|
||||||
// Extraer userId del token JWT
|
// Extraer userId del token JWT
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
return this.emailVerificationService.resendVerification(userId);
|
return this.emailVerificationService.resendVerification(userId);
|
||||||
@ -226,7 +226,7 @@ export class PasswordController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async checkVerificationStatus(@Request() req: any): Promise<{ verified: boolean }> {
|
async checkVerificationStatus(@Request() req: AuthRequest): Promise<{ verified: boolean }> {
|
||||||
// Extraer userId del token JWT
|
// Extraer userId del token JWT
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
return this.emailVerificationService.checkVerificationStatus(userId);
|
return this.emailVerificationService.checkVerificationStatus(userId);
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export class UsersController {
|
|||||||
type: UserResponseDto,
|
type: UserResponseDto,
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async getProfile(@Request() req: any): Promise<UserResponseDto> {
|
async getProfile(@Request() req: AuthRequest): Promise<UserResponseDto> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const user = await this.authService.validateUser(userId);
|
const user = await this.authService.validateUser(userId);
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ export class UsersController {
|
|||||||
throw new UnauthorizedException('Usuario no encontrado');
|
throw new UnauthorizedException('Usuario no encontrado');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { _encrypted_password, ...userResponse } = user;
|
const { encrypted_password: _encrypted_password, ...userResponse } = user;
|
||||||
return userResponse as UserResponseDto;
|
return userResponse as UserResponseDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ export class UsersController {
|
|||||||
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
@ApiResponse({ status: 400, description: 'Datos inválidos' })
|
||||||
@ApiBody({ type: UpdateProfileDto })
|
@ApiBody({ type: UpdateProfileDto })
|
||||||
async updateProfile(
|
async updateProfile(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Body() dto: UpdateProfileDto,
|
@Body() dto: UpdateProfileDto,
|
||||||
): Promise<UserResponseDto> {
|
): Promise<UserResponseDto> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
@ -98,7 +98,7 @@ export class UsersController {
|
|||||||
throw new UnauthorizedException('Usuario no encontrado');
|
throw new UnauthorizedException('Usuario no encontrado');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { _encrypted_password, ...userResponse } = updatedUser;
|
const { encrypted_password: _encrypted_password, ...userResponse } = updatedUser;
|
||||||
return userResponse as UserResponseDto;
|
return userResponse as UserResponseDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ export class UsersController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async getPreferences(@Request() req: any): Promise<{ preferences: any }> {
|
async getPreferences(@Request() req: AuthRequest): Promise<{ preferences: any }> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const preferences = await this.authService.getUserPreferences(userId);
|
const preferences = await this.authService.getUserPreferences(userId);
|
||||||
return { preferences };
|
return { preferences };
|
||||||
@ -151,7 +151,7 @@ export class UsersController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
async updatePreferences(
|
async updatePreferences(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@Body('preferences') preferences: any,
|
@Body('preferences') preferences: any,
|
||||||
): Promise<{ preferences: any }> {
|
): Promise<{ preferences: any }> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
@ -194,7 +194,7 @@ export class UsersController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
async uploadAvatar(
|
async uploadAvatar(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@UploadedFile() file: any,
|
@UploadedFile() file: any,
|
||||||
): Promise<{ avatar_url: string }> {
|
): Promise<{ avatar_url: string }> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
@ -230,7 +230,7 @@ export class UsersController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ApiResponse({ status: 401, description: 'No autenticado' })
|
@ApiResponse({ status: 401, description: 'No autenticado' })
|
||||||
async getStatistics(@Request() req: any): Promise<any> {
|
async getStatistics(@Request() req: AuthRequest): Promise<any> {
|
||||||
const userId = req.user?.id;
|
const userId = req.user?.id;
|
||||||
const statistics = await this.authService.getUserStatistics(userId);
|
const statistics = await this.authService.getUserStatistics(userId);
|
||||||
return statistics;
|
return statistics;
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export class AssignRoleDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'permissions debe ser un objeto JSON válido' })
|
@IsObject({ message: 'permissions debe ser un objeto JSON válido' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
permissions?: Record<string, any>;
|
permissions?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de expiración del rol (opcional)
|
* Fecha y hora de expiración del rol (opcional)
|
||||||
@ -81,5 +81,5 @@ export class AssignRoleDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'metadata debe ser un objeto JSON válido' })
|
@IsObject({ message: 'metadata debe ser un objeto JSON válido' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -205,7 +205,7 @@ export class CreateProfileDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario en auth.users
|
* ID del usuario en auth.users
|
||||||
|
|||||||
@ -126,7 +126,7 @@ export class CreateTenantDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'Las configuraciones deben ser un objeto JSON válido' })
|
@IsObject({ message: 'Las configuraciones deben ser un objeto JSON válido' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
settings?: Record<string, any>;
|
settings?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata adicional del tenant (JSONB)
|
* Metadata adicional del tenant (JSONB)
|
||||||
@ -135,5 +135,5 @@ export class CreateTenantDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'La metadata debe ser un objeto JSON válido' })
|
@IsObject({ message: 'La metadata debe ser un objeto JSON válido' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,5 +141,5 @@ export class CreateUserPreferencesDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
preferences?: Record<string, any>;
|
preferences?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,5 +55,5 @@ export class CreateUserDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'Los metadatos deben ser un objeto JSON' })
|
@IsObject({ message: 'Los metadatos deben ser un objeto JSON' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
raw_user_meta_data?: Record<string, any>;
|
raw_user_meta_data?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ export class ProfileResponseDto {
|
|||||||
last_activity_at!: Date | null;
|
last_activity_at!: Date | null;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
created_at!: Date;
|
created_at!: Date;
|
||||||
|
|||||||
@ -39,7 +39,7 @@ export class RegisterUserDto {
|
|||||||
*/
|
*/
|
||||||
@IsObject({ message: 'Los metadatos deben ser un objeto JSON' })
|
@IsObject({ message: 'Los metadatos deben ser un objeto JSON' })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
raw_user_meta_data?: Record<string, any>;
|
raw_user_meta_data?: Record<string, unknown>;
|
||||||
|
|
||||||
// Campos opcionales adicionales para registro:
|
// Campos opcionales adicionales para registro:
|
||||||
// Nota: Estos campos se podrían mapear al Profile (auth_management.profiles)
|
// Nota: Estos campos se podrían mapear al Profile (auth_management.profiles)
|
||||||
|
|||||||
@ -75,13 +75,13 @@ export class TenantResponseDto {
|
|||||||
* Configuraciones del tenant (JSONB)
|
* Configuraciones del tenant (JSONB)
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
settings!: Record<string, any>;
|
settings!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata adicional del tenant (JSONB)
|
* Metadata adicional del tenant (JSONB)
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación del tenant
|
* Fecha de creación del tenant
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export class UpdateUserDto extends PartialType(
|
|||||||
) {
|
) {
|
||||||
// Hereda de CreateUserDto excepto password y email:
|
// Hereda de CreateUserDto excepto password y email:
|
||||||
// - role?: GamilityRoleEnum
|
// - role?: GamilityRoleEnum
|
||||||
// - raw_user_meta_data?: Record<string, any>
|
// - raw_user_meta_data?: Record<string, unknown>
|
||||||
|
|
||||||
// Campos opcionales adicionales para actualización:
|
// Campos opcionales adicionales para actualización:
|
||||||
// (actualmente solo role y raw_user_meta_data son editables)
|
// (actualmente solo role y raw_user_meta_data son editables)
|
||||||
|
|||||||
@ -99,7 +99,7 @@ export class UserPreferencesResponseDto {
|
|||||||
dashboard_layout: 'grid',
|
dashboard_layout: 'grid',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
preferences!: Record<string, any>;
|
preferences!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación
|
* Fecha de creación
|
||||||
|
|||||||
@ -99,7 +99,7 @@ export class UserResponseDto {
|
|||||||
* NOTA: Filtrar campos sensibles si existen
|
* NOTA: Filtrar campos sensibles si existen
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
raw_user_meta_data!: Record<string, any>;
|
raw_user_meta_data!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de creación del registro
|
* Fecha y hora de creación del registro
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export class UserRoleResponseDto {
|
|||||||
* Permisos específicos asociados a este rol
|
* Permisos específicos asociados a este rol
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
permissions!: Record<string, any>;
|
permissions!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario (Profile) que asignó este rol (nullable)
|
* ID del usuario (Profile) que asignó este rol (nullable)
|
||||||
@ -80,7 +80,7 @@ export class UserRoleResponseDto {
|
|||||||
* Metadata adicional del user_role
|
* Metadata adicional del user_role
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación del registro
|
* Fecha de creación del registro
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export class AuthAttempt {
|
|||||||
attempted_at!: Date;
|
attempted_at!: Date;
|
||||||
|
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// NOTA: La tabla auth_attempts NO tiene user_id
|
// NOTA: La tabla auth_attempts NO tiene user_id
|
||||||
// Es una tabla de auditoría independiente que solo registra el email
|
// Es una tabla de auditoría independiente que solo registra el email
|
||||||
|
|||||||
@ -125,7 +125,7 @@ export class Profile {
|
|||||||
last_activity_at!: Date | null;
|
last_activity_at!: Date | null;
|
||||||
|
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
@CreateDateColumn({ type: 'timestamp with time zone' })
|
@CreateDateColumn({ type: 'timestamp with time zone' })
|
||||||
created_at!: Date;
|
created_at!: Date;
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export class SecurityEvent {
|
|||||||
* @example { "failed_attempts": 3, "reason": "invalid_password" }
|
* @example { "failed_attempts": 3, "reason": "invalid_password" }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de creación del evento
|
* Fecha y hora de creación del evento
|
||||||
|
|||||||
@ -113,14 +113,14 @@ export class Tenant {
|
|||||||
timezone: 'America/Mexico_City',
|
timezone: 'America/Mexico_City',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
settings!: Record<string, any>;
|
settings!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata adicional del tenant (JSONB)
|
* Metadata adicional del tenant (JSONB)
|
||||||
* @example { billing_contact: "admin@example.com", notes: "..." }
|
* @example { billing_contact: "admin@example.com", notes: "..." }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: false, default: {} })
|
@Column({ type: 'jsonb', nullable: false, default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación del tenant
|
* Fecha de creación del tenant
|
||||||
|
|||||||
@ -117,7 +117,7 @@ export class UserPreferences {
|
|||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
@Index('idx_user_preferences_preferences', { synchronize: false }) // GIN index creado en DDL
|
@Index('idx_user_preferences_preferences', { synchronize: false }) // GIN index creado en DDL
|
||||||
preferences!: Record<string, any>;
|
preferences!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación
|
* Fecha de creación
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export class UserRole {
|
|||||||
nullable: false,
|
nullable: false,
|
||||||
default: { read: true, write: false, admin: false, analytics: false },
|
default: { read: true, write: false, admin: false, analytics: false },
|
||||||
})
|
})
|
||||||
permissions!: Record<string, any>;
|
permissions!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario (Profile) que asignó este rol (nullable)
|
* ID del usuario (Profile) que asignó este rol (nullable)
|
||||||
@ -143,7 +143,7 @@ export class UserRole {
|
|||||||
* @example { notes: "Rol temporal para proyecto X", reason: "..." }
|
* @example { notes: "Rol temporal para proyecto X", reason: "..." }
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: false, default: {} })
|
@Column({ type: 'jsonb', nullable: false, default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación del registro
|
* Fecha de creación del registro
|
||||||
|
|||||||
@ -77,7 +77,7 @@ export class UserSession {
|
|||||||
revoked_at!: Date | null;
|
revoked_at!: Date | null;
|
||||||
|
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// Relaciones
|
// Relaciones
|
||||||
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
@ManyToOne(() => User, { onDelete: 'CASCADE' })
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export class User {
|
|||||||
* Metadatos adicionales del usuario en formato JSON
|
* Metadatos adicionales del usuario en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
raw_user_meta_data!: Record<string, any>;
|
raw_user_meta_data!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de eliminación lógica (soft delete)
|
* Fecha y hora de eliminación lógica (soft delete)
|
||||||
|
|||||||
@ -658,7 +658,7 @@ export class AuthService {
|
|||||||
* @returns UserResponseDto con campos derivados calculados
|
* @returns UserResponseDto con campos derivados calculados
|
||||||
*/
|
*/
|
||||||
public toUserResponse(user: User): UserResponseDto {
|
public toUserResponse(user: User): UserResponseDto {
|
||||||
const { _encrypted_password, ...userWithoutPassword } = user;
|
const { encrypted_password: _encrypted_password, ...userWithoutPassword } = user;
|
||||||
|
|
||||||
// Calcular campos derivados para coherencia Frontend-Backend
|
// Calcular campos derivados para coherencia Frontend-Backend
|
||||||
const emailVerified = !!user.email_confirmed_at;
|
const emailVerified = !!user.email_confirmed_at;
|
||||||
|
|||||||
@ -42,9 +42,9 @@ export class ContentTemplatesController {
|
|||||||
@ApiResponse({ status: 200, description: 'Lista de plantillas obtenida exitosamente', type: [ContentTemplateResponseDto] })
|
@ApiResponse({ status: 200, description: 'Lista de plantillas obtenida exitosamente', type: [ContentTemplateResponseDto] })
|
||||||
async findAll(
|
async findAll(
|
||||||
@Query('type') type?: string,
|
@Query('type') type?: string,
|
||||||
@Query('category') category?: string,
|
@Query('category') _category?: string,
|
||||||
) {
|
) {
|
||||||
return this.templatesService.findAll(type, category);
|
return this.templatesService.findAll(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -38,11 +38,11 @@ export class ContentTemplateResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Estructura JSON de la plantilla' })
|
@ApiProperty({ description: 'Estructura JSON de la plantilla' })
|
||||||
@Expose()
|
@Expose()
|
||||||
template_structure!: Record<string, any>;
|
template_structure!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Valores predeterminados' })
|
@ApiPropertyOptional({ description: 'Valores predeterminados' })
|
||||||
@Expose()
|
@Expose()
|
||||||
default_values?: Record<string, any>;
|
default_values?: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'Campos requeridos' })
|
@ApiPropertyOptional({ description: 'Campos requeridos' })
|
||||||
@Expose()
|
@Expose()
|
||||||
@ -82,7 +82,7 @@ export class ContentTemplateResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Metadatos adicionales' })
|
@ApiProperty({ description: 'Metadatos adicionales' })
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiPropertyOptional({ description: 'ID del usuario creador' })
|
@ApiPropertyOptional({ description: 'ID del usuario creador' })
|
||||||
@Expose()
|
@Expose()
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export class CreateContentTemplateDto {
|
|||||||
*/
|
*/
|
||||||
@ApiProperty({ description: 'Estructura JSON de la plantilla', example: { sections: [], fields: [] } })
|
@ApiProperty({ description: 'Estructura JSON de la plantilla', example: { sections: [], fields: [] } })
|
||||||
@IsObject()
|
@IsObject()
|
||||||
template_structure!: Record<string, any>;
|
template_structure!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valores predeterminados JSON
|
* Valores predeterminados JSON
|
||||||
@ -70,7 +70,7 @@ export class CreateContentTemplateDto {
|
|||||||
@ApiPropertyOptional({ description: 'Valores predeterminados', example: { difficulty: 'medium', duration: 30 } })
|
@ApiPropertyOptional({ description: 'Valores predeterminados', example: { difficulty: 'medium', duration: 30 } })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
default_values?: Record<string, any>;
|
default_values?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Campos requeridos
|
* Campos requeridos
|
||||||
@ -141,7 +141,7 @@ export class CreateContentTemplateDto {
|
|||||||
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del creador
|
* ID del creador
|
||||||
|
|||||||
@ -72,7 +72,7 @@ export class CreateMarieCurieContentDto {
|
|||||||
*/
|
*/
|
||||||
@ApiProperty({ description: 'Contenido estructurado JSON', example: { introduction: 'Texto introductorio...', main_content: 'Contenido principal...', key_points: [], timeline: [], quotes: [] } })
|
@ApiProperty({ description: 'Contenido estructurado JSON', example: { introduction: 'Texto introductorio...', main_content: 'Contenido principal...', key_points: [], timeline: [], quotes: [] } })
|
||||||
@IsObject()
|
@IsObject()
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// EDUCATIONAL METADATA
|
// EDUCATIONAL METADATA
|
||||||
@ -196,7 +196,7 @@ export class CreateMarieCurieContentDto {
|
|||||||
@ApiPropertyOptional({ description: 'Contexto cultural JSON', example: {} })
|
@ApiPropertyOptional({ description: 'Contexto cultural JSON', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
cultural_context?: Record<string, any>;
|
cultural_context?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// PUBLICATION STATUS
|
// PUBLICATION STATUS
|
||||||
@ -286,5 +286,5 @@ export class CreateMarieCurieContentDto {
|
|||||||
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -260,7 +260,7 @@ export class CreateMediaFileDto {
|
|||||||
@ApiPropertyOptional({ description: 'Información de procesamiento JSON', example: {} })
|
@ApiPropertyOptional({ description: 'Información de procesamiento JSON', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
processing_info?: Record<string, any>;
|
processing_info?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// SEARCH & ORGANIZATION
|
// SEARCH & ORGANIZATION
|
||||||
@ -381,7 +381,7 @@ export class CreateMediaFileDto {
|
|||||||
@ApiPropertyOptional({ description: 'Datos EXIF JSON', example: {} })
|
@ApiPropertyOptional({ description: 'Datos EXIF JSON', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
exif_data?: Record<string, any>;
|
exif_data?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadatos adicionales
|
* Metadatos adicionales
|
||||||
@ -389,5 +389,5 @@ export class CreateMediaFileDto {
|
|||||||
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
@ApiPropertyOptional({ description: 'Metadatos adicionales', example: {} })
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export class MarieCurieContentResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Contenido estructurado JSON' })
|
@ApiProperty({ description: 'Contenido estructurado JSON' })
|
||||||
@Expose()
|
@Expose()
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// EDUCATIONAL METADATA
|
// EDUCATIONAL METADATA
|
||||||
@ -109,7 +109,7 @@ export class MarieCurieContentResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Contexto cultural JSON' })
|
@ApiProperty({ description: 'Contexto cultural JSON' })
|
||||||
@Expose()
|
@Expose()
|
||||||
cultural_context!: Record<string, any>;
|
cultural_context!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// PUBLICATION STATUS
|
// PUBLICATION STATUS
|
||||||
@ -161,7 +161,7 @@ export class MarieCurieContentResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Metadatos adicionales' })
|
@ApiProperty({ description: 'Metadatos adicionales' })
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Fecha de creación' })
|
@ApiProperty({ description: 'Fecha de creación' })
|
||||||
@Expose()
|
@Expose()
|
||||||
|
|||||||
@ -145,7 +145,7 @@ export class MediaFileResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Información de procesamiento' })
|
@ApiProperty({ description: 'Información de procesamiento' })
|
||||||
@Expose()
|
@Expose()
|
||||||
processing_info!: Record<string, any>;
|
processing_info!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// SEARCH & ORGANIZATION
|
// SEARCH & ORGANIZATION
|
||||||
@ -213,11 +213,11 @@ export class MediaFileResponseDto {
|
|||||||
|
|
||||||
@ApiProperty({ description: 'Datos EXIF' })
|
@ApiProperty({ description: 'Datos EXIF' })
|
||||||
@Expose()
|
@Expose()
|
||||||
exif_data!: Record<string, any>;
|
exif_data!: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'Metadatos adicionales' })
|
@ApiProperty({ description: 'Metadatos adicionales' })
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT TIMESTAMPS
|
// AUDIT TIMESTAMPS
|
||||||
|
|||||||
@ -75,14 +75,14 @@ export class ContentTemplate {
|
|||||||
* Define cómo se estructura el contenido
|
* Define cómo se estructura el contenido
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
template_structure!: Record<string, any>;
|
template_structure!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valores predeterminados JSON
|
* Valores predeterminados JSON
|
||||||
* Valores iniciales al crear contenido desde esta plantilla
|
* Valores iniciales al crear contenido desde esta plantilla
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
default_values?: Record<string, any>;
|
default_values?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Campos requeridos en el contenido
|
* Campos requeridos en el contenido
|
||||||
@ -146,7 +146,7 @@ export class ContentTemplate {
|
|||||||
* Metadatos adicionales en formato JSON
|
* Metadatos adicionales en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de creación del registro
|
* Fecha y hora de creación del registro
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export class MarieCurieContent {
|
|||||||
main_content: '',
|
main_content: '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// EDUCATIONAL METADATA
|
// EDUCATIONAL METADATA
|
||||||
@ -190,7 +190,7 @@ export class MarieCurieContent {
|
|||||||
* Contexto cultural en formato JSON
|
* Contexto cultural en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
cultural_context!: Record<string, any>;
|
cultural_context!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// PUBLICATION STATUS
|
// PUBLICATION STATUS
|
||||||
@ -265,7 +265,7 @@ export class MarieCurieContent {
|
|||||||
* Metadatos adicionales en formato JSON
|
* Metadatos adicionales en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de creación del registro
|
* Fecha y hora de creación del registro
|
||||||
|
|||||||
@ -234,7 +234,7 @@ export class MediaFile {
|
|||||||
* Información de procesamiento en formato JSON
|
* Información de procesamiento en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
processing_info!: Record<string, any>;
|
processing_info!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// SEARCH & ORGANIZATION
|
// SEARCH & ORGANIZATION
|
||||||
@ -326,13 +326,13 @@ export class MediaFile {
|
|||||||
* Datos EXIF del archivo (imágenes)
|
* Datos EXIF del archivo (imágenes)
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
exif_data!: Record<string, any>;
|
exif_data!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadatos adicionales en formato JSON
|
* Metadatos adicionales en formato JSON
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT TIMESTAMPS
|
// AUDIT TIMESTAMPS
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export class ContentTemplatesService {
|
|||||||
* @param category - Categoría (opcional, no usado en DDL pero útil para filtros futuros)
|
* @param category - Categoría (opcional, no usado en DDL pero útil para filtros futuros)
|
||||||
* @returns Lista de plantillas
|
* @returns Lista de plantillas
|
||||||
*/
|
*/
|
||||||
async findAll(type?: string?: string): Promise<ContentTemplate[]> {
|
async findAll(type?: string): Promise<ContentTemplate[]> {
|
||||||
const query = this.templateRepo.createQueryBuilder('t');
|
const query = this.templateRepo.createQueryBuilder('t');
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
@ -140,7 +140,7 @@ export class ContentTemplatesService {
|
|||||||
* @param category - Categoría de plantilla
|
* @param category - Categoría de plantilla
|
||||||
* @returns Lista de plantillas de la categoría
|
* @returns Lista de plantillas de la categoría
|
||||||
*/
|
*/
|
||||||
async findByCategory(category: string): Promise<ContentTemplate[]> {
|
async findByCategory(_category: string): Promise<ContentTemplate[]> {
|
||||||
// Actualmente retorna todas ya que no existe el campo category en DDL
|
// Actualmente retorna todas ya que no existe el campo category en DDL
|
||||||
// Se puede extender con metadata o agregando el campo en una migración futura
|
// Se puede extender con metadata o agregando el campo en una migración futura
|
||||||
return this.templateRepo.find({
|
return this.templateRepo.find({
|
||||||
|
|||||||
@ -90,7 +90,7 @@ export class ExercisesController {
|
|||||||
*/
|
*/
|
||||||
private normalizeSubmitData(dto: SubmitExerciseDto, req: any): {
|
private normalizeSubmitData(dto: SubmitExerciseDto, req: any): {
|
||||||
userId: string;
|
userId: string;
|
||||||
answers: Record<string, any>;
|
answers: Record<string, unknown>;
|
||||||
timeSpentSeconds?: number;
|
timeSpentSeconds?: number;
|
||||||
hintsUsed: number;
|
hintsUsed: number;
|
||||||
powerupsUsed: string[];
|
powerupsUsed: string[];
|
||||||
@ -105,7 +105,7 @@ export class ExercisesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Extraer respuestas (nuevo formato tiene prioridad)
|
// 2. Extraer respuestas (nuevo formato tiene prioridad)
|
||||||
let answers: Record<string, any>;
|
let answers: Record<string, unknown>;
|
||||||
|
|
||||||
if (dto.answers) {
|
if (dto.answers) {
|
||||||
// Formato nuevo (estándar)
|
// Formato nuevo (estándar)
|
||||||
@ -220,7 +220,7 @@ export class ExercisesController {
|
|||||||
status: 500,
|
status: 500,
|
||||||
description: 'Error interno del servidor',
|
description: 'Error interno del servidor',
|
||||||
})
|
})
|
||||||
async findAll(@Request() req: any) {
|
async findAll(@Request() req: AuthRequest) {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
const userRole = req.user.role;
|
const userRole = req.user.role;
|
||||||
|
|
||||||
@ -372,7 +372,7 @@ export class ExercisesController {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
async findOne(@Param('id') id: string, @Request() req: any) {
|
async findOne(@Param('id') id: string, @Request() req: AuthRequest) {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
|
|
||||||
// Obtener ejercicio
|
// Obtener ejercicio
|
||||||
@ -671,7 +671,7 @@ export class ExercisesController {
|
|||||||
status: 404,
|
status: 404,
|
||||||
description: 'Módulo no encontrado',
|
description: 'Módulo no encontrado',
|
||||||
})
|
})
|
||||||
async findByModule(@Param('moduleId') moduleId: string, @Request() req: any) {
|
async findByModule(@Param('moduleId') moduleId: string, @Request() req: AuthRequest) {
|
||||||
// Obtener ejercicios del módulo
|
// Obtener ejercicios del módulo
|
||||||
const exercises = await this.exercisesService.findByModuleId(moduleId);
|
const exercises = await this.exercisesService.findByModuleId(moduleId);
|
||||||
|
|
||||||
@ -818,7 +818,7 @@ export class ExercisesController {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
async validateContentByExerciseType(
|
async validateContentByExerciseType(
|
||||||
@Body() body: { exercise_type: ExerciseTypeEnum; content: Record<string, any> },
|
@Body() body: { exercise_type: ExerciseTypeEnum; content: Record<string, unknown> },
|
||||||
) {
|
) {
|
||||||
this.exercisesService.validateContentByExerciseType(body.exercise_type, body.content);
|
this.exercisesService.validateContentByExerciseType(body.exercise_type, body.content);
|
||||||
return {
|
return {
|
||||||
@ -943,7 +943,7 @@ export class ExercisesController {
|
|||||||
async submitExercise(
|
async submitExercise(
|
||||||
@Param('id') exerciseId: string,
|
@Param('id') exerciseId: string,
|
||||||
@Body() dto: SubmitExerciseDto,
|
@Body() dto: SubmitExerciseDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
): Promise<SubmitExerciseResponseDto> {
|
): Promise<SubmitExerciseResponseDto> {
|
||||||
// ========================================
|
// ========================================
|
||||||
// 1. NORMALIZACIÓN
|
// 1. NORMALIZACIÓN
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export class MediaUploadController {
|
|||||||
})
|
})
|
||||||
@ApiResponse({ status: 400, description: 'Archivo inválido o excede límite de tamaño' })
|
@ApiResponse({ status: 400, description: 'Archivo inválido o excede límite de tamaño' })
|
||||||
async uploadFile(
|
async uploadFile(
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
@UploadedFile() file: any,
|
@UploadedFile() file: any,
|
||||||
@Body() dto: UploadMediaDto,
|
@Body() dto: UploadMediaDto,
|
||||||
): Promise<MediaAttachment> {
|
): Promise<MediaAttachment> {
|
||||||
|
|||||||
@ -349,7 +349,7 @@ export class MediaController {
|
|||||||
})
|
})
|
||||||
async updateProcessingStatus(
|
async updateProcessingStatus(
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() body: { status: ProcessingStatusEnum; metadata?: Record<string, any> },
|
@Body() body: { status: ProcessingStatusEnum; metadata?: Record<string, unknown> },
|
||||||
) {
|
) {
|
||||||
return this.mediaService.updateProcessingStatus(id, body.status, body.metadata);
|
return this.mediaService.updateProcessingStatus(id, body.status, body.metadata);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,7 +110,7 @@ export class ModulesController {
|
|||||||
status: 500,
|
status: 500,
|
||||||
description: 'Error interno del servidor',
|
description: 'Error interno del servidor',
|
||||||
})
|
})
|
||||||
async findAll(@Request() req: any, @Query() query: GetModulesQueryDto) {
|
async findAll(@Request() req: AuthRequest, @Query() query: GetModulesQueryDto) {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
// Reutilizar getUserModules que ya tiene la lógica correcta para ambas tablas
|
// Reutilizar getUserModules que ya tiene la lógica correcta para ambas tablas
|
||||||
// Ahora acepta classroomId opcional para filtrar
|
// Ahora acepta classroomId opcional para filtrar
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export class CreateExerciseDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
config?: Record<string, any>;
|
config?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contenido del ejercicio (JSONB) (REQUERIDO)
|
* Contenido del ejercicio (JSONB) (REQUERIDO)
|
||||||
@ -92,21 +92,21 @@ export class CreateExerciseDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
content?: Record<string, any>;
|
content?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Solución del ejercicio (JSONB)
|
* Solución del ejercicio (JSONB)
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
solution?: Record<string, any>;
|
solution?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rúbrica de evaluación (JSONB)
|
* Rúbrica de evaluación (JSONB)
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
rubric?: Record<string, any>;
|
rubric?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GRADING & SCORING
|
// GRADING & SCORING
|
||||||
@ -233,7 +233,7 @@ export class CreateExerciseDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
comodines_config?: Record<string, any>;
|
comodines_config?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GAMIFICATION & REWARDS
|
// GAMIFICATION & REWARDS
|
||||||
@ -345,5 +345,5 @@ export class CreateExerciseDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,16 +61,16 @@ export class ExerciseResponseDto {
|
|||||||
exercise_type!: ExerciseTypeEnum;
|
exercise_type!: ExerciseTypeEnum;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
config!: Record<string, any>;
|
config!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
solution?: Record<string, any>;
|
solution?: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
rubric?: Record<string, any>;
|
rubric?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GRADING & SCORING
|
// GRADING & SCORING
|
||||||
@ -132,7 +132,7 @@ export class ExerciseResponseDto {
|
|||||||
comodines_allowed!: ComodinTypeEnum[];
|
comodines_allowed!: ComodinTypeEnum[];
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
comodines_config!: Record<string, any>;
|
comodines_config!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GAMIFICATION & REWARDS
|
// GAMIFICATION & REWARDS
|
||||||
@ -187,7 +187,7 @@ export class ExerciseResponseDto {
|
|||||||
prerequisites?: string[];
|
prerequisites?: string[];
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT FIELDS
|
// AUDIT FIELDS
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export class SubmitExerciseDto {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject({ message: 'answers must be an object' })
|
@IsObject({ message: 'answers must be an object' })
|
||||||
@IsNotEmpty({ message: 'answers cannot be empty' })
|
@IsNotEmpty({ message: 'answers cannot be empty' })
|
||||||
answers?: Record<string, any>;
|
answers?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamp de inicio del ejercicio (milisegundos desde epoch)
|
* Timestamp de inicio del ejercicio (milisegundos desde epoch)
|
||||||
@ -133,7 +133,7 @@ export class SubmitExerciseDto {
|
|||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
submitted_answers?: Record<string, any>;
|
submitted_answers?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Usar 'startedAt' para calcular tiempo
|
* @deprecated Usar 'startedAt' para calcular tiempo
|
||||||
|
|||||||
@ -211,7 +211,7 @@ export class MediaResponseDto {
|
|||||||
* Metadatos adicionales
|
* Metadatos adicionales
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha de creación
|
* Fecha de creación
|
||||||
|
|||||||
@ -246,5 +246,5 @@ export class UploadMediaDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export class InfografiaInteractivaAnswerDto {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@IsObject({ message: 'answers must be an object' })
|
@IsObject({ message: 'answers must be an object' })
|
||||||
answers: Record<string, any>;
|
answers: Record<string, unknown>;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -59,5 +59,5 @@ export class NavegacionHipertextualAnswerDto {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
@IsObject({ message: 'information_found must be an object' })
|
@IsObject({ message: 'information_found must be an object' })
|
||||||
information_found: Record<string, any>;
|
information_found: Record<string, unknown>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export class CreateModuleDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
content?: Record<string, any>;
|
content?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Índice de orden para la secuencia de módulos (REQUERIDO)
|
* Índice de orden para la secuencia de módulos (REQUERIDO)
|
||||||
@ -345,14 +345,14 @@ export class CreateModuleDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
settings?: Record<string, any>;
|
settings?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadatos adicionales (JSONB)
|
* Metadatos adicionales (JSONB)
|
||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Total de ejercicios en el módulo
|
* Total de ejercicios en el módulo
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export class ModuleResponseDto {
|
|||||||
summary?: string;
|
summary?: string;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
order_index!: number;
|
order_index!: number;
|
||||||
@ -165,10 +165,10 @@ export class ModuleResponseDto {
|
|||||||
cover_image_url?: string;
|
cover_image_url?: string;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
settings!: Record<string, any>;
|
settings!: Record<string, unknown>;
|
||||||
|
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT FIELDS
|
// AUDIT FIELDS
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export class CreateRubricDto {
|
|||||||
* Estructura: {"criteria_1": {"name": string, "levels": {}, "weight": number}}
|
* Estructura: {"criteria_1": {"name": string, "levels": {}, "weight": number}}
|
||||||
*/
|
*/
|
||||||
@IsObject()
|
@IsObject()
|
||||||
criteria!: Record<string, any>;
|
criteria!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escala de puntuación en formato JSONB
|
* Escala de puntuación en formato JSONB
|
||||||
@ -73,7 +73,7 @@ export class CreateRubricDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
scoring_scale?: Record<string, any>;
|
scoring_scale?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peso porcentual de esta rúbrica (1-100%)
|
* Peso porcentual de esta rúbrica (1-100%)
|
||||||
@ -125,7 +125,7 @@ export class CreateRubricDto {
|
|||||||
*/
|
*/
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsObject()
|
@IsObject()
|
||||||
metadata?: Record<string, any>;
|
metadata?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que crea la rúbrica
|
* ID del usuario que crea la rúbrica
|
||||||
|
|||||||
@ -55,13 +55,13 @@ export class RubricResponseDto {
|
|||||||
* Criterios de evaluación en formato JSONB
|
* Criterios de evaluación en formato JSONB
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
criteria!: Record<string, any>;
|
criteria!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escala de puntuación
|
* Escala de puntuación
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
scoring_scale!: Record<string, any>;
|
scoring_scale!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peso porcentual de la rúbrica
|
* Peso porcentual de la rúbrica
|
||||||
@ -105,7 +105,7 @@ export class RubricResponseDto {
|
|||||||
* Metadatos adicionales
|
* Metadatos adicionales
|
||||||
*/
|
*/
|
||||||
@Expose()
|
@Expose()
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que creó la rúbrica
|
* ID del usuario que creó la rúbrica
|
||||||
|
|||||||
@ -76,14 +76,14 @@ export class AssessmentRubric {
|
|||||||
* Incluye niveles de logro con puntos y descripciones
|
* Incluye niveles de logro con puntos y descripciones
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
criteria: Record<string, any> = {};
|
criteria: Record<string, unknown> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escala de puntuación en formato JSONB
|
* Escala de puntuación en formato JSONB
|
||||||
* Estructura: {"min": number, "max": number, "passing": number}
|
* Estructura: {"min": number, "max": number, "passing": number}
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: { min: 0, max: 100, passing: 70 } })
|
@Column({ type: 'jsonb', default: { min: 0, max: 100, passing: 70 } })
|
||||||
scoring_scale!: Record<string, any>;
|
scoring_scale!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Peso porcentual de esta rúbrica en la evaluación total (1-100%)
|
* Peso porcentual de esta rúbrica en la evaluación total (1-100%)
|
||||||
@ -120,7 +120,7 @@ export class AssessmentRubric {
|
|||||||
* Puede incluir configuraciones específicas de evaluación
|
* Puede incluir configuraciones específicas de evaluación
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ID del usuario que creó la rúbrica
|
* ID del usuario que creó la rúbrica
|
||||||
|
|||||||
@ -150,7 +150,7 @@ export class Exercise {
|
|||||||
* - etc.
|
* - etc.
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
config!: Record<string, any>;
|
config!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contenido del ejercicio (JSONB)
|
* Contenido del ejercicio (JSONB)
|
||||||
@ -165,20 +165,20 @@ export class Exercise {
|
|||||||
correct_answers: [],
|
correct_answers: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Solución del ejercicio (JSONB)
|
* Solución del ejercicio (JSONB)
|
||||||
* Información privada no visible para estudiantes durante la resolución
|
* Información privada no visible para estudiantes durante la resolución
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
solution?: Record<string, any>;
|
solution?: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rúbrica de evaluación (JSONB)
|
* Rúbrica de evaluación (JSONB)
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', nullable: true })
|
@Column({ type: 'jsonb', nullable: true })
|
||||||
rubric?: Record<string, any>;
|
rubric?: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GRADING & SCORING
|
// GRADING & SCORING
|
||||||
@ -328,7 +328,7 @@ export class Exercise {
|
|||||||
segunda_oportunidad: { cost: 40, enabled: true },
|
segunda_oportunidad: { cost: 40, enabled: true },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
comodines_config!: Record<string, any>;
|
comodines_config!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// GAMIFICATION & REWARDS
|
// GAMIFICATION & REWARDS
|
||||||
@ -423,7 +423,7 @@ export class Exercise {
|
|||||||
* Metadatos adicionales (JSONB)
|
* Metadatos adicionales (JSONB)
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT FIELDS
|
// AUDIT FIELDS
|
||||||
|
|||||||
@ -241,7 +241,7 @@ export class MediaResource {
|
|||||||
* Puede incluir información técnica, codec, bitrate, etc.
|
* Puede incluir información técnica, codec, bitrate, etc.
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fecha y hora de creación del registro
|
* Fecha y hora de creación del registro
|
||||||
|
|||||||
@ -94,7 +94,7 @@ export class Module {
|
|||||||
multimedia_resources: [],
|
multimedia_resources: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
content!: Record<string, any>;
|
content!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Índice de orden para la secuencia de módulos
|
* Índice de orden para la secuencia de módulos
|
||||||
@ -350,13 +350,13 @@ export class Module {
|
|||||||
* Configuraciones del módulo (JSONB)
|
* Configuraciones del módulo (JSONB)
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
settings!: Record<string, any>;
|
settings!: Record<string, unknown>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadatos adicionales (JSONB)
|
* Metadatos adicionales (JSONB)
|
||||||
*/
|
*/
|
||||||
@Column({ type: 'jsonb', default: {} })
|
@Column({ type: 'jsonb', default: {} })
|
||||||
metadata!: Record<string, any>;
|
metadata!: Record<string, unknown>;
|
||||||
|
|
||||||
// =====================================================
|
// =====================================================
|
||||||
// AUDIT FIELDS
|
// AUDIT FIELDS
|
||||||
|
|||||||
@ -195,8 +195,8 @@ export class ExercisesService {
|
|||||||
*/
|
*/
|
||||||
validateContentByExerciseType(
|
validateContentByExerciseType(
|
||||||
exerciseType: ExerciseTypeEnum,
|
exerciseType: ExerciseTypeEnum,
|
||||||
content: Record<string, any>,
|
content: Record<string, unknown>,
|
||||||
config?: Record<string, any>,
|
config?: Record<string, unknown>,
|
||||||
): void {
|
): void {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
throw new BadRequestException('Content is required');
|
throw new BadRequestException('Content is required');
|
||||||
@ -474,10 +474,10 @@ export class ExercisesService {
|
|||||||
* @returns Sanitized content without correct answers
|
* @returns Sanitized content without correct answers
|
||||||
*/
|
*/
|
||||||
private sanitizeContent(
|
private sanitizeContent(
|
||||||
content: Record<string, any>,
|
content: Record<string, unknown>,
|
||||||
config: Record<string, any>,
|
config: Record<string, unknown>,
|
||||||
exerciseType: ExerciseTypeEnum,
|
exerciseType: ExerciseTypeEnum,
|
||||||
): Record<string, any> {
|
): Record<string, unknown> {
|
||||||
if (!content) {
|
if (!content) {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export class MediaService {
|
|||||||
async updateProcessingStatus(
|
async updateProcessingStatus(
|
||||||
id: string,
|
id: string,
|
||||||
status: ProcessingStatusEnum,
|
status: ProcessingStatusEnum,
|
||||||
metadata?: Record<string, any>,
|
metadata?: Record<string, unknown>,
|
||||||
): Promise<MediaResource> {
|
): Promise<MediaResource> {
|
||||||
const media = await this.findById(id);
|
const media = await this.findById(id);
|
||||||
if (!media) {
|
if (!media) {
|
||||||
|
|||||||
@ -141,7 +141,7 @@ export class ClassroomMissionsController {
|
|||||||
async assignMissionToClassroom(
|
async assignMissionToClassroom(
|
||||||
@Param('classroomId') classroomId: string,
|
@Param('classroomId') classroomId: string,
|
||||||
@Body() dto: AssignClassroomMissionDto,
|
@Body() dto: AssignClassroomMissionDto,
|
||||||
@Request() req: any,
|
@Request() req: AuthRequest,
|
||||||
) {
|
) {
|
||||||
const teacherId = req.user.id;
|
const teacherId = req.user.id;
|
||||||
return this.classroomMissionsService.assignMissionToClassroom(classroomId, teacherId, dto);
|
return this.classroomMissionsService.assignMissionToClassroom(classroomId, teacherId, dto);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user