@arex95/vue-core 1.1.27 → 1.1.29
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/config/global/index.d.ts +1 -0
- package/dist/config/global/keyConfig.d.ts +20 -0
- package/dist/config/global/sessionConfig.d.ts +5 -0
- package/dist/config/global/tokensConfig.d.ts +0 -14
- package/dist/index.mjs +228 -168
- package/dist/types/AppKeyConfig.d.ts +3 -0
- package/dist/types/ArexVueCoreOptions.d.ts +1 -14
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/credentials.d.ts +1 -1
- package/dist/utils/storage.d.ts +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AppKeyConfig } from "../../types/AppKeyConfig";
|
|
2
|
+
/**
|
|
3
|
+
* Sets the main application encryption key.
|
|
4
|
+
* This key is expected to be used for encryption purposes within the application.
|
|
5
|
+
*
|
|
6
|
+
* @param {AppKeyConfig} config - An object containing the application encryption key.
|
|
7
|
+
* @param {string} config.key - The new application encryption key.
|
|
8
|
+
*
|
|
9
|
+
* @returns {void} Does not return anything, but updates the application key.
|
|
10
|
+
* @throws {Error} If the provided key is null, undefined, or an empty string.
|
|
11
|
+
*/
|
|
12
|
+
export declare function configAppKey(config: AppKeyConfig): void;
|
|
13
|
+
/**
|
|
14
|
+
* Retrieves the current application encryption key.
|
|
15
|
+
* Throws an error if the application key has not been configured.
|
|
16
|
+
*
|
|
17
|
+
* @returns {string} The configured application encryption key.
|
|
18
|
+
* @throws {Error} If the application encryption key has not been set.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getAppKey(): string;
|
|
@@ -8,6 +8,11 @@ interface SessionConfigObject {
|
|
|
8
8
|
/** The storage preference: 'local' for localStorage, 'session' for sessionStorage. */
|
|
9
9
|
persistencePreference?: SessionPreference;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* Loads the session configuration from storage (local or session).
|
|
13
|
+
* This should be called once when the application initializes.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadSessionConfigFromStorage(): Promise<void>;
|
|
11
16
|
/**
|
|
12
17
|
* Configures the session identifier and/or the data persistence preference for the active browser session.
|
|
13
18
|
* Once configured, the session ID cannot be modified. The persistence preference can be updated.
|
|
@@ -23,18 +23,4 @@ export declare function configTokenKeys(config: TokenKeyConfig): void;
|
|
|
23
23
|
* @returns {TokensConfig} The configuration of the access and refresh token keys.
|
|
24
24
|
*/
|
|
25
25
|
export declare function getTokenConfig(): TokensConfig;
|
|
26
|
-
/**
|
|
27
|
-
* Sets the secret key for use in authentication.
|
|
28
|
-
*
|
|
29
|
-
* @param {string} key - The new secret key.
|
|
30
|
-
*
|
|
31
|
-
* @returns {void} Does not return anything, but updates the secret key.
|
|
32
|
-
*/
|
|
33
|
-
export declare function setSecretKey(key: string): void;
|
|
34
|
-
/**
|
|
35
|
-
* Retrieves the current secret key.
|
|
36
|
-
*
|
|
37
|
-
* @returns {string} The configured secret key.
|
|
38
|
-
*/
|
|
39
|
-
export declare function getSecretKey(): string;
|
|
40
26
|
export {};
|
package/dist/index.mjs
CHANGED
|
@@ -538,7 +538,6 @@ function inferErrorType(error) {
|
|
|
538
538
|
return 'error';
|
|
539
539
|
}
|
|
540
540
|
|
|
541
|
-
let secretKey = "12345678901234567890123456789012";
|
|
542
541
|
let tokensConfig = Object.freeze({
|
|
543
542
|
ACCESS_TOKEN: "access_token",
|
|
544
543
|
REFRESH_TOKEN: "refresh_token",
|
|
@@ -567,24 +566,6 @@ function configTokenKeys(config) {
|
|
|
567
566
|
function getTokenConfig() {
|
|
568
567
|
return tokensConfig;
|
|
569
568
|
}
|
|
570
|
-
/**
|
|
571
|
-
* Sets the secret key for use in authentication.
|
|
572
|
-
*
|
|
573
|
-
* @param {string} key - The new secret key.
|
|
574
|
-
*
|
|
575
|
-
* @returns {void} Does not return anything, but updates the secret key.
|
|
576
|
-
*/
|
|
577
|
-
function setSecretKey(key) {
|
|
578
|
-
secretKey = key;
|
|
579
|
-
}
|
|
580
|
-
/**
|
|
581
|
-
* Retrieves the current secret key.
|
|
582
|
-
*
|
|
583
|
-
* @returns {string} The configured secret key.
|
|
584
|
-
*/
|
|
585
|
-
function getSecretKey() {
|
|
586
|
-
return secretKey;
|
|
587
|
-
}
|
|
588
569
|
|
|
589
570
|
let endpointsConfig = {
|
|
590
571
|
LOGIN: "/login",
|
|
@@ -784,11 +765,219 @@ const createCustomAxiosInstance = (config) => {
|
|
|
784
765
|
return new AxiosService(config.baseURL, config.headers).getAxiosInstance();
|
|
785
766
|
};
|
|
786
767
|
|
|
768
|
+
/**
|
|
769
|
+
* Converts an ArrayBuffer or Uint8Array to a hexadecimal string.
|
|
770
|
+
* @param buffer The ArrayBuffer or Uint8Array to convert.
|
|
771
|
+
* @returns The hexadecimal string.
|
|
772
|
+
*/
|
|
773
|
+
function ab2hex(buffer) {
|
|
774
|
+
return Array.from(new Uint8Array(buffer))
|
|
775
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
776
|
+
.join("");
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* Converts a hexadecimal string to a Uint8Array.
|
|
780
|
+
* @param hex The hexadecimal string to convert.
|
|
781
|
+
* @returns The Uint8Array.
|
|
782
|
+
* @throws {TypeError} If the input is not a string.
|
|
783
|
+
* @throws {Error} If the hexadecimal string format is invalid or has an odd length.
|
|
784
|
+
*/
|
|
785
|
+
function hex2ab(hex) {
|
|
786
|
+
if (typeof hex !== "string") {
|
|
787
|
+
throw new TypeError("Input must be a string.");
|
|
788
|
+
}
|
|
789
|
+
if (hex.length === 0) {
|
|
790
|
+
return new Uint8Array();
|
|
791
|
+
}
|
|
792
|
+
if (!/^[0-9a-fA-F]*$/.test(hex) || hex.length % 2 !== 0) {
|
|
793
|
+
throw new Error("Invalid hexadecimal string format or odd length.");
|
|
794
|
+
}
|
|
795
|
+
const array = new Uint8Array(hex.length / 2);
|
|
796
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
797
|
+
array[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
798
|
+
}
|
|
799
|
+
return array;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Derives an encryption key from a secret key.
|
|
803
|
+
* @param secretKey The secret key in plain text.
|
|
804
|
+
* @returns A promise that resolves with the derived CryptoKey.
|
|
805
|
+
* @throws {Error} If the secretKey is null or empty.
|
|
806
|
+
*/
|
|
807
|
+
async function importKey(secretKey) {
|
|
808
|
+
if (!secretKey) {
|
|
809
|
+
throw new Error("Secret key cannot be null or empty.");
|
|
810
|
+
}
|
|
811
|
+
const keyMaterial = new TextEncoder().encode(secretKey);
|
|
812
|
+
const digest = await crypto.subtle.digest("SHA-256", keyMaterial);
|
|
813
|
+
return crypto.subtle.importKey("raw", digest, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* Encrypts a value with the provided secret key.
|
|
817
|
+
* @param value The value to encrypt.
|
|
818
|
+
* @param secretKey The secret key for encryption.
|
|
819
|
+
* @returns A promise that resolves with the IV (hex) + ciphertext (hex) string.
|
|
820
|
+
* @throws {Error} If the secretKey is null or empty (via importKey).
|
|
821
|
+
*/
|
|
822
|
+
async function encrypt(value, secretKey) {
|
|
823
|
+
const key = await importKey(secretKey);
|
|
824
|
+
const iv = crypto.getRandomValues(new Uint8Array(16));
|
|
825
|
+
const encodedValue = new TextEncoder().encode(value);
|
|
826
|
+
const ciphertext = await crypto.subtle.encrypt({ name: "AES-CBC", iv: iv }, key, encodedValue);
|
|
827
|
+
return ab2hex(iv) + ab2hex(new Uint8Array(ciphertext));
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* Decrypts an encrypted value.
|
|
831
|
+
* @param encryptedValue The encrypted string (IV_hex + ciphertext_hex).
|
|
832
|
+
* @param secretKey The secret key for decryption.
|
|
833
|
+
* @returns A promise that resolves with the decrypted value.
|
|
834
|
+
* @throws {Error} If encryptedValue is null or empty, too short,
|
|
835
|
+
* or if the IV/ciphertext have incorrect lengths after conversion.
|
|
836
|
+
* @throws {Error} If the secretKey is null or empty (via importKey).
|
|
837
|
+
* @throws {TypeError} If hex2ab receives an invalid input type.
|
|
838
|
+
*/
|
|
839
|
+
async function decrypt(encryptedValue, secretKey) {
|
|
840
|
+
if (!encryptedValue) {
|
|
841
|
+
throw new Error("Encrypted value cannot be null or empty.");
|
|
842
|
+
}
|
|
843
|
+
// For AES-CBC, the IV is ALWAYS 16 bytes.
|
|
844
|
+
// 16 bytes * 2 hex characters/byte = 32 hex characters for the IV.
|
|
845
|
+
if (encryptedValue.length < 32) {
|
|
846
|
+
throw new Error("Encrypted value is too short. Expected at least 32 hexadecimal characters for the IV.");
|
|
847
|
+
}
|
|
848
|
+
const key = await importKey(secretKey);
|
|
849
|
+
const ivHex = encryptedValue.substring(0, 32);
|
|
850
|
+
const ciphertextHex = encryptedValue.substring(32);
|
|
851
|
+
const iv = hex2ab(ivHex);
|
|
852
|
+
const ciphertext = hex2ab(ciphertextHex);
|
|
853
|
+
if (iv.byteLength !== 16) {
|
|
854
|
+
throw new Error(`Converted IV has incorrect length: ${iv.byteLength} bytes. Expected 16 bytes.`);
|
|
855
|
+
}
|
|
856
|
+
if (ciphertext.byteLength === 0) {
|
|
857
|
+
throw new Error("Ciphertext is empty. No data to decrypt.");
|
|
858
|
+
}
|
|
859
|
+
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-CBC", iv: iv }, key, ciphertext);
|
|
860
|
+
return new TextDecoder().decode(decryptedBuffer);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* Encrypts and stores an item in local or session storage.
|
|
865
|
+
* Assumes the `window` environment is available.
|
|
866
|
+
* @param key The key under which to store the value.
|
|
867
|
+
* @param value The value to encrypt and store.
|
|
868
|
+
* @param secretKey The secret key for encryption.
|
|
869
|
+
* @param persistent If true, uses localStorage; otherwise, uses sessionStorage.
|
|
870
|
+
* @returns A promise that resolves when the item is stored. Throws an error if it fails.
|
|
871
|
+
*/
|
|
872
|
+
async function storeEncryptedItem(key, value, secretKey, persistent) {
|
|
873
|
+
if (typeof window === "undefined") {
|
|
874
|
+
throw new Error("Cannot access storage: window is not defined.");
|
|
875
|
+
}
|
|
876
|
+
const storage = persistent ? window.localStorage : window.sessionStorage;
|
|
877
|
+
const encryptedValue = await encrypt(value, secretKey);
|
|
878
|
+
storage.setItem(key, encryptedValue);
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Retrieves and decrypts a value from local or session storage.
|
|
882
|
+
* Assumes the `window` environment is available.
|
|
883
|
+
* @param key The key of the item to retrieve.
|
|
884
|
+
* @param secretKey The secret key for decryption.
|
|
885
|
+
* @param persistent If true, searches localStorage; otherwise, sessionStorage.
|
|
886
|
+
* @returns A promise that resolves with the decrypted value or null if not found or decryption fails.
|
|
887
|
+
*/
|
|
888
|
+
async function getDecryptedItem(key, secretKey, persistent) {
|
|
889
|
+
if (typeof window === "undefined") {
|
|
890
|
+
return null;
|
|
891
|
+
}
|
|
892
|
+
const storage = persistent ? window.localStorage : window.sessionStorage;
|
|
893
|
+
const encryptedData = storage.getItem(key);
|
|
894
|
+
if (!encryptedData) {
|
|
895
|
+
return null;
|
|
896
|
+
}
|
|
897
|
+
try {
|
|
898
|
+
return await decrypt(encryptedData, secretKey);
|
|
899
|
+
}
|
|
900
|
+
catch (error) {
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
let appKey = null;
|
|
906
|
+
/**
|
|
907
|
+
* Sets the main application encryption key.
|
|
908
|
+
* This key is expected to be used for encryption purposes within the application.
|
|
909
|
+
*
|
|
910
|
+
* @param {AppKeyConfig} config - An object containing the application encryption key.
|
|
911
|
+
* @param {string} config.key - The new application encryption key.
|
|
912
|
+
*
|
|
913
|
+
* @returns {void} Does not return anything, but updates the application key.
|
|
914
|
+
* @throws {Error} If the provided key is null, undefined, or an empty string.
|
|
915
|
+
*/
|
|
916
|
+
function configAppKey(config) {
|
|
917
|
+
if (!config || !config.appKey || config.appKey.trim() === "") {
|
|
918
|
+
throw new Error("The application encryption key cannot be null or empty.");
|
|
919
|
+
}
|
|
920
|
+
appKey = config.appKey;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Retrieves the current application encryption key.
|
|
924
|
+
* Throws an error if the application key has not been configured.
|
|
925
|
+
*
|
|
926
|
+
* @returns {string} The configured application encryption key.
|
|
927
|
+
* @throws {Error} If the application encryption key has not been set.
|
|
928
|
+
*/
|
|
929
|
+
function getAppKey() {
|
|
930
|
+
if (appKey === null) {
|
|
931
|
+
throw new Error("The application encryption key has not been configured. Please call 'configAppKey()' before attempting to access it.");
|
|
932
|
+
}
|
|
933
|
+
return appKey;
|
|
934
|
+
}
|
|
935
|
+
|
|
787
936
|
let sessionId = v4();
|
|
788
937
|
let sessionConfig = Object.freeze({
|
|
789
938
|
SESSION_ID: sessionId,
|
|
790
939
|
});
|
|
791
940
|
let persistencePreference = "session";
|
|
941
|
+
/**
|
|
942
|
+
* Loads the session configuration from storage (local or session).
|
|
943
|
+
* This should be called once when the application initializes.
|
|
944
|
+
*/
|
|
945
|
+
async function loadSessionConfigFromStorage() {
|
|
946
|
+
const isPersistent = persistencePreference === "local";
|
|
947
|
+
const storedConfig = await getDecryptedItem("sessionConfig", getAppKey(), isPersistent);
|
|
948
|
+
if (storedConfig) {
|
|
949
|
+
try {
|
|
950
|
+
const parsedConfig = JSON.parse(storedConfig);
|
|
951
|
+
sessionConfig = Object.freeze({
|
|
952
|
+
...sessionConfig,
|
|
953
|
+
...parsedConfig,
|
|
954
|
+
});
|
|
955
|
+
if (parsedConfig.SESSION_ID) {
|
|
956
|
+
sessionId = parsedConfig.SESSION_ID;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
catch (error) {
|
|
960
|
+
console.error("Error parsing stored session config:", error);
|
|
961
|
+
regenerateSessionId();
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
regenerateSessionId();
|
|
966
|
+
}
|
|
967
|
+
await saveSessionConfigToStorage();
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Saves the current session configuration to local or session storage.
|
|
971
|
+
*/
|
|
972
|
+
async function saveSessionConfigToStorage() {
|
|
973
|
+
const isPersistent = persistencePreference === "local";
|
|
974
|
+
try {
|
|
975
|
+
await storeEncryptedItem("sessionConfig", JSON.stringify(sessionConfig), getAppKey(), isPersistent);
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
console.error("Error saving session config to storage:", error);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
792
981
|
/**
|
|
793
982
|
* Configures the session identifier and/or the data persistence preference for the active browser session.
|
|
794
983
|
* Once configured, the session ID cannot be modified. The persistence preference can be updated.
|
|
@@ -798,15 +987,19 @@ let persistencePreference = "session";
|
|
|
798
987
|
* @returns {void} Does not return anything, but freezes the session configuration (for ID) and updates preference.
|
|
799
988
|
*/
|
|
800
989
|
function configSession(config) {
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
990
|
+
let updatedConfig = { ...sessionConfig };
|
|
991
|
+
if (config.sessionId && sessionConfig.SESSION_ID === sessionId) {
|
|
992
|
+
updatedConfig = {
|
|
993
|
+
...updatedConfig,
|
|
804
994
|
SESSION_ID: config.sessionId,
|
|
805
|
-
}
|
|
995
|
+
};
|
|
996
|
+
sessionId = config.sessionId;
|
|
806
997
|
}
|
|
807
998
|
if (config.persistencePreference) {
|
|
808
999
|
persistencePreference = config.persistencePreference;
|
|
809
1000
|
}
|
|
1001
|
+
sessionConfig = Object.freeze(updatedConfig);
|
|
1002
|
+
saveSessionConfigToStorage();
|
|
810
1003
|
}
|
|
811
1004
|
/**
|
|
812
1005
|
* Retrieves the current session identifier configuration.
|
|
@@ -2504,143 +2697,6 @@ function isValidHexNumber(hex) {
|
|
|
2504
2697
|
// console.log(isValidHexNumber('1A3F')); // true
|
|
2505
2698
|
// console.log(isValidHexNumber('GHIJ')); // false
|
|
2506
2699
|
|
|
2507
|
-
/**
|
|
2508
|
-
* Converts an ArrayBuffer or Uint8Array to a hexadecimal string.
|
|
2509
|
-
* @param buffer The ArrayBuffer or Uint8Array to convert.
|
|
2510
|
-
* @returns The hexadecimal string.
|
|
2511
|
-
*/
|
|
2512
|
-
function ab2hex(buffer) {
|
|
2513
|
-
return Array.from(new Uint8Array(buffer))
|
|
2514
|
-
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
2515
|
-
.join("");
|
|
2516
|
-
}
|
|
2517
|
-
/**
|
|
2518
|
-
* Converts a hexadecimal string to a Uint8Array.
|
|
2519
|
-
* @param hex The hexadecimal string to convert.
|
|
2520
|
-
* @returns The Uint8Array.
|
|
2521
|
-
* @throws {TypeError} If the input is not a string.
|
|
2522
|
-
* @throws {Error} If the hexadecimal string format is invalid or has an odd length.
|
|
2523
|
-
*/
|
|
2524
|
-
function hex2ab(hex) {
|
|
2525
|
-
if (typeof hex !== "string") {
|
|
2526
|
-
throw new TypeError("Input must be a string.");
|
|
2527
|
-
}
|
|
2528
|
-
if (hex.length === 0) {
|
|
2529
|
-
return new Uint8Array();
|
|
2530
|
-
}
|
|
2531
|
-
if (!/^[0-9a-fA-F]*$/.test(hex) || hex.length % 2 !== 0) {
|
|
2532
|
-
throw new Error("Invalid hexadecimal string format or odd length.");
|
|
2533
|
-
}
|
|
2534
|
-
const array = new Uint8Array(hex.length / 2);
|
|
2535
|
-
for (let i = 0; i < hex.length; i += 2) {
|
|
2536
|
-
array[i / 2] = parseInt(hex.substring(i, i + 2), 16);
|
|
2537
|
-
}
|
|
2538
|
-
return array;
|
|
2539
|
-
}
|
|
2540
|
-
/**
|
|
2541
|
-
* Derives an encryption key from a secret key.
|
|
2542
|
-
* @param secretKey The secret key in plain text.
|
|
2543
|
-
* @returns A promise that resolves with the derived CryptoKey.
|
|
2544
|
-
* @throws {Error} If the secretKey is null or empty.
|
|
2545
|
-
*/
|
|
2546
|
-
async function importKey(secretKey) {
|
|
2547
|
-
if (!secretKey) {
|
|
2548
|
-
throw new Error("Secret key cannot be null or empty.");
|
|
2549
|
-
}
|
|
2550
|
-
const keyMaterial = new TextEncoder().encode(secretKey);
|
|
2551
|
-
const digest = await crypto.subtle.digest("SHA-256", keyMaterial);
|
|
2552
|
-
return crypto.subtle.importKey("raw", digest, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
2553
|
-
}
|
|
2554
|
-
/**
|
|
2555
|
-
* Encrypts a value with the provided secret key.
|
|
2556
|
-
* @param value The value to encrypt.
|
|
2557
|
-
* @param secretKey The secret key for encryption.
|
|
2558
|
-
* @returns A promise that resolves with the IV (hex) + ciphertext (hex) string.
|
|
2559
|
-
* @throws {Error} If the secretKey is null or empty (via importKey).
|
|
2560
|
-
*/
|
|
2561
|
-
async function encrypt(value, secretKey) {
|
|
2562
|
-
const key = await importKey(secretKey);
|
|
2563
|
-
const iv = crypto.getRandomValues(new Uint8Array(16));
|
|
2564
|
-
const encodedValue = new TextEncoder().encode(value);
|
|
2565
|
-
const ciphertext = await crypto.subtle.encrypt({ name: "AES-CBC", iv: iv }, key, encodedValue);
|
|
2566
|
-
return ab2hex(iv) + ab2hex(new Uint8Array(ciphertext));
|
|
2567
|
-
}
|
|
2568
|
-
/**
|
|
2569
|
-
* Decrypts an encrypted value.
|
|
2570
|
-
* @param encryptedValue The encrypted string (IV_hex + ciphertext_hex).
|
|
2571
|
-
* @param secretKey The secret key for decryption.
|
|
2572
|
-
* @returns A promise that resolves with the decrypted value.
|
|
2573
|
-
* @throws {Error} If encryptedValue is null or empty, too short,
|
|
2574
|
-
* or if the IV/ciphertext have incorrect lengths after conversion.
|
|
2575
|
-
* @throws {Error} If the secretKey is null or empty (via importKey).
|
|
2576
|
-
* @throws {TypeError} If hex2ab receives an invalid input type.
|
|
2577
|
-
*/
|
|
2578
|
-
async function decrypt(encryptedValue, secretKey) {
|
|
2579
|
-
if (!encryptedValue) {
|
|
2580
|
-
throw new Error("Encrypted value cannot be null or empty.");
|
|
2581
|
-
}
|
|
2582
|
-
// For AES-CBC, the IV is ALWAYS 16 bytes.
|
|
2583
|
-
// 16 bytes * 2 hex characters/byte = 32 hex characters for the IV.
|
|
2584
|
-
if (encryptedValue.length < 32) {
|
|
2585
|
-
throw new Error("Encrypted value is too short. Expected at least 32 hexadecimal characters for the IV.");
|
|
2586
|
-
}
|
|
2587
|
-
const key = await importKey(secretKey);
|
|
2588
|
-
const ivHex = encryptedValue.substring(0, 32);
|
|
2589
|
-
const ciphertextHex = encryptedValue.substring(32);
|
|
2590
|
-
const iv = hex2ab(ivHex);
|
|
2591
|
-
const ciphertext = hex2ab(ciphertextHex);
|
|
2592
|
-
if (iv.byteLength !== 16) {
|
|
2593
|
-
throw new Error(`Converted IV has incorrect length: ${iv.byteLength} bytes. Expected 16 bytes.`);
|
|
2594
|
-
}
|
|
2595
|
-
if (ciphertext.byteLength === 0) {
|
|
2596
|
-
throw new Error("Ciphertext is empty. No data to decrypt.");
|
|
2597
|
-
}
|
|
2598
|
-
const decryptedBuffer = await crypto.subtle.decrypt({ name: "AES-CBC", iv: iv }, key, ciphertext);
|
|
2599
|
-
return new TextDecoder().decode(decryptedBuffer);
|
|
2600
|
-
}
|
|
2601
|
-
|
|
2602
|
-
/**
|
|
2603
|
-
* Encrypts and stores an item in local or session storage.
|
|
2604
|
-
* Assumes the `window` environment is available.
|
|
2605
|
-
* @param key The key under which to store the value.
|
|
2606
|
-
* @param value The value to encrypt and store.
|
|
2607
|
-
* @param secretKey The secret key for encryption.
|
|
2608
|
-
* @param isRememberMe If true, uses localStorage; otherwise, uses sessionStorage.
|
|
2609
|
-
* @returns A promise that resolves when the item is stored. Throws an error if it fails.
|
|
2610
|
-
*/
|
|
2611
|
-
async function storeEncryptedItem(key, value, secretKey, isRememberMe) {
|
|
2612
|
-
if (typeof window === "undefined") {
|
|
2613
|
-
throw new Error("Cannot access storage: window is not defined.");
|
|
2614
|
-
}
|
|
2615
|
-
const storage = isRememberMe ? window.localStorage : window.sessionStorage;
|
|
2616
|
-
const encryptedValue = await encrypt(value, secretKey);
|
|
2617
|
-
storage.setItem(key, encryptedValue);
|
|
2618
|
-
}
|
|
2619
|
-
/**
|
|
2620
|
-
* Retrieves and decrypts a value from local or session storage.
|
|
2621
|
-
* Assumes the `window` environment is available.
|
|
2622
|
-
* @param key The key of the item to retrieve.
|
|
2623
|
-
* @param secretKey The secret key for decryption.
|
|
2624
|
-
* @param isRememberMe If true, searches localStorage; otherwise, sessionStorage.
|
|
2625
|
-
* @returns A promise that resolves with the decrypted value or null if not found or decryption fails.
|
|
2626
|
-
*/
|
|
2627
|
-
async function getDecryptedItem(key, secretKey, isRememberMe) {
|
|
2628
|
-
if (typeof window === "undefined") {
|
|
2629
|
-
return null;
|
|
2630
|
-
}
|
|
2631
|
-
const storage = isRememberMe ? window.localStorage : window.sessionStorage;
|
|
2632
|
-
const encryptedData = storage.getItem(key);
|
|
2633
|
-
if (!encryptedData) {
|
|
2634
|
-
return null;
|
|
2635
|
-
}
|
|
2636
|
-
try {
|
|
2637
|
-
return await decrypt(encryptedData, secretKey);
|
|
2638
|
-
}
|
|
2639
|
-
catch (error) {
|
|
2640
|
-
return null;
|
|
2641
|
-
}
|
|
2642
|
-
}
|
|
2643
|
-
|
|
2644
2700
|
/**
|
|
2645
2701
|
* Clears all stored authentication data (access and refresh tokens)
|
|
2646
2702
|
* from either sessionStorage or localStorage based on the provided preference.
|
|
@@ -2715,9 +2771,10 @@ const storeAuthRefreshToken = async (token, secretKey, preference) => {
|
|
|
2715
2771
|
* @throws {Error} "TOKEN_MISSING" if no token is found, "TOKEN_EXPIRED" if the token has expired,
|
|
2716
2772
|
* "TOKEN_INVALID" if the token format is invalid.
|
|
2717
2773
|
*/
|
|
2718
|
-
const verifyAuth = async (
|
|
2774
|
+
const verifyAuth = async () => {
|
|
2775
|
+
const preference = getSessionPersistencePreference();
|
|
2719
2776
|
try {
|
|
2720
|
-
const token = await getAuthToken(
|
|
2777
|
+
const token = await getAuthToken(getAppKey(), preference);
|
|
2721
2778
|
if (!token) {
|
|
2722
2779
|
handleError("TOKEN_MISSING: No valid token found", false);
|
|
2723
2780
|
await cleanCredentials(preference);
|
|
@@ -3317,7 +3374,7 @@ function useSorter(items, criteriaList, selectedCriteria) {
|
|
|
3317
3374
|
* @param {string} secretKey - The secret key used for token encryption/decryption.
|
|
3318
3375
|
* @returns {AuthHook} An object containing authentication functions.
|
|
3319
3376
|
*/
|
|
3320
|
-
function useAuth(secretKey =
|
|
3377
|
+
function useAuth(secretKey = getAppKey()) {
|
|
3321
3378
|
const axiosInstance = getAxiosInstance();
|
|
3322
3379
|
const endpoints = getEndpointsConfig();
|
|
3323
3380
|
const currentPersistencePreference = getSessionPersistencePreference();
|
|
@@ -3449,10 +3506,8 @@ const ArexVueCore = {
|
|
|
3449
3506
|
console.warn("ArexVueCore: No configuration options were provided. The library may not function correctly.");
|
|
3450
3507
|
return;
|
|
3451
3508
|
}
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
refreshEndpoint: options.endpoints.refresh,
|
|
3455
|
-
logoutEndpoint: options.endpoints.logout
|
|
3509
|
+
configAppKey({
|
|
3510
|
+
appKey: options.appKey
|
|
3456
3511
|
});
|
|
3457
3512
|
configTokenKeys({
|
|
3458
3513
|
accessTokenKey: options.tokenKeys.accessToken,
|
|
@@ -3461,7 +3516,12 @@ const ArexVueCore = {
|
|
|
3461
3516
|
configAxios({
|
|
3462
3517
|
baseURL: options.apiUrl,
|
|
3463
3518
|
});
|
|
3519
|
+
configEndpoints({
|
|
3520
|
+
loginEndpoint: options.endpoints.login,
|
|
3521
|
+
refreshEndpoint: options.endpoints.refresh,
|
|
3522
|
+
logoutEndpoint: options.endpoints.logout,
|
|
3523
|
+
});
|
|
3464
3524
|
},
|
|
3465
3525
|
};
|
|
3466
3526
|
|
|
3467
|
-
export { AppTypes, ArchiveTypes, ArexVueCore, AudioTypes, AxiosService, ContentTypeEnum, DocumentTypes, ERROR_MESSAGES, ERROR_STYLES, ErrorEnum, ErrorMessages, ErrorStyles, ExceptionEnum, FontTypes, ImageTypes, KeyCodeEnum, OtherTypes, RestStd, ScreenBreakpoint, ScreenSize, StorageKeyEnum, StorageTypeEnum, TextTypes, VideoTypes, ab2hex, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, axiosFetch, blobToFormData, bufferToBlob, calculateAge, cleanCredentials, clickOutside, compareObject, configAxios, configEndpoints, configSession, configTokenKeys, copyToClipboard, countWords, createCustomAxiosInstance, createFetch, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, decrypt, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, encrypt, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getAuthRefreshToken, getAuthToken, getAxiosInstance, getDecryptedItem, getEndOfMonth, getEndpointsConfig, getObjectDifferences, getObjectKeys, getQueryParam,
|
|
3527
|
+
export { AppTypes, ArchiveTypes, ArexVueCore, AudioTypes, AxiosService, ContentTypeEnum, DocumentTypes, ERROR_MESSAGES, ERROR_STYLES, ErrorEnum, ErrorMessages, ErrorStyles, ExceptionEnum, FontTypes, ImageTypes, KeyCodeEnum, OtherTypes, RestStd, ScreenBreakpoint, ScreenSize, StorageKeyEnum, StorageTypeEnum, TextTypes, VideoTypes, ab2hex, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, axiosFetch, blobToFormData, bufferToBlob, calculateAge, cleanCredentials, clickOutside, compareObject, configAppKey, configAxios, configEndpoints, configSession, configTokenKeys, copyToClipboard, countWords, createCustomAxiosInstance, createFetch, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, decrypt, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, encrypt, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getAppKey, getAuthRefreshToken, getAuthToken, getAxiosInstance, getDecryptedItem, getEndOfMonth, getEndpointsConfig, getObjectDifferences, getObjectKeys, getQueryParam, getSessionConfig, getSessionId, getSessionPersistencePreference, getStartOfMonth, getTokenConfig, handleError, hasNestedProperties, hex2ab, importKey, isEmptyObject, isLeapYear, isStrongPassword, isValidAge, isValidCreditCard, isValidDate, isValidEmail, isValidExpiryDate, isValidHexColor, isValidHexColorAlpha, isValidHexNumber, isValidIP, isValidPhoneNumber, isValidSSN, isValidTime, isValidURL, isValidUsername, isValidZIP, loadSessionConfigFromStorage, lowerFirst, objectToFormData, objectToFormDataEnhanced, objectToQueryString, openWindow, parseDate, proxyToPlainObject, readFileAsDataURL, readFileAsText, regenerateSessionId, registerKeyboardShortcuts, removeAccent, removeClickOutside, removeCustomKeyboardShortcut, removeCustomShortcuts, removeDoubleClickListener, removeEmptyProperties, removeKeyListeners, replaceAll, reverseString, safeGet, screenMap, scrollToTop, simulateKeyPress, stopDetectingKeyHold, storeAuthRefreshToken, storeAuthToken, storeEncryptedItem, stringToBlob, subtractDays, throttle, toCamelCase, toKebabCase, toggleTabNavigation, truncateString, unregisterKeyboardShortcuts, upperFirst, useAuth, useBreakpoint, useFilter, usePagination, useSorter, useVueQuery, validateAlphanumeric, validateLetters, validateNumbers, verifyAuth };
|
|
@@ -1,26 +1,13 @@
|
|
|
1
1
|
export interface ArexVueCoreOptions {
|
|
2
|
-
|
|
3
|
-
* The authentication endpoints.
|
|
4
|
-
*/
|
|
2
|
+
appKey: string;
|
|
5
3
|
endpoints: {
|
|
6
|
-
/** The login endpoint. */
|
|
7
4
|
login: string;
|
|
8
|
-
/** The token refresh endpoint. */
|
|
9
5
|
refresh: string;
|
|
10
|
-
/** The logout endpoint. */
|
|
11
6
|
logout: string;
|
|
12
7
|
};
|
|
13
|
-
/**
|
|
14
|
-
* The key prefixes for storing tokens.
|
|
15
|
-
*/
|
|
16
8
|
tokenKeys: {
|
|
17
|
-
/** The access token key prefix. */
|
|
18
9
|
accessToken: string;
|
|
19
|
-
/** The refresh token key prefix. */
|
|
20
10
|
refreshToken: string;
|
|
21
11
|
};
|
|
22
|
-
/**
|
|
23
|
-
* The base URL for the API.
|
|
24
|
-
*/
|
|
25
12
|
apiUrl: string;
|
|
26
13
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -55,4 +55,4 @@ export declare const storeAuthRefreshToken: (token: string, secretKey: string, p
|
|
|
55
55
|
* @throws {Error} "TOKEN_MISSING" if no token is found, "TOKEN_EXPIRED" if the token has expired,
|
|
56
56
|
* "TOKEN_INVALID" if the token format is invalid.
|
|
57
57
|
*/
|
|
58
|
-
export declare const verifyAuth: (
|
|
58
|
+
export declare const verifyAuth: () => Promise<boolean>;
|
package/dist/utils/storage.d.ts
CHANGED
|
@@ -4,16 +4,16 @@
|
|
|
4
4
|
* @param key The key under which to store the value.
|
|
5
5
|
* @param value The value to encrypt and store.
|
|
6
6
|
* @param secretKey The secret key for encryption.
|
|
7
|
-
* @param
|
|
7
|
+
* @param persistent If true, uses localStorage; otherwise, uses sessionStorage.
|
|
8
8
|
* @returns A promise that resolves when the item is stored. Throws an error if it fails.
|
|
9
9
|
*/
|
|
10
|
-
export declare function storeEncryptedItem(key: string, value: string, secretKey: string,
|
|
10
|
+
export declare function storeEncryptedItem(key: string, value: string, secretKey: string, persistent: boolean): Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* Retrieves and decrypts a value from local or session storage.
|
|
13
13
|
* Assumes the `window` environment is available.
|
|
14
14
|
* @param key The key of the item to retrieve.
|
|
15
15
|
* @param secretKey The secret key for decryption.
|
|
16
|
-
* @param
|
|
16
|
+
* @param persistent If true, searches localStorage; otherwise, sessionStorage.
|
|
17
17
|
* @returns A promise that resolves with the decrypted value or null if not found or decryption fails.
|
|
18
18
|
*/
|
|
19
|
-
export declare function getDecryptedItem(key: string, secretKey: string,
|
|
19
|
+
export declare function getDecryptedItem(key: string, secretKey: string, persistent: boolean): Promise<string | null>;
|