Adding sync user endpoint to server which can be used by the worker.
This commit is contained in:
parent
1aeb12b0aa
commit
8bf2e7278e
|
@ -152,6 +152,17 @@ exports.getDeployedAppID = appId => {
|
||||||
return appId
|
return appId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a deployed app ID to a development app ID.
|
||||||
|
*/
|
||||||
|
exports.getDevelopmentAppID = appId => {
|
||||||
|
if (!appId.startsWith(exports.APP_DEV_PREFIX)) {
|
||||||
|
const id = appId.split(exports.APP_PREFIX)[1]
|
||||||
|
return `${exports.APP_DEV_PREFIX}${id}`
|
||||||
|
}
|
||||||
|
return appId
|
||||||
|
}
|
||||||
|
|
||||||
exports.getCouchUrl = () => {
|
exports.getCouchUrl = () => {
|
||||||
if (!env.COUCH_DB_URL) return
|
if (!env.COUCH_DB_URL) return
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,14 @@ const {
|
||||||
getUserMetadataParams,
|
getUserMetadataParams,
|
||||||
} = require("../../db/utils")
|
} = require("../../db/utils")
|
||||||
const { InternalTables } = require("../../db/utils")
|
const { InternalTables } = require("../../db/utils")
|
||||||
const { getGlobalUsers } = require("../../utilities/global")
|
const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global")
|
||||||
const { getFullUser } = require("../../utilities/users")
|
const { getFullUser } = require("../../utilities/users")
|
||||||
const { isEqual } = require("lodash")
|
const { isEqual } = require("lodash")
|
||||||
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
const { BUILTIN_ROLE_IDS } = require("@budibase/auth/roles")
|
||||||
|
const { getDevelopmentAppID } = require("@budibase/auth/db")
|
||||||
|
const { doesDatabaseExist } = require("../../utilities")
|
||||||
|
|
||||||
exports.rawMetadata = async db => {
|
async function rawMetadata(db) {
|
||||||
return (
|
return (
|
||||||
await db.allDocs(
|
await db.allDocs(
|
||||||
getUserMetadataParams(null, {
|
getUserMetadataParams(null, {
|
||||||
|
@ -19,45 +21,80 @@ exports.rawMetadata = async db => {
|
||||||
).rows.map(row => row.doc)
|
).rows.map(row => row.doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function combineMetadataAndUser(user, metadata) {
|
||||||
|
// skip users with no access
|
||||||
|
if (user.roleId === BUILTIN_ROLE_IDS.PUBLIC) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
delete user._rev
|
||||||
|
const metadataId = generateUserMetadataID(user._id)
|
||||||
|
const newDoc = {
|
||||||
|
...user,
|
||||||
|
_id: metadataId,
|
||||||
|
tableId: InternalTables.USER_METADATA,
|
||||||
|
}
|
||||||
|
const found = Array.isArray(metadata)
|
||||||
|
? metadata.find(doc => doc._id === metadataId)
|
||||||
|
: metadata
|
||||||
|
// copy rev over for the purposes of equality check
|
||||||
|
if (found) {
|
||||||
|
newDoc._rev = found._rev
|
||||||
|
}
|
||||||
|
if (found == null || !isEqual(newDoc, found)) {
|
||||||
|
return {
|
||||||
|
...found,
|
||||||
|
...newDoc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
exports.syncGlobalUsers = async appId => {
|
exports.syncGlobalUsers = async appId => {
|
||||||
// sync user metadata
|
// sync user metadata
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
const [users, metadata] = await Promise.all([
|
const [users, metadata] = await Promise.all([
|
||||||
getGlobalUsers(appId),
|
getGlobalUsers(appId),
|
||||||
exports.rawMetadata(db),
|
rawMetadata(db),
|
||||||
])
|
])
|
||||||
const toWrite = []
|
const toWrite = []
|
||||||
for (let user of users) {
|
for (let user of users) {
|
||||||
// skip users with no access
|
const combined = await combineMetadataAndUser(user, metadata)
|
||||||
if (user.roleId === BUILTIN_ROLE_IDS.PUBLIC) {
|
if (combined) {
|
||||||
continue
|
toWrite.push(combined)
|
||||||
}
|
|
||||||
delete user._rev
|
|
||||||
const metadataId = generateUserMetadataID(user._id)
|
|
||||||
const newDoc = {
|
|
||||||
...user,
|
|
||||||
_id: metadataId,
|
|
||||||
tableId: InternalTables.USER_METADATA,
|
|
||||||
}
|
|
||||||
const found = metadata.find(doc => doc._id === metadataId)
|
|
||||||
// copy rev over for the purposes of equality check
|
|
||||||
if (found) {
|
|
||||||
newDoc._rev = found._rev
|
|
||||||
}
|
|
||||||
if (found == null || !isEqual(newDoc, found)) {
|
|
||||||
toWrite.push({
|
|
||||||
...found,
|
|
||||||
...newDoc,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await db.bulkDocs(toWrite)
|
await db.bulkDocs(toWrite)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.syncUser = async function (ctx) {
|
||||||
|
const user = await getRawGlobalUser(ctx.params.id)
|
||||||
|
const roles = user.roles
|
||||||
|
delete user.roles
|
||||||
|
for (let [prodAppId, roleId] of Object.entries(roles)) {
|
||||||
|
if (roleId === BUILTIN_ROLE_IDS.PUBLIC) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const devAppId = getDevelopmentAppID(prodAppId)
|
||||||
|
for (let appId of [prodAppId, devAppId]) {
|
||||||
|
if (!(await doesDatabaseExist(appId))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const db = new CouchDB(appId)
|
||||||
|
const userId = generateUserMetadataID(user._id)
|
||||||
|
const metadata = await db.get(userId)
|
||||||
|
const combined = combineMetadataAndUser(user, metadata)
|
||||||
|
await db.put(combined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.body = {
|
||||||
|
message: "User synced.",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
exports.fetchMetadata = async function (ctx) {
|
exports.fetchMetadata = async function (ctx) {
|
||||||
const database = new CouchDB(ctx.appId)
|
const database = new CouchDB(ctx.appId)
|
||||||
const global = await getGlobalUsers(ctx.appId)
|
const global = await getGlobalUsers(ctx.appId)
|
||||||
const metadata = await exports.rawMetadata(database)
|
const metadata = await rawMetadata(database)
|
||||||
const users = []
|
const users = []
|
||||||
for (let user of global) {
|
for (let user of global) {
|
||||||
// find the metadata that matches up to the global ID
|
// find the metadata that matches up to the global ID
|
||||||
|
|
|
@ -34,5 +34,10 @@ router
|
||||||
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
||||||
controller.destroyMetadata
|
controller.destroyMetadata
|
||||||
)
|
)
|
||||||
|
.post(
|
||||||
|
"/api/users/sync/:id",
|
||||||
|
authorized(PermissionTypes.USER, PermissionLevels.WRITE),
|
||||||
|
controller.syncUser
|
||||||
|
)
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -46,9 +46,13 @@ exports.getCachedSelf = async (ctx, appId) => {
|
||||||
return processUser(appId, user)
|
return processUser(appId, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.getGlobalUser = async (appId, userId) => {
|
exports.getRawGlobalUser = async userId => {
|
||||||
const db = getGlobalDB()
|
const db = getGlobalDB()
|
||||||
let user = await db.get(getGlobalIDFromUserMetadataID(userId))
|
return db.get(getGlobalIDFromUserMetadataID(userId))
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getGlobalUser = async (appId, userId) => {
|
||||||
|
let user = await exports.getRawGlobalUser(userId)
|
||||||
return processUser(appId, user)
|
return processUser(appId, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -134,3 +134,9 @@ exports.stringToReadStream = string => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.doesDatabaseExist = async dbName => {
|
||||||
|
const db = new CouchDB(dbName, { skip_setup: true })
|
||||||
|
const info = await db.info()
|
||||||
|
return info && !info.error
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue