New_Micro_Learning/backend/routes/api.php

285 خطوط
24 KiB
PHP

<?php
use App\Modules\AI\Http\AiChatController;
use App\Modules\AI\Http\AiConnectionController;
use App\Modules\AI\Http\AiStudioController;
use App\Modules\Analytics\Http\CourseAnalyticsController;
use App\Modules\Assessments\Http\AssessmentController;
use App\Modules\Assessments\Http\QuestionBankController;
use App\Modules\Assessments\Http\QuestionCategoryController;
use App\Modules\Assets\Http\AssetController;
use App\Modules\Assignments\Http\AssignmentController;
use App\Modules\Certificates\Http\CertificateController;
use App\Modules\Collaboration\Http\CollaborationController;
use App\Modules\Collaboration\Http\NotificationController;
use App\Modules\Courses\Http\CourseBuilderController;
use App\Modules\Courses\Http\CourseController;
use App\Modules\Courses\Http\CourseStructureController;
use App\Modules\Courses\Http\CourseVersionController;
use App\Modules\Export\Http\ExportController;
use App\Modules\Identity\Http\AuthController;
use App\Modules\Identity\Http\InvitationController;
use App\Modules\Identity\Http\PasswordController;
use App\Modules\Identity\Http\UserController;
use App\Modules\Learner\Http\LearnerController;
use App\Modules\LearningPaths\Http\LearningPathController;
use App\Modules\Manager\Http\ManagerAssignmentController;
use App\Modules\Manager\Http\ManagerWorkspaceController;
use App\Modules\Monitoring\Http\MonitoringController;
use App\Modules\Organizations\Http\OrganizationController;
use App\Modules\Product\Http\PlatformGovernanceController;
use App\Modules\Product\Http\PlatformOperationsController;
use App\Modules\Product\Http\ProductSurfaceController;
use App\Modules\Publishing\Http\CoursePublicationController;
use App\Modules\Subscriptions\Http\PlatformOrganizationPlanController;
use App\Modules\Subscriptions\Http\PlatformPlanController;
use App\Modules\Subscriptions\Http\PlatformSubscriptionController;
use App\Modules\Subscriptions\Http\SubscriptionController;
use App\Modules\System\Http\SystemHealthController;
use App\Modules\Taxonomy\Http\ContentMappingController;
use App\Modules\Taxonomy\Http\TaxonomyNodeController;
use App\Modules\Taxonomy\Http\TaxonomyTypeController;
use App\Modules\Taxonomy\Http\TaxonomyWorkspaceController;
use App\Modules\Teams\Http\TeamController;
use App\Modules\Tenancy\Application\TenantContext;
use Illuminate\Support\Facades\Route;
Route::get('/v1/assets/{asset}/content', [AssetController::class, 'content'])->name('assets.content')->middleware('signed:relative');
Route::prefix('v1')->group(function () {
Route::get('/health', SystemHealthController::class);
Route::get('/certificates/verify/{code}', [CertificateController::class, 'verify'])->middleware('throttle:60,1');
Route::post('/auth/login', [AuthController::class, 'login'])->middleware('throttle:login');
Route::post('/auth/forgot-password', [PasswordController::class, 'forgot'])->middleware('throttle:login');
Route::post('/auth/reset-password', [PasswordController::class, 'reset'])->middleware('throttle:login');
Route::post('/auth/invitations/accept', [InvitationController::class, 'accept'])->middleware('throttle:login');
Route::middleware('auth:sanctum')->group(function () {
Route::get('/auth/me', [AuthController::class, 'me']);
Route::post('/auth/logout', [AuthController::class, 'logout']);
Route::get('/organizations', [OrganizationController::class, 'index']);
Route::post('/organizations', [OrganizationController::class, 'store']);
Route::get('/organizations/{organization}', [OrganizationController::class, 'show']);
Route::patch('/organizations/{organization}', [OrganizationController::class, 'update']);
Route::middleware('tenant')->group(function () {
Route::post('/ai/chat', [AiChatController::class, 'chat'])->middleware('throttle:10,1');
Route::get('/organization-context', fn (TenantContext $tenant) => response()->json([
'data' => [
'id' => $tenant->id(),
'name' => $tenant->organization()->name,
],
]));
Route::get('/learner/home', [LearnerController::class, 'home']);
Route::get('/learner/progress', [LearnerController::class, 'progress']);
Route::get('/learner/assignments/{assignment}', [LearnerController::class, 'show']);
Route::post('/learner/events/sync', [LearnerController::class, 'sync']);
Route::post('/learner/assignments/{assignment}/notes', [LearnerController::class, 'note']);
Route::post('/learner/assignments/{assignment}/bookmarks', [LearnerController::class, 'bookmark']);
Route::post('/learner/assignments/{assignment}/highlights', [LearnerController::class, 'highlight']);
Route::post('/learner/assignments/{assignment}/favorite', [LearnerController::class, 'favorite']);
Route::post('/learner/assignments/{assignment}/discussions', [LearnerController::class, 'discuss']);
Route::post('/learner/discussions/{discussion}/reactions', [LearnerController::class, 'react']);
Route::get('/manager/workspace', [ManagerWorkspaceController::class, 'show']);
Route::get('/manager/assignment-contexts', [ManagerAssignmentController::class, 'contexts']);
Route::get('/manager/assignments', [ManagerAssignmentController::class, 'index']);
Route::post('/manager/assignments', [ManagerAssignmentController::class, 'store']);
Route::patch('/manager/assignments/{assignment}/deadline', [ManagerAssignmentController::class, 'deadline']);
Route::post('/manager/assignments/{assignment}/reminders', [ManagerAssignmentController::class, 'remind'])->middleware('throttle:20,1');
Route::get('/monitoring', [MonitoringController::class, 'show']);
Route::post('/monitoring/rebuild', [MonitoringController::class, 'rebuild']);
Route::get('/courses/{course}/analytics', [CourseAnalyticsController::class, 'show']);
Route::get('/courses/{course}/analytics/report', [CourseAnalyticsController::class, 'report']);
Route::get('/course-versions/{version}/collaboration', [CollaborationController::class, 'snapshot']);
Route::post('/blocks/{block}/soft-lock', [CollaborationController::class, 'acquireLock']);
Route::put('/blocks/{block}/soft-lock', [CollaborationController::class, 'renewLock']);
Route::delete('/blocks/{block}/soft-lock', [CollaborationController::class, 'releaseLock']);
Route::post('/course-versions/{version}/review-threads', [CollaborationController::class, 'createThread']);
Route::post('/review-threads/{thread}/replies', [CollaborationController::class, 'reply']);
Route::patch('/review-threads/{thread}/resolution', [CollaborationController::class, 'resolve']);
Route::patch('/review-threads/{thread}/assignees', [CollaborationController::class, 'assign']);
Route::post('/review-threads/{thread}/read', [CollaborationController::class, 'markRead']);
Route::patch('/review-messages/{kind}/{message}', [CollaborationController::class, 'updateMessage']);
Route::delete('/review-messages/{kind}/{message}', [CollaborationController::class, 'deleteMessage']);
Route::post('/review-threads/{thread}/reactions', [CollaborationController::class, 'react']);
Route::get('/review-center', [CollaborationController::class, 'reviewCenter']);
Route::get('/notifications', [NotificationController::class, 'index']);
Route::post('/notifications/{notification}/read', [NotificationController::class, 'read']);
Route::delete('/notifications/{notification}', [NotificationController::class, 'dismiss']);
Route::get('/preferences', [ProductSurfaceController::class, 'preferences']);
Route::patch('/preferences', [ProductSurfaceController::class, 'updatePreferences']);
Route::get('/organization-settings', [ProductSurfaceController::class, 'organizationSettings']);
Route::patch('/organization-settings', [ProductSurfaceController::class, 'updateOrganizationSettings']);
Route::get('/brand', [ProductSurfaceController::class, 'brand']);
Route::patch('/brand', [ProductSurfaceController::class, 'updateBrand']);
Route::get('/templates', [ProductSurfaceController::class, 'templates']);
Route::post('/templates', [ProductSurfaceController::class, 'storeTemplate']);
Route::patch('/templates/{template}', [ProductSurfaceController::class, 'updateTemplate']);
Route::delete('/templates/{template}', [ProductSurfaceController::class, 'destroyTemplate']);
Route::post('/templates/{template}/instantiate', [ProductSurfaceController::class, 'instantiateTemplate']);
Route::get('/product-surfaces/{surface}', [ProductSurfaceController::class, 'surface']);
Route::get('/exports', [ExportController::class, 'index']);
Route::get('/exports/data/{type}', [ExportController::class, 'data']);
Route::post('/exports/compatibility', [ExportController::class, 'compatibility']);
Route::post('/exports', [ExportController::class, 'store']);
Route::post('/exports/{export}/retry', [ExportController::class, 'retry']);
Route::post('/exports/{export}/cancel', [ExportController::class, 'cancel']);
Route::get('/exports/{export}/download', [ExportController::class, 'download']);
Route::get('/certificates', [CertificateController::class, 'index']);
Route::post('/certificate-templates', [CertificateController::class, 'storeTemplate']);
Route::patch('/certificate-templates/{template}', [CertificateController::class, 'updateTemplate']);
Route::delete('/certificate-templates/{template}', [CertificateController::class, 'archiveTemplate']);
Route::post('/certificates/issue', [CertificateController::class, 'issue']);
Route::post('/certificates/issue-bulk', [CertificateController::class, 'issueBulk']);
Route::post('/certificates/{certificate}/revoke', [CertificateController::class, 'revoke']);
Route::get('/certificates/{certificate}/download', [CertificateController::class, 'download']);
Route::get('/ai-studio/jobs', [AiStudioController::class, 'index']);
Route::get('/ai-settings', [AiStudioController::class, 'settings']);
Route::patch('/ai-settings', [AiStudioController::class, 'updateSettings']);
Route::post('/ai-settings/health', [AiStudioController::class, 'health'])->middleware('throttle:10,1');
Route::get('/ai-connections', [AiConnectionController::class, 'index']);
Route::post('/ai-connections', [AiConnectionController::class, 'store']);
Route::patch('/ai-connections/{connection}', [AiConnectionController::class, 'update']);
Route::delete('/ai-connections/{connection}', [AiConnectionController::class, 'destroy']);
Route::post('/ai-connections/{connection}/default', [AiConnectionController::class, 'makeDefault']);
Route::post('/ai-connections/{connection}/test', [AiConnectionController::class, 'test'])->middleware('throttle:10,1');
Route::post('/ai-connections/{connection}/models', [AiConnectionController::class, 'discover'])->middleware('throttle:10,1');
Route::post('/ai-studio/jobs', [AiStudioController::class, 'store'])->middleware('throttle:10,1');
Route::get('/ai-studio/jobs/{job}', [AiStudioController::class, 'show']);
Route::post('/ai-studio/jobs/{job}/cancel', [AiStudioController::class, 'cancel']);
Route::post('/ai-studio/jobs/{job}/retry', [AiStudioController::class, 'retry'])->middleware('throttle:10,1');
Route::post('/ai-studio/assist', [AiStudioController::class, 'assist'])->middleware('throttle:10,1');
Route::post('/ai-studio/taxonomy-suggestions', [AiStudioController::class, 'taxonomySuggestions']);
Route::post('/ai-studio/suggestions/{suggestion}/accept', [AiStudioController::class, 'accept']);
Route::post('/ai-studio/suggestions/{suggestion}/reject', [AiStudioController::class, 'reject']);
Route::get('/taxonomy-types', [TaxonomyTypeController::class, 'index']);
Route::post('/taxonomy-types', [TaxonomyTypeController::class, 'store']);
Route::get('/taxonomy-nodes', [TaxonomyNodeController::class, 'index']);
Route::post('/taxonomy-nodes', [TaxonomyNodeController::class, 'store']);
Route::patch('/taxonomy-nodes/{node}', [TaxonomyNodeController::class, 'update']);
Route::get('/content-mappings', [ContentMappingController::class, 'index']);
Route::post('/content-mappings', [ContentMappingController::class, 'store']);
Route::delete('/content-mappings/{mapping}', [ContentMappingController::class, 'destroy']);
Route::get('/taxonomy-workspace', [TaxonomyWorkspaceController::class, 'index']);
Route::post('/competency-frameworks', [TaxonomyWorkspaceController::class, 'storeFramework']);
Route::patch('/competency-frameworks/{framework}', [TaxonomyWorkspaceController::class, 'updateFramework']);
Route::put('/competency-frameworks/{framework}/items', [TaxonomyWorkspaceController::class, 'syncItems']);
Route::delete('/competency-frameworks/{framework}', [TaxonomyWorkspaceController::class, 'destroyFramework']);
Route::get('/assets', [AssetController::class, 'index']);
Route::get('/assets/{asset}', [AssetController::class, 'show']);
Route::post('/assets', [AssetController::class, 'store']);
Route::delete('/assets/{asset}', [AssetController::class, 'destroy']);
Route::get('/assessment-contexts', [AssessmentController::class, 'contexts']);
Route::get('/assessments', [AssessmentController::class, 'index']);
Route::post('/assessments', [AssessmentController::class, 'store']);
Route::get('/assessments/{assessment}', [AssessmentController::class, 'show']);
Route::patch('/assessments/{assessment}', [AssessmentController::class, 'update']);
Route::delete('/assessments/{assessment}', [AssessmentController::class, 'destroy']);
Route::post('/assessments/{assessment}/questions', [AssessmentController::class, 'storeQuestion']);
Route::put('/assessments/{assessment}/questions/order', [AssessmentController::class, 'reorderQuestions']);
Route::patch('/questions/{question}', [AssessmentController::class, 'updateQuestion']);
Route::delete('/questions/{question}', [AssessmentController::class, 'destroyQuestion']);
Route::get('/question-bank', [QuestionBankController::class, 'index']);
Route::post('/question-bank', [QuestionBankController::class, 'store']);
Route::patch('/question-bank/{question}', [QuestionBankController::class, 'update']);
Route::delete('/question-bank/{question}', [QuestionBankController::class, 'destroy']);
Route::get('/question-categories', [QuestionCategoryController::class, 'index']);
Route::post('/question-categories', [QuestionCategoryController::class, 'store']);
Route::delete('/question-categories/{category}', [QuestionCategoryController::class, 'destroy']);
Route::get('/users', [UserController::class, 'index']);
Route::get('/users/import-template', [UserController::class, 'template']);
Route::post('/users/import', [UserController::class, 'import']);
Route::patch('/users/{user}', [UserController::class, 'update']);
Route::post('/user-invitations', [InvitationController::class, 'store']);
Route::get('/user-invitations', [InvitationController::class, 'index']);
Route::post('/user-invitations/{invitation}/resend', [InvitationController::class, 'resend']);
Route::delete('/user-invitations/{invitation}', [InvitationController::class, 'revoke']);
Route::get('/teams', [TeamController::class, 'index']);
Route::post('/teams', [TeamController::class, 'store']);
Route::get('/teams/{team}', [TeamController::class, 'show']);
Route::patch('/teams/{team}', [TeamController::class, 'update']);
Route::put('/teams/{team}/members', [TeamController::class, 'attachMember']);
Route::put('/teams/{team}/managers', [TeamController::class, 'attachManager']);
Route::delete('/teams/{team}/members/{user}', [TeamController::class, 'detachMember']);
Route::delete('/teams/{team}/managers/{user}', [TeamController::class, 'detachManager']);
Route::get('/subscription', [SubscriptionController::class, 'current']);
Route::get('/courses', [CourseController::class, 'index']);
Route::post('/courses', [CourseController::class, 'store']);
Route::get('/courses/{course}', [CourseController::class, 'show']);
Route::patch('/courses/{course}', [CourseController::class, 'update']);
Route::post('/courses/{course}/bookmark', [CourseController::class, 'toggleBookmark']);
Route::post('/courses/{course}/archive', [CourseController::class, 'archive']);
Route::get('/courses/{course}/versions', [CourseVersionController::class, 'index']);
Route::get('/courses/{course}/versions/compare', [CourseVersionController::class, 'compare']);
Route::patch('/courses/{course}/versions/{version}', [CourseController::class, 'updateVersion']);
Route::post('/courses/{course}/versions/{version}/fork', [CourseController::class, 'fork']);
Route::get('/courses/{course}/versions/{version}/readiness', [CoursePublicationController::class, 'readiness']);
Route::put('/courses/{course}/versions/{version}/completion-rules', [CoursePublicationController::class, 'configure']);
Route::post('/courses/{course}/versions/{version}/review', [CoursePublicationController::class, 'submitReview']);
Route::post('/courses/{course}/versions/{version}/return-to-draft', [CoursePublicationController::class, 'returnDraft']);
Route::post('/courses/{course}/versions/{version}/publish', [CoursePublicationController::class, 'publish']);
Route::post('/courses/{course}/versions/{version}/schedule', [CoursePublicationController::class, 'schedule']);
Route::delete('/courses/{course}/versions/{version}/schedule', [CoursePublicationController::class, 'cancelSchedule']);
Route::post('/courses/{course}/versions/{version}/unpublish', [CoursePublicationController::class, 'unpublish']);
Route::get('/assignment-contexts', [AssignmentController::class, 'contexts']);
Route::post('/assignment-audience-import', [AssignmentController::class, 'importAudience']);
Route::get('/assignments', [AssignmentController::class, 'index']);
Route::post('/assignments', [AssignmentController::class, 'store']);
Route::post('/assignments/bulk', [AssignmentController::class, 'bulk']);
Route::get('/assignments/{assignment}', [AssignmentController::class, 'show']);
Route::patch('/assignments/{assignment}', [AssignmentController::class, 'update']);
Route::post('/assignments/{assignment}/reminders', [AssignmentController::class, 'remind'])->middleware('throttle:20,1');
Route::post('/assignments/sync', [AssignmentController::class, 'sync']);
Route::post('/assignments/{assignment}/cancel', [AssignmentController::class, 'cancel']);
Route::get('/learning-path-contexts', [LearningPathController::class, 'contexts']);
Route::get('/learning-paths', [LearningPathController::class, 'index']);
Route::post('/learning-paths', [LearningPathController::class, 'store']);
Route::get('/learning-paths/{path}', [LearningPathController::class, 'show']);
Route::patch('/learning-paths/{path}/versions/{version}', [LearningPathController::class, 'update']);
Route::post('/learning-paths/{path}/versions/{version}/items', [LearningPathController::class, 'addItem']);
Route::put('/learning-paths/{path}/versions/{version}/items/order', [LearningPathController::class, 'reorder']);
Route::delete('/learning-path-items/{item}', [LearningPathController::class, 'removeItem']);
Route::post('/learning-paths/{path}/versions/{version}/review', [LearningPathController::class, 'submitReview']);
Route::post('/learning-paths/{path}/versions/{version}/publish', [LearningPathController::class, 'publish']);
Route::post('/learning-paths/{path}/versions/{version}/fork', [LearningPathController::class, 'fork']);
Route::post('/course-versions/{version}/modules', [CourseStructureController::class, 'storeModule']);
Route::put('/course-versions/{version}/modules/order', [CourseStructureController::class, 'reorderModules']);
Route::patch('/course-modules/{module}', [CourseStructureController::class, 'updateModule']);
Route::post('/course-modules/{module}/duplicate', [CourseStructureController::class, 'duplicateModule']);
Route::delete('/course-modules/{module}', [CourseStructureController::class, 'destroyModule']);
Route::post('/course-modules/{module}/lessons', [CourseStructureController::class, 'storeLesson']);
Route::put('/course-modules/{module}/lessons/order', [CourseStructureController::class, 'reorderLessons']);
Route::patch('/lessons/{lesson}', [CourseStructureController::class, 'updateLesson']);
Route::post('/lessons/{lesson}/duplicate', [CourseStructureController::class, 'duplicateLesson']);
Route::delete('/lessons/{lesson}', [CourseStructureController::class, 'destroyLesson']);
Route::get('/block-registry', [CourseBuilderController::class, 'registry']);
Route::get('/courses/{course}/versions/{version}/lessons/{lesson}/builder', [CourseBuilderController::class, 'show']);
Route::post('/courses/{course}/versions/{version}/lessons/{lesson}/blocks', [CourseBuilderController::class, 'store']);
Route::patch('/blocks/{block}', [CourseBuilderController::class, 'update']);
Route::post('/blocks/{block}/duplicate', [CourseBuilderController::class, 'duplicate']);
Route::delete('/blocks/{block}', [CourseBuilderController::class, 'destroy']);
Route::put('/lessons/{lesson}/blocks/order', [CourseBuilderController::class, 'reorder']);
});
Route::get('/platform/overview', [ProductSurfaceController::class, 'platform']);
Route::get('/platform/usage', [PlatformOperationsController::class, 'usage']);
Route::get('/platform/storage', [PlatformOperationsController::class, 'storage']);
Route::get('/platform/ai', [PlatformOperationsController::class, 'ai']);
Route::get('/platform/health', [PlatformOperationsController::class, 'health']);
Route::get('/platform/jobs', [PlatformOperationsController::class, 'jobs']);
Route::get('/platform/backups', [PlatformOperationsController::class, 'backups']);
Route::get('/platform/audit', [PlatformGovernanceController::class, 'audit']);
Route::get('/platform/administrators', [PlatformGovernanceController::class, 'administrators']);
Route::match(['get', 'patch'], '/platform/settings', [ProductSurfaceController::class, 'platformSettings']);
Route::get('/platform/subscriptions', [PlatformSubscriptionController::class, 'index']);
Route::post('/platform/subscriptions', [PlatformSubscriptionController::class, 'store']);
Route::patch('/platform/subscriptions/{subscription}', [PlatformSubscriptionController::class, 'update']);
Route::get('/platform/plans', [PlatformPlanController::class, 'index']);
Route::post('/platform/plans', [PlatformPlanController::class, 'store']);
Route::patch('/platform/plans/{plan}', [PlatformPlanController::class, 'update']);
Route::get('/platform/organizations/{organization}/plan', [PlatformOrganizationPlanController::class, 'show']);
Route::patch('/platform/organizations/{organization}/plan', [PlatformOrganizationPlanController::class, 'update']);
});
});