diff --git a/api/swagger/docs.go b/api/swagger/docs.go index 0b44751f..b7ccdc0d 100644 --- a/api/swagger/docs.go +++ b/api/swagger/docs.go @@ -394,7 +394,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -495,7 +495,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -532,7 +532,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -569,7 +569,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -679,7 +679,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -716,7 +716,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -753,7 +753,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -834,7 +834,7 @@ const docTemplate = `{ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -7385,7 +7385,7 @@ const docTemplate = `{ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -9000,14 +9000,68 @@ const docTemplate = `{ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11305,6 +11359,46 @@ const docTemplate = `{ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -11391,9 +11485,36 @@ const docTemplate = `{ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -11837,9 +11958,69 @@ const docTemplate = `{ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 58f58a56..6a9be303 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -388,7 +388,7 @@ } } }, - "/admin/policytemplates": { + "/admin/policy-templates": { "get": { "security": [ { @@ -489,7 +489,7 @@ } } }, - "/admin/policytemplates/kind/{policyTemplateKind}/existence": { + "/admin/policy-templates/kind/{policyTemplateKind}/existence": { "get": { "security": [ { @@ -526,7 +526,7 @@ } } }, - "/admin/policytemplates/name/{policyTemplateName}/existence": { + "/admin/policy-templates/name/{policyTemplateName}/existence": { "get": { "security": [ { @@ -563,7 +563,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}": { + "/admin/policy-templates/{policyTemplateId}": { "get": { "security": [ { @@ -673,7 +673,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/deploy": { + "/admin/policy-templates/{policyTemplateId}/deploy": { "get": { "security": [ { @@ -710,7 +710,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/statistics": { + "/admin/policy-templates/{policyTemplateId}/statistics": { "get": { "security": [ { @@ -747,7 +747,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions": { + "/admin/policy-templates/{policyTemplateId}/versions": { "get": { "security": [ { @@ -828,7 +828,7 @@ } } }, - "/admin/policytemplates/{policyTemplateId}/versions/{version}": { + "/admin/policy-templates/{policyTemplateId}/versions/{version}": { "get": { "security": [ { @@ -7379,7 +7379,7 @@ } } }, - "/policytemplates/rego-compile": { + "/policy-templates/rego-compile": { "post": { "security": [ { @@ -8994,14 +8994,68 @@ "github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleRequest": { "type": "object", "required": [ - "name" + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" ], "properties": { "description": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -11299,6 +11353,46 @@ } } }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + }, + "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter": { + "type": "object", + "properties": { + "operator": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "value": { + "type": "string" + } + } + }, "github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse": { "type": "object", "properties": { @@ -11385,9 +11479,36 @@ "id": { "type": "string" }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, "name": { "type": "string" }, + "systemNotificationConditions": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse" + } + }, + "systemNotificationTemplate": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse" + }, + "targetUsers": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse" + } + }, "updatedAt": { "type": "string" }, @@ -11831,9 +11952,69 @@ }, "github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationRuleRequest": { "type": "object", + "required": [ + "messageCondition", + "messageContent", + "messageTitle", + "name", + "systemNotificationTemplateId" + ], "properties": { "description": { "type": "string" + }, + "messageActionProposal": { + "type": "string" + }, + "messageCondition": { + "type": "string" + }, + "messageContent": { + "type": "string" + }, + "messageTitle": { + "type": "string" + }, + "name": { + "type": "string" + }, + "systemNotificationConditions": { + "type": "array", + "items": { + "type": "object", + "properties": { + "duration": { + "type": "integer" + }, + "enableEmail": { + "type": "boolean" + }, + "enablePortal": { + "type": "boolean" + }, + "order": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter" + } + }, + "severity": { + "type": "string" + } + } + } + }, + "systemNotificationTemplateId": { + "type": "string" + }, + "targetUserIds": { + "type": "array", + "items": { + "type": "string" + } } } }, diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml index 71ac2318..1dc24bd5 100644 --- a/api/swagger/swagger.yaml +++ b/api/swagger/swagger.yaml @@ -1060,10 +1060,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array required: + - messageCondition + - messageContent + - messageTitle - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.CreateSystemNotificationRuleResponse: properties: @@ -2576,6 +2613,32 @@ definitions: updatedAt: type: string type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter: + properties: + operator: + type: string + order: + type: integer + value: + type: string + type: object github_com_openinfradev_tks-api_pkg_domain.SystemNotificationResponse: properties: closedAt: @@ -2633,8 +2696,26 @@ definitions: type: string id: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string name: type: string + systemNotificationConditions: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationConditionResponse' + type: array + systemNotificationTemplate: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleSystemNotificationTemplateResponse' + targetUsers: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SimpleUserResponse' + type: array updatedAt: type: string updator: @@ -2930,6 +3011,47 @@ definitions: properties: description: type: string + messageActionProposal: + type: string + messageCondition: + type: string + messageContent: + type: string + messageTitle: + type: string + name: + type: string + systemNotificationConditions: + items: + properties: + duration: + type: integer + enableEmail: + type: boolean + enablePortal: + type: boolean + order: + type: integer + parameters: + items: + $ref: '#/definitions/github_com_openinfradev_tks-api_pkg_domain.SystemNotificationParameter' + type: array + severity: + type: string + type: object + type: array + systemNotificationTemplateId: + type: string + targetUserIds: + items: + type: string + type: array + required: + - messageCondition + - messageContent + - messageTitle + - name + - systemNotificationTemplateId type: object github_com_openinfradev_tks-api_pkg_domain.UpdateSystemNotificationTemplateRequest: properties: @@ -3397,7 +3519,7 @@ paths: summary: Update user by admin tags: - Admin - /admin/policytemplates: + /admin/policy-templates: get: consumes: - application/json @@ -3461,7 +3583,7 @@ paths: summary: '[CreatePolicyTemplate] 정책 템플릿 신규 생성' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}: + /admin/policy-templates/{policyTemplateId}: delete: consumes: - application/json @@ -3530,7 +3652,7 @@ paths: summary: '[UpdatePolicyTemplate] 정책 템플릿 업데이트' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/deploy: + /admin/policy-templates/{policyTemplateId}/deploy: get: consumes: - application/json @@ -3553,7 +3675,7 @@ paths: summary: '[GetPolicyTemplateDeploy] 정책 템플릿 클러스터 별 설치 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/statistics: + /admin/policy-templates/{policyTemplateId}/statistics: get: consumes: - application/json @@ -3577,7 +3699,7 @@ paths: summary: '[ListPolicyTemplateStatistics] 정책 템플릿 사용 카운트 조회' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions: + /admin/policy-templates/{policyTemplateId}/versions: get: consumes: - application/json @@ -3628,7 +3750,7 @@ paths: summary: '[CreatePolicyTemplateVersion] 정책 템플릿 특정 버전 저장' tags: - PolicyTemplate - /admin/policytemplates/{policyTemplateId}/versions/{version}: + /admin/policy-templates/{policyTemplateId}/versions/{version}: delete: consumes: - application/json @@ -3681,7 +3803,7 @@ paths: summary: '[GetPolicyTemplateVersion] 정책 템플릿 특정 버전 조회' tags: - PolicyTemplate - /admin/policytemplates/kind/{policyTemplateKind}/existence: + /admin/policy-templates/kind/{policyTemplateKind}/existence: get: consumes: - application/json @@ -3704,7 +3826,7 @@ paths: summary: '[ExistsPolicyTemplateKind] 정책 템플릿 유형 존재 여부 확인' tags: - PolicyTemplate - /admin/policytemplates/name/{policyTemplateName}/existence: + /admin/policy-templates/name/{policyTemplateName}/existence: get: consumes: - application/json @@ -7860,7 +7982,7 @@ paths: summary: Get Permission Templates tags: - Permission - /policytemplates/rego-compile: + /policy-templates/rego-compile: post: consumes: - application/json diff --git a/internal/database/database.go b/internal/database/database.go index a6d9cb85..5af01cbb 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -127,13 +127,10 @@ func migrateSchema(db *gorm.DB) error { } // SystemNotificationRule - if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { - return err - } if err := db.AutoMigrate(&model.SystemNotificationCondition{}); err != nil { return err } - if err := db.AutoMigrate(&model.SystemNotificationMessage{}); err != nil { + if err := db.AutoMigrate(&model.SystemNotificationRule{}); err != nil { return err } diff --git a/internal/delivery/http/system-notification-rule.go b/internal/delivery/http/system-notification-rule.go index 068966bc..2c27207c 100644 --- a/internal/delivery/http/system-notification-rule.go +++ b/internal/delivery/http/system-notification-rule.go @@ -1,6 +1,7 @@ package http import ( + "encoding/json" "fmt" "net/http" @@ -38,6 +39,13 @@ func NewSystemNotificationRuleHandler(h usecase.Usecase) *SystemNotificationRule // @Router /organizations/{organizationId}/system-notification-rules [post] // @Security JWT func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(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.CreateSystemNotificationRuleRequest{} err := UnmarshalRequestInput(r, &input) if err != nil { @@ -49,6 +57,14 @@ func (h *SystemNotificationRuleHandler) CreateSystemNotificationRule(w http.Resp if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId + + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } id, err := h.usecase.Create(r.Context(), dto) if err != nil { @@ -99,6 +115,25 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRules(w http.Respon if err := serializer.Map(r.Context(), systemNotificationRule, &out.SystemNotificationRules[i]); err != nil { log.Info(r.Context(), err) } + + out.SystemNotificationRules[i].TargetUsers = make([]domain.SimpleUserResponse, len(systemNotificationRule.TargetUsers)) + for j, targetUser := range systemNotificationRule.TargetUsers { + if err := serializer.Map(r.Context(), targetUser, &out.SystemNotificationRules[i].TargetUsers[j]); err != nil { + log.Info(r.Context(), err) + } + } + + out.SystemNotificationRules[i].SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for j, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRules[i].SystemNotificationConditions[j]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRules[i].SystemNotificationConditions[j].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } } if out.Pagination, err = pg.Response(r.Context()); err != nil { @@ -144,6 +179,18 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons log.Info(r.Context(), err) } + out.SystemNotificationRule.SystemNotificationConditions = make([]domain.SystemNotificationConditionResponse, len(systemNotificationRule.SystemNotificationConditions)) + for i, condition := range systemNotificationRule.SystemNotificationConditions { + if err := serializer.Map(r.Context(), condition, &out.SystemNotificationRule.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + log.Info(r.Context(), condition.Parameter) + err = json.Unmarshal(condition.Parameter, &out.SystemNotificationRule.SystemNotificationConditions[i].Parameters) + if err != nil { + log.Error(r.Context(), err) + } + } + ResponseJSON(w, r, http.StatusOK, out) } @@ -160,24 +207,44 @@ func (h *SystemNotificationRuleHandler) GetSystemNotificationRule(w http.Respons // @Security JWT func (h *SystemNotificationRuleHandler) UpdateSystemNotificationRule(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 + } + strId, ok := vars["systemNotificationRuleId"] if !ok { ErrorJSON(w, r, httpErrors.NewBadRequestError(fmt.Errorf("invalid systemNotificationRuleId"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } - systemNotificationRuleId, err := uuid.Parse(strId) if err != nil { ErrorJSON(w, r, httpErrors.NewBadRequestError(errors.Wrap(err, "Failed to parse uuid %s"), "C_INVALID_STACK_TEMPLATE_ID", "")) return } + input := domain.UpdateSystemNotificationRuleRequest{} + err = UnmarshalRequestInput(r, &input) + if err != nil { + ErrorJSON(w, r, err) + return + } + var dto model.SystemNotificationRule - if err := serializer.Map(r.Context(), r, &dto); err != nil { + if err = serializer.Map(r.Context(), input, &dto); err != nil { log.Info(r.Context(), err) } + dto.OrganizationId = organizationId dto.ID = systemNotificationRuleId + dto.SystemNotificationConditions = make([]model.SystemNotificationCondition, len(input.SystemNotificationConditions)) + for i, systemNotificationCondition := range input.SystemNotificationConditions { + if err := serializer.Map(r.Context(), systemNotificationCondition, &dto.SystemNotificationConditions[i]); err != nil { + log.Info(r.Context(), err) + } + } + err = h.usecase.Update(r.Context(), dto) if err != nil { ErrorJSON(w, r, err) diff --git a/internal/model/system-notification-rule.go b/internal/model/system-notification-rule.go index b1ddee30..9ab63c37 100644 --- a/internal/model/system-notification-rule.go +++ b/internal/model/system-notification-rule.go @@ -2,40 +2,43 @@ package model import ( "github.com/google/uuid" + "github.com/openinfradev/tks-api/pkg/domain" "gorm.io/datatypes" "gorm.io/gorm" ) type SystemNotificationCondition struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Order int `gorm:"primarykey"` + gorm.Model + + SystemNotificationRuleId uuid.UUID + Order int Severity string Duration int - Condition datatypes.JSON - EnableEmail bool `gorm:"default:false"` - EnablePortal bool `gorm:"default:true"` -} - -type SystemNotificationMessage struct { - SystemNotificationRuleId uuid.UUID `gorm:"primarykey"` - Title string - Content int - Condition datatypes.JSON - ActionProposal string - TargetUsers []User `gorm:"many2many:system_notification_message_users"` + Parameter datatypes.JSON + Parameters []domain.SystemNotificationParameter `gorm:"-:all"` + EnableEmail bool `gorm:"default:false"` + EnablePortal bool `gorm:"default:true"` } type SystemNotificationRule struct { gorm.Model - ID uuid.UUID `gorm:"primarykey"` - Name string `gorm:"index,unique"` - Description string - Templates []SystemNotificationTemplate `gorm:"many2many:system_notification_rule_system_notification_templates"` - Messages []SystemNotificationMessage `gorm:"many2many:system_notification_rule_system_notification_messages"` - - CreatorId *uuid.UUID `gorm:"type:uuid"` - Creator *User `gorm:"foreignKey:CreatorId"` - UpdatorId *uuid.UUID `gorm:"type:uuid"` - Updator *User `gorm:"foreignKey:UpdatorId"` + ID uuid.UUID `gorm:"primarykey"` + Name string `gorm:"index,unique"` + Description string + OrganizationId string + Organization Organization `gorm:"foreignKey:OrganizationId"` + SystemNotificationTemplate SystemNotificationTemplate `gorm:"foreignKey:SystemNotificationTemplateId"` + SystemNotificationTemplateId string + SystemNotificationConditions []SystemNotificationCondition `gorm:"foreignKey:SystemNotificationRuleId"` + TargetUsers []User `gorm:"many2many:system_notification_rule_users"` + TargetUserIds []string `gorm:"-:all"` + MessageTitle string + MessageContent string + MessageCondition datatypes.JSON + MessageActionProposal string + CreatorId *uuid.UUID `gorm:"type:uuid"` + Creator *User `gorm:"foreignKey:CreatorId"` + UpdatorId *uuid.UUID `gorm:"type:uuid"` + Updator *User `gorm:"foreignKey:UpdatorId"` } diff --git a/internal/repository/system-notification-rule.go b/internal/repository/system-notification-rule.go index 3e07db21..84ed1063 100644 --- a/internal/repository/system-notification-rule.go +++ b/internal/repository/system-notification-rule.go @@ -20,7 +20,6 @@ type ISystemNotificationRuleRepository interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRuleId uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) - UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizationIds []model.Organization) (err error) } type SystemNotificationRuleRepository struct { @@ -83,40 +82,48 @@ func (r *SystemNotificationRuleRepository) Create(ctx context.Context, dto model if res.Error != nil { return uuid.Nil, res.Error } + return dto.ID, nil } func (r *SystemNotificationRuleRepository) Update(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Model(&model.SystemNotificationRule{}). - Where("id = ?", dto.ID). - Updates(map[string]interface{}{ - "Name": dto.Name, - "Description": dto.Description, - "UpdatorId": dto.UpdatorId}) + var m model.SystemNotificationRule + res := r.db.WithContext(ctx).Preload(clause.Associations).First(&m, "id = ?", dto.ID) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { - res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + m.Name = dto.Name + m.Description = dto.Description + m.SystemNotificationTemplateId = dto.SystemNotificationTemplateId + //m.SystemNotificationConditions = dto.SystemNotificationConditions + m.MessageTitle = dto.MessageTitle + m.MessageContent = dto.MessageContent + m.MessageCondition = dto.MessageCondition + m.MessageActionProposal = dto.MessageActionProposal + m.UpdatorId = dto.UpdatorId + + res = r.db.WithContext(ctx).Session(&gorm.Session{FullSaveAssociations: true}).Updates(&m) if res.Error != nil { return res.Error } - return nil -} -func (r *SystemNotificationRuleRepository) UpdateOrganizations(ctx context.Context, systemNotificationRuleId uuid.UUID, organizations []model.Organization) (err error) { - var systemNotificationRule = model.SystemNotificationRule{} - res := r.db.WithContext(ctx).Preload("Organizations").First(&systemNotificationRule, "id = ?", systemNotificationRuleId) - if res.Error != nil { - return res.Error + err = r.db.WithContext(ctx).Model(&m).Association("TargetUsers").Replace(dto.TargetUsers) + if err != nil { + return err } - err = r.db.WithContext(ctx).Model(&systemNotificationRule).Association("Organizations").Replace(organizations) + err = r.db.WithContext(ctx).Model(&m).Association("SystemNotificationConditions").Replace(dto.SystemNotificationConditions) if err != nil { return err } return nil } + +func (r *SystemNotificationRuleRepository) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { + res := r.db.WithContext(ctx).Delete(&model.SystemNotificationRule{}, "id = ?", dto.ID) + if res.Error != nil { + return res.Error + } + return nil +} diff --git a/internal/route/route.go b/internal/route/route.go index bb00ba3b..be0ef533 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -225,10 +225,10 @@ func SetupRouter(db *gorm.DB, argoClient argowf.ArgoClient, kc keycloak.IKeycloa r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-templates", customMiddleware.Handle(internalApi.RemoveOrganizationSystemNotificationTemplates, http.HandlerFunc(systemNotificationTemplateHandler.RemoveOrganizationSystemNotificationTemplates))).Methods(http.MethodPut) systemNotificationRuleHandler := delivery.NewSystemNotificationRuleHandler(usecaseFactory) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) - r.Handle(API_PREFIX+API_VERSION+"/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.CreateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.CreateSystemNotificationRule))).Methods(http.MethodPost) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules", customMiddleware.Handle(internalApi.GetSystemNotificationRules, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRules))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.GetSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.GetSystemNotificationRule))).Methods(http.MethodGet) + r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/system-notification-rules/{systemNotificationRuleId}", customMiddleware.Handle(internalApi.UpdateSystemNotificationRule, http.HandlerFunc(systemNotificationRuleHandler.UpdateSystemNotificationRule))).Methods(http.MethodPut) stackHandler := delivery.NewStackHandler(usecaseFactory) r.Handle(API_PREFIX+API_VERSION+"/organizations/{organizationId}/stacks", customMiddleware.Handle(internalApi.GetStacks, http.HandlerFunc(stackHandler.GetStacks))).Methods(http.MethodGet) diff --git a/internal/usecase/organization.go b/internal/usecase/organization.go index ff7c59d0..9fa70a56 100644 --- a/internal/usecase/organization.go +++ b/internal/usecase/organization.go @@ -35,7 +35,6 @@ type OrganizationUsecase struct { roleRepo repository.IRoleRepository clusterRepo repository.IClusterRepository stackTemplateRepo repository.IStackTemplateRepository - policyTemplateRepo repository.IPolicyTemplateRepository systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository argo argowf.ArgoClient kc keycloak.IKeycloak diff --git a/internal/usecase/system-notification-rule.go b/internal/usecase/system-notification-rule.go index 8aa4c384..d69c5c15 100644 --- a/internal/usecase/system-notification-rule.go +++ b/internal/usecase/system-notification-rule.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/google/uuid" + "github.com/openinfradev/tks-api/internal/helper" "github.com/openinfradev/tks-api/internal/middleware/auth/request" "github.com/openinfradev/tks-api/internal/model" "github.com/openinfradev/tks-api/internal/pagination" @@ -20,19 +21,22 @@ type ISystemNotificationRuleUsecase interface { Create(ctx context.Context, dto model.SystemNotificationRule) (systemNotificationRule uuid.UUID, err error) Update(ctx context.Context, dto model.SystemNotificationRule) error Delete(ctx context.Context, dto model.SystemNotificationRule) error - UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error GetByName(ctx context.Context, name string) (model.SystemNotificationRule, error) } type SystemNotificationRuleUsecase struct { - repo repository.ISystemNotificationRuleRepository - organizationRepo repository.IOrganizationRepository + repo repository.ISystemNotificationRuleRepository + organizationRepo repository.IOrganizationRepository + userRepo repository.IUserRepository + systemNotificationTemplateRepo repository.ISystemNotificationTemplateRepository } func NewSystemNotificationRuleUsecase(r repository.Repository) ISystemNotificationRuleUsecase { return &SystemNotificationRuleUsecase{ - repo: r.SystemNotificationRule, - organizationRepo: r.Organization, + repo: r.SystemNotificationRule, + organizationRepo: r.Organization, + userRepo: r.User, + systemNotificationTemplateRepo: r.SystemNotificationTemplate, } } @@ -46,10 +50,34 @@ func (u *SystemNotificationRuleUsecase) Create(ctx context.Context, dto model.Sy dto.UpdatorId = &userId if _, err = u.GetByName(ctx, dto.Name); err == nil { - return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "ST_CREATE_ALREADY_EXISTED_NAME", "") + return uuid.Nil, httpErrors.NewBadRequestError(fmt.Errorf("duplicate systemNotificationRule name"), "SNR_CREATE_ALREADY_EXISTED_NAME", "") } - return systemNotificationRuleId, nil + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + // Make parameters + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + + systemNotificationRuleId, err = u.repo.Create(ctx, dto) + if err != nil { + return uuid.Nil, err + } + + // [TODO] update kubernetes resources + + return } func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.SystemNotificationRule) error { @@ -58,10 +86,30 @@ func (u *SystemNotificationRuleUsecase) Update(ctx context.Context, dto model.Sy return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") } + // Users + dto.TargetUsers = make([]model.User, 0) + for _, strId := range dto.TargetUserIds { + userId, err := uuid.Parse(strId) + if err == nil { + user, err := u.userRepo.GetByUuid(ctx, userId) + if err == nil { + dto.TargetUsers = append(dto.TargetUsers, user) + } + } + } + + for i, condition := range dto.SystemNotificationConditions { + dto.SystemNotificationConditions[i].SystemNotificationRuleId = dto.ID + dto.SystemNotificationConditions[i].Parameter = []byte(helper.ModelToJson(condition.Parameters)) + } + err = u.repo.Update(ctx, dto) if err != nil { return err } + + // [TODO] update kubernetes resources + return nil } @@ -77,7 +125,7 @@ func (u *SystemNotificationRuleUsecase) GetByName(ctx context.Context, name stri out, err = u.repo.GetByName(ctx, name) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_STACK_TEMPLATE", "") + return out, httpErrors.NewNotFoundError(err, "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE", "") } return out, err } @@ -96,12 +144,3 @@ func (u *SystemNotificationRuleUsecase) Fetch(ctx context.Context, organizationI func (u *SystemNotificationRuleUsecase) Delete(ctx context.Context, dto model.SystemNotificationRule) (err error) { return nil } - -func (u *SystemNotificationRuleUsecase) UpdateOrganizations(ctx context.Context, dto model.SystemNotificationRule) error { - _, err := u.repo.Get(ctx, dto.ID) - if err != nil { - return httpErrors.NewBadRequestError(err, "SNR_NOT_EXISTED_STACK_TEMPLATE", "") - } - - return nil -} diff --git a/pkg/domain/system-notification-rule.go b/pkg/domain/system-notification-rule.go index e21e3477..d891799a 100644 --- a/pkg/domain/system-notification-rule.go +++ b/pkg/domain/system-notification-rule.go @@ -5,13 +5,35 @@ import ( ) type SystemNotificationRuleResponse struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Creator SimpleUserResponse `json:"creator"` - Updator SimpleUserResponse `json:"updator"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle"` + MessageContent string `json:"messageContent"` + MessageCondition string `json:"messageCondition"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUsers []SimpleUserResponse `json:"targetUsers"` + SystemNotificationTemplate SimpleSystemNotificationTemplateResponse `json:"systemNotificationTemplate"` + SystemNotificationConditions []SystemNotificationConditionResponse `json:"systemNotificationConditions"` + Creator SimpleUserResponse `json:"creator"` + Updator SimpleUserResponse `json:"updator"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +type SystemNotificationParameter struct { + Order int `json:"order"` + Operator string `json:"operator"` + Value string `json:"value"` +} + +type SystemNotificationConditionResponse struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` } type SimpleSystemNotificationRuleResponse struct { @@ -30,8 +52,22 @@ type GetSystemNotificationRuleResponse struct { } type CreateSystemNotificationRuleRequest struct { - Name string `json:"name" validate:"required,name"` - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CreateSystemNotificationRuleResponse struct { @@ -39,7 +75,22 @@ type CreateSystemNotificationRuleResponse struct { } type UpdateSystemNotificationRuleRequest struct { - Description string `json:"description"` + Name string `json:"name" validate:"required,name"` + Description string `json:"description"` + MessageTitle string `json:"messageTitle" validate:"required"` + MessageContent string `json:"messageContent" validate:"required"` + MessageCondition string `json:"messageCondition" validate:"required"` + MessageActionProposal string `json:"messageActionProposal"` + TargetUserIds []string `json:"targetUserIds"` + SystemNotificationTemplateId string `json:"systemNotificationTemplateId" validate:"required"` + SystemNotificationConditions []struct { + Order int `json:"order"` + Severity string `json:"severity"` + Duration int `json:"duration"` + Parameters []SystemNotificationParameter `json:"parameters"` + EnableEmail bool `json:"enableEmail"` + EnablePortal bool `json:"enablePortal"` + } `json:"systemNotificationConditions"` } type CheckSystemNotificationRuleNameResponse struct { diff --git a/pkg/httpErrors/errorCode.go b/pkg/httpErrors/errorCode.go index 5dff7467..2db07ce1 100644 --- a/pkg/httpErrors/errorCode.go +++ b/pkg/httpErrors/errorCode.go @@ -88,10 +88,10 @@ var errorMap = map[ErrorCode]string{ "SNT_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿이 존재하지 않습니다.", // SystemNotificationRule - "SNR_CREATE_ALREADY_EXISTED_NAME": "알림템플릿 설정에 이미 존재하는 이름입니다.", - "SNR_FAILED_FETCH_ALERT_TEMPLATE": "알림템플릿 설정을 가져오는데 실패했습니다.", - "SNR_FAILED_UPDATE_ORGANIZATION": "알림템플릿 설정에 조직을 설정하는데 실패했습니다.", - "SNR_NOT_EXISTED_ALERT_TEMPLATE": "업데이트할 알림템플릿 설정이 존재하지 않습니다.", + "SNR_CREATE_ALREADY_EXISTED_NAME": "알림 설정에 이미 존재하는 이름입니다.", + "SNR_FAILED_FETCH_SYSTEM_NOTIFICATION_RULE": "알림 설정을 가져오는데 실패했습니다.", + "SNR_FAILED_UPDATE_ORGANIZATION": "알림 설정에 조직을 설정하는데 실패했습니다.", + "SNR_NOT_EXISTED_SYSTEM_NOTIFICATION_RULE": "업데이트할 알림 설정이 존재하지 않습니다.", // AppGroup "AG_NOT_FOUND_CLUSTER": "지장한 클러스터가 존재하지 않습니다.",