@supersoniks/concorde 3.1.58 → 3.1.59
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/build-infos.json +1 -1
- package/concorde-core.bundle.js +216 -186
- package/concorde-core.es.js +1491 -1408
- package/dist/concorde-core.bundle.js +216 -186
- package/dist/concorde-core.es.js +1491 -1408
- package/index.html +1 -1
- package/package.json +6 -2
- package/src/core/_types/types.ts +0 -5
- package/src/core/components/functional/list/list.ts +0 -0
- package/src/core/components/functional/queue/queue.ts +0 -0
- package/src/core/components/functional/submit/submit.ts +41 -34
- package/src/core/components/ui/badge/badge.ts +1 -1
- package/src/core/components/ui/captcha/captcha.md +13 -1
- package/src/core/components/ui/captcha/captcha.ts +96 -44
- package/src/core/mixins/Fetcher.ts +0 -0
- package/src/core/utils/aesCrypto.ts +129 -0
- package/src/tsconfig.json +3 -0
- package/src/tsconfig.tsbuildinfo +1 -1
- package/vite.config.mts +2 -0
- package/vite.config.mts.timestamp-1728318208370-f1724bcfd87d3.mjs +0 -85
package/index.html
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supersoniks/concorde",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.59",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "",
|
|
@@ -270,6 +270,7 @@
|
|
|
270
270
|
"./utils/Objects": "./src/core/utils/Objects.ts",
|
|
271
271
|
"./utils/PublisherProxy": "./src/core/utils/PublisherProxy.ts",
|
|
272
272
|
"./utils/Utils": "./src/core/utils/Utils.ts",
|
|
273
|
+
"./utils/aesCrypto": "./src/core/utils/aesCrypto.ts",
|
|
273
274
|
"./utils/api": "./src/core/utils/api.ts",
|
|
274
275
|
"./utils/route": "./src/core/utils/route.ts",
|
|
275
276
|
"./utils/url-pattern": "./src/core/utils/url-pattern.ts",
|
|
@@ -293,6 +294,8 @@
|
|
|
293
294
|
"@types/intl": "^1.2.2",
|
|
294
295
|
"@types/jest": "^29.5.12",
|
|
295
296
|
"@types/node": "^20.12.4",
|
|
297
|
+
"@vitejs/plugin-basic-ssl": "^1.2.0",
|
|
298
|
+
"altcha": "^1.0.7",
|
|
296
299
|
"autoprefixer": "^10.4.19",
|
|
297
300
|
"intl": "^1.2.5",
|
|
298
301
|
"lit": "^3.1.3",
|
|
@@ -309,5 +312,6 @@
|
|
|
309
312
|
"@lit-labs/motion": "^1.0.7",
|
|
310
313
|
"@lit-labs/observers": "^2.0.2",
|
|
311
314
|
"url-pattern": "^1.0.3"
|
|
312
|
-
}
|
|
315
|
+
},
|
|
316
|
+
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
|
313
317
|
}
|
package/src/core/_types/types.ts
CHANGED
|
@@ -14,11 +14,6 @@ export interface ConcordeWindow extends Window {
|
|
|
14
14
|
id: string;
|
|
15
15
|
password: string;
|
|
16
16
|
}) => Credential;
|
|
17
|
-
grecaptcha?: {
|
|
18
|
-
ready: (handler: () => void) => void;
|
|
19
|
-
reset: () => void;
|
|
20
|
-
execute: (key: string, options: { action: string }) => Promise<string>;
|
|
21
|
-
};
|
|
22
17
|
SonicModal: any;
|
|
23
18
|
SonicToast: any;
|
|
24
19
|
[key: string]: any;
|
|
File without changes
|
|
File without changes
|
|
@@ -63,8 +63,9 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
63
63
|
const form: HTMLFormElement = HTML.getClosestForm(this) as HTMLFormElement;
|
|
64
64
|
if (!form) return;
|
|
65
65
|
const formDataProvider = this.getAncestorAttributeValue("formDataProvider");
|
|
66
|
-
const
|
|
67
|
-
|
|
66
|
+
const dataToSend = { ...PublisherManager.get(formDataProvider).get() };
|
|
67
|
+
delete dataToSend.needsCaptchaValidation;
|
|
68
|
+
for (const name in dataToSend) {
|
|
68
69
|
if (name == "isFormValid") continue;
|
|
69
70
|
let control = form.querySelector(
|
|
70
71
|
'input[name="' +
|
|
@@ -82,7 +83,7 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
82
83
|
control.name = name;
|
|
83
84
|
form.appendChild(control);
|
|
84
85
|
}
|
|
85
|
-
let value =
|
|
86
|
+
let value = dataToSend[name];
|
|
86
87
|
if (Array.isArray(value)) value = value.join(",");
|
|
87
88
|
if (control.type === "checkbox" || control.type === "radio") {
|
|
88
89
|
if (value) (control as HTMLInputElement).checked = true;
|
|
@@ -100,12 +101,12 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
clickTimeStamp = 0;
|
|
103
|
-
submit = async (e?:Event)=> {
|
|
104
|
-
if(this.disabled) return;
|
|
104
|
+
submit = async (e?: Event) => {
|
|
105
|
+
if (this.disabled) return;
|
|
105
106
|
|
|
106
|
-
if(e instanceof KeyboardEvent && !(e.key === "Enter")) return;
|
|
107
|
-
if(e instanceof MouseEvent) {
|
|
108
|
-
e.stopPropagation();
|
|
107
|
+
if (e instanceof KeyboardEvent && !(e.key === "Enter")) return;
|
|
108
|
+
if (e instanceof MouseEvent) {
|
|
109
|
+
e.stopPropagation();
|
|
109
110
|
}
|
|
110
111
|
const formPublisher = PublisherManager.getInstance().get(
|
|
111
112
|
this.getAncestorAttributeValue("formDataProvider")
|
|
@@ -116,6 +117,7 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
116
117
|
formPublisher.invalidateForm();
|
|
117
118
|
if (!formPublisher.isFormValid.get()) return;
|
|
118
119
|
this.disabled = true;
|
|
120
|
+
Loader.show();
|
|
119
121
|
formPublisher.isFormValid;
|
|
120
122
|
// support native html form
|
|
121
123
|
const native = this.hasAttribute("native");
|
|
@@ -136,47 +138,49 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
136
138
|
const headerPublisher = headesDataProvider
|
|
137
139
|
? PublisherManager.getInstance().get(headesDataProvider)
|
|
138
140
|
: null;
|
|
139
|
-
let headerData = {};
|
|
141
|
+
let headerData: any = {};
|
|
140
142
|
if (headerPublisher) headerData = headerPublisher.get();
|
|
141
143
|
let result: SubmitResult = null;
|
|
142
144
|
const dataProvider = this.getAncestorAttributeValue("dataProvider");
|
|
143
145
|
const endPoint = this.endPoint || dataProvider;
|
|
144
|
-
Loader.show();
|
|
145
146
|
|
|
146
147
|
const sendData = async () => {
|
|
148
|
+
const dataToSend = { ...formData };
|
|
149
|
+
delete dataToSend.needsCaptchaValidation;
|
|
150
|
+
delete headerData.needsCaptchaValidation;
|
|
147
151
|
//
|
|
148
152
|
//envoi données
|
|
149
153
|
if (sendAsFormData) {
|
|
150
154
|
result = await this.api?.submitFormData(
|
|
151
155
|
endPoint,
|
|
152
|
-
|
|
156
|
+
dataToSend,
|
|
153
157
|
method,
|
|
154
158
|
headerData
|
|
155
159
|
);
|
|
156
160
|
} else {
|
|
157
161
|
switch (method) {
|
|
158
162
|
case "put":
|
|
159
|
-
result = await this.api?.put(endPoint,
|
|
163
|
+
result = await this.api?.put(endPoint, dataToSend, headerData);
|
|
160
164
|
break;
|
|
161
165
|
case "patch":
|
|
162
|
-
result = await this.api?.patch(endPoint,
|
|
166
|
+
result = await this.api?.patch(endPoint, dataToSend, headerData);
|
|
163
167
|
break;
|
|
164
168
|
case "delete":
|
|
165
|
-
result = await this.api?.delete(endPoint,
|
|
169
|
+
result = await this.api?.delete(endPoint, dataToSend, headerData);
|
|
166
170
|
break;
|
|
167
171
|
case "get":
|
|
168
|
-
// add
|
|
172
|
+
// add dataToSend to endpoint
|
|
169
173
|
const params = new URLSearchParams();
|
|
170
|
-
if (
|
|
171
|
-
for (const key in
|
|
172
|
-
params.append(key,
|
|
174
|
+
if (dataToSend) {
|
|
175
|
+
for (const key in dataToSend) {
|
|
176
|
+
params.append(key, dataToSend[key]);
|
|
173
177
|
}
|
|
174
178
|
}
|
|
175
179
|
const paramString = "?" + params.toString();
|
|
176
180
|
result = await this.api?.get(endPoint + paramString, headerData);
|
|
177
181
|
break;
|
|
178
182
|
default:
|
|
179
|
-
result = await this.api?.post(endPoint,
|
|
183
|
+
result = await this.api?.post(endPoint, dataToSend, headerData);
|
|
180
184
|
break;
|
|
181
185
|
}
|
|
182
186
|
}
|
|
@@ -211,10 +215,13 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
211
215
|
: "password";
|
|
212
216
|
if (
|
|
213
217
|
this.api?.lastResult?.ok &&
|
|
214
|
-
|
|
215
|
-
|
|
218
|
+
dataToSend[username_key] &&
|
|
219
|
+
dataToSend[password_key]
|
|
216
220
|
) {
|
|
217
|
-
this.saveCredentials(
|
|
221
|
+
this.saveCredentials(
|
|
222
|
+
dataToSend[username_key],
|
|
223
|
+
dataToSend[password_key]
|
|
224
|
+
);
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
if (this.submitResultKey) {
|
|
@@ -241,31 +248,31 @@ export class Submit extends Subscriber(LitElement) {
|
|
|
241
248
|
})
|
|
242
249
|
);
|
|
243
250
|
};
|
|
244
|
-
const captchaPublisher =
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
251
|
+
const captchaPublisher =
|
|
252
|
+
// TODO Comprendre pourquoi header publisher
|
|
253
|
+
headerPublisher?.needsCaptchaValidation.get()
|
|
254
|
+
? headerPublisher
|
|
255
|
+
: formPublisher.needsCaptchaValidation.get()
|
|
256
|
+
? formPublisher
|
|
257
|
+
: null;
|
|
249
258
|
if (captchaPublisher) {
|
|
250
|
-
captchaPublisher.captchaMethod = method;
|
|
251
|
-
captchaPublisher.captchaAction =
|
|
252
|
-
dataProvider?.split("?")[0] ??
|
|
253
|
-
this.getAncestorAttributeValue("formDataProvider") ??
|
|
254
|
-
"submit";
|
|
255
259
|
captchaPublisher.captchaToken = "request_token";
|
|
256
260
|
const captchaAssign = (token?: string) => {
|
|
257
|
-
if (token
|
|
261
|
+
if (token != "request_token") {
|
|
258
262
|
sendData();
|
|
259
263
|
// Après l'envoie des données, on supprime ce onAssign.
|
|
260
264
|
// Sinon les handler se cumuleraient après plusieurs submit consécutifs.
|
|
261
265
|
captchaPublisher.captchaToken.offAssign(captchaAssign);
|
|
266
|
+
} else {
|
|
267
|
+
Loader.hide();
|
|
268
|
+
this.disabled = false;
|
|
262
269
|
}
|
|
263
270
|
};
|
|
264
271
|
captchaPublisher.captchaToken.onAssign(captchaAssign);
|
|
265
272
|
} else {
|
|
266
273
|
sendData();
|
|
267
274
|
}
|
|
268
|
-
}
|
|
275
|
+
};
|
|
269
276
|
|
|
270
277
|
async saveCredentials(username: string, password: string) {
|
|
271
278
|
// Check if the browser supports password credentials (and the Credential Management API)
|
|
@@ -60,7 +60,7 @@ export class Badge extends LitElement {
|
|
|
60
60
|
:host([type="primary"]) {
|
|
61
61
|
--sc-badge-color: var(--sc-primary-content, var(--sc-base, #fff));
|
|
62
62
|
--sc-badge-bg: var(--sc-primary, var(--sc-base-content, #000));
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
64
|
:host([type="warning"]) {
|
|
65
65
|
--sc-badge-color: var(--sc-warning-content, var(--sc-base, #fff));
|
|
66
66
|
--sc-badge-bg: var(--sc-warning, var(--sc-base-content, #000));
|
|
@@ -4,7 +4,19 @@
|
|
|
4
4
|
<template>
|
|
5
5
|
<sonic-captcha formDataProvider="captchaTestDataProvider" key="6Leq5V0iAAAAAB-41DlWN335jDlcIuXmhNtdd00t">
|
|
6
6
|
<sonic-submit serviceURL="https://reqres.in" endPoint="api/unknown" onclick>
|
|
7
|
-
<sonic-button>Submit with captcha</sonic-button>
|
|
7
|
+
<sonic-button class="mt-4">Submit with captcha</sonic-button>
|
|
8
|
+
</sonic-submit>
|
|
9
|
+
</sonic-captcha>
|
|
10
|
+
</template>
|
|
11
|
+
</sonic-code>
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
<sonic-code>
|
|
16
|
+
<template>
|
|
17
|
+
<sonic-captcha formDataProvider="captchaTestDataProvider">
|
|
18
|
+
<sonic-submit serviceURL="https://atelier.julien.supersoniks.pro" endPoint="php/some-service.php" onclick>
|
|
19
|
+
<sonic-button class="mt-4">Submit with captcha</sonic-button>
|
|
8
20
|
</sonic-submit>
|
|
9
21
|
</sonic-captcha>
|
|
10
22
|
</template>
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { Subscriber } from "@supersoniks/concorde/mixins";
|
|
2
|
-
import { PublisherManager } from "@supersoniks/concorde/utils";
|
|
3
|
-
import { html, LitElement } from "lit";
|
|
2
|
+
import { HTML, PublisherManager } from "@supersoniks/concorde/utils";
|
|
3
|
+
import { css, html, LitElement, nothing } from "lit";
|
|
4
4
|
import { customElement, property } from "lit/decorators.js";
|
|
5
5
|
import { ConcordeWindow } from "@supersoniks/concorde/core/_types/types";
|
|
6
6
|
import Publisher from "@supersoniks/concorde/core/utils/PublisherProxy";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
generateKey,
|
|
9
|
+
encryptToBase64,
|
|
10
|
+
} from "@supersoniks/concorde/core/utils/aesCrypto";
|
|
11
|
+
|
|
12
|
+
const PASS_PHRASE = "supersoniks_altcha";
|
|
13
|
+
const IV = "Si2\\]X8M4!n9DCLd";
|
|
14
|
+
|
|
15
|
+
let scriptAdded = false;
|
|
8
16
|
|
|
9
17
|
declare const window: ConcordeWindow;
|
|
10
18
|
const tagName = "sonic-captcha";
|
|
@@ -16,14 +24,34 @@ const tagName = "sonic-captcha";
|
|
|
16
24
|
*/
|
|
17
25
|
@customElement(tagName)
|
|
18
26
|
export class Captcha extends Subscriber(LitElement) {
|
|
27
|
+
static styles = [
|
|
28
|
+
css`
|
|
29
|
+
:host {
|
|
30
|
+
--altcha-border-width: var(--sc-border-width, 1px);
|
|
31
|
+
--altcha-border-radius: var(--sc-rounded);
|
|
32
|
+
--altcha-color-base: var(--sc-base);
|
|
33
|
+
--altcha-color-border: var(
|
|
34
|
+
--sc-input-border-color,
|
|
35
|
+
var(--sc-base-content, #000)
|
|
36
|
+
);
|
|
37
|
+
--altcha-color-text: currentColor;
|
|
38
|
+
--altcha-color-border-focus: currentColor;
|
|
39
|
+
--altcha-color-error-text: var(
|
|
40
|
+
--sc-danger,
|
|
41
|
+
var(--sc-base-content, #000)
|
|
42
|
+
);
|
|
43
|
+
--altcha-color-footer-bg: var(--sc-base-100);
|
|
44
|
+
--altcha-max-width: 260px;
|
|
45
|
+
}
|
|
46
|
+
`,
|
|
47
|
+
];
|
|
19
48
|
@property() key = "";
|
|
20
49
|
@property() action: string | null = null;
|
|
21
50
|
@property({ type: Number }) zIndex = 9999;
|
|
22
51
|
formPublisher?: {
|
|
23
52
|
needsCaptchaValidation: boolean;
|
|
53
|
+
captchaKey: string;
|
|
24
54
|
captchaToken: Publisher<string> | string;
|
|
25
|
-
captchaMethod?: { get: () => string };
|
|
26
|
-
captchaAction?: { get: () => string };
|
|
27
55
|
};
|
|
28
56
|
|
|
29
57
|
onCaptchaTokenChanged = (v: string) => {
|
|
@@ -33,27 +61,22 @@ export class Captcha extends Subscriber(LitElement) {
|
|
|
33
61
|
}
|
|
34
62
|
};
|
|
35
63
|
connectedCallback() {
|
|
36
|
-
|
|
37
|
-
if (!document.getElementById("captcha-" + this.key)) {
|
|
64
|
+
if (!scriptAdded) {
|
|
38
65
|
const script = document.createElement("script");
|
|
39
|
-
script.
|
|
40
|
-
|
|
66
|
+
script.type = "module";
|
|
67
|
+
this.setAttribute("async", "");
|
|
68
|
+
this.setAttribute("defer", "");
|
|
69
|
+
script.src = "https://eu.altcha.org/js/latest/altcha.min.js";
|
|
70
|
+
scriptAdded = true;
|
|
41
71
|
document.head.appendChild(script);
|
|
42
72
|
}
|
|
73
|
+
this.generateEncryptedKey();
|
|
43
74
|
super.connectedCallback();
|
|
44
75
|
this.formPublisher = PublisherManager.get(
|
|
45
76
|
this.getAncestorAttributeValue("headersDataProvider") ??
|
|
46
77
|
this.getAncestorAttributeValue("formDataProvider")
|
|
47
78
|
);
|
|
48
79
|
|
|
49
|
-
// add css to document to force z-index
|
|
50
|
-
if (!document.getElementById("concorde-recaptcha-css")) {
|
|
51
|
-
const style = document.createElement("style");
|
|
52
|
-
style.innerHTML = ".grecaptcha-badge {z-index: 9999;}";
|
|
53
|
-
style.id = "concorde-recaptcha-css";
|
|
54
|
-
document.head.appendChild(style);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
80
|
if (
|
|
58
81
|
this.formPublisher &&
|
|
59
82
|
!(this.formPublisher.captchaToken as Publisher<string>).get()
|
|
@@ -77,35 +100,64 @@ export class Captcha extends Subscriber(LitElement) {
|
|
|
77
100
|
requestToken() {
|
|
78
101
|
if (!this.formPublisher) return;
|
|
79
102
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
"submit"
|
|
86
|
-
).replace(/[^\w_/]/g, "_");
|
|
87
|
-
const method = (
|
|
88
|
-
this.formPublisher.captchaMethod?.get() ?? "POST"
|
|
89
|
-
).toUpperCase();
|
|
90
|
-
delete this.formPublisher.captchaAction;
|
|
91
|
-
delete this.formPublisher.captchaMethod;
|
|
92
|
-
if (!window.grecaptcha) {
|
|
93
|
-
log("grecaptcha not loaded");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
window.grecaptcha.ready(() => {
|
|
97
|
-
if (!window.grecaptcha) return;
|
|
98
|
-
window.grecaptcha
|
|
99
|
-
.execute(this.key, { action: method + "//" + action })
|
|
100
|
-
.then((token: string) => {
|
|
101
|
-
if (this.formPublisher) {
|
|
102
|
-
this.formPublisher.captchaToken = token;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
});
|
|
103
|
+
const form = this.shadowRoot.querySelector("form");
|
|
104
|
+
if (!form) return;
|
|
105
|
+
const formData = new FormData(form);
|
|
106
|
+
this.formPublisher.captchaKey = this.key;
|
|
107
|
+
this.formPublisher.captchaToken = formData.get("altcha")?.toString() || "";
|
|
106
108
|
}
|
|
107
109
|
|
|
110
|
+
async generateEncryptedKey() {
|
|
111
|
+
if (this.key) return;
|
|
112
|
+
const key = await generateKey();
|
|
113
|
+
const iv = new TextEncoder().encode(IV);
|
|
114
|
+
const encryptedBase64 = await encryptToBase64(PASS_PHRASE, key, iv);
|
|
115
|
+
this.key = encryptedBase64;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
maxNumber = 50000;
|
|
119
|
+
chalengeUrl = "https://altcha.supersoniks.org/get-challenge";
|
|
108
120
|
protected render() {
|
|
109
|
-
|
|
121
|
+
if (!this.key) {
|
|
122
|
+
return nothing;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const isFR = HTML.getLanguage().match("^fr\\b");
|
|
126
|
+
const labels = isFR
|
|
127
|
+
? {
|
|
128
|
+
aria: "Visitez altcha.org",
|
|
129
|
+
error: "La vérification a échoué, réessayez plus tard.",
|
|
130
|
+
expired: "La vérification a expiré, réessayez.",
|
|
131
|
+
footer: "Protégé par Altcha",
|
|
132
|
+
label: "Je ne suis pas un robot.",
|
|
133
|
+
verified: "Vérifié",
|
|
134
|
+
verifying: "Vérification en cours...",
|
|
135
|
+
wait: "Vérification en cours… Veuillez patienter.",
|
|
136
|
+
}
|
|
137
|
+
: {
|
|
138
|
+
aria: "Visit altcha.org",
|
|
139
|
+
error: "Verification failed, try again later.",
|
|
140
|
+
expired: "Verification expired, try again.",
|
|
141
|
+
footer: "Protected by Altcha",
|
|
142
|
+
label: "I'm not a robot.",
|
|
143
|
+
verified: "Verified",
|
|
144
|
+
verifying: "Verifying...",
|
|
145
|
+
wait: "Verifying... Please wait.",
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
return html`
|
|
149
|
+
<form>
|
|
150
|
+
<altcha-widget
|
|
151
|
+
challengeurl="${this.chalengeUrl}?key=${this.key}&maxNumber=${this
|
|
152
|
+
.maxNumber}"
|
|
153
|
+
maxnumber=${this.maxNumber}
|
|
154
|
+
hidelogo
|
|
155
|
+
hidefooter
|
|
156
|
+
auto="onfocus"
|
|
157
|
+
strings=${JSON.stringify(labels)}
|
|
158
|
+
></altcha-widget>
|
|
159
|
+
</form>
|
|
160
|
+
<slot></slot>
|
|
161
|
+
`;
|
|
110
162
|
}
|
|
111
163
|
}
|
|
File without changes
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// Algorithme et configuration constants
|
|
2
|
+
const algorithm = "AES-CBC";
|
|
3
|
+
const keyLength = 256;
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Génère une clé AES-256
|
|
7
|
+
*/
|
|
8
|
+
export async function generateKey(): Promise<CryptoKey> {
|
|
9
|
+
return crypto.subtle.generateKey(
|
|
10
|
+
{
|
|
11
|
+
name: algorithm,
|
|
12
|
+
length: keyLength,
|
|
13
|
+
},
|
|
14
|
+
true, // extractable
|
|
15
|
+
["encrypt", "decrypt"]
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Exporte une clé AES en format JSON Web Key (JWK)
|
|
21
|
+
*/
|
|
22
|
+
export async function exportKey(key: CryptoKey): Promise<JsonWebKey> {
|
|
23
|
+
return crypto.subtle.exportKey("jwk", key);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Importe une clé AES à partir d'un format JSON Web Key (JWK)
|
|
28
|
+
*/
|
|
29
|
+
export async function importKey(jwk: JsonWebKey): Promise<CryptoKey> {
|
|
30
|
+
return crypto.subtle.importKey(
|
|
31
|
+
"jwk",
|
|
32
|
+
jwk,
|
|
33
|
+
{ name: algorithm },
|
|
34
|
+
true, // extractable
|
|
35
|
+
["encrypt", "decrypt"]
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Encode les données en Base64
|
|
41
|
+
*/
|
|
42
|
+
function toBase64(buffer: ArrayBuffer): string {
|
|
43
|
+
return btoa(String.fromCharCode(...new Uint8Array(buffer)));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Décode les données en Base64
|
|
48
|
+
*/
|
|
49
|
+
function fromBase64(base64: string): ArrayBuffer {
|
|
50
|
+
const binaryString = atob(base64);
|
|
51
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
52
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
53
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
54
|
+
}
|
|
55
|
+
return bytes.buffer;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Chiffre une donnée
|
|
60
|
+
* @param data - Les données à chiffrer
|
|
61
|
+
* @param key - La clé AES
|
|
62
|
+
* @param iv - Le vecteur d'initialisation
|
|
63
|
+
* @returns Une chaîne encodée en Base64
|
|
64
|
+
*/
|
|
65
|
+
export async function encryptToBase64(
|
|
66
|
+
data: string,
|
|
67
|
+
key: CryptoKey,
|
|
68
|
+
iv: Uint8Array
|
|
69
|
+
): Promise<string> {
|
|
70
|
+
const encodedData = new TextEncoder().encode(data);
|
|
71
|
+
const encrypted = await crypto.subtle.encrypt(
|
|
72
|
+
{
|
|
73
|
+
name: algorithm,
|
|
74
|
+
iv: iv,
|
|
75
|
+
},
|
|
76
|
+
key,
|
|
77
|
+
encodedData
|
|
78
|
+
);
|
|
79
|
+
return toBase64(encrypted);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Déchiffre une donnée
|
|
84
|
+
* @param base64Data - Les données chiffrées en Base64
|
|
85
|
+
* @param key - La clé AES
|
|
86
|
+
* @param iv - Le vecteur d'initialisation
|
|
87
|
+
* @returns Une chaîne déchiffrée
|
|
88
|
+
*/
|
|
89
|
+
export async function decryptFromBase64(
|
|
90
|
+
base64Data: string,
|
|
91
|
+
key: CryptoKey,
|
|
92
|
+
iv: Uint8Array
|
|
93
|
+
): Promise<string> {
|
|
94
|
+
const encryptedData = fromBase64(base64Data);
|
|
95
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
96
|
+
{
|
|
97
|
+
name: algorithm,
|
|
98
|
+
iv: iv,
|
|
99
|
+
},
|
|
100
|
+
key,
|
|
101
|
+
encryptedData
|
|
102
|
+
);
|
|
103
|
+
return new TextDecoder().decode(decrypted);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* USAGE
|
|
108
|
+
|
|
109
|
+
import { generateKey, encryptToBase64, decryptFromBase64, exportKey, importKey } from './aesCrypto';
|
|
110
|
+
|
|
111
|
+
(async () => {
|
|
112
|
+
const key = await generateKey();
|
|
113
|
+
const iv = crypto.getRandomValues(new Uint8Array(16)); // Génère un IV aléatoire
|
|
114
|
+
|
|
115
|
+
const data = "Ceci est un secret!";
|
|
116
|
+
|
|
117
|
+
// Chiffrement
|
|
118
|
+
const encryptedBase64 = await encryptToBase64(data, key, iv);
|
|
119
|
+
|
|
120
|
+
// Déchiffrement
|
|
121
|
+
const decrypted = await decryptFromBase64(encryptedBase64, key, iv);
|
|
122
|
+
|
|
123
|
+
// Exporter et importer la clé
|
|
124
|
+
const exportedKey = await exportKey(key);
|
|
125
|
+
|
|
126
|
+
const importedKey = await importKey(exportedKey);
|
|
127
|
+
})();
|
|
128
|
+
|
|
129
|
+
*/
|
package/src/tsconfig.json
CHANGED
package/src/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./components.ts","./concorde-loaded.ts","./decorators.ts","./directives.ts","./index.ts","./mixins.ts","./utils.ts","./core/core.ts","./core/_types/types.ts","./core/components/functional/functional.ts","./core/components/functional/date/date.ts","./core/components/functional/example/example.ts","./core/components/functional/fetch/fetch.ts","./core/components/functional/if/if.test.ts","./core/components/functional/if/if.ts","./core/components/functional/list/list.ts","./core/components/functional/mix/mix.ts","./core/components/functional/queue/queue.ts","./core/components/functional/router/redirect.ts","./core/components/functional/router/router.ts","./core/components/functional/sdui/SDUIDescriptorTransformer.ts","./core/components/functional/sdui/sdui-utils.ts","./core/components/functional/sdui/sdui.ts","./core/components/functional/sdui/types.ts","./core/components/functional/sonic-scope/sonic-scope.ts","./core/components/functional/states/states.ts","./core/components/functional/submit/submit.ts","./core/components/functional/subscriber/subscriber.ts","./core/components/functional/translation/translation.ts","./core/components/functional/value/value.ts","./core/components/ui/ui.ts","./core/components/ui/_css/scroll.ts","./core/components/ui/_css/shadow.ts","./core/components/ui/_css/size.ts","./core/components/ui/_css/type.ts","./core/components/ui/alert/alert.ts","./core/components/ui/alert-messages/alert-messages.ts","./core/components/ui/badge/badge.ts","./core/components/ui/button/button.ts","./core/components/ui/captcha/captcha.ts","./core/components/ui/card/card-footer.ts","./core/components/ui/card/card-header-descripton.ts","./core/components/ui/card/card-header.ts","./core/components/ui/card/card-main.ts","./core/components/ui/card/card.ts","./core/components/ui/divider/divider.ts","./core/components/ui/form/checkbox/checkbox.ts","./core/components/ui/form/css/form-control.ts","./core/components/ui/form/fieldset/fieldset.ts","./core/components/ui/form/fieldset/legend-description.ts","./core/components/ui/form/fieldset/legend.ts","./core/components/ui/form/form-actions/form-actions.ts","./core/components/ui/form/form-layout/form-layout.ts","./core/components/ui/form/input/input.ts","./core/components/ui/form/input/password-helper.ts","./core/components/ui/form/input/same-value-helper.ts","./core/components/ui/form/input-autocomplete/input-autocomplete.ts","./core/components/ui/form/radio/radio.ts","./core/components/ui/form/select/select.ts","./core/components/ui/form/switch/switch.ts","./core/components/ui/form/textarea/textarea.ts","./core/components/ui/group/group.ts","./core/components/ui/icon/icon.stories.ts","./core/components/ui/icon/icon.ts","./core/components/ui/icon/icons.ts","./core/components/ui/image/image.ts","./core/components/ui/link/link.ts","./core/components/ui/loader/loader.stories.ts","./core/components/ui/loader/loader.ts","./core/components/ui/loader/styles/fixed.ts","./core/components/ui/loader/styles/inline.ts","./core/components/ui/menu/menu-item.ts","./core/components/ui/menu/menu.ts","./core/components/ui/modal/modal-actions.ts","./core/components/ui/modal/modal-close.ts","./core/components/ui/modal/modal-content.ts","./core/components/ui/modal/modal-subtitle.ts","./core/components/ui/modal/modal-title.ts","./core/components/ui/modal/modal.stories.ts","./core/components/ui/modal/modal.ts","./core/components/ui/pop/pop.ts","./core/components/ui/progress/progress.ts","./core/components/ui/table/table-caption.ts","./core/components/ui/table/table-tbody.ts","./core/components/ui/table/table-td.ts","./core/components/ui/table/table-tfoot.ts","./core/components/ui/table/table-th.ts","./core/components/ui/table/table-thead.ts","./core/components/ui/table/table-tr.ts","./core/components/ui/table/table.ts","./core/components/ui/theme/theme.ts","./core/components/ui/theme/theme-collection/core-variables.ts","./core/components/ui/theme/theme-collection/dark.ts","./core/components/ui/theme/theme-collection/light.ts","./core/components/ui/toast/message-subscriber.stories.ts","./core/components/ui/toast/message-subscriber.ts","./core/components/ui/toast/toast-item.ts","./core/components/ui/toast/toast.ts","./core/components/ui/toast/types.ts","./core/components/ui/tooltip/tooltip.ts","./core/decorators/Subscriber.ts","./core/directives/DataProvider.ts","./core/directives/Wording.ts","./core/mixins/Fetcher.ts","./core/mixins/FormCheckable.ts","./core/mixins/FormElement.ts","./core/mixins/FormInput.ts","./core/mixins/Subscriber.ts","./core/mixins/TemplatesContainer.ts","./core/mixins/mixins.ts","./core/utils/Arrays.ts","./core/utils/DataBindObserver.ts","./core/utils/Electron.ts","./core/utils/Format.ts","./core/utils/HTML.ts","./core/utils/LocationHandler.ts","./core/utils/Objects.ts","./core/utils/PublisherProxy.ts","./core/utils/Utils.ts","./core/utils/api.ts","./core/utils/route.ts","./core/utils/url-pattern.ts","./test-utils/TestUtils.ts"],"version":"5.6.3"}
|
|
1
|
+
{"root":["./components.ts","./concorde-loaded.ts","./decorators.ts","./directives.ts","./index.ts","./mixins.ts","./utils.ts","./core/core.ts","./core/_types/types.ts","./core/components/functional/functional.ts","./core/components/functional/date/date.ts","./core/components/functional/example/example.ts","./core/components/functional/fetch/fetch.ts","./core/components/functional/if/if.test.ts","./core/components/functional/if/if.ts","./core/components/functional/list/list.ts","./core/components/functional/mix/mix.ts","./core/components/functional/queue/queue.ts","./core/components/functional/router/redirect.ts","./core/components/functional/router/router.ts","./core/components/functional/sdui/SDUIDescriptorTransformer.ts","./core/components/functional/sdui/sdui-utils.ts","./core/components/functional/sdui/sdui.ts","./core/components/functional/sdui/types.ts","./core/components/functional/sonic-scope/sonic-scope.ts","./core/components/functional/states/states.ts","./core/components/functional/submit/submit.ts","./core/components/functional/subscriber/subscriber.ts","./core/components/functional/translation/translation.ts","./core/components/functional/value/value.ts","./core/components/ui/ui.ts","./core/components/ui/_css/scroll.ts","./core/components/ui/_css/shadow.ts","./core/components/ui/_css/size.ts","./core/components/ui/_css/type.ts","./core/components/ui/alert/alert.ts","./core/components/ui/alert-messages/alert-messages.ts","./core/components/ui/badge/badge.ts","./core/components/ui/button/button.ts","./core/components/ui/captcha/captcha.ts","./core/components/ui/card/card-footer.ts","./core/components/ui/card/card-header-descripton.ts","./core/components/ui/card/card-header.ts","./core/components/ui/card/card-main.ts","./core/components/ui/card/card.ts","./core/components/ui/divider/divider.ts","./core/components/ui/form/checkbox/checkbox.ts","./core/components/ui/form/css/form-control.ts","./core/components/ui/form/fieldset/fieldset.ts","./core/components/ui/form/fieldset/legend-description.ts","./core/components/ui/form/fieldset/legend.ts","./core/components/ui/form/form-actions/form-actions.ts","./core/components/ui/form/form-layout/form-layout.ts","./core/components/ui/form/input/input.ts","./core/components/ui/form/input/password-helper.ts","./core/components/ui/form/input/same-value-helper.ts","./core/components/ui/form/input-autocomplete/input-autocomplete.ts","./core/components/ui/form/radio/radio.ts","./core/components/ui/form/select/select.ts","./core/components/ui/form/switch/switch.ts","./core/components/ui/form/textarea/textarea.ts","./core/components/ui/group/group.ts","./core/components/ui/icon/icon.stories.ts","./core/components/ui/icon/icon.ts","./core/components/ui/icon/icons.ts","./core/components/ui/image/image.ts","./core/components/ui/link/link.ts","./core/components/ui/loader/loader.stories.ts","./core/components/ui/loader/loader.ts","./core/components/ui/loader/styles/fixed.ts","./core/components/ui/loader/styles/inline.ts","./core/components/ui/menu/menu-item.ts","./core/components/ui/menu/menu.ts","./core/components/ui/modal/modal-actions.ts","./core/components/ui/modal/modal-close.ts","./core/components/ui/modal/modal-content.ts","./core/components/ui/modal/modal-subtitle.ts","./core/components/ui/modal/modal-title.ts","./core/components/ui/modal/modal.stories.ts","./core/components/ui/modal/modal.ts","./core/components/ui/pop/pop.ts","./core/components/ui/progress/progress.ts","./core/components/ui/table/table-caption.ts","./core/components/ui/table/table-tbody.ts","./core/components/ui/table/table-td.ts","./core/components/ui/table/table-tfoot.ts","./core/components/ui/table/table-th.ts","./core/components/ui/table/table-thead.ts","./core/components/ui/table/table-tr.ts","./core/components/ui/table/table.ts","./core/components/ui/theme/theme.ts","./core/components/ui/theme/theme-collection/core-variables.ts","./core/components/ui/theme/theme-collection/dark.ts","./core/components/ui/theme/theme-collection/light.ts","./core/components/ui/toast/message-subscriber.stories.ts","./core/components/ui/toast/message-subscriber.ts","./core/components/ui/toast/toast-item.ts","./core/components/ui/toast/toast.ts","./core/components/ui/toast/types.ts","./core/components/ui/tooltip/tooltip.ts","./core/decorators/Subscriber.ts","./core/directives/DataProvider.ts","./core/directives/Wording.ts","./core/mixins/Fetcher.ts","./core/mixins/FormCheckable.ts","./core/mixins/FormElement.ts","./core/mixins/FormInput.ts","./core/mixins/Subscriber.ts","./core/mixins/TemplatesContainer.ts","./core/mixins/mixins.ts","./core/utils/Arrays.ts","./core/utils/DataBindObserver.ts","./core/utils/Electron.ts","./core/utils/Format.ts","./core/utils/HTML.ts","./core/utils/LocationHandler.ts","./core/utils/Objects.ts","./core/utils/PublisherProxy.ts","./core/utils/Utils.ts","./core/utils/aesCrypto.ts","./core/utils/api.ts","./core/utils/route.ts","./core/utils/url-pattern.ts","./test-utils/TestUtils.ts"],"version":"5.6.3"}
|
package/vite.config.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import postcssLit from "rollup-plugin-postcss-lit";
|
|
2
|
+
import basicSsl from "@vitejs/plugin-basic-ssl";
|
|
2
3
|
|
|
3
4
|
// import minifyHTML from "rollup-plugin-minify-html-literals";
|
|
4
5
|
import { defineConfig } from "vite";
|
|
@@ -81,6 +82,7 @@ export default defineConfig({
|
|
|
81
82
|
},
|
|
82
83
|
build: build,
|
|
83
84
|
plugins: [
|
|
85
|
+
basicSsl(),
|
|
84
86
|
CustomHmr(),
|
|
85
87
|
postcssLit({
|
|
86
88
|
include: ["src/**/*.css", "src/**/*.css?*"],
|