Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/all/background_page/controller/autofill/AutofillController.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import DecryptAndParseResourceSecretService from "../../service/secret/decryptAn
import InformMenuPagemod from "../../pagemod/informMenuPagemod";
import QuickAccessPagemod from "../../pagemod/quickAccessPagemod";
import FindSecretService from "../../service/secret/findSecretService";
import TotpService from "../../service/otp/totpService";
import CopyToClipboardService from "../../service/clipboard/copyToClipboardService";
import AutofillSettingLocalStorage from "../../service/local_storage/autofillSettingLocalStorage";

class AutofillController {
/**
Expand All @@ -33,6 +36,7 @@ class AutofillController {
constructor(worker, requestId, apiClientOptions, account) {
this.worker = worker;
this.requestId = requestId;
this.account = account;
this.resourceModel = new ResourceModel(apiClientOptions, account);
this.findSecretService = new FindSecretService(account, apiClientOptions);
this.resourceTypeModel = new ResourceTypeModel(apiClientOptions);
Expand Down Expand Up @@ -76,6 +80,8 @@ class AutofillController {
const username = resource.metadata?.username || "";
const password = plaintextSecret?.password;
this.fillCredential(webIntegrationWorker, {username, password});
// Copy TOTP to clipboard if available
await this.copyTotpToClipboard(plaintextSecret?.totp);
} finally {
if (this.isInformMenuWorker) {
webIntegrationWorker.port.emit('passbolt.in-form-menu.close');
Expand Down Expand Up @@ -132,6 +138,32 @@ class AutofillController {
webIntegrationWorker.port.request('passbolt.quickaccess.fill-form', credential.username, credential.password, url);
}
}

/**
* Copy TOTP code to clipboard if the resource has TOTP configured and the setting is enabled.
* @private
* @param {Object|null} totp - The TOTP configuration from the decrypted secret
* @return {Promise<void>}
*/
async copyTotpToClipboard(totp) {
if (!totp) {
return;
}
try {
// Check if the setting is enabled
const autofillSettingLocalStorage = new AutofillSettingLocalStorage(this.account);
const autofillSetting = await autofillSettingLocalStorage.get();
if (!autofillSetting.copyTotpOnAutofill) {
return;
}
const totpCode = TotpService.generate(totp);
const clipboardService = new CopyToClipboardService();
await clipboardService.copyTemporarily(totpCode);
} catch (error) {
// Log but don't fail the autofill operation if TOTP copy fails
console.error("Failed to copy TOTP to clipboard:", error);
}
}
}

export default AutofillController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 5.8.0
*/

import AutofillSettingLocalStorage from "../../service/local_storage/autofillSettingLocalStorage";

class GetAutofillSettingController {
/**
* Constructor
* @param {Worker} worker
* @param {string} requestId uuid
* @param {AccountEntity} account The account associated to the worker.
*/
constructor(worker, requestId, account) {
this.worker = worker;
this.requestId = requestId;
this.autofillSettingLocalStorage = new AutofillSettingLocalStorage(account);
}

/**
* Controller executor.
* @returns {Promise<void>}
*/
async _exec() {
try {
const result = await this.exec();
this.worker.port.emit(this.requestId, 'SUCCESS', result);
} catch (error) {
console.error(error);
this.worker.port.emit(this.requestId, 'ERROR', error);
}
}

/**
* Get the autofill settings
* @return {Promise<Object>} The autofill settings DTO
*/
async exec() {
const entity = await this.autofillSettingLocalStorage.get();
return entity.toDto();
}
}

export default GetAutofillSettingController;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 5.8.0
*/

import AutofillSettingLocalStorage from "../../service/local_storage/autofillSettingLocalStorage";
import AutofillSettingEntity from "../../model/entity/autofillSetting/autofillSettingEntity";

class SetAutofillSettingController {
/**
* Constructor
* @param {Worker} worker
* @param {string} requestId uuid
* @param {AccountEntity} account The account associated to the worker.
*/
constructor(worker, requestId, account) {
this.worker = worker;
this.requestId = requestId;
this.autofillSettingLocalStorage = new AutofillSettingLocalStorage(account);
}

/**
* Controller executor.
* @param {Object} autofillSettingDto The autofill setting DTO
* @returns {Promise<void>}
*/
async _exec(autofillSettingDto) {
try {
await this.exec(autofillSettingDto);
this.worker.port.emit(this.requestId, 'SUCCESS');
} catch (error) {
console.error(error);
this.worker.port.emit(this.requestId, 'ERROR', error);
}
}

/**
* Set the autofill settings
* @param {Object} autofillSettingDto The autofill setting DTO
* @return {Promise<void>}
*/
async exec(autofillSettingDto) {
const entity = new AutofillSettingEntity(autofillSettingDto);
await this.autofillSettingLocalStorage.set(entity);
}
}

