Fixing issues with the user table within the apps.
This commit is contained in:
parent
dbf8e426bc
commit
8c68f1c134
|
@ -190,7 +190,7 @@ exports.getAllApps = async ({ dev, all } = {}) => {
|
|||
} else {
|
||||
return apps.map(app => ({
|
||||
...app,
|
||||
status: isDevApp(app) ? "development" : "published"
|
||||
status: isDevApp(app) ? "development" : "published",
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,9 @@ exports.isClient = ctx => {
|
|||
* @return {Promise<object|null>}
|
||||
*/
|
||||
exports.getGlobalUserByEmail = async email => {
|
||||
if (email == null) {
|
||||
throw "Must supply an email address to view"
|
||||
}
|
||||
const db = getDB(StaticDatabases.GLOBAL.name)
|
||||
try {
|
||||
let users = (
|
||||
|
|
|
@ -85,10 +85,6 @@
|
|||
bind:value={row.email}
|
||||
readonly={!creating}
|
||||
/>
|
||||
<RowFieldControl
|
||||
meta={{ name: "password", type: "password" }}
|
||||
bind:value={row.password}
|
||||
/>
|
||||
<RowFieldControl
|
||||
meta={{ ...tableSchema.firstName, name: "First Name" }}
|
||||
bind:value={row.firstName}
|
||||
|
@ -107,16 +103,6 @@
|
|||
getOptionLabel={role => role.name}
|
||||
getOptionValue={role => role._id}
|
||||
/>
|
||||
<Select
|
||||
label="Status"
|
||||
bind:value={row.status}
|
||||
options={[
|
||||
{ label: "Active", value: "active" },
|
||||
{ label: "Inactive", value: "inactive" },
|
||||
]}
|
||||
getOptionLabel={status => status.label}
|
||||
getOptionValue={status => status.value}
|
||||
/>
|
||||
{#each customSchemaKeys as [key, meta]}
|
||||
{#if !meta.autocolumn}
|
||||
<RowFieldControl {meta} bind:value={row[key]} {creating} />
|
||||
|
|
|
@ -56,13 +56,28 @@ async function findRow(ctx, db, tableId, rowId) {
|
|||
exports.patch = async function (ctx) {
|
||||
const appId = ctx.appId
|
||||
const db = new CouchDB(appId)
|
||||
let dbRow = await db.get(ctx.params.rowId)
|
||||
let dbTable = await db.get(dbRow.tableId)
|
||||
const patchfields = ctx.request.body
|
||||
const inputs = ctx.request.body
|
||||
const tableId = inputs.tableId
|
||||
const isUserTable = tableId === InternalTables.USER_METADATA
|
||||
let dbRow
|
||||
try {
|
||||
dbRow = await db.get(ctx.params.rowId)
|
||||
} catch (err) {
|
||||
if (isUserTable) {
|
||||
// don't include the rev, it'll be the global rev
|
||||
// this time
|
||||
dbRow = {
|
||||
_id: inputs._id,
|
||||
}
|
||||
} else {
|
||||
ctx.throw(400, "Row does not exist")
|
||||
}
|
||||
}
|
||||
let dbTable = await db.get(tableId)
|
||||
// need to build up full patch fields before coerce
|
||||
for (let key of Object.keys(patchfields)) {
|
||||
for (let key of Object.keys(inputs)) {
|
||||
if (!dbTable.schema[key]) continue
|
||||
dbRow[key] = patchfields[key]
|
||||
dbRow[key] = inputs[key]
|
||||
}
|
||||
|
||||
// this returns the table and row incase they have been updated
|
||||
|
@ -90,13 +105,9 @@ exports.patch = async function (ctx) {
|
|||
table,
|
||||
})
|
||||
|
||||
// TODO remove special user case in future
|
||||
if (row.tableId === InternalTables.USER_METADATA) {
|
||||
if (isUserTable) {
|
||||
// the row has been updated, need to put it into the ctx
|
||||
ctx.request.body = {
|
||||
...row,
|
||||
password: ctx.request.body.password,
|
||||
}
|
||||
ctx.request.body = row
|
||||
await userController.updateMetadata(ctx)
|
||||
return
|
||||
}
|
||||
|
@ -129,12 +140,9 @@ exports.save = async function (ctx) {
|
|||
|
||||
// if the row obj had an _id then it will have been retrieved
|
||||
if (inputs._id && inputs._rev) {
|
||||
const existingRow = await db.get(inputs._id)
|
||||
if (existingRow) {
|
||||
ctx.params.rowId = inputs._id
|
||||
await exports.patch(ctx)
|
||||
return
|
||||
}
|
||||
ctx.params.rowId = inputs._id
|
||||
await exports.patch(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
if (!inputs._rev && !inputs._id) {
|
||||
|
@ -167,13 +175,6 @@ exports.save = async function (ctx) {
|
|||
table,
|
||||
})
|
||||
|
||||
if (row.tableId === InternalTables.USER_METADATA && row._id) {
|
||||
// the row has been updated, need to put it into the ctx
|
||||
ctx.request.body = row
|
||||
await userController.updateMetadata(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
row.type = "row"
|
||||
const response = await db.put(row)
|
||||
// don't worry about rev, tables handle rev/lastID updates
|
||||
|
|
|
@ -5,7 +5,10 @@ const {
|
|||
} = require("../../db/utils")
|
||||
const { InternalTables } = require("../../db/utils")
|
||||
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
||||
const { getGlobalUsers, addAppRoleToSelf } = require("../../utilities/workerRequests")
|
||||
const {
|
||||
getGlobalUsers,
|
||||
addAppRoleToUser,
|
||||
} = require("../../utilities/workerRequests")
|
||||
const { getFullUser } = require("../../utilities/users")
|
||||
|
||||
function removeGlobalProps(user) {
|
||||
|
@ -46,7 +49,7 @@ exports.updateSelfMetadata = async function (ctx) {
|
|||
ctx.request.body._id = ctx.user._id
|
||||
if (ctx.user.builder && ctx.user.builder.global) {
|
||||
// specific case, update self role in global user
|
||||
await addAppRoleToSelf(ctx, ctx.appId, BUILTIN_ROLE_IDS.ADMIN)
|
||||
await addAppRoleToUser(ctx, ctx.appId, BUILTIN_ROLE_IDS.ADMIN)
|
||||
}
|
||||
// make sure no stale rev
|
||||
delete ctx.request.body._rev
|
||||
|
@ -57,10 +60,12 @@ exports.updateMetadata = async function (ctx) {
|
|||
const appId = ctx.appId
|
||||
const db = new CouchDB(appId)
|
||||
const user = removeGlobalProps(ctx.request.body)
|
||||
if (user.roleId) {
|
||||
await addAppRoleToUser(ctx, appId, user.roleId, user._id)
|
||||
}
|
||||
const metadata = {
|
||||
tableId: InternalTables.USER_METADATA,
|
||||
_id: user._id,
|
||||
_rev: user._rev,
|
||||
...user,
|
||||
}
|
||||
ctx.body = await db.put(metadata)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ const env = require("../environment")
|
|||
const { checkSlashesInUrl } = require("./index")
|
||||
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
||||
const { getDeployedAppID } = require("@budibase/auth/db")
|
||||
const { getGlobalIDFromUserMetadataID } = require("../db/utils")
|
||||
|
||||
function getAppRole(appId, user) {
|
||||
if (!user.roles) {
|
||||
|
@ -131,21 +132,33 @@ exports.getGlobalSelf = async ctx => {
|
|||
return json
|
||||
}
|
||||
|
||||
exports.addAppRoleToSelf = async (ctx, appId, roleId) => {
|
||||
const self = await exports.getGlobalSelf(ctx)
|
||||
const endpoint = `/api/admin/users/self`
|
||||
const reqCfg = {
|
||||
method: "POST",
|
||||
body: {
|
||||
roles: {
|
||||
...self.roles,
|
||||
[appId]: roleId,
|
||||
}
|
||||
exports.addAppRoleToUser = async (ctx, appId, roleId, userId = null) => {
|
||||
appId = getDeployedAppID(appId)
|
||||
let user,
|
||||
endpoint,
|
||||
body = {}
|
||||
if (!userId) {
|
||||
user = await exports.getGlobalSelf(ctx)
|
||||
endpoint = `/api/admin/users/self`
|
||||
} else {
|
||||
userId = getGlobalIDFromUserMetadataID(userId)
|
||||
user = await exports.getGlobalUsers(ctx, appId, userId)
|
||||
body._id = userId
|
||||
endpoint = `/api/admin/users`
|
||||
}
|
||||
body = {
|
||||
...body,
|
||||
roles: {
|
||||
...user.roles,
|
||||
[appId]: roleId,
|
||||
},
|
||||
}
|
||||
const response = await fetch(
|
||||
checkSlashesInUrl(env.WORKER_URL + endpoint),
|
||||
request(ctx, reqCfg)
|
||||
request(ctx, {
|
||||
method: "POST",
|
||||
body,
|
||||
})
|
||||
)
|
||||
const json = await response.json()
|
||||
if (json.status !== 200 && response.status !== 200) {
|
||||
|
|
|
@ -16,9 +16,14 @@ exports.save = async ctx => {
|
|||
const { email, password, _id } = ctx.request.body
|
||||
|
||||
// make sure another user isn't using the same email
|
||||
const dbUser = await getGlobalUserByEmail(email)
|
||||
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
|
||||
ctx.throw(400, "Email address already in use.")
|
||||
let dbUser
|
||||
if (email) {
|
||||
dbUser = await getGlobalUserByEmail(email)
|
||||
if (dbUser != null && (dbUser._id !== _id || Array.isArray(dbUser))) {
|
||||
ctx.throw(400, "Email address already in use.")
|
||||
}
|
||||
} else {
|
||||
dbUser = await db.get(_id)
|
||||
}
|
||||
|
||||
// get the password, make sure one is defined
|
||||
|
|
Loading…
Reference in New Issue