Fix the bug, I think.
This commit is contained in:
parent
4170213c0d
commit
182a1df960
|
@ -1,17 +1,18 @@
|
||||||
|
import PouchDB from "pouchdb"
|
||||||
import { getPouchDB, closePouchDB } from "./couch"
|
import { getPouchDB, closePouchDB } from "./couch"
|
||||||
import { DocumentType } from "../constants"
|
import { DocumentType } from "../constants"
|
||||||
|
|
||||||
class Replication {
|
class Replication {
|
||||||
source: any
|
source: PouchDB.Database
|
||||||
target: any
|
target: PouchDB.Database
|
||||||
replication: any
|
replication?: Promise<any>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param source - the DB you want to replicate or rollback to
|
* @param source - the DB you want to replicate or rollback to
|
||||||
* @param target - the DB you want to replicate to, or rollback from
|
* @param target - the DB you want to replicate to, or rollback from
|
||||||
*/
|
*/
|
||||||
constructor({ source, target }: any) {
|
constructor({ source, target }: { source: string; target: string }) {
|
||||||
this.source = getPouchDB(source)
|
this.source = getPouchDB(source)
|
||||||
this.target = getPouchDB(target)
|
this.target = getPouchDB(target)
|
||||||
}
|
}
|
||||||
|
@ -40,7 +41,7 @@ class Replication {
|
||||||
* Two way replication operation, intended to be promise based.
|
* Two way replication operation, intended to be promise based.
|
||||||
* @param opts - PouchDB replication options
|
* @param opts - PouchDB replication options
|
||||||
*/
|
*/
|
||||||
sync(opts = {}) {
|
sync(opts: PouchDB.Replication.SyncOptions = {}) {
|
||||||
this.replication = this.promisify(this.source.sync, opts)
|
this.replication = this.promisify(this.source.sync, opts)
|
||||||
return this.replication
|
return this.replication
|
||||||
}
|
}
|
||||||
|
@ -49,18 +50,31 @@ class Replication {
|
||||||
* One way replication operation, intended to be promise based.
|
* One way replication operation, intended to be promise based.
|
||||||
* @param opts - PouchDB replication options
|
* @param opts - PouchDB replication options
|
||||||
*/
|
*/
|
||||||
replicate(opts = {}) {
|
replicate(opts: PouchDB.Replication.ReplicateOptions = {}) {
|
||||||
this.replication = this.promisify(this.source.replicate.to, opts)
|
this.replication = this.promisify(this.source.replicate.to, opts)
|
||||||
return this.replication
|
return this.replication
|
||||||
}
|
}
|
||||||
|
|
||||||
appReplicateOpts() {
|
appReplicateOpts(
|
||||||
|
opts: PouchDB.Replication.ReplicateOptions = {}
|
||||||
|
): PouchDB.Replication.ReplicateOptions {
|
||||||
|
if (typeof opts.filter === "string") {
|
||||||
|
return opts
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = opts.filter
|
||||||
|
delete opts.filter
|
||||||
|
|
||||||
return {
|
return {
|
||||||
filter: (doc: any) => {
|
...opts,
|
||||||
|
filter: (doc: any, params: any) => {
|
||||||
if (doc._id && doc._id.startsWith(DocumentType.AUTOMATION_LOG)) {
|
if (doc._id && doc._id.startsWith(DocumentType.AUTOMATION_LOG)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return doc._id !== DocumentType.APP_METADATA
|
if (doc._id === DocumentType.APP_METADATA) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return filter ? filter(doc, params) : true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,10 +89,6 @@ class Replication {
|
||||||
// take the opportunity to remove deleted tombstones
|
// take the opportunity to remove deleted tombstones
|
||||||
await this.replicate()
|
await this.replicate()
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel() {
|
|
||||||
this.replication.cancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Replication
|
export default Replication
|
||||||
|
|
|
@ -101,10 +101,7 @@ export function getBuiltinRole(roleId: string): Role | undefined {
|
||||||
/**
|
/**
|
||||||
* Works through the inheritance ranks to see how far up the builtin stack this ID is.
|
* Works through the inheritance ranks to see how far up the builtin stack this ID is.
|
||||||
*/
|
*/
|
||||||
export function builtinRoleToNumber(id?: string) {
|
export function builtinRoleToNumber(id: string) {
|
||||||
if (!id) {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
const builtins = getBuiltinRoles()
|
const builtins = getBuiltinRoles()
|
||||||
const MAX = Object.values(builtins).length + 1
|
const MAX = Object.values(builtins).length + 1
|
||||||
if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
|
if (id === BUILTIN_IDS.ADMIN || id === BUILTIN_IDS.BUILDER) {
|
||||||
|
|
|
@ -106,6 +106,16 @@ export async function save(ctx: UserCtx<SaveRoleRequest, SaveRoleResponse>) {
|
||||||
)
|
)
|
||||||
role._rev = result.rev
|
role._rev = result.rev
|
||||||
ctx.body = role
|
ctx.body = role
|
||||||
|
|
||||||
|
const replication = new dbCore.Replication({
|
||||||
|
source: context.getDevAppDB().name,
|
||||||
|
target: context.getProdAppDB().name,
|
||||||
|
})
|
||||||
|
await replication.replicate({
|
||||||
|
filter: (doc: any, params: any) => {
|
||||||
|
return doc._id === _id
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: UserCtx<void, DestroyRoleResponse>) {
|
export async function destroy(ctx: UserCtx<void, DestroyRoleResponse>) {
|
||||||
|
|
|
@ -16,16 +16,9 @@ import * as setup from "./utilities"
|
||||||
import { AppStatus } from "../../../db/utils"
|
import { AppStatus } from "../../../db/utils"
|
||||||
import { events, utils, context } from "@budibase/backend-core"
|
import { events, utils, context } from "@budibase/backend-core"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import {
|
import { type App } from "@budibase/types"
|
||||||
PermissionLevel,
|
|
||||||
type App,
|
|
||||||
INTERNAL_TABLE_SOURCE_ID,
|
|
||||||
TableSourceType,
|
|
||||||
FieldType,
|
|
||||||
} from "@budibase/types"
|
|
||||||
import tk from "timekeeper"
|
import tk from "timekeeper"
|
||||||
|
import * as uuid from "uuid"
|
||||||
jest.setTimeout(99999999)
|
|
||||||
|
|
||||||
describe("/applications", () => {
|
describe("/applications", () => {
|
||||||
let config = setup.getConfig()
|
let config = setup.getConfig()
|
||||||
|
@ -258,25 +251,12 @@ describe("/applications", () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("permissions", () => {
|
describe("permissions", () => {
|
||||||
it.only("should only return apps a user has access to", async () => {
|
it("should only return apps a user has access to", async () => {
|
||||||
let user = await config.createUser({
|
let user = await config.createUser({
|
||||||
builder: { global: false },
|
builder: { global: false },
|
||||||
admin: { global: false },
|
admin: { global: false },
|
||||||
})
|
})
|
||||||
|
|
||||||
const table = await config.api.table.save({
|
|
||||||
name: "table",
|
|
||||||
type: "table",
|
|
||||||
sourceId: INTERNAL_TABLE_SOURCE_ID,
|
|
||||||
sourceType: TableSourceType.INTERNAL,
|
|
||||||
schema: {
|
|
||||||
name: {
|
|
||||||
type: FieldType.STRING,
|
|
||||||
name: "name",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await config.withUser(user, async () => {
|
await config.withUser(user, async () => {
|
||||||
const apps = await config.api.application.fetch()
|
const apps = await config.api.application.fetch()
|
||||||
expect(apps).toHaveLength(0)
|
expect(apps).toHaveLength(0)
|
||||||
|
@ -295,25 +275,12 @@ describe("/applications", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should only return apps a user has access to through a custom role on a group", async () => {
|
it("should only return apps a user has access to through a custom role", async () => {
|
||||||
const user = await config.createUser({
|
let user = await config.createUser({
|
||||||
builder: { global: false },
|
builder: { global: false },
|
||||||
admin: { global: false },
|
admin: { global: false },
|
||||||
})
|
})
|
||||||
|
|
||||||
const table = await config.api.table.save({
|
|
||||||
name: "table",
|
|
||||||
type: "table",
|
|
||||||
sourceId: INTERNAL_TABLE_SOURCE_ID,
|
|
||||||
sourceType: TableSourceType.INTERNAL,
|
|
||||||
schema: {
|
|
||||||
name: {
|
|
||||||
type: FieldType.STRING,
|
|
||||||
name: "name",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await config.withUser(user, async () => {
|
await config.withUser(user, async () => {
|
||||||
const apps = await config.api.application.fetch()
|
const apps = await config.api.application.fetch()
|
||||||
expect(apps).toHaveLength(0)
|
expect(apps).toHaveLength(0)
|
||||||
|
@ -326,17 +293,43 @@ describe("/applications", () => {
|
||||||
version: "name",
|
version: "name",
|
||||||
})
|
})
|
||||||
|
|
||||||
await config.api.user.update({
|
user = await config.globalUser({
|
||||||
...user,
|
...user,
|
||||||
roles: {
|
roles: {
|
||||||
[config.getAppId()]: role._id!,
|
[config.getProdAppId()]: role.name,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
await config.api.permission.add({
|
await config.withUser(user, async () => {
|
||||||
resourceId: table._id!,
|
const apps = await config.api.application.fetch()
|
||||||
roleId: role._id!,
|
expect(apps).toHaveLength(1)
|
||||||
level: PermissionLevel.READ,
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it.only("should only return apps a user has access to through a custom role on a group", async () => {
|
||||||
|
let user = await config.createUser({
|
||||||
|
builder: { global: false },
|
||||||
|
admin: { global: false },
|
||||||
|
})
|
||||||
|
|
||||||
|
await config.withUser(user, async () => {
|
||||||
|
const apps = await config.api.application.fetch()
|
||||||
|
expect(apps).toHaveLength(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
const roleName = uuid.v4().replace(/-/g, "")
|
||||||
|
const role = await config.api.roles.save({
|
||||||
|
name: roleName,
|
||||||
|
inherits: "PUBLIC",
|
||||||
|
permissionId: "read_only",
|
||||||
|
version: "name",
|
||||||
|
})
|
||||||
|
|
||||||
|
const group = await config.createGroup(role._id!)
|
||||||
|
|
||||||
|
user = await config.globalUser({
|
||||||
|
...user,
|
||||||
|
userGroups: [group._id!],
|
||||||
})
|
})
|
||||||
|
|
||||||
await config.withUser(user, async () => {
|
await config.withUser(user, async () => {
|
||||||
|
|
|
@ -5,4 +5,5 @@ export interface Role extends Document {
|
||||||
inherits?: string
|
inherits?: string
|
||||||
permissions: { [key: string]: string[] }
|
permissions: { [key: string]: string[] }
|
||||||
version?: string
|
version?: string
|
||||||
|
name: string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue