mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
bug fix and translated login error msg
This commit is contained in:
parent
f11fd19288
commit
b2e837f4b1
35 changed files with 324 additions and 301 deletions
|
@ -11,3 +11,6 @@ export default createGettext({
|
|||
translations: translations,
|
||||
silent: true
|
||||
})
|
||||
|
||||
export class useGettext {
|
||||
}
|
||||
|
|
7
frontend/src/language/constants.ts
Normal file
7
frontend/src/language/constants.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import gettext from '@/gettext'
|
||||
|
||||
const {$gettext} = gettext
|
||||
|
||||
export const msg = [
|
||||
$gettext('The username or password is incorrect')
|
||||
]
|
|
@ -25,7 +25,7 @@ msgstr ""
|
|||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:31
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
msgid "Add Directive Below"
|
||||
msgstr "Add Directive Below"
|
||||
|
||||
|
@ -60,7 +60,7 @@ msgstr "Auto-renewal disabled for %{name}"
|
|||
msgid "Auto-renewal enabled for %{name}"
|
||||
msgstr "Auto-renewal enabled for %{name}"
|
||||
|
||||
#: src/views/domain/DomainEdit.vue:158
|
||||
#: src/views/domain/DomainEdit.vue:166
|
||||
msgid "Back"
|
||||
msgstr "Back"
|
||||
|
||||
|
@ -101,7 +101,7 @@ msgstr "Certificate Status"
|
|||
#: src/views/domain/ngx_conf/directive/DirectiveEditor.vue:29
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:21
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:7
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:145
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:154
|
||||
msgid "Comments"
|
||||
msgstr "Comments"
|
||||
|
||||
|
@ -304,7 +304,7 @@ msgstr "Login successful"
|
|||
msgid "Logout successful"
|
||||
msgstr "Logout successful"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:172
|
||||
#: src/views/domain/cert/IssueCert.vue:181
|
||||
msgid ""
|
||||
"Make sure you have configured a reverse proxy for .well-known directory to "
|
||||
"HTTPChallengePort (default: 9180) before getting the certificate."
|
||||
|
@ -384,7 +384,7 @@ msgstr "Not Found"
|
|||
msgid "Not Valid Before: %{date}"
|
||||
msgstr "Not Valid Before: %{date}"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:164
|
||||
#: src/views/domain/cert/IssueCert.vue:173
|
||||
msgid ""
|
||||
"Note: The server_name in the current configuration must be the domain name "
|
||||
"you need to get the certificate."
|
||||
|
@ -402,7 +402,7 @@ msgstr ""
|
|||
msgid "OS:"
|
||||
msgstr "OS:"
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:21
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:22
|
||||
msgid "Params"
|
||||
msgstr "Params"
|
||||
|
||||
|
@ -447,13 +447,13 @@ msgstr "Receive"
|
|||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:161
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:169
|
||||
msgid "Save"
|
||||
msgstr "Save"
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:35
|
||||
msgid "Save Directive"
|
||||
msgstr "Save Directive"
|
||||
|
||||
|
@ -482,7 +482,7 @@ msgstr "Send"
|
|||
#: src/views/config/ConfigEdit.vue:22 src/views/domain/DomainEdit.vue:44
|
||||
#: src/views/domain/DomainEdit.vue:56 src/views/domain/DomainEdit.vue:65
|
||||
#: src/views/domain/DomainEdit.vue:83 src/views/domain/DomainList.vue:78
|
||||
#: src/views/other/Install.vue:71 src/views/other/Login.vue:56
|
||||
#: src/views/other/Install.vue:71
|
||||
msgid "Server error"
|
||||
msgstr "Server error"
|
||||
|
||||
|
@ -494,11 +494,11 @@ msgstr "Server Info"
|
|||
msgid "server_name not found in directives"
|
||||
msgstr "server_name not found in directives"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:155 src/views/domain/DomainAdd.vue:112
|
||||
#: src/views/domain/cert/IssueCert.vue:164 src/views/domain/DomainAdd.vue:112
|
||||
msgid "server_name parameter is required"
|
||||
msgstr "server_name parameter is required"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:158
|
||||
#: src/views/domain/cert/IssueCert.vue:167
|
||||
#: src/views/domain/cert/IssueCert.vue:34
|
||||
msgid "server_name parameters more than one"
|
||||
msgstr "server_name parameters more than one"
|
||||
|
@ -536,7 +536,7 @@ msgstr "Enabled"
|
|||
msgid "Terminal"
|
||||
msgstr "Terminal"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:168
|
||||
#: src/views/domain/cert/IssueCert.vue:177
|
||||
msgid ""
|
||||
"The certificate for the domain will be checked every hour, and will be "
|
||||
"renewed if it has been more than 1 month since it was last issued."
|
||||
|
@ -548,6 +548,10 @@ msgstr ""
|
|||
msgid "The filename cannot contain the following characters: %{c}"
|
||||
msgstr "The filename cannot contain the following characters: %{c}"
|
||||
|
||||
#: src/language/constants.ts:6
|
||||
msgid "The username or password is incorrect"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/config/Config.vue:17 src/views/domain/DomainList.vue:36
|
||||
#: src/views/user/User.vue:36
|
||||
msgid "Updated at"
|
||||
|
|
|
@ -19,7 +19,7 @@ msgstr ""
|
|||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:31
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
msgid "Add Directive Below"
|
||||
msgstr ""
|
||||
|
||||
|
@ -54,7 +54,7 @@ msgstr ""
|
|||
msgid "Auto-renewal enabled for %{name}"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/DomainEdit.vue:158
|
||||
#: src/views/domain/DomainEdit.vue:166
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
|
||||
|
@ -94,7 +94,7 @@ msgstr ""
|
|||
#: src/views/domain/ngx_conf/directive/DirectiveEditor.vue:29
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:21
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:7
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:145
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:154
|
||||
msgid "Comments"
|
||||
msgstr ""
|
||||
|
||||
|
@ -308,7 +308,7 @@ msgstr ""
|
|||
msgid "Logout successful"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:172
|
||||
#: src/views/domain/cert/IssueCert.vue:181
|
||||
msgid "Make sure you have configured a reverse proxy for .well-known directory to HTTPChallengePort (default: 9180) before getting the certificate."
|
||||
msgstr ""
|
||||
|
||||
|
@ -387,7 +387,7 @@ msgstr ""
|
|||
msgid "Not Valid Before: %{date}"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:164
|
||||
#: src/views/domain/cert/IssueCert.vue:173
|
||||
msgid "Note: The server_name in the current configuration must be the domain name you need to get the certificate."
|
||||
msgstr ""
|
||||
|
||||
|
@ -401,7 +401,7 @@ msgstr ""
|
|||
msgid "OS:"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:21
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:22
|
||||
msgid "Params"
|
||||
msgstr ""
|
||||
|
||||
|
@ -451,13 +451,13 @@ msgid "Reset"
|
|||
msgstr ""
|
||||
|
||||
#: src/views/config/ConfigEdit.vue:52
|
||||
#: src/views/domain/DomainEdit.vue:161
|
||||
#: src/views/domain/DomainEdit.vue:169
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:35
|
||||
msgid "Save Directive"
|
||||
msgstr ""
|
||||
|
||||
|
@ -492,7 +492,6 @@ msgstr ""
|
|||
#: src/views/domain/DomainEdit.vue:83
|
||||
#: src/views/domain/DomainList.vue:78
|
||||
#: src/views/other/Install.vue:71
|
||||
#: src/views/other/Login.vue:56
|
||||
msgid "Server error"
|
||||
msgstr ""
|
||||
|
||||
|
@ -504,12 +503,12 @@ msgstr ""
|
|||
msgid "server_name not found in directives"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:155
|
||||
#: src/views/domain/cert/IssueCert.vue:164
|
||||
#: src/views/domain/DomainAdd.vue:112
|
||||
msgid "server_name parameter is required"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:158
|
||||
#: src/views/domain/cert/IssueCert.vue:167
|
||||
#: src/views/domain/cert/IssueCert.vue:34
|
||||
msgid "server_name parameters more than one"
|
||||
msgstr ""
|
||||
|
@ -547,7 +546,7 @@ msgstr ""
|
|||
msgid "Terminal"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:168
|
||||
#: src/views/domain/cert/IssueCert.vue:177
|
||||
msgid "The certificate for the domain will be checked every hour, and will be renewed if it has been more than 1 month since it was last issued."
|
||||
msgstr ""
|
||||
|
||||
|
@ -555,6 +554,10 @@ msgstr ""
|
|||
msgid "The filename cannot contain the following characters: %{c}"
|
||||
msgstr ""
|
||||
|
||||
#: src/language/constants.ts:6
|
||||
msgid "The username or password is incorrect"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/config/Config.vue:17
|
||||
#: src/views/domain/DomainList.vue:36
|
||||
#: src/views/user/User.vue:36
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -28,7 +28,7 @@ msgstr "添加"
|
|||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:31
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
msgid "Add Directive Below"
|
||||
msgstr "在下面添加指令"
|
||||
|
||||
|
@ -62,7 +62,7 @@ msgstr "成功关闭 %{name} 自动续签"
|
|||
msgid "Auto-renewal enabled for %{name}"
|
||||
msgstr "成功启用 %{name} 自动续签"
|
||||
|
||||
#: src/views/domain/DomainEdit.vue:158
|
||||
#: src/views/domain/DomainEdit.vue:166
|
||||
msgid "Back"
|
||||
msgstr "返回"
|
||||
|
||||
|
@ -102,7 +102,7 @@ msgstr "证书状态"
|
|||
#: src/views/domain/ngx_conf/directive/DirectiveEditor.vue:29
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:21
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:7
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:145
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:154
|
||||
msgid "Comments"
|
||||
msgstr "注释"
|
||||
|
||||
|
@ -304,7 +304,7 @@ msgstr "登录成功"
|
|||
msgid "Logout successful"
|
||||
msgstr "登出成功"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:172
|
||||
#: src/views/domain/cert/IssueCert.vue:181
|
||||
msgid ""
|
||||
"Make sure you have configured a reverse proxy for .well-known directory to "
|
||||
"HTTPChallengePort (default: 9180) before getting the certificate."
|
||||
|
@ -383,7 +383,7 @@ msgstr "找不到页面"
|
|||
msgid "Not Valid Before: %{date}"
|
||||
msgstr "此前无效: %{date}"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:164
|
||||
#: src/views/domain/cert/IssueCert.vue:173
|
||||
msgid ""
|
||||
"Note: The server_name in the current configuration must be the domain name "
|
||||
"you need to get the certificate."
|
||||
|
@ -399,7 +399,7 @@ msgstr "确定"
|
|||
msgid "OS:"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:21
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:22
|
||||
msgid "Params"
|
||||
msgstr "参数"
|
||||
|
||||
|
@ -444,13 +444,13 @@ msgstr "下载"
|
|||
msgid "Reset"
|
||||
msgstr "重置"
|
||||
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:161
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:169
|
||||
msgid "Save"
|
||||
msgstr "保存"
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:35
|
||||
msgid "Save Directive"
|
||||
msgstr "保存指令"
|
||||
|
||||
|
@ -478,7 +478,7 @@ msgstr "上传"
|
|||
#: src/views/config/ConfigEdit.vue:22 src/views/domain/DomainEdit.vue:44
|
||||
#: src/views/domain/DomainEdit.vue:56 src/views/domain/DomainEdit.vue:65
|
||||
#: src/views/domain/DomainEdit.vue:83 src/views/domain/DomainList.vue:78
|
||||
#: src/views/other/Install.vue:71 src/views/other/Login.vue:56
|
||||
#: src/views/other/Install.vue:71
|
||||
msgid "Server error"
|
||||
msgstr "服务器错误"
|
||||
|
||||
|
@ -490,11 +490,11 @@ msgstr "服务器信息"
|
|||
msgid "server_name not found in directives"
|
||||
msgstr "未在指令集合中找到 server_name"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:155 src/views/domain/DomainAdd.vue:112
|
||||
#: src/views/domain/cert/IssueCert.vue:164 src/views/domain/DomainAdd.vue:112
|
||||
msgid "server_name parameter is required"
|
||||
msgstr "必须为 server_name 指令指明参数"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:158
|
||||
#: src/views/domain/cert/IssueCert.vue:167
|
||||
#: src/views/domain/cert/IssueCert.vue:34
|
||||
msgid "server_name parameters more than one"
|
||||
msgstr "server_name 指令包含多个参数"
|
||||
|
@ -531,7 +531,7 @@ msgstr "列表"
|
|||
msgid "Terminal"
|
||||
msgstr "终端"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:168
|
||||
#: src/views/domain/cert/IssueCert.vue:177
|
||||
msgid ""
|
||||
"The certificate for the domain will be checked every hour, and will be "
|
||||
"renewed if it has been more than 1 month since it was last issued."
|
||||
|
@ -542,6 +542,10 @@ msgstr ""
|
|||
msgid "The filename cannot contain the following characters: %{c}"
|
||||
msgstr "文件名不能包含以下字符: %{c}"
|
||||
|
||||
#: src/language/constants.ts:6
|
||||
msgid "The username or password is incorrect"
|
||||
msgstr "用户名或密码错误"
|
||||
|
||||
#: src/views/config/Config.vue:17 src/views/domain/DomainList.vue:36
|
||||
#: src/views/user/User.vue:36
|
||||
msgid "Updated at"
|
||||
|
|
|
@ -29,7 +29,7 @@ msgstr ""
|
|||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:31
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
msgid "Add Directive Below"
|
||||
msgstr "在下面新增指令"
|
||||
|
||||
|
@ -64,7 +64,7 @@ msgstr "已關閉 %{name} 自動續簽"
|
|||
msgid "Auto-renewal enabled for %{name}"
|
||||
msgstr "已啟用 %{name} 自動續簽"
|
||||
|
||||
#: src/views/domain/DomainEdit.vue:158
|
||||
#: src/views/domain/DomainEdit.vue:166
|
||||
msgid "Back"
|
||||
msgstr "返回"
|
||||
|
||||
|
@ -105,7 +105,7 @@ msgstr "憑證狀態"
|
|||
#: src/views/domain/ngx_conf/directive/DirectiveEditor.vue:29
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:21
|
||||
#: src/views/domain/ngx_conf/LocationEditor.vue:7
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:145
|
||||
#: src/views/domain/ngx_conf/NgxConfigEditor.vue:154
|
||||
msgid "Comments"
|
||||
msgstr "註釋"
|
||||
|
||||
|
@ -309,7 +309,7 @@ msgstr "登入成功"
|
|||
msgid "Logout successful"
|
||||
msgstr "登出成功"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:172
|
||||
#: src/views/domain/cert/IssueCert.vue:181
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Make sure you have configured a reverse proxy for .well-known directory to "
|
||||
|
@ -390,7 +390,7 @@ msgstr "找不到頁面"
|
|||
msgid "Not Valid Before: %{date}"
|
||||
msgstr "此前無效: %{date}"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:164
|
||||
#: src/views/domain/cert/IssueCert.vue:173
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Note: The server_name in the current configuration must be the domain name "
|
||||
|
@ -407,7 +407,7 @@ msgstr "確定"
|
|||
msgid "OS:"
|
||||
msgstr "作業系統:"
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:21
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:22
|
||||
msgid "Params"
|
||||
msgstr "參數"
|
||||
|
||||
|
@ -452,13 +452,13 @@ msgstr "下載"
|
|||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:161
|
||||
#: src/views/config/ConfigEdit.vue:52 src/views/domain/DomainEdit.vue:169
|
||||
msgid "Save"
|
||||
msgstr "儲存"
|
||||
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:32
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:33
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:34
|
||||
#: src/views/domain/ngx_conf/directive/DirectiveAdd.vue:35
|
||||
msgid "Save Directive"
|
||||
msgstr "儲存指令"
|
||||
|
||||
|
@ -487,7 +487,7 @@ msgstr "上傳"
|
|||
#: src/views/config/ConfigEdit.vue:22 src/views/domain/DomainEdit.vue:44
|
||||
#: src/views/domain/DomainEdit.vue:56 src/views/domain/DomainEdit.vue:65
|
||||
#: src/views/domain/DomainEdit.vue:83 src/views/domain/DomainList.vue:78
|
||||
#: src/views/other/Install.vue:71 src/views/other/Login.vue:56
|
||||
#: src/views/other/Install.vue:71
|
||||
msgid "Server error"
|
||||
msgstr "伺服器錯誤"
|
||||
|
||||
|
@ -499,11 +499,11 @@ msgstr "伺服器資訊"
|
|||
msgid "server_name not found in directives"
|
||||
msgstr "未在指令集合中找到 server_name"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:155 src/views/domain/DomainAdd.vue:112
|
||||
#: src/views/domain/cert/IssueCert.vue:164 src/views/domain/DomainAdd.vue:112
|
||||
msgid "server_name parameter is required"
|
||||
msgstr "必須為 server_name 指令指明參數"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:158
|
||||
#: src/views/domain/cert/IssueCert.vue:167
|
||||
#: src/views/domain/cert/IssueCert.vue:34
|
||||
msgid "server_name parameters more than one"
|
||||
msgstr "server_name 指令包含多個參數"
|
||||
|
@ -541,7 +541,7 @@ msgstr "啟用"
|
|||
msgid "Terminal"
|
||||
msgstr "終端"
|
||||
|
||||
#: src/views/domain/cert/IssueCert.vue:168
|
||||
#: src/views/domain/cert/IssueCert.vue:177
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"The certificate for the domain will be checked every hour, and will be "
|
||||
|
@ -554,6 +554,10 @@ msgstr ""
|
|||
msgid "The filename cannot contain the following characters: %{c}"
|
||||
msgstr "檔名不能包含以下字元: %{c}"
|
||||
|
||||
#: src/language/constants.ts:6
|
||||
msgid "The username or password is incorrect"
|
||||
msgstr ""
|
||||
|
||||
#: src/views/config/Config.vue:17 src/views/domain/DomainList.vue:36
|
||||
#: src/views/user/User.vue:36
|
||||
msgid "Updated at"
|
||||
|
|
|
@ -53,7 +53,7 @@ const onSubmit = () => {
|
|||
const next = (route.query?.next || '').toString() || '/'
|
||||
await router.push(next)
|
||||
}).catch(e => {
|
||||
message.error(e.message ?? $gettext('Server error'))
|
||||
message.error($gettext(e.message ?? 'Server error'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
6
main.go
6
main.go
|
@ -5,10 +5,10 @@ import (
|
|||
"flag"
|
||||
"github.com/0xJacky/Nginx-UI/server/analytic"
|
||||
"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/0xJacky/Nginx-UI/server/router"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-co-op/gocron"
|
||||
"log"
|
||||
|
@ -40,7 +40,7 @@ func main() {
|
|||
model.Init()
|
||||
|
||||
s := gocron.NewScheduler(time.UTC)
|
||||
job, err := s.Every(1).Hour().SingletonMode().Do(tool.AutoCert)
|
||||
job, err := s.Every(1).Hour().SingletonMode().Do(cert.AutoCert)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("AutoCert Job: %v, Err: %v\n", job, err)
|
||||
|
|
|
@ -41,8 +41,9 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
|
|||
if !ok {
|
||||
log.Println("verrs", verrs)
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"message": "请求参数错误",
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
"error": verrs,
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ func BindAndValid(c *gin.Context, target interface{}) bool {
|
|||
|
||||
c.JSON(http.StatusNotAcceptable, gin.H{
|
||||
"errors": errs,
|
||||
"message": "请求参数错误",
|
||||
"message": "Requested with wrong parameters",
|
||||
"code": http.StatusNotAcceptable,
|
||||
})
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ func Login(c *gin.Context) {
|
|||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(user.Password)); err != nil {
|
||||
c.JSON(http.StatusForbidden, gin.H{
|
||||
"message": "用户名或密码错误",
|
||||
"message": "The username or password is incorrect",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"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"
|
||||
"log"
|
||||
|
@ -13,7 +13,7 @@ import (
|
|||
func CertInfo(c *gin.Context) {
|
||||
domain := c.Param("domain")
|
||||
|
||||
key, err := tool.GetCertInfo(domain)
|
||||
key, err := cert.GetCertInfo(domain)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
@ -61,7 +61,7 @@ func IssueCert(c *gin.Context) {
|
|||
|
||||
if mt == websocket.TextMessage && string(message) == "go" {
|
||||
|
||||
err = tool.IssueCert(domain)
|
||||
err = cert.IssueCert(domain)
|
||||
|
||||
if err != nil {
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -21,7 +20,7 @@ func GetConfigs(c *gin.Context) {
|
|||
"modify": "time",
|
||||
}
|
||||
|
||||
configFiles, err := ioutil.ReadDir(nginx.GetNginxConfPath("/"))
|
||||
configFiles, err := os.ReadDir(nginx.GetNginxConfPath("/"))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
|
@ -32,17 +31,18 @@ func GetConfigs(c *gin.Context) {
|
|||
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
|
||||
if !file.IsDir() && "." != file.Name()[0:1] {
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": file.Size(),
|
||||
"modify": file.ModTime(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
|
@ -53,7 +53,7 @@ func GetConfig(c *gin.Context) {
|
|||
name := c.Param("name")
|
||||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
|
||||
content, err := ioutil.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
|
@ -93,7 +93,7 @@ func AddConfig(c *gin.Context) {
|
|||
}
|
||||
|
||||
if content != "" {
|
||||
err := ioutil.WriteFile(path, []byte(content), 0644)
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
|
@ -131,7 +131,7 @@ func EditConfig(c *gin.Context) {
|
|||
path := filepath.Join(nginx.GetNginxConfPath("/"), name)
|
||||
content := request.Content
|
||||
|
||||
origContent, err := ioutil.ReadFile(path)
|
||||
origContent, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
|
@ -139,7 +139,7 @@ func EditConfig(c *gin.Context) {
|
|||
|
||||
if content != "" && content != string(origContent) {
|
||||
// model.CreateBackup(path)
|
||||
err := ioutil.WriteFile(path, []byte(content), 0644)
|
||||
err = os.WriteFile(path, []byte(content), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
|
|
|
@ -2,10 +2,9 @@ package api
|
|||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/config_list"
|
||||
nginx2 "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -22,14 +21,14 @@ func GetDomains(c *gin.Context) {
|
|||
"modify": "time",
|
||||
}
|
||||
|
||||
configFiles, err := ioutil.ReadDir(nginx.GetNginxConfPath("sites-available"))
|
||||
configFiles, err := os.ReadDir(nginx2.GetNginxConfPath("sites-available"))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
enabledConfig, err := ioutil.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
|
||||
enabledConfig, err := os.ReadDir(filepath.Join(nginx2.GetNginxConfPath("sites-enabled")))
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
|
@ -45,17 +44,18 @@ func GetDomains(c *gin.Context) {
|
|||
|
||||
for i := range configFiles {
|
||||
file := configFiles[i]
|
||||
fileInfo, _ := file.Info()
|
||||
if !file.IsDir() {
|
||||
configs = append(configs, gin.H{
|
||||
"name": file.Name(),
|
||||
"size": file.Size(),
|
||||
"modify": file.ModTime(),
|
||||
"size": fileInfo.Size(),
|
||||
"modify": fileInfo.ModTime(),
|
||||
"enabled": enabledConfigMap[file.Name()],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
configs = tool.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
configs = config_list.Sort(orderBy, sort, mySort[orderBy], configs)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": configs,
|
||||
|
@ -64,14 +64,14 @@ func GetDomains(c *gin.Context) {
|
|||
|
||||
func GetDomain(c *gin.Context) {
|
||||
name := c.Param("name")
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
path := filepath.Join(nginx2.GetNginxConfPath("sites-available"), name)
|
||||
|
||||
enabled := true
|
||||
if _, err := os.Stat(filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
||||
if _, err := os.Stat(filepath.Join(nginx2.GetNginxConfPath("sites-enabled"), name)); os.IsNotExist(err) {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
config, err := nginx.ParseNgxConfig(path)
|
||||
config, err := nginx2.ParseNgxConfig(path)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
|
@ -95,18 +95,18 @@ func EditDomain(c *gin.Context) {
|
|||
name := c.Param("name")
|
||||
request := make(gin.H)
|
||||
err = c.BindJSON(&request)
|
||||
path := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
path := filepath.Join(nginx2.GetNginxConfPath("sites-available"), name)
|
||||
|
||||
err = ioutil.WriteFile(path, []byte(request["content"].(string)), 0644)
|
||||
err = os.WriteFile(path, []byte(request["content"].(string)), 0644)
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
enabledConfigFilePath := filepath.Join(nginx2.GetNginxConfPath("sites-enabled"), name)
|
||||
if _, err = os.Stat(enabledConfigFilePath); err == nil {
|
||||
// Test nginx configuration
|
||||
err = nginx.TestNginxConf()
|
||||
err = nginx2.TestNginxConf()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
|
@ -114,7 +114,7 @@ func EditDomain(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx2.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
@ -128,8 +128,8 @@ func EditDomain(c *gin.Context) {
|
|||
}
|
||||
|
||||
func EnableDomain(c *gin.Context) {
|
||||
configFilePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
configFilePath := filepath.Join(nginx2.GetNginxConfPath("sites-available"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx2.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
|
||||
_, err := os.Stat(configFilePath)
|
||||
|
||||
|
@ -148,7 +148,7 @@ func EnableDomain(c *gin.Context) {
|
|||
}
|
||||
|
||||
// Test nginx config, if not pass then rollback.
|
||||
err = nginx.TestNginxConf()
|
||||
err = nginx2.TestNginxConf()
|
||||
if err != nil {
|
||||
_ = os.Remove(enabledConfigFilePath)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
@ -157,7 +157,7 @@ func EnableDomain(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx2.ReloadNginx()
|
||||
|
||||
if output != "" && strings.Contains(output, "error") {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
@ -172,7 +172,7 @@ func EnableDomain(c *gin.Context) {
|
|||
}
|
||||
|
||||
func DisableDomain(c *gin.Context) {
|
||||
enabledConfigFilePath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
enabledConfigFilePath := filepath.Join(nginx2.GetNginxConfPath("sites-enabled"), c.Param("name"))
|
||||
|
||||
_, err := os.Stat(enabledConfigFilePath)
|
||||
|
||||
|
@ -196,7 +196,7 @@ func DisableDomain(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
output := nginx.ReloadNginx()
|
||||
output := nginx2.ReloadNginx()
|
||||
|
||||
if output != "" {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
|
@ -213,8 +213,8 @@ func DisableDomain(c *gin.Context) {
|
|||
func DeleteDomain(c *gin.Context) {
|
||||
var err error
|
||||
name := c.Param("name")
|
||||
availablePath := filepath.Join(nginx.GetNginxConfPath("sites-available"), name)
|
||||
enabledPath := filepath.Join(nginx.GetNginxConfPath("sites-enabled"), name)
|
||||
availablePath := filepath.Join(nginx2.GetNginxConfPath("sites-available"), name)
|
||||
enabledPath := filepath.Join(nginx2.GetNginxConfPath("sites-enabled"), name)
|
||||
|
||||
if _, err = os.Stat(availablePath); os.IsNotExist(err) {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
|
|
|
@ -2,14 +2,14 @@ package api
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
nginx2 "github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func BuildNginxConfig(c *gin.Context) {
|
||||
var ngxConf nginx.NgxConfig
|
||||
var ngxConf nginx2.NgxConfig
|
||||
if !BindAndValid(c, &ngxConf) {
|
||||
return
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ func TokenizeNginxConfig(c *gin.Context) {
|
|||
|
||||
scanner := bufio.NewScanner(strings.NewReader(json.Content))
|
||||
|
||||
ngxConfig, err := nginx.ParseNgxConfigByScanner("", scanner)
|
||||
ngxConfig, err := nginx2.ParseNgxConfigByScanner("", scanner)
|
||||
|
||||
if err != nil {
|
||||
ErrHandler(c, err)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/pty"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/pty"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
|
|
@ -91,7 +91,7 @@ func EditUser(c *gin.Context) {
|
|||
}
|
||||
edit.Name = json.Name
|
||||
|
||||
// 改密码加密
|
||||
// encrypt passowrd
|
||||
if json.Password != "" {
|
||||
var pwd []byte
|
||||
pwd, err = bcrypt.GenerateFromPassword([]byte(json.Password), bcrypt.DefaultCost)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"io/ioutil"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
|
@ -29,7 +29,7 @@ func GetAutoCertList() (c []Cert) {
|
|||
db.Find(&t)
|
||||
// check if this domain is enabled
|
||||
|
||||
enabledConfig, err := ioutil.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
|
||||
enabledConfig, err := os.ReadDir(filepath.Join(nginx.GetNginxConfPath("sites-enabled")))
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
|
@ -36,7 +36,7 @@ func GetBackup(id int) (config ConfigBackup) {
|
|||
}
|
||||
|
||||
func CreateBackup(path string) {
|
||||
content, err := ioutil.ReadFile(path)
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
|
188
server/pkg/cert/cert.go
Normal file
188
server/pkg/cert/cert.go
Normal file
|
@ -0,0 +1,188 @@
|
|||
package cert
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge/http01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MyUser You'll need a user or account type that implements acme.User
|
||||
type MyUser struct {
|
||||
Email string
|
||||
Registration *registration.Resource
|
||||
key crypto.PrivateKey
|
||||
}
|
||||
|
||||
func (u *MyUser) GetEmail() string {
|
||||
return u.Email
|
||||
}
|
||||
func (u *MyUser) GetRegistration() *registration.Resource {
|
||||
return u.Registration
|
||||
}
|
||||
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
||||
return u.key
|
||||
}
|
||||
|
||||
func AutoCert() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Println("[AutoCert] Recover", err)
|
||||
}
|
||||
}()
|
||||
log.Println("[AutoCert] Start")
|
||||
autoCertList := model.GetAutoCertList()
|
||||
for i := range autoCertList {
|
||||
domain := autoCertList[i].Domain
|
||||
key, err := GetCertInfo(domain)
|
||||
if err != nil {
|
||||
log.Println("GetCertInfo Err", err)
|
||||
// Get certificate info error, ignore this domain
|
||||
continue
|
||||
}
|
||||
// before 1 mo
|
||||
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
|
||||
continue
|
||||
}
|
||||
// after 1 mo, reissue certificate
|
||||
err = IssueCert(domain)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetCertInfo(domain string) (key *x509.Certificate, err error) {
|
||||
|
||||
var response *http.Response
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}).DialContext,
|
||||
DisableKeepAlives: true,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
response, err = client.Get("https://" + domain)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "get cert info error")
|
||||
return
|
||||
}
|
||||
|
||||
defer func(Body io.ReadCloser) {
|
||||
err = Body.Close()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
}(response.Body)
|
||||
|
||||
key = response.TLS.PeerCertificates[0]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func IssueCert(domain string) error {
|
||||
// Create a user. New accounts need an email and private key to start.
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert generate key error")
|
||||
}
|
||||
|
||||
myUser := MyUser{
|
||||
Email: settings.ServerSettings.Email,
|
||||
key: privateKey,
|
||||
}
|
||||
|
||||
config := lego.NewConfig(&myUser)
|
||||
|
||||
if settings.ServerSettings.Demo {
|
||||
config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
// A client facilitates communication with the CA server.
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert new client error")
|
||||
}
|
||||
|
||||
err = client.Challenge.SetHTTP01Provider(
|
||||
http01.NewProviderServer("",
|
||||
settings.ServerSettings.HTTPChallengePort,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert challenge fail")
|
||||
}
|
||||
|
||||
// New users will need to register
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert register fail")
|
||||
}
|
||||
myUser.Registration = reg
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{domain},
|
||||
Bundle: true,
|
||||
}
|
||||
certificates, err := client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert fail to obtain")
|
||||
}
|
||||
saveDir := nginx.GetNginxConfPath("ssl/" + domain)
|
||||
if _, err = os.Stat(saveDir); os.IsNotExist(err) {
|
||||
err = os.Mkdir(saveDir, 0755)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert fail to create")
|
||||
}
|
||||
}
|
||||
|
||||
// Each certificate comes back with the cert bytes, the bytes of the client's
|
||||
// private key, and a certificate URL. SAVE THESE TO DISK.
|
||||
err = os.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
|
||||
certificates.Certificate, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert write fullchain.cer fail")
|
||||
}
|
||||
|
||||
err = os.WriteFile(filepath.Join(saveDir, domain+".key"),
|
||||
certificates.PrivateKey, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert write key fail")
|
||||
}
|
||||
|
||||
nginx.ReloadNginx()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package tool
|
||||
package config_list
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
|
@ -2,7 +2,7 @@ package test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
|
|
@ -2,7 +2,7 @@ package test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -35,6 +35,4 @@ func TestCert(t *testing.T) {
|
|||
}
|
||||
|
||||
log.Println("[found]", "cert key")
|
||||
|
||||
log.Println("申请成功")
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ package test
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/server/pkg/nginx"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
package tool
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"github.com/0xJacky/Nginx-UI/server/model"
|
||||
"github.com/0xJacky/Nginx-UI/server/settings"
|
||||
"github.com/0xJacky/Nginx-UI/server/tool/nginx"
|
||||
"github.com/go-acme/lego/v4/certcrypto"
|
||||
"github.com/go-acme/lego/v4/certificate"
|
||||
"github.com/go-acme/lego/v4/challenge/http01"
|
||||
"github.com/go-acme/lego/v4/lego"
|
||||
"github.com/go-acme/lego/v4/registration"
|
||||
"github.com/pkg/errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MyUser You'll need a user or account type that implements acme.User
|
||||
type MyUser struct {
|
||||
Email string
|
||||
Registration *registration.Resource
|
||||
key crypto.PrivateKey
|
||||
}
|
||||
|
||||
func (u *MyUser) GetEmail() string {
|
||||
return u.Email
|
||||
}
|
||||
func (u *MyUser) GetRegistration() *registration.Resource {
|
||||
return u.Registration
|
||||
}
|
||||
func (u *MyUser) GetPrivateKey() crypto.PrivateKey {
|
||||
return u.key
|
||||
}
|
||||
|
||||
func AutoCert() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Println("[AutoCert] Recover", err)
|
||||
}
|
||||
}()
|
||||
log.Println("[AutoCert] Start")
|
||||
autoCertList := model.GetAutoCertList()
|
||||
for i := range autoCertList {
|
||||
domain := autoCertList[i].Domain
|
||||
key, err := GetCertInfo(domain)
|
||||
if err != nil {
|
||||
log.Println("GetCertInfo Err", err)
|
||||
// 获取证书信息失败,本次跳过
|
||||
continue
|
||||
}
|
||||
// 未到一个月
|
||||
if time.Now().Before(key.NotBefore.AddDate(0, 1, 0)) {
|
||||
continue
|
||||
}
|
||||
// 过一个月了,重新申请证书
|
||||
err = IssueCert(domain)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetCertInfo(domain string) (key *x509.Certificate, err error) {
|
||||
|
||||
var response *http.Response
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 5 * time.Second,
|
||||
}).DialContext,
|
||||
DisableKeepAlives: true,
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
|
||||
response, err = client.Get("https://" + domain)
|
||||
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "get cert info error")
|
||||
return
|
||||
}
|
||||
|
||||
defer func(Body io.ReadCloser) {
|
||||
err = Body.Close()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
}(response.Body)
|
||||
|
||||
key = response.TLS.PeerCertificates[0]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func IssueCert(domain string) error {
|
||||
// Create a user. New accounts need an email and private key to start.
|
||||
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert generate key error")
|
||||
}
|
||||
|
||||
myUser := MyUser{
|
||||
Email: settings.ServerSettings.Email,
|
||||
key: privateKey,
|
||||
}
|
||||
|
||||
config := lego.NewConfig(&myUser)
|
||||
|
||||
if settings.ServerSettings.Demo {
|
||||
config.CADirURL = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||
}
|
||||
|
||||
config.Certificate.KeyType = certcrypto.RSA2048
|
||||
|
||||
// A client facilitates communication with the CA server.
|
||||
client, err := lego.NewClient(config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert new client error")
|
||||
}
|
||||
|
||||
err = client.Challenge.SetHTTP01Provider(
|
||||
http01.NewProviderServer("",
|
||||
settings.ServerSettings.HTTPChallengePort,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert challenge fail")
|
||||
}
|
||||
|
||||
// New users will need to register
|
||||
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert register fail")
|
||||
}
|
||||
myUser.Registration = reg
|
||||
|
||||
request := certificate.ObtainRequest{
|
||||
Domains: []string{domain},
|
||||
Bundle: true,
|
||||
}
|
||||
certificates, err := client.Certificate.Obtain(request)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert fail to obtain")
|
||||
}
|
||||
saveDir := nginx.GetNginxConfPath("ssl/" + domain)
|
||||
if _, err = os.Stat(saveDir); os.IsNotExist(err) {
|
||||
err = os.Mkdir(saveDir, 0755)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue cert fail to create")
|
||||
}
|
||||
}
|
||||
|
||||
// Each certificate comes back with the cert bytes, the bytes of the client's
|
||||
// private key, and a certificate URL. SAVE THESE TO DISK.
|
||||
err = ioutil.WriteFile(filepath.Join(saveDir, "fullchain.cer"),
|
||||
certificates.Certificate, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert write fullchain.cer fail")
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(saveDir, domain+".key"),
|
||||
certificates.PrivateKey, 0644)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return errors.Wrap(err, "issue cert write key fail")
|
||||
}
|
||||
|
||||
nginx.ReloadNginx()
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue