Skip to content

Commit

Permalink
Merge branch 'IDTEAM-1628-1PUX-main-2FA' into 'main'
Browse files Browse the repository at this point in the history
IDTEAM-1628: 1Password 1PUX import first totp extra field as primary totp

See merge request web/clients!6367

Changelog:
  • Loading branch information
MargeBot committed Jul 13, 2023
2 parents cc792f5 + 87a962a commit 50e7cf0
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 30 deletions.
37 changes: 10 additions & 27 deletions packages/pass/import/providers/1password.1pux.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,18 +68,11 @@ describe('Import 1password 1pux', () => {
username: 'john@wick.com',
password: 'password',
urls: ['http://localhost:7777'],
totpUri: '',
totpUri:
'otpauth://totp/Login%20item%20with%20two%20TOTP%20and%20one%20text%20extra%20fields?secret=BASE32SECRET3232&algorithm=SHA1&digits=6&period=30',
});
expect(loginItemMultiTOTP.trashed).toEqual(false);
expect(loginItemMultiTOTP.extraFields).toEqual([
{
fieldName: 'one-time password',
type: 'totp',
data: {
totpUri:
'otpauth://totp/Login%20item%20with%20two%20TOTP%20and%20one%20text%20extra%20fields?secret=BASE32SECRET3232&algorithm=SHA1&digits=6&period=30',
},
},
{
fieldName: 'one-time password',
type: 'totp',
Expand Down Expand Up @@ -107,15 +100,10 @@ describe('Import 1password 1pux', () => {
expect(emptyLoginItem.metadata.itemUuid).not.toBeUndefined();
expect(emptyLoginItem.metadata.note).toEqual('');
expect(emptyLoginItem.trashed).toEqual(false);
expect(emptyLoginItem.extraFields).toEqual([
{
fieldName: 'empty TOTP',
type: 'totp',
data: {
totpUri: '',
},
},
]);
expect(emptyLoginItem.content.username).toEqual('');
expect(emptyLoginItem.content.password).toEqual('');
expect(emptyLoginItem.content.totpUri).toEqual('');
expect(emptyLoginItem.extraFields).toEqual([]);

/* Login item with single TOTP extra field */
const loginItemSingleTOTPName = 'Login item with a note and single TOTP extra field';
Expand All @@ -127,16 +115,11 @@ describe('Import 1password 1pux', () => {
expect(loginItemSingleTOTP.modifyTime).toEqual(1688983719);
expect(loginItemSingleTOTP.metadata.itemUuid).not.toBeUndefined();
expect(loginItemSingleTOTP.metadata.note).toEqual('this is a login item note');
expect(loginItemSingleTOTP.content.totpUri).toEqual(
'otpauth://totp/az?secret=QQ&algorithm=SHA1&digits=6&period=30'
);
expect(loginItemSingleTOTP.trashed).toEqual(false);
expect(loginItemSingleTOTP.extraFields).toEqual([
{
fieldName: 'one-time password',
type: 'totp',
data: {
totpUri: 'otpauth://totp/az?secret=QQ&algorithm=SHA1&digits=6&period=30',
},
},
]);
expect(loginItemSingleTOTP.extraFields).toEqual([]);

/* Login item with special chars in password */
const specialCharItemName = 'Login item with " in password';
Expand Down
18 changes: 15 additions & 3 deletions packages/pass/import/providers/1password.reader.1pux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@ import jszip from 'jszip';
import { c } from 'ttag';

import type { ItemExtraField, ItemImportIntent, Maybe, Unpack } from '@proton/pass/types';
import { extractFirst } from '@proton/pass/utils/array';
import { truthy } from '@proton/pass/utils/fp';
import { logger } from '@proton/pass/utils/logger';
import { uniqueId } from '@proton/pass/utils/string';

import { ImportReaderError } from '../helpers/reader.error';
import { getImportedVaultName, importCreditCardItem, importLoginItem, importNoteItem } from '../helpers/transformers';
import type { ImportPayload, ImportVault } from '../types';
import type { OnePass1PuxData, OnePassBaseItem, OnePassItem, OnePassItemDetails ,
OnePassField} from './1password.1pux.types';
import type {
OnePass1PuxData,
OnePassBaseItem,
OnePassField,
OnePassItem,
OnePassItemDetails,
} from './1password.1pux.types';
import {
OnePassCategory,
OnePassFieldIdCreditCard,
Expand Down Expand Up @@ -142,13 +148,19 @@ const extractLoginFieldFromLoginItem = (
const processLoginItem = (
item: Extract<OnePassItem, { categoryUuid: OnePassCategory.LOGIN }>
): ItemImportIntent<'login'> => {
const [totp, extraFields] = extractFirst<ItemExtraField<'totp'>, ItemExtraField>(
extractExtraFields(item),
(extraField: ItemExtraField) => extraField.type === 'totp'
);

return importLoginItem({
name: item.overview.title,
note: item.details.notesPlain,
username: extractLoginFieldFromLoginItem(item, OnePassLoginDesignation.USERNAME),
password: extractLoginFieldFromLoginItem(item, OnePassLoginDesignation.PASSWORD),
urls: extractURLs(item),
extraFields: extractExtraFields(item),
totp: totp?.data.totpUri,
extraFields,
trashed: item.state === OnePassState.ARCHIVED,
createTime: item.createdAt,
modifyTime: item.updatedAt,
Expand Down
11 changes: 11 additions & 0 deletions packages/pass/utils/array/array-extract-first.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { MaybeNull } from '@proton/pass/types';

export const extractFirst = <K extends T, T>(arr: T[], condition: (entry: T) => boolean) =>
arr.reduce<[MaybeNull<K>, T[]]>(
(acc, entry) => {
if (acc[0] === null && condition(entry)) acc[0] = entry as MaybeNull<K>;
else acc[1].push(entry);
return acc;
},
[null, []]
);
1 change: 1 addition & 0 deletions packages/pass/utils/array/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './array-duplicates';
export * from './array-extract-first';
export * from './array-first';
export * from './array-interpolate';
export * from './array-partition';
Expand Down

0 comments on commit 50e7cf0

Please sign in to comment.