feat: implement automation key management with middleware and routes for organization API keys, invite improvements
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
ZCreateOrganizationApiKey,
|
||||
ZListOrganizationApiKeysQuery,
|
||||
ZOrganizationApiKeyParam
|
||||
} from '@cio/utils/validation/organization';
|
||||
import {
|
||||
createOrganizationApiKeyService,
|
||||
listOrganizationApiKeysService,
|
||||
revokeOrganizationApiKeyService,
|
||||
rotateOrganizationApiKeyService
|
||||
} from '@api/services/organization/automation-key';
|
||||
|
||||
import { Hono } from '@api/utils/hono';
|
||||
import { authMiddleware } from '@api/middlewares/auth';
|
||||
import { handleError } from '@api/utils/errors';
|
||||
import { orgAdminMiddleware } from '@api/middlewares/org-admin';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
|
||||
export const automationRouter = new Hono()
|
||||
.get('/keys', authMiddleware, orgAdminMiddleware, zValidator('query', ZListOrganizationApiKeysQuery), async (c) => {
|
||||
try {
|
||||
const orgId = c.req.header('cio-org-id')!;
|
||||
const query = c.req.valid('query');
|
||||
const keys = await listOrganizationApiKeysService(orgId, query);
|
||||
|
||||
return c.json({ success: true, data: keys }, 200);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to list organization automation keys');
|
||||
}
|
||||
})
|
||||
.post('/keys', authMiddleware, orgAdminMiddleware, zValidator('json', ZCreateOrganizationApiKey), async (c) => {
|
||||
try {
|
||||
const orgId = c.req.header('cio-org-id')!;
|
||||
const user = c.get('user')!;
|
||||
const payload = c.req.valid('json');
|
||||
const key = await createOrganizationApiKeyService(orgId, user.id, payload);
|
||||
|
||||
return c.json({ success: true, data: key }, 201);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to create organization automation key');
|
||||
}
|
||||
})
|
||||
.delete(
|
||||
'/keys/:keyId',
|
||||
authMiddleware,
|
||||
orgAdminMiddleware,
|
||||
zValidator('param', ZOrganizationApiKeyParam),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.req.header('cio-org-id')!;
|
||||
const { keyId } = c.req.valid('param');
|
||||
const key = await revokeOrganizationApiKeyService(orgId, keyId);
|
||||
|
||||
return c.json({ success: true, data: key }, 200);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to revoke organization automation key');
|
||||
}
|
||||
}
|
||||
)
|
||||
.post(
|
||||
'/keys/:keyId/rotate',
|
||||
authMiddleware,
|
||||
orgAdminMiddleware,
|
||||
zValidator('param', ZOrganizationApiKeyParam),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.req.header('cio-org-id')!;
|
||||
const { keyId } = c.req.valid('param');
|
||||
const key = await rotateOrganizationApiKeyService(orgId, keyId);
|
||||
|
||||
return c.json({ success: true, data: key }, 200);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to rotate organization automation key');
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,98 @@
|
||||
import {
|
||||
ZCourseImportDraftCreate,
|
||||
ZCourseImportDraftGetParam,
|
||||
ZCourseImportDraftPublish,
|
||||
ZCourseImportDraftUpdate
|
||||
} from '@cio/utils/validation/course-import';
|
||||
import {
|
||||
createCourseImportDraftService,
|
||||
getCourseImportDraftService,
|
||||
publishCourseImportDraftService,
|
||||
updateCourseImportDraftService
|
||||
} from '@api/services/course-import/course-import';
|
||||
|
||||
import { Hono } from '@api/utils/hono';
|
||||
import { authOrAutomationKeyMiddleware } from '@api/middlewares/auth-or-automation-key';
|
||||
import { handleError } from '@api/utils/errors';
|
||||
import { orgAdminOrAutomationKeyMiddleware } from '@api/middlewares/org-admin-or-automation-key';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
|
||||
export const courseImportRouter = new Hono()
|
||||
.post(
|
||||
'/drafts',
|
||||
authOrAutomationKeyMiddleware,
|
||||
orgAdminOrAutomationKeyMiddleware(['course_import:draft:create']),
|
||||
zValidator('json', ZCourseImportDraftCreate),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.get('orgId')!;
|
||||
const actorId = c.get('actorId')!;
|
||||
const payload = c.req.valid('json');
|
||||
|
||||
const draft = await createCourseImportDraftService(orgId, actorId, payload);
|
||||
|
||||
return c.json({ success: true, data: draft }, 201);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to create course import draft');
|
||||
}
|
||||
}
|
||||
)
|
||||
.get(
|
||||
'/drafts/:draftId',
|
||||
authOrAutomationKeyMiddleware,
|
||||
orgAdminOrAutomationKeyMiddleware(['course_import:draft:read']),
|
||||
zValidator('param', ZCourseImportDraftGetParam),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.get('orgId')!;
|
||||
const { draftId } = c.req.valid('param');
|
||||
|
||||
const draft = await getCourseImportDraftService(orgId, draftId);
|
||||
|
||||
return c.json({ success: true, data: draft }, 200);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to fetch course import draft');
|
||||
}
|
||||
}
|
||||
)
|
||||
.put(
|
||||
'/drafts/:draftId',
|
||||
authOrAutomationKeyMiddleware,
|
||||
orgAdminOrAutomationKeyMiddleware(['course_import:draft:update']),
|
||||
zValidator('param', ZCourseImportDraftGetParam),
|
||||
zValidator('json', ZCourseImportDraftUpdate),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.get('orgId')!;
|
||||
const { draftId } = c.req.valid('param');
|
||||
const payload = c.req.valid('json');
|
||||
|
||||
const draft = await updateCourseImportDraftService(orgId, draftId, payload);
|
||||
|
||||
return c.json({ success: true, data: draft }, 200);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to update course import draft');
|
||||
}
|
||||
}
|
||||
)
|
||||
.post(
|
||||
'/drafts/:draftId/publish',
|
||||
authOrAutomationKeyMiddleware,
|
||||
orgAdminOrAutomationKeyMiddleware(['course_import:draft:publish']),
|
||||
zValidator('param', ZCourseImportDraftGetParam),
|
||||
zValidator('json', ZCourseImportDraftPublish),
|
||||
async (c) => {
|
||||
try {
|
||||
const orgId = c.get('orgId')!;
|
||||
const actorId = c.get('actorId')!;
|
||||
const { draftId } = c.req.valid('param');
|
||||
const payload = c.req.valid('json');
|
||||
|
||||
const result = await publishCourseImportDraftService(orgId, actorId, draftId, payload);
|
||||
|
||||
return c.json({ success: true, data: result }, 201);
|
||||
} catch (error) {
|
||||
return handleError(c, error, 'Failed to publish course import draft');
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -2,3 +2,5 @@ export * from './organization';
|
||||
export * from './assets';
|
||||
export * from './tags';
|
||||
export * from './token-auth';
|
||||
export * from './course-import';
|
||||
export * from './automation';
|
||||
|
||||
@@ -34,9 +34,11 @@ import {
|
||||
|
||||
import { Hono } from '@api/utils/hono';
|
||||
import { TOrganization } from '@db/types';
|
||||
import { automationRouter } from '@api/routes/organization/automation';
|
||||
import { assetsRouter } from '@api/routes/organization/assets';
|
||||
import { authMiddleware } from '@api/middlewares/auth';
|
||||
import { authOrApiKeyMiddleware } from '@api/middlewares/auth-or-api-key';
|
||||
import { courseImportRouter } from '@api/routes/organization/course-import';
|
||||
import { getLMSExercisesService } from '@api/services/exercise';
|
||||
import { handleError } from '@api/utils/errors';
|
||||
import { inviteTeamMembers } from '@api/services/organization/invite';
|
||||
@@ -505,6 +507,8 @@ export const organizationRouter = new Hono()
|
||||
return handleError(c, error, 'Failed to fetch LMS exercises');
|
||||
}
|
||||
})
|
||||
.route('/automation', automationRouter)
|
||||
.route('/course-import', courseImportRouter)
|
||||
.route('/tags', tagsRouter)
|
||||
.route('/assets', assetsRouter)
|
||||
.route('/:orgId/quiz', quizRouter);
|
||||
|
||||
Reference in New Issue
Block a user