Database: time_entries, billing_rates, invoices tables with RLS.
Backend: CRUD services+handlers for time entries, billing rates, invoices.
- Time entries: list/create/update/delete, summary by case/user/month
- Billing rates: upsert with auto-close previous, current rate lookup
- Invoices: create with auto-number (RE-YYYY-NNN), status transitions
(draft->sent->paid, cancellation), link time entries on invoice create
API: 11 new endpoints under /api/time-entries, /api/billing-rates, /api/invoices
Frontend: Zeiterfassung tab on case detail, /abrechnung overview with filters,
/abrechnung/rechnungen list+detail with status actions, billing rates settings
Also: resolved merge conflicts between audit-trail and role-based branches,
added missing types (Notification, AuditLogResponse, NotificationPreferences)
65 lines
1.5 KiB
Go
65 lines
1.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const (
|
|
userIDKey contextKey = "user_id"
|
|
tenantIDKey contextKey = "tenant_id"
|
|
userRoleKey contextKey = "user_role"
|
|
ipKey contextKey = "ip_address"
|
|
userAgentKey contextKey = "user_agent"
|
|
)
|
|
|
|
func ContextWithUserID(ctx context.Context, userID uuid.UUID) context.Context {
|
|
return context.WithValue(ctx, userIDKey, userID)
|
|
}
|
|
|
|
func ContextWithTenantID(ctx context.Context, tenantID uuid.UUID) context.Context {
|
|
return context.WithValue(ctx, tenantIDKey, tenantID)
|
|
}
|
|
|
|
func UserFromContext(ctx context.Context) (uuid.UUID, bool) {
|
|
id, ok := ctx.Value(userIDKey).(uuid.UUID)
|
|
return id, ok
|
|
}
|
|
|
|
func TenantFromContext(ctx context.Context) (uuid.UUID, bool) {
|
|
id, ok := ctx.Value(tenantIDKey).(uuid.UUID)
|
|
return id, ok
|
|
}
|
|
|
|
func ContextWithUserRole(ctx context.Context, role string) context.Context {
|
|
return context.WithValue(ctx, userRoleKey, role)
|
|
}
|
|
|
|
func UserRoleFromContext(ctx context.Context) string {
|
|
role, _ := ctx.Value(userRoleKey).(string)
|
|
return role
|
|
}
|
|
|
|
func ContextWithRequestInfo(ctx context.Context, ip, userAgent string) context.Context {
|
|
ctx = context.WithValue(ctx, ipKey, ip)
|
|
ctx = context.WithValue(ctx, userAgentKey, userAgent)
|
|
return ctx
|
|
}
|
|
|
|
func IPFromContext(ctx context.Context) *string {
|
|
if v, ok := ctx.Value(ipKey).(string); ok && v != "" {
|
|
return &v
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UserAgentFromContext(ctx context.Context) *string {
|
|
if v, ok := ctx.Value(userAgentKey).(string); ok && v != "" {
|
|
return &v
|
|
}
|
|
return nil
|
|
}
|