Skip to content

Commit a6fc56e

Browse files
taneltmmrts
authored andcommitted
feat: Automatic version check when an action fails
Signed-off-by: Tanel Metsar <[email protected]>
1 parent 230cc6d commit a6fc56e

File tree

7 files changed

+147
-49
lines changed

7 files changed

+147
-49
lines changed

package-lock.json

Lines changed: 49 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "web-eid-webextension",
3-
"version": "2.0.1",
3+
"version": "2.1.0",
44
"description": "",
55
"main": "src/index.js",
66
"scripts": {

src/background/actions/authenticate.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,29 @@ import Action from "@web-eid.js/models/Action";
2424
import { NativeAuthenticateRequest } from "@web-eid.js/models/message/NativeRequest";
2525
import { NativeAuthenticateResponse } from "@web-eid.js/models/message/NativeResponse";
2626
import UserTimeoutError from "@web-eid.js/errors/UserTimeoutError";
27-
import { serializeError } from "@web-eid.js/utils/errorSerializer";
2827

2928
import { ExtensionAuthenticateResponse, ExtensionFailureResponse } from "@web-eid.js/models/message/ExtensionResponse";
3029
import { MessageSender } from "../../models/Browser/Runtime";
3130
import NativeAppService from "../services/NativeAppService";
3231
import UnknownError from "@web-eid.js/errors/UnknownError";
32+
import actionErrorHandler from "../../shared/actionErrorHandler";
3333
import config from "../../config";
3434
import { getSenderUrl } from "../../shared/utils/sender";
3535
import { throwAfterTimeout } from "../../shared/utils/timing";
3636

3737
export default async function authenticate(
3838
challengeNonce: string,
3939
sender: MessageSender,
40+
libraryVersion: string,
4041
userInteractionTimeout: number,
4142
lang?: string,
4243
): Promise<ExtensionAuthenticateResponse | ExtensionFailureResponse> {
4344
let nativeAppService: NativeAppService | undefined;
45+
let nativeAppStatus: { version: string } | undefined;
4446

4547
try {
4648
nativeAppService = new NativeAppService();
47-
48-
const nativeAppStatus = await nativeAppService.connect();
49+
nativeAppStatus = await nativeAppService.connect();
4950

5051
config.DEBUG && console.log("Authenticate: connected to native", nativeAppStatus);
5152

@@ -85,10 +86,7 @@ export default async function authenticate(
8586
} catch (error) {
8687
console.error("Authenticate:", error);
8788

88-
return {
89-
action: Action.AUTHENTICATE_FAILURE,
90-
error: serializeError(error),
91-
};
89+
return actionErrorHandler(Action.AUTHENTICATE_FAILURE, error, libraryVersion, nativeAppStatus?.version);
9290
} finally {
9391
nativeAppService?.close();
9492
}

src/background/actions/getSigningCertificate.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import { NativeGetSigningCertificateRequest } from "@web-eid.js/models/message/N
2525
import { NativeGetSigningCertificateResponse } from "@web-eid.js/models/message/NativeResponse";
2626
import UnknownError from "@web-eid.js/errors/UnknownError";
2727
import UserTimeoutError from "@web-eid.js/errors/UserTimeoutError";
28-
import { serializeError } from "@web-eid.js/utils/errorSerializer";
2928

3029
import {
3130
ExtensionFailureResponse,
@@ -34,19 +33,23 @@ import {
3433

3534
import { MessageSender } from "../../models/Browser/Runtime";
3635
import NativeAppService from "../services/NativeAppService";
36+
import actionErrorHandler from "../../shared/actionErrorHandler";
3737
import config from "../../config";
3838
import { getSenderUrl } from "../../shared/utils/sender";
3939
import { throwAfterTimeout } from "../../shared/utils/timing";
4040

4141
export default async function getSigningCertificate(
4242
sender: MessageSender,
43+
libraryVersion: string,
4344
userInteractionTimeout: number,
4445
lang?: string,
4546
): Promise<ExtensionGetSigningCertificateResponse | ExtensionFailureResponse> {
46-
const nativeAppService = new NativeAppService();
47+
let nativeAppService: NativeAppService | undefined;
48+
let nativeAppStatus: { version: string } | undefined;
4749

4850
try {
49-
const nativeAppStatus = await nativeAppService.connect();
51+
nativeAppService = new NativeAppService();
52+
nativeAppStatus = await nativeAppService.connect();
5053

5154
config.DEBUG && console.log("getSigningCertificate: connected to native", nativeAppStatus);
5255

@@ -78,11 +81,8 @@ export default async function getSigningCertificate(
7881
} catch (error: any) {
7982
console.error("GetSigningCertificate:", error);
8083

81-
return {
82-
action: Action.GET_SIGNING_CERTIFICATE_FAILURE,
83-
error: serializeError(error),
84-
};
84+
return actionErrorHandler(Action.GET_SIGNING_CERTIFICATE_FAILURE, error, libraryVersion, nativeAppStatus?.version);
8585
} finally {
86-
nativeAppService.close();
86+
nativeAppService?.close();
8787
}
8888
}

src/background/actions/sign.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ import { NativeSignRequest } from "@web-eid.js/models/message/NativeRequest";
3030
import { NativeSignResponse } from "@web-eid.js/models/message/NativeResponse";
3131
import UnknownError from "@web-eid.js/errors/UnknownError";
3232
import UserTimeoutError from "@web-eid.js/errors/UserTimeoutError";
33-
import { serializeError } from "@web-eid.js/utils/errorSerializer";
3433

3534
import { MessageSender } from "../../models/Browser/Runtime";
3635
import NativeAppService from "../services/NativeAppService";
36+
import actionErrorHandler from "../../shared/actionErrorHandler";
3737
import config from "../../config";
3838
import { getSenderUrl } from "../../shared/utils/sender";
3939
import { throwAfterTimeout } from "../../shared/utils/timing";
@@ -44,15 +44,16 @@ export default async function sign(
4444
hash: string,
4545
hashFunction: string,
4646
sender: MessageSender,
47+
libraryVersion: string,
4748
userInteractionTimeout: number,
4849
lang?: string,
4950
): Promise<ExtensionSignResponse | ExtensionFailureResponse> {
5051
let nativeAppService: NativeAppService | undefined;
52+
let nativeAppStatus: { version: string } | undefined;
5153

5254
try {
5355
nativeAppService = new NativeAppService();
54-
55-
const nativeAppStatus = await nativeAppService.connect();
56+
nativeAppStatus = await nativeAppService.connect();
5657

5758
config.DEBUG && console.log("Sign: connected to native", nativeAppStatus);
5859

@@ -90,10 +91,7 @@ export default async function sign(
9091
} catch (error) {
9192
console.error("Sign:", error);
9293

93-
return {
94-
action: Action.SIGN_FAILURE,
95-
error: serializeError(error),
96-
};
94+
return actionErrorHandler(Action.SIGN_FAILURE, error, libraryVersion, nativeAppStatus?.version);
9795
} finally {
9896
nativeAppService?.close();
9997
}

src/background/background.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ async function onAction(message: ExtensionRequest, sender: MessageSender): Promi
3939
message.challengeNonce,
4040

4141
sender,
42+
message.libraryVersion,
4243
message.options?.userInteractionTimeout || libraryConfig.DEFAULT_USER_INTERACTION_TIMEOUT,
4344
message.options?.lang
4445
);
4546

4647
case Action.GET_SIGNING_CERTIFICATE:
4748
return await getSigningCertificate(
4849
sender,
50+
message.libraryVersion,
4951
message.options?.userInteractionTimeout || libraryConfig.DEFAULT_USER_INTERACTION_TIMEOUT,
5052
message.options?.lang
5153
);
@@ -57,6 +59,7 @@ async function onAction(message: ExtensionRequest, sender: MessageSender): Promi
5759
message.hashFunction,
5860

5961
sender,
62+
message.libraryVersion,
6063
message.options?.userInteractionTimeout || libraryConfig.DEFAULT_USER_INTERACTION_TIMEOUT,
6164
message.options?.lang
6265
);

src/shared/actionErrorHandler.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright (c) 2020-2021 Estonian Information System Authority
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
import Action from "@web-eid.js/models/Action";
24+
import ErrorCode from "@web-eid.js/errors/ErrorCode";
25+
import { ExtensionFailureResponse } from "@web-eid.js/models/message/ExtensionResponse";
26+
import VersionMismatchError from "@web-eid.js/errors/VersionMismatchError";
27+
import { serializeError } from "@web-eid.js/utils/errorSerializer";
28+
29+
import checkCompatibility from "./utils/checkCompatibility";
30+
import config from "../config";
31+
32+
export default function actionErrorHandler(
33+
action:
34+
| Action.AUTHENTICATE_FAILURE
35+
| Action.GET_SIGNING_CERTIFICATE_FAILURE
36+
| Action.SIGN_FAILURE,
37+
38+
originalError: any,
39+
libraryVersion: string,
40+
nativeAppVersion?: string,
41+
): ExtensionFailureResponse {
42+
let error;
43+
44+
/**
45+
* Always show the original error when native app version is unavailable.
46+
* The native app might not be available (ERR_WEBEID_NATIVE_UNAVAILABLE)
47+
* or an error ocurred in the extension before native app version could be detected.
48+
* In addition, if the native app version is missing, checkCompatibility(...) would throw an "Invalid SemVer string" error.
49+
*
50+
* Always show the original error when the error code is ERR_WEBEID_USER_CANCELLED.
51+
* In this case the user cancelled the operation in native app UI, which means the native app API had to be compatible for this action.
52+
*/
53+
if (!nativeAppVersion || originalError?.code === ErrorCode.ERR_WEBEID_USER_CANCELLED) {
54+
error = originalError;
55+
56+
} else {
57+
const versions = {
58+
extension: config.VERSION,
59+
library: libraryVersion,
60+
nativeApp: nativeAppVersion,
61+
};
62+
63+
const requiresUpdate = checkCompatibility(versions);
64+
65+
error = (
66+
(requiresUpdate.extension || requiresUpdate.nativeApp)
67+
? new VersionMismatchError(undefined, versions, requiresUpdate)
68+
: originalError
69+
);
70+
}
71+
72+
return {
73+
action,
74+
error: serializeError(error),
75+
};
76+
}

0 commit comments

Comments
 (0)