@anmiles/google-api-wrapper 19.0.0 → 19.0.2
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/CHANGELOG.md +8 -0
- package/dist/lib/credentials/index.d.ts.map +1 -1
- package/dist/lib/credentials/index.js +3 -2
- package/dist/lib/credentials/index.js.map +1 -1
- package/dist/lib/credentials/validator.d.ts +3 -2
- package/dist/lib/credentials/validator.d.ts.map +1 -1
- package/dist/lib/credentials/validator.js +2 -3
- package/dist/lib/credentials/validator.js.map +1 -1
- package/dist/lib/secrets.js +5 -4
- package/dist/lib/secrets.js.map +1 -1
- package/dist/templates/index.html +1 -1
- package/package.json +1 -1
- package/src/lib/__tests__/__snapshots__/renderer.test.ts.snap +2 -2
- package/src/lib/__tests__/__snapshots__/secrets.test.ts.snap +2 -2
- package/src/lib/credentials/__tests__/index.test.ts +6 -6
- package/src/lib/credentials/__tests__/validator.test.ts +23 -14
- package/src/lib/credentials/index.ts +3 -2
- package/src/lib/credentials/validator.ts +8 -3
- package/src/lib/secrets.ts +6 -4
- package/src/templates/index.html +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [19.0.2](../../tags/v19.0.2) - 2025-05-19
|
|
9
|
+
### Changed
|
|
10
|
+
- Fixed typo
|
|
11
|
+
|
|
12
|
+
## [19.0.1](../../tags/v19.0.1) - 2025-05-19
|
|
13
|
+
### Changed
|
|
14
|
+
- Fixed expecting refresh_token in temporary credentials
|
|
15
|
+
|
|
8
16
|
## [19.0.0](../../tags/v19.0.0) - 2025-05-18
|
|
9
17
|
__(BREAKING) Dropped support for NodeJS 18 (EOL). Minimum required version is now NodeJS 20.__
|
|
10
18
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/credentials/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/credentials/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,CA+BvJ;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMvD"}
|
|
@@ -13,7 +13,7 @@ async function getCredentials(profile, auth, options) {
|
|
|
13
13
|
const credentialsFile = (0, paths_1.getCredentialsFile)(profile);
|
|
14
14
|
if (options?.temporary) {
|
|
15
15
|
const credentials = await (0, generator_1.generateCredentials)(profile, auth, options);
|
|
16
|
-
const validationResult =
|
|
16
|
+
const validationResult = (0, validator_1.validateCredentials)(credentials, options);
|
|
17
17
|
if (!validationResult.isValid) {
|
|
18
18
|
throw new Error(validationResult.validationError);
|
|
19
19
|
}
|
|
@@ -30,7 +30,8 @@ async function getCredentials(profile, auth, options) {
|
|
|
30
30
|
refresh_token: refreshToken,
|
|
31
31
|
...credentials,
|
|
32
32
|
};
|
|
33
|
-
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
34
|
+
}, async (credentials) => (0, validator_1.validateCredentials)(credentials));
|
|
34
35
|
}
|
|
35
36
|
function deleteCredentials(profile) {
|
|
36
37
|
const credentialsFile = (0, paths_1.getCredentialsFile)(profile);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/credentials/index.ts"],"names":[],"mappings":";;;;;AAUA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/credentials/index.ts"],"names":[],"mappings":";;;;;AAUA,wCA+BC;AAED,8CAMC;AAjDD,4CAAoB;AAKpB,0CAAoD;AAEpD,2CAAkD;AAClD,2CAAkD;AAE3C,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,IAAoC,EAAE,OAAqB;IAChH,MAAM,eAAe,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAC,CAAC;IAEpD,IAAI,OAAO,EAAE,SAAS,EAAE,CAAC;QACxB,MAAM,WAAW,GAAQ,MAAM,IAAA,+BAAmB,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3E,MAAM,gBAAgB,GAAG,IAAA,+BAAmB,EAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAEnE,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;QACnD,CAAC;QAED,OAAO,WAAW,CAAC;IACpB,CAAC;IAED,OAAO,YAAE,CAAC,YAAY,CAAC,eAAe,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,YAAY,GAAG,YAAE,CAAC,UAAU,CAAC,eAAe,CAAC;YAClD,CAAC,CAAC,YAAE,CAAC,QAAQ,CAA8B,eAAe,CAAC,CAAC,aAAa;YACzE,CAAC,CAAC,SAAS,CAAC;QAEb,MAAM,WAAW,GAAG,MAAM,IAAA,+BAAmB,EAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EACnE,YAAY;YACX,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,SAAS,CACZ,CAAC;QAEF,OAAO;YACN,aAAa,EAAE,YAAY;YAC3B,GAAG,WAAW;SACd,CAAC;QACH,4DAA4D;IAC5D,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,IAAA,+BAAmB,EAAC,WAAW,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,SAAgB,iBAAiB,CAAC,OAAe;IAChD,MAAM,eAAe,GAAG,IAAA,0BAAkB,EAAC,OAAO,CAAC,CAAC;IAEpD,IAAI,YAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,YAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAC5B,CAAC;AACF,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type GoogleApis from 'googleapis';
|
|
2
|
-
|
|
2
|
+
import type { AuthOptions } from '../../types/options';
|
|
3
|
+
export declare function validateCredentials(credentials: GoogleApis.Auth.Credentials, options?: AuthOptions): {
|
|
3
4
|
isValid: boolean;
|
|
4
5
|
validationError?: string;
|
|
5
|
-
}
|
|
6
|
+
};
|
|
6
7
|
//# sourceMappingURL=validator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/lib/credentials/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/lib/credentials/validator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,YAAY,CAAC;AAEzC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,wBAAgB,mBAAmB,CAClC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,WAAW,EACxC,OAAO,CAAC,EAAE,WAAW,GACnB;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAmBhD"}
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateCredentials = validateCredentials;
|
|
4
4
|
const tokenExpiration = 7 * 24 * 60 * 60 * 1000;
|
|
5
|
-
|
|
6
|
-
async function validateCredentials(credentials) {
|
|
5
|
+
function validateCredentials(credentials, options) {
|
|
7
6
|
if (!credentials.access_token) {
|
|
8
7
|
return { isValid: false, validationError: 'Credentials does not have access_token' };
|
|
9
8
|
}
|
|
10
|
-
if (!credentials.refresh_token) {
|
|
9
|
+
if (!credentials.refresh_token && !options?.temporary) {
|
|
11
10
|
return { isValid: false, validationError: 'Credentials does not have refresh_token' };
|
|
12
11
|
}
|
|
13
12
|
if (!credentials.expiry_date) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/lib/credentials/validator.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../src/lib/credentials/validator.ts"],"names":[],"mappings":";;AAMA,kDAsBC;AAxBD,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhD,SAAgB,mBAAmB,CAClC,WAAwC,EACxC,OAAqB;IAGrB,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,wCAAwC,EAAE,CAAC;IACtF,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,aAAa,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;QACvD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,yCAAyC,EAAE,CAAC;IACvF,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC9B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,uCAAuC,EAAE,CAAC;IACrF,CAAC;IAED,IAAI,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,WAAW,IAAI,eAAe,EAAE,CAAC;QACvE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
|
package/dist/lib/secrets.js
CHANGED
|
@@ -20,14 +20,15 @@ function checkSecrets(secretsObject) {
|
|
|
20
20
|
function getSecrets(profile) {
|
|
21
21
|
const secretsFile = (0, paths_1.getSecretsFile)(profile);
|
|
22
22
|
const secretsObject = fs_1.default.getJSON(secretsFile, () => {
|
|
23
|
-
throw new Error(getSecretsError(
|
|
23
|
+
throw new Error(getSecretsError(secretsFile));
|
|
24
24
|
});
|
|
25
25
|
checkSecrets(secretsObject);
|
|
26
26
|
return secretsObject;
|
|
27
27
|
}
|
|
28
|
-
function getSecretsError(
|
|
28
|
+
function getSecretsError(secretsFile) {
|
|
29
|
+
const relativePath = secretsFile.replace('\\', '/');
|
|
29
30
|
return [
|
|
30
|
-
`File ${
|
|
31
|
+
`File ${relativePath} not found!`,
|
|
31
32
|
'Here is how to obtain it:',
|
|
32
33
|
'\tGo to https://console.cloud.google.com/projectcreate',
|
|
33
34
|
'\t\tChoose project name',
|
|
@@ -57,7 +58,7 @@ function getSecretsError(profile, secretsFile) {
|
|
|
57
58
|
'\t\t\t\tSpecify app name, i.e. "NodeJS"',
|
|
58
59
|
`\t\t\t\tAdd authorized redirect URI: ${callbackURI}`,
|
|
59
60
|
'\t\t\t\tClick "CREATE"',
|
|
60
|
-
`\t\t\t\tClick "DOWNLOAD JSON" and download credentials to
|
|
61
|
+
`\t\t\t\tClick "DOWNLOAD JSON" and download credentials to ${relativePath}`,
|
|
61
62
|
'Then start this script again',
|
|
62
63
|
].join('\n');
|
|
63
64
|
}
|
package/dist/lib/secrets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":";;;;;AAoBA,gCAOC;AA3BD,4CAAoB;AAEpB,+BAA6B;AAI7B,qCAAqC;AACrC,yCAA+C;AAE/C,MAAM,IAAI,GAAU,IAAI,CAAC;AACzB,MAAM,IAAI,GAAU,aAAa,IAAI,EAAE,CAAC;AACxC,MAAM,WAAW,GAAG,UAAU,IAAI,gBAAgB,CAAC;AAEnD,SAAS,YAAY,CAAC,aAAsB;IAC3C,IAAI,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qDAAqD,WAAW,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,SAAgB,UAAU,CAAC,OAAe;IACzC,MAAM,WAAW,GAAK,IAAA,sBAAc,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,YAAE,CAAC,OAAO,CAAU,WAAW,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../src/lib/secrets.ts"],"names":[],"mappings":";;;;;AAoBA,gCAOC;AA3BD,4CAAoB;AAEpB,+BAA6B;AAI7B,qCAAqC;AACrC,yCAA+C;AAE/C,MAAM,IAAI,GAAU,IAAI,CAAC;AACzB,MAAM,IAAI,GAAU,aAAa,IAAI,EAAE,CAAC;AACxC,MAAM,WAAW,GAAG,UAAU,IAAI,gBAAgB,CAAC;AAEnD,SAAS,YAAY,CAAC,aAAsB;IAC3C,IAAI,aAAa,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qDAAqD,WAAW,EAAE,CAAC,CAAC;AACrF,CAAC;AAED,SAAgB,UAAU,CAAC,OAAe;IACzC,MAAM,WAAW,GAAK,IAAA,sBAAc,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,aAAa,GAAG,YAAE,CAAC,OAAO,CAAU,WAAW,EAAE,GAAG,EAAE;QAC3D,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IACH,YAAY,CAAC,aAAa,CAAC,CAAC;IAC5B,OAAO,aAAa,CAAC;AACtB,CAAC;AAED,SAAS,eAAe,CAAC,WAAmB;IAC3C,MAAM,YAAY,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAEpD,OAAO;QACN,QAAQ,YAAY,aAAa;QACjC,2BAA2B;QAC3B,wDAAwD;QACxD,yBAAyB;QACzB,2DAA2D;QAC3D,yDAAyD;QACzD,+DAA+D;QAC/D,sCAAsC;QACtC,0BAA0B;QAC1B,yDAAyD;QACzD,iDAAiD;QACjD,qDAAqD;QACrD,2BAA2B;QAC3B,wBAAwB;QACxB,wCAAwC;QACxC,0GAA0G;QAC1G,mCAAmC;QACnC,oCAAoC;QACpC,uBAAuB,IAAA,kBAAS,GAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC9C,mCAAmC;QACnC,yBAAyB;QACzB,wBAAwB;QACxB,mCAAmC;QACnC,oDAAoD;QACpD,6CAA6C;QAC7C,+DAA+D;QAC/D,mDAAmD;QACnD,yCAAyC;QACzC,wCAAwC,WAAW,EAAE;QACrD,wBAAwB;QACxB,6DAA6D,YAAY,EAAE;QAC3E,8BAA8B;KAC9B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC"}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ exports[`src/lib/renderer renderAuth should return auth page 1`] = `
|
|
|
4
4
|
"<!DOCTYPE html>
|
|
5
5
|
<html>
|
|
6
6
|
<head>
|
|
7
|
-
<title>Google API sign-in
|
|
7
|
+
<title>Google API sign-in</title>
|
|
8
8
|
<meta charset="utf-8">
|
|
9
9
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
10
10
|
</head>
|
|
@@ -143,7 +143,7 @@ exports[`src/lib/renderer renderDone should return done page 1`] = `
|
|
|
143
143
|
"<!DOCTYPE html>
|
|
144
144
|
<html>
|
|
145
145
|
<head>
|
|
146
|
-
<title>Google API sign-in
|
|
146
|
+
<title>Google API sign-in</title>
|
|
147
147
|
<meta charset="utf-8">
|
|
148
148
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
149
149
|
</head>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`src/lib/secrets getSecrets should throw if callbackURI is incorrect 1`] = `"Error in credentials file: redirect URI should be http://localhost:6006/oauthcallback"`;
|
|
4
4
|
|
|
5
5
|
exports[`src/lib/secrets getSecrets should throw if no secrets file 1`] = `
|
|
6
|
-
"File secrets
|
|
6
|
+
"File secrets/username1.json not found!
|
|
7
7
|
Here is how to obtain it:
|
|
8
8
|
Go to https://console.cloud.google.com/projectcreate
|
|
9
9
|
Choose project name
|
|
@@ -33,6 +33,6 @@ Here is how to obtain it:
|
|
|
33
33
|
Specify app name, i.e. "NodeJS"
|
|
34
34
|
Add authorized redirect URI: http://localhost:6006/oauthcallback
|
|
35
35
|
Click "CREATE"
|
|
36
|
-
Click "DOWNLOAD JSON" and download credentials to
|
|
36
|
+
Click "DOWNLOAD JSON" and download credentials to secrets/username1.json
|
|
37
37
|
Then start this script again"
|
|
38
38
|
`;
|
|
@@ -41,7 +41,7 @@ beforeEach(() => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
generateCredentialsMock.mockResolvedValue(generatedCredentials);
|
|
44
|
-
validateCredentialsMock.
|
|
44
|
+
validateCredentialsMock.mockReturnValue({ isValid: true });
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
afterAll(() => {
|
|
@@ -99,7 +99,7 @@ describe('src/lib/credentials/index', () => {
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
it('should throw if saved credentials do not pass validation', async () => {
|
|
102
|
-
validateCredentialsMock.
|
|
102
|
+
validateCredentialsMock.mockReturnValueOnce({ isValid: false, validationError: 'Test error' });
|
|
103
103
|
|
|
104
104
|
const promise = getCredentials(profile, auth);
|
|
105
105
|
|
|
@@ -109,7 +109,7 @@ describe('src/lib/credentials/index', () => {
|
|
|
109
109
|
|
|
110
110
|
describe('on existing file with failed validation', () => {
|
|
111
111
|
beforeEach(() => {
|
|
112
|
-
validateCredentialsMock.
|
|
112
|
+
validateCredentialsMock.mockReturnValueOnce({ isValid: false });
|
|
113
113
|
});
|
|
114
114
|
|
|
115
115
|
it('should return generated credentials', async () => {
|
|
@@ -150,7 +150,7 @@ describe('src/lib/credentials/index', () => {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
it('should throw if generated credentials do not pass validation', async () => {
|
|
153
|
-
validateCredentialsMock.
|
|
153
|
+
validateCredentialsMock.mockReturnValueOnce({ isValid: false, validationError: 'Test error' });
|
|
154
154
|
|
|
155
155
|
const promise = getCredentials(profile, auth);
|
|
156
156
|
|
|
@@ -180,11 +180,11 @@ describe('src/lib/credentials/index', () => {
|
|
|
180
180
|
it('should call validation on generated credentials', async () => {
|
|
181
181
|
await getCredentials(profile, auth, { temporary: true });
|
|
182
182
|
|
|
183
|
-
expect(validateCredentialsMock).toHaveBeenCalledWith(generatedCredentials);
|
|
183
|
+
expect(validateCredentialsMock).toHaveBeenCalledWith(generatedCredentials, { temporary: true });
|
|
184
184
|
});
|
|
185
185
|
|
|
186
186
|
it('should throw if generated credentials do not pass validation', async () => {
|
|
187
|
-
validateCredentialsMock.
|
|
187
|
+
validateCredentialsMock.mockReturnValueOnce({ isValid: false, validationError: 'Test error' });
|
|
188
188
|
|
|
189
189
|
const promise = getCredentials(profile, auth, { temporary: true });
|
|
190
190
|
|
|
@@ -2,32 +2,41 @@ import { validateCredentials } from '../validator';
|
|
|
2
2
|
|
|
3
3
|
describe('src/lib/credentials/validator', () => {
|
|
4
4
|
describe('validateCredentials', () => {
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
let expiryDate: Date;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
expiryDate = new Date();
|
|
9
|
+
expiryDate.setDate(expiryDate.getDate() - 6);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('should return false if no access token', () => {
|
|
13
|
+
expect(validateCredentials({ refresh_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
7
14
|
.toEqual({ isValid: false, validationError: 'Credentials does not have access_token' });
|
|
8
15
|
});
|
|
9
16
|
|
|
10
|
-
it('should return false if no refresh token',
|
|
11
|
-
expect(
|
|
17
|
+
it('should return false if no refresh token', () => {
|
|
18
|
+
expect(validateCredentials({ access_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
12
19
|
.toEqual({ isValid: false, validationError: 'Credentials does not have refresh_token' });
|
|
13
20
|
});
|
|
14
21
|
|
|
15
|
-
it('should return
|
|
16
|
-
expect(
|
|
22
|
+
it('should return true if no refresh token for temporary credentials', () => {
|
|
23
|
+
expect(validateCredentials({ access_token: 'token', expiry_date: expiryDate.getTime() }, { temporary: true }))
|
|
24
|
+
.toEqual({ isValid: true });
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should return false if no expiration date', () => {
|
|
28
|
+
expect(validateCredentials({ access_token: 'token', refresh_token: 'token' }))
|
|
17
29
|
.toEqual({ isValid: false, validationError: 'Credentials does not have expiry_date' });
|
|
18
30
|
});
|
|
19
31
|
|
|
20
|
-
it('should return true if credentials are not more than 1 week ago',
|
|
21
|
-
|
|
22
|
-
expiryDate.setDate(expiryDate.getDate() - 6);
|
|
23
|
-
expect(await validateCredentials({ access_token: 'token', refresh_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
32
|
+
it('should return true if credentials are not more than 1 week ago', () => {
|
|
33
|
+
expect(validateCredentials({ access_token: 'token', refresh_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
24
34
|
.toEqual({ isValid: true });
|
|
25
35
|
});
|
|
26
36
|
|
|
27
|
-
it('should return false if credentials are more than 1 week ago',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
expect(await validateCredentials({ access_token: 'token', refresh_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
37
|
+
it('should return false if credentials are more than 1 week ago', () => {
|
|
38
|
+
expiryDate.setDate(expiryDate.getDate() - 2);
|
|
39
|
+
expect(validateCredentials({ access_token: 'token', refresh_token: 'token', expiry_date: expiryDate.getTime() }))
|
|
31
40
|
.toEqual({ isValid: false, validationError: 'Credentials expired' });
|
|
32
41
|
});
|
|
33
42
|
});
|
|
@@ -13,7 +13,7 @@ export async function getCredentials(profile: string, auth: GoogleApis.Common.OA
|
|
|
13
13
|
|
|
14
14
|
if (options?.temporary) {
|
|
15
15
|
const credentials = await generateCredentials(profile, auth, options);
|
|
16
|
-
const validationResult =
|
|
16
|
+
const validationResult = validateCredentials(credentials, options);
|
|
17
17
|
|
|
18
18
|
if (!validationResult.isValid) {
|
|
19
19
|
throw new Error(validationResult.validationError);
|
|
@@ -37,7 +37,8 @@ export async function getCredentials(profile: string, auth: GoogleApis.Common.OA
|
|
|
37
37
|
refresh_token: refreshToken,
|
|
38
38
|
...credentials,
|
|
39
39
|
};
|
|
40
|
-
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
41
|
+
}, async (credentials) => validateCredentials(credentials));
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export function deleteCredentials(profile: string): void {
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type GoogleApis from 'googleapis';
|
|
2
2
|
|
|
3
|
+
import type { AuthOptions } from '../../types/options';
|
|
4
|
+
|
|
3
5
|
const tokenExpiration = 7 * 24 * 60 * 60 * 1000;
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
export function validateCredentials(
|
|
8
|
+
credentials: GoogleApis.Auth.Credentials,
|
|
9
|
+
options?: AuthOptions,
|
|
10
|
+
): { isValid: boolean; validationError?: string } {
|
|
11
|
+
|
|
7
12
|
if (!credentials.access_token) {
|
|
8
13
|
return { isValid: false, validationError: 'Credentials does not have access_token' };
|
|
9
14
|
}
|
|
10
15
|
|
|
11
|
-
if (!credentials.refresh_token) {
|
|
16
|
+
if (!credentials.refresh_token && !options?.temporary) {
|
|
12
17
|
return { isValid: false, validationError: 'Credentials does not have refresh_token' };
|
|
13
18
|
}
|
|
14
19
|
|
package/src/lib/secrets.ts
CHANGED
|
@@ -21,15 +21,17 @@ function checkSecrets(secretsObject: Secrets): true {
|
|
|
21
21
|
export function getSecrets(profile: string): Secrets {
|
|
22
22
|
const secretsFile = getSecretsFile(profile);
|
|
23
23
|
const secretsObject = fs.getJSON<Secrets>(secretsFile, () => {
|
|
24
|
-
throw new Error(getSecretsError(
|
|
24
|
+
throw new Error(getSecretsError(secretsFile));
|
|
25
25
|
});
|
|
26
26
|
checkSecrets(secretsObject);
|
|
27
27
|
return secretsObject;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function getSecretsError(
|
|
30
|
+
function getSecretsError(secretsFile: string): string {
|
|
31
|
+
const relativePath = secretsFile.replace('\\', '/');
|
|
32
|
+
|
|
31
33
|
return [
|
|
32
|
-
`File ${
|
|
34
|
+
`File ${relativePath} not found!`,
|
|
33
35
|
'Here is how to obtain it:',
|
|
34
36
|
'\tGo to https://console.cloud.google.com/projectcreate',
|
|
35
37
|
'\t\tChoose project name',
|
|
@@ -59,7 +61,7 @@ function getSecretsError(profile: string, secretsFile: string): string {
|
|
|
59
61
|
'\t\t\t\tSpecify app name, i.e. "NodeJS"',
|
|
60
62
|
`\t\t\t\tAdd authorized redirect URI: ${callbackURI}`,
|
|
61
63
|
'\t\t\t\tClick "CREATE"',
|
|
62
|
-
`\t\t\t\tClick "DOWNLOAD JSON" and download credentials to
|
|
64
|
+
`\t\t\t\tClick "DOWNLOAD JSON" and download credentials to ${relativePath}`,
|
|
63
65
|
'Then start this script again',
|
|
64
66
|
].join('\n');
|
|
65
67
|
}
|
package/src/templates/index.html
CHANGED