Redone
This commit is contained in:
@@ -1,108 +0,0 @@
|
||||
import { FastifyInstance } from "fastify";
|
||||
|
||||
export default async function userRoutes(server: FastifyInstance) {
|
||||
//TODO: PERMISSIONS Rückmeldung beschränken
|
||||
|
||||
server.get("/user/:id", async (req, reply) => {
|
||||
const authUser = req.user // kommt aus JWT (user_id + tenant_id)
|
||||
|
||||
const { id } = req.params as { id?: string }
|
||||
|
||||
if (!authUser) {
|
||||
return reply.code(401).send({ error: "Unauthorized" })
|
||||
}
|
||||
|
||||
|
||||
// 1. User laden
|
||||
const { data: user, error: userError } = await server.supabase
|
||||
.from("auth_users")
|
||||
.select("id, email, created_at, must_change_password")
|
||||
.eq("id", id)
|
||||
.single()
|
||||
|
||||
if (userError || !user) {
|
||||
return reply.code(401).send({ error: "User not found" })
|
||||
}
|
||||
|
||||
// 2. Tenants laden (alle Tenants des Users)
|
||||
/*const { data: tenantLinks, error: tenantLinksError } = await server.supabase
|
||||
.from("auth_users")
|
||||
.select(`*, tenants!auth_tenant_users ( id, name, locked )`)
|
||||
.eq("id", authUser.user_id)
|
||||
.single();
|
||||
|
||||
if (tenantLinksError) {
|
||||
|
||||
console.log(tenantLinksError)
|
||||
|
||||
return reply.code(401).send({ error: "Tenant Error" })
|
||||
}
|
||||
|
||||
const tenants = tenantLinks?.tenants*/
|
||||
|
||||
// 3. Aktiven Tenant bestimmen
|
||||
const activeTenant = authUser.tenant_id /*|| tenants[0].id*/
|
||||
|
||||
// 4. Profil für den aktiven Tenant laden
|
||||
let profile = null
|
||||
if (activeTenant) {
|
||||
const { data: profileData } = await server.supabase
|
||||
.from("auth_profiles")
|
||||
.select("*")
|
||||
.eq("user_id", id)
|
||||
.eq("tenant_id", activeTenant)
|
||||
.single()
|
||||
|
||||
profile = profileData
|
||||
}
|
||||
|
||||
// 5. Permissions laden (über Funktion)
|
||||
|
||||
// 6. Response zurückgeben
|
||||
return {
|
||||
user,
|
||||
profile,
|
||||
}
|
||||
})
|
||||
|
||||
server.put("/user/:id/profile", async (req, reply) => {
|
||||
|
||||
const { id } = req.params as { id?: string }
|
||||
|
||||
const { data } = req.body as { data?: object }
|
||||
|
||||
// 4. Profil für den aktiven Tenant laden
|
||||
let profile = null
|
||||
if (req.user.tenant_id) {
|
||||
const { data: profileData } = await server.supabase
|
||||
.from("auth_profiles")
|
||||
.select("*")
|
||||
.eq("user_id", req.user.user_id)
|
||||
.eq("tenant_id", req.user.tenant_id)
|
||||
.single()
|
||||
|
||||
profile = profileData
|
||||
}
|
||||
|
||||
console.log(data)
|
||||
|
||||
//Update Profile
|
||||
const { data: updatedProfileData, error: updateError } = await server.supabase
|
||||
.from("auth_profiles")
|
||||
.update(data)
|
||||
.eq("user_id", id)
|
||||
.eq("id", profile?.id)
|
||||
.select("*")
|
||||
.single()
|
||||
|
||||
console.log(updateError)
|
||||
console.log(updatedProfileData)
|
||||
|
||||
// 5. Permissions laden (über Funktion)
|
||||
|
||||
// 6. Response zurückgeben
|
||||
return {
|
||||
data,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,143 +1,173 @@
|
||||
import { FastifyInstance } from 'fastify'
|
||||
import { StaffTimeEntry } from '../../types/staff'
|
||||
import { FastifyInstance } from "fastify"
|
||||
import {
|
||||
stafftimeentries,
|
||||
stafftimenetryconnects
|
||||
} from "../../../db/schema"
|
||||
import {
|
||||
eq,
|
||||
and,
|
||||
gte,
|
||||
lte,
|
||||
desc
|
||||
} from "drizzle-orm"
|
||||
|
||||
export default async function staffTimeRoutes(server: FastifyInstance) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Neue Zeit starten
|
||||
server.post(
|
||||
'/staff/time',
|
||||
async (req, reply) => {
|
||||
const { started_at, stopped_at, type = 'work', description, user_id } = req.body as any
|
||||
// -------------------------------------------------------------
|
||||
server.post("/staff/time", async (req, reply) => {
|
||||
try {
|
||||
const { user_id, ...rest } = req.body as any
|
||||
const userId = req.user.user_id
|
||||
const tenantId = req.user.tenant_id
|
||||
|
||||
|
||||
let dataToInsert = {
|
||||
const newEntry = {
|
||||
tenant_id: tenantId,
|
||||
user_id: user_id ? user_id : userId,
|
||||
// @ts-ignore
|
||||
...req.body
|
||||
user_id: user_id || userId,
|
||||
...rest
|
||||
}
|
||||
|
||||
const { data, error } = await server.supabase
|
||||
.from('staff_time_entries')
|
||||
.insert([dataToInsert])
|
||||
.select()
|
||||
.maybeSingle()
|
||||
const [created] = await server.db
|
||||
.insert(stafftimeentries)
|
||||
.values(newEntry)
|
||||
.returning()
|
||||
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
return reply.send(data)
|
||||
return created
|
||||
} catch (err: any) {
|
||||
console.error(err)
|
||||
return reply.code(400).send({ error: err.message })
|
||||
}
|
||||
)
|
||||
|
||||
// ▶ Zeit stoppen
|
||||
server.put<{ Params: { id: string }, Body: { stopped_at: string } }>(
|
||||
'/staff/time/:id/stop',
|
||||
async (req, reply) => {
|
||||
const { id } = req.params
|
||||
const { stopped_at } = req.body
|
||||
|
||||
const { data, error } = await server.supabase
|
||||
.from('staff_time_entries')
|
||||
.update({ stopped_at, updated_at: new Date().toISOString() })
|
||||
.eq('id', id)
|
||||
.select()
|
||||
.maybeSingle()
|
||||
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
return reply.send(data)
|
||||
}
|
||||
)
|
||||
|
||||
// ▶ Liste aller Zeiten
|
||||
server.get<{
|
||||
Querystring: {
|
||||
from?: string
|
||||
to?: string
|
||||
type?: string
|
||||
user_id?: string
|
||||
}
|
||||
}>('/staff/time', async (req, reply) => {
|
||||
const { from, to, type, user_id } = req.query
|
||||
const { user_id: currentUserId, tenant_id } = req.user
|
||||
|
||||
// 🧩 Basis-Query für den Tenant
|
||||
let query = server.supabase
|
||||
.from('staff_time_entries')
|
||||
.select('*')
|
||||
.eq('tenant_id', tenant_id)
|
||||
.order('started_at', { ascending: false })
|
||||
|
||||
// 🔒 Zugriffsbeschränkung: nur eigene Zeiten, außer Berechtigung erlaubt mehr
|
||||
if (!req.hasPermission('staff.time.read_all')) {
|
||||
query = query.eq('user_id', currentUserId)
|
||||
} else if (user_id) {
|
||||
// falls explizit user_id angegeben wurde
|
||||
query = query.eq('user_id', user_id)
|
||||
}
|
||||
|
||||
// 📅 Zeitfilter
|
||||
if (from) query = query.gte('started_at', from)
|
||||
if (to) query = query.lte('started_at', to)
|
||||
if (type) query = query.eq('type', type)
|
||||
|
||||
const { data, error } = await query
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
|
||||
return reply.send(data)
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Zeit stoppen
|
||||
// -------------------------------------------------------------
|
||||
server.put("/staff/time/:id/stop", async (req, reply) => {
|
||||
try {
|
||||
const { id } = req.params as any
|
||||
const { stopped_at } = req.body as any
|
||||
|
||||
// ▶ Einzelne Zeit abrufen (inkl. Connects)
|
||||
server.get<{ Params: { id: string } }>(
|
||||
'/staff/time/:id',
|
||||
async (req, reply) => {
|
||||
const { id } = req.params
|
||||
const [updated] = await server.db
|
||||
.update(stafftimeentries)
|
||||
.set({
|
||||
stopped_at,
|
||||
updated_at: new Date()
|
||||
})
|
||||
.where(eq(stafftimeentries.id, id))
|
||||
.returning()
|
||||
|
||||
const { data, error } = await server.supabase
|
||||
.from('staff_time_entries')
|
||||
.select(`
|
||||
*,
|
||||
staff_time_entry_connects(*)
|
||||
`)
|
||||
.eq('id', id)
|
||||
.maybeSingle()
|
||||
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
return reply.send(data)
|
||||
return updated
|
||||
} catch (err) {
|
||||
return reply.code(400).send({ error: (err as Error).message })
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// ▶ Zeit bearbeiten
|
||||
server.put<{ Params: { id: string }, Body: Partial<StaffTimeEntry> }>(
|
||||
'/staff/time/:id',
|
||||
async (req, reply) => {
|
||||
const { id } = req.params
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Liste aller Zeiten
|
||||
// -------------------------------------------------------------
|
||||
server.get("/staff/time", async (req, reply) => {
|
||||
try {
|
||||
const { from, to, type, user_id } = req.query as any
|
||||
const { tenant_id, user_id: currentUserId } = req.user
|
||||
|
||||
const { data, error } = await server.supabase
|
||||
.from('staff_time_entries')
|
||||
.update({ ...req.body, updated_at: new Date().toISOString() })
|
||||
.eq('id', id)
|
||||
let where = and(eq(stafftimeentries.tenant_id, tenant_id))
|
||||
|
||||
// Zugriffsbeschränkung
|
||||
if (!req.hasPermission("staff.time.read_all")) {
|
||||
where = and(where, eq(stafftimeentries.user_id, currentUserId))
|
||||
} else if (user_id) {
|
||||
where = and(where, eq(stafftimeentries.user_id, user_id))
|
||||
}
|
||||
|
||||
if (from) where = and(where, gte(stafftimeentries.started_at, from))
|
||||
if (to) where = and(where, lte(stafftimeentries.started_at, to))
|
||||
if (type) where = and(where, eq(stafftimeentries.type, type))
|
||||
|
||||
const rows = await server.db
|
||||
.select()
|
||||
.maybeSingle()
|
||||
.from(stafftimeentries)
|
||||
.where(where)
|
||||
.orderBy(desc(stafftimeentries.started_at))
|
||||
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
return reply.send(data)
|
||||
return rows
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
return reply.code(400).send({ error: (err as Error).message })
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Einzelne Zeit (inkl. Connects)
|
||||
// -------------------------------------------------------------
|
||||
server.get("/staff/time/:id", async (req, reply) => {
|
||||
try {
|
||||
const { id } = req.params as any
|
||||
|
||||
const rows = await server.db
|
||||
.select()
|
||||
.from(stafftimeentries)
|
||||
.where(eq(stafftimeentries.id, id))
|
||||
.limit(1)
|
||||
|
||||
if (!rows.length) return reply.code(404).send({ error: "Not found" })
|
||||
|
||||
const entry = rows[0]
|
||||
|
||||
const connects = await server.db
|
||||
.select()
|
||||
.from(stafftimenetryconnects)
|
||||
.where(eq(stafftimenetryconnects.stafftimeentry, id))
|
||||
|
||||
return {
|
||||
...entry,
|
||||
staff_time_entry_connects: connects
|
||||
}
|
||||
} catch (err) {
|
||||
return reply.code(400).send({ error: (err as Error).message })
|
||||
}
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Zeit bearbeiten
|
||||
// -------------------------------------------------------------
|
||||
server.put("/staff/time/:id", async (req, reply) => {
|
||||
try {
|
||||
const { id } = req.params as any
|
||||
|
||||
|
||||
const updateData = {
|
||||
// @ts-ignore
|
||||
...req.body,
|
||||
updated_at: new Date()
|
||||
}
|
||||
|
||||
const [updated] = await server.db
|
||||
.update(stafftimeentries)
|
||||
.set(updateData)
|
||||
.where(eq(stafftimeentries.id, id))
|
||||
.returning()
|
||||
|
||||
return updated
|
||||
} catch (err) {
|
||||
return reply.code(400).send({ error: (err as Error).message })
|
||||
}
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// ▶ Zeit löschen
|
||||
server.delete<{ Params: { id: string } }>(
|
||||
'/staff/time/:id',
|
||||
async (req, reply) => {
|
||||
const { id } = req.params
|
||||
const { error } = await server.supabase
|
||||
.from('staff_time_entries')
|
||||
.delete()
|
||||
.eq('id', id)
|
||||
// -------------------------------------------------------------
|
||||
server.delete("/staff/time/:id", async (req, reply) => {
|
||||
try {
|
||||
const { id } = req.params as any
|
||||
|
||||
if (error) return reply.code(400).send({ error: error.message })
|
||||
return reply.send({ success: true })
|
||||
await server.db
|
||||
.delete(stafftimeentries)
|
||||
.where(eq(stafftimeentries.id, id))
|
||||
|
||||
return { success: true }
|
||||
} catch (err) {
|
||||
return reply.code(400).send({ error: (err as Error).message })
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user