export default SetAutofillSettingController;
40 changes: 40 additions & 0 deletions src/all/background_page/event/autofillSettingEvents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 5.8.0
*/

import GetAutofillSettingController from "../controller/autofillSetting/getAutofillSettingController";
import SetAutofillSettingController from "../controller/autofillSetting/setAutofillSettingController";

const listen = function(worker, _, account) {
/*
* Get the autofill settings
*
* @listens passbolt.autofill-setting.get
*/
worker.port.on('passbolt.autofill-setting.get', async requestId => {
const controller = new GetAutofillSettingController(worker, requestId, account);
await controller._exec();
});

/*
* Set the autofill settings
*
* @listens passbolt.autofill-setting.set
*/
worker.port.on('passbolt.autofill-setting.set', async(requestId, autofillSettingDto) => {
const controller = new SetAutofillSettingController(worker, requestId, account);
await controller._exec(autofillSettingDto);
});
};

export const AutofillSettingEvents = {listen};
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Passbolt ~ Open source password manager for teams
* Copyright (c) Passbolt SA (https://www.passbolt.com)
*
* Licensed under GNU Affero General Public License version 3 of the or any later version.
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Passbolt SA (https://www.passbolt.com)
* @license https://opensource.org/licenses/AGPL-3.0 AGPL License
* @link https://www.passbolt.com Passbolt(tm)
* @since 5.8.0
*/
import Entity from "passbolt-styleguide/src/shared/models/entity/abstract/entity";
import EntitySchema from "passbolt-styleguide/src/shared/models/entity/abstract/entitySchema";

const ENTITY_NAME = 'AutofillSetting';

class AutofillSettingEntity extends Entity {
/**
* @inheritDoc
*/
constructor(autofillSettingDto, options = {}) {
super(EntitySchema.validate(
AutofillSettingEntity.ENTITY_NAME,
autofillSettingDto,
AutofillSettingEntity.getSchema()
), options);
}

/**
* Get entity schema
* @returns {Object} schema
*/
static getSchema() {
return {
"type": "object",
"required": [
"copyTotpOnAutofill",
],
"properties": {
"copyTotpOnAutofill": {
"type": "boolean"
}
}
};
}

/**
* Return whether TOTP should be copied to clipboard on autofill
* @returns {boolean}
*/
get copyTotpOnAutofill() {
return this._props.copyTotpOnAutofill;
}

/**
* Get the default settings
* @returns {AutofillSettingEntity}
*/
static createFromDefault() {
return new AutofillSettingEntity({copyTotpOnAutofill: false});
}

/**
* AutofillSettingEntity.ENTITY_NAME
* @returns {string}
*/
static get ENTITY_NAME() {
return ENTITY_NAME;
}
}

export default AutofillSettingEntity;
4 changes: 3 additions & 1 deletion src/all/background_page/pagemod/appPagemod.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import CheckAuthStatusService from "../service/auth/checkAuthStatusService";
import GetActiveAccountService from "../service/account/getActiveAccountService";
import {PermissionEvents} from "../event/permissionEvents";
import {AccountEvents} from "../event/accountEvents";
import {AutofillSettingEvents} from "../event/autofillSettingEvents";

class App extends Pagemod {
/**
Expand Down Expand Up @@ -86,7 +87,8 @@ class App extends Pagemod {
MfaEvents,
RememberMeEvents,
PermissionEvents,
AccountEvents
AccountEvents,
AutofillSettingEvents
];
}

Expand Down
4 changes: 3 additions & 1 deletion src/all/background_page/pagemod/quickAccessPagemod.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {ResourceTypeEvents} from "../event/resourceTypeEvents";
import BuildApiClientOptionsService from "../service/account/buildApiClientOptionsService";
import GetActiveAccountService from "../service/account/getActiveAccountService";
import {AccountEvents} from "../event/accountEvents";
import {AutofillSettingEvents} from "../event/autofillSettingEvents";

class QuickAccess extends Pagemod {
/**
Expand Down Expand Up @@ -58,7 +59,8 @@ class QuickAccess extends Pagemod {
PownedPasswordEvents,
RememberMeEvents,
ResourceTypeEvents,
AccountEvents
AccountEvents,
AutofillSettingEvents
];
}

Expand Down
Loading