efront 4.5.0 → 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 +30 -0
- package/apps/pivot/api.yml +1 -0
- package/apps/pivot/cert/edit.js +1 -0
- package/apps/pivot/cert/list.js +9 -0
- package/apps/pivot/cert/main.xht +25 -18
- package/apps/pivot/cert/orders.xht +105 -17
- package/apps/pivot/cert/update.xht +7 -0
- package/coms/basic/cross_.js +2 -1
- package/coms/basic/valid.js +4 -2
- package/coms/compile/Javascript.js +25 -12
- package/coms/frame/edit.html +1 -0
- package/coms/frame/edit.js +3 -2
- package/coms/pivot/acme2.js +134 -29
- package/coms/pivot/pedit.js +13 -5
- package/coms/pivot/plist.js +12 -5
- package/coms/zimoli/button.less +1 -0
- package/coms/zimoli/container.js +8 -1
- package/coms/zimoli/data.js +64 -127
- package/coms/zimoli/list.js +2 -2
- package/coms/zimoli/model.js +20 -3
- package/coms/zimoli/scrollbar.js +2 -0
- package/coms/zimoli/view.js +10 -7
- package/coms/zimoli/view.less +1 -1
- package/coms/zimoli/watch.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,33 @@
|
|
|
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
|
+
|
|
1
31
|
- zh-CN: 请求无效!
|
|
2
32
|
en: Request is invalid!
|
|
3
33
|
|
package/apps/pivot/api.yml
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
setauth|: options ::setauth-/.well-known/acme-challenge/:token?:token.:thumb
|
|
22
22
|
unique: options ::unique
|
|
23
23
|
unique-save: options ::unique-:data
|
|
24
|
+
recert: options ::recert
|
|
24
25
|
upload: put :path
|
|
25
26
|
https://www.ip.cn/:
|
|
26
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');
|
package/apps/pivot/cert/main.xht
CHANGED
|
@@ -46,10 +46,8 @@
|
|
|
46
46
|
border: none;
|
|
47
47
|
}
|
|
48
48
|
</style>
|
|
49
|
-
<div -if="!enabled">
|
|
50
|
-
|
|
51
|
-
</div>
|
|
52
|
-
<form on-submit="nosubmit" #box>
|
|
49
|
+
<div -if="!enabled"></div>
|
|
50
|
+
<form on-submit="nosubmit" renderid=box>
|
|
53
51
|
<xmenu head #menubar -src="(m,i) in menus" @active="activeMenu(m,i)"></xmenu>
|
|
54
52
|
<div body #body>
|
|
55
53
|
<div info>${i18n`本页使用的证书服务来自`}<a target="_blank" href="${i18n`https://letsencrypt.org/zh-cn/`}">Let's
|
|
@@ -66,9 +64,8 @@
|
|
|
66
64
|
</div>
|
|
67
65
|
</form>
|
|
68
66
|
<script>
|
|
69
|
-
var subtle = window.crypto?.subtle;
|
|
70
67
|
var enabled = acme2.enabled;
|
|
71
|
-
if (!enabled) return;
|
|
68
|
+
if (!enabled) return ["请在支持window.crypto.subtle的浏览器上使用此页面的功能"];
|
|
72
69
|
var form = view;
|
|
73
70
|
var activeIndex = 0;
|
|
74
71
|
var nosubmit = e => e.preventDefault();
|
|
@@ -79,14 +76,20 @@
|
|
|
79
76
|
var loadUnique = async function () {
|
|
80
77
|
unique = await data.from("unique");
|
|
81
78
|
await acme2.makeUnique(unique);
|
|
82
|
-
if (
|
|
83
|
-
|
|
79
|
+
if (menuIndex === 0) {
|
|
80
|
+
if (acme2.orders?.length) activeMenu(menus[2], 2);
|
|
81
|
+
else if (acme2.kid) activeMenu(menus[1], 1);
|
|
82
|
+
}
|
|
84
83
|
extend(formdata, acme2);
|
|
85
84
|
};
|
|
85
|
+
|
|
86
86
|
var publicKey, privateKey;
|
|
87
|
-
loadUnique().then(render.digest).then(lazy(function () {
|
|
87
|
+
loadUnique().then(render.digest).then(lazy(async function () {
|
|
88
88
|
box.reshape();
|
|
89
89
|
bar.reshape();
|
|
90
|
+
var certlist = await plist.load('cert');
|
|
91
|
+
formdata.domain = certlist.map(c => c.hostname).join("\r\n");
|
|
92
|
+
render.digest();
|
|
90
93
|
}));
|
|
91
94
|
var a = button;
|
|
92
95
|
var xmenu = menu;
|
|
@@ -114,7 +117,7 @@
|
|
|
114
117
|
await saveUnique();
|
|
115
118
|
}
|
|
116
119
|
})
|
|
117
|
-
}}
|
|
120
|
+
}}
|
|
118
121
|
*邮箱/email email
|
|
119
122
|
/termsOfServiceAgreed/同意 checker ${{
|
|
120
123
|
async"《服务条款》"(data) {
|
|
@@ -148,7 +151,6 @@
|
|
|
148
151
|
async 创建订单(actived) {
|
|
149
152
|
var params = submit(actived.fields, formdata);
|
|
150
153
|
var order = await acme2.newOrder(params);
|
|
151
|
-
formdata.orders = acme2.orders;
|
|
152
154
|
await saveUnique();
|
|
153
155
|
activeMenu(menus[2], 2);
|
|
154
156
|
}
|
|
@@ -158,8 +160,16 @@
|
|
|
158
160
|
name: "订单信息",
|
|
159
161
|
src: '/cert/orders',
|
|
160
162
|
get params() {
|
|
161
|
-
return
|
|
163
|
+
return { orders: acme2.orders, saveUnique };
|
|
162
164
|
}
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "证书列表",
|
|
168
|
+
src: "/cert/list",
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: "更新服务",
|
|
172
|
+
src: "/cert/update",
|
|
163
173
|
}
|
|
164
174
|
];
|
|
165
175
|
|
|
@@ -170,12 +180,9 @@
|
|
|
170
180
|
m.actived = true;
|
|
171
181
|
actived = m;
|
|
172
182
|
activeIndex = i;
|
|
183
|
+
state({ index: i })
|
|
173
184
|
};
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
* 域名 / hostname input / 190
|
|
177
|
-
更新连接 / url text / 290
|
|
178
|
-
密码 / password input / 290
|
|
179
|
-
`, '/cert/edit');
|
|
185
|
+
var menuIndex = state().index || 0;
|
|
186
|
+
activeMenu(menus[menuIndex], menuIndex);
|
|
180
187
|
|
|
181
188
|
</script>
|
|
@@ -67,26 +67,36 @@
|
|
|
67
67
|
@status(invalid, #c24);
|
|
68
68
|
</style>
|
|
69
69
|
<xmenu -src="o of orders" @active="openOrder(o)"></xmenu>
|
|
70
|
-
<
|
|
70
|
+
<div -if="!order">
|
|
71
|
+
暂无订单
|
|
72
|
+
</div>
|
|
73
|
+
<form -elseif="order.oid" onsubmit="event.preventDefault()">
|
|
71
74
|
<div body>
|
|
72
75
|
<field -repeat="f in fields" _src="[f,order]"></field>
|
|
73
76
|
</div>
|
|
74
77
|
<div foot>
|
|
75
|
-
<button -if="order
|
|
76
|
-
<button -if="order.
|
|
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>
|
|
77
84
|
</div>
|
|
78
85
|
</form>
|
|
86
|
+
<div -else>
|
|
87
|
+
订单异常
|
|
88
|
+
</div>
|
|
79
89
|
<script>
|
|
80
90
|
var fields = refilm`
|
|
81
|
-
$状态/status radio [
|
|
82
|
-
$证书/certificate anchor
|
|
91
|
+
$状态/status radio [未审核/pending,审核通过/ready,生成中/processing,生效/valid,无效/invalid]
|
|
92
|
+
$证书/certificate/下载 anchor
|
|
83
93
|
$域名/identifiers ${function (elem) {
|
|
84
94
|
var { field, data } = elem;
|
|
85
95
|
var value = data[field.key];
|
|
86
96
|
if (value instanceof Array) elem.innerHTML = value.map(v => `${v.value} (${v.type})`).join("<br/>")
|
|
87
97
|
else elem.innerHTML = '';
|
|
88
98
|
}}
|
|
89
|
-
|
|
99
|
+
$订单失效时间/expires ${function (elem) {
|
|
90
100
|
var { field, data } = elem;
|
|
91
101
|
elem.innerHTML = filterTime(data[field.key]);
|
|
92
102
|
}}
|
|
@@ -100,9 +110,9 @@
|
|
|
100
110
|
};
|
|
101
111
|
|
|
102
112
|
function main(params) {
|
|
103
|
-
var orders =
|
|
113
|
+
var { orders = [], saveUnique } = params;
|
|
104
114
|
orders = orders.map(acme2.parseOrder);
|
|
105
|
-
orders[0].actived = true;
|
|
115
|
+
if (orders.length) orders[0].actived = true;
|
|
106
116
|
var page = document.createElement('orders');
|
|
107
117
|
page.innerHTML = template;
|
|
108
118
|
var scope = {
|
|
@@ -112,28 +122,106 @@
|
|
|
112
122
|
orders,
|
|
113
123
|
order: null,
|
|
114
124
|
async openOrder(o) {
|
|
115
|
-
this.order = o;
|
|
116
|
-
if (!o.oid) return;
|
|
117
|
-
var order = await acme2.getOrder(
|
|
125
|
+
o = this.order = shallowClone(o);
|
|
126
|
+
if (!o || !o.oid) return;
|
|
127
|
+
var order = await acme2.getOrder(o);
|
|
118
128
|
extend(o, order);
|
|
119
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
|
+
}
|
|
120
148
|
this.order = shallowClone(o);
|
|
121
149
|
},
|
|
122
150
|
async auditOrder(o) {
|
|
123
151
|
a: for (var a of o.authorizations) {
|
|
124
|
-
var
|
|
125
|
-
if (
|
|
126
|
-
for (var c of
|
|
152
|
+
var b = await acme2.audit(a);
|
|
153
|
+
if (b.challenges) {
|
|
154
|
+
for (var c of b.challenges) {
|
|
127
155
|
if (c.type === 'http-01') {
|
|
156
|
+
if (c.status !== 'pending') continue a;
|
|
128
157
|
await data.from("setauth", { token: c.token, thumb: await acme2.thumbprint() });
|
|
129
|
-
await
|
|
158
|
+
await acme2.requestURL(c.url, {});
|
|
130
159
|
continue a;
|
|
131
160
|
}
|
|
132
161
|
}
|
|
133
162
|
}
|
|
134
|
-
alert("无法找到可用的提审方案" +
|
|
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 });
|
|
135
222
|
}
|
|
136
|
-
|
|
223
|
+
o.shouldupload = false;
|
|
224
|
+
o.removable = true;
|
|
137
225
|
}
|
|
138
226
|
}
|
|
139
227
|
renderWithDefaults(page, scope);
|
package/coms/basic/cross_.js
CHANGED
|
@@ -154,8 +154,9 @@ function cross_(jsonp, digest = noop, method, url, headers) {
|
|
|
154
154
|
if (e.type === 'error') {
|
|
155
155
|
e = createResponse("无法访问服务器!");
|
|
156
156
|
}
|
|
157
|
+
headers = extend({}, _headers);
|
|
157
158
|
for (var r of reforms) {
|
|
158
|
-
var r = await reform.call(xhr, r, { method, url, status: xhr.status, headers
|
|
159
|
+
var r = await reform.call(xhr, r, { method, url, status: xhr.status, headers }, fire, onerror1, e);
|
|
159
160
|
if (r === false) {
|
|
160
161
|
return;
|
|
161
162
|
}
|
package/coms/basic/valid.js
CHANGED
|
@@ -45,8 +45,10 @@ function valid(field, data) {
|
|
|
45
45
|
if (e) return e;
|
|
46
46
|
}
|
|
47
47
|
if (field.options instanceof Function) {
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
if (/^(input|text|html|password|raw)/.test(field.type)) {
|
|
49
|
+
var e = field.options(data[field.key]);
|
|
50
|
+
if (e) return e;
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
return error;
|
|
52
54
|
}
|
|
@@ -514,6 +514,11 @@ Javascript.prototype.detour = function (o, ie) {
|
|
|
514
514
|
context = null;
|
|
515
515
|
return envs;
|
|
516
516
|
}
|
|
517
|
+
var getfunc = function (o, k) {
|
|
518
|
+
var q = o.queue;
|
|
519
|
+
while (q && (!q.scoped || !q.scoped.used[k])) q = q.queue;
|
|
520
|
+
return q;
|
|
521
|
+
};
|
|
517
522
|
var context = null, rootenvs = null;
|
|
518
523
|
function detour(o, ie) {
|
|
519
524
|
while (o) {
|
|
@@ -528,21 +533,29 @@ function detour(o, ie) {
|
|
|
528
533
|
var m = /^[^\.\[\]]+/.exec(o.text);
|
|
529
534
|
if (m) { context.avoidMap[m[0]] = true; }
|
|
530
535
|
}
|
|
531
|
-
if (
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
rest.push(o);
|
|
540
|
-
}
|
|
541
|
-
text = createString(rest);
|
|
536
|
+
if (/\?\.|\?\?/.test(text)) {
|
|
537
|
+
o = snapExpressHead(o);
|
|
538
|
+
var f = snapExpressFoot(o);
|
|
539
|
+
var rest = [o];
|
|
540
|
+
remove(o, f.prev);
|
|
541
|
+
while (o !== f) {
|
|
542
|
+
o = o.next;
|
|
543
|
+
rest.push(o);
|
|
542
544
|
}
|
|
545
|
+
text = createString(rest);
|
|
543
546
|
text = renderExpress(text, false);
|
|
544
547
|
if (hasdot) text = "..." + text;
|
|
545
|
-
|
|
548
|
+
var o1 = scan(text);
|
|
549
|
+
var s1 = createScoped(o1);
|
|
550
|
+
if (s1.used.this) {
|
|
551
|
+
var s = getfunc(o, 'this').scoped;
|
|
552
|
+
s.used.this.push(...s1.used.this);
|
|
553
|
+
}
|
|
554
|
+
if (s1.used.arguments) {
|
|
555
|
+
var s = getfunc(o, 'arguments').scoped;
|
|
556
|
+
s.used.arguments.push(...s1.used.arguments);
|
|
557
|
+
};
|
|
558
|
+
o = replace(o, ...o1);
|
|
546
559
|
continue;
|
|
547
560
|
}
|
|
548
561
|
text = text.replace(/\.([^\.\[\!\=\:]+)/g, (_, a) => ie === undefined || context.strap_reg.test(a) || /#/.test(a) ? `[${strings.recode(a)}]` : _);
|
package/coms/frame/edit.html
CHANGED
package/coms/frame/edit.js
CHANGED
|
@@ -11,6 +11,7 @@ function main(title, { submit }, { data: origin, fields, }) {
|
|
|
11
11
|
fields,
|
|
12
12
|
title,
|
|
13
13
|
origin,
|
|
14
|
+
scrollbar,
|
|
14
15
|
data: item,
|
|
15
16
|
remove() {
|
|
16
17
|
remove(page);
|
|
@@ -19,7 +20,7 @@ function main(title, { submit }, { data: origin, fields, }) {
|
|
|
19
20
|
on('submit')(page, async function (e) {
|
|
20
21
|
e.preventDefault();
|
|
21
22
|
var res = await submit(item, fields, origin);
|
|
22
|
-
if (typeof res === 'string') {
|
|
23
|
+
if (typeof res === 'string' && res) {
|
|
23
24
|
return alert(res, 'error');
|
|
24
25
|
}
|
|
25
26
|
if (res === false) return;
|
|
@@ -31,7 +32,7 @@ function main(title, { submit }, { data: origin, fields, }) {
|
|
|
31
32
|
await submit(item, fields, origin);
|
|
32
33
|
dispatch(this, 'submited');
|
|
33
34
|
});
|
|
34
|
-
on("
|
|
35
|
+
on("mounted")(page, lazy(function () {
|
|
35
36
|
page.querySelector("input").focus();
|
|
36
37
|
}));
|
|
37
38
|
return page;
|