import Users from './index' import Models from './models' const perPage = 6 function cleanUserObject (dbe, admin) { return { id: dbe.id, username: dbe.username, display_name: dbe.display_name, uuid: dbe.uuid, email: dbe.email, avatar_file: dbe.avatar_file, activated: dbe.activated === 1, locked: dbe.locked === 1, ip_address: dbe.ip_address, password: dbe.password !== null, nw_privilege: dbe.nw_privilege, created_at: dbe.created_at, bannable: dbe.nw_privilege < admin.nw_privilege && dbe.id !== admin.id } } async function cleanClientObject (dbe) { let user = await Users.User.get(dbe.user_id) return { id: dbe.id, title: dbe.title, description: dbe.description, url: dbe.url, redirect_url: dbe.redirect_url, grants: dbe.grants, icon: dbe.icon, user: { id: user.id, display_name: user.display_name }, scope: dbe.scope, secret: dbe.secret, verified: dbe.verified === 1, created_at: dbe.created_at } } async function cleanBanObject (dbe) { let user = await Users.User.get(dbe.user_id) let admin = await Users.User.get(dbe.admin_id) return { id: dbe.id, reason: dbe.reason, user: { id: user.id, display_name: user.display_name }, admin: { id: admin.id, display_name: admin.display_name }, expires_at: dbe.expires_at, created_at: dbe.created_at, ip_address: dbe.associated_ip, expired: dbe.expires_at && new Date(dbe.expires_at).getTime() < Date.now() } } function dataFilter (data, fields, optional = []) { // Remove keys not listed in `fields` for (let i in data) { if (fields.indexOf(i) === -1) { delete data[i] } } // Ensure all the entries in `fields` are present as keys in `data` or are `optional` for (let j in fields) { if (!data[fields[j]] && optional.indexOf(fields[j]) === -1) return null } return data } const API = { // List all users (paginated) getAllUsers: async function (page, adminId) { let count = await Models.User.query().count('id as ids') if (!count.length || !count[0]['ids'] || isNaN(page)) { return { error: 'No users found in database' } } count = count[0].ids let paginated = Users.Pagination(perPage, parseInt(count), page) let raw = await Models.User.query().offset(paginated.offset).limit(perPage) let admin = await Users.User.get(adminId) let users = [] for (let i in raw) { let entry = raw[i] users.push(cleanUserObject(entry, admin)) } return { page: paginated, users: users } }, // List all clients (paginated) getAllClients: async function (page) { let count = await Models.OAuth2Client.query().count('id as ids') if (!count.length || !count[0]['ids'] || isNaN(page)) { return { error: 'No clients' } } count = count[0].ids let paginated = Users.Pagination(perPage, parseInt(count), page) let raw = await Models.OAuth2Client.query().offset(paginated.offset).limit(perPage) let clients = [] for (let i in raw) { let entry = raw[i] clients.push(await cleanClientObject(entry)) } return { page: paginated, clients: clients } }, // Get information about a client via id getClient: async function (id) { let raw = await Models.OAuth2Client.query().where('id', id) if (!raw.length) return null return cleanClientObject(raw[0]) }, // Update a client `id` in database with `data` updateClient: async function (id, data) { let fields = [ 'title', 'description', 'url', 'redirect_url', 'scope', 'verified' ] data = dataFilter(data, fields, ['scope', 'verified']) if (!data) throw new Error('Missing fields') try { await Models.OAuth2Client.query().patchAndFetchById(id, data) await Models.OAuth2AuthorizedClient.query().delete().where('client_id', id) } catch (e) { throw new Error('No such client') } return {} }, // Create a new secret for a client newSecret: async function (id) { if (isNaN(id)) throw new Error('Invalid client ID') let secret = Users.Hash(16) try { await Models.OAuth2Client.query().patchAndFetchById(id, {secret: secret}) } catch (e) { throw new Error('No such client') } return {} }, // Create a new client createClient: async function (data, user) { let fields = [ 'title', 'description', 'url', 'redirect_url', 'scope' ] data = dataFilter(data, fields, ['scope']) if (!data) throw new Error('Missing fields') let obj = Object.assign({ secret: Users.Hash(16), grants: 'authorization_code', created_at: new Date(), user_id: user.id }, data) return Models.OAuth2Client.query().insert(obj) }, // Remove a client and all associated data removeClient: async function (id) { if (isNaN(id)) throw new Error('Invalid ID number') await Models.OAuth2Client.query().delete().where('id', id) await Models.OAuth2AuthorizedClient.query().delete().where('client_id', id) await Models.OAuth2AccessToken.query().delete().where('client_id', id) await Models.OAuth2RefreshToken.query().delete().where('client_id', id) return true }, // List all bans (paginated) getAllBans: async function (page) { let count = await Models.Ban.query().count('id as ids') if (!count.length || !count[0]['ids'] || isNaN(page)) { return { error: 'No bans on record' } } count = count[0].ids let paginated = Users.Pagination(perPage, parseInt(count), page) let raw = await Models.Ban.query().offset(paginated.offset).limit(perPage) let bans = [] for (let i in raw) { let entry = raw[i] bans.push(await cleanBanObject(entry)) } return { page: paginated, bans: bans } }, // Remove a ban removeBan: async function (banId) { return Models.Ban.query().delete().where('id', banId) }, // Create a ban addBan: async function (data, adminId) { let user = await Users.User.get(parseInt(data.user_id)) if (!user) throw new Error('No such user.') if (user.id === adminId) throw new Error('Cannot ban yourself!') let admin = await Users.User.get(adminId) if (user.nw_privilege > admin.nw_privilege) throw new Error('Cannot ban user.') let banAdd = { reason: data.reason || 'Unspecified ban', admin_id: adminId, user_id: user.id, expires_at: data.expires_at != null ? new Date(data.expires_at) : null, created_at: new Date(), associated_ip: data.ip_address || user.ip_address || null } await Models.Ban.query().insert(banAdd) return {} } } module.exports = API