Skip to content
This repository was archived by the owner on Sep 23, 2025. It is now read-only.

Commit a184f0d

Browse files
committed
Fix compatibility with API v3
1 parent 9c507dd commit a184f0d

26 files changed

+2419
-386
lines changed

README.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,26 @@
66
/_/ \__,_/____/____/_.___/\____/_/\__/
77

88
Open source password manager for teams
9-
(c) 2020 Passbolt SA
9+
(c) 2021 Passbolt SA
1010

1111
## License
1212

13-
This program is free software: you can redistribute it and/or modify
14-
it under the terms of the GNU Affero General Public License as
15-
published by the Free Software Foundation, either version 3 of the
16-
License, or (at your option) any later version.
13+
Passbolt - Open source password manager for teams
1714

18-
This program is distributed in the hope that it will be useful,
19-
but without any warranty; without even the implied warranty of
20-
merchantability or fitness for a particular purpose. See the
21-
GNU Affero General Public License for more details.
15+
(c) 2021 Passbolt SA
2216

23-
[Affero General Public License v3](http://www.gnu.org/licenses/agpl-3.0.html)
17+
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
18+
Public License (AGPL) as published by the Free Software Foundation version 3.
19+
20+
The name "Passbolt" is a registered trademark of Passbolt SA, and Passbolt SA hereby declines to grant a trademark
21+
license to "Passbolt" pursuant to the GNU Affero General Public License version 3 Section 7(e), without a separate
22+
agreement with Passbolt SA.
23+
24+
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
25+
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See GNU Affero General Public License for more details.
26+
27+
You should have received a copy of the GNU Affero General Public License along with this program. If not,
28+
see [GNU Affero General Public License v3](http://www.gnu.org/licenses/agpl-3.0.html).
2429

2530
# What is the purpose of this repository
2631

app/controllers/appController.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
1111
* @link https://www.passbolt.com Passbolt(tm)
1212
*/
13-
const i18n = require('../models/i18n.js');
1413
const GpgAuthController = require('./gpgAuthController.js');
1514
const validate = require('validator');
1615

@@ -28,15 +27,15 @@ class AppController extends GpgAuthController {
2827
* App controllers should not be instanciated without a name
2928
*/
3029
getName() {
31-
throw new Error(i18n.__('Error: no controller name set'));
30+
throw new Error('Error: no controller name set');
3231
}
3332

3433
/**
3534
* Index Action - Find and filter
3635
* @returns {Promise<*>}
3736
*/
3837
async index() {
39-
const url = `${this.URL_BASE}.json?api-version=v1`;
38+
const url = `${this.URL_BASE}.json?api-version=v2`;
4039
const request = {
4140
url,
4241
jar: this.cookieJar
@@ -58,11 +57,11 @@ class AppController extends GpgAuthController {
5857
async view(id, options) {
5958
// Check if this is a valid UUID
6059
if (!validate.isUUID(id)) {
61-
this.error(i18n.__(`This is not a valid UUID: ${id}`));
60+
this.error(`This is not a valid UUID: ${id}`);
6261
}
6362

6463
// Get the record
65-
let url = `${this.URL_BASE}/${id}.json?api-version=v1&`;
64+
let url = `${this.URL_BASE}/${id}.json?api-version=v2&`;
6665
if (typeof options !== 'undefined') {
6766
url += options;
6867
}

app/controllers/controller.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
1111
* @link https://www.passbolt.com Passbolt(tm)
1212
*/
13-
const i18n = require('../models/i18n.js');
1413
const Config = require('../models/config.js');
1514

1615
class Controller {
@@ -20,7 +19,7 @@ class Controller {
2019
*/
2120
constructor(program) {
2221
this._request = require('request');
23-
this._verbose = (program !== undefined && program.verbose !== undefined && program.verbose);
22+
this._verbose = (program && program.opts() && program.opts().verbose);
2423
const config = Config.get();
2524
this._agentOptions = config.agentOptions;
2625
}
@@ -53,11 +52,11 @@ class Controller {
5352
resolve(result);
5453
})
5554
.on('error', () => {
56-
const err = new Error(i18n.__('Error: could not connect to ') + options.url);
55+
const err = new Error(`Error: could not connect to ${options.url}`);
5756
reject(err);
5857
});
5958
} catch (error) {
60-
const err = new Error(i18n.__('Error: could not connect to ') + options.url);
59+
const err = new Error(`Error: could not connect to ${options.url}`);
6160
reject(err);
6261
}
6362
});
@@ -91,11 +90,11 @@ class Controller {
9190
resolve(result);
9291
})
9392
.on('error', () => {
94-
const err = new Error(i18n.__('Error: could not connect to ') + options.url);
93+
const err = new Error(`Error: could not connect to ${options.url}`);
9594
reject(err);
9695
});
9796
} catch (error) {
98-
const err = new Error(i18n.__('Error: could not connect to ') + options.url);
97+
const err = new Error(`Error: could not connect to ${options.url}`);
9998
reject(err);
10099
}
101100
});
@@ -119,6 +118,9 @@ class Controller {
119118
error(error) {
120119
if (error instanceof Error) {
121120
this.log(error.message);
121+
if (this._verbose) {
122+
this.log(error);
123+
}
122124
} else if (typeof error === 'string') {
123125
this.log(error);
124126
} else {
@@ -140,7 +142,7 @@ class Controller {
140142
body = JSON.parse(response.body);
141143
} catch (syntaxError) {
142144
this.log(response.body.toString(), 'verbose');
143-
this.error(`${i18n.__('Error')} ${response.statusCode} ${i18n.__('could not parse server response.')}`);
145+
this.error(`'Error ${response.statusCode} could not parse server response.`);
144146
return;
145147
}
146148
return body;

app/controllers/gpgAuthController.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ const CookieStore = require('tough-cookie-file-store');
1616
const Crypto = require('../models/crypto.js');
1717
const GpgAuthToken = require('../models/gpgAuthToken.js');
1818
const GpgAuthHeader = require('../models/gpgAuthHeader.js');
19-
const i18n = require('../models/i18n.js');
2019
const path = require('path');
2120
const User = require('../models/user.js');
2221

@@ -44,7 +43,7 @@ class GpgAuthController extends MfaController {
4443
// URLs
4544
const baseUrl = `${this.domain.url}/auth`;
4645
this.URL_VERIFY = `${baseUrl}/verify.json`;
47-
this.URL_CHECKSESSION = `${baseUrl}/checkSession.json`;
46+
this.URL_CHECKSESSION = `${baseUrl}/is-authenticated.json`;
4847
this.URL_LOGIN = `${baseUrl}/login.json`;
4948
this.URL_LOGOUT = `${baseUrl}/logout`;
5049

@@ -132,12 +131,12 @@ class GpgAuthController extends MfaController {
132131

133132
async getCsrfToken() {
134133
return new Promise((resolve, reject) => {
135-
const domain = new URL(this.domain.url).host;
134+
const domain = new URL(this.domain.url).hostname;
136135
const path = '/';
137136
const key = 'csrfToken';
138137

139138
this.cookieStore.findCookie(domain, path, key, (error, cookie) => {
140-
if (cookie === null) {
139+
if (!cookie) {
141140
reject();
142141
} else {
143142
resolve(cookie.value);
@@ -268,21 +267,22 @@ class GpgAuthController extends MfaController {
268267
_serverResponseHealthCheck(step, response) {
269268
// Check if the HTTP status is OK
270269
if (response.statusCode !== 200) {
271-
throw new Error(`${i18n.__('There was a problem when trying to communicate with the server')
272-
} (HTTP Code:${response.status})`);
270+
throw new Error(`There was a problem when trying to communicate with the server (HTTP Code:${response.status})`);
273271
}
274272

275273
// Check if there is GPGAuth error flagged by the server
276-
if (response.headers['x-gpgauth-error']) {
277-
throw new Error(i18n.__('The server rejected the verification request.') + response.headers['x-gpgauth-debug']);
274+
if (step !== 'logout') {
275+
if (response.headers['x-gpgauth-error']) {
276+
throw new Error(`The server rejected the verification request ${response.headers['x-gpgauth-debug']}`);
277+
}
278278
}
279279

280280
// Check if the headers are correct
281281
try {
282282
GpgAuthHeader.validateByStage(step, response.headers);
283283
} catch (error) {
284284
this.log(error.message, 'verbose');
285-
throw new Error(i18n.__('The server was unable to respect the authentication protocol.'));
285+
throw new Error('The server was unable to respect the authentication protocol.');
286286
}
287287

288288
return true;
@@ -302,11 +302,11 @@ class GpgAuthController extends MfaController {
302302
GpgAuthToken.validate('token', token);
303303
} catch (error) {
304304
console.log(error.message, 'verbose');
305-
throw new Error(i18n.__('Error: GPGAuth verify step failed. Maybe your user does not exist or have been deleted.'));
305+
throw new Error('Error: GPGAuth verify step failed. Maybe your user does not exist or have been deleted.');
306306
}
307307

308308
if (!this.token || token !== this.token) {
309-
throw new Error(i18n.__('Error: The server was unable to identify. GPGAuth tokens do not match.'));
309+
throw new Error('Error: The server was unable to identify. GPGAuth tokens do not match.');
310310
}
311311
return response;
312312
}
@@ -371,7 +371,7 @@ class GpgAuthController extends MfaController {
371371
body = JSON.parse(response.body);
372372
} catch (syntaxError) {
373373
this.log(response.body.toString(), 'verbose');
374-
this.error(`${i18n.__('Error')} ${response.statusCode} ${i18n.__('could not parse server response.')}`);
374+
this.error(`Error ${response.statusCode} could not parse server response.`);
375375
return;
376376
}
377377
return body;

app/controllers/mfaController.js

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
const CliController = require('./cliController.js');
1414
const Domain = require('../models/domain.js');
1515
const Config = require('../models/config.js');
16-
const i18n = require('../models/i18n.js');
1716

1817
class MfaController extends CliController {
1918
/**
@@ -76,7 +75,7 @@ class MfaController extends CliController {
7675

7776
if (response.statusCode !== 200) {
7877
this.log(JSON.parse(response.body), 'verbose');
79-
const msg = `${i18n.__('There was a problem with MFA authentication.')} (HTTP Code:${response.statusCode})\n`;
78+
const msg = `There was a problem with MFA authentication. (HTTP Code:${response.statusCode})`;
8079
this.error(msg);
8180
}
8281
}
@@ -102,7 +101,8 @@ class MfaController extends CliController {
102101
}
103102
}
104103
if (!provider) {
105-
const msg = i18n.__('No supported MFA provider found in config. Please setup an additional provider using passbolt web client.');
104+
const msg = 'No supported MFA provider found in config.' +
105+
' Please setup an additional provider using passbolt web client.';
106106
throw new Error(msg);
107107
}
108108
return provider;
@@ -121,11 +121,11 @@ class MfaController extends CliController {
121121
} else {
122122
userProviders = config.mfa.providers;
123123
if (!Array.isArray(userProviders) || userProviders.length === 0) {
124-
const msg = i18n.__('No supported MFA provider found in user config. Please setup MFA provider preferences.');
124+
const msg = 'No supported MFA provider found in user config. Please setup MFA provider preferences.';
125125
this.error(msg);
126126
}
127127
if (userProviders.length === 1 && userProviders[0].toLowerCase() === 'duo') {
128-
const msg = i18n.__('Duo is not a supported MFA provider. Please edit MFA provider preferences to include more providers.');
128+
const msg ='Duo is not a supported MFA provider. Please edit MFA provider preferences to include more providers.';
129129
this.error(msg);
130130
}
131131
for (let i = 0; i < userProviders.length; i++) {
@@ -150,7 +150,7 @@ class MfaController extends CliController {
150150
url = this.URL_MFA_VERIFY_TOTP;
151151
break;
152152
default:
153-
this.error(i18n.__(`MFA provider not supported: ${this.provider}`));
153+
this.error(`MFA provider not supported: ${this.provider}`);
154154
}
155155
return url;
156156
}
@@ -171,7 +171,7 @@ class MfaController extends CliController {
171171
data = {'totp': otp};
172172
break;
173173
default:
174-
this.error(i18n.__(`MFA provider not supported: ${this.provider}`));
174+
this.error(`MFA provider not supported: ${this.provider}`);
175175
}
176176
return data;
177177
}
@@ -203,9 +203,9 @@ class MfaController extends CliController {
203203
const input = await this.prompt({
204204
properties: {
205205
otp: {
206-
description: i18n.__('Please enter the one time password displayed on your tablet or phone.\notp'),
206+
description: 'Please enter the one time password displayed on your tablet or phone.\notp',
207207
pattern: /^[0-9]{6}$/,
208-
message: i18n.__('One time password must be a six digit number.'),
208+
message: 'One time password must be a six digit number.',
209209
required: true
210210
}
211211
}
@@ -222,9 +222,9 @@ class MfaController extends CliController {
222222
const input = await this.prompt({
223223
properties: {
224224
otp: {
225-
description: i18n.__('Plug in your yubikey and put your finger on it.\notp'),
225+
description: 'Plug in your yubikey and put your finger on it.\notp',
226226
pattern: /^[cbdefghijklnrtuv]{44}$/,
227-
message: i18n.__('Yubikey OTP must be a ModHex compatible 44 characters in length string.'),
227+
message: 'Yubikey OTP must be a ModHex compatible 44 characters in length string.',
228228
required: true,
229229
hidden: true
230230
}

app/models/crypto.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ const Config = require('./config');
1414
const Gpg = require('gpg');
1515
const XRegExp = require('xregexp');
1616
const jsSHA = require('jssha');
17-
const randomBytes = require('crypto').randomBytes;
18-
const StringDecoder = require('string_decoder').StringDecoder;
17+
const {randomBytes} = require('crypto');
18+
const {StringDecoder} = require('string_decoder');
1919

2020
class Crypto {
2121
/**
@@ -75,7 +75,7 @@ class Crypto {
7575
* @returns {Promise}
7676
*/
7777
static encrypt(recipient, msg) {
78-
const promise = new Promise(((resolve, reject) => {
78+
return new Promise(((resolve, reject) => {
7979
const p = {
8080
resolve,
8181
reject
@@ -90,37 +90,36 @@ class Crypto {
9090
}
9191
}
9292
Gpg.encrypt(msg, options, (error, buffer) => {
93-
if (error != undefined) {
93+
if (error) {
9494
return p.reject(error);
9595
}
9696
const decoder = new StringDecoder('utf8');
9797
return p.resolve(decoder.write(buffer));
9898
});
9999
}));
100-
return promise;
101100
}
102101

103102

104103
/**
105104
* Decrypt a msg with a given key
106105
* @param msg string message to decrypt
106+
* @param options
107107
* @returns {Promise}
108108
*/
109109
static decrypt(msg, options) {
110-
const promise = new Promise(((resolve, reject) => {
110+
return new Promise(((resolve, reject) => {
111111
const p = {
112112
resolve,
113113
reject
114114
};
115115

116116
Gpg.decrypt(msg, options, (error, decrypted) => {
117-
if (error != undefined) {
117+
if (error) {
118118
return p.reject(error);
119119
}
120120
return p.resolve(decrypted.toString('utf8'));
121121
});
122122
}));
123-
return promise;
124123
}
125124
}
126125

0 commit comments

Comments
 (0)