diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 967c0070..457bdecb 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -202,6 +202,52 @@ const docTemplate = `{ } } }, + "/admin/organizations/{organizationId}": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail ( for admin )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail ( for admin )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2178,6 +2224,40 @@ const docTemplate = `{ } } }, + "/organizations/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Check name for organization", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}": { "get": { "security": [ @@ -6919,6 +6999,53 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "primaryClusterId": { + "type": "string" + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9270,9 +9397,6 @@ const docTemplate = `{ "name": { "type": "string" }, - "phone": { - "type": "string" - }, "policyTemplates": { "type": "array", "items": { @@ -10028,7 +10152,7 @@ const docTemplate = `{ "services": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse" } }, "template": { @@ -10036,6 +10160,14 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10551,9 +10683,6 @@ const docTemplate = `{ "maxLength": 30, "minLength": 1 }, - "phone": { - "type": "string" - }, "primaryClusterId": { "type": "string" } @@ -10570,9 +10699,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index f333c1f6..1194bfaf 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -196,6 +196,52 @@ } } }, + "/admin/organizations/{organizationId}": { + "put": { + "security": [ + { + "JWT": [] + } + ], + "description": "Update organization detail ( for admin )", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Update organization detail ( for admin )", + "parameters": [ + { + "type": "string", + "description": "organizationId", + "name": "organizationId", + "in": "path", + "required": true + }, + { + "description": "update organization request", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse" + } + } + } + } + }, "/admin/organizations/{organizationId}/projects": { "get": { "security": [ @@ -2172,6 +2218,40 @@ } } }, + "/organizations/name/{name}/existence": { + "get": { + "security": [ + { + "JWT": [] + } + ], + "description": "Check name for organization", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Organizations" + ], + "summary": "Check name for organization", + "parameters": [ + { + "type": "string", + "description": "name", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/organizations/{organizationId}": { "get": { "security": [ @@ -6913,6 +6993,53 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "description": { + "type": "string", + "maxLength": 100, + "minLength": 0 + }, + "name": { + "type": "string", + "maxLength": 30, + "minLength": 1 + }, + "policyTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "primaryClusterId": { + "type": "string" + }, + "stackTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "systemNotificationTemplateIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse": { "type": "object", "properties": { @@ -9264,9 +9391,6 @@ "name": { "type": "string" }, - "phone": { - "type": "string" - }, "policyTemplates": { "type": "array", "items": { @@ -10022,7 +10146,7 @@ "services": { "type": "array", "items": { - "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse" + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse" } }, "template": { @@ -10030,6 +10154,14 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse": { + "type": "object", + "properties": { + "type": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse": { "type": "object", "properties": { @@ -10545,9 +10677,6 @@ "maxLength": 30, "minLength": 1 }, - "phone": { - "type": "string" - }, "primaryClusterId": { "type": "string" } @@ -10564,9 +10693,6 @@ }, "name": { "type": "string" - }, - "phone": { - "type": "string" } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index d727754a..b4b647d7 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -147,6 +147,38 @@ definitions: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.ProjectMemberRequest' type: array type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest: + properties: + description: + maxLength: 100 + minLength: 0 + type: string + name: + maxLength: 30 + minLength: 1 + type: string + policyTemplateIds: + items: + type: string + type: array + primaryClusterId: + type: string + stackTemplateIds: + items: + type: string + type: array + systemNotificationTemplateIds: + items: + type: string + type: array + required: + - name + type: object + github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse: + properties: + id: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.AppGroupResponse: properties: appGroupType: @@ -1728,8 +1760,6 @@ definitions: type: string name: type: string - phone: - type: string policyTemplates: items: $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimplePolicyTemplateResponse' @@ -2235,11 +2265,16 @@ definitions: type: string services: items: - $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.StackTemplateServiceResponse' + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse' type: array template: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SimpleStackTemplateServiceResponse: + properties: + type: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse: properties: accountId: @@ -2581,8 +2616,6 @@ definitions: maxLength: 30 minLength: 1 type: string - phone: - type: string primaryClusterId: type: string required: @@ -2596,8 +2629,6 @@ definitions: type: string name: type: string - phone: - type: string type: object github_com_openinfradev_tks-api_pkg_domain.UpdatePasswordRequest: properties: @@ -3027,6 +3058,35 @@ paths: summary: Get Audit tags: - Audits + /admin/organizations/{organizationId}: + put: + consumes: + - application/json + description: Update organization detail ( for admin ) + parameters: + - description: organizationId + in: path + name: organizationId + required: true + type: string + - description: update organization request + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.Admin_UpdateOrganizationResponse' + security: + - JWT: [] + summary: Update organization detail ( for admin ) + tags: + - Organizations /admin/organizations/{organizationId}/projects: get: consumes: @@ -7125,6 +7185,27 @@ paths: summary: Get user email existence tags: - Users + /organizations/name/{name}/existence: + get: + consumes: + - application/json + description: Check name for organization + parameters: + - description: name + in: path + name: name + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + security: + - JWT: [] + summary: Check name for organization + tags: + - Organizations /permissions/templates: get: consumes: diff --git a/internal/delivery/api/endpoint.go b/internal/delivery/api/endpoint.go index 81013594..8ff1bab7 100644 --- a/internal/delivery/api/endpoint.go +++ b/internal/delivery/api/endpoint.go @@ -39,12 +39,14 @@ const ( DeleteMyProfile // Organization - CreateOrganization + Admin_CreateOrganization + Admin_DeleteOrganization + Admin_UpdateOrganization GetOrganizations GetOrganization - DeleteOrganization UpdateOrganization UpdatePrimaryCluster + CheckOrganizationName // Cluster CreateCluster diff --git a/internal/delivery/api/generated_endpoints.go.go b/internal/delivery/api/generated_endpoints.go.go index 6a09a23f..1955a7e8 100644 --- a/internal/delivery/api/generated_endpoints.go.go +++ b/internal/delivery/api/generated_endpoints.go.go @@ -91,8 +91,16 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "DeleteMyProfile", Group: "MyProfile", }, - CreateOrganization: { - Name: "CreateOrganization", + Admin_CreateOrganization: { + Name: "Admin_CreateOrganization", + Group: "Organization", + }, + Admin_DeleteOrganization: { + Name: "Admin_DeleteOrganization", + Group: "Organization", + }, + Admin_UpdateOrganization: { + Name: "Admin_UpdateOrganization", Group: "Organization", }, GetOrganizations: { @@ -103,10 +111,6 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "GetOrganization", Group: "Organization", }, - DeleteOrganization: { - Name: "DeleteOrganization", - Group: "Organization", - }, UpdateOrganization: { Name: "UpdateOrganization", Group: "Organization", @@ -115,6 +119,10 @@ var ApiMap = map[Endpoint]EndpointInfo{ Name: "UpdatePrimaryCluster", Group: "Organization", }, + CheckOrganizationName: { + Name: "CheckOrganizationName", + Group: "Organization", + }, CreateCluster: { Name: "CreateCluster", Group: "Cluster", @@ -798,18 +806,22 @@ func (e Endpoint) String() string { return "RenewPasswordExpiredDate" case DeleteMyProfile: return "DeleteMyProfile" - case CreateOrganization: - return "CreateOrganization" + case Admin_CreateOrganization: + return "Admin_CreateOrganization" + case Admin_DeleteOrganization: + return "Admin_DeleteOrganization" + case Admin_UpdateOrganization: + return "Admin_UpdateOrganization" case GetOrganizations: return "GetOrganizations" case GetOrganization: return "GetOrganization" - case DeleteOrganization: - return "DeleteOrganization" case UpdateOrganization: return "UpdateOrganization" case UpdatePrimaryCluster: return "UpdatePrimaryCluster" + case CheckOrganizationName: + return "CheckOrganizationName" case CreateCluster: return "CreateCluster" case GetClusters: @@ -1178,18 +1190,22 @@ func GetEndpoint(name string) Endpoint { return RenewPasswordExpiredDate case "DeleteMyProfile": return DeleteMyProfile - case "CreateOrganization": - return CreateOrganization + case "Admin_CreateOrganization": + return Admin_CreateOrganization + case "Admin_DeleteOrganization": + return Admin_DeleteOrganization + case "Admin_UpdateOrganization": + return Admin_UpdateOrganization case "GetOrganizations": return GetOrganizations case "GetOrganization": return GetOrganization - case "DeleteOrganization": - return DeleteOrganization case "UpdateOrganization": return UpdateOrganization case "UpdatePrimaryCluster": return UpdatePrimaryCluster + case "CheckOrganizationName": + return CheckOrganizationName case "CreateCluster": return CreateCluster case "GetClusters": diff --git a/internal/delivery/http/organization.go b/internal/delivery/http/organization.go index 683873d4..eafbe9aa 100644 --- a/internal/delivery/http/organization.go +++ b/internal/delivery/http/organization.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/gorilla/mux" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" @@ -43,7 +44,7 @@ func NewOrganizationHandler(u usecase.Usecase) *OrganizationHandler { // @Success 200 {object} object // @Router /organizations [post] // @Security JWT -func (h *OrganizationHandler) CreateOrganization(w http.ResponseWriter, r *http.Request) { +func (h *OrganizationHandler) Admin_CreateOrganization(w http.ResponseWriter, r *http.Request) { input := domain.CreateOrganizationRequest{} err := UnmarshalRequestInput(r, &input) @@ -246,7 +247,7 @@ func (h *OrganizationHandler) GetOrganization(w http.ResponseWriter, r *http.Req // @Success 200 {object} domain.DeleteOrganizationResponse // @Router /organizations/{organizationId} [delete] // @Security JWT -func (h *OrganizationHandler) DeleteOrganization(w http.ResponseWriter, r *http.Request) { +func (h *OrganizationHandler) Admin_DeleteOrganization(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) organizationId, ok := vars["organizationId"] if !ok { @@ -313,7 +314,12 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. return } - organization, err := h.usecase.Update(r.Context(), organizationId, input) + var dto model.Organization + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + organization, err := h.usecase.Update(r.Context(), organizationId, dto) if err != nil { log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) if _, status := httpErrors.ErrorResponse(err); status == http.StatusNotFound { @@ -332,6 +338,67 @@ func (h *OrganizationHandler) UpdateOrganization(w http.ResponseWriter, r *http. ResponseJSON(w, r, http.StatusOK, out) } +// Admin_UpdateOrganization godoc +// +// @Tags Organizations +// @Summary Update organization detail ( for admin ) +// @Description Update organization detail ( for admin ) +// @Accept json +// @Produce json +// @Param organizationId path string true "organizationId" +// @Param body body domain.Admin_UpdateOrganizationRequest true "update organization request" +// @Success 200 {object} domain.Admin_UpdateOrganizationResponse +// @Router /admin/organizations/{organizationId} [put] +// @Security JWT +func (h *OrganizationHandler) Admin_UpdateOrganization(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + organizationId, ok := vars["organizationId"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid organizationId"), "C_INVALID_ORGANIZATION_ID", "")) + return + } + + input := domain.Admin_UpdateOrganizationRequest{} + err := UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var dto model.Organization + if err = serializer.Map(r.Context(), input, &dto); err != nil { + log.Info(r.Context(), err) + } + + for _, strId := range input.StackTemplateIds { + stackTemplateId, err := uuid.Parse(strId) + if err != nil || stackTemplateId == uuid.Nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid stackTemplateId"), "C_INVALID_STACK_TEMPLATE_ID", "")) + return + } + dto.StackTemplateIds = append(dto.StackTemplateIds, stackTemplateId) + } + for _, strId := range input.PolicyTemplateIds { + policyTemplateId, err := uuid.Parse(strId) + if err != nil || policyTemplateId == uuid.Nil { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid policyTemplateId"), "C_INVALID_POLICY_TEMPLATE_ID", "")) + return + } + dto.PolicyTemplateIds = append(dto.PolicyTemplateIds, policyTemplateId) + } + + err = h.usecase.UpdateWithTemplates(r.Context(), organizationId, dto) + if err != nil { + ErrorJSON(w, r, err) + return + } + + var out domain.Admin_UpdateOrganizationResponse + out.ID = organizationId + + ResponseJSON(w, r, http.StatusOK, out) +} + // UpdatePrimaryCluster godoc // // @Tags Organizations @@ -371,3 +438,41 @@ func (h *OrganizationHandler) UpdatePrimaryCluster(w http.ResponseWriter, r *htt ResponseJSON(w, r, http.StatusOK, nil) } + +// CheckOrganizationName godoc +// +// @Tags Organizations +// @Summary Check name for organization +// @Description Check name for organization +// @Accept json +// @Produce json +// @Param name path string true "name" +// @Success 200 {object} nil +// @Router /organizations/name/{name}/existence [GET] +// @Security JWT +func (h *OrganizationHandler) CheckOrganizationName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + name, ok := vars["name"] + if !ok { + ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("Invalid name"), "O_INVALID_ORGANIZATION_NAME", "")) + return + } + + exist := false + pg := pagination.NewPaginationWithFilter("name", "", "$eq", []string{name}) + organizations, err := h.usecase.Fetch(r.Context(), pg) + if err != nil { + log.Errorf(r.Context(), "error is :%s(%T)", err.Error(), err) + ErrorJSON(w, r, err) + return + } + + if organizations != nil && len(*organizations) > 0 { + exist = true + } + + var out domain.CheckStackNameResponse + out.Existed = exist + + ResponseJSON(w, r, http.StatusOK, out) +} diff --git a/internal/middleware/audit/audit-map.go b/internal/middleware/audit/audit-map.go index a5fead14..d7c70439 100644 --- a/internal/middleware/audit/audit-map.go +++ b/internal/middleware/audit/audit-map.go @@ -45,7 +45,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("클라우드 어카운트 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteCloudAccount: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.DeleteCloudAccount: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteCloudAccountResponse{} if err := json.Unmarshal(in, &output); err != nil { @@ -55,7 +55,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return "클라우드어카운트 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -65,7 +65,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("사용자 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreateOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateOrganizationRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -75,7 +75,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("조직 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.DeleteOrganization: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_DeleteOrganization: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { if isSuccess(statusCode) { output := domain.DeleteOrganizationResponse{} if err := json.Unmarshal(in, &output); err != nil { @@ -85,7 +85,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return "조직 [%s]를 삭제하는데 실패하였습니다. ", errorText(ctx, out) } - }, internalApi.CreateAppServeApp: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreateAppServeApp: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateAppServeAppRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -95,7 +95,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("앱서빙 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateStackTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateStackTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -106,7 +106,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("스택 템플릿 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.Admin_CreateUser: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.Admin_CreateUser: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreateUserRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) @@ -116,7 +116,7 @@ var auditMap = map[internalApi.Endpoint]fnAudit{ } else { return fmt.Sprintf("어드민 [%s]을 생성하는데 실패하였습니다.", input.Name), errorText(ctx, out) } - }, internalApi.CreatePolicyTemplate: func(ctx context.Context,out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { + }, internalApi.CreatePolicyTemplate: func(ctx context.Context, out *bytes.Buffer, in []byte, statusCode int) (message string, description string) { input := domain.CreatePolicyTemplateRequest{} if err := json.Unmarshal(in, &input); err != nil { log.Error(ctx, err) diff --git a/internal/middleware/auth/role/default.go b/internal/middleware/auth/role/default.go index b50efd3f..d56e092e 100644 --- a/internal/middleware/auth/role/default.go +++ b/internal/middleware/auth/role/default.go @@ -57,10 +57,11 @@ var defaultPermissionOfAdmin = defaultPermission{ internalApi.DeleteMyProfile, // Organization - internalApi.CreateOrganization, + internalApi.Admin_CreateOrganization, + internalApi.Admin_UpdateOrganization, + internalApi.Admin_DeleteOrganization, internalApi.GetOrganizations, internalApi.GetOrganization, - internalApi.DeleteOrganization, internalApi.UpdateOrganization, // Cluster diff --git a/internal/model/app-group.go b/internal/model/app-group.go index fea48726..72cd1f88 100644 --- a/internal/model/app-group.go +++ b/internal/model/app-group.go @@ -2,7 +2,6 @@ package model import ( "github.com/google/uuid" - "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/datatypes" "gorm.io/gorm" @@ -26,11 +25,6 @@ type AppGroup struct { Updator User `gorm:"foreignKey:UpdatorId"` } -func (c *AppGroup) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = domain.AppGroupId(helper.GenerateApplicaionGroupId()) - return nil -} - type Application struct { gorm.Model @@ -40,8 +34,3 @@ type Application struct { Metadata datatypes.JSON Type domain.ApplicationType } - -func (c *Application) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/app-serve-app.go b/internal/model/app-serve-app.go index 4b6e779e..4a9b2186 100644 --- a/internal/model/app-serve-app.go +++ b/internal/model/app-serve-app.go @@ -2,9 +2,6 @@ package model import ( "time" - - "github.com/google/uuid" - "gorm.io/gorm" ) type AppServeApp struct { @@ -55,13 +52,3 @@ type AppServeAppTask struct { UpdatedAt *time.Time `gorm:"autoUpdateTime:false" json:"updatedAt"` DeletedAt *time.Time `json:"deletedAt"` } - -func (a *AppServeApp) BeforeCreate(tx *gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - -func (t *AppServeAppTask) BeforeCreate(tx *gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} diff --git a/internal/model/audit.go b/internal/model/audit.go index bfa853c1..1f39c252 100644 --- a/internal/model/audit.go +++ b/internal/model/audit.go @@ -19,8 +19,3 @@ type Audit struct { UserId *uuid.UUID `gorm:"type:uuid"` User User `gorm:"foreignKey:UserId"` } - -func (c *Audit) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cloud-account.go b/internal/model/cloud-account.go index 33d3a14b..98bf3f9c 100644 --- a/internal/model/cloud-account.go +++ b/internal/model/cloud-account.go @@ -31,8 +31,3 @@ type CloudAccount struct { UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` } - -func (c *CloudAccount) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/cluster.go b/internal/model/cluster.go index 8ca4b764..4e7480f6 100644 --- a/internal/model/cluster.go +++ b/internal/model/cluster.go @@ -77,8 +77,3 @@ type ClusterFavorite struct { UserId uuid.UUID `gorm:"type:uuid"` User User `gorm:"foreignKey:UserId"` } - -func (c *ClusterFavorite) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/organization.go b/internal/model/organization.go index f95a8a5b..2c6ca725 100644 --- a/internal/model/organization.go +++ b/internal/model/organization.go @@ -10,18 +10,20 @@ import ( type Organization struct { gorm.Model - ID string `gorm:"primarykey;type:varchar(36);not null"` - Name string - Description string - Phone string - PrimaryClusterId string - WorkflowId string - Status domain.OrganizationStatus - StatusDesc string - CreatorId *uuid.UUID `gorm:"type:uuid"` - StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations"` - PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` - ClusterCount int `gorm:"-:all"` - AdminId *uuid.UUID - Admin *User `gorm:"foreignKey:AdminId"` + ID string `gorm:"primarykey;type:varchar(36);not null"` + Name string + Description string + Phone string + PrimaryClusterId string + WorkflowId string + Status domain.OrganizationStatus + StatusDesc string + CreatorId *uuid.UUID `gorm:"type:uuid"` + StackTemplates []StackTemplate `gorm:"many2many:stack_template_organizations;"` + StackTemplateIds []uuid.UUID `gorm:"-:all"` + PolicyTemplates []PolicyTemplate `gorm:"many2many:policy_template_permitted_organiations;"` + PolicyTemplateIds []uuid.UUID `gorm:"-:all"` + ClusterCount int `gorm:"-:all"` + AdminId *uuid.UUID + Admin *User `gorm:"foreignKey:AdminId"` } diff --git a/internal/model/permission.go b/internal/model/permission.go index 9283bea3..9be78e6d 100644 --- a/internal/model/permission.go +++ b/internal/model/permission.go @@ -35,13 +35,6 @@ type Permission struct { Children []*Permission `gorm:"foreignKey:ParentID;references:ID;" json:"children,omitempty"` } -func (p *Permission) BeforeCreate(tx *gorm.DB) (err error) { - if p.ID == uuid.Nil { - p.ID = uuid.New() - } - return nil -} - type PermissionSet struct { Dashboard *Permission `gorm:"-:all" json:"dashboard,omitempty"` Stack *Permission `gorm:"-:all" json:"stack,omitempty"` diff --git a/internal/model/policy-template.go b/internal/model/policy-template.go index 430c4b7d..52b947c2 100644 --- a/internal/model/policy-template.go +++ b/internal/model/policy-template.go @@ -41,8 +41,3 @@ type PolicyTemplate struct { UpdatorId *uuid.UUID `gorm:"type:uuid"` Updator User `gorm:"foreignKey:UpdatorId"` } - -func (c *PolicyTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/project.go b/internal/model/project.go index 011e7704..7b69911f 100644 --- a/internal/model/project.go +++ b/internal/model/project.go @@ -7,30 +7,11 @@ import ( "gorm.io/gorm" ) -func (a *Project) BeforeCreate(*gorm.DB) (err error) { - a.ID = uuid.New().String() - return nil -} - func (t *ProjectRole) BeforeCreate(*gorm.DB) (err error) { t.ID = uuid.New().String() return nil } -func (t *ProjectMember) BeforeCreate(*gorm.DB) (err error) { - t.ID = uuid.New().String() - return nil -} - -//func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { -// t.ID = uuid.New().String() -// return nil -//} - -func (t *ProjectNamespace) BeforeCreate(*gorm.DB) (err error) { - return nil -} - type Project struct { ID string `gorm:"primarykey" json:"id"` OrganizationId string `json:"organizationId"` diff --git a/internal/model/role.go b/internal/model/role.go index 01f6497a..981d92d2 100644 --- a/internal/model/role.go +++ b/internal/model/role.go @@ -7,11 +7,6 @@ import ( "gorm.io/gorm" ) -func (r *Role) BeforeCreate(tx *gorm.DB) (err error) { - r.ID = uuid.New().String() - return nil -} - type Role struct { gorm.Model diff --git a/internal/model/stack-template.go b/internal/model/stack-template.go index c74cad06..afcef83b 100644 --- a/internal/model/stack-template.go +++ b/internal/model/stack-template.go @@ -29,11 +29,6 @@ type StackTemplate struct { Updator User `gorm:"foreignKey:UpdatorId"` } -func (c *StackTemplate) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - type StackTemplateOrganization struct { StackTemplateId uuid.UUID `gorm:"primarykey"` OrganizationId string `gorm:"primarykey"` diff --git a/internal/model/system-notification.go b/internal/model/system-notification.go index aa723983..aea8cbb0 100644 --- a/internal/model/system-notification.go +++ b/internal/model/system-notification.go @@ -38,11 +38,6 @@ type SystemNotification struct { Status domain.SystemNotificationActionStatus `gorm:"index"` } -func (c *SystemNotification) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} - type SystemNotificationAction struct { gorm.Model @@ -53,8 +48,3 @@ type SystemNotificationAction struct { TakerId *uuid.UUID `gorm:"type:uuid"` Taker User `gorm:"foreignKey:TakerId"` } - -func (c *SystemNotificationAction) BeforeCreate(tx *gorm.DB) (err error) { - c.ID = uuid.New() - return nil -} diff --git a/internal/model/user.go b/internal/model/user.go index 96303110..c8a2c7de 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -4,7 +4,6 @@ import ( "time" "github.com/google/uuid" - "gorm.io/gorm" ) type User struct { @@ -27,8 +26,3 @@ type User struct { Department string `json:"department"` Description string `json:"description"` } - -func (g *User) BeforeCreate(tx *gorm.DB) (err error) { - g.PasswordUpdatedAt = time.Now() - return nil -} diff --git a/internal/repository/app-group.go b/internal/repository/app-group.go index df2b76af..2885155b 100644 --- a/internal/repository/app-group.go +++ b/internal/repository/app-group.go @@ -7,6 +7,8 @@ import ( "gorm.io/datatypes" "gorm.io/gorm" + "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" @@ -61,6 +63,7 @@ func (r *AppGroupRepository) Get(ctx context.Context, id domain.AppGroupId) (out func (r *AppGroupRepository) Create(ctx context.Context, dto model.AppGroup) (appGroupId domain.AppGroupId, err error) { appGroup := model.AppGroup{ + ID: domain.AppGroupId(helper.GenerateApplicaionGroupId()), ClusterId: dto.ClusterId, AppGroupType: dto.AppGroupType, Name: dto.Name, @@ -116,6 +119,7 @@ func (r *AppGroupRepository) UpsertApplication(ctx context.Context, dto model.Ap Type: dto.Type, }). Assign(model.Application{ + ID: uuid.New(), Endpoint: dto.Endpoint, Metadata: datatypes.JSON([]byte(dto.Metadata))}). FirstOrCreate(&model.Application{}) diff --git a/internal/repository/app-serve-app.go b/internal/repository/app-serve-app.go index 53460c70..a37559ca 100644 --- a/internal/repository/app-serve-app.go +++ b/internal/repository/app-serve-app.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "github.com/openinfradev/tks-api/pkg/domain" @@ -42,7 +43,7 @@ func NewAppServeAppRepository(db *gorm.DB) IAppServeAppRepository { } func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *model.AppServeApp) (appId string, taskId string, err error) { - + app.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&app) if res.Error != nil { return "", "", res.Error @@ -53,6 +54,7 @@ func (r *AppServeAppRepository) CreateAppServeApp(ctx context.Context, app *mode // Update creates new appServeApp task for existing appServeApp. func (r *AppServeAppRepository) CreateTask(ctx context.Context, task *model.AppServeAppTask) (string, error) { + task.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(task) if res.Error != nil { return "", res.Error diff --git a/internal/repository/audit.go b/internal/repository/audit.go index 8d9a594f..c0ac2010 100644 --- a/internal/repository/audit.go +++ b/internal/repository/audit.go @@ -54,6 +54,7 @@ func (r *AuditRepository) Fetch(ctx context.Context, pg *pagination.Pagination) func (r *AuditRepository) Create(ctx context.Context, dto model.Audit) (auditId uuid.UUID, err error) { audit := model.Audit{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Group: dto.Group, Message: dto.Message, diff --git a/internal/repository/cloud-account.go b/internal/repository/cloud-account.go index 72508451..b3dd6efc 100644 --- a/internal/repository/cloud-account.go +++ b/internal/repository/cloud-account.go @@ -75,6 +75,7 @@ func (r *CloudAccountRepository) Fetch(ctx context.Context, organizationId strin func (r *CloudAccountRepository) Create(ctx context.Context, dto model.CloudAccount) (cloudAccountId uuid.UUID, err error) { cloudAccount := model.CloudAccount{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Name: dto.Name, Description: dto.Description, diff --git a/internal/repository/cluster.go b/internal/repository/cluster.go index 9d25be0a..88c786ee 100644 --- a/internal/repository/cluster.go +++ b/internal/repository/cluster.go @@ -212,6 +212,7 @@ func (r *ClusterRepository) SetFavorite(ctx context.Context, clusterId domain.Cl } clusterFavorite := model.ClusterFavorite{ + ID: uuid.New(), ClusterId: clusterId, UserId: userId, } diff --git a/internal/repository/organization.go b/internal/repository/organization.go index e98cd899..f7266bba 100644 --- a/internal/repository/organization.go +++ b/internal/repository/organization.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -16,9 +17,11 @@ type IOrganizationRepository interface { Create(ctx context.Context, dto *model.Organization) (model.Organization, error) Fetch(ctx context.Context, pg *pagination.Pagination) (res *[]model.Organization, err error) Get(ctx context.Context, organizationId string) (res model.Organization, err error) - Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Update(ctx context.Context, organizationId string, in model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, primaryClusterId string) error UpdateAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error + UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) + UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) Delete(ctx context.Context, organizationId string) (err error) InitWorkflow(ctx context.Context, organizationId string, workflowId string, status domain.OrganizationStatus) error } @@ -94,13 +97,12 @@ func (r *OrganizationRepository) Get(ctx context.Context, id string) (out model. return } -func (r *OrganizationRepository) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (out model.Organization, err error) { +func (r *OrganizationRepository) Update(ctx context.Context, organizationId string, in model.Organization) (out model.Organization, err error) { res := r.db.WithContext(ctx).Model(&model.Organization{}). Where("id = ?", organizationId). Updates(map[string]interface{}{ "name": in.Name, "description": in.Description, - "phone": in.Phone, }) if res.Error != nil { @@ -163,3 +165,24 @@ func (r *OrganizationRepository) InitWorkflow(ctx context.Context, organizationI } return nil } + +func (r *OrganizationRepository) UpdateStackTemplates(ctx context.Context, organizationId string, stackTemplates []model.StackTemplate) (err error) { + var organization = model.Organization{} + res := r.db.WithContext(ctx).Preload("StackTemplates").First(&organization, "id = ?", organizationId) + if res.Error != nil { + return res.Error + } + + err = r.db.WithContext(ctx).Model(&organization).Association("StackTemplates").Replace(stackTemplates) + if err != nil { + return err + } + + return nil +} + +func (r *OrganizationRepository) UpdatePolicyTemplates(ctx context.Context, organizationId string, policyTemplates []model.PolicyTemplate) (err error) { + // [TODO] + + return nil +} diff --git a/internal/repository/permission.go b/internal/repository/permission.go index 335ce2e4..144d0a68 100644 --- a/internal/repository/permission.go +++ b/internal/repository/permission.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "gorm.io/gorm" @@ -47,6 +48,7 @@ func (r PermissionRepository) Create(ctx context.Context, p *model.Permission) e // } //} + p.ID = uuid.New() return r.db.WithContext(ctx).Create(p).Error } diff --git a/internal/repository/policy-template.go b/internal/repository/policy-template.go index 92053bb4..806661d9 100644 --- a/internal/repository/policy-template.go +++ b/internal/repository/policy-template.go @@ -52,6 +52,7 @@ func (r *PolicyTemplateRepository) Create(ctx context.Context, dto model.PolicyT } policyTemplate := model.PolicyTemplate{ + ID: uuid.New(), Type: "tks", Name: dto.TemplateName, Version: "v1.0.0", diff --git a/internal/repository/project.go b/internal/repository/project.go index a5df7edf..53c4041d 100644 --- a/internal/repository/project.go +++ b/internal/repository/project.go @@ -55,6 +55,7 @@ func NewProjectRepository(db *gorm.DB) IProjectRepository { } func (r *ProjectRepository) CreateProject(ctx context.Context, p *model.Project) (string, error) { + p.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&p) if res.Error != nil { return "", res.Error @@ -366,6 +367,7 @@ func (r *ProjectRepository) GetProjectRoleByName(ctx context.Context, name strin } func (r *ProjectRepository) AddProjectMember(ctx context.Context, pm *model.ProjectMember) (string, error) { + pm.ID = uuid.New().String() res := r.db.WithContext(ctx).Create(&pm) if res.Error != nil { return "", res.Error diff --git a/internal/repository/role.go b/internal/repository/role.go index b3b1aa12..a4af220d 100644 --- a/internal/repository/role.go +++ b/internal/repository/role.go @@ -1,10 +1,11 @@ package repository import ( + "context" "fmt" "math" - "context" + "github.com/google/uuid" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" "gorm.io/gorm" @@ -36,6 +37,7 @@ func (r RoleRepository) Create(ctx context.Context, roleObj *model.Role) (string if roleObj == nil { return "", fmt.Errorf("roleObj is nil") } + roleObj.ID = uuid.New().String() if err := r.db.WithContext(ctx).Create(roleObj).Error; err != nil { return "", err } @@ -69,7 +71,6 @@ func (r RoleRepository) ListTksRoles(ctx context.Context, organizationId string, return roles, nil } - func (r RoleRepository) GetTksRole(ctx context.Context, id string) (*model.Role, error) { var role model.Role if err := r.db.WithContext(ctx).First(&role, "id = ?", id).Error; err != nil { diff --git a/internal/repository/stack-template.go b/internal/repository/stack-template.go index 56dc5bd1..e94b70fc 100644 --- a/internal/repository/stack-template.go +++ b/internal/repository/stack-template.go @@ -2,6 +2,7 @@ package repository import ( "context" + "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -77,6 +78,7 @@ func (r *StackTemplateRepository) FetchWithOrganization(ctx context.Context, org } func (r *StackTemplateRepository) Create(ctx context.Context, dto model.StackTemplate) (stackTemplateId uuid.UUID, err error) { + dto.ID = uuid.New() res := r.db.WithContext(ctx).Create(&dto) if res.Error != nil { return uuid.Nil, res.Error diff --git a/internal/repository/system-notification.go b/internal/repository/system-notification.go index 3c6dff2b..58bb1336 100644 --- a/internal/repository/system-notification.go +++ b/internal/repository/system-notification.go @@ -85,6 +85,7 @@ func (r *SystemNotificationRepository) FetchPodRestart(ctx context.Context, orga func (r *SystemNotificationRepository) Create(ctx context.Context, dto model.SystemNotification) (systemNotificationId uuid.UUID, err error) { systemNotification := model.SystemNotification{ + ID: uuid.New(), OrganizationId: dto.OrganizationId, Name: dto.Name, Code: dto.Code, @@ -126,6 +127,7 @@ func (r *SystemNotificationRepository) Delete(ctx context.Context, dto model.Sys func (r *SystemNotificationRepository) CreateSystemNotificationAction(ctx context.Context, dto model.SystemNotificationAction) (systemNotificationActionId uuid.UUID, err error) { systemNotification := model.SystemNotificationAction{ + ID: uuid.New(), SystemNotificationId: dto.SystemNotificationId, Content: dto.Content, Status: dto.Status, diff --git a/internal/repository/user.go b/internal/repository/user.go index 478aaba5..451271e0 100644 --- a/internal/repository/user.go +++ b/internal/repository/user.go @@ -55,14 +55,15 @@ func (r *UserRepository) CreateWithUuid(ctx context.Context, uuid uuid.UUID, acc department string, description string, organizationId string, roleId string) (model.User, error) { newUser := model.User{ - ID: uuid, - AccountId: accountId, - Name: name, - Email: email, - Department: department, - Description: description, - OrganizationId: organizationId, - RoleId: roleId, + ID: uuid, + AccountId: accountId, + Name: name, + Email: email, + Department: department, + Description: description, + OrganizationId: organizationId, + RoleId: roleId, + PasswordUpdatedAt: time.Now(), } res := r.db.WithContext(ctx).Create(&newUser) if res.Error != nil { diff --git a/internal/route/route.go b/internal/route/route.go index 5d789954..7e40bd6a 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -116,7 +116,6 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile/next-password-change", customMiddleware.Handle(internalApi.RenewPasswordExpiredDate, http.HandlerFunc(userHandler.RenewPasswordExpiredDate))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/my-profile", customMiddleware.Handle(internalApi.DeleteMyProfile, http.HandlerFunc(userHandler.DeleteMyProfile))).Methods(http.MethodDelete) - // Admin r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_CreateUser, http.HandlerFunc(userHandler.Admin_Create))).Methods(http.MethodPost) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users", customMiddleware.Handle(internalApi.Admin_ListUser, http.HandlerFunc(userHandler.Admin_List))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_GetUser, http.HandlerFunc(userHandler.Admin_Get))).Methods(http.MethodGet) @@ -124,12 +123,14 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}/users/{accountId}", customMiddleware.Handle(internalApi.Admin_DeleteUser, http.HandlerFunc(userHandler.Admin_Delete))).Methods(http.MethodDelete) organizationHandler := delivery.NewOrganizationHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.CreateOrganization, http.HandlerFunc(organizationHandler.CreateOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations", customMiddleware.Handle(internalApi.Admin_CreateOrganization, http.HandlerFunc(organizationHandler.Admin_CreateOrganization))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_DeleteOrganization, http.HandlerFunc(organizationHandler.Admin_DeleteOrganization))).Methods(http.MethodDelete) + r.Handle(API_PREFIX+API_VERSION+ADMINAPI_PREFIX+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.Admin_UpdateOrganization, http.HandlerFunc(organizationHandler.Admin_UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations", customMiddleware.Handle(internalApi.GetOrganizations, http.HandlerFunc(organizationHandler.GetOrganizations))).Methods(http.MethodGet) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.GetOrganization, http.HandlerFunc(organizationHandler.GetOrganization))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.DeleteOrganization, http.HandlerFunc(organizationHandler.DeleteOrganization))).Methods(http.MethodDelete) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}", customMiddleware.Handle(internalApi.UpdateOrganization, http.HandlerFunc(organizationHandler.UpdateOrganization))).Methods(http.MethodPut) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/primary-cluster", customMiddleware.Handle(internalApi.UpdatePrimaryCluster, http.HandlerFunc(organizationHandler.UpdatePrimaryCluster))).Methods(http.MethodPatch) + r.Handle(API_PREFIX+API_VERSION+"/organizations/name/{name}/existence", customMiddleware.Handle(internalApi.CheckOrganizationName, http.HandlerFunc(organizationHandler.CheckOrganizationName))).Methods(http.MethodGet) clusterHandler := delivery.NewClusterHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/clusters", customMiddleware.Handle(internalApi.CreateCluster, http.HandlerFunc(clusterHandler.CreateCluster))).Methods(http.MethodPost) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index 83970930..7409a392 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -24,27 +24,31 @@ type IOrganizationUsecase interface { Create(context.Context, *model.Organization) (organizationId string, err error) Fetch(ctx context.Context, pg *pagination.Pagination) (*[]model.Organization, error) Get(ctx context.Context, organizationId string) (model.Organization, error) - Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) + Update(ctx context.Context, organizationId string, dto model.Organization) (model.Organization, error) UpdatePrimaryClusterId(ctx context.Context, organizationId string, clusterId string) (err error) + UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) ChangeAdminId(ctx context.Context, organizationId string, adminId uuid.UUID) error Delete(ctx context.Context, organizationId string, accessToken string) error } type OrganizationUsecase struct { - repo repository.IOrganizationRepository - roleRepo repository.IRoleRepository - clusterRepo repository.IClusterRepository - argo argowf.ArgoClient - kc keycloak.IKeycloak + repo repository.IOrganizationRepository + roleRepo repository.IRoleRepository + clusterRepo repository.IClusterRepository + stackTemplateRepo repository.IStackTemplateRepository + policyTemplateRepo repository.IPolicyTemplateRepository + argo argowf.ArgoClient + kc keycloak.IKeycloak } func NewOrganizationUsecase(r repository.Repository, argoClient argowf.ArgoClient, kc keycloak.IKeycloak) IOrganizationUsecase { return &OrganizationUsecase{ - repo: r.Organization, - roleRepo: r.Role, - clusterRepo: r.Cluster, - argo: argoClient, - kc: kc, + repo: r.Organization, + roleRepo: r.Role, + clusterRepo: r.Cluster, + stackTemplateRepo: r.StackTemplate, + argo: argoClient, + kc: kc, } } @@ -144,7 +148,7 @@ func (u *OrganizationUsecase) Delete(ctx context.Context, organizationId string, return nil } -func (u *OrganizationUsecase) Update(ctx context.Context, organizationId string, in domain.UpdateOrganizationRequest) (model.Organization, error) { +func (u *OrganizationUsecase) Update(ctx context.Context, organizationId string, in model.Organization) (model.Organization, error) { _, err := u.Get(ctx, organizationId) if err != nil { return model.Organization{}, httpErrors.NewNotFoundError(err, "", "") @@ -188,3 +192,38 @@ func (u *OrganizationUsecase) ChangeAdminId(ctx context.Context, organizationId return nil } + +func (u *OrganizationUsecase) UpdateWithTemplates(ctx context.Context, organizationId string, dto model.Organization) (err error) { + _, err = u.Update(ctx, organizationId, dto) + if err != nil { + return err + } + + stackTemplates := make([]model.StackTemplate, 0) + for _, stackTemplateId := range dto.StackTemplateIds { + stackTemplate, err := u.stackTemplateRepo.Get(ctx, stackTemplateId) + if err != nil { + return fmt.Errorf("Invalid stackTemplateId") + } + stackTemplates = append(stackTemplates, stackTemplate) + } + err = u.repo.UpdateStackTemplates(ctx, organizationId, stackTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_STACK_TEMPLATES", "") + } + + policyTemplates := make([]model.PolicyTemplate, 0) + for _, policyTemplateId := range dto.PolicyTemplateIds { + policyTemplate, err := u.policyTemplateRepo.GetByID(ctx, policyTemplateId) + if err != nil { + return fmt.Errorf("Invalid policyTemplateId") + } + policyTemplates = append(policyTemplates, *policyTemplate) + } + err = u.repo.UpdatePolicyTemplates(ctx, organizationId, policyTemplates) + if err != nil { + return httpErrors.NewBadRequestError(err, "O_FAILED_UPDATE_POLICY_TEMPLATES", "") + } + + return nil +} diff --git a/pkg/domain/organization.go b/pkg/domain/organization.go index 7153744d..3e330fa6 100644 --- a/pkg/domain/organization.go +++ b/pkg/domain/organization.go @@ -52,7 +52,6 @@ type OrganizationResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` - Phone string `json:"phone"` PrimaryClusterId string `json:"primaryClusterId"` Status string `json:"status"` StatusDesc string `json:"statusDesc"` @@ -94,14 +93,25 @@ type UpdateOrganizationRequest struct { PrimaryClusterId string `json:"primaryClusterId"` Name string `json:"name" validate:"required,min=1,max=30"` Description string `json:"description" validate:"omitempty,min=0,max=100"` - Phone string `json:"phone"` } type UpdateOrganizationResponse struct { ID string `json:"id"` Name string `json:"name"` Description string `json:"description"` - Phone string `json:"phone"` +} + +type Admin_UpdateOrganizationRequest struct { + PrimaryClusterId string `json:"primaryClusterId"` + Name string `json:"name" validate:"required,min=1,max=30"` + Description string `json:"description" validate:"omitempty,min=0,max=100"` + StackTemplateIds []string `json:"stackTemplateIds"` + PolicyTemplateIds []string `json:"policyTemplateIds"` + SystemNotificationTemplateIds []string `json:"systemNotificationTemplateIds"` +} + +type Admin_UpdateOrganizationResponse struct { + ID string `json:"id"` } type UpdatePrimaryClusterRequest struct { diff --git a/pkg/domain/stack-template.go b/pkg/domain/stack-template.go index d25a570a..ff1f2570 100644 --- a/pkg/domain/stack-template.go +++ b/pkg/domain/stack-template.go @@ -37,15 +37,19 @@ type StackTemplateResponse struct { UpdatedAt time.Time `json:"updatedAt"` } +type SimpleStackTemplateServiceResponse struct { + Type string `json:"type"` +} + type SimpleStackTemplateResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Template string `json:"template"` - CloudService string `json:"cloudService"` - KubeVersion string `json:"kubeVersion"` - KubeType string `json:"kubeType"` - Services []StackTemplateServiceResponse `json:"services"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Template string `json:"template"` + CloudService string `json:"cloudService"` + KubeVersion string `json:"kubeVersion"` + KubeType string `json:"kubeType"` + Services []SimpleStackTemplateServiceResponse `json:"services"` } type GetStackTemplatesResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index c2ee6d0d..30bcb76e 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -33,6 +33,12 @@ var errorMap = map[ErrorCode]string{ "A_EXPIRED_CODE": "인증번호가 만료되었습니다.", "A_UNUSABLE_TOKEN": "사용할 수 없는 토큰입니다.", + // Organization + "O_INVALID_ORGANIZATION_NAME": "조직에 이미 존재하는 이름입니다.", + "O_FAILED_UPDATE_STACK_TEMPLATES": "조직에 스택템플릿을 설정하는데 실패했습니다", + "O_FAILED_UPDATE_POLICY_TEMPLATES": "조직에 정책템플릿을 설정하는데 실패했습니다", + "O_FAILED_UPDATE_SYSTEM_NOTIFICATION_TEMPLATES": "조직에 알림템플릿을 설정하는데 실패했습니다", + // User "U_NO_USER": "해당 사용자 정보를 찾을 수 없습니다.",