瀏覽代碼

feat: modify certification content #29, #52

0xJacky 2 年之前
父節點
當前提交
6ee9eefa8b

+ 3 - 6
frontend/src/components/CodeEditor/CodeEditor.vue

@@ -4,16 +4,13 @@ import 'ace-builds/src-noconflict/mode-nginx'
 import 'ace-builds/src-noconflict/theme-monokai'
 import {computed} from 'vue'
 
-const props = defineProps<{
-    content: string
-    defaultHeight?: string
-}>()
+const props = defineProps(['content', 'defaultHeight'])
 
 const emit = defineEmits(['update:content'])
 
 const value = computed({
     get() {
-        return props.content
+        return props.content ?? ''
     },
     set(value) {
         emit('update:content', value)
@@ -27,7 +24,7 @@ const value = computed({
         lang="nginx"
         theme="monokai"
         :style="{
-            minHeight: props.defaultHeight || '100vh'
+            minHeight: defaultHeight || '100vh'
         }"/>
 </template>
 

+ 30 - 16
frontend/src/language/en/app.po

@@ -17,7 +17,7 @@ msgstr "About"
 msgid "Access Logs"
 msgstr ""
 
-#: src/views/cert/Cert.vue:75 src/views/config/config.ts:36
+#: src/views/cert/Cert.vue:78 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:47 src/views/user/User.vue:43
 msgid "Action"
 msgstr "Action"
@@ -68,10 +68,14 @@ msgstr "Are you sure you want to remove this directive?"
 msgid "Auto"
 msgstr ""
 
-#: src/views/cert/Cert.vue:38
+#: src/views/cert/Cert.vue:41
 msgid "Auto Cert"
 msgstr ""
 
+#: src/views/cert/Cert.vue:8
+msgid "Auto cert is enabled, please do not modify this certification."
+msgstr ""
+
 #: src/views/nginx_log/NginxLog.vue:4
 msgid "Auto Refresh"
 msgstr ""
@@ -123,15 +127,15 @@ msgstr "Build with"
 msgid "Cancel"
 msgstr "Cancel"
 
-#: src/views/domain/cert/CertInfo.vue:24
+#: src/views/domain/cert/CertInfo.vue:19
 msgid "Certificate has expired"
 msgstr "Certificate has expired"
 
-#: src/views/domain/cert/CertInfo.vue:28
+#: src/views/domain/cert/CertInfo.vue:23
 msgid "Certificate is valid"
 msgstr "Certificate is valid"
 
-#: src/views/domain/cert/CertInfo.vue:14
+#: src/views/cert/Cert.vue:12 src/views/domain/cert/Cert.vue:31
 msgid "Certificate Status"
 msgstr "Certificate Status"
 
@@ -232,7 +236,7 @@ msgstr "Directives"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "Disable auto-renewal failed for %{name}"
 
-#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:10
+#: src/views/cert/Cert.vue:51 src/views/domain/DomainEdit.vue:10
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainList.vue:16
 #: src/views/domain/DomainList.vue:34 src/views/domain/DomainList.vue:7
 #: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:9
@@ -247,7 +251,7 @@ msgstr "Disabled successfully"
 msgid "Disk IO"
 msgstr "Disk IO"
 
-#: src/views/cert/Cert.vue:29
+#: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr ""
 
@@ -283,7 +287,7 @@ msgstr "Enable failed"
 msgid "Enable TLS"
 msgstr "Enable TLS"
 
-#: src/views/cert/Cert.vue:45 src/views/domain/DomainEdit.vue:33
+#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:33
 #: src/views/domain/DomainEdit.vue:6 src/views/domain/DomainEdit.vue:7
 #: src/views/domain/DomainList.vue:10 src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:12 src/views/domain/DomainList.vue:19
@@ -304,7 +308,7 @@ msgstr "Encrypt website with Let's Encrypt"
 msgid "Error Logs"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:17
+#: src/views/domain/cert/CertInfo.vue:12
 msgid "Expiration Date: %{date}"
 msgstr "Expiration Date: %{date}"
 
@@ -377,7 +381,7 @@ msgstr "Install"
 msgid "Install successfully"
 msgstr "Enabled successfully"
 
-#: src/views/domain/cert/CertInfo.vue:15
+#: src/views/domain/cert/CertInfo.vue:10
 msgid "Intermediate Certification Authorities: %{issuer}"
 msgstr "Intermediate Certification Authorities: %{issuer}"
 
@@ -467,7 +471,7 @@ msgstr "Modify Config"
 msgid "Modify Config"
 msgstr "Modify Config"
 
-#: src/views/cert/Cert.vue:13 src/views/config/config.ts:9
+#: src/views/cert/Cert.vue:16 src/views/config/config.ts:9
 #: src/views/domain/DomainEdit.vue:36 src/views/domain/DomainList.vue:15
 msgid "Name"
 msgstr "Name"
@@ -515,7 +519,7 @@ msgstr "No"
 msgid "Not Found"
 msgstr "Not Found"
 
-#: src/views/domain/cert/CertInfo.vue:19
+#: src/views/domain/cert/CertInfo.vue:14
 msgid "Not Valid Before: %{date}"
 msgstr "Not Valid Before: %{date}"
 
@@ -705,16 +709,26 @@ msgstr "Sites List"
 msgid "Sites List"
 msgstr "Sites List"
 
-#: src/views/cert/Cert.vue:62
+#: src/views/cert/Cert.vue:65
 #, fuzzy
 msgid "SSL Certificate Key Path"
 msgstr "Certificate Status"
 
-#: src/views/cert/Cert.vue:55
+#: src/views/cert/Cert.vue:58
 #, fuzzy
 msgid "SSL Certificate Path"
 msgstr "Certificate Status"
 
+#: src/views/cert/Cert.vue:19
+#, fuzzy
+msgid "SSL Certification Content"
+msgstr "Certificate Status"
+
+#: src/views/cert/Cert.vue:22
+#, fuzzy
+msgid "SSL Certification Key Content"
+msgstr "Certificate Status"
+
 #: src/views/domain/DomainList.vue:24
 msgid "Status"
 msgstr "Status"
@@ -723,7 +737,7 @@ msgstr "Status"
 msgid "Storage"
 msgstr "Storage"
 
-#: src/views/domain/cert/CertInfo.vue:16
+#: src/views/domain/cert/CertInfo.vue:11
 msgid "Subject Name: %{name}"
 msgstr "Subject Name: %{name}"
 
@@ -768,7 +782,7 @@ msgstr ""
 msgid "Type"
 msgstr ""
 
-#: src/views/cert/Cert.vue:69 src/views/config/config.ts:29
+#: src/views/cert/Cert.vue:72 src/views/config/config.ts:29
 #: src/views/domain/DomainList.vue:41 src/views/user/User.vue:37
 msgid "Updated at"
 msgstr "Updated at"

+ 29 - 16
frontend/src/language/messages.pot

@@ -11,7 +11,7 @@ msgstr ""
 msgid "Access Logs"
 msgstr ""
 
-#: src/views/cert/Cert.vue:75
+#: src/views/cert/Cert.vue:78
 #: src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:47
 #: src/views/user/User.vue:43
@@ -64,10 +64,14 @@ msgstr ""
 msgid "Auto"
 msgstr ""
 
-#: src/views/cert/Cert.vue:38
+#: src/views/cert/Cert.vue:41
 msgid "Auto Cert"
 msgstr ""
 
+#: src/views/cert/Cert.vue:8
+msgid "Auto cert is enabled, please do not modify this certification."
+msgstr ""
+
 #: src/views/nginx_log/NginxLog.vue:4
 msgid "Auto Refresh"
 msgstr ""
@@ -121,15 +125,16 @@ msgstr ""
 msgid "Cancel"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:24
+#: src/views/domain/cert/CertInfo.vue:19
 msgid "Certificate has expired"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:28
+#: src/views/domain/cert/CertInfo.vue:23
 msgid "Certificate is valid"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:14
+#: src/views/cert/Cert.vue:12
+#: src/views/domain/cert/Cert.vue:31
 msgid "Certificate Status"
 msgstr ""
 
@@ -231,7 +236,7 @@ msgstr ""
 msgid "Disable auto-renewal failed for %{name}"
 msgstr ""
 
-#: src/views/cert/Cert.vue:48
+#: src/views/cert/Cert.vue:51
 #: src/views/domain/DomainEdit.vue:10
 #: src/views/domain/DomainEdit.vue:9
 #: src/views/domain/DomainList.vue:16
@@ -251,7 +256,7 @@ msgstr ""
 msgid "Disk IO"
 msgstr ""
 
-#: src/views/cert/Cert.vue:29
+#: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr ""
 
@@ -289,7 +294,7 @@ msgstr ""
 msgid "Enable TLS"
 msgstr ""
 
-#: src/views/cert/Cert.vue:45
+#: src/views/cert/Cert.vue:48
 #: src/views/domain/DomainEdit.vue:33
 #: src/views/domain/DomainEdit.vue:6
 #: src/views/domain/DomainEdit.vue:7
@@ -316,7 +321,7 @@ msgstr ""
 msgid "Error Logs"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:17
+#: src/views/domain/cert/CertInfo.vue:12
 msgid "Expiration Date: %{date}"
 msgstr ""
 
@@ -393,7 +398,7 @@ msgstr ""
 msgid "Install successfully"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:15
+#: src/views/domain/cert/CertInfo.vue:10
 msgid "Intermediate Certification Authorities: %{issuer}"
 msgstr ""
 
@@ -481,7 +486,7 @@ msgstr ""
 msgid "Modify Config"
 msgstr ""
 
-#: src/views/cert/Cert.vue:13
+#: src/views/cert/Cert.vue:16
 #: src/views/config/config.ts:9
 #: src/views/domain/DomainEdit.vue:36
 #: src/views/domain/DomainList.vue:15
@@ -533,7 +538,7 @@ msgstr ""
 msgid "Not Found"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:19
+#: src/views/domain/cert/CertInfo.vue:14
 msgid "Not Valid Before: %{date}"
 msgstr ""
 
@@ -729,14 +734,22 @@ msgstr ""
 msgid "Sites List"
 msgstr ""
 
-#: src/views/cert/Cert.vue:62
+#: src/views/cert/Cert.vue:65
 msgid "SSL Certificate Key Path"
 msgstr ""
 
-#: src/views/cert/Cert.vue:55
+#: src/views/cert/Cert.vue:58
 msgid "SSL Certificate Path"
 msgstr ""
 
+#: src/views/cert/Cert.vue:19
+msgid "SSL Certification Content"
+msgstr ""
+
+#: src/views/cert/Cert.vue:22
+msgid "SSL Certification Key Content"
+msgstr ""
+
 #: src/views/domain/DomainList.vue:24
 msgid "Status"
 msgstr ""
@@ -745,7 +758,7 @@ msgstr ""
 msgid "Storage"
 msgstr ""
 
-#: src/views/domain/cert/CertInfo.vue:16
+#: src/views/domain/cert/CertInfo.vue:11
 msgid "Subject Name: %{name}"
 msgstr ""
 
@@ -786,7 +799,7 @@ msgstr ""
 msgid "Type"
 msgstr ""
 
-#: src/views/cert/Cert.vue:69
+#: src/views/cert/Cert.vue:72
 #: src/views/config/config.ts:29
 #: src/views/domain/DomainList.vue:41
 #: src/views/user/User.vue:37

文件差異過大導致無法顯示
+ 0 - 0
frontend/src/language/translations.json


二進制
frontend/src/language/zh_CN/app.mo


+ 28 - 16
frontend/src/language/zh_CN/app.po

@@ -20,7 +20,7 @@ msgstr "关于"
 msgid "Access Logs"
 msgstr "访问日志"
 
-#: src/views/cert/Cert.vue:75 src/views/config/config.ts:36
+#: src/views/cert/Cert.vue:78 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:47 src/views/user/User.vue:43
 msgid "Action"
 msgstr "操作"
@@ -69,10 +69,14 @@ msgstr "您确定要删除这个 Location?"
 msgid "Auto"
 msgstr "自动"
 
-#: src/views/cert/Cert.vue:38
+#: src/views/cert/Cert.vue:41
 msgid "Auto Cert"
 msgstr "自动更新"
 
+#: src/views/cert/Cert.vue:8
+msgid "Auto cert is enabled, please do not modify this certification."
+msgstr "自动更新已启用,请勿修改此证书配置。"
+
 #: src/views/nginx_log/NginxLog.vue:4
 msgid "Auto Refresh"
 msgstr "自动刷新"
@@ -122,15 +126,15 @@ msgstr "构建基于"
 msgid "Cancel"
 msgstr "取消"
 
-#: src/views/domain/cert/CertInfo.vue:24
+#: src/views/domain/cert/CertInfo.vue:19
 msgid "Certificate has expired"
 msgstr "此证书已过期"
 
-#: src/views/domain/cert/CertInfo.vue:28
+#: src/views/domain/cert/CertInfo.vue:23
 msgid "Certificate is valid"
 msgstr "此证书有效"
 
-#: src/views/domain/cert/CertInfo.vue:14
+#: src/views/cert/Cert.vue:12 src/views/domain/cert/Cert.vue:31
 msgid "Certificate Status"
 msgstr "证书状态"
 
@@ -230,7 +234,7 @@ msgstr "指令"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "关闭 %{name} 自动续签失败"
 
-#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:10
+#: src/views/cert/Cert.vue:51 src/views/domain/DomainEdit.vue:10
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainList.vue:16
 #: src/views/domain/DomainList.vue:34 src/views/domain/DomainList.vue:7
 #: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:9
@@ -245,7 +249,7 @@ msgstr "禁用成功"
 msgid "Disk IO"
 msgstr "磁盘 IO"
 
-#: src/views/cert/Cert.vue:29
+#: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr "域名"
 
@@ -281,7 +285,7 @@ msgstr "启用失败"
 msgid "Enable TLS"
 msgstr "启用 TLS"
 
-#: src/views/cert/Cert.vue:45 src/views/domain/DomainEdit.vue:33
+#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:33
 #: src/views/domain/DomainEdit.vue:6 src/views/domain/DomainEdit.vue:7
 #: src/views/domain/DomainList.vue:10 src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:12 src/views/domain/DomainList.vue:19
@@ -302,7 +306,7 @@ msgstr "用 Let's Encrypt 对网站进行加密"
 msgid "Error Logs"
 msgstr "错误日志"
 
-#: src/views/domain/cert/CertInfo.vue:17
+#: src/views/domain/cert/CertInfo.vue:12
 msgid "Expiration Date: %{date}"
 msgstr "过期时间: %{date}"
 
@@ -374,7 +378,7 @@ msgstr "安装"
 msgid "Install successfully"
 msgstr "安装成功"
 
-#: src/views/domain/cert/CertInfo.vue:15
+#: src/views/domain/cert/CertInfo.vue:10
 msgid "Intermediate Certification Authorities: %{issuer}"
 msgstr "中级证书颁发机构: %{issuer}"
 
@@ -462,7 +466,7 @@ msgstr "修改"
 msgid "Modify Config"
 msgstr "修改配置文件"
 
-#: src/views/cert/Cert.vue:13 src/views/config/config.ts:9
+#: src/views/cert/Cert.vue:16 src/views/config/config.ts:9
 #: src/views/domain/DomainEdit.vue:36 src/views/domain/DomainList.vue:15
 msgid "Name"
 msgstr "名称"
@@ -510,7 +514,7 @@ msgstr "取消"
 msgid "Not Found"
 msgstr "找不到页面"
 
-#: src/views/domain/cert/CertInfo.vue:19
+#: src/views/domain/cert/CertInfo.vue:14
 msgid "Not Valid Before: %{date}"
 msgstr "此前无效: %{date}"
 
@@ -693,14 +697,22 @@ msgstr "站点列表"
 msgid "Sites List"
 msgstr "站点列表"
 
-#: src/views/cert/Cert.vue:62
+#: src/views/cert/Cert.vue:65
 msgid "SSL Certificate Key Path"
 msgstr "SSL证书密钥路径"
 
-#: src/views/cert/Cert.vue:55
+#: src/views/cert/Cert.vue:58
 msgid "SSL Certificate Path"
 msgstr "SSL证书路径"
 
+#: src/views/cert/Cert.vue:19
+msgid "SSL Certification Content"
+msgstr "SSL证书内容"
+
+#: src/views/cert/Cert.vue:22
+msgid "SSL Certification Key Content"
+msgstr "SSL证书密钥内容"
+
 #: src/views/domain/DomainList.vue:24
 msgid "Status"
 msgstr "状态"
@@ -709,7 +721,7 @@ msgstr "状态"
 msgid "Storage"
 msgstr "存储"
 
-#: src/views/domain/cert/CertInfo.vue:16
+#: src/views/domain/cert/CertInfo.vue:11
 msgid "Subject Name: %{name}"
 msgstr "主体名称: %{name}"
 
@@ -752,7 +764,7 @@ msgstr "主题"
 msgid "Type"
 msgstr "类型"
 
-#: src/views/cert/Cert.vue:69 src/views/config/config.ts:29
+#: src/views/cert/Cert.vue:72 src/views/config/config.ts:29
 #: src/views/domain/DomainList.vue:41 src/views/user/User.vue:37
 msgid "Updated at"
 msgstr "修改时间"

+ 30 - 16
frontend/src/language/zh_TW/app.po

@@ -21,7 +21,7 @@ msgstr "關於"
 msgid "Access Logs"
 msgstr "訪問日誌"
 
-#: src/views/cert/Cert.vue:75 src/views/config/config.ts:36
+#: src/views/cert/Cert.vue:78 src/views/config/config.ts:36
 #: src/views/domain/DomainList.vue:47 src/views/user/User.vue:43
 msgid "Action"
 msgstr "操作"
@@ -70,11 +70,15 @@ msgstr "您確定要刪除此 Location 嗎?"
 msgid "Auto"
 msgstr "自動"
 
-#: src/views/cert/Cert.vue:38
+#: src/views/cert/Cert.vue:41
 #, fuzzy
 msgid "Auto Cert"
 msgstr "自動刷新"
 
+#: src/views/cert/Cert.vue:8
+msgid "Auto cert is enabled, please do not modify this certification."
+msgstr ""
+
 #: src/views/nginx_log/NginxLog.vue:4
 msgid "Auto Refresh"
 msgstr "自動刷新"
@@ -124,15 +128,15 @@ msgstr "構建基於"
 msgid "Cancel"
 msgstr "取消"
 
-#: src/views/domain/cert/CertInfo.vue:24
+#: src/views/domain/cert/CertInfo.vue:19
 msgid "Certificate has expired"
 msgstr "此憑證已過期"
 
-#: src/views/domain/cert/CertInfo.vue:28
+#: src/views/domain/cert/CertInfo.vue:23
 msgid "Certificate is valid"
 msgstr "此憑證有效"
 
-#: src/views/domain/cert/CertInfo.vue:14
+#: src/views/cert/Cert.vue:12 src/views/domain/cert/Cert.vue:31
 msgid "Certificate Status"
 msgstr "憑證狀態"
 
@@ -233,7 +237,7 @@ msgstr "指令"
 msgid "Disable auto-renewal failed for %{name}"
 msgstr "關閉 %{name} 自動續簽失敗"
 
-#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:10
+#: src/views/cert/Cert.vue:51 src/views/domain/DomainEdit.vue:10
 #: src/views/domain/DomainEdit.vue:9 src/views/domain/DomainList.vue:16
 #: src/views/domain/DomainList.vue:34 src/views/domain/DomainList.vue:7
 #: src/views/domain/DomainList.vue:8 src/views/domain/DomainList.vue:9
@@ -248,7 +252,7 @@ msgstr "禁用成功"
 msgid "Disk IO"
 msgstr "磁碟 IO"
 
-#: src/views/cert/Cert.vue:29
+#: src/views/cert/Cert.vue:32
 msgid "Domain"
 msgstr ""
 
@@ -284,7 +288,7 @@ msgstr "啟用失敗"
 msgid "Enable TLS"
 msgstr "啟用 TLS"
 
-#: src/views/cert/Cert.vue:45 src/views/domain/DomainEdit.vue:33
+#: src/views/cert/Cert.vue:48 src/views/domain/DomainEdit.vue:33
 #: src/views/domain/DomainEdit.vue:6 src/views/domain/DomainEdit.vue:7
 #: src/views/domain/DomainList.vue:10 src/views/domain/DomainList.vue:11
 #: src/views/domain/DomainList.vue:12 src/views/domain/DomainList.vue:19
@@ -305,7 +309,7 @@ msgstr "用 Let's Encrypt 對網站進行加密"
 msgid "Error Logs"
 msgstr "錯誤日志"
 
-#: src/views/domain/cert/CertInfo.vue:17
+#: src/views/domain/cert/CertInfo.vue:12
 msgid "Expiration Date: %{date}"
 msgstr "過期時間: %{date}"
 
@@ -379,7 +383,7 @@ msgstr "安裝"
 msgid "Install successfully"
 msgstr "安裝成功"
 
-#: src/views/domain/cert/CertInfo.vue:15
+#: src/views/domain/cert/CertInfo.vue:10
 msgid "Intermediate Certification Authorities: %{issuer}"
 msgstr "中級憑證頒發機構: %{issuer}"
 
@@ -467,7 +471,7 @@ msgstr "修改"
 msgid "Modify Config"
 msgstr "修改配置"
 
-#: src/views/cert/Cert.vue:13 src/views/config/config.ts:9
+#: src/views/cert/Cert.vue:16 src/views/config/config.ts:9
 #: src/views/domain/DomainEdit.vue:36 src/views/domain/DomainList.vue:15
 msgid "Name"
 msgstr "名稱"
@@ -517,7 +521,7 @@ msgstr "取消"
 msgid "Not Found"
 msgstr "找不到頁面"
 
-#: src/views/domain/cert/CertInfo.vue:19
+#: src/views/domain/cert/CertInfo.vue:14
 msgid "Not Valid Before: %{date}"
 msgstr "此前無效: %{date}"
 
@@ -701,16 +705,26 @@ msgstr "網站日誌"
 msgid "Sites List"
 msgstr "站點列表"
 
-#: src/views/cert/Cert.vue:62
+#: src/views/cert/Cert.vue:65
 #, fuzzy
 msgid "SSL Certificate Key Path"
 msgstr "憑證狀態"
 
-#: src/views/cert/Cert.vue:55
+#: src/views/cert/Cert.vue:58
 #, fuzzy
 msgid "SSL Certificate Path"
 msgstr "憑證狀態"
 
+#: src/views/cert/Cert.vue:19
+#, fuzzy
+msgid "SSL Certification Content"
+msgstr "憑證狀態"
+
+#: src/views/cert/Cert.vue:22
+#, fuzzy
+msgid "SSL Certification Key Content"
+msgstr "憑證狀態"
+
 #: src/views/domain/DomainList.vue:24
 msgid "Status"
 msgstr "狀態"
@@ -719,7 +733,7 @@ msgstr "狀態"
 msgid "Storage"
 msgstr "儲存"
 
-#: src/views/domain/cert/CertInfo.vue:16
+#: src/views/domain/cert/CertInfo.vue:11
 msgid "Subject Name: %{name}"
 msgstr "主體名稱: %{name}"
 
@@ -763,7 +777,7 @@ msgstr "外觀樣式"
 msgid "Type"
 msgstr ""
 
-#: src/views/cert/Cert.vue:69 src/views/config/config.ts:29
+#: src/views/cert/Cert.vue:72 src/views/config/config.ts:29
 #: src/views/domain/DomainList.vue:41 src/views/user/User.vue:37
 msgid "Updated at"
 msgstr "修改時間"

+ 28 - 2
frontend/src/views/cert/Cert.vue

@@ -6,6 +6,9 @@ import {h} from 'vue'
 import {Badge} from 'ant-design-vue'
 import cert from '@/api/cert'
 import StdCurd from '@/components/StdDataDisplay/StdCurd.vue'
+import Template from '@/views/template/Template.vue'
+import CodeEditor from '@/components/CodeEditor/CodeEditor.vue'
+import CertInfo from '@/views/domain/cert/CertInfo.vue'
 
 const {$gettext} = useGettext()
 
@@ -44,7 +47,7 @@ const columns = [{
             template.push(<Badge status="success"/>)
             template.push($gettext('Enabled'))
         } else {
-            template.push(<Badge status="error"/>)
+            template.push(<Badge status="warning"/>)
             template.push($gettext('Disabled'))
         }
         return h('div', template)
@@ -80,7 +83,30 @@ const columns = [{
 <template>
     <std-curd :title="$gettext('Certification')" :api="cert" :columns="columns"
               row-key="name"
-    />
+    >
+        <template #beforeEdit="{data}">
+            <div v-if="data.auto_cert===1" style="margin-bottom: 15px">
+                <a-alert
+                    :message="$gettext('Auto cert is enabled, please do not modify this certification.')" type="info"
+                    show-icon/>
+            </div>
+            <a-form layout="vertical" v-if="data.certificate_info">
+                <a-form-item :label="$gettext('Certificate Status')">
+                    <cert-info :cert="data.certificate_info"/>
+                </a-form-item>
+            </a-form>
+        </template>
+        <template #edit="{data}">
+            <a-form layout="vertical">
+                <a-form-item :label="$gettext('SSL Certification Content')">
+                    <code-editor v-model:content="data.ssl_certification" default-height="200px"/>
+                </a-form-item>
+                <a-form-item :label="$gettext('SSL Certification Key Content')">
+                    <code-editor v-model:content="data.ssl_certification_key" default-height="200px"/>
+                </a-form-item>
+            </a-form>
+        </template>
+    </std-curd>
 </template>
 
 <style lang="less" scoped>

+ 1 - 0
frontend/src/views/domain/cert/Cert.vue

@@ -28,6 +28,7 @@ const enabled = computed({
 
 <template>
     <div>
+        <h2 v-translate>Certificate Status</h2>
         <cert-info ref="info" :cert="props.cert_info"/>
 
         <issue-cert

+ 0 - 5
frontend/src/views/domain/cert/CertInfo.vue

@@ -1,17 +1,12 @@
 <script setup lang="ts">
 import {CloseCircleOutlined, CheckCircleOutlined} from '@ant-design/icons-vue'
 import dayjs from 'dayjs'
-import {reactive, ref} from 'vue'
-import domain from '@/api/domain'
 
 const props = defineProps(['cert'])
-
-const cert = props.cert
 </script>
 
 <template>
     <div class="cert-info" v-if="cert">
-        <h2 v-translate>Certificate Status</h2>
         <p v-translate="{issuer: cert.issuer_name}">Intermediate Certification Authorities: %{issuer}</p>
         <p v-translate="{name: cert.subject_name}">Subject Name: %{name}</p>
         <p v-translate="{date: dayjs(cert.not_after).format('YYYY-MM-DD HH:mm:ss').toString()}">

+ 288 - 182
server/api/cert.go

@@ -1,246 +1,352 @@
 package api
 
 import (
-	"github.com/0xJacky/Nginx-UI/server/model"
-	"github.com/0xJacky/Nginx-UI/server/pkg/cert"
-	"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
-	"github.com/gin-gonic/gin"
-	"github.com/gorilla/websocket"
-	"github.com/spf13/cast"
-	"log"
-	"net/http"
-	"strings"
+    "github.com/0xJacky/Nginx-UI/server/model"
+    "github.com/0xJacky/Nginx-UI/server/pkg/cert"
+    "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
+    "github.com/gin-gonic/gin"
+    "github.com/gorilla/websocket"
+    "github.com/spf13/cast"
+    "log"
+    "net/http"
+    "os"
+    "path/filepath"
+    "strings"
 )
 
 const (
-	Success = "success"
-	Info    = "info"
-	Error   = "error"
+    Success = "success"
+    Info    = "info"
+    Error   = "error"
 )
 
 type IssueCertResponse struct {
-	Status            string `json:"status"`
-	Message           string `json:"message"`
-	SSLCertificate    string `json:"ssl_certificate,omitempty"`
-	SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
+    Status            string `json:"status"`
+    Message           string `json:"message"`
+    SSLCertificate    string `json:"ssl_certificate,omitempty"`
+    SSLCertificateKey string `json:"ssl_certificate_key,omitempty"`
 }
 
 func handleIssueCertLogChan(conn *websocket.Conn, logChan chan string) {
-	defer func() {
-		if err := recover(); err != nil {
-			log.Println("api.handleIssueCertLogChan recover", err)
-		}
-	}()
+    defer func() {
+        if err := recover(); err != nil {
+            log.Println("api.handleIssueCertLogChan recover", err)
+        }
+    }()
 
-	for logString := range logChan {
+    for logString := range logChan {
 
-		err := conn.WriteJSON(IssueCertResponse{
-			Status:  Info,
-			Message: logString,
-		})
+        err := conn.WriteJSON(IssueCertResponse{
+            Status:  Info,
+            Message: logString,
+        })
 
-		if err != nil {
-			log.Println("Error handleIssueCertLogChan", err)
-			return
-		}
+        if err != nil {
+            log.Println("Error handleIssueCertLogChan", err)
+            return
+        }
 
-	}
+    }
 }
 
 func IssueCert(c *gin.Context) {
-	var upGrader = websocket.Upgrader{
-		CheckOrigin: func(r *http.Request) bool {
-			return true
-		},
-	}
+    var upGrader = websocket.Upgrader{
+        CheckOrigin: func(r *http.Request) bool {
+            return true
+        },
+    }
 
-	// upgrade http to websocket
-	ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
-	if err != nil {
-		log.Println(err)
-		return
-	}
+    // upgrade http to websocket
+    ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
+    if err != nil {
+        log.Println(err)
+        return
+    }
 
-	defer func(ws *websocket.Conn) {
-		err := ws.Close()
-		if err != nil {
-			log.Println("defer websocket close err", err)
-		}
-	}(ws)
+    defer func(ws *websocket.Conn) {
+        err := ws.Close()
+        if err != nil {
+            log.Println("defer websocket close err", err)
+        }
+    }(ws)
 
-	// read
-	var buffer struct {
-		ServerName []string `json:"server_name"`
-	}
+    // read
+    var buffer struct {
+        ServerName []string `json:"server_name"`
+    }
 
-	err = ws.ReadJSON(&buffer)
+    err = ws.ReadJSON(&buffer)
 
-	if err != nil {
-		log.Println(err)
-		return
-	}
+    if err != nil {
+        log.Println(err)
+        return
+    }
 
-	logChan := make(chan string, 1)
-	errChan := make(chan error, 1)
+    logChan := make(chan string, 1)
+    errChan := make(chan error, 1)
 
-	go cert.IssueCert(buffer.ServerName, logChan, errChan)
+    go cert.IssueCert(buffer.ServerName, logChan, errChan)
 
-	domain := strings.Join(buffer.ServerName, "_")
+    domain := strings.Join(buffer.ServerName, "_")
 
-	go handleIssueCertLogChan(ws, logChan)
+    go handleIssueCertLogChan(ws, logChan)
 
-	// block, unless errChan closed
-	for err = range errChan {
-		log.Println("Error cert.IssueCert", err)
+    // block, unless errChan closed
+    for err = range errChan {
+        log.Println("Error cert.IssueCert", err)
 
-		err = ws.WriteJSON(IssueCertResponse{
-			Status:  Error,
-			Message: err.Error(),
-		})
+        err = ws.WriteJSON(IssueCertResponse{
+            Status:  Error,
+            Message: err.Error(),
+        })
 
-		if err != nil {
-			log.Println("Error WriteJSON", err)
-			return
-		}
+        if err != nil {
+            log.Println("Error WriteJSON", err)
+            return
+        }
 
-		return
-	}
+        return
+    }
 
-	close(logChan)
+    close(logChan)
 
-	sslCertificatePath := nginx.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
-	sslCertificateKeyPath := nginx.GetNginxConfPath("ssl/" + domain + "/private.key")
+    sslCertificatePath := nginx.GetNginxConfPath("ssl/" + domain + "/fullchain.cer")
+    sslCertificateKeyPath := nginx.GetNginxConfPath("ssl/" + domain + "/private.key")
 
-	certModel, err := model.FirstOrCreateCert(domain)
+    certModel, err := model.FirstOrCreateCert(domain)
 
-	if err != nil {
-		log.Println(err)
-	}
+    if err != nil {
+        log.Println(err)
+    }
 
-	err = certModel.Updates(&model.Cert{
-		SSLCertificatePath:    sslCertificatePath,
-		SSLCertificateKeyPath: sslCertificateKeyPath,
-	})
+    err = certModel.Updates(&model.Cert{
+        SSLCertificatePath:    sslCertificatePath,
+        SSLCertificateKeyPath: sslCertificateKeyPath,
+    })
 
-	if err != nil {
-		log.Println(err)
-	}
+    if err != nil {
+        log.Println(err)
+    }
 
-	err = ws.WriteJSON(IssueCertResponse{
-		Status:            Success,
-		Message:           "Issued certificate successfully",
-		SSLCertificate:    sslCertificatePath,
-		SSLCertificateKey: sslCertificateKeyPath,
-	})
+    err = ws.WriteJSON(IssueCertResponse{
+        Status:            Success,
+        Message:           "Issued certificate successfully",
+        SSLCertificate:    sslCertificatePath,
+        SSLCertificateKey: sslCertificateKeyPath,
+    })
 
-	if err != nil {
-		log.Println(err)
-		return
-	}
+    if err != nil {
+        log.Println(err)
+        return
+    }
 
 }
 
 func GetCertList(c *gin.Context) {
-	certList := model.GetCertList(c.Query("name"), c.Query("domain"))
+    certList := model.GetCertList(c.Query("name"), c.Query("domain"))
 
-	c.JSON(http.StatusOK, gin.H{
-		"data": certList,
-	})
+    c.JSON(http.StatusOK, gin.H{
+        "data": certList,
+    })
+}
+
+func getCert(c *gin.Context, certModel model.Cert) {
+    type resp struct {
+        model.Cert
+        SSLCertification    string           `json:"ssl_certification"`
+        SSLCertificationKey string           `json:"ssl_certification_key"`
+        CertificateInfo     *CertificateInfo `json:"certificate_info,omitempty"`
+    }
+
+    var sslCertificationBytes, sslCertificationKeyBytes []byte
+    var certificateInfo *CertificateInfo
+    if certModel.SSLCertificatePath != "" {
+        if _, err := os.Stat(certModel.SSLCertificatePath); err == nil {
+            sslCertificationBytes, _ = os.ReadFile(certModel.SSLCertificatePath)
+        }
+
+        pubKey, err := cert.GetCertInfo(certModel.SSLCertificatePath)
+
+        if err != nil {
+            ErrHandler(c, err)
+            return
+        }
+
+        certificateInfo = &CertificateInfo{
+            SubjectName: pubKey.Subject.CommonName,
+            IssuerName:  pubKey.Issuer.CommonName,
+            NotAfter:    pubKey.NotAfter,
+            NotBefore:   pubKey.NotBefore,
+        }
+    }
+
+    if certModel.SSLCertificateKeyPath != "" {
+        if _, err := os.Stat(certModel.SSLCertificateKeyPath); err == nil {
+            sslCertificationKeyBytes, _ = os.ReadFile(certModel.SSLCertificateKeyPath)
+        }
+    }
+
+    c.JSON(http.StatusOK, resp{
+        certModel,
+        string(sslCertificationBytes),
+        string(sslCertificationKeyBytes),
+        certificateInfo,
+    })
 }
 
 func GetCert(c *gin.Context) {
-	certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id")))
+    certModel, err := model.FirstCertByID(cast.ToInt(c.Param("id")))
 
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
 
-	c.JSON(http.StatusOK, certModel)
+    getCert(c, certModel)
 }
 
 func AddCert(c *gin.Context) {
-	var json struct {
-		Name                  string `json:"name" binding:"required"`
-		Domain                string `json:"domain" binding:"required"`
-		SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
-		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
-	}
-	if !BindAndValid(c, &json) {
-		return
-	}
-	certModel, err := model.FirstOrCreateCert(json.Domain)
-
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
-
-	err = certModel.Updates(&model.Cert{
-		Name:                  json.Name,
-		Domain:                json.Domain,
-		SSLCertificatePath:    json.SSLCertificatePath,
-		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
-	})
-
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
-
-	c.JSON(http.StatusOK, nil)
+    var json struct {
+        Name                  string `json:"name"`
+        Domain                string `json:"domain" binding:"required"`
+        SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
+        SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
+        SSLCertification      string `json:"ssl_certification"`
+        SSLCertificationKey   string `json:"ssl_certification_key"`
+    }
+    if !BindAndValid(c, &json) {
+        return
+    }
+    certModel, err := model.FirstOrCreateCert(json.Domain)
+
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = certModel.Updates(&model.Cert{
+        Name:                  json.Name,
+        Domain:                json.Domain,
+        SSLCertificatePath:    json.SSLCertificatePath,
+        SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+    })
+
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    if json.SSLCertification != "" {
+        err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644)
+        if err != nil {
+            ErrHandler(c, err)
+            return
+        }
+    }
+
+    if json.SSLCertificationKey != "" {
+        err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644)
+        if err != nil {
+            ErrHandler(c, err)
+            return
+        }
+    }
+
+    getCert(c, certModel)
 }
 
 func ModifyCert(c *gin.Context) {
-	id := cast.ToInt(c.Param("id"))
-	certModel, err := model.FirstCertByID(id)
-
-	var json struct {
-		Name                  string `json:"name" binding:"required"`
-		Domain                string `json:"domain" binding:"required"`
-		SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
-		SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
-	}
-
-	if !BindAndValid(c, &json) {
-		return
-	}
-
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
-
-	err = certModel.Updates(&model.Cert{
-		Name:                  json.Name,
-		Domain:                json.Domain,
-		SSLCertificatePath:    json.SSLCertificatePath,
-		SSLCertificateKeyPath: json.SSLCertificateKeyPath,
-	})
-
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
-
-	c.JSON(http.StatusOK, certModel)
+    id := cast.ToInt(c.Param("id"))
+    certModel, err := model.FirstCertByID(id)
+
+    var json struct {
+        Name                  string `json:"name"`
+        Domain                string `json:"domain" binding:"required"`
+        SSLCertificatePath    string `json:"ssl_certificate_path" binding:"required"`
+        SSLCertificateKeyPath string `json:"ssl_certificate_key_path" binding:"required"`
+        SSLCertification      string `json:"ssl_certification"`
+        SSLCertificationKey   string `json:"ssl_certification_key"`
+    }
+
+    if !BindAndValid(c, &json) {
+        return
+    }
+
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = certModel.Updates(&model.Cert{
+        Name:                  json.Name,
+        Domain:                json.Domain,
+        SSLCertificatePath:    json.SSLCertificatePath,
+        SSLCertificateKeyPath: json.SSLCertificateKeyPath,
+    })
+
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = os.MkdirAll(filepath.Dir(json.SSLCertificatePath), 0644)
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    err = os.MkdirAll(filepath.Dir(json.SSLCertificateKeyPath), 0644)
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
+
+    if json.SSLCertification != "" {
+        err = os.WriteFile(json.SSLCertificatePath, []byte(json.SSLCertification), 0644)
+        if err != nil {
+            ErrHandler(c, err)
+            return
+        }
+    }
+
+    if json.SSLCertificationKey != "" {
+        err = os.WriteFile(json.SSLCertificateKeyPath, []byte(json.SSLCertificationKey), 0644)
+        if err != nil {
+            ErrHandler(c, err)
+            return
+        }
+    }
+
+    GetCert(c)
 }
 
 func RemoveCert(c *gin.Context) {
-	id := cast.ToInt(c.Param("id"))
-	certModel, err := model.FirstCertByID(id)
+    id := cast.ToInt(c.Param("id"))
+    certModel, err := model.FirstCertByID(id)
 
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
 
-	err = certModel.Remove()
+    err = certModel.Remove()
 
-	if err != nil {
-		ErrHandler(c, err)
-		return
-	}
+    if err != nil {
+        ErrHandler(c, err)
+        return
+    }
 
-	c.JSON(http.StatusOK, nil)
+    c.JSON(http.StatusNoContent, nil)
 }

部分文件因文件數量過多而無法顯示