refactor: reorganize imports in course route and update middleware for course tags endpoint
This commit is contained in:
@@ -25,33 +25,33 @@ import {
|
|||||||
getCourseProgress,
|
getCourseProgress,
|
||||||
updateCourse
|
updateCourse
|
||||||
} from '@api/services/course/course';
|
} from '@api/services/course/course';
|
||||||
import { enrollInCourse } from '@api/services/course/invite';
|
|
||||||
import { getCourseTags, replaceCourseTags } from '@api/services/tag';
|
import { getCourseTags, replaceCourseTags } from '@api/services/tag';
|
||||||
import { createRateLimiter } from '@api/middlewares/rate-limiter';
|
|
||||||
import { extractClientIp } from '@api/utils/redis/key-generators';
|
|
||||||
|
|
||||||
import { Hono } from '@api/utils/hono';
|
import { Hono } from '@api/utils/hono';
|
||||||
import { attendanceRouter } from '@api/routes/course/attendance';
|
import { attendanceRouter } from '@api/routes/course/attendance';
|
||||||
import { authMiddleware } from '@api/middlewares/auth';
|
import { authMiddleware } from '@api/middlewares/auth';
|
||||||
import { cloneCourse } from '@api/services/course/clone';
|
import { cloneCourse } from '@api/services/course/clone';
|
||||||
|
import { contentRouter } from '@api/routes/course/content';
|
||||||
import { courseMemberMiddleware } from '@api/middlewares/course-member';
|
import { courseMemberMiddleware } from '@api/middlewares/course-member';
|
||||||
import { courseTeamMemberMiddleware } from '@api/middlewares/course-team-member';
|
import { courseTeamMemberMiddleware } from '@api/middlewares/course-team-member';
|
||||||
import { contentRouter } from '@api/routes/course/content';
|
import { createRateLimiter } from '@api/middlewares/rate-limiter';
|
||||||
|
import { enrollInCourse } from '@api/services/course/invite';
|
||||||
import { exerciseRouter } from '@api/routes/course/exercise';
|
import { exerciseRouter } from '@api/routes/course/exercise';
|
||||||
|
import { extractClientIp } from '@api/utils/redis/key-generators';
|
||||||
import { generateCertificate } from '@api/utils/certificate';
|
import { generateCertificate } from '@api/utils/certificate';
|
||||||
import { generateCoursePdf } from '@api/utils/course';
|
import { generateCoursePdf } from '@api/utils/course';
|
||||||
import { handleError } from '@api/utils/errors';
|
import { handleError } from '@api/utils/errors';
|
||||||
|
import { invitesRouter } from '@api/routes/course/invite';
|
||||||
import { katexRouter } from '@api/routes/course/katex';
|
import { katexRouter } from '@api/routes/course/katex';
|
||||||
import { lessonRouter } from '@api/routes/course/lesson';
|
import { lessonRouter } from '@api/routes/course/lesson';
|
||||||
import { markRouter } from '@api/routes/course/mark';
|
import { markRouter } from '@api/routes/course/mark';
|
||||||
import { sectionRouter } from '@api/routes/course/section';
|
|
||||||
import { membersRouter } from '@api/routes/course/people';
|
import { membersRouter } from '@api/routes/course/people';
|
||||||
import { invitesRouter } from '@api/routes/course/invite';
|
|
||||||
import { newsfeedRouter } from '@api/routes/course/newsfeed';
|
import { newsfeedRouter } from '@api/routes/course/newsfeed';
|
||||||
import { orgAdminMiddleware } from '@api/middlewares/org-admin';
|
import { orgAdminMiddleware } from '@api/middlewares/org-admin';
|
||||||
import { orgMemberMiddleware } from '@api/middlewares/org-member';
|
import { orgMemberMiddleware } from '@api/middlewares/org-member';
|
||||||
import { paymentRequestRouter } from '@api/routes/course/payment-request';
|
import { paymentRequestRouter } from '@api/routes/course/payment-request';
|
||||||
import { presignRouter } from '@api/routes/course/presign';
|
import { presignRouter } from '@api/routes/course/presign';
|
||||||
|
import { sectionRouter } from '@api/routes/course/section';
|
||||||
import { submissionRouter } from '@api/routes/course/submission';
|
import { submissionRouter } from '@api/routes/course/submission';
|
||||||
import { zValidator } from '@hono/zod-validator';
|
import { zValidator } from '@hono/zod-validator';
|
||||||
|
|
||||||
@@ -157,7 +157,7 @@ export const courseRouter = new Hono()
|
|||||||
* GET /course/:courseId/tags
|
* GET /course/:courseId/tags
|
||||||
* Gets tags assigned to a course (organization admin only)
|
* Gets tags assigned to a course (organization admin only)
|
||||||
*/
|
*/
|
||||||
.get('/:courseId/tags', authMiddleware, orgAdminMiddleware, zValidator('param', ZCourseTagParam), async (c) => {
|
.get('/:courseId/tags', authMiddleware, orgMemberMiddleware, zValidator('param', ZCourseTagParam), async (c) => {
|
||||||
try {
|
try {
|
||||||
const orgId = c.req.header('cio-org-id')!;
|
const orgId = c.req.header('cio-org-id')!;
|
||||||
const { courseId } = c.req.valid('param');
|
const { courseId } = c.req.valid('param');
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ export async function getAccountData(userId: string): Promise<GetAccountDataResu
|
|||||||
roleId: ROLE.STUDENT,
|
roleId: ROLE.STUDENT,
|
||||||
verified: true
|
verified: true
|
||||||
});
|
});
|
||||||
|
|
||||||
organizations = await getOrganizationByProfileId(userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
organizations = await getOrganizationByProfileId(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
|
import * as schema from '@cio/db/schema';
|
||||||
|
|
||||||
import { AppError, ErrorCodes } from '@api/utils/errors';
|
import { AppError, ErrorCodes } from '@api/utils/errors';
|
||||||
import { and, eq, isNull } from 'drizzle-orm';
|
import { and, eq, isNull } from 'drizzle-orm';
|
||||||
import {
|
import {
|
||||||
checkEmailsExistInOrg,
|
checkEmailsExistInOrg,
|
||||||
createOrganizationMembers,
|
|
||||||
createOrganizationInvite,
|
createOrganizationInvite,
|
||||||
createOrganizationInviteAudit,
|
createOrganizationInviteAudit,
|
||||||
|
createOrganizationMembers,
|
||||||
getOrganizationById,
|
getOrganizationById,
|
||||||
getOrganizationInviteByTokenHash,
|
getOrganizationInviteByTokenHash,
|
||||||
revokeActiveOrganizationInvitesByEmails
|
revokeActiveOrganizationInvitesByEmails
|
||||||
} from '@cio/db/queries/organization';
|
} from '@cio/db/queries/organization';
|
||||||
|
|
||||||
|
import { ROLE } from '@cio/utils/constants';
|
||||||
|
import crypto from 'node:crypto';
|
||||||
import { db } from '@cio/db/drizzle';
|
import { db } from '@cio/db/drizzle';
|
||||||
import { getDashboardBaseUrl } from '@api/config/dashboard-url';
|
import { getDashboardBaseUrl } from '@api/config/dashboard-url';
|
||||||
|
import { markUserAndProfileEmailVerified } from '@cio/db/queries/auth/profile';
|
||||||
import { sendEmail } from '@cio/email';
|
import { sendEmail } from '@cio/email';
|
||||||
import { ROLE } from '@cio/utils/constants';
|
|
||||||
import * as schema from '@cio/db/schema';
|
|
||||||
import crypto from 'node:crypto';
|
|
||||||
|
|
||||||
type OrganizationInviteStatus = 'ACTIVE' | 'EXPIRED' | 'REVOKED' | 'ACCEPTED';
|
type OrganizationInviteStatus = 'ACTIVE' | 'EXPIRED' | 'REVOKED' | 'ACCEPTED';
|
||||||
|
|
||||||
@@ -302,6 +305,8 @@ export async function acceptOrganizationInvite(token: string, user: TAuthUser, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status === 'ACCEPTED') {
|
if (status === 'ACCEPTED') {
|
||||||
|
await markUserAndProfileEmailVerified(user.id, tx);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
organization: row.organization,
|
organization: row.organization,
|
||||||
roleId: row.invite.roleId,
|
roleId: row.invite.roleId,
|
||||||
@@ -366,6 +371,8 @@ export async function acceptOrganizationInvite(token: string, user: TAuthUser, c
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await markUserAndProfileEmailVerified(user.id, tx);
|
||||||
|
|
||||||
const [acceptedInvite] = await tx
|
const [acceptedInvite] = await tx
|
||||||
.update(schema.organizationInvite)
|
.update(schema.organizationInvite)
|
||||||
.set({
|
.set({
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { and, eq } from 'drizzle-orm';
|
|||||||
|
|
||||||
import { User } from 'better-auth';
|
import { User } from 'better-auth';
|
||||||
import { db } from '@db/drizzle';
|
import { db } from '@db/drizzle';
|
||||||
|
import { markUserAndProfileEmailVerified } from '@db/queries/auth';
|
||||||
|
|
||||||
const DEFAULT_STUDENT_ROLE_ID = 3;
|
const DEFAULT_STUDENT_ROLE_ID = 3;
|
||||||
|
|
||||||
@@ -60,6 +61,8 @@ export async function ensureOrgMembership(
|
|||||||
updatedAt: new Date().toISOString()
|
updatedAt: new Date().toISOString()
|
||||||
})
|
})
|
||||||
.where(eq(schema.organizationInvite.id, invite.id));
|
.where(eq(schema.organizationInvite.id, invite.id));
|
||||||
|
|
||||||
|
await markUserAndProfileEmailVerified(userId, tx);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.debug('User joined org via invite:', orgId);
|
console.debug('User joined org via invite:', orgId);
|
||||||
|
|||||||
@@ -515,6 +515,12 @@ export async function getExerciseWithRelationsOptimized(
|
|||||||
*/
|
*/
|
||||||
export async function syncOptionIdSequence(dbClient: DbOrTxClient = db): Promise<void> {
|
export async function syncOptionIdSequence(dbClient: DbOrTxClient = db): Promise<void> {
|
||||||
await dbClient.execute(
|
await dbClient.execute(
|
||||||
sql`SELECT setval(pg_get_serial_sequence('option', 'id'), COALESCE((SELECT MAX(id) FROM "option"), 0))`
|
sql`
|
||||||
|
SELECT setval(
|
||||||
|
pg_get_serial_sequence('option', 'id'),
|
||||||
|
COALESCE((SELECT MAX(id) FROM "option"), 1),
|
||||||
|
EXISTS(SELECT 1 FROM "option")
|
||||||
|
)
|
||||||
|
`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user