diff --git a/config/template.localdb.json b/config/template.localdb.json index 00b2452..3d49343 100644 --- a/config/template.localdb.json +++ b/config/template.localdb.json @@ -117,6 +117,58 @@ "useriso": { "node": "examplenode1", "storage": "cephfs" + }, + "defaultuser": { + "resources": { + "cpu": [], + "cores": { + "max": 0 + }, + "memory": { + "max": 0 + }, + "swap": { + "max": 0 + }, + "local": { + "max": 0 + }, + "cephpl": { + "max": 0 + }, + "network": { + "max": 0 + }, + "pci": [] + }, + "nodes": [], + "cluster": { + "vmid": { + "min": -1, + "max": -1 + }, + "pool": "" + }, + "templates": { + "instances": { + "lxc": {}, + "qemu": {} + } + }, + "network": { + "lxc": { + "type": "veth", + "bridge": "vmbr0", + "vlan": 10, + "ip": "dhcp", + "ip6": "dhcp" + }, + "qemu": { + "type": "virtio", + "bridge": "vmbr0", + "vlan": 10 + } + } } }, "users": { diff --git a/src/db.js b/src/db.js index 37fed7b..f693293 100644 --- a/src/db.js +++ b/src/db.js @@ -7,12 +7,12 @@ class LocalDB { constructor (path) { try { this.#path = path; - this.load(); - this.pveAPI = this.getGlobalConfig().application.pveAPI; - this.pveAPIToken = this.getGlobalConfig().application.pveAPIToken; - this.listenPort = this.getGlobalConfig().application.listenPort; - this.hostname = this.getGlobalConfig().application.hostname; - this.domain = this.getGlobalConfig().application.domain; + this.#load(); + this.pveAPI = this.getConfig().application.pveAPI; + this.pveAPIToken = this.getConfig().application.pveAPIToken; + this.listenPort = this.getConfig().application.listenPort; + this.hostname = this.getConfig().application.hostname; + this.domain = this.getConfig().application.domain; } catch { console.log(`Error: ${path} was not found. Please follow the directions in the README to initialize localdb.json.`); @@ -21,34 +21,63 @@ class LocalDB { } /** - * Load db from local file system. Reads from file path store in filename. + * Load db from local file system. Reads from file path store in path. */ - load () { + #load () { this.#data = JSON.parse(readFileSync(this.#path)); } /** - * Save db to local file system. Saves to file path stored in filename. + * Save db to local file system. Saves to file path stored in path. */ - save () { + #save () { writeFileSync(this.#path, JSON.stringify(this.#data)); } - /** - * Gets the global config object from db. - * @returns {Object} global config data. - */ - getGlobalConfig () { + getGlobal () { return this.#data.global; } + + setGloal (config) { + this.#data.global = config; + this.#save(); + } - /** - * Gets a specific user's config from db. - * @param {string} username of user to get config. - * @returns {Object} specific user config data. - */ - getUserConfig (username) { - return this.#data.users[username]; + addUser (username, config = null) { + config = config ? config : this.#data.global.defaultuser; + this.#data.users[username] = config; + this.#save(); + } + + getUser (username) { + if (this.#data.users[username]) { + return this.#data.users[username]; + } + else { + return null; + } + } + + setUser (username, config) { + if (this.#data.users[username]) { + this.#data.users[username] = config; + this.#save(); + return true; + } + else { + return false; + } + } + + delUser (username) { + if (this.#data.users[username]) { + delete this.#data.users[username]; + this.#save(); + return true; + } + else { + return false; + } } } diff --git a/src/routes/cluster.js b/src/routes/cluster.js index c72078f..fe0121a 100644 --- a/src/routes/cluster.js +++ b/src/routes/cluster.js @@ -37,7 +37,7 @@ router.get(`/:node(${nodeRegexP})/pci`, async (req, res) => { if (!auth) { return; } - const userNodes = db.getUserConfig(req.cookies.username).nodes; + const userNodes = db.getUser(req.cookies.username).nodes; if (!userNodes.includes(params.node)) { res.status(401).send({ auth: false, path: params.node }); res.end(); @@ -164,7 +164,7 @@ router.post(`${basePath}/create`, async (req, res) => { return; } // get user db config - const user = await db.getUserConfig(req.cookies.username); + const user = await db.getUser(req.cookies.username); const vmid = Number.parseInt(params.vmid); const vmidMin = user.cluster.vmid.min; const vmidMax = user.cluster.vmid.max; diff --git a/src/routes/cluster/disk.js b/src/routes/cluster/disk.js index e0f0a2f..11d514d 100644 --- a/src/routes/cluster/disk.js +++ b/src/routes/cluster/disk.js @@ -95,7 +95,7 @@ router.post("/:disk/attach", async (req, res) => { } // target disk must be allowed according to source disk's storage options const diskConfig = await getDiskInfo(params.node, config, `unused${params.source}`); // get target disk - const resourceConfig = db.getGlobalConfig().resources; + const resourceConfig = db.getGlobal().resources; if (!resourceConfig[diskConfig.storage].disks.some(diskPrefix => params.disk.startsWith(diskPrefix))) { res.status(500).send({ error: `Requested target ${params.disk} is not in allowed list [${resourceConfig[diskConfig.storage].disks}].` }); res.end(); @@ -337,7 +337,7 @@ router.post("/:disk/create", async (req, res) => { return; } // target disk must be allowed according to storage options - const resourceConfig = db.getGlobalConfig().resources; + const resourceConfig = db.getGlobal().resources; if (!resourceConfig[params.storage].disks.some(diskPrefix => params.disk.startsWith(diskPrefix))) { res.status(500).send({ error: `Requested target ${params.disk} is not in allowed list [${resourceConfig[params.storage].disks}].` }); res.end(); diff --git a/src/routes/cluster/net.js b/src/routes/cluster/net.js index 46012e6..77ae1eb 100644 --- a/src/routes/cluster/net.js +++ b/src/routes/cluster/net.js @@ -63,7 +63,7 @@ router.post("/:netid/create", async (req, res) => { return; } // setup action - const nc = db.getUserConfig(req.cookies.username).templates.network[params.type]; + const nc = db.getUser(req.cookies.username).network[params.type]; let action = {}; if (params.type === "lxc") { action[`net${params.netid}`] = `name=${params.name},bridge=${nc.bridge},ip=${nc.ip},ip6=${nc.ip6},tag=${nc.vlan},type=${nc.type},rate=${params.rate}`; diff --git a/src/routes/cluster/pci.js b/src/routes/cluster/pci.js index e41abfe..d96e904 100644 --- a/src/routes/cluster/pci.js +++ b/src/routes/cluster/pci.js @@ -126,7 +126,7 @@ router.post("/:hostpci/modify", async (req, res) => { action[`hostpci${params.hostpci}`] = `${params.device},pcie=${params.pcie}`; action = JSON.stringify(action); // commit action - const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobalConfig().application.pveroot)); + const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobal().application.pveroot)); if (!(rootauth.status === 200)) { res.status(rootauth.status).send({ auth: false, error: "API could not authenticate as root user." }); res.end(); @@ -206,7 +206,7 @@ router.post("/create", async (req, res) => { action[`hostpci${hostpci}`] = `${params.device},pcie=${params.pcie}`; action = JSON.stringify(action); // commit action - const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobalConfig().application.pveroot)); + const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobal().application.pveroot)); if (!(rootauth.status === 200)) { res.status(rootauth.status).send({ auth: false, error: "API could not authenticate as root user." }); res.end(); @@ -263,7 +263,7 @@ router.delete("/:hostpci/delete", async (req, res) => { // setup action const action = JSON.stringify({ delete: `hostpci${params.hostpci}` }); // commit action, need to use root user here because proxmox api only allows root to modify hostpci for whatever reason - const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobalConfig().application.pveroot)); + const rootauth = await requestPVE("/access/ticket", "POST", null, JSON.stringify(db.getGlobal().application.pveroot)); if (!(rootauth.status === 200)) { res.status(rootauth.status).send({ auth: false, error: "API could not authenticate as root user." }); res.end(); diff --git a/src/routes/global.js b/src/routes/global.js index 2f2b6da..efd32ac 100644 --- a/src/routes/global.js +++ b/src/routes/global.js @@ -20,7 +20,7 @@ router.get("/config/:key", async (req, res) => { } const allowKeys = ["resources"]; if (allowKeys.includes(params.key)) { - const config = db.getGlobalConfig(); + const config = db.getGlobal(); res.status(200).send(config[params.key]); } else { diff --git a/src/routes/sync.js b/src/routes/sync.js index 076a8ba..c3de968 100644 --- a/src/routes/sync.js +++ b/src/routes/sync.js @@ -24,8 +24,8 @@ let prevState = {}; // target ms value let targetMSTime = null; -const schemes = db.getGlobalConfig().clientsync.schemes; -const resourceTypes = db.getGlobalConfig().clientsync.resourcetypes; +const schemes = db.getGlobal().clientsync.schemes; +const resourceTypes = db.getGlobal().clientsync.resourcetypes; /** * GET - get list of supported synchronization schemes * responses: @@ -164,7 +164,7 @@ if (schemes.interrupt.enabled) { } else { wsServer.handleUpgrade(req, socket, head, (socket) => { - const pool = db.getUserConfig(cookies.username).cluster.pool; + const pool = db.getUser(cookies.username).cluster.pool; wsServer.emit("connection", socket, cookies.username, pool); }); } diff --git a/src/routes/user.js b/src/routes/user.js index 41afe86..0535c44 100644 --- a/src/routes/user.js +++ b/src/routes/user.js @@ -43,7 +43,7 @@ router.get("/config/:key", async (req, res) => { } const allowKeys = ["resources", "cluster", "nodes"]; if (allowKeys.includes(params.key)) { - const config = db.getUserConfig(req.cookies.username); + const config = db.getUser(req.cookies.username); res.status(200).send(config[params.key]); } else { @@ -64,7 +64,7 @@ router.get("/iso", async (req, res) => { return; } // get user iso config - const userIsoConfig = db.getGlobalConfig().useriso; + const userIsoConfig = db.getGlobal().useriso; // get all isos const isos = (await requestPVE(`/nodes/${userIsoConfig.node}/storage/${userIsoConfig.storage}/content?content=iso`, "GET", { token: pveAPIToken })).data.data; const userIsos = []; diff --git a/src/utils.js b/src/utils.js index 3bcc699..9346b33 100644 --- a/src/utils.js +++ b/src/utils.js @@ -16,7 +16,7 @@ export async function checkAuth (cookies, res, vmpath = null) { const db = global.db; let auth = false; - if (db.getUserConfig(cookies.username) === null) { + if (db.getUser(cookies.username) === null) { auth = false; res.status(401).send({ auth, path: vmpath ? `${vmpath}/config` : "/version", error: `User ${cookies.username} not found in localdb.` }); res.end(); @@ -47,9 +47,9 @@ export async function checkAuth (cookies, res, vmpath = null) { */ export async function getUserResources (req, username) { const db = global.db; - const dbResources = db.getGlobalConfig().resources; + const dbResources = db.getGlobal().resources; const used = await getUsedResources(req, dbResources); - const userResources = db.getUserConfig(username).resources; + const userResources = db.getUser(username).resources; Object.keys(userResources).forEach((k) => { if (dbResources[k] && dbResources[k].type === "list") { userResources[k].forEach((listResource) => { @@ -79,7 +79,7 @@ export async function getUserResources (req, username) { */ export async function approveResources (req, username, request) { const db = global.db; - const dbResources = db.getGlobalConfig().resources; + const dbResources = db.getGlobal().resources; const userResources = await getUserResources(req, username); let approved = true; Object.keys(request).forEach((key) => {