diff --git a/app/challenges-platform/services/accesible-challenges-service.ts b/app/challenges-platform/services/accesible-challenges-service.ts new file mode 100644 index 0000000..afeb5d7 --- /dev/null +++ b/app/challenges-platform/services/accesible-challenges-service.ts @@ -0,0 +1,24 @@ +import { accessibleChallenges } from "../../../db/schema"; +import { Ok, Result } from "ts-results"; +import { eq } from "drizzle-orm"; +import { db } from "../../../db"; +import { Challenge, Participant } from "../models"; + +export const count = async ( + challenge: Challenge, + participant: Participant, +): Promise> => { + const accessibleChallengesResult = await db + .select({ + pId: accessibleChallenges.participantId, + cId: accessibleChallenges.challengeId, + }) + .from(accessibleChallenges) + .where( + eq(accessibleChallenges.participantId, participant.id) && + eq(accessibleChallenges.challengeId, challenge.id), + ) + .execute(); + + return Ok(accessibleChallengesResult.length); +}; diff --git a/app/challenges-platform/services/index.ts b/app/challenges-platform/services/index.ts index 11b5ac8..ff88acb 100644 --- a/app/challenges-platform/services/index.ts +++ b/app/challenges-platform/services/index.ts @@ -1,3 +1,4 @@ +export * as AccesibleChallengesService from "./accesible-challenges-service"; export * as ChallengesService from "./challenges-service"; export * as ParticipantsService from "./participants-service"; export * as ReviewsService from "./reviews-service"; diff --git a/app/challenges-platform/services/submissions-service.ts b/app/challenges-platform/services/submissions-service.ts index 223aaf1..927e1eb 100644 --- a/app/challenges-platform/services/submissions-service.ts +++ b/app/challenges-platform/services/submissions-service.ts @@ -1,11 +1,14 @@ import { Ok, Err, Result } from "ts-results"; import { db } from "../../../db"; -import { submissions, accessibleChallenges, participants } from "../../../db/schema"; +import { submissions } from "../../../db/schema"; import { uuid } from "../../../app/common"; -import { Submission } from "../models"; -import { ChallengesService, ParticipantsService } from "../services"; +import { Challenge, Participant, Submission } from "../models"; +import { + AccesibleChallengesService, + ChallengesService, + ParticipantsService, +} from "../services"; import { challengesPlatform } from ".."; -import { eq } from "drizzle-orm"; export const create = async ( challengeId: string, @@ -13,25 +16,10 @@ export const create = async ( type: string = "base", metadata?: any, ): Promise> => { - const challengeResult = await ChallengesService.findByUuid(challengeId); - if (!challengeResult.ok) { - return Err(new Error("Failed to find challenge")); - } - const participantResult = await ParticipantsService.findByUuid(participantId); - if (!participantResult.ok) { - return Err(new Error("Failed to find participant")); - } - - const accessibleChallengesResult = await db - .select({pId: accessibleChallenges.participantId,cId: accessibleChallenges.challengeId}) - .from(accessibleChallenges) - .where(eq(accessibleChallenges.participantId, participantResult.val.id) && eq(accessibleChallenges.challengeId, challengeResult.val.id)) - .execute(); - - if (accessibleChallengesResult.length === 0) { - return Err(new Error("Participant is not allowed to submit this challenge" )); - } + const result = await beforeCreate(challengeId, participantId); + if (!result.ok) return result; + const [challenge, participant] = result.val; // TODO: switch on submission.challenge.evaluation // if submission.challenge.evaluation is MANUAL, than save it to the database @@ -52,18 +40,51 @@ export const create = async ( .insert(submissions) .values({ uuid: id.toString(), - challengeId: challengeResult.val.id, - participantId: participantResult.val.id, + challengeId: challenge.id, + participantId: participant.id, }) .returning(); const submission = transformer.newSubmission( result[0], - challengeResult.val, - participantResult.val, + challenge, + participant, ); return Ok(submission); } catch (e) { return Err(new Error("Failed to create submission")); } }; + +// private +const beforeCreate = async ( + challengeId: string, + participantId: string, +): Promise> => { + const challengeResult = await ChallengesService.findByUuid(challengeId); + if (!challengeResult.ok) { + return Err(new Error("Failed to find challenge")); + } + + const participantResult = await ParticipantsService.findByUuid(participantId); + if (!participantResult.ok) { + return Err(new Error("Failed to find participant")); + } + + const countResult = await AccesibleChallengesService.count( + challengeResult.val, + participantResult.val, + ); + if (!countResult.ok) { + return Err(new Error("Failed to count accessible challenges")); + } + + const count = countResult.val; + if (count === 0) { + return Err( + new Error("Participant is not allowed to submit this challenge"), + ); + } + + return Ok([challengeResult.val, participantResult.val]); +}; diff --git a/db/schema.ts b/db/schema.ts index 4ada70f..ceba0e9 100644 --- a/db/schema.ts +++ b/db/schema.ts @@ -19,7 +19,7 @@ export const accessibleChallenges = sqliteTable("accessible_challenges", { participantId: integer("participant_id").references(() => participants.id), createdAt: text("created_at").default(sql`CURRENT_TIMESTAMP`), updatedAt: text("updated_at").default(sql`CURRENT_TIMESTAMP`), -}) +}); export const participants = sqliteTable("participants", { id: integer("id").primaryKey(), @@ -48,4 +48,3 @@ export const reviews = sqliteTable("reviews", { createdAt: text("created_at").default(sql`CURRENT_TIMESTAMP`), updatedAt: text("updated_at").default(sql`CURRENT_TIMESTAMP`), }); - diff --git a/test/challenges-platform/services/submissions-service.test.ts b/test/challenges-platform/services/submissions-service.test.ts index 0788d86..25508b5 100644 --- a/test/challenges-platform/services/submissions-service.test.ts +++ b/test/challenges-platform/services/submissions-service.test.ts @@ -13,7 +13,7 @@ describe("SubmissionService", () => { challenge.uuid, participant.uuid, ); - + if (!result.ok) fail("Expected result to be Ok"); expect(result.val.challenge.id).toBe(challenge.id); expect(result.val.participant.id).toBe(participant.id); @@ -46,4 +46,4 @@ describe("SubmissionService", () => { }); }); }); -}); \ No newline at end of file +});