feat(workspaces): toggle embedded viewer branding (#4762)
* feat(viewer): embedded viewer option to hide speckle branding * chore(viewer): can edit embed options policy * chore(embeds): tests for new policy and gql
This commit is contained in:
@@ -30,6 +30,14 @@ export default {
|
||||
workspaceId: parent.workspaceId
|
||||
})
|
||||
return Authz.toGraphqlResult(canMoveProjectToWorkspace)
|
||||
},
|
||||
canEditEmbedOptions: async (parent, _args, ctx) => {
|
||||
const canEditEmbedOptions =
|
||||
await ctx.authPolicies.workspace.canUpdateEmbedOptions({
|
||||
userId: ctx.userId,
|
||||
workspaceId: parent.workspaceId
|
||||
})
|
||||
return Authz.toGraphqlResult(canEditEmbedOptions)
|
||||
}
|
||||
}
|
||||
} as Resolvers
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
countInvitableCollaboratorsByProjectIdFactory,
|
||||
getInvitableCollaboratorsByProjectIdFactory
|
||||
} from '@/modules/workspaces/repositories/users'
|
||||
import { getWorkspaceFactory } from '@/modules/workspaces/repositories/workspaces'
|
||||
import { getMoveProjectToWorkspaceDryRunFactory } from '@/modules/workspaces/services/projects'
|
||||
|
||||
const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
@@ -61,6 +62,21 @@ export default FF_WORKSPACES_MODULE_ENABLED
|
||||
})({ projectId, workspaceId })
|
||||
|
||||
return addedToWorkspace
|
||||
},
|
||||
embedOptions: async (parent) => {
|
||||
const { workspaceId } = parent
|
||||
|
||||
if (!workspaceId) {
|
||||
return {
|
||||
hideSpeckleBranding: false
|
||||
}
|
||||
}
|
||||
|
||||
const workspace = await getWorkspaceFactory({ db })({ workspaceId })
|
||||
|
||||
return {
|
||||
hideSpeckleBranding: workspace?.isEmbedSpeckleBrandingHidden ?? false
|
||||
}
|
||||
}
|
||||
},
|
||||
ProjectMoveToWorkspaceDryRun: {
|
||||
|
||||
@@ -1042,6 +1042,44 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
)
|
||||
return true
|
||||
},
|
||||
updateEmbedOptions: async (parent, args, context) => {
|
||||
const { workspaceId, hideSpeckleBranding } = args.input
|
||||
|
||||
const logger = context.log.child({ workspaceId })
|
||||
|
||||
return await asOperation(
|
||||
async ({ db, emit }) => {
|
||||
const workspace = await updateWorkspaceFactory({
|
||||
validateSlug: validateSlugFactory({
|
||||
getWorkspaceBySlug: getWorkspaceBySlugFactory({ db })
|
||||
}),
|
||||
getWorkspace: getWorkspaceWithDomainsFactory({ db }),
|
||||
getWorkspaceSsoProviderRecord: getWorkspaceSsoProviderFactory({
|
||||
db,
|
||||
decrypt: getDecryptor()
|
||||
}),
|
||||
upsertWorkspace: upsertWorkspaceFactory({ db }),
|
||||
emitWorkspaceEvent: emit
|
||||
})({
|
||||
workspaceId,
|
||||
workspaceInput: {
|
||||
isEmbedSpeckleBrandingHidden: hideSpeckleBranding
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
hideSpeckleBranding: workspace.isEmbedSpeckleBrandingHidden
|
||||
}
|
||||
},
|
||||
{
|
||||
logger,
|
||||
name: 'updateWorkspaceEmbedOptions',
|
||||
description:
|
||||
'Update workspace-level configuration for the embedded viewer',
|
||||
transaction: true
|
||||
}
|
||||
)
|
||||
},
|
||||
invites: () => ({}),
|
||||
projects: () => ({}),
|
||||
dismiss: async (_parent, args, ctx) => {
|
||||
@@ -1652,6 +1690,11 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
return await getWorkspaceSsoProviderRecordFactory({ db })({
|
||||
workspaceId: parent.id
|
||||
})
|
||||
},
|
||||
embedOptions: async (parent) => {
|
||||
return {
|
||||
hideSpeckleBranding: parent.isEmbedSpeckleBrandingHidden
|
||||
}
|
||||
}
|
||||
},
|
||||
WorkspaceSso: {
|
||||
|
||||
@@ -262,7 +262,8 @@ export const upsertWorkspaceFactory =
|
||||
'name',
|
||||
'updatedAt',
|
||||
'domainBasedMembershipProtectionEnabled',
|
||||
'discoverabilityEnabled'
|
||||
'discoverabilityEnabled',
|
||||
'isEmbedSpeckleBrandingHidden'
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,8 @@ export const createWorkspaceFactory =
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
discoverabilityEnabled: false
|
||||
discoverabilityEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
await upsertWorkspace({ workspace })
|
||||
|
||||
|
||||
@@ -30,7 +30,10 @@ import {
|
||||
CreateWorkspaceProjectDocument,
|
||||
DismissWorkspaceDocument,
|
||||
GetActiveUserDiscoverableWorkspacesDocument,
|
||||
GetWorkspaceWithMembersByRoleDocument
|
||||
GetWorkspaceWithMembersByRoleDocument,
|
||||
UpdateEmbedOptionsDocument,
|
||||
WorkspaceEmbedOptionsDocument,
|
||||
ProjectEmbedOptionsDocument
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { beforeEachContext } from '@/test/hooks'
|
||||
import { AllScopes } from '@/modules/core/helpers/mainConstants'
|
||||
@@ -1359,5 +1362,72 @@ describe('Workspaces GQL CRUD', () => {
|
||||
).to.false
|
||||
})
|
||||
})
|
||||
|
||||
describe('mutation workspaceMutations.updateEmbedOptions', () => {
|
||||
const workspace: BasicTestWorkspace = {
|
||||
id: '',
|
||||
ownerId: '',
|
||||
slug: cryptoRandomString({ length: 10 }),
|
||||
name: 'My Test Workspace'
|
||||
}
|
||||
|
||||
const workspaceProject: BasicTestStream = {
|
||||
id: '',
|
||||
ownerId: '',
|
||||
name: 'My Test Project',
|
||||
isPublic: false
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
await createTestWorkspace(workspace, testAdminUser, { addPlan: false })
|
||||
workspaceProject.workspaceId = workspace.id
|
||||
await createTestStream(workspaceProject, testAdminUser)
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await apollo.execute(UpdateEmbedOptionsDocument, {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
hideSpeckleBranding: false
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('should update options at workspace level', async () => {
|
||||
const resA = await apollo.execute(UpdateEmbedOptionsDocument, {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
hideSpeckleBranding: true
|
||||
}
|
||||
})
|
||||
|
||||
expect(resA).to.not.haveGraphQLErrors()
|
||||
|
||||
const resB = await apollo.execute(WorkspaceEmbedOptionsDocument, {
|
||||
workspaceId: workspace.id
|
||||
})
|
||||
|
||||
expect(resB).to.not.haveGraphQLErrors()
|
||||
expect(resB?.data?.workspace.embedOptions.hideSpeckleBranding).to.equal(true)
|
||||
})
|
||||
|
||||
it('should update options at workspace project level', async () => {
|
||||
const resA = await apollo.execute(UpdateEmbedOptionsDocument, {
|
||||
input: {
|
||||
workspaceId: workspace.id,
|
||||
hideSpeckleBranding: true
|
||||
}
|
||||
})
|
||||
|
||||
expect(resA).to.not.haveGraphQLErrors()
|
||||
|
||||
const resB = await apollo.execute(ProjectEmbedOptionsDocument, {
|
||||
projectId: workspaceProject.id
|
||||
})
|
||||
|
||||
expect(resB).to.not.haveGraphQLErrors()
|
||||
expect(resB.data?.project.embedOptions.hideSpeckleBranding).to.equal(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -260,6 +260,7 @@ describe('Workspace services', () => {
|
||||
logo: null,
|
||||
discoverabilityEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false,
|
||||
domains: []
|
||||
}
|
||||
return merge(workspace, input)
|
||||
@@ -1139,7 +1140,8 @@ describe('Workspace role services', () => {
|
||||
updatedAt: new Date(),
|
||||
description: null,
|
||||
discoverabilityEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
},
|
||||
getDomains: async () => {
|
||||
@@ -1178,7 +1180,8 @@ describe('Workspace role services', () => {
|
||||
updatedAt: new Date(),
|
||||
description: null,
|
||||
discoverabilityEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
|
||||
await addDomainToWorkspaceFactory({
|
||||
|
||||
@@ -383,6 +383,7 @@ describe('Workspace SSO services', () => {
|
||||
logo: null,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
discoverabilityEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user