From ade007482cba4a4c413c082bf633327331e5166a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 19 Apr 2021 16:26:33 +0100 Subject: [PATCH] Updating the server to remove use of the email in the user ID. --- packages/server/src/api/controllers/auth.js | 69 +------------------ packages/server/src/api/controllers/row.js | 13 ++-- packages/server/src/api/controllers/user.js | 53 +++++++------- .../server/src/api/routes/tests/auth.spec.js | 15 ++-- .../src/api/routes/tests/routing.spec.js | 5 -- .../server/src/api/routes/tests/user.spec.js | 43 +++++------- .../routes/tests/utilities/TestFunctions.js | 16 ++--- .../src/api/routes/tests/utilities/index.js | 9 +++ packages/server/src/api/routes/user.js | 4 +- .../src/automations/tests/createUser.spec.js | 1 + packages/server/src/constants/index.js | 1 + packages/server/src/db/utils.js | 16 ++--- packages/server/src/middleware/currentapp.js | 7 +- .../src/middleware/tests/currentapp.spec.js | 4 +- .../src/tests/utilities/TestConfiguration.js | 34 +++------ packages/server/src/utilities/users.js | 20 +++--- .../server/src/utilities/workerRequests.js | 21 +++--- 17 files changed, 119 insertions(+), 212 deletions(-) diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index 5cf87d5a57..2ac3d30e48 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -1,75 +1,8 @@ -const jwt = require("jsonwebtoken") const CouchDB = require("../../db") -const bcrypt = require("../../utilities/bcrypt") -const env = require("../../environment") -const { getAPIKey } = require("../../utilities/usageQuota") -const { generateUserMetadataID } = require("../../db/utils") -const { setCookie } = require("../../utilities") const { outputProcessing } = require("../../utilities/rowProcessor") const { InternalTables } = require("../../db/utils") -const { UserStatus } = require("@budibase/auth") const { getFullUser } = require("../../utilities/users") -const INVALID_ERR = "Invalid Credentials" - -exports.authenticate = async ctx => { - const appId = ctx.appId - if (!appId) ctx.throw(400, "No appId") - - const { email, password } = ctx.request.body - - if (!email) ctx.throw(400, "Email Required.") - if (!password) ctx.throw(400, "Password Required.") - - // Check the user exists in the instance DB by email - const db = new CouchDB(appId) - const app = await db.get(appId) - - let dbUser - try { - dbUser = await db.get(generateUserMetadataID(email)) - } catch (_) { - // do not want to throw a 404 - as this could be - // used to determine valid emails - ctx.throw(401, INVALID_ERR) - } - - // check that the user is currently inactive, if this is the case throw invalid - if (dbUser.status === UserStatus.INACTIVE) { - ctx.throw(401, INVALID_ERR) - } - - // authenticate - if (await bcrypt.compare(password, dbUser.password)) { - const payload = { - userId: dbUser._id, - roleId: dbUser.roleId, - version: app.version, - } - // if in prod add the user api key, unless self hosted - /* istanbul ignore next */ - if (env.isProd() && !env.SELF_HOSTED) { - const { apiKey } = await getAPIKey(ctx.appId) - payload.apiKey = apiKey - } - - const token = jwt.sign(payload, ctx.config.jwtSecret, { - expiresIn: "1 day", - }) - - setCookie(ctx, token, appId) - - delete dbUser.password - ctx.body = { - token, - ...dbUser, - appId, - } - } else { - ctx.throw(401, INVALID_ERR) - } -} - exports.fetchSelf = async ctx => { if (!ctx.user) { ctx.throw(403, "No user logged in") @@ -82,7 +15,7 @@ exports.fetchSelf = async ctx => { return } - const user = await getFullUser({ ctx, userId: userId }) + const user = await getFullUser(ctx, userId) if (appId) { const db = new CouchDB(appId) diff --git a/packages/server/src/api/controllers/row.js b/packages/server/src/api/controllers/row.js index 2987cbeace..3ceac0d832 100644 --- a/packages/server/src/api/controllers/row.js +++ b/packages/server/src/api/controllers/row.js @@ -42,7 +42,7 @@ async function findRow(ctx, db, tableId, rowId) { // TODO remove special user case in future if (tableId === InternalTables.USER_METADATA) { ctx.params = { - userId: rowId, + id: rowId, } await userController.findMetadata(ctx) row = ctx.body @@ -140,12 +140,7 @@ exports.save = async function(ctx) { } if (!inputs._rev && !inputs._id) { - // TODO remove special user case in future - if (inputs.tableId === InternalTables.USER_METADATA) { - inputs._id = generateUserMetadataID(inputs.email) - } else { - inputs._id = generateRowID(inputs.tableId) - } + inputs._id = generateRowID(inputs.tableId) } // this returns the table and row incase they have been updated @@ -342,7 +337,7 @@ exports.destroy = async function(ctx) { // TODO remove special user case in future if (ctx.params.tableId === InternalTables.USER_METADATA) { ctx.params = { - userId: ctx.params.rowId, + id: ctx.params.rowId, } await userController.destroyMetadata(ctx) } else { @@ -449,7 +444,7 @@ async function bulkDelete(ctx) { updates = updates.concat( rows.map(row => { ctx.params = { - userId: row._id, + id: row._id, } return userController.destroyMetadata(ctx) }) diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 28576194c0..eee1f3f048 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -2,7 +2,7 @@ const CouchDB = require("../../db") const { generateUserMetadataID, getUserMetadataParams, - getEmailFromUserMetadataID, + getGlobalIDFromUserMetadataID, } = require("../../db/utils") const { InternalTables } = require("../../db/utils") const { getRole } = require("../../utilities/security/roles") @@ -25,15 +25,14 @@ exports.fetchMetadata = async function(ctx) { ).rows.map(row => row.doc) const users = [] for (let user of global) { - const info = metadata.find(meta => meta._id.includes(user.email)) + // find the metadata that matches up to the global ID + const info = metadata.find(meta => meta._id.includes(user._id)) // remove these props, not for the correct DB - delete user._id - delete user._rev users.push({ ...user, ...info, // make sure the ID is always a local ID, not a global one - _id: generateUserMetadataID(user.email), + _id: generateUserMetadataID(user._id), }) } ctx.body = users @@ -43,17 +42,16 @@ exports.createMetadata = async function(ctx) { const appId = ctx.appId const db = new CouchDB(appId) const { roleId } = ctx.request.body - const email = ctx.request.body.email || ctx.user.email // check role valid const role = await getRole(appId, roleId) if (!role) ctx.throw(400, "Invalid Role") - const metadata = await saveGlobalUser(ctx, appId, email, ctx.request.body) + const globalUser = await saveGlobalUser(ctx, appId, ctx.request.body) const user = { - ...metadata, - _id: generateUserMetadataID(email), + ...globalUser, + _id: generateUserMetadataID(globalUser._id), type: "user", tableId: InternalTables.USER_METADATA, } @@ -64,7 +62,7 @@ exports.createMetadata = async function(ctx) { ctx.body = { _id: response.id, _rev: response.rev, - email, + email: ctx.request.body.email, } } @@ -72,39 +70,34 @@ exports.updateMetadata = async function(ctx) { const appId = ctx.appId const db = new CouchDB(appId) const user = ctx.request.body - let email = user.email || getEmailFromUserMetadataID(user._id) - const metadata = await saveGlobalUser(ctx, appId, email, ctx.request.body) - if (!metadata._id) { - metadata._id = generateUserMetadataID(email) + const globalUser = await saveGlobalUser( + ctx, + appId, + getGlobalIDFromUserMetadataID(user._id), + ctx.request.body + ) + const metadata = { + ...globalUser, + _id: user._id || generateUserMetadataID(globalUser._id), + _rev: ctx.request.body._rev, } - if (!metadata._rev) { - metadata._rev = ctx.request.body._rev - } - ctx.body = await db.put({ - ...metadata, - }) + ctx.body = await db.put(metadata) } exports.destroyMetadata = async function(ctx) { const db = new CouchDB(ctx.appId) - const email = - ctx.params.email || getEmailFromUserMetadataID(ctx.params.userId) - await deleteGlobalUser(ctx, email) + await deleteGlobalUser(ctx, getGlobalIDFromUserMetadataID(ctx.params.id)) try { - const dbUser = await db.get(generateUserMetadataID(email)) + const dbUser = await db.get(ctx.params.id) await db.remove(dbUser._id, dbUser._rev) } catch (err) { // error just means the global user has no config in this app } ctx.body = { - message: `User ${ctx.params.email} deleted.`, + message: `User ${ctx.params.id} deleted.`, } } exports.findMetadata = async function(ctx) { - ctx.body = await getFullUser({ - ctx, - email: ctx.params.email, - userId: ctx.params.userId, - }) + ctx.body = await getFullUser(ctx, ctx.params.id) } diff --git a/packages/server/src/api/routes/tests/auth.spec.js b/packages/server/src/api/routes/tests/auth.spec.js index ec38003c1d..5978381f86 100644 --- a/packages/server/src/api/routes/tests/auth.spec.js +++ b/packages/server/src/api/routes/tests/auth.spec.js @@ -1,13 +1,18 @@ const setup = require("./utilities") +const { generateUserMetadataID } = require("../../../db/utils") require("../../../utilities/workerRequests") jest.mock("../../../utilities/workerRequests", () => ({ getGlobalUsers: jest.fn(() => { return { - email: "test@test.com", + _id: "us_uuid1", + } + }), + saveGlobalUser: jest.fn(() => { + return { + _id: "us_uuid1", } }), - saveGlobalUser: jest.fn(), })) describe("/authenticate", () => { @@ -22,14 +27,14 @@ describe("/authenticate", () => { describe("fetch self", () => { it("should be able to fetch self", async () => { - await config.createUser("test@test.com", "p4ssw0rd") - const headers = await config.login("test@test.com", "p4ssw0rd") + const user = await config.createUser("test@test.com", "p4ssw0rd") + const headers = await config.login("test@test.com", "p4ssw0rd", { userId: user._id }) const res = await request .get(`/api/self`) .set(headers) .expect("Content-Type", /json/) .expect(200) - expect(res.body.email).toEqual("test@test.com") + expect(res.body._id).toEqual(generateUserMetadataID("us_uuid1")) }) }) }) \ No newline at end of file diff --git a/packages/server/src/api/routes/tests/routing.spec.js b/packages/server/src/api/routes/tests/routing.spec.js index 79b28e82dd..5fe0e26f15 100644 --- a/packages/server/src/api/routes/tests/routing.spec.js +++ b/packages/server/src/api/routes/tests/routing.spec.js @@ -4,11 +4,6 @@ const { checkBuilderEndpoint } = require("./utilities/TestFunctions") const { BUILTIN_ROLE_IDS } = require("../../../utilities/security/roles") const workerRequests = require("../../../utilities/workerRequests") -jest.mock("../../../utilities/workerRequests", () => ({ - getGlobalUsers: jest.fn(), - saveGlobalUser: jest.fn(), -})) - const route = "/test" describe("/routing", () => { diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.js index 3c4d6a09e6..e80672284d 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.js @@ -7,7 +7,10 @@ const workerRequests = require("../../../utilities/workerRequests") jest.mock("../../../utilities/workerRequests", () => ({ getGlobalUsers: jest.fn(), saveGlobalUser: jest.fn(() => { - return {} + const uuid = require("uuid/v4") + return { + _id: `us_${uuid()}` + } }), deleteGlobalUser: jest.fn(), })) @@ -26,10 +29,10 @@ describe("/users", () => { beforeEach(() => { workerRequests.getGlobalUsers.mockImplementationOnce(() => ([ { - email: "brenda@brenda.com" + _id: "us_uuid1", }, { - email: "pam@pam.com" + _id: "us_uuid2", } ] )) @@ -45,8 +48,8 @@ describe("/users", () => { .expect(200) expect(res.body.length).toBe(2) - expect(res.body.find(u => u.email === "brenda@brenda.com")).toBeDefined() - expect(res.body.find(u => u.email === "pam@pam.com")).toBeDefined() + expect(res.body.find(u => u._id === `ro_ta_users_us_uuid1`)).toBeDefined() + expect(res.body.find(u => u._id === `ro_ta_users_us_uuid2`)).toBeDefined() }) it("should apply authorization to endpoint", async () => { @@ -66,10 +69,10 @@ describe("/users", () => { beforeEach(() => { workerRequests.getGlobalUsers.mockImplementationOnce(() => ([ { - email: "bill@budibase.com" + _id: "us_uuid1", }, { - email: "brandNewUser@user.com" + _id: "us_uuid2", } ] )) @@ -86,7 +89,6 @@ describe("/users", () => { it("returns a success message when a user is successfully created", async () => { const body = basicUser(BUILTIN_ROLE_IDS.POWER) - body.email = "bill@budibase.com" const res = await create(body) expect(res.res.statusMessage).toEqual("OK") @@ -95,7 +97,6 @@ describe("/users", () => { it("should apply authorization to endpoint", async () => { const body = basicUser(BUILTIN_ROLE_IDS.POWER) - body.email = "brandNewUser@user.com" await checkPermissionsEndpoint({ config, method: "POST", @@ -110,13 +111,6 @@ describe("/users", () => { const user = basicUser(null) await create(user, 400) }) - - it("should throw error if user exists already", async () => { - await config.createUser("test@test.com") - const user = basicUser(BUILTIN_ROLE_IDS.POWER) - user.email = "test@test.com" - await create(user, 409) - }) }) describe("update", () => { @@ -141,10 +135,9 @@ describe("/users", () => { describe("destroy", () => { it("should be able to delete the user", async () => { - const email = "test@test.com" - await config.createUser(email) + const user = await config.createUser() const res = await request - .delete(`/api/users/metadata/${email}`) + .delete(`/api/users/metadata/${user._id}`) .set(config.defaultHeaders()) .expect(200) .expect("Content-Type", /json/) @@ -156,21 +149,23 @@ describe("/users", () => { describe("find", () => { beforeEach(() => { jest.resetAllMocks() + workerRequests.saveGlobalUser.mockImplementationOnce(() => ({ + _id: "us_uuid1", + })) workerRequests.getGlobalUsers.mockImplementationOnce(() => ({ - email: "test@test.com", + _id: "us_uuid1", roleId: BUILTIN_ROLE_IDS.POWER, })) }) it("should be able to find the user", async () => { - const email = "test@test.com" - await config.createUser(email) + const user = await config.createUser() const res = await request - .get(`/api/users/metadata/${email}`) + .get(`/api/users/metadata/${user._id}`) .set(config.defaultHeaders()) .expect(200) .expect("Content-Type", /json/) - expect(res.body.email).toEqual(email) + expect(res.body._id).toEqual(user._id) expect(res.body.roleId).toEqual(BUILTIN_ROLE_IDS.POWER) expect(res.body.tableId).toBeDefined() }) diff --git a/packages/server/src/api/routes/tests/utilities/TestFunctions.js b/packages/server/src/api/routes/tests/utilities/TestFunctions.js index 0bcb4512a7..9ee68c283f 100644 --- a/packages/server/src/api/routes/tests/utilities/TestFunctions.js +++ b/packages/server/src/api/routes/tests/utilities/TestFunctions.js @@ -63,11 +63,9 @@ exports.checkPermissionsEndpoint = async ({ }) => { const password = "PASSWORD" await config.createUser("passUser@budibase.com", password, passRole) - const passHeader = await config.login( - "passUser@budibase.com", - password, - passRole - ) + const passHeader = await config.login("passUser@budibase.com", password, { + roleId: passRole, + }) await exports .createRequest(config.request, method, url, body) @@ -75,11 +73,9 @@ exports.checkPermissionsEndpoint = async ({ .expect(200) await config.createUser("failUser@budibase.com", password, failRole) - const failHeader = await config.login( - "failUser@budibase.com", - password, - failRole - ) + const failHeader = await config.login("failUser@budibase.com", password, { + roleId: failRole, + }) await exports .createRequest(config.request, method, url, body) diff --git a/packages/server/src/api/routes/tests/utilities/index.js b/packages/server/src/api/routes/tests/utilities/index.js index 3bd3886a31..e9361aa67d 100644 --- a/packages/server/src/api/routes/tests/utilities/index.js +++ b/packages/server/src/api/routes/tests/utilities/index.js @@ -2,6 +2,15 @@ const TestConfig = require("../../../../tests/utilities/TestConfiguration") const structures = require("../../../../tests/utilities/structures") const env = require("../../../../environment") +jest.mock("../../../../utilities/workerRequests", () => ({ + getGlobalUsers: jest.fn(), + saveGlobalUser: jest.fn(() => { + return { + _id: "us_uuid1", + } + }), +})) + exports.delay = ms => new Promise(resolve => setTimeout(resolve, ms)) let request, config diff --git a/packages/server/src/api/routes/user.js b/packages/server/src/api/routes/user.js index b0450b72cc..bafb648fc6 100644 --- a/packages/server/src/api/routes/user.js +++ b/packages/server/src/api/routes/user.js @@ -16,7 +16,7 @@ router controller.fetchMetadata ) .get( - "/api/users/metadata/:email", + "/api/users/metadata/:id", authorized(PermissionTypes.USER, PermissionLevels.READ), controller.findMetadata ) @@ -32,7 +32,7 @@ router controller.createMetadata ) .delete( - "/api/users/metadata/:email", + "/api/users/metadata/:id", authorized(PermissionTypes.USER, PermissionLevels.WRITE), usage, controller.destroyMetadata diff --git a/packages/server/src/automations/tests/createUser.spec.js b/packages/server/src/automations/tests/createUser.spec.js index f085d52712..7291b75505 100644 --- a/packages/server/src/automations/tests/createUser.spec.js +++ b/packages/server/src/automations/tests/createUser.spec.js @@ -25,6 +25,7 @@ describe("test the create user action", () => { expect(res.id).toBeDefined() expect(res.revision).toBeDefined() const userDoc = await config.getRow(InternalTables.USER_METADATA, res.id) + expect(userDoc).toBeDefined() }) it("should return an error if no inputs provided", async () => { diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 940c1100dd..5b4291998e 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -33,6 +33,7 @@ exports.USERS_TABLE_SCHEMA = { type: "table", views: {}, name: "Users", + // TODO: ADMIN PANEL - when implemented this doesn't need to be carried out schema: { email: { type: exports.FieldTypes.STRING, diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index 5cd9e1b31f..e6bcfada5b 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -127,23 +127,23 @@ exports.generateRowID = (tableId, id = null) => { /** * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ -exports.getUserMetadataParams = (email = "", otherProps = {}) => { - return exports.getRowParams(InternalTables.USER_METADATA, email, otherProps) +exports.getUserMetadataParams = (userId = null, otherProps = {}) => { + return exports.getRowParams(InternalTables.USER_METADATA, userId, otherProps) } /** - * Generates a new user ID based on the passed in email. - * @param {string} email The email which the ID is going to be built up of. + * Generates a new user ID based on the passed in global ID. + * @param {string} globalId The ID of the global user. * @returns {string} The new user ID which the user doc can be stored under. */ -exports.generateUserMetadataID = email => { - return exports.generateRowID(InternalTables.USER_METADATA, email) +exports.generateUserMetadataID = globalId => { + return exports.generateRowID(InternalTables.USER_METADATA, globalId) } /** - * Breaks up the ID to get the email address back out of it. + * Breaks up the ID to get the global ID. */ -exports.getEmailFromUserMetadataID = id => { +exports.getGlobalIDFromUserMetadataID = id => { return id.split( `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}` )[1] diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index 6616888c57..89c46c6bff 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -1,6 +1,5 @@ const { getAppId, setCookie, getCookie, Cookies } = require("@budibase/auth") const { getRole } = require("../utilities/security/roles") -const { generateUserMetadataID } = require("../db/utils") const { getGlobalUsers } = require("../utilities/workerRequests") const { BUILTIN_ROLE_IDS } = require("../utilities/security/roles") @@ -40,14 +39,10 @@ module.exports = async (ctx, next) => { if (appId) { ctx.appId = appId if (roleId) { - const userId = ctx.user - ? generateUserMetadataID(ctx.user.email) - : undefined ctx.roleId = roleId ctx.user = { ...ctx.user, - _id: userId, - userId, + _id: ctx.user ? ctx.user.userId : null, role: await getRole(appId, roleId), } } diff --git a/packages/server/src/middleware/tests/currentapp.spec.js b/packages/server/src/middleware/tests/currentapp.spec.js index 44c1c6b7ad..3ed17bb521 100644 --- a/packages/server/src/middleware/tests/currentapp.spec.js +++ b/packages/server/src/middleware/tests/currentapp.spec.js @@ -5,7 +5,7 @@ function mockWorker() { jest.mock("../../utilities/workerRequests", () => ({ getGlobalUsers: () => { return { - email: "test@test.com", + email: "us_uuid1", roles: { "app_test": "BASIC", } @@ -59,7 +59,7 @@ class TestConfiguration { setUser() { this.ctx.user = { - email: "test@test.com", + userId: "ro_ta_user_us_uuid1", } } diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 42ff603139..e4510905b5 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -70,8 +70,7 @@ class TestConfiguration { defaultHeaders() { const user = { - userId: "us_test@test.com", - email: "test@test.com", + userId: "ro_ta_user_us_uuid1", builder: { global: true, }, @@ -106,12 +105,13 @@ class TestConfiguration { } async roleHeaders(email = EMAIL, roleId = BUILTIN_ROLE_IDS.ADMIN) { + let user try { - await this.createUser(email, PASSWORD, roleId) + user = await this.createUser(email, PASSWORD, roleId) } catch (err) { // allow errors here } - return this.login(email, PASSWORD, roleId) + return this.login(email, PASSWORD, { roleId, userId: user._id }) } async createApp(appName) { @@ -293,33 +293,19 @@ class TestConfiguration { ) } - async makeUserInactive(email) { - const user = await this._req( - null, - { - email, - }, - controllers.user.findMetadata - ) - return this._req( - { - ...user, - status: "inactive", - }, - null, - controllers.user.updateMetadata - ) - } - - async login(email, password, roleId = BUILTIN_ROLE_IDS.BUILDER) { + async login(email, password, { roleId, userId } = {}) { + if (!roleId) { + roleId = BUILTIN_ROLE_IDS.BUILDER + } if (!this.request) { throw "Server has not been opened, cannot login." } if (!email || !password) { await this.createUser() } + // have to fake this const user = { - userId: `us_${email || EMAIL}`, + userId: userId || `ro_ta_users_us_uuid1`, email: email || EMAIL, } const app = { diff --git a/packages/server/src/utilities/users.js b/packages/server/src/utilities/users.js index 319a0cfa41..4c637c1865 100644 --- a/packages/server/src/utilities/users.js +++ b/packages/server/src/utilities/users.js @@ -1,20 +1,18 @@ const CouchDB = require("../db") -const { - generateUserMetadataID, - getEmailFromUserMetadataID, -} = require("../db/utils") +const { getGlobalIDFromUserMetadataID } = require("../db/utils") const { getGlobalUsers } = require("../utilities/workerRequests") -exports.getFullUser = async ({ ctx, email, userId }) => { - if (!email) { - email = getEmailFromUserMetadataID(userId) - } - const global = await getGlobalUsers(ctx, ctx.appId, email) +exports.getFullUser = async (ctx, userId) => { + const global = await getGlobalUsers( + ctx, + ctx.appId, + getGlobalIDFromUserMetadataID(userId) + ) let metadata try { // this will throw an error if the db doesn't exist, or there is no appId const db = new CouchDB(ctx.appId) - metadata = await db.get(generateUserMetadataID(email)) + metadata = await db.get(userId) } catch (err) { // it is fine if there is no user metadata, just remove global db info delete global._id @@ -24,6 +22,6 @@ exports.getFullUser = async ({ ctx, email, userId }) => { ...global, ...metadata, // make sure the ID is always a local ID, not a global one - _id: generateUserMetadataID(email), + _id: userId, } } diff --git a/packages/server/src/utilities/workerRequests.js b/packages/server/src/utilities/workerRequests.js index 93a7c26753..12dc5e9ff9 100644 --- a/packages/server/src/utilities/workerRequests.js +++ b/packages/server/src/utilities/workerRequests.js @@ -60,8 +60,8 @@ exports.getDeployedApps = async ctx => { } } -exports.deleteGlobalUser = async (ctx, email) => { - const endpoint = `/api/admin/users/${email}` +exports.deleteGlobalUser = async (ctx, globalId) => { + const endpoint = `/api/admin/users/${globalId}` const reqCfg = { method: "DELETE" } const response = await fetch( checkSlashesInUrl(env.WORKER_URL + endpoint), @@ -70,8 +70,10 @@ exports.deleteGlobalUser = async (ctx, email) => { return response.json() } -exports.getGlobalUsers = async (ctx, appId = null, email = null) => { - const endpoint = email ? `/api/admin/users/${email}` : `/api/admin/users` +exports.getGlobalUsers = async (ctx, appId = null, globalId = null) => { + const endpoint = globalId + ? `/api/admin/users/${globalId}` + : `/api/admin/users` const reqCfg = { method: "GET" } const response = await fetch( checkSlashesInUrl(env.WORKER_URL + endpoint), @@ -89,8 +91,8 @@ exports.getGlobalUsers = async (ctx, appId = null, email = null) => { return users } -exports.saveGlobalUser = async (ctx, appId, email, body) => { - const globalUser = await exports.getGlobalUsers(ctx, appId, email) +exports.saveGlobalUser = async (ctx, appId, body, globalId = null) => { + const globalUser = await exports.getGlobalUsers(ctx, appId, globalId) const roles = globalUser.roles || {} if (body.roleId) { roles[appId] = body.roleId @@ -100,9 +102,9 @@ exports.saveGlobalUser = async (ctx, appId, email, body) => { method: "POST", body: { ...globalUser, - email, password: body.password || undefined, status: body.status, + email: body.email, roles, builder: { global: true, @@ -124,5 +126,8 @@ exports.saveGlobalUser = async (ctx, appId, email, body) => { delete body.status delete body.roles delete body.builder - return body + return { + ...body, + _id: json._id, + } }