Backend (Go): - Project structure with chi router, pgxpool, goose migrations - JWT auth (access/refresh tokens) with Firebase token verification - NoopTokenVerifier for local dev without Firebase credentials - PostgreSQL user repository with atomic profile updates (transactions) - Mifflin-St Jeor calorie calculation based on profile data - REST API: POST /auth/login, /auth/refresh, /auth/logout, GET/PUT /profile, GET /health - Middleware: auth, CORS (localhost wildcard), logging, recovery, request_id - Unit tests (51 passing) and integration tests (testcontainers) - Docker Compose setup with postgres healthcheck and graceful shutdown Flutter client: - Riverpod state management with GoRouter navigation - Firebase Auth (email/password + Google sign-in with web popup support) - Platform-aware API URLs (web/Android/iOS) - Dio HTTP client with JWT auth interceptor and concurrent refresh handling - Secure token storage - Screens: Login, Register, Home (tabs: Menu, Recipes, Products, Profile) - Unit tests (17 passing) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
50 lines
1.4 KiB
SQL
50 lines
1.4 KiB
SQL
-- +goose Up
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
CREATE TYPE user_plan AS ENUM ('free', 'paid');
|
|
CREATE TYPE user_gender AS ENUM ('male', 'female');
|
|
CREATE TYPE user_goal AS ENUM ('lose', 'maintain', 'gain');
|
|
CREATE TYPE activity_level AS ENUM ('low', 'moderate', 'high');
|
|
|
|
CREATE TABLE users (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
firebase_uid VARCHAR(128) NOT NULL UNIQUE,
|
|
email VARCHAR(255) NOT NULL,
|
|
name VARCHAR(255) NOT NULL DEFAULT '',
|
|
avatar_url TEXT,
|
|
|
|
-- Body parameters
|
|
height_cm SMALLINT,
|
|
weight_kg DECIMAL(5,2),
|
|
age SMALLINT,
|
|
gender user_gender,
|
|
activity activity_level,
|
|
|
|
-- Goal and calculated daily norm
|
|
goal user_goal,
|
|
daily_calories INTEGER,
|
|
|
|
-- Plan
|
|
plan user_plan NOT NULL DEFAULT 'free',
|
|
|
|
-- Preferences (JSONB for flexibility)
|
|
preferences JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
|
|
-- Refresh token
|
|
refresh_token TEXT,
|
|
token_expires_at TIMESTAMPTZ,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX idx_users_firebase_uid ON users (firebase_uid);
|
|
CREATE INDEX idx_users_email ON users (email);
|
|
|
|
-- +goose Down
|
|
DROP TABLE IF EXISTS users;
|
|
DROP TYPE IF EXISTS activity_level;
|
|
DROP TYPE IF EXISTS user_goal;
|
|
DROP TYPE IF EXISTS user_gender;
|
|
DROP TYPE IF EXISTS user_plan;
|