feat: certification rules, content sanitization, handle draft course updates and reset content, better redis logging

This commit is contained in:
Rotimi Best
2026-03-30 08:24:55 +01:00
parent ff2ad59377
commit 5a8f50f67b
131 changed files with 5643 additions and 2134 deletions
+12 -3
View File
@@ -39,7 +39,10 @@ export async function seedCourses({ mvcGroupId, reactGroupId, pandasGroupId }: S
cost: 0,
currency: 'NGN',
isPublished: true,
isCertificateDownloadable: false,
certificate: {
isDownloadable: false,
theme: 'professional'
},
status: 'ACTIVE'
},
{
@@ -63,7 +66,10 @@ export async function seedCourses({ mvcGroupId, reactGroupId, pandasGroupId }: S
cost: 0,
currency: 'NGN',
isPublished: true,
isCertificateDownloadable: false,
certificate: {
isDownloadable: false,
theme: 'professional'
},
status: 'ACTIVE'
},
{
@@ -87,7 +93,10 @@ export async function seedCourses({ mvcGroupId, reactGroupId, pandasGroupId }: S
cost: 0,
currency: 'NGN',
isPublished: true,
isCertificateDownloadable: false,
certificate: {
isDownloadable: false,
theme: 'professional'
},
status: 'ACTIVE'
}
].filter((c) => !existingCourseIds.includes(c.id));
+14 -1
View File
@@ -1,6 +1,6 @@
import { db, organization } from '@db/drizzle';
export async function seedOrganization({ testOrgId }: { testOrgId: string }) {
export async function seedOrganization({ testOrgId, enterpriseOrgId }: { testOrgId: string; enterpriseOrgId: string }) {
const existingOrgs = await db.select().from(organization);
const existingOrgIds = existingOrgs.map((o) => o.id);
@@ -17,6 +17,19 @@ export async function seedOrganization({ testOrgId }: { testOrgId: string }) {
course: { grading: true, newsfeed: true },
dashboard: { exercise: true, community: true, bannerText: '', bannerImage: '' }
}
},
{
id: enterpriseOrgId,
name: 'Coursera Test',
siteName: 'coursera-test',
settings: {},
landingpage: {},
theme: '',
customization: {
apps: { poll: true, comments: true },
course: { grading: true, newsfeed: true },
dashboard: { exercise: true, community: true, bannerText: '', bannerImage: '' }
}
}
].filter((o) => !existingOrgIds.includes(o.id));
@@ -0,0 +1,28 @@
import { and, db, eq, organizationPlan } from '@db/drizzle';
export async function seedEnterpriseOrganizationPlan({ enterpriseOrgId }: { enterpriseOrgId: string }) {
const existing = await db
.select()
.from(organizationPlan)
.where(
and(
eq(organizationPlan.orgId, enterpriseOrgId),
eq(organizationPlan.planName, 'ENTERPRISE'),
eq(organizationPlan.isActive, true)
)
);
if (existing.length > 0) {
console.log(' ✓ Enterprise organization plan already exists, skipping');
return;
}
await db.insert(organizationPlan).values({
orgId: enterpriseOrgId,
planName: 'ENTERPRISE',
isActive: true,
subscriptionId: 'seed-coursera-test-enterprise',
provider: 'seed'
});
console.log(' ✓ Inserted enterprise organization plan');
}
@@ -3,14 +3,23 @@ import { db, organizationmember } from '@db/drizzle';
interface SeedOrganizationMember {
testOrgId: string;
adminUserId: string;
studentUserId: string;
enterpriseOrgId: string;
enterpriseAdminUserId: string;
enterpriseStudentUserId: string;
}
export async function seedOrganizationMember({ testOrgId, adminUserId }: SeedOrganizationMember) {
export async function seedOrganizationMember({
testOrgId,
adminUserId,
studentUserId,
enterpriseOrgId,
enterpriseAdminUserId,
enterpriseStudentUserId
}: SeedOrganizationMember) {
const existingOrgMembers = await db.select().from(organizationmember);
const existingOrgMemberKeys = existingOrgMembers.map((om) => `${om.organizationId}-${om.profileId}`);
const studentUserId = '0c256e75-aa40-4f62-8d30-0217ca1c60d9';
const orgMembersToInsert = [
{
organizationId: testOrgId,
@@ -23,6 +32,18 @@ export async function seedOrganizationMember({ testOrgId, adminUserId }: SeedOrg
roleId: 3, // STUDENT
profileId: studentUserId,
verified: false
},
{
organizationId: enterpriseOrgId,
roleId: 1, // ADMIN
profileId: enterpriseAdminUserId,
verified: false
},
{
organizationId: enterpriseOrgId,
roleId: 3, // STUDENT
profileId: enterpriseStudentUserId,
verified: false
}
].filter((om) => !existingOrgMemberKeys.includes(`${om.organizationId}-${om.profileId}`));