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