From 756c1e50987995cf9fd1e80e18ebabe5f6df5d40 Mon Sep 17 00:00:00 2001 From: Rhythm Bhiwani Date: Sun, 3 Mar 2024 12:12:25 +0530 Subject: [PATCH] Added `populateOrgName` param in `/v1/workspace` api which adds `orgName` and `displayName` in result Updated the CLI to use this new paramter to display organization name with project name with support for backward compatibility keeping original behaviour for older apis --- backend/src/server/routes/index.ts | 1 + .../src/server/routes/v1/project-router.ts | 12 +++++++-- .../src/services/project/project-service.ts | 16 ++++++++++- cli/packages/api/api.go | 17 +----------- cli/packages/api/model.go | 11 ++++---- cli/packages/cmd/init.go | 11 +++----- cli/packages/models/cli.go | 11 ++++---- cli/packages/util/init.go | 27 +++++++++++++++++++ 8 files changed, 69 insertions(+), 37 deletions(-) create mode 100644 cli/packages/util/init.go diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index d3d01ccb5..f6264d580 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -341,6 +341,7 @@ export const registerRoutes = async ( const projectService = projectServiceFactory({ permissionService, projectDAL, + orgDAL, projectQueue: projectQueueService, secretBlindIndexDAL, identityProjectDAL, diff --git a/backend/src/server/routes/v1/project-router.ts b/backend/src/server/routes/v1/project-router.ts index 0a5f8d85e..a4c385283 100644 --- a/backend/src/server/routes/v1/project-router.ts +++ b/backend/src/server/routes/v1/project-router.ts @@ -16,7 +16,9 @@ import { sanitizedServiceTokenSchema } from "../v2/service-token-router"; const projectWithEnv = ProjectsSchema.merge( z.object({ _id: z.string(), - environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array() + environments: z.object({ name: z.string(), slug: z.string(), id: z.string() }).array(), + orgName: z.string().optional(), + displayName: z.string().optional() }) ); @@ -91,6 +93,12 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { url: "/", method: "GET", schema: { + querystring: z.object({ + populateOrgName: z + .enum(["true", "false"]) + .default("false") + .transform((value) => value === "true") + }), response: { 200: z.object({ workspaces: projectWithEnv.array() @@ -99,7 +107,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => { }, onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]), handler: async (req) => { - const workspaces = await server.services.project.getProjects(req.permission.id); + const workspaces = await server.services.project.getProjects(req.permission.id, req.query.populateOrgName); return { workspaces }; } }); diff --git a/backend/src/services/project/project-service.ts b/backend/src/services/project/project-service.ts index c7c3af6fa..4bd322494 100644 --- a/backend/src/services/project/project-service.ts +++ b/backend/src/services/project/project-service.ts @@ -17,6 +17,7 @@ import { TProjectPermission } from "@app/lib/types"; import { ActorType } from "../auth/auth-type"; import { TIdentityOrgDALFactory } from "../identity/identity-org-dal"; import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal"; +import { TOrgDALFactory } from "../org/org-dal"; import { TOrgServiceFactory } from "../org/org-service"; import { TProjectBotDALFactory } from "../project-bot/project-bot-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; @@ -46,6 +47,7 @@ type TProjectServiceFactoryDep = { projectDAL: TProjectDALFactory; projectQueue: TProjectQueueFactory; userDAL: TUserDALFactory; + orgDAL: TOrgDALFactory; folderDAL: TSecretFolderDALFactory; projectEnvDAL: Pick; identityOrgMembershipDAL: TIdentityOrgDALFactory; @@ -64,6 +66,7 @@ export type TProjectServiceFactory = ReturnType; export const projectServiceFactory = ({ projectDAL, projectQueue, + orgDAL, projectKeyDAL, permissionService, userDAL, @@ -306,8 +309,19 @@ export const projectServiceFactory = ({ return deletedProject; }; - const getProjects = async (actorId: string) => { + const getProjects = async (actorId: string, populateOrgName?: boolean) => { const workspaces = await projectDAL.findAllProjects(actorId); + if (populateOrgName) { + const orgs = await orgDAL.findAllOrgsByUserId(actorId); + return workspaces.map((workspace) => { + const orgName = orgs.find((org) => org.id === workspace.orgId)?.name || ""; + return { + ...workspace, + orgName, + displayName: `${workspace.name} (${orgName})` + }; + }); + } return workspaces; }; diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index eaf1c650b..73d8b3916 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -170,6 +170,7 @@ func CallGetAllWorkSpacesUserBelongsTo(httpClient *resty.Client) (GetWorkSpacesR R(). SetResult(&workSpacesResponse). SetHeader("User-Agent", USER_AGENT). + SetQueryParam("populateOrgName", "true"). Get(fmt.Sprintf("%v/v1/workspace", config.INFISICAL_URL)) if err != nil { @@ -180,22 +181,6 @@ func CallGetAllWorkSpacesUserBelongsTo(httpClient *resty.Client) (GetWorkSpacesR return GetWorkSpacesResponse{}, fmt.Errorf("CallGetAllWorkSpacesUserBelongsTo: Unsuccessful response: [response=%v]", response) } - // Call the organization API - orgResponse, err := CallGetAllOrganizations(httpClient) - if err != nil { - return GetWorkSpacesResponse{}, err - } - - // Update organization names in workspacesResponse - for i, workspace := range workSpacesResponse.Workspaces { - for _, organization := range orgResponse.Organizations { - if workspace.Organization == organization.ID { - workSpacesResponse.Workspaces[i].Organization = organization.Name - break - } - } - } - return workSpacesResponse, nil } diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index 5fc04dee3..de4949c17 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -120,11 +120,12 @@ type PullSecretsByInfisicalTokenResponse struct { type GetWorkSpacesResponse struct { Workspaces []struct { - ID string `json:"_id"` - Name string `json:"name"` - Plan string `json:"plan,omitempty"` - V int `json:"__v"` - Organization string `json:"orgId,omitempty"` + ID string `json:"_id"` + Name string `json:"name"` + Plan string `json:"plan,omitempty"` + V int `json:"__v"` + Organization *string `json:"orgName,omitempty"` + DisplayName *string `json:"displayName,omitempty"` } `json:"workspaces"` } diff --git a/cli/packages/cmd/init.go b/cli/packages/cmd/init.go index 9e7c2fe6a..217e0842e 100644 --- a/cli/packages/cmd/init.go +++ b/cli/packages/cmd/init.go @@ -5,7 +5,6 @@ package cmd import ( "encoding/json" - "fmt" "github.com/Infisical/infisical-merge/packages/api" "github.com/Infisical/infisical-merge/packages/models" @@ -58,14 +57,10 @@ var initCmd = &cobra.Command{ } workspaces := workspaceResponse.Workspaces - if len(workspaces) == 0 { - message := fmt.Sprintf("You don't have any projects created in Infisical. You must first create a project at %s", util.INFISICAL_TOKEN_NAME) - util.PrintErrorMessageAndExit(message) - } - var workspaceNames []string - for _, workspace := range workspaces { - workspaceNames = append(workspaceNames, fmt.Sprintf("%s (%s)", workspace.Name, workspace.Organization)) + workspaceNames, err := util.GetWorkspacesNameList(workspaceResponse) + if err != nil { + util.HandleError(err, "Error extracting workspace names") } prompt := promptui.Select{ diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 801cfddfc..556b70051 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -45,11 +45,12 @@ type SingleFolder struct { } type Workspace struct { - ID string `json:"_id"` - Name string `json:"name"` - Plan string `json:"plan,omitempty"` - V int `json:"__v"` - Organization string `json:"orgId,omitempty"` + ID string `json:"_id"` + Name string `json:"name"` + Plan string `json:"plan,omitempty"` + V int `json:"__v"` + Organization *string `json:"orgName,omitempty"` + DisplayName *string `json:"displayName,omitempty"` } type WorkspaceConfigFile struct { diff --git a/cli/packages/util/init.go b/cli/packages/util/init.go new file mode 100644 index 000000000..be91e811d --- /dev/null +++ b/cli/packages/util/init.go @@ -0,0 +1,27 @@ +package util + +import ( + "fmt" + + "github.com/Infisical/infisical-merge/packages/api" +) + +func GetWorkspacesNameList(workspaceResponse api.GetWorkSpacesResponse) ([]string, error) { + workspaces := workspaceResponse.Workspaces + + if len(workspaces) == 0 { + message := fmt.Sprintf("You don't have any projects created in Infisical. You must first create a project at %s", INFISICAL_TOKEN_NAME) + PrintErrorMessageAndExit(message) + } + + var workspaceNames []string + for _, workspace := range workspaces { + if workspace.DisplayName != nil { + workspaceNames = append(workspaceNames, *workspace.DisplayName) + } else { + workspaceNames = append(workspaceNames, workspace.Name) + } + } + + return workspaceNames, nil +}