diff --git a/config/template.config.json b/config/template.config.json index 7e4ced2..152d446 100644 --- a/config/template.config.json +++ b/config/template.config.json @@ -25,7 +25,8 @@ "paasldap": { "import": "paasldap.js", "config": { - "url": "http://paasldap.mydomain.example" + "url": "http://paasldap.mydomain.example", + "realm": "ldap" } } }, diff --git a/src/backends/localdb.js b/src/backends/localdb.js index c68f530..7b4022a 100644 --- a/src/backends/localdb.js +++ b/src/backends/localdb.js @@ -62,6 +62,16 @@ export default class LocalDB extends DB_BACKEND { } } + async getAllUsers (params = null) { + const requestingUser = params.username; // assume checkAuth has been run, which already checks that username matches PVE token + if (this.#data.users[requestingUser].cluster.admin === true) { + return this.#data.users; + } + else { + return null; + } + } + setUser (user, attributes, params = null) { if (attributes.resources && attributes.cluster && attributes.templates) { // localdb should only deal with these attributes const username = `${user.id}@${user.realm}`; @@ -94,6 +104,10 @@ export default class LocalDB extends DB_BACKEND { // group methods not implemented because db backend does not store groups addGroup (group, atrributes, params = null) {} getGroup (group, params = null) {} + getAllGroups (params = null) { + return null; + } + setGroup (group, attributes, params = null) {} delGroup (group, params = null) {} diff --git a/src/backends/paasldap.js b/src/backends/paasldap.js index 7140aa4..6a374c4 100644 --- a/src/backends/paasldap.js +++ b/src/backends/paasldap.js @@ -4,10 +4,12 @@ import * as setCookie from "set-cookie-parser"; export default class PAASLDAP extends AUTH_BACKEND { #url = null; + #realm = null; constructor (config) { super(); this.#url = config.url; + this.#realm = config.realm; } /** @@ -45,6 +47,19 @@ export default class PAASLDAP extends AUTH_BACKEND { } } + #handleGenericReturn (res) { + if (res.ok) { // if ok, return null + return null; + } + else { // if not ok, return error obj + return { + ok: res.ok, + status: res.status, + message: res.ok ? "" : res.data.error + }; + } + } + async openSession (user, password) { const username = user.id; const content = { username, password }; @@ -65,7 +80,7 @@ export default class PAASLDAP extends AUTH_BACKEND { return { ok: false, status: result.status, - message: result.data.error.message, + message: result.data.error, cookies: [] }; } @@ -73,16 +88,7 @@ export default class PAASLDAP extends AUTH_BACKEND { async addUser (user, attributes, params = null) { const res = await this.#request(`/users/${user.id}`, "POST", params, attributes); - if (res.ok) { // if ok, return null - return null; - } - else { // if not ok, return error obj - return { - ok: res.ok, - status: res.status, - message: res.ok ? "" : res.data.error.message - }; - } + return this.#handleGenericReturn(res); } async getUser (user, params = null) { @@ -98,35 +104,80 @@ export default class PAASLDAP extends AUTH_BACKEND { } } + async getAllUsers (params = null) { + if (!params) { + return null; + } + const res = await this.#request("/users", "GET", params); + if (res.ok) { // if ok, return user data + const users = res.data.users; + const usersFormatted = {}; + // label each user object by user@realm + for (const user of users) { + usersFormatted[`${user.attributes.uid}@${this.#realm}`] = user; + } + return usersFormatted; + } + else { // else return null + return null; + } + } + async setUser (user, attributes, params = null) { - return await this.#request(`/users/${user.id}`, "POST", params, attributes); + const res = await this.#request(`/users/${user.id}`, "POST", params, attributes); + return this.#handleGenericReturn(res); } async delUser (user, params = null) { - return await this.#request(`/users/${user.id}`, "DELETE", params); + const res = await this.#request(`/users/${user.id}`, "DELETE", params); + return this.#handleGenericReturn(res); } async addGroup (group, attributes, params = null) { - return await this.#request(`/groups/${group.id}`, "POST", params); + const res = await this.#request(`/groups/${group.id}`, "POST", params); + return this.#handleGenericReturn(res); } async getGroup (group, params = null) { return await this.#request(`/groups/${group.id}`, "GET", params); } + async getAllGroups (params = null) { + if (!params) { + return null; + } + const res = await this.#request("/groups", "GET", params); + if (res.ok) { // if ok, return user data + const groups = res.data.groups; + const groupsFormatted = {}; + // label each user object by user@realm + for (const group of groups) { + groupsFormatted[`${group.attributes.cn}@${this.#realm}`] = group; + } + return groupsFormatted; + } + else { // else return null + return null; + } + } + async setGroup (group, attributes, params = null) { // not implemented, LDAP groups do not have any attributes to change + return null; } async delGroup (group, params = null) { - return await this.#request(`/groups/${group.id}`, "DELETE", params); + const res = await this.#request(`/groups/${group.id}`, "DELETE", params); + return this.#handleGenericReturn(res); } async addUserToGroup (user, group, params = null) { - return await this.#request(`/groups/${group.id}/members/${user.id}`, "POST", params); + const res = await this.#request(`/groups/${group.id}/members/${user.id}`, "POST", params); + return this.#handleGenericReturn(res); } async delUserFromGroup (user, group, params = null) { - return await this.#request(`/groups/${group.id}/members/${user.id}`, "DELETE", params); + const res = await this.#request(`/groups/${group.id}/members/${user.id}`, "DELETE", params); + return this.#handleGenericReturn(res); } } diff --git a/src/utils.js b/src/utils.js index bbed7cd..8b5b369 100644 --- a/src/utils.js +++ b/src/utils.js @@ -36,7 +36,7 @@ export async function checkAuth (cookies, res, vmpath = null) { return false; } - if ((await global.userManager.getUser(userObj)) === null) { // check if user exists in database + if ((await global.userManager.getUser(userObj)) === null) { // check if user exists in database res.status(401).send({ auth, path: vmpath ? `${vmpath}/config` : "/version", error: `User ${cookies.username} not found in database.` }); res.end(); return false; @@ -348,7 +348,7 @@ export function getTimeLeft (timeout) { /** * Recursively import routes from target folder. * @param {Object} router or app object. - * @param {string} baseroute API route for each imported module. + * @param {string} baseroute base route of imported modules starting from the current path. * @param {string} target folder to import modules. * @param {string} from source folder of calling module, optional for imports from the same base directory. */