diff --git a/src/ui/api/systeminfo.go b/src/ui/api/systeminfo.go index 154c4bea7..8c8d4fadc 100644 --- a/src/ui/api/systeminfo.go +++ b/src/ui/api/systeminfo.go @@ -2,6 +2,7 @@ package api import ( "net/http" + "os" "path/filepath" "syscall" @@ -18,6 +19,7 @@ type SystemInfoAPI struct { } const harborStoragePath = "/harbor_storage" +const defaultRootCert = "/harbor_storage/ca-download-dir/ca.crt" //SystemInfo models for system info. type SystemInfo struct { @@ -66,3 +68,17 @@ func (sia *SystemInfoAPI) GetVolumeInfo() { sia.Data["json"] = systemInfo sia.ServeJSON() } + +//GetCert gets default self-signed certificate. +func (sia *SystemInfoAPI) GetCert() { + if sia.isAdmin { + if _, err := os.Stat(defaultRootCert); !os.IsNotExist(err) { + sia.Ctx.Output.Header("Content-Disposition", "attachment; filename=ca.crt") + http.ServeFile(sia.Ctx.ResponseWriter, sia.Ctx.Request, defaultRootCert) + } else { + log.Error("No certificate found.") + sia.CustomAbort(http.StatusNotFound, "No certificate found.") + } + } + sia.CustomAbort(http.StatusUnauthorized, "") +} diff --git a/src/ui/controllers/base.go b/src/ui/controllers/base.go index beaa10cf8..2a891ba03 100644 --- a/src/ui/controllers/base.go +++ b/src/ui/controllers/base.go @@ -31,9 +31,10 @@ type langType struct { } const ( - viewPath = "sections" - prefixNg = "" - defaultLang = "en-US" + viewPath = "sections" + prefixNg = "" + defaultLang = "en-US" + defaultRootCert = "/harbor_storage/ca-download-dir/ca.crt" ) var supportLanguages map[string]langType @@ -45,6 +46,8 @@ func (b *BaseController) Prepare() { var lang string var langHasChanged bool + var showDownloadCert bool + langRequest := b.GetString("lang") if langRequest != "" { lang = langRequest @@ -120,6 +123,20 @@ func (b *BaseController) Prepare() { b.SelfRegistration = config.SelfRegistration() b.Data["SelfRegistration"] = config.SelfRegistration() + + sessionUserID := b.GetSession("userId") + if sessionUserID != nil { + isAdmin, err := dao.IsAdminRole(sessionUserID.(int)) + if err != nil { + log.Errorf("Error occurred in IsAdminRole: %v", err) + } + if isAdmin { + if _, err := os.Stat(defaultRootCert); !os.IsNotExist(err) { + showDownloadCert = true + } + } + } + b.Data["ShowDownloadCert"] = showDownloadCert } // Forward to setup layout and template for content for a page. diff --git a/src/ui/router.go b/src/ui/router.go index 0f5245d92..537748b03 100644 --- a/src/ui/router.go +++ b/src/ui/router.go @@ -86,6 +86,7 @@ func initRouters() { beego.Router("/api/logs", &api.LogAPI{}) beego.Router("/api/systeminfo/volumes", &api.SystemInfoAPI{}, "get:GetVolumeInfo") + beego.Router("/api/systeminfo/getcert", &api.SystemInfoAPI{}, "get:GetCert") //external service that hosted on harbor process: beego.Router("/service/notifications", &service.NotificationHandler{}) beego.Router("/service/token", &token.Handler{}) diff --git a/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js b/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js index 534a49b98..136763fd6 100644 --- a/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js +++ b/src/ui/static/resources/js/components/optional-menu/optional-menu.directive.js @@ -35,7 +35,7 @@ vm.setLanguage = setLanguage; vm.logOut = logOut; vm.about = about; - + function setLanguage(language) { vm.languageName = i18n.getLanguageName(vm.language); var hash = $window.location.hash; @@ -62,10 +62,12 @@ function about() { $scope.$emit('modalTitle', $filter('tr')('about_harbor')); - vm.modalMessage = $filter('tr')('current_version', [vm.version || 'Unknown']); + vm.modalMessage = $filter('tr')('current_version', [vm.version || 'Unknown']); + if(vm.showDownloadCert === 'true') { + appendDownloadCertLink(); + } GetVolumeInfoService("data") .then(getVolumeInfoSuccess, getVolumeInfoFailed); - } function getVolumeInfoSuccess(response) { var storage = response.data; @@ -79,10 +81,15 @@ $scope.$emit('modalMessage', vm.modalMessage); $scope.$emit('raiseInfo', raiseInfo); } + function toGigaBytes(val) { return Math.round(val / (1024 * 1024 * 1024)); } + function appendDownloadCertLink() { + vm.modalMessage += '
' + $filter('tr')('default_root_cert', ['/api/systeminfo/getcert', $filter('tr')('download')]); + } + } function optionalMenu() { @@ -91,7 +98,8 @@ 'templateUrl': '/optional_menu?timestamp=' + new Date().getTime(), 'scope': { 'version': '@', - 'language': '@' + 'language': '@', + 'showDownloadCert': '@' }, 'controller': OptionalMenuController, 'controllerAs': 'vm', diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js index 5f6a1cc43..ea8e24260 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js @@ -233,6 +233,8 @@ var locale_messages = { 'about_harbor': 'About Harbor', 'current_version': '  $0', 'current_storage': '  $0 GB available of $1 GB.', + 'default_root_cert': '  $1', + 'download': 'Download', 'failed_to_get_project_member': 'Failed to get current project member.', 'failed_to_delete_repo': 'Failed to delete repository. ', 'failed_to_delete_repo_insuffient_permissions': 'Failed to delete repository, insuffient permissions.', @@ -285,4 +287,4 @@ var locale_messages = { 'confirm_to_toggle_disabled_policy_title': 'Disable Policy', 'confirm_to_toggle_disabled_policy': 'After disabling the policy, all unfinished replication jobs of this policy will be stopped and canceled. Please confirm to continue.', 'begin_date_is_later_than_end_date': 'Begin date should not be later than end date.' -}; +}; \ No newline at end of file diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js index 133dd0761..5b7b5175f 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js @@ -233,6 +233,8 @@ var locale_messages = { 'about_harbor': '关于 Harbor', 'current_version': '  $0', 'current_storage': '  可用: $0 GB,总共: $1 GB。', + 'default_root_cert': '  $1', + 'download': '下载', 'failed_to_get_project_member': '无法获取当前项目成员。', 'failed_to_delete_repo': '无法删除镜像仓库。', 'failed_to_delete_repo_insuffient_permissions': '无法删除镜像仓库,权限不足。', @@ -287,4 +289,4 @@ var locale_messages = { 'confirm_to_toggle_disabled_policy_title': '停用策略', 'confirm_to_toggle_disabled_policy': '停用策略后,所有未完成的复制任务将被终止和取消。请确认继续。', 'begin_date_is_later_than_end_date': '起始日期不能晚于结束日期。' -}; +}; \ No newline at end of file diff --git a/src/ui/views/sections/header-content.htm b/src/ui/views/sections/header-content.htm index ab6a4b373..f927847f9 100644 --- a/src/ui/views/sections/header-content.htm +++ b/src/ui/views/sections/header-content.htm @@ -25,7 +25,7 @@