Skip to content

Commit

Permalink
feat(cli,api-client,schema): Add project environments support to work…
Browse files Browse the repository at this point in the history
…space role
  • Loading branch information
muntaxir4 committed Dec 28, 2024
1 parent bc4bdf3 commit 1bfac4c
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 42 deletions.
2 changes: 1 addition & 1 deletion apps/api/src/common/collective-authorities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export const getCollectiveProjectAuthorities = async (
* roles that the user has in the workspace, adding an extra layer of filtering
* by the project and the environment.
* @param userId The id of the user
* @param environemnt The environment with the project
* @param environment The environment with the project
* @param prisma The prisma client
* @returns
*/
Expand Down
31 changes: 22 additions & 9 deletions apps/api/src/workspace-role/service/workspace-role.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ export class WorkspaceRoleService {
if (dto.projectEnvironments) {
// Create the project associations
const projectSlugToIdMap = await this.getProjectSlugToIdMap(
dto.projectEnvironments.map((pe) => pe.projectSlug)
dto.projectEnvironments
.map((pe) => pe.projectSlug)
.filter((slug) => slug)
)

for (const pe of dto.projectEnvironments) {
Expand Down Expand Up @@ -242,7 +244,9 @@ export class WorkspaceRoleService {
})

const projectSlugToIdMap = await this.getProjectSlugToIdMap(
dto.projectEnvironments.map((pe) => pe.projectSlug)
dto.projectEnvironments
.map((pe) => pe.projectSlug)
.filter((slug) => slug)
)

for (const pe of dto.projectEnvironments) {
Expand Down Expand Up @@ -525,6 +529,13 @@ export class WorkspaceRoleService {
slug: true,
name: true
}
},
environments: {
select: {
id: true,
slug: true,
name: true
}
}
}
}
Expand Down Expand Up @@ -563,13 +574,15 @@ export class WorkspaceRoleService {
* @returns a Map of project slug to id
*/
private async getProjectSlugToIdMap(projectSlugs: string[]) {
const projects = await this.prisma.project.findMany({
where: {
slug: {
in: projectSlugs
}
}
})
const projects = projectSlugs.length
? await this.prisma.project.findMany({
where: {
slug: {
in: projectSlugs
}
}
})
: []

return new Map(projects.map((project) => [project.slug, project.id]))
}
Expand Down
130 changes: 130 additions & 0 deletions apps/cli/src/commands/workspace/role/create.role.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import BaseCommand from '@/commands/base.command'
import {
type CommandOption,
type CommandActionData,
type CommandArgument
} from '@/types/command/command.types'
import { Logger } from '@/util/logger'
import ControllerInstance from '@/util/controller-instance'

export default class UpdateRoleCommand extends BaseCommand {
getName() {
return 'create'
}

getDescription(): string {
return 'Create workspace role'
}

getArguments(): CommandArgument[] {
return [
{
name: '<Workspace Role Slug>',
description: 'Slug of the workspace role you want to fetch.'
}
]
}

getOptions(): CommandOption[] {
return [
{
short: '-n',
long: '--name <string>',
description: 'Name of the workspace role.'
},
{
short: '-d',
long: '--description <string>',
description: 'Description of the workspace role.'
},
{
short: '-c',
long: '--color-code <hexcode>',
description: 'Color code of the workspace role.'
},
{
short: '-a',
long: '--authorities <comma separated list>',
description: 'Authorities of the workspace role.'
},
{
short: '-p',
long: '--project-slugs <comma separated list>',
description: 'Project slugs of the workspace role.'
},
{
short: '-e',
long: '--environment-slugs <comma separated list>',
description:
'Environment slugs to be associated for projects. Separate list of environments with colon(:) for each project. And comma(,) to separate each project.'
}
]
}

async action({ args, options }: CommandActionData): Promise<void> {
const [workspaceRoleSlug] = args
const {
name,
description,
colorCode,
authorities,
projectSlugs,
environmentSlugs
} = options

const authoritiesArray = authorities?.split(',')
const projectSlugsArray = projectSlugs?.split(',')
const environmentSlugsArray = environmentSlugs?.split(',')

if (projectSlugsArray?.length !== environmentSlugsArray?.length) {
Logger.error('Number of projects and environments should be equal')
return
}

const projectEnvironments: Array<{
projectSlug: string
environmentSlugs: string[]
}> = []

const len = projectSlugsArray.length
for (let i = 0; i < len; i++) {
projectEnvironments.push({
projectSlug: projectSlugsArray[i],
environmentSlugs: environmentSlugsArray[i].split(':')
})
}

const { data, error, success } =
await ControllerInstance.getInstance().workspaceRoleController.updateWorkspaceRole(
{
workspaceRoleSlug,
name,
description,
colorCode,
authorities: authoritiesArray,
projectEnvironments:
projectEnvironments.length > 0 ? projectEnvironments : undefined
},
this.headers
)

if (success) {
Logger.info('Workspace role created successfully:')
Logger.info(`Workspace role: ${data.name} (${data.slug})`)
Logger.info(`Description: ${data.description || 'N/A'}`)
Logger.info(`Created at ${data.createdAt}`)
Logger.info(`Updated at ${data.updatedAt}`)
Logger.info(`Color code: ${data.colorCode}`)
Logger.info('Authorities:')
for (const authority of data.authorities) {
Logger.info(`- ${authority}`)
}
Logger.info('Projects:')
for (const project of data.projects) {
Logger.info(`- ${project.project.name} (${project.project.slug})`)
}
} else {
Logger.error(`Failed creating workspace role: ${error.message}`)
}
}
}
37 changes: 35 additions & 2 deletions apps/cli/src/commands/workspace/role/update.role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,48 @@ export default class UpdateRoleCommand extends BaseCommand {
short: '-p',
long: '--project-slugs <comma separated list>',
description: 'Project slugs of the workspace role.'
},
{
short: '-e',
long: '--environment-slugs <comma separated list>',
description:
'Environment slugs to be associated for projects. Separate list of environments with colon(:) for each project. And comma(,) to separate each project.'
}
]
}

