Add private health tracker (owner-only)
- health schema: vaccinations, body_measurements, workouts, nutrition_daily, sleep (generated hours), medications, hair_progress, appointments - migration with updated_at triggers; grants to personal_app only - /trackers/health overview with add/edit/delete, owner-gated (404 otherwise), noindex + private no-store, hidden from listings for non-owners - owner-only JSON/CSV import endpoint and scripts/health-import.ts
This commit is contained in:
21
src/lib/server/owner.test.ts
Normal file
21
src/lib/server/owner.test.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { isOwner, isOwnerOnlyPath } from './owner';
|
||||
|
||||
const event = (user: Partial<NonNullable<App.Locals['user']>> | null) =>
|
||||
({ locals: { user, session: null } }) as unknown as { locals: App.Locals };
|
||||
|
||||
describe('owner gate', () => {
|
||||
it('needs admin role and the owner email', () => {
|
||||
expect(isOwner(event(null))).toBe(false);
|
||||
expect(isOwner(event({ role: 'admin', email: 'someone@example.com' }))).toBe(false);
|
||||
expect(isOwner(event({ role: 'user', email: 'stan@stanrunge.dev' }))).toBe(false);
|
||||
expect(isOwner(event({ role: 'admin', email: 'Stan@StanRunge.dev' }))).toBe(true);
|
||||
});
|
||||
it('matches owner-only paths', () => {
|
||||
expect(isOwnerOnlyPath('/trackers/health')).toBe(true);
|
||||
expect(isOwnerOnlyPath('/trackers/health/')).toBe(true);
|
||||
expect(isOwnerOnlyPath('/trackers/Health/import')).toBe(true);
|
||||
expect(isOwnerOnlyPath('/trackers/healthy')).toBe(false);
|
||||
expect(isOwnerOnlyPath('/trackers')).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user