efront 4.4.14 → 4.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/#/345/233/275/351/231/205/345/214/226.yml +83 -5
- package/apps/pivot/api.yml +4 -0
- package/apps/pivot/cert/edit.js +1 -0
- package/apps/pivot/cert/list.js +9 -0
- package/apps/pivot/cert/main.xht +188 -0
- package/apps/pivot/cert/orders.xht +232 -0
- package/apps/pivot/cert/update.xht +7 -0
- package/apps/pivot/menu.yml +1 -0
- package/coms/basic/assert.js +40 -16
- package/coms/basic/cross_.js +22 -4
- package/coms/basic/renderTags.js +23 -0
- package/coms/basic/shallowClone.js +8 -0
- package/coms/basic/shallowEqual.js +13 -4
- package/coms/basic/valid.js +19 -4
- package/coms/compile/Javascript.js +25 -12
- package/coms/compile//347/264/240/351/246/250.js +2 -1
- package/coms/docs/codetext.xht +3 -3
- package/coms/frame/chat.js +1 -1
- package/coms/frame/edit.html +1 -0
- package/coms/frame/edit.js +3 -2
- package/coms/kugou/bindScroll.js +1 -1
- package/coms/kugou/krc.js +2 -2
- package/coms/layer/leftCenter.js +5 -5
- package/coms/pivot/acme2.js +290 -0
- package/coms/pivot/pedit.js +13 -5
- package/coms/pivot/plist.js +12 -5
- package/coms/reptile/colored_console.js +5 -17
- package/coms/zimoli/appendChild.js +3 -2
- package/coms/zimoli/autofocus.js +2 -2
- package/coms/zimoli/button.less +5 -3
- package/coms/zimoli/checker.js +34 -15
- package/coms/zimoli/checker.less +2 -3
- package/coms/zimoli/container.js +26 -15
- package/coms/zimoli/data.js +124 -169
- package/coms/zimoli/field.js +3 -3
- package/coms/zimoli/field.less +8 -2
- package/coms/zimoli/filterTime.js +39 -8
- package/coms/zimoli/fromBase64.js +2 -0
- package/coms/zimoli/grid.js +2 -2
- package/coms/zimoli/isMounted.js +3 -3
- package/coms/zimoli/list.js +5 -5
- package/coms/zimoli/maps.js +1 -1
- package/coms/zimoli/menuList.js +1 -1
- package/coms/zimoli/model.js +61 -8
- package/coms/zimoli/on.js +4 -4
- package/coms/zimoli/remove.js +3 -3
- package/coms/zimoli/render.js +25 -33
- package/coms/zimoli/scrollbar.js +54 -19
- package/coms/zimoli/scrollbar.less +14 -2
- package/coms/zimoli/scrollbar_test.less +1 -0
- package/coms/zimoli/select.js +3 -3
- package/coms/zimoli/table.js +1 -1
- package/coms/zimoli/toBase64.js +16 -6
- package/coms/zimoli/view.js +24 -14
- package/coms/zimoli/view.less +6 -4
- package/coms/zimoli/watch.js +1 -1
- package/docs/loader.js +1 -1
- package/docs//347/273/204/344/273/266.xht +0 -1
- package/package.json +1 -1
- package/public/efront.js +1 -1
|
@@ -1,3 +1,81 @@
|
|
|
1
|
+
- zh-CN: 端口异常
|
|
2
|
+
en: Port abnormality
|
|
3
|
+
|
|
4
|
+
- zh-CN: 分配地址失败
|
|
5
|
+
en: Address allocation failed
|
|
6
|
+
|
|
7
|
+
- zh-CN: 电子邮箱地址应包含符号“@”
|
|
8
|
+
en: "The email address should contain the symbol \"@\""
|
|
9
|
+
|
|
10
|
+
- zh-CN: "@符号前应有内容"
|
|
11
|
+
en: "There should be content before the symbol \"@\""
|
|
12
|
+
|
|
13
|
+
- zh-CN: "@符号后应有内容"
|
|
14
|
+
en: "There should be content after the symbol\"@\""
|
|
15
|
+
|
|
16
|
+
- zh-CN: 私钥
|
|
17
|
+
en: Private key
|
|
18
|
+
|
|
19
|
+
- zh-CN: 证书
|
|
20
|
+
en: certificate
|
|
21
|
+
|
|
22
|
+
- zh-CN: 账户
|
|
23
|
+
en: account
|
|
24
|
+
|
|
25
|
+
- zh-CN: 当前服务器的域名
|
|
26
|
+
en: The domain name of the current server
|
|
27
|
+
|
|
28
|
+
- zh-CN: 订单失效时间
|
|
29
|
+
en: Order expiration time
|
|
30
|
+
|
|
31
|
+
- zh-CN: 请求无效!
|
|
32
|
+
en: Request is invalid!
|
|
33
|
+
|
|
34
|
+
- zh-CN: 已取消
|
|
35
|
+
en: Canceled
|
|
36
|
+
|
|
37
|
+
- zh-CN: 输入原密码:
|
|
38
|
+
en: "Enter the original password:"
|
|
39
|
+
|
|
40
|
+
- zh-CN: 数据过载..
|
|
41
|
+
en: Data overload..
|
|
42
|
+
|
|
43
|
+
- zh-CN: 服务器忙!
|
|
44
|
+
en: Server busy!
|
|
45
|
+
|
|
46
|
+
- zh-CN: 无权访问
|
|
47
|
+
en: Unauthorized access
|
|
48
|
+
|
|
49
|
+
- zh-CN: 清理完成
|
|
50
|
+
en: Cleaning completed
|
|
51
|
+
|
|
52
|
+
- zh-CN: 正在重启
|
|
53
|
+
en: Restarting
|
|
54
|
+
|
|
55
|
+
- zh-CN: 已存在相同标识的数据
|
|
56
|
+
en: Data with the same identifier already exists
|
|
57
|
+
|
|
58
|
+
- zh-CN: 禁止访问
|
|
59
|
+
en: Prohibit access
|
|
60
|
+
|
|
61
|
+
- zh-CN: 已关闭$1端口
|
|
62
|
+
en: $1 port has been closed
|
|
63
|
+
|
|
64
|
+
- zh-CN: <red>端口异常</red>
|
|
65
|
+
en: <red>Port exception</red>
|
|
66
|
+
|
|
67
|
+
- zh-CN: filelist
|
|
68
|
+
en: filelist
|
|
69
|
+
|
|
70
|
+
- zh-CN: pathlist
|
|
71
|
+
en: pathlist
|
|
72
|
+
|
|
73
|
+
- zh-CN: pathend
|
|
74
|
+
en: pathend
|
|
75
|
+
|
|
76
|
+
- zh-CN: 邮箱
|
|
77
|
+
en: mailbox
|
|
78
|
+
|
|
1
79
|
- zh-CN: 过滤空串
|
|
2
80
|
en: Filter empty strings
|
|
3
81
|
|
|
@@ -5,10 +83,10 @@
|
|
|
5
83
|
en: ","
|
|
6
84
|
|
|
7
85
|
- zh-CN: ,
|
|
8
|
-
en:
|
|
86
|
+
en: .
|
|
9
87
|
|
|
10
88
|
- zh-CN: !
|
|
11
|
-
en:
|
|
89
|
+
en: !
|
|
12
90
|
|
|
13
91
|
- zh-CN: https://letsencrypt.org/zh-cn/
|
|
14
92
|
en:
|
|
@@ -260,7 +338,7 @@
|
|
|
260
338
|
en: Server restart
|
|
261
339
|
|
|
262
340
|
- zh-CN: 正在退出..
|
|
263
|
-
en: Exiting
|
|
341
|
+
en: Exiting..
|
|
264
342
|
|
|
265
343
|
- zh-CN: 进程已退出
|
|
266
344
|
en: Process has exited
|
|
@@ -401,7 +479,7 @@
|
|
|
401
479
|
en: Not supported
|
|
402
480
|
|
|
403
481
|
- zh-CN: 当前运行环境使用class extends Array会有难以解决的不兼容性问题,请更换代码的实现方式!
|
|
404
|
-
en:
|
|
482
|
+
en: The current operating environment using class extends Array may have compatibility issues that are difficult to solve. Please change the implementation method of the code!
|
|
405
483
|
|
|
406
484
|
- zh-CN: 代码异常!
|
|
407
485
|
en: Code exception!
|
|
@@ -719,7 +797,7 @@
|
|
|
719
797
|
en: The path does not point to file $1
|
|
720
798
|
|
|
721
799
|
- zh-CN: 文件过大!$1
|
|
722
|
-
en: The file is too large$
|
|
800
|
+
en: The file is too large! $1
|
|
723
801
|
|
|
724
802
|
- zh-CN: 读取文件信息出错$1
|
|
725
803
|
en: Error reading file information $1
|
package/apps/pivot/api.yml
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
room: options ::link-:id
|
|
19
19
|
care: options ::care-:id
|
|
20
20
|
cast: options ::cast-:id?:msg
|
|
21
|
+
setauth|: options ::setauth-/.well-known/acme-challenge/:token?:token.:thumb
|
|
22
|
+
unique: options ::unique
|
|
23
|
+
unique-save: options ::unique-:data
|
|
24
|
+
recert: options ::recert
|
|
21
25
|
upload: put :path
|
|
22
26
|
https://www.ip.cn/:
|
|
23
27
|
iplocation: get https://www.ip.cn/api/index?ip=:ip&type=1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pedit.bind(null, "证书", "cert");
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
plist.bind(null, '接口管理', "cert", refilm`
|
|
2
|
+
*域名/hostname input/253
|
|
3
|
+
公钥/private gen/600 ${async function (data) {
|
|
4
|
+
var [private_key, public_key] = await acme2.createKeyPair();
|
|
5
|
+
data.private = private_key;
|
|
6
|
+
data.public = public_key;
|
|
7
|
+
}}
|
|
8
|
+
-私钥/public text
|
|
9
|
+
$证书/cert text`, '/cert/edit');
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
a {
|
|
3
|
+
text-decoration: none;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
* {
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
form {
|
|
12
|
+
display: block;
|
|
13
|
+
max-height: 100%;
|
|
14
|
+
width: 100%;
|
|
15
|
+
|
|
16
|
+
>[body] {
|
|
17
|
+
height: auto;
|
|
18
|
+
height: 100%;
|
|
19
|
+
overflow-x: hidden;
|
|
20
|
+
overflow-y: scroll;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
:root {
|
|
25
|
+
height: 100%;
|
|
26
|
+
overflow: auto;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
[type=function] {
|
|
30
|
+
display: -webkit-box;
|
|
31
|
+
-webkit-box-orient: vertical;
|
|
32
|
+
-webkit-line-clamp: 2;
|
|
33
|
+
text-overflow: ellipsis;
|
|
34
|
+
overflow: hidden;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[info] {
|
|
38
|
+
text-align: center;
|
|
39
|
+
background: #ffe;
|
|
40
|
+
padding: 2px 20px;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
[body] {
|
|
45
|
+
appearance: none;
|
|
46
|
+
border: none;
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
49
|
+
<div -if="!enabled"></div>
|
|
50
|
+
<form on-submit="nosubmit" renderid=box>
|
|
51
|
+
<xmenu head #menubar -src="(m,i) in menus" @active="activeMenu(m,i)"></xmenu>
|
|
52
|
+
<div body #body>
|
|
53
|
+
<div info>${i18n`本页使用的证书服务来自`}<a target="_blank" href="${i18n`https://letsencrypt.org/zh-cn/`}">Let's
|
|
54
|
+
Encrypt</a>
|
|
55
|
+
</div>
|
|
56
|
+
<field -repeat="s in actived.fields" -src="[s,formdata]"></field>
|
|
57
|
+
<container -if="actived.src" _src="actived.src" _params="actived.params">
|
|
58
|
+
</container>
|
|
59
|
+
</div>
|
|
60
|
+
<scrollbar y #bar></scrollbar>
|
|
61
|
+
<div foot>
|
|
62
|
+
<span -bind="actived.message"></span>
|
|
63
|
+
<button -repeat="(f,k) in actived.actions" -click="f(actived)"><span -bind="k"></span></button>
|
|
64
|
+
</div>
|
|
65
|
+
</form>
|
|
66
|
+
<script>
|
|
67
|
+
var enabled = acme2.enabled;
|
|
68
|
+
if (!enabled) return ["请在支持window.crypto.subtle的浏览器上使用此页面的功能"];
|
|
69
|
+
var form = view;
|
|
70
|
+
var activeIndex = 0;
|
|
71
|
+
var nosubmit = e => e.preventDefault();
|
|
72
|
+
var directory;
|
|
73
|
+
var formdata = {};
|
|
74
|
+
var private_key, public_key;
|
|
75
|
+
var unique;
|
|
76
|
+
var loadUnique = async function () {
|
|
77
|
+
unique = await data.from("unique");
|
|
78
|
+
await acme2.makeUnique(unique);
|
|
79
|
+
if (menuIndex === 0) {
|
|
80
|
+
if (acme2.orders?.length) activeMenu(menus[2], 2);
|
|
81
|
+
else if (acme2.kid) activeMenu(menus[1], 1);
|
|
82
|
+
}
|
|
83
|
+
extend(formdata, acme2);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
var publicKey, privateKey;
|
|
87
|
+
loadUnique().then(render.digest).then(lazy(async function () {
|
|
88
|
+
box.reshape();
|
|
89
|
+
bar.reshape();
|
|
90
|
+
var certlist = await plist.load('cert');
|
|
91
|
+
formdata.domain = certlist.map(c => c.hostname).join("\r\n");
|
|
92
|
+
render.digest();
|
|
93
|
+
}));
|
|
94
|
+
var a = button;
|
|
95
|
+
var xmenu = menu;
|
|
96
|
+
var that = this;
|
|
97
|
+
|
|
98
|
+
var saveUnique = async function (params) {
|
|
99
|
+
extendIfOccurs(acme2, params);
|
|
100
|
+
var extra = acme2.pickUnique();
|
|
101
|
+
await data.from("unique-save", { data: extra });
|
|
102
|
+
};
|
|
103
|
+
var openOrder = async function (event, href) {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
}
|
|
106
|
+
var menus = [
|
|
107
|
+
{
|
|
108
|
+
"name": "创建账户",
|
|
109
|
+
fields: refilm`
|
|
110
|
+
$公钥/public_key/单击生成 ${function (elem) {
|
|
111
|
+
var { data, field } = elem;
|
|
112
|
+
elem.innerHTML = `<a @click="gen()" -if="!data[field.key]">单击生成</a><span -else -bind="data[field.key]"></span>`;
|
|
113
|
+
render(elem, {
|
|
114
|
+
data, field, async gen() {
|
|
115
|
+
await acme2.initUnique();
|
|
116
|
+
formdata.public_key = acme2.public_key;
|
|
117
|
+
await saveUnique();
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
}}
|
|
121
|
+
*邮箱/email email
|
|
122
|
+
/termsOfServiceAgreed/同意 checker ${{
|
|
123
|
+
async"《服务条款》"(data) {
|
|
124
|
+
var termsOfService = await acme2.getTermsOfService();
|
|
125
|
+
if (termsOfService) window.open(termsOfService, "_blank", "popup,noopener,noreferer")
|
|
126
|
+
},
|
|
127
|
+
}}
|
|
128
|
+
`,
|
|
129
|
+
get message() {
|
|
130
|
+
return formdata.kid ? "已创建账户" : '';
|
|
131
|
+
},
|
|
132
|
+
actions: {
|
|
133
|
+
async 创建账户(actived) {
|
|
134
|
+
var params = submit(actived.fields, formdata);
|
|
135
|
+
await saveUnique(params);
|
|
136
|
+
formdata.kid = await acme2.newAccount(params);
|
|
137
|
+
await saveUnique();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "创建订单",
|
|
143
|
+
get disabled() {
|
|
144
|
+
return !!formdata.kid;
|
|
145
|
+
},
|
|
146
|
+
fields: refilm`
|
|
147
|
+
$账户/kid input
|
|
148
|
+
*当前服务器的域名/domain/每行一个 text
|
|
149
|
+
`,
|
|
150
|
+
actions: {
|
|
151
|
+
async 创建订单(actived) {
|
|
152
|
+
var params = submit(actived.fields, formdata);
|
|
153
|
+
var order = await acme2.newOrder(params);
|
|
154
|
+
await saveUnique();
|
|
155
|
+
activeMenu(menus[2], 2);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "订单信息",
|
|
161
|
+
src: '/cert/orders',
|
|
162
|
+
get params() {
|
|
163
|
+
return { orders: acme2.orders, saveUnique };
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "证书列表",
|
|
168
|
+
src: "/cert/list",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "更新服务",
|
|
172
|
+
src: "/cert/update",
|
|
173
|
+
}
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
var actived = null;
|
|
177
|
+
var activeMenu = function (m, i) {
|
|
178
|
+
if (actived === m) return;
|
|
179
|
+
if (actived) actived.actived = false;
|
|
180
|
+
m.actived = true;
|
|
181
|
+
actived = m;
|
|
182
|
+
activeIndex = i;
|
|
183
|
+
state({ index: i })
|
|
184
|
+
};
|
|
185
|
+
var menuIndex = state().index || 0;
|
|
186
|
+
activeMenu(menus[menuIndex], menuIndex);
|
|
187
|
+
|
|
188
|
+
</script>
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
<style>
|
|
2
|
+
&>list,
|
|
3
|
+
&>div {
|
|
4
|
+
display: inline-block;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
& {
|
|
8
|
+
--border: 1px solid #0006;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&>xmenu[horizonal] {
|
|
12
|
+
width: 100%;
|
|
13
|
+
margin-bottom: -2px;
|
|
14
|
+
z-index: 1;
|
|
15
|
+
border-bottom: none;
|
|
16
|
+
box-shadow: none;
|
|
17
|
+
|
|
18
|
+
&:after {
|
|
19
|
+
content: "";
|
|
20
|
+
display: block;
|
|
21
|
+
position: absolute;
|
|
22
|
+
left: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
right: 0;
|
|
25
|
+
height: 0;
|
|
26
|
+
border-bottom: --border;
|
|
27
|
+
z-index: -1;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.actived {
|
|
31
|
+
background: #fff;
|
|
32
|
+
color: #333;
|
|
33
|
+
border: --border;
|
|
34
|
+
border-bottom: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
+form {
|
|
38
|
+
border: --border;
|
|
39
|
+
background: #fff;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[actived] {
|
|
44
|
+
background: #fff;
|
|
45
|
+
/* border-bottom: 2px solid; */
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
[status]>s {
|
|
49
|
+
width: 0;
|
|
50
|
+
height: 0;
|
|
51
|
+
border-radius: 50%;
|
|
52
|
+
display: inline-block;
|
|
53
|
+
border: .3em solid;
|
|
54
|
+
margin-right: 6px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@status(@s, @c) {
|
|
58
|
+
[status=@s] {
|
|
59
|
+
color: @c;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@status(pending, #777);
|
|
64
|
+
@status(processing, #f82);
|
|
65
|
+
@status(ready, #284);
|
|
66
|
+
@status(valid, #26c);
|
|
67
|
+
@status(invalid, #c24);
|
|
68
|
+
</style>
|
|
69
|
+
<xmenu -src="o of orders" @active="openOrder(o)"></xmenu>
|
|
70
|
+
<div -if="!order">
|
|
71
|
+
暂无订单
|
|
72
|
+
</div>
|
|
73
|
+
<form -elseif="order.oid" onsubmit="event.preventDefault()">
|
|
74
|
+
<div body>
|
|
75
|
+
<field -repeat="f in fields" _src="[f,order]"></field>
|
|
76
|
+
</div>
|
|
77
|
+
<div foot>
|
|
78
|
+
<button -if="order?.removable" class="danger" confirm @click="dropOrder(order)">删除订单</button>
|
|
79
|
+
<button -if="order.status==='processing'" @click="openOrder(order)">刷新</button>
|
|
80
|
+
<button -if="order.status==='pending'" @click="auditOrder(order)">提交审核</button>
|
|
81
|
+
<button -if="order.status==='ready'" @click="finalize(order)">请求证书</button>
|
|
82
|
+
<button -if="order.status==='valid'" @click="see(order)">查看证书</button>
|
|
83
|
+
<button -if="order.shouldupload" @click="upload(order)">上传到服务器</button>
|
|
84
|
+
</div>
|
|
85
|
+
</form>
|
|
86
|
+
<div -else>
|
|
87
|
+
订单异常
|
|
88
|
+
</div>
|
|
89
|
+
<script>
|
|
90
|
+
var fields = refilm`
|
|
91
|
+
$状态/status radio [未审核/pending,审核通过/ready,生成中/processing,生效/valid,无效/invalid]
|
|
92
|
+
$证书/certificate/下载 anchor
|
|
93
|
+
$域名/identifiers ${function (elem) {
|
|
94
|
+
var { field, data } = elem;
|
|
95
|
+
var value = data[field.key];
|
|
96
|
+
if (value instanceof Array) elem.innerHTML = value.map(v => `${v.value} (${v.type})`).join("<br/>")
|
|
97
|
+
else elem.innerHTML = '';
|
|
98
|
+
}}
|
|
99
|
+
$订单失效时间/expires ${function (elem) {
|
|
100
|
+
var { field, data } = elem;
|
|
101
|
+
elem.innerHTML = filterTime(data[field.key]);
|
|
102
|
+
}}
|
|
103
|
+
`;
|
|
104
|
+
var order = {
|
|
105
|
+
authorizations: [],
|
|
106
|
+
expires: NaN,
|
|
107
|
+
finalize: '',
|
|
108
|
+
identifiers: [],
|
|
109
|
+
status: ''
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
function main(params) {
|
|
113
|
+
var { orders = [], saveUnique } = params;
|
|
114
|
+
orders = orders.map(acme2.parseOrder);
|
|
115
|
+
if (orders.length) orders[0].actived = true;
|
|
116
|
+
var page = document.createElement('orders');
|
|
117
|
+
page.innerHTML = template;
|
|
118
|
+
var scope = {
|
|
119
|
+
fields,
|
|
120
|
+
form: view,
|
|
121
|
+
xmenu: menu,
|
|
122
|
+
orders,
|
|
123
|
+
order: null,
|
|
124
|
+
async openOrder(o) {
|
|
125
|
+
o = this.order = shallowClone(o);
|
|
126
|
+
if (!o || !o.oid) return;
|
|
127
|
+
var order = await acme2.getOrder(o);
|
|
128
|
+
extend(o, order);
|
|
129
|
+
if (o !== this.order) return;
|
|
130
|
+
if (o.certificate && !o.shouldupload) {
|
|
131
|
+
var identifiers = o.identifiers;
|
|
132
|
+
var d = await pedit.query("cert", identifiers[identifiers.length - 1].value);
|
|
133
|
+
if (d && d.oid === o.oid && !d.cert) {
|
|
134
|
+
o.shouldupload = true;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
o.removable = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (o.status === 'invalid') {
|
|
141
|
+
o.removable = true;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
if (o.certificate && +o.expires < Date.now()) {
|
|
145
|
+
o.removable = true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
this.order = shallowClone(o);
|
|
149
|
+
},
|
|
150
|
+
async auditOrder(o) {
|
|
151
|
+
a: for (var a of o.authorizations) {
|
|
152
|
+
var b = await acme2.audit(a);
|
|
153
|
+
if (b.challenges) {
|
|
154
|
+
for (var c of b.challenges) {
|
|
155
|
+
if (c.type === 'http-01') {
|
|
156
|
+
if (c.status !== 'pending') continue a;
|
|
157
|
+
await data.from("setauth", { token: c.token, thumb: await acme2.thumbprint() });
|
|
158
|
+
await acme2.requestURL(c.url, {});
|
|
159
|
+
continue a;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
alert("无法找到可用的提审方案" + b.identifier?.value, 'warn');
|
|
164
|
+
}
|
|
165
|
+
await wait(600);
|
|
166
|
+
if (this.order === o) await this.openOrder(this.order);
|
|
167
|
+
},
|
|
168
|
+
async finalize(o) {
|
|
169
|
+
var domains = o.identifiers.map(d => d.value);
|
|
170
|
+
var kp = await acme2.createKeyPair();
|
|
171
|
+
var csr = await acme2.createCSR(domains, kp[0]);
|
|
172
|
+
var order = await acme2.requestURL(o.finalize, { csr });
|
|
173
|
+
order = extend({}, o, order);
|
|
174
|
+
if (o === this.order) o = this.order = order;
|
|
175
|
+
render.digest();
|
|
176
|
+
await wait(600);
|
|
177
|
+
var order = await acme2.getOrder(o);
|
|
178
|
+
var cert = order.certificate;
|
|
179
|
+
if (!cert) {
|
|
180
|
+
order.shouldupload = true;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
cert = await data.fromURL(cert);
|
|
184
|
+
}
|
|
185
|
+
for (var d of domains) {
|
|
186
|
+
pedit.update("cert", d, { hostname: d, private: kp[0], public: kp[1], cert, oid: o.oid })
|
|
187
|
+
}
|
|
188
|
+
if (this.order === o) this.order = extend({}, o, order);
|
|
189
|
+
},
|
|
190
|
+
async dropOrder(o) {
|
|
191
|
+
for (var cx = 0, dx = orders.length; cx < dx; cx++) {
|
|
192
|
+
if (orders[cx].oid === o.oid) break;
|
|
193
|
+
};
|
|
194
|
+
if (cx < 0) return;
|
|
195
|
+
orders.splice(cx, 1);
|
|
196
|
+
acme2.orders.splice(cx, 1);
|
|
197
|
+
if (cx >= orders.length) cx = orders.length - 1;
|
|
198
|
+
await saveUnique();
|
|
199
|
+
this.openOrder(orders[cx]);
|
|
200
|
+
},
|
|
201
|
+
async see(o) {
|
|
202
|
+
var content = `<div head>${o.identifiers.map(d => d.value).join(', ')}<close @click=remove()></close></div><loading -if='cert.loading'></loading><div body style='font-size:10px;font-family:Consolas, "Courier New", monospace;white-space:pre;' -bind='cert.data'></div><scrollbar y></scrollbar>`;
|
|
203
|
+
var e = view();
|
|
204
|
+
css(e, 'position:absolute;width:366px;');
|
|
205
|
+
e.innerHTML = content;
|
|
206
|
+
drag.on(e.firstElementChild, e);
|
|
207
|
+
resize.on(e);
|
|
208
|
+
renderWithDefaults(e, {
|
|
209
|
+
cert: data.fromURL(o.certificate),
|
|
210
|
+
scrollbar,
|
|
211
|
+
remove() {
|
|
212
|
+
remove(e);
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
popup(e);
|
|
216
|
+
move.setPosition(e, [.5, .5]);
|
|
217
|
+
},
|
|
218
|
+
async upload(o) {
|
|
219
|
+
var cert = await data.fromURL(o.certificate);
|
|
220
|
+
for (var d of o.identifiers) {
|
|
221
|
+
await pedit.merge("cert", d.value, { cert });
|
|
222
|
+
}
|
|
223
|
+
o.shouldupload = false;
|
|
224
|
+
o.removable = true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
renderWithDefaults(page, scope);
|
|
228
|
+
if (orders.length) scope.openOrder(orders[0]).then(render.digest);
|
|
229
|
+
|
|
230
|
+
return page;
|
|
231
|
+
}
|
|
232
|
+
</script>
|
package/apps/pivot/menu.yml
CHANGED
package/coms/basic/assert.js
CHANGED
|
@@ -1,18 +1,42 @@
|
|
|
1
1
|
var mark = require("./mark");
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
var format = console.format, clog = console.log;
|
|
3
|
+
if (!format) format = a => a, clog = function () {
|
|
4
|
+
var args = [];
|
|
5
|
+
var colors = {
|
|
6
|
+
green: 'color:green;',
|
|
7
|
+
gray: "color:gray;",
|
|
8
|
+
red2: "color:red;",
|
|
9
|
+
bgblue: 'background-color:blue;',
|
|
10
|
+
bgred: 'background-color:red;',
|
|
11
|
+
cyan: 'color:#29c;',
|
|
12
|
+
reset: 'color:;background-color:;',
|
|
13
|
+
}
|
|
14
|
+
for (var a of arguments) {
|
|
15
|
+
if (typeof a === "string") {
|
|
16
|
+
var tags = [];
|
|
17
|
+
a = renderTags(a, function (tag, e) {
|
|
18
|
+
var c = tag ? colors[tag] : colors.reset;
|
|
19
|
+
if (c) {
|
|
20
|
+
if (e !== false) tags.push(c);
|
|
21
|
+
return '%c'
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
});
|
|
25
|
+
args.push(a, ...tags);
|
|
26
|
+
}
|
|
27
|
+
else args.push(a);
|
|
28
|
+
}
|
|
29
|
+
console.log(...args);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
var gray = format('<gray>;</gray>').split(';');
|
|
34
|
+
var green = format('<green>;</green>').split(';');
|
|
35
|
+
var crack = format('<red2>;</red2>').split(';');
|
|
12
36
|
var dump = function (a, msg) {
|
|
13
|
-
if (a instanceof Object) console.error(i18n`属性错误`),
|
|
14
|
-
else if (msg)
|
|
15
|
-
else
|
|
37
|
+
if (a instanceof Object) console.error(i18n`属性错误`), clog(msg ? msg + " " : " {\r\n", Object.keys(a).map(k => ` ${k}${gray.join(':')}\r\n ${a[k]}`).join('\r\n') + "\r\n }");
|
|
38
|
+
else if (msg) clog(msg + ":", a);
|
|
39
|
+
else clog(a);
|
|
16
40
|
};
|
|
17
41
|
var colorString = function (s, color1, e, color2) {
|
|
18
42
|
s = String(s);
|
|
@@ -35,9 +59,9 @@ var assert = function (result, expect, log = dump) {
|
|
|
35
59
|
errors = `结果 (${args}) 应为 ${JSON.stringify(k)}`;
|
|
36
60
|
}
|
|
37
61
|
if (k === undefined) return function () {
|
|
38
|
-
var color1 =
|
|
39
|
-
var color2 =
|
|
40
|
-
var color3 =
|
|
62
|
+
var color1 = format("<bgred>; </bgred>").split(";");
|
|
63
|
+
var color2 = format("<bgblue>; </bgblue>").split(";");
|
|
64
|
+
var color3 = format("<cyan>;</cyan>").split(";");
|
|
41
65
|
mark.setTag1(color1[1], color1[0]);
|
|
42
66
|
mark.setTag2(color2[1], color2[0]);
|
|
43
67
|
var [r, e] = mark.pair(result, expect);
|