@gataca/qr 3.0.0 → 3.0.7
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/dist/cjs/gataca-ssibutton_2.cjs.entry.js +193 -9
- package/dist/cjs/gatacaqr.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/gataca-ssibutton/gataca-ssibutton.js +286 -10
- package/dist/components/gataca-ssibutton2.js +203 -10
- package/dist/esm/gataca-ssibutton_2.entry.js +193 -9
- package/dist/esm/gatacaqr.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/gatacaqr/gatacaqr.esm.js +1 -1
- package/dist/gatacaqr/p-78f503dc.entry.js +1 -0
- package/dist/types/components/gataca-ssibutton/gataca-ssibutton.d.ts +35 -1
- package/dist/types/components.d.ts +32 -0
- package/package.json +2 -2
- package/dist/gatacaqr/p-4dc10b69.entry.js +0 -1
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { h, } from "@stencil/core";
|
|
2
2
|
import "../gataca-qrdisplay/gataca-qrdisplay";
|
|
3
|
+
import { RESULT_STATUS } from "../../utils/utils";
|
|
3
4
|
const PHONE_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHvSURBVHgB3ZZPTttAFMbfe3YjL7qYLopcpZXSG7Q3CDfIsqrSJpyg5QQtJ2h7glgUdVs4AeEE5AYEQSDAgtnw357Hm0hAQDaeIRFCfFKyeKPxzzPzvc+DUKCZN80GEv1ABgWOQgSdGbOwv7u0nDueV4zjTzUIKhuAZna4vdQFR828azbI0K/TI/qodaLvjlP+tLDGDCs+IKv9Lbsi7kcv0w9541Q0EREPYcoieEQ9KiyECRXHzbpBUOcnYTfPFOOaaGVx9WsLiDrSIp0iU0wFNgIx/AQyc9I/OmOjy+Y8aBvHQcDUYebewc6/Xtk8J5htcg5efEPGhk0JtqkyBjo7DuZcnuO2sqCyKv8rUDmfTS9IBURqBAL+I6CkzBjOMOs22TLY21n8fl17KzXR3uDvb/CQk0GEdfvN07QvpnAOaGfYaRT25JzU6+rnG2tTpcWAy+Cp0m3U/URLms8HWfg/rn6RFaGSs9KQkZMpvGBWNs2Vandt46ac6YNBuc0fDLMaOU5DFybQ8039p/KJ4bq4rwPewtqoM/1gsCm/NfBXvWjgHhhuDAeLyd3qVSifHQULeZkou9EqemLhmUmav8qrZ4GEMGA7ivzjKvfeqGptFV2YdWPMPHHq0cCh3DdpVdLl/XCY9J1gVvbCiWa6N+JLocPFjCsx9cAAAAAASUVORK5CYII=";
|
|
5
|
+
//Default values
|
|
6
|
+
const DEFAULT_SESSION_TIMEOUT = 300; //5mins as in connect
|
|
7
|
+
const DEFAULT_POLLING_FREQ = 3;
|
|
4
8
|
export class GatacaSSIButton {
|
|
5
9
|
constructor() {
|
|
6
10
|
this.buttonText = "Easy login";
|
|
11
|
+
this.autostart = true;
|
|
7
12
|
this.checkStatus = undefined;
|
|
8
13
|
this.createSession = undefined;
|
|
9
14
|
this.successCallback = undefined;
|
|
10
15
|
this.errorCallback = undefined;
|
|
16
|
+
this.handleCheckAppLoading = undefined;
|
|
17
|
+
this.checkAppTimeout = 6;
|
|
11
18
|
this.qrRole = undefined;
|
|
12
19
|
this.callbackServer = undefined;
|
|
13
20
|
this.sessionTimeout = undefined;
|
|
@@ -34,7 +41,11 @@ export class GatacaSSIButton {
|
|
|
34
41
|
this.waitingStartSessionLabel = "waiting to start a session";
|
|
35
42
|
this.hideQrModalDescription = false;
|
|
36
43
|
this.open = false;
|
|
37
|
-
this.
|
|
44
|
+
this.sessionId = undefined;
|
|
45
|
+
this.authenticationRequest = undefined;
|
|
46
|
+
this.sessionData = undefined;
|
|
47
|
+
this.result = RESULT_STATUS.NOT_STARTED;
|
|
48
|
+
this.qr = (h("gataca-qr", { ref: (el) => (this.qrElement = el), checkStatus: this.checkStatus, createSession: this.createSession, successCallback: this.successCallback, errorCallback: this.errorCallback, qrRole: this.qrRole, callbackServer: this.callbackServer, sessionTimeout: this.sessionTimeout, pollingFrequency: this.pollingFrequency, autostart: this.autostart, autorefresh: this.autorefresh, v: this.v, qrModalTitle: this.qrModalTitle, qrModalDescription: this.qrModalDescription, hideBrandTitle: this.hideBrandTitle, dynamicLink: this.dynamicLink, logoSize: this.logoSize, logoSrc: this.logoSrc, modalTitleColor: this.modalTitleColor, qrCodeExpiredLabel: this.qrCodeExpiredLabel, credentialsNotValidatedLabel: this.credentialsNotValidatedLabel, clickInsideBoxLabel: this.clickInsideBoxLabel, refreshQrLabel: this.refreshQrLabel, scanQrLabel: this.scanQrLabel, userNotScanInTimeErrorLabel: this.userNotScanInTimeErrorLabel, credsNotValidatedErrorLabel: this.credsNotValidatedErrorLabel, failedLoginErrorLabel: this.failedLoginErrorLabel, successLoginLabel: this.successLoginLabel, byBrandLabel: this.byBrandLabel, waitingStartSessionLabel: this.waitingStartSessionLabel, hideQrModalDescription: this.hideQrModalDescription }));
|
|
38
49
|
}
|
|
39
50
|
/**
|
|
40
51
|
* Retrieve manually the session data on a successful login
|
|
@@ -42,22 +53,195 @@ export class GatacaSSIButton {
|
|
|
42
53
|
async getSessionData() {
|
|
43
54
|
return this.qr.getSessionData();
|
|
44
55
|
}
|
|
56
|
+
async getSessionId() {
|
|
57
|
+
if (this.sessionId) {
|
|
58
|
+
return this.sessionId;
|
|
59
|
+
}
|
|
60
|
+
let { sessionId, authenticationRequest } = await this.createSession();
|
|
61
|
+
this.sessionId = sessionId;
|
|
62
|
+
this.authenticationRequest = authenticationRequest;
|
|
63
|
+
return this.sessionId;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Force manually the start polling
|
|
67
|
+
*/
|
|
68
|
+
async startMobilePolling() {
|
|
69
|
+
await this.getSessionId();
|
|
70
|
+
this.result = RESULT_STATUS.ONGOING;
|
|
71
|
+
this.poll()
|
|
72
|
+
.then((data) => {
|
|
73
|
+
this.result = RESULT_STATUS.SUCCESS;
|
|
74
|
+
this.sessionData = data;
|
|
75
|
+
this.gatacaLoginCompleted.emit(data);
|
|
76
|
+
this.successCallback(data);
|
|
77
|
+
})
|
|
78
|
+
.catch((err) => {
|
|
79
|
+
this.clean();
|
|
80
|
+
let expired = err === RESULT_STATUS.EXPIRED;
|
|
81
|
+
if (expired && this.autorefresh) {
|
|
82
|
+
this.startMobilePolling();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (err !== RESULT_STATUS.NOT_STARTED) {
|
|
86
|
+
let error = expired
|
|
87
|
+
? new Error(this.userNotScanInTimeErrorLabel)
|
|
88
|
+
: new Error(this.credsNotValidatedErrorLabel);
|
|
89
|
+
this.result = err;
|
|
90
|
+
this.gatacaLoginFailed.emit(error);
|
|
91
|
+
this.errorCallback(error);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Stop manually an ongoing session
|
|
98
|
+
*/
|
|
99
|
+
async stop() {
|
|
100
|
+
this.clean();
|
|
101
|
+
if (this.result === RESULT_STATUS.ONGOING || RESULT_STATUS.READ) {
|
|
102
|
+
this.result = RESULT_STATUS.NOT_STARTED;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
clean() {
|
|
106
|
+
this.sessionData = undefined;
|
|
107
|
+
this.sessionId = undefined;
|
|
108
|
+
}
|
|
45
109
|
renderModal() {
|
|
46
110
|
return this.qr;
|
|
47
111
|
}
|
|
48
|
-
|
|
112
|
+
async poll() {
|
|
113
|
+
let endTime = new Date().getTime() +
|
|
114
|
+
(this.sessionTimeout || DEFAULT_SESSION_TIMEOUT) * 1000;
|
|
115
|
+
let interval = (this.pollingFrequency || DEFAULT_POLLING_FREQ) * 1000;
|
|
116
|
+
let checkFunc = async (component) => {
|
|
117
|
+
if (component.result === RESULT_STATUS.NOT_STARTED) {
|
|
118
|
+
return { result: RESULT_STATUS.NOT_STARTED };
|
|
119
|
+
}
|
|
120
|
+
let id = await component.getSessionId();
|
|
121
|
+
return component.checkStatus(id);
|
|
122
|
+
};
|
|
123
|
+
let component = this;
|
|
124
|
+
let checkCondition = async function (resolve, reject) {
|
|
125
|
+
// If the condition is met, we're done!
|
|
126
|
+
let { result, data } = await checkFunc(component);
|
|
127
|
+
switch (result) {
|
|
128
|
+
case RESULT_STATUS.SUCCESS:
|
|
129
|
+
resolve(data);
|
|
130
|
+
break;
|
|
131
|
+
case RESULT_STATUS.READ:
|
|
132
|
+
component.result = RESULT_STATUS.READ;
|
|
133
|
+
case RESULT_STATUS.ONGOING:
|
|
134
|
+
if (component.sessionTimeout > 0 && new Date().getTime() < endTime) {
|
|
135
|
+
setTimeout(checkCondition, interval, resolve, reject);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
reject(RESULT_STATUS.EXPIRED);
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
default:
|
|
142
|
+
reject(result);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
return new Promise(checkCondition);
|
|
147
|
+
}
|
|
148
|
+
isAppInstalled(appScheme, callback) {
|
|
149
|
+
let timeout;
|
|
150
|
+
let detected = false;
|
|
151
|
+
if (appScheme === null || appScheme === void 0 ? void 0 : appScheme.length) {
|
|
152
|
+
window.location.href = appScheme;
|
|
153
|
+
}
|
|
154
|
+
const waitTimeToCheckApp = this.checkAppTimeout * 1000;
|
|
155
|
+
timeout = setTimeout(() => {
|
|
156
|
+
if (!detected) {
|
|
157
|
+
callback(false);
|
|
158
|
+
}
|
|
159
|
+
cleanup();
|
|
160
|
+
}, waitTimeToCheckApp);
|
|
161
|
+
const handleVisibilityChange = () => {
|
|
162
|
+
if (document.hidden) {
|
|
163
|
+
detected = true;
|
|
164
|
+
callback(true);
|
|
165
|
+
this.startMobilePolling();
|
|
166
|
+
cleanup();
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
170
|
+
function cleanup() {
|
|
171
|
+
clearTimeout(timeout);
|
|
172
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
renderDesktopButton() {
|
|
49
176
|
return (h("div", { class: "gatacaButtonWrapper" }, h("button", { class: "gatacaButton", onClick: () => {
|
|
50
177
|
this.open = !this.open;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
178
|
+
setTimeout(() => {
|
|
179
|
+
var _a, _b;
|
|
180
|
+
if (this.open) {
|
|
181
|
+
(_a = this.qrElement) === null || _a === void 0 ? void 0 : _a.display();
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
(_b = this.qrElement) === null || _b === void 0 ? void 0 : _b.stop();
|
|
185
|
+
}
|
|
186
|
+
}, 0);
|
|
57
187
|
} }, h("img", { src: PHONE_ICON, class: "buttonImg", alt: this.buttonText }), h("span", null, this.buttonText))));
|
|
58
188
|
}
|
|
189
|
+
async getAuthRequest() {
|
|
190
|
+
let { authenticationRequest } = await this.createSession();
|
|
191
|
+
return authenticationRequest;
|
|
192
|
+
}
|
|
193
|
+
renderMobileButton(isAndroid, isIos) {
|
|
194
|
+
if (this.autostart) {
|
|
195
|
+
this.startMobilePolling();
|
|
196
|
+
}
|
|
197
|
+
let loading = false;
|
|
198
|
+
const handleLoading = (isLoading) => {
|
|
199
|
+
loading = isLoading;
|
|
200
|
+
if (this.handleCheckAppLoading) {
|
|
201
|
+
this.handleCheckAppLoading(isLoading);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
const executeRedirection = async () => {
|
|
205
|
+
handleLoading(true);
|
|
206
|
+
const androidStoreLink = "https://play.google.com/store/apps/details?id=com.gataca.identity";
|
|
207
|
+
const iosStoreLink = "https://apps.apple.com/us/app/gataca/id1498607616";
|
|
208
|
+
try {
|
|
209
|
+
const appScheme = await this.getAuthRequest();
|
|
210
|
+
this.isAppInstalled(appScheme, (installed) => {
|
|
211
|
+
if (!installed) {
|
|
212
|
+
this.stop();
|
|
213
|
+
if (isAndroid) {
|
|
214
|
+
window.location.href = androidStoreLink;
|
|
215
|
+
}
|
|
216
|
+
else if (isIos) {
|
|
217
|
+
window.location.href = iosStoreLink;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
handleLoading(false);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
this.stop();
|
|
225
|
+
handleLoading(false);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
return (h("div", { class: "gatacaButtonWrapper" }, h("button", { class: "gatacaButton", onClick: () => {
|
|
229
|
+
executeRedirection();
|
|
230
|
+
}, disabled: loading }, h("img", { src: PHONE_ICON, class: "buttonImg", alt: this.buttonText }), h("span", null, this.buttonText))));
|
|
231
|
+
}
|
|
59
232
|
render() {
|
|
60
|
-
|
|
233
|
+
const userAgent =
|
|
234
|
+
// @ts-ignore
|
|
235
|
+
(navigator === null || navigator === void 0 ? void 0 : navigator.userAgent) || (navigator === null || navigator === void 0 ? void 0 : navigator.vendor) || (window === null || window === void 0 ? void 0 : window.opera);
|
|
236
|
+
const isAndroid = /android/i.test(userAgent);
|
|
237
|
+
const isIos =
|
|
238
|
+
// @ts-ignore
|
|
239
|
+
(/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) ||
|
|
240
|
+
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
241
|
+
const isMobile = isAndroid || isIos;
|
|
242
|
+
return (h("div", { class: "buttonContainer" }, isMobile && this.v === "3"
|
|
243
|
+
? this.renderMobileButton(isAndroid, isIos)
|
|
244
|
+
: this.renderDesktopButton(), this.open && (!isMobile || this.v === "3") && this.renderModal()));
|
|
61
245
|
}
|
|
62
246
|
static get is() { return "gataca-ssibutton"; }
|
|
63
247
|
static get encapsulation() { return "shadow"; }
|
|
@@ -91,6 +275,24 @@ export class GatacaSSIButton {
|
|
|
91
275
|
"reflect": false,
|
|
92
276
|
"defaultValue": "\"Easy login\""
|
|
93
277
|
},
|
|
278
|
+
"autostart": {
|
|
279
|
+
"type": "boolean",
|
|
280
|
+
"mutable": false,
|
|
281
|
+
"complexType": {
|
|
282
|
+
"original": "boolean",
|
|
283
|
+
"resolved": "boolean",
|
|
284
|
+
"references": {}
|
|
285
|
+
},
|
|
286
|
+
"required": false,
|
|
287
|
+
"optional": false,
|
|
288
|
+
"docs": {
|
|
289
|
+
"tags": [],
|
|
290
|
+
"text": "_[Optional]_\nSet to start polling when button or QR is displayed. By default it is true"
|
|
291
|
+
},
|
|
292
|
+
"attribute": "autostart",
|
|
293
|
+
"reflect": false,
|
|
294
|
+
"defaultValue": "true"
|
|
295
|
+
},
|
|
94
296
|
"checkStatus": {
|
|
95
297
|
"type": "unknown",
|
|
96
298
|
"mutable": false,
|
|
@@ -171,6 +373,40 @@ export class GatacaSSIButton {
|
|
|
171
373
|
},
|
|
172
374
|
"defaultValue": "undefined"
|
|
173
375
|
},
|
|
376
|
+
"handleCheckAppLoading": {
|
|
377
|
+
"type": "unknown",
|
|
378
|
+
"mutable": false,
|
|
379
|
+
"complexType": {
|
|
380
|
+
"original": "(isCheckingApp?: boolean) => void",
|
|
381
|
+
"resolved": "(isCheckingApp?: boolean) => void",
|
|
382
|
+
"references": {}
|
|
383
|
+
},
|
|
384
|
+
"required": false,
|
|
385
|
+
"optional": true,
|
|
386
|
+
"docs": {
|
|
387
|
+
"tags": [],
|
|
388
|
+
"text": "_[Optional]_\nFunction that runs every time the loading state changes while checking if the App is installed. Only on mobile with v3."
|
|
389
|
+
},
|
|
390
|
+
"defaultValue": "undefined"
|
|
391
|
+
},
|
|
392
|
+
"checkAppTimeout": {
|
|
393
|
+
"type": "number",
|
|
394
|
+
"mutable": false,
|
|
395
|
+
"complexType": {
|
|
396
|
+
"original": "number",
|
|
397
|
+
"resolved": "number",
|
|
398
|
+
"references": {}
|
|
399
|
+
},
|
|
400
|
+
"required": false,
|
|
401
|
+
"optional": true,
|
|
402
|
+
"docs": {
|
|
403
|
+
"tags": [],
|
|
404
|
+
"text": "_[Optional]_\nMaximum time window to check if the App is installed"
|
|
405
|
+
},
|
|
406
|
+
"attribute": "check-app-timeout",
|
|
407
|
+
"reflect": false,
|
|
408
|
+
"defaultValue": "6"
|
|
409
|
+
},
|
|
174
410
|
"qrRole": {
|
|
175
411
|
"type": "string",
|
|
176
412
|
"mutable": false,
|
|
@@ -620,7 +856,11 @@ export class GatacaSSIButton {
|
|
|
620
856
|
}
|
|
621
857
|
static get states() {
|
|
622
858
|
return {
|
|
623
|
-
"open": {}
|
|
859
|
+
"open": {},
|
|
860
|
+
"sessionId": {},
|
|
861
|
+
"authenticationRequest": {},
|
|
862
|
+
"sessionData": {},
|
|
863
|
+
"result": {}
|
|
624
864
|
};
|
|
625
865
|
}
|
|
626
866
|
static get events() {
|
|
@@ -673,6 +913,42 @@ export class GatacaSSIButton {
|
|
|
673
913
|
"text": "Retrieve manually the session data on a successful login",
|
|
674
914
|
"tags": []
|
|
675
915
|
}
|
|
916
|
+
},
|
|
917
|
+
"startMobilePolling": {
|
|
918
|
+
"complexType": {
|
|
919
|
+
"signature": "() => Promise<void>",
|
|
920
|
+
"parameters": [],
|
|
921
|
+
"references": {
|
|
922
|
+
"Promise": {
|
|
923
|
+
"location": "global"
|
|
924
|
+
},
|
|
925
|
+
"RESULT_STATUS": {
|
|
926
|
+
"location": "import",
|
|
927
|
+
"path": "../../utils/utils"
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
"return": "Promise<void>"
|
|
931
|
+
},
|
|
932
|
+
"docs": {
|
|
933
|
+
"text": "Force manually the start polling",
|
|
934
|
+
"tags": []
|
|
935
|
+
}
|
|
936
|
+
},
|
|
937
|
+
"stop": {
|
|
938
|
+
"complexType": {
|
|
939
|
+
"signature": "() => Promise<void>",
|
|
940
|
+
"parameters": [],
|
|
941
|
+
"references": {
|
|
942
|
+
"Promise": {
|
|
943
|
+
"location": "global"
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
"return": "Promise<void>"
|
|
947
|
+
},
|
|
948
|
+
"docs": {
|
|
949
|
+
"text": "Stop manually an ongoing session",
|
|
950
|
+
"tags": []
|
|
951
|
+
}
|
|
676
952
|
}
|
|
677
953
|
};
|
|
678
954
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
|
|
2
2
|
import { d as defineCustomElement$1 } from './gataca-qrdisplay2.js';
|
|
3
|
+
import { R as RESULT_STATUS } from './gat-icon-alert.js';
|
|
3
4
|
import { d as defineCustomElement$2 } from './gataca-qr2.js';
|
|
4
5
|
|
|
5
6
|
const gatacaSsibuttonCss = "@import url(\"https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400&display=swap\"); html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:\"\";content:none}table{border-collapse:collapse;border-spacing:0}.img-fluid{height:auto;max-width:50%}img{margin-left:auto;margin-right:auto}.buttonContainer{display:inline-block;text-align:right;padding:10px;position:relative}.gatacaButtonWrapper{margin:8px}.gatacaButtonWrapper .gatacaButton{display:flex;min-width:100px;padding:8px 8px;background-color:white;font-size:12px;font-family:\"Work Sans\", sans-serif;letter-spacing:1px;font-weight:2;justify-content:space-between;align-items:center;border-radius:6px;border:1px solid rgba(24, 27, 94, 0.5);color:rgba(24, 27, 94, 0.8);box-shadow:0px 1px 3px rgba(48, 48, 48, 0.15);cursor:pointer}.gatacaButtonWrapper .gatacaButton>span{margin-right:10px}.gatacaButtonWrapper .gatacaButton:hover{box-shadow:0px 2px 8px rgba(48, 48, 48, 0.1)}.gatacaButtonWrapper .buttonText{text-align:right;font-size:8px;color:rgba(24, 27, 94, 0.5);font-family:\"Helvetica Neue\", sans-serif;letter-spacing:1px;padding-right:8px;font-weight:1}.gatacaButtonWrapper .buttonImg{height:25px;width:25px;margin:0;margin-right:20px}";
|
|
6
7
|
|
|
7
8
|
const PHONE_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAHvSURBVHgB3ZZPTttAFMbfe3YjL7qYLopcpZXSG7Q3CDfIsqrSJpyg5QQtJ2h7glgUdVs4AeEE5AYEQSDAgtnw357Hm0hAQDaeIRFCfFKyeKPxzzPzvc+DUKCZN80GEv1ABgWOQgSdGbOwv7u0nDueV4zjTzUIKhuAZna4vdQFR828azbI0K/TI/qodaLvjlP+tLDGDCs+IKv9Lbsi7kcv0w9541Q0EREPYcoieEQ9KiyECRXHzbpBUOcnYTfPFOOaaGVx9WsLiDrSIp0iU0wFNgIx/AQyc9I/OmOjy+Y8aBvHQcDUYebewc6/Xtk8J5htcg5efEPGhk0JtqkyBjo7DuZcnuO2sqCyKv8rUDmfTS9IBURqBAL+I6CkzBjOMOs22TLY21n8fl17KzXR3uDvb/CQk0GEdfvN07QvpnAOaGfYaRT25JzU6+rnG2tTpcWAy+Cp0m3U/URLms8HWfg/rn6RFaGSs9KQkZMpvGBWNs2Vandt46ac6YNBuc0fDLMaOU5DFybQ8039p/KJ4bq4rwPewtqoM/1gsCm/NfBXvWjgHhhuDAeLyd3qVSifHQULeZkou9EqemLhmUmav8qrZ4GEMGA7ivzjKvfeqGptFV2YdWPMPHHq0cCh3DdpVdLl/XCY9J1gVvbCiWa6N+JLocPFjCsx9cAAAAAASUVORK5CYII=";
|
|
9
|
+
//Default values
|
|
10
|
+
const DEFAULT_SESSION_TIMEOUT = 300; //5mins as in connect
|
|
11
|
+
const DEFAULT_POLLING_FREQ = 3;
|
|
8
12
|
const GatacaSSIButton = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
|
|
9
13
|
constructor() {
|
|
10
14
|
super();
|
|
@@ -13,10 +17,13 @@ const GatacaSSIButton = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
|
|
|
13
17
|
this.gatacaLoginCompleted = createEvent(this, "gatacaLoginCompleted", 7);
|
|
14
18
|
this.gatacaLoginFailed = createEvent(this, "gatacaLoginFailed", 7);
|
|
15
19
|
this.buttonText = "Easy login";
|
|
20
|
+
this.autostart = true;
|
|
16
21
|
this.checkStatus = undefined;
|
|
17
22
|
this.createSession = undefined;
|
|
18
23
|
this.successCallback = undefined;
|
|
19
24
|
this.errorCallback = undefined;
|
|
25
|
+
this.handleCheckAppLoading = undefined;
|
|
26
|
+
this.checkAppTimeout = 6;
|
|
20
27
|
this.qrRole = undefined;
|
|
21
28
|
this.callbackServer = undefined;
|
|
22
29
|
this.sessionTimeout = undefined;
|
|
@@ -43,7 +50,11 @@ const GatacaSSIButton = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
|
|
|
43
50
|
this.waitingStartSessionLabel = "waiting to start a session";
|
|
44
51
|
this.hideQrModalDescription = false;
|
|
45
52
|
this.open = false;
|
|
46
|
-
this.
|
|
53
|
+
this.sessionId = undefined;
|
|
54
|
+
this.authenticationRequest = undefined;
|
|
55
|
+
this.sessionData = undefined;
|
|
56
|
+
this.result = RESULT_STATUS.NOT_STARTED;
|
|
57
|
+
this.qr = (h("gataca-qr", { ref: (el) => (this.qrElement = el), checkStatus: this.checkStatus, createSession: this.createSession, successCallback: this.successCallback, errorCallback: this.errorCallback, qrRole: this.qrRole, callbackServer: this.callbackServer, sessionTimeout: this.sessionTimeout, pollingFrequency: this.pollingFrequency, autostart: this.autostart, autorefresh: this.autorefresh, v: this.v, qrModalTitle: this.qrModalTitle, qrModalDescription: this.qrModalDescription, hideBrandTitle: this.hideBrandTitle, dynamicLink: this.dynamicLink, logoSize: this.logoSize, logoSrc: this.logoSrc, modalTitleColor: this.modalTitleColor, qrCodeExpiredLabel: this.qrCodeExpiredLabel, credentialsNotValidatedLabel: this.credentialsNotValidatedLabel, clickInsideBoxLabel: this.clickInsideBoxLabel, refreshQrLabel: this.refreshQrLabel, scanQrLabel: this.scanQrLabel, userNotScanInTimeErrorLabel: this.userNotScanInTimeErrorLabel, credsNotValidatedErrorLabel: this.credsNotValidatedErrorLabel, failedLoginErrorLabel: this.failedLoginErrorLabel, successLoginLabel: this.successLoginLabel, byBrandLabel: this.byBrandLabel, waitingStartSessionLabel: this.waitingStartSessionLabel, hideQrModalDescription: this.hideQrModalDescription }));
|
|
47
58
|
}
|
|
48
59
|
/**
|
|
49
60
|
* Retrieve manually the session data on a successful login
|
|
@@ -51,30 +62,206 @@ const GatacaSSIButton = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
|
|
|
51
62
|
async getSessionData() {
|
|
52
63
|
return this.qr.getSessionData();
|
|
53
64
|
}
|
|
65
|
+
async getSessionId() {
|
|
66
|
+
if (this.sessionId) {
|
|
67
|
+
return this.sessionId;
|
|
68
|
+
}
|
|
69
|
+
let { sessionId, authenticationRequest } = await this.createSession();
|
|
70
|
+
this.sessionId = sessionId;
|
|
71
|
+
this.authenticationRequest = authenticationRequest;
|
|
72
|
+
return this.sessionId;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Force manually the start polling
|
|
76
|
+
*/
|
|
77
|
+
async startMobilePolling() {
|
|
78
|
+
await this.getSessionId();
|
|
79
|
+
this.result = RESULT_STATUS.ONGOING;
|
|
80
|
+
this.poll()
|
|
81
|
+
.then((data) => {
|
|
82
|
+
this.result = RESULT_STATUS.SUCCESS;
|
|
83
|
+
this.sessionData = data;
|
|
84
|
+
this.gatacaLoginCompleted.emit(data);
|
|
85
|
+
this.successCallback(data);
|
|
86
|
+
})
|
|
87
|
+
.catch((err) => {
|
|
88
|
+
this.clean();
|
|
89
|
+
let expired = err === RESULT_STATUS.EXPIRED;
|
|
90
|
+
if (expired && this.autorefresh) {
|
|
91
|
+
this.startMobilePolling();
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (err !== RESULT_STATUS.NOT_STARTED) {
|
|
95
|
+
let error = expired
|
|
96
|
+
? new Error(this.userNotScanInTimeErrorLabel)
|
|
97
|
+
: new Error(this.credsNotValidatedErrorLabel);
|
|
98
|
+
this.result = err;
|
|
99
|
+
this.gatacaLoginFailed.emit(error);
|
|
100
|
+
this.errorCallback(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stop manually an ongoing session
|
|
107
|
+
*/
|
|
108
|
+
async stop() {
|
|
109
|
+
this.clean();
|
|
110
|
+
if (this.result === RESULT_STATUS.ONGOING || RESULT_STATUS.READ) {
|
|
111
|
+
this.result = RESULT_STATUS.NOT_STARTED;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
clean() {
|
|
115
|
+
this.sessionData = undefined;
|
|
116
|
+
this.sessionId = undefined;
|
|
117
|
+
}
|
|
54
118
|
renderModal() {
|
|
55
119
|
return this.qr;
|
|
56
120
|
}
|
|
57
|
-
|
|
121
|
+
async poll() {
|
|
122
|
+
let endTime = new Date().getTime() +
|
|
123
|
+
(this.sessionTimeout || DEFAULT_SESSION_TIMEOUT) * 1000;
|
|
124
|
+
let interval = (this.pollingFrequency || DEFAULT_POLLING_FREQ) * 1000;
|
|
125
|
+
let checkFunc = async (component) => {
|
|
126
|
+
if (component.result === RESULT_STATUS.NOT_STARTED) {
|
|
127
|
+
return { result: RESULT_STATUS.NOT_STARTED };
|
|
128
|
+
}
|
|
129
|
+
let id = await component.getSessionId();
|
|
130
|
+
return component.checkStatus(id);
|
|
131
|
+
};
|
|
132
|
+
let component = this;
|
|
133
|
+
let checkCondition = async function (resolve, reject) {
|
|
134
|
+
// If the condition is met, we're done!
|
|
135
|
+
let { result, data } = await checkFunc(component);
|
|
136
|
+
switch (result) {
|
|
137
|
+
case RESULT_STATUS.SUCCESS:
|
|
138
|
+
resolve(data);
|
|
139
|
+
break;
|
|
140
|
+
case RESULT_STATUS.READ:
|
|
141
|
+
component.result = RESULT_STATUS.READ;
|
|
142
|
+
case RESULT_STATUS.ONGOING:
|
|
143
|
+
if (component.sessionTimeout > 0 && new Date().getTime() < endTime) {
|
|
144
|
+
setTimeout(checkCondition, interval, resolve, reject);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
reject(RESULT_STATUS.EXPIRED);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
default:
|
|
151
|
+
reject(result);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
return new Promise(checkCondition);
|
|
156
|
+
}
|
|
157
|
+
isAppInstalled(appScheme, callback) {
|
|
158
|
+
let timeout;
|
|
159
|
+
let detected = false;
|
|
160
|
+
if (appScheme === null || appScheme === void 0 ? void 0 : appScheme.length) {
|
|
161
|
+
window.location.href = appScheme;
|
|
162
|
+
}
|
|
163
|
+
const waitTimeToCheckApp = this.checkAppTimeout * 1000;
|
|
164
|
+
timeout = setTimeout(() => {
|
|
165
|
+
if (!detected) {
|
|
166
|
+
callback(false);
|
|
167
|
+
}
|
|
168
|
+
cleanup();
|
|
169
|
+
}, waitTimeToCheckApp);
|
|
170
|
+
const handleVisibilityChange = () => {
|
|
171
|
+
if (document.hidden) {
|
|
172
|
+
detected = true;
|
|
173
|
+
callback(true);
|
|
174
|
+
this.startMobilePolling();
|
|
175
|
+
cleanup();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
179
|
+
function cleanup() {
|
|
180
|
+
clearTimeout(timeout);
|
|
181
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
renderDesktopButton() {
|
|
58
185
|
return (h("div", { class: "gatacaButtonWrapper" }, h("button", { class: "gatacaButton", onClick: () => {
|
|
59
186
|
this.open = !this.open;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
187
|
+
setTimeout(() => {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
if (this.open) {
|
|
190
|
+
(_a = this.qrElement) === null || _a === void 0 ? void 0 : _a.display();
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
(_b = this.qrElement) === null || _b === void 0 ? void 0 : _b.stop();
|
|
194
|
+
}
|
|
195
|
+
}, 0);
|
|
66
196
|
} }, h("img", { src: PHONE_ICON, class: "buttonImg", alt: this.buttonText }), h("span", null, this.buttonText))));
|
|
67
197
|
}
|
|
198
|
+
async getAuthRequest() {
|
|
199
|
+
let { authenticationRequest } = await this.createSession();
|
|
200
|
+
return authenticationRequest;
|
|
201
|
+
}
|
|
202
|
+
renderMobileButton(isAndroid, isIos) {
|
|
203
|
+
if (this.autostart) {
|
|
204
|
+
this.startMobilePolling();
|
|
205
|
+
}
|
|
206
|
+
let loading = false;
|
|
207
|
+
const handleLoading = (isLoading) => {
|
|
208
|
+
loading = isLoading;
|
|
209
|
+
if (this.handleCheckAppLoading) {
|
|
210
|
+
this.handleCheckAppLoading(isLoading);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const executeRedirection = async () => {
|
|
214
|
+
handleLoading(true);
|
|
215
|
+
const androidStoreLink = "https://play.google.com/store/apps/details?id=com.gataca.identity";
|
|
216
|
+
const iosStoreLink = "https://apps.apple.com/us/app/gataca/id1498607616";
|
|
217
|
+
try {
|
|
218
|
+
const appScheme = await this.getAuthRequest();
|
|
219
|
+
this.isAppInstalled(appScheme, (installed) => {
|
|
220
|
+
if (!installed) {
|
|
221
|
+
this.stop();
|
|
222
|
+
if (isAndroid) {
|
|
223
|
+
window.location.href = androidStoreLink;
|
|
224
|
+
}
|
|
225
|
+
else if (isIos) {
|
|
226
|
+
window.location.href = iosStoreLink;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
handleLoading(false);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
this.stop();
|
|
234
|
+
handleLoading(false);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
return (h("div", { class: "gatacaButtonWrapper" }, h("button", { class: "gatacaButton", onClick: () => {
|
|
238
|
+
executeRedirection();
|
|
239
|
+
}, disabled: loading }, h("img", { src: PHONE_ICON, class: "buttonImg", alt: this.buttonText }), h("span", null, this.buttonText))));
|
|
240
|
+
}
|
|
68
241
|
render() {
|
|
69
|
-
|
|
242
|
+
const userAgent =
|
|
243
|
+
// @ts-ignore
|
|
244
|
+
(navigator === null || navigator === void 0 ? void 0 : navigator.userAgent) || (navigator === null || navigator === void 0 ? void 0 : navigator.vendor) || (window === null || window === void 0 ? void 0 : window.opera);
|
|
245
|
+
const isAndroid = /android/i.test(userAgent);
|
|
246
|
+
const isIos =
|
|
247
|
+
// @ts-ignore
|
|
248
|
+
(/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) ||
|
|
249
|
+
(navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1);
|
|
250
|
+
const isMobile = isAndroid || isIos;
|
|
251
|
+
return (h("div", { class: "buttonContainer" }, isMobile && this.v === "3"
|
|
252
|
+
? this.renderMobileButton(isAndroid, isIos)
|
|
253
|
+
: this.renderDesktopButton(), this.open && (!isMobile || this.v === "3") && this.renderModal()));
|
|
70
254
|
}
|
|
71
255
|
static get style() { return gatacaSsibuttonCss; }
|
|
72
256
|
}, [1, "gataca-ssibutton", {
|
|
73
257
|
"buttonText": [1, "button-text"],
|
|
258
|
+
"autostart": [4],
|
|
74
259
|
"checkStatus": [16],
|
|
75
260
|
"createSession": [16],
|
|
76
261
|
"successCallback": [16],
|
|
77
262
|
"errorCallback": [16],
|
|
263
|
+
"handleCheckAppLoading": [16],
|
|
264
|
+
"checkAppTimeout": [2, "check-app-timeout"],
|
|
78
265
|
"qrRole": [1, "qr-role"],
|
|
79
266
|
"callbackServer": [1, "callback-server"],
|
|
80
267
|
"sessionTimeout": [2, "session-timeout"],
|
|
@@ -101,7 +288,13 @@ const GatacaSSIButton = /*@__PURE__*/ proxyCustomElement(class extends HTMLEleme
|
|
|
101
288
|
"waitingStartSessionLabel": [1, "waiting-start-session-label"],
|
|
102
289
|
"hideQrModalDescription": [4, "hide-qr-modal-description"],
|
|
103
290
|
"open": [32],
|
|
104
|
-
"
|
|
291
|
+
"sessionId": [32],
|
|
292
|
+
"authenticationRequest": [32],
|
|
293
|
+
"sessionData": [32],
|
|
294
|
+
"result": [32],
|
|
295
|
+
"getSessionData": [64],
|
|
296
|
+
"startMobilePolling": [64],
|
|
297
|
+
"stop": [64]
|
|
105
298
|
}]);
|
|
106
299
|
function defineCustomElement() {
|
|
107
300
|
if (typeof customElements === "undefined") {
|