This repository has been archived on 2022-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
IcyNet.eu/server/api/admin.js

320 lines
8.6 KiB
JavaScript
Raw Normal View History

2017-08-28 15:42:16 +00:00
import Users from './index'
import Models from './models'
const perPage = 6
async function cleanUserObject (dbe, admin) {
let totp = await Users.User.Login.totpTokenRequired(dbe)
2017-08-28 15:42:16 +00:00
return {
id: dbe.id,
username: dbe.username,
display_name: dbe.display_name,
uuid: dbe.uuid,
2017-08-28 15:42:16 +00:00
email: dbe.email,
avatar_file: dbe.avatar_file,
activated: dbe.activated === 1,
locked: dbe.locked === 1,
2017-08-28 22:36:13 +00:00
ip_address: dbe.ip_address,
2017-08-28 15:42:16 +00:00
password: dbe.password !== null,
nw_privilege: dbe.nw_privilege,
2017-08-28 22:36:13 +00:00
created_at: dbe.created_at,
totp_enabled: totp,
bannable: admin ? (dbe.nw_privilege < admin.nw_privilege && dbe.id !== admin.id) : false
2017-08-28 15:42:16 +00:00
}
}
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
}
}
2017-08-28 22:36:13 +00:00
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()
}
}
2017-11-07 16:52:12 +00:00
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
}
2017-08-28 15:42:16 +00:00
const API = {
2017-11-07 16:52:12 +00:00
// List all users (paginated)
2017-08-28 22:36:13 +00:00
getAllUsers: async function (page, adminId) {
2017-08-28 15:42:16 +00:00
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' }
2017-08-28 15:42:16 +00:00
}
count = count[0].ids
let paginated = Users.Pagination(perPage, parseInt(count), page)
let raw = await Models.User.query().offset(paginated.offset).limit(perPage)
2017-08-28 22:36:13 +00:00
let admin = await Users.User.get(adminId)
2017-08-28 15:42:16 +00:00
let users = []
for (let i in raw) {
let entry = raw[i]
users.push(await cleanUserObject(entry, admin))
2017-08-28 15:42:16 +00:00
}
return {
page: paginated,
users: users
}
},
getUser: async function (id) {
let user = await Users.User.get(id)
if (!user) throw new Error('No such user')
return cleanUserObject(user, null)
},
editUser: async function (id, data) {
let user = await Users.User.get(id)
if (!user) throw new Error('No such user')
let fields = [
'username', 'display_name', 'email', 'nw_privilege', 'activated'
]
data = dataFilter(data, fields, ['nw_privilege', 'activated'])
if (!data) throw new Error('Missing fields')
await Users.User.update(user, data)
return {}
},
resendActivationEmail: async function (id) {
let user = await Users.User.get(id)
if (!user) throw new Error('No such user')
if (user.activated === 1) return {}
await Users.User.Register.activationEmail(user)
return {}
},
revokeTotpToken: async function (id) {
let user = await Users.User.get(id)
if (!user) throw new Error('No such user')
await Models.TotpToken.query().delete().where('user_id', user.id)
return {}
},
sendPasswordEmail: async function (id) {
let user = await Users.User.get(id)
if (!user) throw new Error('No such user')
let token = await Users.User.Reset.reset(user.email, false, true)
return {token}
},
2017-12-07 19:57:42 +00:00
// Search for users by terms and fields
searchUsers: async function (terms, fields = ['email']) {
let qb = Models.User.query()
terms = terms.replace(/_/g, '\\_').replace(/%/g, '\\%')
qb = qb.where(fields[0], 'like', '%' + terms + '%')
if (fields.length >= 1) {
for (let i = 1; i < fields.length; i++) {
qb = qb.orWhere(fields[i], 'like', '%' + terms + '%')
}
}
let rows = await qb.limit(8)
if (!rows.length) return { error: 'No results' }
let cleaned = []
for (let i in rows) {
let userRaw = rows[i]
cleaned.push(await cleanUserObject(userRaw, null))
}
return cleaned
},
2017-11-07 16:52:12 +00:00
// 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
}
},
2017-11-07 16:52:12 +00:00
// Get information about a client via id
getClient: async function (id) {
let raw = await Models.OAuth2Client.query().where('id', id)
if (!raw.length) throw new Error('No such client')
return cleanClientObject(raw[0])
},
2017-11-07 16:52:12 +00:00
// Update a client `id` in database with `data`
updateClient: async function (id, data) {
let fields = [
2017-11-07 16:52:12 +00:00
'title', 'description', 'url', 'redirect_url', 'scope', 'verified'
]
2017-11-07 16:52:12 +00:00
data = dataFilter(data, fields, ['scope', 'verified'])
if (!data) throw new Error('Missing fields')
try {
await Models.OAuth2Client.query().patchAndFetchById(id, data)
2017-08-28 22:36:13 +00:00
await Models.OAuth2AuthorizedClient.query().delete().where('client_id', id)
} catch (e) {
throw new Error('No such client')
}
return {}
},
2017-11-07 16:52:12 +00:00
// 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 {}
},
2017-11-07 16:52:12 +00:00
// Create a new client
createClient: async function (data, user) {
let fields = [
'title', 'description', 'url', 'redirect_url', 'scope'
]
2017-11-07 16:52:12 +00:00
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)
},
2017-11-07 16:52:12 +00:00
// 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
2017-08-28 22:36:13 +00:00
},
2017-11-07 16:52:12 +00:00
// List all bans (paginated)
2017-08-28 22:36:13 +00:00
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' }
2017-08-28 22:36:13 +00:00
}
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
2017-08-28 22:36:13 +00:00
}
},
2017-11-07 16:52:12 +00:00
// Remove a ban
2017-08-28 22:36:13 +00:00
removeBan: async function (banId) {
return Models.Ban.query().delete().where('id', banId)
},
2017-11-07 16:52:12 +00:00
// Create a ban
2017-08-28 22:36:13 +00:00
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!')
2017-08-28 22:36:13 +00:00
let admin = await Users.User.get(adminId)
if (user.nw_privilege > admin.nw_privilege) throw new Error('Cannot ban user.')
2017-08-28 22:36:13 +00:00
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 {}
2017-08-28 15:42:16 +00:00
}
}
module.exports = API