Sync global-info users to fix login + prevent double password hashing
This commit is contained in:
parent
a53bc1ec07
commit
1b6b877546
|
@ -37,4 +37,8 @@ export const DEFINITIONS: MigrationDefinition[] = [
|
|||
type: MigrationType.INSTALLATION,
|
||||
name: MigrationName.EVENT_INSTALLATION_BACKFILL,
|
||||
},
|
||||
{
|
||||
type: MigrationType.GLOBAL,
|
||||
name: MigrationName.GLOBAL_INFO_SYNC_USERS,
|
||||
},
|
||||
]
|
||||
|
|
|
@ -46,6 +46,7 @@ export enum MigrationName {
|
|||
EVENT_APP_BACKFILL = "event_app_backfill",
|
||||
EVENT_GLOBAL_BACKFILL = "event_global_backfill",
|
||||
EVENT_INSTALLATION_BACKFILL = "event_installation_backfill",
|
||||
GLOBAL_INFO_SYNC_USERS = "global_info_sync_users",
|
||||
}
|
||||
|
||||
export interface MigrationDefinition {
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
const { migrate, MIGRATIONS } = require("../../../migrations")
|
||||
|
||||
export const runMigrations = async (ctx: any) => {
|
||||
const options = ctx.request.body
|
||||
// don't await as can take a while, just return
|
||||
migrate(options)
|
||||
ctx.status = 200
|
||||
}
|
||||
|
||||
export const fetchDefinitions = async (ctx: any) => {
|
||||
ctx.body = MIGRATIONS
|
||||
ctx.status = 200
|
||||
}
|
|
@ -106,7 +106,10 @@ router
|
|||
if (ctx.publicEndpoint) {
|
||||
return next()
|
||||
}
|
||||
if ((!ctx.isAuthenticated || !ctx.user.budibaseAccess) && !ctx.internal) {
|
||||
if (
|
||||
(!ctx.isAuthenticated || (ctx.user && !ctx.user.budibaseAccess)) &&
|
||||
!ctx.internal
|
||||
) {
|
||||
ctx.throw(403, "Unauthorized - no public worker access")
|
||||
}
|
||||
return next()
|
||||
|
|
|
@ -12,6 +12,7 @@ const tenantsRoutes = require("./system/tenants")
|
|||
const statusRoutes = require("./system/status")
|
||||
const selfRoutes = require("./global/self")
|
||||
const licenseRoutes = require("./global/license")
|
||||
const migrationRoutes = require("./system/migrations")
|
||||
|
||||
let userGroupRoutes = api.groups
|
||||
exports.routes = [
|
||||
|
@ -29,4 +30,5 @@ exports.routes = [
|
|||
selfRoutes,
|
||||
licenseRoutes,
|
||||
userGroupRoutes,
|
||||
migrationRoutes,
|
||||
]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import Router from "@koa/router"
|
||||
import * as migrationsController from "../../controllers/system/migrations"
|
||||
import { auth } from "@budibase/backend-core"
|
||||
|
||||
const router = new Router()
|
||||
|
||||
router
|
||||
.post(
|
||||
"/api/system/migrations/run",
|
||||
auth.internalApi,
|
||||
migrationsController.runMigrations
|
||||
)
|
||||
.get(
|
||||
"/api/system/migrations/definitions",
|
||||
auth.internalApi,
|
||||
migrationsController.fetchDefinitions
|
||||
)
|
||||
|
||||
export = router
|
|
@ -0,0 +1,20 @@
|
|||
import { User } from "@budibase/types"
|
||||
import * as sdk from "../../sdk"
|
||||
|
||||
/**
|
||||
* Date:
|
||||
* Aug 2022
|
||||
*
|
||||
* Description:
|
||||
* Re-sync the global-db users to the global-info db users
|
||||
*/
|
||||
export const run = async (globalDb: any) => {
|
||||
const users = (await sdk.users.allUsers()) as User[]
|
||||
const promises = []
|
||||
for (let user of users) {
|
||||
promises.push(
|
||||
sdk.users.addTenant(user.tenantId, user._id as string, user.email)
|
||||
)
|
||||
}
|
||||
await Promise.all(promises)
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
import { migrations, redis } from "@budibase/backend-core"
|
||||
import { Migration, MigrationOptions, MigrationName } from "@budibase/types"
|
||||
import env from "../environment"
|
||||
|
||||
// migration functions
|
||||
import * as syncUserInfo from "./functions/globalInfoSyncUsers"
|
||||
|
||||
/**
|
||||
* Populate the migration function and additional configuration from
|
||||
* the static migration definitions.
|
||||
*/
|
||||
export const buildMigrations = () => {
|
||||
const definitions = migrations.DEFINITIONS
|
||||
const workerMigrations: Migration[] = []
|
||||
|
||||
for (const definition of definitions) {
|
||||
switch (definition.name) {
|
||||
case MigrationName.GLOBAL_INFO_SYNC_USERS: {
|
||||
// only needed in cloud
|
||||
if (!env.SELF_HOSTED) {
|
||||
workerMigrations.push({
|
||||
...definition,
|
||||
fn: syncUserInfo.run,
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return workerMigrations
|
||||
}
|
||||
|
||||
export const MIGRATIONS = buildMigrations()
|
||||
|
||||
export const migrate = async (options?: MigrationOptions) => {
|
||||
if (env.SELF_HOSTED) {
|
||||
await migrateWithLock(options)
|
||||
} else {
|
||||
await migrations.runMigrations(MIGRATIONS, options)
|
||||
}
|
||||
}
|
||||
|
||||
const migrateWithLock = async (options?: MigrationOptions) => {
|
||||
// get a new lock client
|
||||
const redlock = await redis.clients.getMigrationsRedlock()
|
||||
// lock for 15 minutes
|
||||
const ttl = 1000 * 60 * 15
|
||||
|
||||
let migrationLock
|
||||
|
||||
// acquire lock
|
||||
try {
|
||||
migrationLock = await redlock.lock("migrations", ttl)
|
||||
} catch (e: any) {
|
||||
if (e.name === "LockError") {
|
||||
return
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
// run migrations
|
||||
try {
|
||||
await migrations.runMigrations(MIGRATIONS, options)
|
||||
} finally {
|
||||
// release lock
|
||||
try {
|
||||
await migrationLock.unlock()
|
||||
} catch (e) {
|
||||
console.error("unable to release migration lock")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -106,7 +106,6 @@ const buildUser = async (
|
|||
opts: SaveUserOpts = {
|
||||
hashPassword: true,
|
||||
requirePassword: true,
|
||||
bulkCreate: false,
|
||||
},
|
||||
tenantId: string,
|
||||
dbUser?: any
|
||||
|
@ -185,15 +184,7 @@ export const save = async (
|
|||
dbUser = await db.get(_id)
|
||||
}
|
||||
|
||||
let builtUser = await buildUser(
|
||||
user,
|
||||
{
|
||||
hashPassword: true,
|
||||
requirePassword: user.requirePassword,
|
||||
},
|
||||
tenantId,
|
||||
dbUser
|
||||
)
|
||||
let builtUser = await buildUser(user, opts, tenantId, dbUser)
|
||||
|
||||
// make sure we set the _id field for a new user
|
||||
if (!_id) {
|
||||
|
@ -298,7 +289,6 @@ export const bulkCreate = async (
|
|||
{
|
||||
hashPassword: true,
|
||||
requirePassword: user.requirePassword,
|
||||
bulkCreate: false,
|
||||
},
|
||||
tenantId
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue