const db = require("better-sqlite3")("brainz-social.db"); db.pragma("journal_mode = WAL"); module.exports = { db, getConfig: (key) => { const row = db.prepare("SELECT * FROM config WHERE key = ?").get(key); return row ? row.value : null; }, setConfig: (key, value) => { db.prepare("INSERT OR REPLACE INTO config (key, value) VALUES(?, ?);").run(key, value); }, createApplication: (client_name, redirect_uri, scopes, website, client_id, client_secret) => { db.prepare("INSERT INTO applications (client_name, redirect_uri, scopes, website, client_id, client_secret) VALUES (?, ?, ?, ?, ?, ?);").run(client_name, redirect_uri, scopes, website, client_id, client_secret); }, getApplication: (client_id) => { return db.prepare("SELECT id, client_id, client_secret, redirect_uri, scopes, website FROM applications WHERE client_id = ?").get(client_id); }, getApplicationById: (id) => { return db.prepare("SELECT id, client_id, client_secret, redirect_uri, scopes, website FROM applications WHERE id = ?").get(id); }, createToken: (token, scope, application_id, user_id, created_at) => { db.prepare("INSERT INTO oauth_tokens (token, scopes, application_id, user_id, created_at, revoked) VALUES (?, ?, ?, ?, ?, false)").run(token, scope, application_id, user_id, created_at); }, getTokenData: (token) => { return db.prepare("SELECT application_id, user_id, created_at, revoked, scopes, token FROM oauth_tokens WHERE token = ?").get(token); }, revokeToken: (token) => { db.prepare("UPDATE oauth_tokens SET revoked = true WHERE token = ?").run(token); }, getAccountByUsername: (username) => { return db.prepare("SELECT id, username, email, password_hash, account_tier FROM accounts WHERE username = ?").get(username); }, createAccount: (username, email, password_hash) => { db.prepare("INSERT INTO accounts (username, email, password_hash, account_tier) VALUES (?, ?, ?, 0)").run(username, email, password_hash); }, checkAuthCookie: (cookie_value) => { return db.prepare("SELECT id, cookie_value, created_at, user_id, revoked FROM cookies WHERE cookie_value = ?").get(cookie_value); }, revokeAuthCookie: (cookie_value) => { db.prepare("UPDATE cookies SET revoked = true WHERE cookie_value = ?").run(cookie_value); }, createAuthCookie: (cookie_value, created_at, user_id) => { db.prepare("INSERT INTO cookies (cookie_value, created_at, user_id, revoked) VALUES (?, ?, ?, false)").run(cookie_value, created_at, user_id); }, createCsrfToken: (url, created_at, cookie_value) => { const db_row_id = db.prepare("INSERT INTO csrf_token (url, created_at, cookie_value) VALUES (?, ?, ?)").run(url, created_at, cookie_value).lastInsertRowid; return db.prepare("SELECT id FROM csrf_token WHERE rowid = ?").get(db_row_id); }, createCsrfTokenAssociation: (...ids) => { for (const source_id in ids) { if (Number.parseInt(ids[source_id], 10) === ids[source_id]) { for (const destination_id in ids) { if (Number.parseInt(ids[destination_id], 10) === ids[destination_id]) { db.prepare("INSERT INTO csrf_token_relations (source_id, destination_id) VALUES (?, ?)").run(ids[source_id], ids[destination_id]); } } } } }, removeAssociatedCsrfTokens: (id) => { db.prepare("DELETE FROM csrf_token WHERE id IN (SELECT destination_id AS id FROM csrf_token_relations WHERE source_id = ?)").run(id); }, getCsrfToken: (url) => { return db.prepare("SELECT id, url, created_at, cookie_value FROM csrf_token WHERE url = ?").get(url); }, createOauthCode: (code, application_id, user_id, scopes, created_at) => { db.prepare("INSERT INTO oauth_code (code, application_id, user_id, scopes, created_at, revoked) VALUES (?, ?, ?, ?, ?, false)").run(code, application_id, user_id, scopes, created_at); }, getOauthCode: (code) => { return db.prepare("SELECT code, application_id, user_id, scopes, created_at, revoked FROM oauth_code WHERE code = ?").get(code); }, revokeOauthCode: (code) => { db.prepare("UPDATE oauth_code SET revoked = true WHERE code = ?").run(code); }, selectApplicationByAuthToken: (token) => { return db.prepare("SELECT id, client_id, client_secret, redirect_uri, scopes, website FROM applications WHERE id in (SELECT application_id as id FROM oauth_tokens WHERE token = ?);").get(token); }, getVapidKey: () => { const vapidPublic = db.prepare("SELECT value FROM config WHERE key = vapid_key_public").get(); const vapidPrivate = db.prepare("SELECT value FROM config WHERE key = vapid_key_private").get(); if (vapidPublic.value && vapidPrivate.value) { return {public: vapidPublic, private: vapidPrivate}; } return null; }, setVapidKey: (publicKey, privateKey) => { db.prepare("INSERT INTO config (key, value) VALUES (vapid_key_public, ?)").run(publicKey); db.prepare("INSERT INTO config (key, value) VALUES (vapid_key_private, ?)").run(privateKey); }, getJsonldSchemaCache: (url) => { return db.prepare("SELECT schema FROM jsonld_schema_cache WHERE schema_uri = ? AND expires > ?").get(url, Math.floor(Date.now() / 1000)); }, storeJsonldSchemaCache: (url, schema, expiry) => { db.prepare("INSERT INTO jsonld_schema_cache (schema, schema_uri, expires) VALUES (?, ?, ?)").run(schema, url, expiry); }, getAccountByToken: (token) => { return db.prepare("SELECT id, username, email, password_hash, account_tier FROM accounts WHERE id IN (SELECT user_id FROM oauth_tokens WHERE token = ?)").get(token); }, getAccountActivityByAccount: (user_id) => { return db.prepare("SELECT id, object, type, local, uri_id, owner FROM activity_objects WHERE (type = 'https://www.w3.org/ns/activitystreams#Person' OR type = 'https://www.w3.org/ns/activitystreams#Service') AND local = true AND owner in (SELECT username FROM accounts WHERE id = ?)").get(user_id); }, addActivity: (object, type, local, uri_id, owner) => { db.prepare("INSERT INTO activity_objects (object, type, local, uri_id, owner) VALUES (?, ?, ?, ?, ?)").run(object, type, local, uri_id, owner); }, getLastStatus: (owner) => { return db.prepare("SELECT created_at FROM activity_objects WHERE type = 'https://www.w3.org/ns/activitystreams#Note' AND owner = ? ORDER BY created_at DESC").get(owner); }, getStatusCount: (owner) => { return db.prepare("SELECT COUNT(*) AS count FROM activity_objects WHERE type = 'https://www.w3.org/ns/activitystreams#Note' AND owner = ?").get(owner); }, storeW3idSecurityKey: (key_uri, publicKey, privateKey, expires) => { db.prepare("INSERT INTO w3id_security_keys (key_uri, public_key, private_key, expires) VALUES (?, ?, ?, ?)").run(key_uri, publicKey, privateKey, expires); }, };