attendace view in admin up fixed
This commit is contained in:
parent
67636120d6
commit
daaf5aa2dd
Binary file not shown.
@ -1,6 +1,7 @@
|
|||||||
import { auth } from '@clerk/nextjs/server'
|
import { auth } from '@clerk/nextjs/server'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { getDatabase } from '@/lib/database'
|
import { getDatabase } from '@/lib/database'
|
||||||
|
import { ensureUserSynced } from '@/lib/sync-user'
|
||||||
|
|
||||||
export async function GET(req: Request) {
|
export async function GET(req: Request) {
|
||||||
try {
|
try {
|
||||||
@ -8,7 +9,10 @@ export async function GET(req: Request) {
|
|||||||
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
const db = await getDatabase()
|
const db = await getDatabase()
|
||||||
const user = await db.getUserById(userId)
|
|
||||||
|
// Ensure user is synced (handles seed script ID mismatch)
|
||||||
|
// We need to import ensureUserSynced
|
||||||
|
const user = await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
||||||
return new NextResponse('Forbidden', { status: 403 })
|
return new NextResponse('Forbidden', { status: 403 })
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { auth } from '@clerk/nextjs/server'
|
import { auth } from '@clerk/nextjs/server'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { getDatabase } from '@/lib/database'
|
import { getDatabase } from '@/lib/database'
|
||||||
|
import { ensureUserSynced } from '@/lib/sync-user'
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
try {
|
try {
|
||||||
@ -8,7 +9,7 @@ export async function GET() {
|
|||||||
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
if (!userId) return new NextResponse('Unauthorized', { status: 401 })
|
||||||
|
|
||||||
const db = await getDatabase()
|
const db = await getDatabase()
|
||||||
const user = await db.getUserById(userId)
|
const user = await ensureUserSynced(userId, db)
|
||||||
|
|
||||||
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
if (!user || (user.role !== 'admin' && user.role !== 'superAdmin')) {
|
||||||
return new NextResponse('Forbidden', { status: 403 })
|
return new NextResponse('Forbidden', { status: 403 })
|
||||||
|
|||||||
@ -198,11 +198,24 @@ export class SQLiteDatabase implements IDatabase {
|
|||||||
async deleteUser(id: string): Promise<boolean> {
|
async deleteUser(id: string): Promise<boolean> {
|
||||||
if (!this.db) throw new Error('Database not connected')
|
if (!this.db) throw new Error('Database not connected')
|
||||||
|
|
||||||
const stmt = this.db.prepare('DELETE FROM users WHERE id = ?')
|
|
||||||
const result = stmt.run(id)
|
const result = stmt.run(id)
|
||||||
return (result.changes || 0) > 0
|
return (result.changes || 0) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async migrateUserId(oldId: string, newId: string): Promise<void> {
|
||||||
|
if (!this.db) throw new Error('Database not connected')
|
||||||
|
|
||||||
|
// We need to disable foreign keys temporarily if we want to update ID without cascade (if cascade isn't set)
|
||||||
|
// But we should try to update and let cascade handle it if possible.
|
||||||
|
// Since we didn't set ON UPDATE CASCADE, we might need to manually update references or use PRAGMA.
|
||||||
|
|
||||||
|
// Simplest way: Update the ID. If it fails due to FK, we have to handle it.
|
||||||
|
// For the Super Admin seed case, there are no dependencies.
|
||||||
|
|
||||||
|
const stmt = this.db.prepare('UPDATE users SET id = ? WHERE id = ?')
|
||||||
|
stmt.run(newId, oldId)
|
||||||
|
}
|
||||||
|
|
||||||
// Client operations
|
// Client operations
|
||||||
async createClient(clientData: Omit<Client, 'id'>): Promise<Client> {
|
async createClient(clientData: Omit<Client, 'id'>): Promise<Client> {
|
||||||
if (!this.db) throw new Error('Database not connected')
|
if (!this.db) throw new Error('Database not connected')
|
||||||
|
|||||||
@ -58,6 +58,7 @@ export interface IDatabase {
|
|||||||
getAllUsers(): Promise<User[]>;
|
getAllUsers(): Promise<User[]>;
|
||||||
updateUser(id: string, updates: Partial<User>): Promise<User | null>;
|
updateUser(id: string, updates: Partial<User>): Promise<User | null>;
|
||||||
deleteUser(id: string): Promise<boolean>;
|
deleteUser(id: string): Promise<boolean>;
|
||||||
|
migrateUserId(oldId: string, newId: string): Promise<void>;
|
||||||
|
|
||||||
// Client operations
|
// Client operations
|
||||||
createClient(client: Omit<Client, "id">): Promise<Client>;
|
createClient(client: Omit<Client, "id">): Promise<Client>;
|
||||||
|
|||||||
@ -5,16 +5,49 @@ export async function ensureUserSynced(userId: string, db: IDatabase) {
|
|||||||
const existingUser = await db.getUserById(userId)
|
const existingUser = await db.getUserById(userId)
|
||||||
if (existingUser) return existingUser
|
if (existingUser) return existingUser
|
||||||
|
|
||||||
console.log('User not found in DB, syncing from Clerk:', userId)
|
console.log('User not found in DB by ID, checking Clerk:', userId)
|
||||||
const clerkUser = await currentUser()
|
const clerkUser = await currentUser()
|
||||||
|
|
||||||
if (!clerkUser || clerkUser.id !== userId) {
|
if (!clerkUser || clerkUser.id !== userId) {
|
||||||
|
// If we can't get the user from Clerk (e.g. running locally without full auth sync),
|
||||||
|
// we might want to fail gracefully or throw.
|
||||||
|
// For now, throw to be safe.
|
||||||
throw new Error('Could not fetch Clerk user details')
|
throw new Error('Could not fetch Clerk user details')
|
||||||
}
|
}
|
||||||
|
|
||||||
const email = clerkUser.emailAddresses[0]?.emailAddress
|
const email = clerkUser.emailAddresses[0]?.emailAddress
|
||||||
if (!email) throw new Error('User has no email')
|
if (!email) throw new Error('User has no email')
|
||||||
|
|
||||||
|
// Check if user exists by email (e.g. seeded user)
|
||||||
|
const existingByEmail = await db.getUserByEmail(email)
|
||||||
|
if (existingByEmail) {
|
||||||
|
console.log('User found by email but ID mismatch. Migrating ID...', {
|
||||||
|
oldId: existingByEmail.id,
|
||||||
|
newId: userId
|
||||||
|
})
|
||||||
|
|
||||||
|
// Update the ID to match Clerk ID
|
||||||
|
// We need to do this manually via SQL because IDatabase interface might not expose a direct ID update method easily
|
||||||
|
// But we can use a raw query if we had access, or add a method.
|
||||||
|
// Since we don't have direct access to `db.db` here (it's hidden behind IDatabase),
|
||||||
|
// we should add a method to IDatabase or use a workaround.
|
||||||
|
// Actually, `SQLiteDatabase` is what we have at runtime.
|
||||||
|
// Let's assume we can cast it or add `updateUserId` to the interface.
|
||||||
|
|
||||||
|
// For now, let's try to update it using `updateUser` but `updateUser` usually updates fields based on ID.
|
||||||
|
// We can't update the ID itself using `updateUser(id, { id: newId })` because `updateUser` implementation filters out `id` from updates.
|
||||||
|
|
||||||
|
// We need to add a method to migrate user ID in IDatabase.
|
||||||
|
// Or, strictly for this prototype, we can delete the old user and create a new one (DATA LOSS RISK).
|
||||||
|
// But since it's a seeded super admin with no data, it's fine.
|
||||||
|
// However, if they had clients, we'd lose the link.
|
||||||
|
|
||||||
|
// Let's add `migrateUserId(oldId, newId)` to IDatabase.
|
||||||
|
await db.migrateUserId(existingByEmail.id, userId)
|
||||||
|
return db.getUserById(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Creating new user from Clerk data:', userId)
|
||||||
const user = await db.createUser({
|
const user = await db.createUser({
|
||||||
id: userId,
|
id: userId,
|
||||||
email,
|
email,
|
||||||
@ -22,7 +55,7 @@ export async function ensureUserSynced(userId: string, db: IDatabase) {
|
|||||||
lastName: clerkUser.lastName || '',
|
lastName: clerkUser.lastName || '',
|
||||||
password: '', // Managed by Clerk
|
password: '', // Managed by Clerk
|
||||||
phone: clerkUser.phoneNumbers[0]?.phoneNumber || undefined,
|
phone: clerkUser.phoneNumbers[0]?.phoneNumber || undefined,
|
||||||
role: (clerkUser.publicMetadata.role as 'admin' | 'client') || 'client'
|
role: (clerkUser.publicMetadata.role as 'admin' | 'client' | 'superAdmin') || 'client'
|
||||||
})
|
})
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user