Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ jobs:
DATABASE_URL: postgresql://test:test@localhost:5432/test_db
REDIS_URL: redis://localhost:6379
JWT_SECRET: test-jwt-secret
GITHUB_CLIENT_ID: test-github-client-id
GITHUB_CLIENT_SECRET: test-github-client-secret
GITHUB_REDIRECT_URI: http://localhost:8080/api/v1/oauth/github/callback
FRONTEND_URL: http://localhost:3000
run: npm run test:coverage || true

frontend:
Expand Down
13 changes: 13 additions & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,16 @@ RATE_LIMIT_ADMIN_SUSTAINED_MAX=2000
# Strict limits for sensitive endpoints
RATE_LIMIT_LOGIN_BURST_MAX=5
RATE_LIMIT_REGISTER_BURST_MAX=3

# ------------------------------------------
# GitHub OAuth Configuration
# ------------------------------------------
# Register a GitHub OAuth App at: https://github.com/settings/developers
# Homepage URL: http://localhost:8080
# Authorization callback URL: http://localhost:8080/api/v1/oauth/github/callback
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"
GITHUB_REDIRECT_URI="http://localhost:8080/api/v1/oauth/github/callback"

# Frontend URL for redirect after OAuth
FRONTEND_URL="http://localhost:3000"
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-- AlterTable: Add GitHub OAuth fields to students table
ALTER TABLE "students" ADD COLUMN "githubId" INTEGER;
ALTER TABLE "students" ADD COLUMN "githubUsername" TEXT;
ALTER TABLE "students" ADD COLUMN "githubAvatarUrl" TEXT;
ALTER TABLE "students" ADD COLUMN "githubAccessToken" TEXT;

-- CreateIndex for githubId
CREATE UNIQUE INDEX "students_githubId_key" ON "students"("githubId");
CREATE INDEX "students_githubId_idx" ON "students"("githubId");

-- CreateTable: OAuthState for CSRF state management
CREATE TABLE "oauth_states" (
"id" TEXT NOT NULL,
"state" TEXT NOT NULL,
"provider" TEXT NOT NULL DEFAULT 'github',
"expiresAt" TIMESTAMP(3) NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"usedAt" TIMESTAMP(3),

CONSTRAINT "oauth_states_pkey" PRIMARY KEY ("id")
);

-- CreateIndex for OAuthState
CREATE UNIQUE INDEX "oauth_states_state_key" ON "oauth_states"("state");
CREATE INDEX "oauth_states_state_idx" ON "oauth_states"("state");
CREATE INDEX "oauth_states_expiresAt_idx" ON "oauth_states"("expiresAt");
48 changes: 33 additions & 15 deletions backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,46 @@ datasource db {
}

model Student {
id String @id @default(cuid())
workspaceId String @default("default")
email String @unique
did String? @unique
password String
firstName String
lastName String
walletAddress String? @unique
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

enrollments Enrollment[]
certificates Certificate[]
feedback Feedback[]
id String @id @default(cuid())
workspaceId String @default("default")
email String @unique
did String? @unique
password String
firstName String
lastName String
walletAddress String? @unique
githubId Int? @unique
githubUsername String?
githubAvatarUrl String?
githubAccessToken String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

enrollments Enrollment[]
certificates Certificate[]
feedback Feedback[]
learningProgress LearningProgress[]
canvases Canvas[]
canvases Canvas[]

@@map("students")
@@index([workspaceId, email])
@@index([firstName, lastName])
@@index([email])
@@index([createdAt])
@@index([githubId])
}

model OAuthState {
id String @id @default(cuid())
state String @unique
provider String @default("github")
expiresAt DateTime
createdAt DateTime @default(now())
usedAt DateTime?

@@map("oauth_states")
@@index([state])
@@index([expiresAt])
}

model Course {
Expand Down
Loading