my own indieAuth provider! indiko.dunkirk.sh/docs
indieauth oauth2-server
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: collapse migrations

dunkirk.sh b50a4288 757350ba

verified
+79 -110
+79
src/migrations/001_init.sql
··· 6 6 email TEXT, 7 7 photo TEXT, 8 8 url TEXT, 9 + status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'suspended', 'inactive')), 10 + role TEXT NOT NULL DEFAULT 'user', 9 11 is_admin INTEGER NOT NULL DEFAULT 0, 10 12 created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')) 11 13 ); ··· 45 47 used INTEGER NOT NULL DEFAULT 0, 46 48 used_by INTEGER, 47 49 used_at INTEGER, 50 + max_uses INTEGER DEFAULT 1, 51 + current_uses INTEGER NOT NULL DEFAULT 0, 52 + expires_at INTEGER, 53 + note TEXT, 54 + message TEXT, 48 55 created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 49 56 FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE, 50 57 FOREIGN KEY (used_by) REFERENCES users(id) ON DELETE SET NULL 51 58 ); 52 59 60 + CREATE TABLE IF NOT EXISTS apps ( 61 + id INTEGER PRIMARY KEY AUTOINCREMENT, 62 + client_id TEXT NOT NULL UNIQUE, 63 + redirect_uris TEXT NOT NULL, 64 + name TEXT, 65 + logo_url TEXT, 66 + description TEXT, 67 + is_preregistered INTEGER NOT NULL DEFAULT 0, 68 + client_secret_hash TEXT, 69 + available_roles TEXT, 70 + default_role TEXT, 71 + first_seen INTEGER NOT NULL DEFAULT (strftime('%s','now')), 72 + last_used INTEGER NOT NULL DEFAULT (strftime('%s','now')) 73 + ); 74 + 75 + CREATE TABLE IF NOT EXISTS permissions ( 76 + id INTEGER PRIMARY KEY AUTOINCREMENT, 77 + user_id INTEGER NOT NULL, 78 + client_id TEXT NOT NULL, 79 + scopes TEXT NOT NULL, 80 + role TEXT, 81 + granted_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 82 + last_used INTEGER NOT NULL DEFAULT (strftime('%s','now')), 83 + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, 84 + FOREIGN KEY (client_id) REFERENCES apps(client_id) ON DELETE CASCADE, 85 + UNIQUE(user_id, client_id) 86 + ); 87 + 88 + CREATE TABLE IF NOT EXISTS authcodes ( 89 + id INTEGER PRIMARY KEY AUTOINCREMENT, 90 + code TEXT NOT NULL UNIQUE, 91 + user_id INTEGER NOT NULL, 92 + client_id TEXT NOT NULL, 93 + redirect_uri TEXT NOT NULL, 94 + scopes TEXT NOT NULL, 95 + code_challenge TEXT NOT NULL, 96 + code_challenge_method TEXT NOT NULL DEFAULT 'S256', 97 + expires_at INTEGER NOT NULL, 98 + used INTEGER NOT NULL DEFAULT 0, 99 + created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 100 + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE 101 + ); 102 + 103 + CREATE TABLE IF NOT EXISTS invite_roles ( 104 + id INTEGER PRIMARY KEY AUTOINCREMENT, 105 + invite_id INTEGER NOT NULL, 106 + app_id INTEGER NOT NULL, 107 + role TEXT NOT NULL, 108 + created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 109 + FOREIGN KEY (invite_id) REFERENCES invites(id) ON DELETE CASCADE, 110 + FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE, 111 + UNIQUE(invite_id, app_id) 112 + ); 113 + 114 + CREATE TABLE IF NOT EXISTS invite_uses ( 115 + id INTEGER PRIMARY KEY AUTOINCREMENT, 116 + invite_id INTEGER NOT NULL, 117 + user_id INTEGER NOT NULL, 118 + used_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 119 + FOREIGN KEY (invite_id) REFERENCES invites(id) ON DELETE CASCADE, 120 + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE 121 + ); 122 + 53 123 CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token); 54 124 CREATE INDEX IF NOT EXISTS idx_sessions_expires_at ON sessions(expires_at); 55 125 CREATE INDEX IF NOT EXISTS idx_challenges_challenge ON challenges(challenge); 56 126 CREATE INDEX IF NOT EXISTS idx_challenges_expires_at ON challenges(expires_at); 57 127 CREATE INDEX IF NOT EXISTS idx_credentials_user_id ON credentials(user_id); 58 128 CREATE INDEX IF NOT EXISTS idx_invites_code ON invites(code); 129 + CREATE INDEX IF NOT EXISTS idx_apps_client_id ON apps(client_id); 130 + CREATE INDEX IF NOT EXISTS idx_permissions_user_id ON permissions(user_id); 131 + CREATE INDEX IF NOT EXISTS idx_permissions_client_id ON permissions(client_id); 132 + CREATE INDEX IF NOT EXISTS idx_authcodes_code ON authcodes(code); 133 + CREATE INDEX IF NOT EXISTS idx_authcodes_expires_at ON authcodes(expires_at); 134 + CREATE INDEX IF NOT EXISTS idx_invite_roles_invite_id ON invite_roles(invite_id); 135 + CREATE INDEX IF NOT EXISTS idx_invite_roles_app_id ON invite_roles(app_id); 136 + CREATE INDEX IF NOT EXISTS idx_invite_uses_invite_id ON invite_uses(invite_id); 137 + CREATE INDEX IF NOT EXISTS idx_invite_uses_user_id ON invite_uses(user_id);
-5
src/migrations/002_add_user_status_role.sql
··· 1 - -- Add status and role columns to users table 2 - ALTER TABLE users ADD COLUMN status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'suspended', 'inactive')); 3 - ALTER TABLE users ADD COLUMN role TEXT NOT NULL DEFAULT 'user'; 4 - -- Update existing admin users to have 'admin' role 5 - UPDATE users SET role = 'admin' WHERE is_admin = 1;
-43
src/migrations/003_add_indieauth_tables.sql
··· 1 - -- Add tables for IndieAuth/OAuth 2.0 support 2 - -- Apps (auto-registered on first authorization request) 3 - CREATE TABLE IF NOT EXISTS apps ( 4 - id INTEGER PRIMARY KEY AUTOINCREMENT, 5 - client_id TEXT NOT NULL UNIQUE, 6 - redirect_uris TEXT NOT NULL, -- JSON array 7 - name TEXT, 8 - first_seen INTEGER NOT NULL DEFAULT (strftime('%s','now')), 9 - last_used INTEGER NOT NULL DEFAULT (strftime('%s','now')) 10 - ); 11 - -- User permissions per app 12 - CREATE TABLE IF NOT EXISTS permissions ( 13 - id INTEGER PRIMARY KEY AUTOINCREMENT, 14 - user_id INTEGER NOT NULL, 15 - client_id TEXT NOT NULL, 16 - scopes TEXT NOT NULL, -- JSON array 17 - granted_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 18 - last_used INTEGER NOT NULL DEFAULT (strftime('%s','now')), 19 - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, 20 - FOREIGN KEY (client_id) REFERENCES apps(client_id) ON DELETE CASCADE, 21 - UNIQUE(user_id, client_id) 22 - ); 23 - -- Authorization codes (short-lived, single-use) 24 - CREATE TABLE IF NOT EXISTS authcodes ( 25 - id INTEGER PRIMARY KEY AUTOINCREMENT, 26 - code TEXT NOT NULL UNIQUE, 27 - user_id INTEGER NOT NULL, 28 - client_id TEXT NOT NULL, 29 - redirect_uri TEXT NOT NULL, 30 - scopes TEXT NOT NULL, -- JSON array 31 - code_challenge TEXT NOT NULL, 32 - code_challenge_method TEXT NOT NULL DEFAULT 'S256', 33 - expires_at INTEGER NOT NULL, 34 - used INTEGER NOT NULL DEFAULT 0, 35 - created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 36 - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE 37 - ); 38 - -- Indexes 39 - CREATE INDEX IF NOT EXISTS idx_apps_client_id ON apps(client_id); 40 - CREATE INDEX IF NOT EXISTS idx_permissions_user_id ON permissions(user_id); 41 - CREATE INDEX IF NOT EXISTS idx_permissions_client_id ON permissions(client_id); 42 - CREATE INDEX IF NOT EXISTS idx_authcodes_code ON authcodes(code); 43 - CREATE INDEX IF NOT EXISTS idx_authcodes_expires_at ON authcodes(expires_at);
-7
src/migrations/004_add_client_preregistration_and_roles.sql
··· 1 - -- Add columns to apps table for pre-registration metadata 2 - ALTER TABLE apps ADD COLUMN logo_url TEXT; 3 - ALTER TABLE apps ADD COLUMN description TEXT; 4 - ALTER TABLE apps ADD COLUMN is_preregistered INTEGER NOT NULL DEFAULT 0; 5 - ALTER TABLE apps ADD COLUMN client_secret_hash TEXT; 6 - -- Add role column to permissions table for per-user, per-app roles 7 - ALTER TABLE permissions ADD COLUMN role TEXT;
-48
src/migrations/004_enhance_invites.sql
··· 1 - -- Enhance invites table with usage limits, expiry, and app role assignments 2 - -- Note: SQLite doesn't support DROP COLUMN, so we keep old columns for backward compatibility 3 - -- But we'll use the new columns going forward 4 - 5 - -- Add new columns to invites table 6 - ALTER TABLE invites ADD COLUMN max_uses INTEGER DEFAULT 1; 7 - ALTER TABLE invites ADD COLUMN current_uses INTEGER NOT NULL DEFAULT 0; 8 - ALTER TABLE invites ADD COLUMN expires_at INTEGER; 9 - ALTER TABLE invites ADD COLUMN note TEXT; 10 - 11 - -- Create invite_roles table for app-specific role assignments 12 - CREATE TABLE IF NOT EXISTS invite_roles ( 13 - id INTEGER PRIMARY KEY AUTOINCREMENT, 14 - invite_id INTEGER NOT NULL, 15 - app_id INTEGER NOT NULL, 16 - role TEXT NOT NULL, 17 - created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 18 - FOREIGN KEY (invite_id) REFERENCES invites(id) ON DELETE CASCADE, 19 - FOREIGN KEY (app_id) REFERENCES apps(id) ON DELETE CASCADE, 20 - UNIQUE(invite_id, app_id) 21 - ); 22 - 23 - CREATE INDEX IF NOT EXISTS idx_invite_roles_invite_id ON invite_roles(invite_id); 24 - CREATE INDEX IF NOT EXISTS idx_invite_roles_app_id ON invite_roles(app_id); 25 - 26 - -- Create invite_uses table to track each use (supports multi-use invites) 27 - CREATE TABLE IF NOT EXISTS invite_uses ( 28 - id INTEGER PRIMARY KEY AUTOINCREMENT, 29 - invite_id INTEGER NOT NULL, 30 - user_id INTEGER NOT NULL, 31 - used_at INTEGER NOT NULL DEFAULT (strftime('%s','now')), 32 - FOREIGN KEY (invite_id) REFERENCES invites(id) ON DELETE CASCADE, 33 - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE 34 - ); 35 - 36 - CREATE INDEX IF NOT EXISTS idx_invite_uses_invite_id ON invite_uses(invite_id); 37 - CREATE INDEX IF NOT EXISTS idx_invite_uses_user_id ON invite_uses(user_id); 38 - 39 - -- Migrate existing single-use invites to new structure 40 - -- For invites that have been used, set current_uses = 1 and max_uses = 1 41 - UPDATE invites SET current_uses = 1, max_uses = 1 WHERE used = 1; 42 - 43 - -- For unused invites, set max_uses = 1 and current_uses = 0 44 - UPDATE invites SET max_uses = 1, current_uses = 0 WHERE used = 0; 45 - 46 - -- Migrate old invite uses to new invite_uses table 47 - INSERT INTO invite_uses (invite_id, user_id, used_at) 48 - SELECT id, used_by, used_at FROM invites WHERE used = 1 AND used_by IS NOT NULL AND used_at IS NOT NULL;
-5
src/migrations/005_add_app_roles.sql
··· 1 - -- Add available_roles column to apps table (JSON array of role names) 2 - ALTER TABLE apps ADD COLUMN available_roles TEXT; 3 - 4 - -- Add default_role column to apps table 5 - ALTER TABLE apps ADD COLUMN default_role TEXT;
-2
src/migrations/006_add_invite_message.sql
··· 1 - -- Add public message field to invites 2 - ALTER TABLE invites ADD COLUMN message TEXT;