Repository navigation
Conversation
…are to real token validation
Kaushik4141
left a comment
There was a problem hiding this comment.
revert all the changes in web and packages/db folders
| id: string | ||
| fullName: string | null | ||
| email: string | ||
| role: 'student' | 'recruiter' | 'admin' |
There was a problem hiding this comment.
check userRoleEnum in packages/db/src/schema/enums.ts we have student | recruiter | core_admin | club_admin
| * - 403 if the user exists but is not a student. | ||
| * On success, sets `user` on the context for downstream handlers. | ||
| */ | ||
| export function requireStudentAuth() { |
There was a problem hiding this comment.
suggestion: keep requireAuth as the only JWT verifier, and for the student check add a secound middleware just to role check and pass both on the router
e.g: studentRouter.use('*' , requireAuth, requireStudentRole)
basically requireStudentRole should only check the role
| }>(async (c, next) => { | ||
| const bindings = env(c) | ||
| const db = createDb(bindings.DATABASE_URL) | ||
| const db = await getDbClient(bindings) |
There was a problem hiding this comment.
revert these changes and delete apps/api/src/db.ts
here the line above does exact same thing what getDBCliet is doing
There was a problem hiding this comment.
revert this file
we don's use aws-sdk/client-s3 , @aws-sdk/s3-request-presigner, or dotenv anywhere
| "main": "src/index.ts", | ||
| "compatibility_date": "2026-08-08", | ||
| "compatibility_flags": [ | ||
| "nodejs_compat" |
There was a problem hiding this comment.
revert this change
adding nodejs_compact would removes the serverless feature of workers
workers don't run on node.js they run on v8 isolates
There was a problem hiding this comment.
@mimionly don't remove nodejs_compact but can i know why are u using it ?
There was a problem hiding this comment.
Good work @mimionly but general comment, this PR touches so many things. It is touching frontend, some part of backend, then adding some migration scripts, and adding some packages somewhere.
Please create PRs for a one particular task, you can create 10s of small PR than 1 big one, it becomes easy to review and deploy
| if (profile.fullName && profile.fullName.trim() !== '') percentage += 15 | ||
| if (profile.headline && profile.headline.trim() !== '') percentage += 15 | ||
| if (profile.bio && profile.bio.trim() !== '') percentage += 15 | ||
| if (profile.gradYear !== null && profile.gradYear !== undefined) percentage += 15 | ||
| if (profile.phone && profile.phone.trim() !== '') percentage += 10 | ||
| if (profile.resumeUrl && profile.resumeUrl.trim() !== '') percentage += 15 | ||
| if (profile.githubUrl && profile.githubUrl.trim() !== '') percentage += 10 | ||
| if (profile.linkedinUrl && profile.linkedinUrl.trim() !== '') percentage += 5 |
There was a problem hiding this comment.
There should be a better way of doing this, create a map, and assign the keys with some points, check which and all keys exist and add up the respective points.
This will get weird in the long run.
| export function calculateCompletionPercentage(profile: { | ||
| fullName?: string | null | ||
| headline?: string | null | ||
| bio?: string | null | ||
| gradYear?: number | null | ||
| phone?: string | null | ||
| resumeUrl?: string | null | ||
| githubUrl?: string | null | ||
| linkedinUrl?: string | null | ||
| }): number { |
| .values({ | ||
| userId, | ||
| headline: null, | ||
| bio: null, | ||
| gradYear: null, | ||
| openToWork: false, | ||
| resumeUrl: null, | ||
| githubUrl: null, | ||
| linkedinUrl: null, | ||
| otherLinks: null, | ||
| dk24Status: 'none', | ||
| }) |
There was a problem hiding this comment.
Can u put this in a object called initialValues
so u can just reference it here
| let experienceRole: string | null = null | ||
| let experienceCompany: string | null = null | ||
| let experienceSummary: string | null = null | ||
|
|
||
| const dbExperience = dbExperiences[0] | ||
| if (dbExperience) { | ||
| experienceRole = dbExperience.role || null | ||
| experienceCompany = dbExperience.companyName || null | ||
| experienceSummary = dbExperience.contributions || null | ||
| } | ||
|
|
||
| // 5. Extract education details from otherLinks | ||
| let school: string | null = null | ||
| let degree: string | null = null | ||
| let gpa: string | null = null | ||
| let specialization: string | null = null | ||
| let portfolioUrl: string | null = null |
There was a problem hiding this comment.
why are we defining variables for each key, use object destructuring
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring
| body: UpdateProfilePayload, | ||
| ) { | ||
| // Update using db client directly (neon-http driver does not support transactions) | ||
| const tx = db |
There was a problem hiding this comment.
why? cant we just use it as db? @Kaushik4141 this needs to be consistent all across
if one function uses tx and other uses db it will get confusing
There was a problem hiding this comment.
why? cant we just use it as
db? @Kaushik4141 this needs to be consistent all acrossif one function uses
txand other usesdbit will get confusing
here this is not a transaction so here we can use db itself
but should we use db itself even when it is transaction
…e with userRoleEnum
Student Profile API & System Documentation
Base URL
http://localhost:8787Authentication & Authorization
All student endpoints require a valid Bearer JWT issued by Neon Auth:
Authorization: Bearer <token>student.401 Unauthorized403 Forbidden1. Get Student Profile
Retrieves the complete profile for the authenticated student. If a profile or contact record does not yet exist for this user, it is auto-initialized with defaults.
GET /api/student/profilestudent)Example Request
Response Format (
200 OK){ "id": "11111111-1111-4111-8111-111111111111", "email": "ada@example.com", "fullName": "Ada Lovelace", "headline": "Full-Stack Software Engineer & CS Student", "bio": "Passionate about distributed systems and modern web apps.", "gradYear": 2026, "openToWork": true, "phone": "+1 (555) 019-2834", "resumeUrl": "https://example.com/resumes/ada.pdf", "githubUrl": "https://github.com/ada", "linkedinUrl": "https://linkedin.com/in/ada", "portfolioUrl": "https://ada.dev", "dk24Status": "none", "completionPercentage": 100, "skills": ["TypeScript", "React", "Node.js", "PostgreSQL"], "school": "University of Technology", "degree": "B.S. in Computer Science", "gpa": "3.9", "specialization": "Software Engineering", "experienceRole": "Software Engineer Intern", "experienceCompany": "Acme Corp", "experienceSummary": "Built full-stack features with Next.js and Hono.", "otherLinks": { "school": "University of Technology", "degree": "B.S. in Computer Science", "gpa": "3.9", "specialization": "Software Engineering", "portfolioUrl": "https://ada.dev" } }2. Update Student Profile
Updates the authenticated student's profile across all normalized tables (
users,student_profiles,contact_details,skills,experience), recalculates the completion score, and returns the updated profile object.PUT /api/student/profilestudent)Content-Type: application/jsonBody Parameters (All Optional)
fullNamestringheadlinestring | nullbiostring | nullgradYearnumber | null1900and2100).openToWorkbooleanphonestring | nullresumeUrlstring | nullgithubUrlstring | nulllinkedinUrlstring | nullportfolioUrlstring | nullskillsstring[]["React", "Node.js"]). Duplicates are deduplicated.schoolstring | nulldegreestring | nullgpastring | nullspecializationstring | nullexperienceRolestring | nullexperienceCompanystring | nullexperienceSummarystring | nullotherLinksobject | nullExample Request
Response Format (
200 OK)Returns the same shape as
GET /api/student/profilewith all updated values and newcompletionPercentage.3. Profile Completion Score Calculation
The API computes a weighted completion score (0% to 100%):
fullNameheadlinebiogradYearresumeUrlphonegithubUrllinkedinUrl4. Error Handling & Status Codes
400 Bad RequestgradYear, emptyfullName, or invalidskillsarray.{"error": "Validation Error", "message": "gradYear must be a valid year number."}400 Bad Request{"error": "Bad Request", "message": "Invalid JSON payload."}401 Unauthorized{"error": "Unauthorized", "message": "Missing or invalid token."}403 Forbiddenstudent.{"error": "Forbidden", "message": "Requires student role."}404 Not Found{"error": "Not Found", "message": "Student account not found."}500 Internal Server Error{"error": "Internal Server Error", "message": "Unable to load profile right now."}5. Frontend Flow (
apps/web)apps/web/app/(onboarding)/student/page.tsxcallsGET /api/student/profile.fullName,headline, andschoolare present), the UI automatically switches into Dashboard Mode.localStorage.getItem('student_profile').