async action({ args, options }: CommandActionData): Promise<void> {
const [workspaceRoleSlug] = args
const { name, description, colorCode, authorities, projectSlugs } = options
const {
name,
description,
colorCode,
authorities,
projectSlugs,
environmentSlugs
} = options

const authoritiesArray = authorities?.split(',')
const projectSlugsArray = projectSlugs?.split(',')
const environmentSlugsArray = environmentSlugs?.split(',')

if (projectSlugsArray?.length !== environmentSlugsArray?.length) {
Logger.error('Number of projects and environments should be equal')
return
}

const projectEnvironments: Array<{
projectSlug: string
environmentSlugs: string[]
}> = []

const len = projectSlugsArray.length
for (let i = 0; i < len; i++) {
projectEnvironments.push({
projectSlug: projectSlugsArray[i],
environmentSlugs: environmentSlugsArray[i].split(':')
})
}

const { data, error, success } =
await ControllerInstance.getInstance().workspaceRoleController.updateWorkspaceRole(
Expand All @@ -70,7 +102,8 @@ export default class UpdateRoleCommand extends BaseCommand {
description,
colorCode,
authorities: authoritiesArray,
projectSlugs: projectSlugsArray
projectEnvironments:
projectEnvironments.length > 0 ? projectEnvironments : undefined
},
this.headers
)
Expand Down
15 changes: 3 additions & 12 deletions packages/api-client/tests/workspace-role.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('Workspace Role Controller Tests', () => {
description: 'Role for developers',
colorCode: '#FF0000',
authorities: ['READ_WORKSPACE', 'READ_PROJECT'],
projectSlugs: [projectSlug!]
projectEnvironments: [{ projectSlug, environmentSlugs: [] }]
}

const createWorkspaceRoleResponse = (
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('Workspace Role Controller Tests', () => {
description: 'Role for admins',
colorCode: '#0000FF',
authorities: ['READ_WORKSPACE'],
projectSlugs: []
projectEnvironments: []
}

const createRoleResponse = (
Expand Down Expand Up @@ -155,15 +155,6 @@ describe('Workspace Role Controller Tests', () => {
).data

expect(updateRoleResponse.name).toBe('Lead Developer')

const fetchRole = (
await workspaceRoleController.getWorkspaceRole(
{ workspaceRoleSlug: workspaceRoleSlug! },
{ 'x-e2e-user-email': email }
)
).data

expect(fetchRole.name).toBe('Lead Developer')
})

it('should delete a workspace role', async () => {
Expand Down Expand Up @@ -208,7 +199,7 @@ describe('Workspace Role Controller Tests', () => {
description: 'Role with project access',
colorCode: '#0000FF',
authorities: ['READ_WORKSPACE'],
projectSlugs: [projectSlug!]
projectEnvironments: [{ projectSlug, environmentSlugs: [] }]
}

const createRoleResponse = (
Expand Down
19 changes: 17 additions & 2 deletions packages/schema/src/workspace-role/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { authorityEnum } from '@/enums'
import { EnvironmentSchema } from '@/environment'
import { PageRequestSchema, PageResponseSchema } from '@/pagination'
import { BaseProjectSchema } from '@/project'
import { WorkspaceSchema } from '@/workspace'
Expand All @@ -21,7 +22,14 @@ export const WorkspaceRoleSchema = z.object({
id: BaseProjectSchema.shape.id,
name: BaseProjectSchema.shape.name,
slug: BaseProjectSchema.shape.slug
})
}),
environments: z.array(
z.object({
id: EnvironmentSchema.shape.id,
name: EnvironmentSchema.shape.name,
slug: EnvironmentSchema.shape.slug
})
)
})
)
})
Expand All @@ -32,7 +40,14 @@ export const CreateWorkspaceRoleRequestSchema = z.object({
description: z.string().optional(),
colorCode: z.string().optional(),
authorities: z.array(authorityEnum).optional(),
projectSlugs: z.array(BaseProjectSchema.shape.slug).optional()
projectEnvironments: z
.array(
z.object({
projectSlug: BaseProjectSchema.shape.slug,
environmentSlugs: z.array(EnvironmentSchema.shape.slug)
})
)
.optional()
})

export const CreateWorkspaceRoleResponseSchema = WorkspaceRoleSchema
Expand Down
Loading

0 comments on commit 1bfac4c

Please sign in to comment.