diff --git a/admin/src/main/scala/com/neu/model/SystemConfig.scala b/admin/src/main/scala/com/neu/model/SystemConfig.scala index 2e9b4c026..da8b78194 100644 --- a/admin/src/main/scala/com/neu/model/SystemConfig.scala +++ b/admin/src/main/scala/com/neu/model/SystemConfig.scala @@ -16,6 +16,17 @@ case class RegistryHttpsProxyCfg( password: Option[String] ) case class Webhook( + name: String, + url: String, + enable: Boolean, + use_proxy: Boolean, + `type`: String, + cfg_type: String, + username: Option[String] = None, + password: Option[String] = None +) + +case class MaskedWebhook( name: String, url: String, enable: Boolean, @@ -23,6 +34,7 @@ case class Webhook( `type`: String, cfg_type: String ) + case class RemoteRepository( nickname: String, provider: String, @@ -186,6 +198,10 @@ case class WebhookConfigWrap( config: Webhook ) +case class MaskedWebhookConfigWrap( + config: MaskedWebhook +) + case class SystemConfig4DashboardWrap( config: SystemConfig4Dashboard, error: Option[Error] diff --git a/admin/src/main/scala/com/neu/model/SystemConfigJsonProtocol.scala b/admin/src/main/scala/com/neu/model/SystemConfigJsonProtocol.scala index 4ddc4b59d..b89f61b41 100644 --- a/admin/src/main/scala/com/neu/model/SystemConfigJsonProtocol.scala +++ b/admin/src/main/scala/com/neu/model/SystemConfigJsonProtocol.scala @@ -25,7 +25,7 @@ object SystemConfigJsonProtocol extends DefaultJsonProtocol { given azureDevopsConfigurationFormat: RootJsonFormat[AzureDevopsConfiguration] = jsonFormat5( AzureDevopsConfiguration.apply ) - given webhookFormat: RootJsonFormat[Webhook] = jsonFormat6(Webhook.apply) + given webhookFormat: RootJsonFormat[Webhook] = jsonFormat8(Webhook.apply) given remoteRepoFormat: RootJsonFormat[RemoteRepository] = jsonFormat6(RemoteRepository.apply) given remoteRepositoryWrapFormat: RootJsonFormat[RemoteRepositoryWrap] = jsonFormat1( RemoteRepositoryWrap.apply @@ -52,6 +52,11 @@ object SystemConfigJsonProtocol extends DefaultJsonProtocol { WebhookConfigWrap.apply ) + given MaskedWebhookFormat: RootJsonFormat[MaskedWebhook] = jsonFormat6(MaskedWebhook.apply) + given MaskedWebhookConfigWrapFormat: RootJsonFormat[MaskedWebhookConfigWrap] = jsonFormat1( + MaskedWebhookConfigWrap.apply + ) + given systemConfigSvcCfgV2Format: RootJsonFormat[SystemConfigSvcCfgV2] = jsonFormat3( SystemConfigSvcCfgV2.apply ) @@ -104,6 +109,9 @@ object SystemConfigJsonProtocol extends DefaultJsonProtocol { def webhookConfigWrapToJson(webhookConfigWrap: WebhookConfigWrap): String = webhookConfigWrap.toJson.compactPrint + def maskedWebhookConfigWrapToJson(maskedWebhookConfigWrap: MaskedWebhookConfigWrap): String = + maskedWebhookConfigWrap.toJson.compactPrint + def remoteRepositoryToJson(remoteRepository: RemoteRepository): String = remoteRepository.toJson.compactPrint diff --git a/admin/src/main/scala/com/neu/service/device/DeviceService.scala b/admin/src/main/scala/com/neu/service/device/DeviceService.scala index 8f1b0ba8a..7852559b7 100644 --- a/admin/src/main/scala/com/neu/service/device/DeviceService.scala +++ b/admin/src/main/scala/com/neu/service/device/DeviceService.scala @@ -127,8 +127,21 @@ class DeviceService extends Directives with DefaultJsonFormats with LazyLogging } def updateWebhook(tokenId: String, webhook: Webhook, scope: Option[String]): Route = complete { + val printedPayload = maskedWebhookConfigWrapToJson( + MaskedWebhookConfigWrap( + MaskedWebhook( + name = webhook.name, + url = webhook.url, + enable = webhook.enable, + use_proxy = webhook.use_proxy, + `type` = webhook.`type`, + cfg_type = webhook.cfg_type + ) + ) + ) + logger.info("Update config: {}", printedPayload) + val payload = webhookConfigWrapToJson(WebhookConfigWrap(webhook)) - logger.info("Update config: {}", payload) RestClient.httpRequestWithHeader( scope.fold( diff --git a/admin/webapp/websrc/app/common/neuvector-formly/select/select.component.html b/admin/webapp/websrc/app/common/neuvector-formly/select/select.component.html index 15f87355f..dd476cac0 100644 --- a/admin/webapp/websrc/app/common/neuvector-formly/select/select.component.html +++ b/admin/webapp/websrc/app/common/neuvector-formly/select/select.component.html @@ -1,17 +1,20 @@ - - {{ field.templateOptions?.label ?? '' | translate }} - - - {{ item.viewValue | translate }} - - - +
+ + {{ field.templateOptions?.label ?? '' | translate }} + + + {{ item.viewValue | translate }} + + + +
diff --git a/admin/webapp/websrc/app/common/types/settings/config.ts b/admin/webapp/websrc/app/common/types/settings/config.ts index 74d055179..f11421045 100644 --- a/admin/webapp/websrc/app/common/types/settings/config.ts +++ b/admin/webapp/websrc/app/common/types/settings/config.ts @@ -151,6 +151,8 @@ export interface Webhook { use_proxy: boolean; type: string; cfg_type: string; + username: string; + password: string | null; isEditable?: boolean; } diff --git a/admin/webapp/websrc/app/routes/components/federated-policy-configuration/federated-config-form/types/constants/webhook-constants.ts b/admin/webapp/websrc/app/routes/components/federated-policy-configuration/federated-config-form/types/constants/webhook-constants.ts index 03f56c081..5d4223d0f 100644 --- a/admin/webapp/websrc/app/routes/components/federated-policy-configuration/federated-config-form/types/constants/webhook-constants.ts +++ b/admin/webapp/websrc/app/routes/components/federated-policy-configuration/federated-config-form/types/constants/webhook-constants.ts @@ -110,6 +110,42 @@ export const WebhookTableField = { }, }, }, + { + key: 'username', + wrappers: [FormlyComponents.READONLY_WRAPPER], + type: FormlyComponents.ICON_INPUT, + templateOptions: { + viewValue: 'login.USERNAME', + placeholder: 'login.USERNAME', + isCell: true, + required: false, + hideRequiredMarker: true, + maxLength: 1000, + }, + validators: { + validation: [FormlyValidators.ObjName], + }, + expressionProperties: { + 'templateOptions.disabled': model => { + return !model.isEditable; + }, + }, + }, + { + key: 'password', + type: FormlyComponents.ICON_INPUT, + templateOptions: { + viewValue: 'login.PASSWORD', + isCell: true, + maxLength: 1000, + type: 'password', + }, + expressionProperties: { + 'templateOptions.disabled': model => { + return !model.isEditable; + }, + }, + }, { key: 'use_proxy', type: FormlyComponents.CHECKBOX, diff --git a/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form-config/constants/webhook-constants.ts b/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form-config/constants/webhook-constants.ts index a5d6bda53..6304f9d24 100644 --- a/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form-config/constants/webhook-constants.ts +++ b/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form-config/constants/webhook-constants.ts @@ -73,6 +73,7 @@ export const WebhookTableField = { templateOptions: { viewValue: 'setting.webhook.WH_TYPE', placeholder: 'setting.webhook.WH_TYPE', + isCell: true, items: WebhookTypes, required: true, hideRequiredMarker: true, @@ -112,6 +113,48 @@ export const WebhookTableField = { }, }, }, + { + key: 'username', + wrappers: [FormlyComponents.READONLY_WRAPPER], + type: FormlyComponents.ICON_INPUT, + templateOptions: { + viewValue: 'login.USERNAME', + placeholder: 'login.USERNAME', + isCell: true, + required: false, + hideRequiredMarker: true, + maxLength: 1000, + }, + validators: { + validation: [FormlyValidators.ObjName], + }, + expressionProperties: { + 'templateOptions.disabled': (model, formState) => { + return ( + !formState.permissions.isWebhookAuthorized || + model.cfg_type === GlobalConstant.CFG_TYPE.FED + ); + }, + }, + }, + { + key: 'password', + type: FormlyComponents.ICON_INPUT, + templateOptions: { + viewValue: 'login.PASSWORD', + isCell: true, + maxLength: 1000, + type: 'password', + }, + expressionProperties: { + 'templateOptions.disabled': (model, formState) => { + return ( + !formState.permissions.isWebhookAuthorized || + model.cfg_type === GlobalConstant.CFG_TYPE.FED + ); + }, + }, + }, { key: 'use_proxy', type: FormlyComponents.CHECKBOX, diff --git a/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form.component.ts b/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form.component.ts index f0101ad27..a194b31f6 100644 --- a/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form.component.ts +++ b/admin/webapp/websrc/app/routes/settings/configuration/config-form/config-form.component.ts @@ -216,6 +216,9 @@ export class ConfigFormComponent implements OnInit, OnDestroy { this.updateWebhookValueChanges(); this.notificationService.open(this.tr.instant('setting.SUBMIT_OK')); + this._config.webhooks.forEach(webhook => { + webhook.password = ''; + }); this.configOptions.resetModel?.(this._config); setTimeout(() => this.configOptions.resetModel?.(this._config)); }, diff --git a/admin/webapp/websrc/app/routes/settings/configuration/remote-repository-form/remote-repository-form-config/index.ts b/admin/webapp/websrc/app/routes/settings/configuration/remote-repository-form/remote-repository-form-config/index.ts index 80065fb6a..9c025b0f8 100644 --- a/admin/webapp/websrc/app/routes/settings/configuration/remote-repository-form/remote-repository-form-config/index.ts +++ b/admin/webapp/websrc/app/routes/settings/configuration/remote-repository-form/remote-repository-form-config/index.ts @@ -8,7 +8,7 @@ export const RemoteRepoFormConfig: FormlyFieldConfig[] = [ fieldGroupClassName: 'row', fieldGroup: [ { - className: 'col-12 col-md-6 mt-2', + className: 'col-12 col-md-6', ...ProviderField, }, {