feat: registration and login with JWT auth
- users table: email, password_hash (bcrypt), role, is_active - POST /auth/register — checks blocklist, hashes password, returns JWT - POST /auth/login — verifies password, returns JWT - Auth middleware: accepts env tokens (dev) OR valid JWTs - end-user role → 403 Insufficient permissions on all /api/* routes - JWT_SECRET + JWT_EXPIRES_IN env vars Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -335,6 +335,29 @@ async function migrate() {
|
||||
await query(`CREATE INDEX IF NOT EXISTS blocklist_phone_idx ON blocklist (phone) WHERE phone IS NOT NULL`);
|
||||
await query(`CREATE INDEX IF NOT EXISTS blocklist_ip_idx ON blocklist (ip) WHERE ip IS NOT NULL`);
|
||||
|
||||
// users
|
||||
await query(`
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
email TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
role VARCHAR(20) NOT NULL DEFAULT 'end-user'
|
||||
CHECK (role IN ('end-user', 'admin')),
|
||||
is_active BOOLEAN NOT NULL DEFAULT true,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
)
|
||||
`);
|
||||
|
||||
await query(`CREATE UNIQUE INDEX IF NOT EXISTS users_email_idx ON users (lower(email))`);
|
||||
|
||||
await query(`
|
||||
DROP TRIGGER IF EXISTS users_updated_at ON users;
|
||||
CREATE TRIGGER users_updated_at
|
||||
BEFORE UPDATE ON users
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at()
|
||||
`);
|
||||
|
||||
console.log('Migration complete');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user