recovery key > account recovery key

This commit is contained in:
dschom 2022-09-02 14:28:51 -07:00
Родитель b8dce82138
Коммит f28e95071b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: F26AEE99174EE68B
84 изменённых файлов: 284 добавлений и 264 удалений

Просмотреть файл

@ -120,7 +120,7 @@ test.describe('severity-3 #smoke', () => {
await recoveryKey.submit();
const dl = await recoveryKey.dataTrio.clickDownload();
expect(dl.suggestedFilename()).toBe(
`${credentials.email} Firefox recovery key.txt`
`${credentials.email} Firefox account recovery key.txt`
);
const clipboard = await recoveryKey.dataTrio.clickCopy();
expect(clipboard).toEqual(await recoveryKey.getKey());

Просмотреть файл

@ -47,7 +47,7 @@ test.describe('severity-1 #smoke', () => {
});
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293431
test('forgot password has recovery key but skip using it #1293431', async ({
test('forgot password has account recovery key but skip using it #1293431', async ({
target,
credentials,
page,

Просмотреть файл

@ -4,7 +4,7 @@ import { EmailHeader, EmailType } from '../../lib/email';
test.describe('severity-1 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293421
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293429
test('add and remove recovery key #1293421 #1293429', async ({
test('add and remove account recovery key #1293421 #1293429', async ({
credentials,
pages: { settings, recoveryKey },
}) => {
@ -26,7 +26,7 @@ test.describe('severity-1 #smoke', () => {
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293432
// https://testrail.stage.mozaws.net/index.php?/cases/view/1293433
test('use recovery key #1293432 #1293433', async ({
test('use account recovery key #1293432 #1293433', async ({
credentials,
target,
pages: { page, login, recoveryKey, settings },

Просмотреть файл

@ -274,7 +274,7 @@ it('displays the totp status', async () => {
expect(getByTestId('totp-enabled')).toBeInTheDocument();
});
it('displays the recovery key status', async () => {
it('displays the account recovery key status', async () => {
const { getByTestId } = render(
<MockedProvider>
<Account {...accountResponse} />

Просмотреть файл

@ -486,7 +486,7 @@ export const Account = ({
)}
<li className="account-li">
<h3 className="account-header">Recovery Key</h3>
<h3 className="account-header">Account Recovery Key</h3>
</li>
{recoveryKeys && recoveryKeys.length > 0 ? (
<>
@ -499,7 +499,7 @@ export const Account = ({
</>
) : (
<li className="account-li account-border-info">
This account doesn't have a recovery key enabled.
This account doesn't have an account recovery key enabled.
</li>
)}
@ -806,13 +806,13 @@ const RecoveryKeys = ({ verifiedAt, createdAt, enabled }: RecoveryKeysType) => {
<li className="account-li">
<ul className="account-border-info">
<li className="account-li">
Recovery Key Created At:{' '}
Account Recovery Key Created At:{' '}
<span data-testid="recovery-keys-created-at">
{recoveryKeyCreatedDate}
</span>
</li>
<li className="account-li">
Recovery Key Confirmed At:{' '}
Account Recovery Key Confirmed At:{' '}
<span
data-testid="recovery-keys-verified"
className={`ml-3 text-base ${
@ -825,7 +825,7 @@ const RecoveryKeys = ({ verifiedAt, createdAt, enabled }: RecoveryKeysType) => {
</span>
</li>
<li className="account-li">
Recovery Key Enabled:{' '}
Account Recovery Key Enabled:{' '}
<span
data-testid="recovery-keys-enabled"
className={`ml-3 text-base ${

Просмотреть файл

@ -3,18 +3,18 @@
To help reduce the risk of a user losing their encrypted data
(such as synced passwords or bookmarks) during a password reset,
Firefox Account users can create an "account recovery key".
This recovery key is used to store an encrypted version
This account recovery key is used to store an encrypted version
of the user's encryption key `kB`,
which can be re-wrapped with their new password
during the password reset process.
## Registering a Recovery Key
## Registering an Account Recovery Key
Creating a new recovery key involves the following steps:
Creating a new account recovery key involves the following steps:
- FxA web-content prompts for the user's password and retrieves kB.
- FxA web-content generates a "recovery key", consisting of between 16 and 32 random bytes.
- FxA web-content uses HKDF to derive two values from the recovery key:
- FxA web-content generates an "account recovery key", consisting of between 16 and 32 random bytes.
- FxA web-content uses HKDF to derive two values from the account recovery key:
- A key fingerprint: recover-kid = HKDF(recover-key, uid, "fxa recovery fingerprint", len=16)
- An encryption key: recover-enc = HKDF(recover-key, uid, "fxa recovery encrypt key", len=32)
- FxA web-content encrypts kB into a JWE to produce the "recovery data":
@ -23,15 +23,15 @@ Creating a new recovery key involves the following steps:
associating it with the fingerprint (recover-kid)
- `POST /recoveryKey`, providing `recoveryKeyId` and `recoveryData` in the request body.
This scheme ensures someone in posession of the recovery key,
This scheme ensures someone in possession of the account recovery key,
can request the encrypted recovery data
from the FxA server,
and use it to recover the user's kB.
## Using a Recovery Key during password reset
## Using an Account Recovery Key during password reset
During the password reset process,
a user who has a recovery key
a user who has an account recovery key
can use it to maintain their existing kB
as follows:
@ -43,7 +43,7 @@ as follows:
and encryption key (recover-kid and recover-enc as defined above).
- FxA web-content requests recover-data from FxA server, providing recover-kid.
- `GET /recoveryKey/:recoveryKeyId`, authenticated with `accountResetToken`.
- Providing the `:recoveryKeyId` here proves that the user posesses the recovery key,
- Providing the `:recoveryKeyId` here proves that the user possesses the account recovery key,
while the `accountResetToken` proves that they control the email address
of the account.
- FxA web-content decrypts recover-data with recover-enc to obtain the user's kB.
@ -53,4 +53,4 @@ as follows:
- `POST /account/reset`, authenticated with `accountResetToken`,
providing `recoveryKeyId` and `wrapKb` in the request body.
- Upon successful password reset, the FxA auth-server deletes the
recovery key and its associated recovery data.
account recovery key and its associated recovery data.

Просмотреть файл

@ -113,10 +113,10 @@ export const AUTH_SERVER_API_DESCRIPTION = {
| 400 | 155 | TOTP token not found. |
| 400 | 156 | Recovery code not found. |
| 400 | 157 | Unavailable device command. |
| 400 | 158 | Recovery key not found. |
| 400 | 159 | Recovery key is not valid. |
| 400 | 158 | Account recovery key not found. |
| 400 | 159 | Account recovery key is not valid. |
| 400 | 160 | This request requires two step authentication enabled on your account. |
| 400 | 161 | Recovery key already exists. |
| 400 | 161 | Account recovery key already exists. |
| 400 | 162 | Unknown client_id |
| 400 | 164 | Stale auth timestamp |
| 409 | 165 | Redis WATCH detected a conflicting update |

Просмотреть файл

@ -16,7 +16,7 @@ const RECOVERYKEY_POST = {
dedent`
🔒 Authenticated with session token
Creates a new recovery key for a user. Recovery keys are one-time-use tokens that can be used to recover the user's kB if they forget their password. For more details, see the [recovery keys](https://github.com/mozilla/fxa/blob/main/packages/fxa-auth-server/docs/recovery_keys.md) docs.
Creates a new account recovery key for a user. Account recovery keys are one-time-use tokens that can be used to recover the user's kB if they forget their password. For more details, see the [account recovery keys](https://github.com/mozilla/fxa/blob/main/packages/fxa-auth-server/docs/recovery_keys.md) docs.
`,
],
};
@ -26,7 +26,7 @@ const RECOVERYKEY_RECOVERYKEYID_GET = {
description: '/recoveryKey/{recoveryKeyId}',
notes: [
'🔒 Authenticated with account reset token',
'Retrieve the account recovery data associated with the given recovery key.',
'Retrieve the account recovery data associated with the given account recovery key.',
],
};
@ -44,7 +44,7 @@ const RECOVERYKEY_DELETE = {
description: '/recoveryKey',
notes: [
'🔒 Authenticated with session token',
"This route remove an account's recovery key. When the key is removed, it can no longer be used to restore an account's kB.",
"This route remove an account's account recovery key. When the key is removed, it can no longer be used to restore an account's kB.",
],
};

Просмотреть файл

@ -122,7 +122,7 @@ const DESCRIPTIONS = {
'Alphanumeric string indicating the reason for establishing a new session; may be "login" (the default) or "reconnect".',
recoveryData: "An encrypted bundle containing the user's kB.",
recoveryKeyId:
'A unique identifier for this recovery key, derived from the key via HKDF.',
'A unique identifier for this account recovery key, derived from the key via HKDF.',
redirectTo:
'URL that the client should be redirected to after handling the request.',
redirectUri:

Просмотреть файл

@ -12,7 +12,7 @@ const TAGS = {
OAUTH_SERVER: ['api', 'OAuth Server API Overview'],
PASSWORD: ['api', 'Password'],
RECOVERY_CODES: ['api', 'Recovery codes'],
RECOVERY_KEY: ['api', 'Recovery key'],
RECOVERY_KEY: ['api', 'Account recovery key'],
SECURITY_EVENTS: ['api', 'Security events'],
SESSION: ['api', 'Session'],
SIGN: ['api', 'Sign'],

Просмотреть файл

@ -1065,7 +1065,7 @@ AppError.recoveryKeyNotFound = () => {
code: 400,
error: 'Bad Request',
errno: ERRNO.RECOVERY_KEY_NOT_FOUND,
message: 'Recovery key not found.',
message: 'Account recovery key not found.',
});
};
@ -1074,7 +1074,7 @@ AppError.recoveryKeyInvalid = () => {
code: 400,
error: 'Bad Request',
errno: ERRNO.RECOVERY_KEY_INVALID,
message: 'Recovery key is not valid.',
message: 'Account recovery key is not valid.',
});
};
@ -1093,7 +1093,7 @@ AppError.recoveryKeyExists = () => {
code: 400,
error: 'Bad Request',
errno: ERRNO.RECOVERY_KEY_EXISTS,
message: 'Recovery key already exists.',
message: 'Account recovery key already exists.',
});
};

Просмотреть файл

@ -1318,8 +1318,8 @@ export class AccountHandler {
};
const recoveryKeyDeleteAndEmailNotification = async () => {
// If the password was reset with a recovery key, then we explicitly delete the
// recovery key and send an email that the account was reset with it.
// If the password was reset with an account recovery key, then we explicitly delete the
// account recovery key and send an email that the account was reset with it.
if (recoveryKeyId) {
await this.db.deleteRecoveryKey(account.uid);

Просмотреть файл

@ -47,8 +47,8 @@ module.exports = (log, db, Password, verifierVersion, customs, mailer) => {
const { uid } = sessionToken;
const { recoveryKeyId, recoveryData, enabled } = request.payload;
// Users that already have an enabled recovery key can not
// create a second recovery key
// Users that already have an enabled account recovery key can not
// create a second account recovery key
try {
await db.createRecoveryKey(uid, recoveryKeyId, recoveryData, enabled);
} catch (err) {
@ -130,7 +130,7 @@ module.exports = (log, db, Password, verifierVersion, customs, mailer) => {
const { recoveryKeyId } = request.payload;
// Attempt to retrieve a recovery key, if it exists and is not already enabled,
// Attempt to retrieve an account recovery key, if it exists and is not already enabled,
// then we enable it.
const recoveryKeyData = await db.getRecoveryKey(uid, recoveryKeyId);
@ -223,7 +223,7 @@ module.exports = (log, db, Password, verifierVersion, customs, mailer) => {
if (!uid) {
// If not using a sessionToken, an email is required to check
// for a recovery key. This occurs when checking from the
// for an account recovery key. This occurs when checking from the
// password reset page and allows us to redirect the user to either
// the regular password reset or account recovery password reset.
if (!email) {

Просмотреть файл

@ -1,7 +1,7 @@
passwordResetAccountRecovery-subject = Password updated using recovery key
passwordResetAccountRecovery-title = Your account password was reset with a recovery key
passwordResetAccountRecovery-description = You have successfully reset your password using a recovery key from the following device:
passwordResetAccountRecovery-action = Create new recovery key
passwordResetAccountRecovery-regen-required = You will need to generate a new recovery key.
passwordResetAccountRecovery-subject = Password updated using account recovery key
passwordResetAccountRecovery-title = Your account password was reset with an account recovery key
passwordResetAccountRecovery-description = You have successfully reset your password using an account recovery key from the following device:
passwordResetAccountRecovery-action = Create new account recovery key
passwordResetAccountRecovery-regen-required = You will need to generate a new account recovery key.
# After the colon, there's a link to https://accounts.firefox.com/settings/account_recovery
passwordResetAccountRecovery-create-key = Create new recovery key:
passwordResetAccountRecovery-create-key = Create new account recovery key:

Просмотреть файл

@ -1,10 +1,10 @@
{
"subject": {
"id": "passwordResetAccountRecovery-subject",
"message": "Password updated using recovery key"
"message": "Password updated using account recovery key"
},
"action": {
"id": "passwordResetAccountRecovery-action",
"message": "Create new recovery key"
"message": "Create new account recovery key"
}
}

Просмотреть файл

@ -5,11 +5,11 @@
<mj-section>
<mj-column>
<mj-text css-class="text-header">
<span data-l10n-id="passwordResetAccountRecovery-title">Your account password was reset with a recovery key</span>
<span data-l10n-id="passwordResetAccountRecovery-title">Your account password was reset with an account recovery key</span>
</mj-text>
<mj-text css-class="text-body">
<span data-l10n-id="passwordResetAccountRecovery-description">You have successfully reset your password using a recovery key from the following device:</span>
<span data-l10n-id="passwordResetAccountRecovery-description">You have successfully reset your password using an account recovery key from the following device:</span>
</mj-text>
</mj-column>
</mj-section>
@ -19,14 +19,14 @@
<mj-section>
<mj-column>
<mj-text css-class="text-body">
<span data-l10n-id="passwordResetAccountRecovery-regen-required">You will need to generate a new recovery key.</span>
<span data-l10n-id="passwordResetAccountRecovery-regen-required">You will need to generate a new account recovery key.</span>
</mj-text>
</mj-column>
</mj-section>
<%- include('/partials/button/index.mjml', {
buttonL10nId: "passwordResetAccountRecovery-action",
buttonText: "Create new recovery key"
buttonText: "Create new account recovery key"
}) %>
<%- include('/partials/automatedEmailChangePassword/index.mjml') %>

Просмотреть файл

@ -12,7 +12,7 @@ export default {
const createStory = storyWithProps(
'passwordResetAccountRecovery',
'Sent when recovery key is used',
'Sent when account recovery key is used',
{
...MOCK_USER_INFO,
link: 'http://localhost:3030/settings/account_recovery',

Просмотреть файл

@ -1,12 +1,12 @@
passwordResetAccountRecovery-title = "Your account password was reset with a recovery key"
passwordResetAccountRecovery-title = "Your account password was reset with an account recovery key"
passwordResetAccountRecovery-description = "You have successfully reset your password using a recovery key from the following device:"
passwordResetAccountRecovery-description = "You have successfully reset your password using an account recovery key from the following device:"
<%- include('/partials/userInfo/index.txt') %>
passwordResetAccountRecovery-regen-required = "You will need to generate a new recovery key."
passwordResetAccountRecovery-regen-required = "You will need to generate a new account recovery key."
passwordResetAccountRecovery-create-key = "Create new recovery key:"
passwordResetAccountRecovery-create-key = "Create new account recovery key:"
<%- link %>
<%- include('/partials/changePassword/index.txt') %>

Просмотреть файл

@ -12,7 +12,7 @@ export default {
const createStory = storyWithProps(
'postAddAccountRecovery',
'Sent when new recovery key is generated',
'Sent when new account recovery key is generated',
{
...MOCK_USER_INFO,
link: 'http://localhost:3030/settings',

Просмотреть файл

@ -2,4 +2,4 @@ postRemoveAccountRecovery-subject = Account recovery key removed
postRemoveAccountRecovery-title = Account recovery key removed
postRemoveAccountRecovery-description = You have successfully removed an account recovery key for your { -product-firefox-account } using the following device:
postRemoveAccountRecovery-action = Manage account
postRemoveAccountRecovery-invalid = This recovery key can no longer be used to recover your account.
postRemoveAccountRecovery-invalid = This account recovery key can no longer be used to recover your account.

Просмотреть файл

@ -19,7 +19,7 @@
<mj-section>
<mj-column>
<mj-text css-class="text-body">
<span data-l10n-id="postRemoveAccountRecovery-invalid">This recovery key can no longer be used to recover your account.</span>
<span data-l10n-id="postRemoveAccountRecovery-invalid">This account recovery key can no longer be used to recover your account.</span>
</mj-text>
</mj-column>
</mj-section>

Просмотреть файл

@ -4,7 +4,7 @@ postRemoveAccountRecovery-description = "You have successfully removed an accoun
<%- include('/partials/userInfo/index.txt') %>
postRemoveAccountRecovery-invalid = "This recovery key can no longer be used to recover your account."
postRemoveAccountRecovery-invalid = "This account recovery key can no longer be used to recover your account."
<%- include('/partials/manageAccount/index.txt') %>

Просмотреть файл

@ -198,7 +198,7 @@ describe('/account/reset', () => {
clientAddress = mockRequest.app.clientAddress;
});
describe('reset account with recovery key', () => {
describe('reset account with account recovery key', () => {
let res;
beforeEach(() => {
mockRequest.payload.wrapKb = hexString(32);
@ -211,7 +211,7 @@ describe('/account/reset', () => {
assert.ok(res.keyFetchToken, 'return keyFetchToken');
});
it('should have checked for recovery key', () => {
it('should have checked for account recovery key', () => {
assert.equal(mockDB.getRecoveryKey.callCount, 1);
const args = mockDB.getRecoveryKey.args[0];
assert.equal(
@ -223,11 +223,11 @@ describe('/account/reset', () => {
assert.equal(
args[1],
mockRequest.payload.recoveryKeyId,
'recovery key id passed'
'account recovery key id passed'
);
});
it('should have reset account with recovery key', () => {
it('should have reset account with account recovery key', () => {
assert.equal(mockDB.resetAccount.callCount, 1);
assert.equal(mockDB.resetAccountTokens.callCount, 1);
assert.equal(mockDB.createKeyFetchToken.callCount, 1);
@ -241,7 +241,7 @@ describe('/account/reset', () => {
assert.equal(args[0].wrapKb, mockRequest.payload.wrapKb, 'wrapKb passed');
});
it('should have deleted recovery key', () => {
it('should have deleted account recovery key', () => {
assert.equal(mockDB.deleteRecoveryKey.callCount, 1);
const args = mockDB.deleteRecoveryKey.args[0];
assert.equal(

Просмотреть файл

@ -17,7 +17,7 @@ const recoveryData = '11111111111';
const uid = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
describe('POST /recoveryKey', () => {
describe('should create recovery key', () => {
describe('should create account recovery key', () => {
beforeEach(() => {
const requestOptions = {
credentials: { uid, email },
@ -85,7 +85,7 @@ describe('POST /recoveryKey', () => {
});
});
describe('should create disabled recovery key', () => {
describe('should create disabled account recovery key', () => {
beforeEach(() => {
const requestOptions = {
credentials: { uid, email },
@ -112,7 +112,7 @@ describe('POST /recoveryKey', () => {
});
});
describe('should verify recovery key', () => {
describe('should verify account recovery key', () => {
beforeEach(() => {
const requestOptions = {
credentials: { uid, email },
@ -196,7 +196,7 @@ describe('POST /recoveryKey', () => {
});
describe('GET /recoveryKey/{recoveryKeyId}', () => {
describe('should get recovery key', () => {
describe('should get account recovery key', () => {
beforeEach(() => {
const requestOptions = {
credentials: { uid, email },
@ -264,14 +264,14 @@ describe('GET /recoveryKey/{recoveryKeyId}', () => {
assert.deepEqual(
response.errno,
errors.ERRNO.RECOVERY_KEY_INVALID,
'correct invalid recovery key errno'
'correct invalid account recovery key errno'
);
});
});
});
describe('POST /recoveryKey/exists', () => {
describe('should check if recovery key exists using sessionToken', () => {
describe('should check if account recovery key exists using sessionToken', () => {
beforeEach(() => {
const requestOptions = {
credentials: { uid, email },
@ -305,7 +305,7 @@ describe('POST /recoveryKey/exists', () => {
});
});
describe('should check if recovery key exists using email', () => {
describe('should check if account recovery key exists using email', () => {
beforeEach(() => {
const requestOptions = {
payload: { email },
@ -349,7 +349,7 @@ describe('POST /recoveryKey/exists', () => {
});
describe('DELETE /recoveryKey', () => {
describe('should delete recovery key', () => {
describe('should delete account recovery key', () => {
beforeEach(() => {
const requestOptions = {
method: 'DELETE',

Просмотреть файл

@ -900,7 +900,7 @@ const TESTS: [string, any, Record<string, any>?][] = [
])],
['passwordResetAccountRecoveryEmail', new Map<string, Test | any>([
['subject', { test: 'equal', expected: 'Password updated using recovery key' }],
['subject', { test: 'equal', expected: 'Password updated using account recovery key' }],
['headers', new Map([
['X-Link', { test: 'equal', expected: configUrl('createAccountRecoveryUrl', 'password-reset-account-recovery-success', 'create-recovery-key', 'email', 'uid') }],
['X-SES-MESSAGE-TAGS', { test: 'equal', expected: sesMessageTagsHeaderValue('passwordResetAccountRecovery') }],
@ -908,7 +908,7 @@ const TESTS: [string, any, Record<string, any>?][] = [
['X-Template-Version', { test: 'equal', expected: TEMPLATE_VERSIONS.passwordResetAccountRecovery }],
])],
['html', [
{ test: 'include', expected: 'Your account password was reset with a recovery key' },
{ test: 'include', expected: 'Your account password was reset with an account recovery key' },
{ test: 'include', expected: decodeUrl(configHref('createAccountRecoveryUrl', 'password-reset-account-recovery-success', 'create-recovery-key', 'email', 'uid')) },
{ test: 'include', expected: decodeUrl(configHref('initiatePasswordChangeUrl', 'password-reset-account-recovery-success', 'change-password', 'email')) },
{ test: 'include', expected: decodeUrl(configHref('privacyUrl', 'password-reset-account-recovery-success', 'privacy')) },
@ -921,7 +921,7 @@ const TESTS: [string, any, Record<string, any>?][] = [
{ test: 'notInclude', expected: 'utm_source=email' },
]],
['text', [
{ test: 'include', expected: 'Your account password was reset with a recovery key' },
{ test: 'include', expected: 'Your account password was reset with an account recovery key' },
{ test: 'include', expected: configUrl('createAccountRecoveryUrl', 'password-reset-account-recovery-success', 'create-recovery-key', 'email', 'uid') },
{ test: 'include', expected: `please change your password.\n${configUrl('initiatePasswordChangeUrl', 'password-reset-account-recovery-success', 'change-password', 'email')}` },
{ test: 'include', expected: `Mozilla Privacy Policy\n${configUrl('privacyUrl', 'password-reset-account-recovery-success', 'privacy')}` },

Просмотреть файл

@ -64,7 +64,7 @@ describe('remote recovery keys', function () {
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
recoveryKeyId = result.recoveryKeyId;
recoveryData = result.recoveryData;
// Should create recovery key
// Should create account recovery key
return client
.createRecoveryKey(result.recoveryKeyId, result.recoveryData)
.then((res) => assert.ok(res, 'empty response'))
@ -79,7 +79,7 @@ describe('remote recovery keys', function () {
});
});
it('should get recovery key', () => {
it('should get account recovery key', () => {
return getAccountResetToken(client, server, email)
.then(() => client.getRecoveryKey(recoveryKeyId))
.then((res) => {
@ -87,11 +87,11 @@ describe('remote recovery keys', function () {
});
});
it('should fail to get unknown recovery key', () => {
it('should fail to get unknown account recovery key', () => {
return getAccountResetToken(client, server, email)
.then(() => client.getRecoveryKey('abce1234567890'))
.then(assert.fail, (err) => {
assert.equal(err.errno, 159, 'recovery key is not valid');
assert.equal(err.errno, 159, 'account recovery key is not valid');
});
});
@ -143,12 +143,12 @@ describe('remote recovery keys', function () {
const duration = 1000 * 60 * 60 * 24; // 24 hours
const publicKey = {
algorithm: 'RS',
n:
'4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
n: '4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123',
e: '65537',
};
const cert1 = jwtool.unverify(await client.sign(publicKey, duration))
.payload;
const cert1 = jwtool.unverify(
await client.sign(publicKey, duration)
).payload;
res = await client.resetAccountWithRecoveryKey(
'newpass',
@ -187,13 +187,13 @@ describe('remote recovery keys', function () {
assert.equal(cert1['fxa-keysChangedAt'], cert2['fxa-keysChangedAt']);
});
it('should delete recovery key', () => {
it('should delete account recovery key', () => {
return client.deleteRecoveryKey().then((res) => {
assert.ok(res, 'empty response');
return client
.getRecoveryKeyExists()
.then((result) => {
assert.equal(result.exists, false, 'recovery key deleted');
assert.equal(result.exists, false, 'account recovery key deleted');
})
.then(() => server.mailbox.waitForEmail(email))
.then((emailData) => {
@ -205,7 +205,7 @@ describe('remote recovery keys', function () {
});
});
it('should fail to create recovery key when one already exists', () => {
it('should fail to create account recovery key when one already exists', () => {
return createMockRecoveryKey(client.uid, keys.kB).then((result) => {
recoveryKeyId = result.recoveryKeyId;
recoveryData = result.recoveryData;
@ -217,15 +217,15 @@ describe('remote recovery keys', function () {
});
});
describe('check recovery key status', () => {
describe('check account recovery key status', () => {
describe('with sessionToken', () => {
it('should return true if recovery key exists and enabled', () => {
it('should return true if account recovery key exists and enabled', () => {
return client.getRecoveryKeyExists().then((res) => {
assert.equal(res.exists, true, 'recovery key exists');
assert.equal(res.exists, true, 'account recovery key exists');
});
});
it("should return false if recovery key doesn't exist", () => {
it("should return false if account recovery key doesn't exist", () => {
email = server.uniqueEmail();
return Client.createAndVerify(
config.publicUrl,
@ -239,11 +239,15 @@ describe('remote recovery keys', function () {
return client.getRecoveryKeyExists();
})
.then((res) => {
assert.equal(res.exists, false, 'recovery key doesnt exists');
assert.equal(
res.exists,
false,
'account recovery key doesnt exists'
);
});
});
it('should return false if recovery key exist but not enabled', async () => {
it('should return false if account recovery key exist but not enabled', async () => {
const email2 = server.uniqueEmail();
const client2 = await Client.createAndVerify(
config.publicUrl,
@ -264,18 +268,18 @@ describe('remote recovery keys', function () {
assert.deepEqual(res, {});
res = await client2.getRecoveryKeyExists();
assert.equal(res.exists, false, 'recovery key doesnt exists');
assert.equal(res.exists, false, 'account recovery key doesnt exists');
});
});
describe('with email', () => {
it('should return true if recovery key exists', () => {
it('should return true if account recovery key exists', () => {
return client.getRecoveryKeyExists(email).then((res) => {
assert.equal(res.exists, true, 'recovery key exists');
assert.equal(res.exists, true, 'account recovery key exists');
});
});
it("should return false if recovery key doesn't exist", () => {
it("should return false if account recovery key doesn't exist", () => {
email = server.uniqueEmail();
return Client.createAndVerify(
config.publicUrl,
@ -289,7 +293,11 @@ describe('remote recovery keys', function () {
return client.getRecoveryKeyExists(email);
})
.then((res) => {
assert.equal(res.exists, false, "recovery key doesn't exist");
assert.equal(
res.exists,
false,
"account recovery key doesn't exist"
);
});
});
});

Просмотреть файл

@ -8,7 +8,6 @@ Changes are now documented at https://github.com/mozilla/fxa/releases
- pair: Show Fx View when version >= 106 Because: ([7f1bccf601](https://github.com/mozilla/fxa/commit/7f1bccf601))
## 1.236.0
### New features
@ -987,7 +986,7 @@ No changes.
- tests: some testing updates ([d13f9fc5e](https://github.com/mozilla/fxa/commit/d13f9fc5e))
- settings: clear local storage on account delete ([382795556](https://github.com/mozilla/fxa/commit/382795556))
- settings: ensure the object returned from useSession is stable ([045902b45](https://github.com/mozilla/fxa/commit/045902b45))
- tests: Fixes recovery key flaky test and updates functional settings test ([37858955f](https://github.com/mozilla/fxa/commit/37858955f))
- tests: Fixes account recovery key flaky test and updates functional settings test ([37858955f](https://github.com/mozilla/fxa/commit/37858955f))
- tests: Enabled the disabled smoke tests ([7f948a394](https://github.com/mozilla/fxa/commit/7f948a394))
### Other changes

Просмотреть файл

@ -239,11 +239,11 @@ var ERRORS = {
},
RECOVERY_KEY_NOT_FOUND: {
errno: 158,
message: t('Recovery key not found'),
message: t('Account recovery key not found'),
},
INVALID_RECOVERY_KEY: {
errno: 159,
message: t('Invalid recovery key'),
message: t('Invalid account recovery key'),
},
TOTP_REQUIRED: {
errno: 160,
@ -586,7 +586,7 @@ var ERRORS = {
},
RECOVERY_KEY_REQUIRED: {
errno: 1059,
message: t('Recovery key required'),
message: t('Account recovery key required'),
},
OTP_CODE_REQUIRED: {
errno: 1060,

Просмотреть файл

@ -139,9 +139,9 @@ module.exports = {
UTM_SOURCE_EMAIL: 'email',
// Recovery keys are base32 encoded, length 32 gives 155 bits of entropy
// Account recovery keys are base32 encoded, length 32 gives 155 bits of entropy
// Ex. (32 char - 1 version char) * 5 bits = 155 bits. This gives us a
// 1 in 2^155 chance of clashing recovery keys.
// 1 in 2^155 chance of clashing account recovery keys.
RECOVERY_KEY_LENGTH: 32,
DEVICE_PAIRING_AUTHORITY_CONTEXT: 'device_pairing_authority',

Просмотреть файл

@ -4,7 +4,7 @@
/**
* This file contains utilities to help create, bundle and unbundle encrypted
* recovery key data.
* account recovery key data.
*
* For more encryption details, check out
* https://github.com/mozilla/fxa/blob/main/packages/fxa-auth-server/docs/recovery_keys.md
@ -22,16 +22,16 @@ function getRecoveryKeyVersion() {
export default {
/**
* Generate a random base32 recovery key. The recovery key
* Generate a random base32 account recovery key. The account recovery key
* string is prepended with version information.
*
* @param {Integer} length Length of string to generate (default 32 length)
* @returns {Promise<string>} recovery key
* @returns {Promise<string>} account recovery key
*/
generateRecoveryKey: function (length = 32) {
return Promise.resolve().then(() => {
if (length < 27) {
throw new Error('Recovery key length must be at least 27');
throw new Error('Account recovery key length must be at least 27');
}
return Base32.generate(length - 1).then((key) => {
return getRecoveryKeyVersion() + key;
@ -42,18 +42,18 @@ export default {
/**
* Get the current version of the recovery keys.
*
* @returns {string} current recovery key version
* @returns {string} current account recovery key version
*/
getCurrentRecoveryKeyVersion: function () {
return getRecoveryKeyVersion();
},
/**
* Generates the recovery JWK from the uid and recovery key. The
* Generates the recovery JWK from the uid and account recovery key. The
* recoveryJwk can be used to encrypt and decrypt data.
*
* @param {String} uid Uid of user
* @param {String} recoveryKey Recovery key
* @param {String} recoveryKey Account recovery key
* @returns {Promise} A promise that will be fulfilled with JWK
*/
getRecoveryJwk: function (uid, recoveryKey) {

Просмотреть файл

@ -291,13 +291,13 @@ FxaClientWrapper.prototype = {
accountData.verificationMethod = VerificationMethods.EMAIL;
}
}
// The `originalLoginEmail` is a users current primary email, ensure
// the account model uses this email and updates local storage with it
if (signInOptions.originalLoginEmail) {
email = signInOptions.originalLoginEmail
email = signInOptions.originalLoginEmail;
}
return getUpdatedSessionData(email, relier, accountData, options);
});
}
@ -1071,8 +1071,8 @@ FxaClientWrapper.prototype = {
replaceRecoveryCodes: createClientDelegate('replaceRecoveryCodes'),
/**
* Creates a new recovery key bundle for the current user. To
* create a recovery key first a session re-auth is performed,
* Creates a new account recovery key bundle for the current user. To
* create an account recovery key first a session re-auth is performed,
* then the account keys are fetched and finally the recovery
* bundle stores an encrypted copy of the original user's `kB`
*
@ -1120,14 +1120,14 @@ FxaClientWrapper.prototype = {
),
/**
* Deletes the recovery key associated with this user.
* Deletes the account recovery key associated with this user.
*
* @param sessionToken
*/
deleteRecoveryKey: createClientDelegate('deleteRecoveryKey'),
/**
* Verify the recovery key associated with this user.
* Verify the account recovery key associated with this user.
*
* @param sessionToken
* @param recoveryKeyId
@ -1135,7 +1135,7 @@ FxaClientWrapper.prototype = {
verifyRecoveryKey: createClientDelegate('verifyRecoveryKey'),
/**
* This checks to see if a recovery key exists for a user.
* This checks to see if an account recovery key exists for a user.
*
* @param sessionToken
* @param {String} email User's email
@ -1149,7 +1149,7 @@ FxaClientWrapper.prototype = {
* @param {String} passwordForgotCode - password forgot code
* @param {String} passwordForgotToken - password forgot token
* @param {Object} [options={}] Options
* @param {String} [options.accountResetWithRecoveryKey] - perform account reset with recovery key
* @param {String} [options.accountResetWithRecoveryKey] - perform account reset with account recovery key
* @returns {Promise} resolves with response when complete.
*/
passwordForgotVerifyCode: withClient(
@ -1163,11 +1163,11 @@ FxaClientWrapper.prototype = {
),
/**
* Gets recovery key bundle for the current user.
* Gets account recovery key bundle for the current user.
*
* @param {String} accountResetToken
* @param {String} uid - Uid of user
* @param {String} recoveryKey - User's recovery key
* @param {String} recoveryKey - User's account recovery key
* @returns {Promise} resolves with response when complete.
*/
getRecoveryBundle: withClient(
@ -1191,12 +1191,12 @@ FxaClientWrapper.prototype = {
),
/**
* Reset an account using a recovery key. This maintains a user's original encryption keys.
* Reset an account using an account recovery key. This maintains a user's original encryption keys.
*
* @param {String} accountResetToken
* @param {String} email - Email of user
* @param {String} newPassword - New password for user
* @param {String} recoveryKeyId - The recoveryKeyId that mapped to original recovery key
* @param {String} recoveryKeyId - The recoveryKeyId that mapped to original account recovery key
* @param {String} kB - Wrap new password with this kB
* @param {String} relier - Relier to sign-in
* @returns {Promise} resolves with response when complete.

Просмотреть файл

@ -738,7 +738,7 @@ _.extend(Metrics.prototype, Backbone.Events, {
/**
* Log when a user preference is updated. Example, two step authentication,
* adding recovery email or recovery key.
* adding recovery email or account recovery key.
*
* @param {String} prefName - name of preference, typically view name
* @param {Boolean} value - value of preference

Просмотреть файл

@ -1533,10 +1533,10 @@ const Account = Backbone.Model.extend(
},
/**
* Creates a new recovery key bundle for the current user.
* Creates a new account recovery key bundle for the current user.
*
* @param {String} password The current password for the user
* @param {String} enable Enable to recovery key
* @param {String} enable Enable to account recovery key
* @returns {Promise}
*/
createRecoveryBundle(password, enabled) {
@ -1550,7 +1550,7 @@ const Account = Backbone.Model.extend(
},
/**
* Deletes the recovery key associated with this user.
* Deletes the account recovery key associated with this user.
*
* @returns {Promise} resolves when complete.
*/
@ -1559,7 +1559,7 @@ const Account = Backbone.Model.extend(
},
/**
* Verify the recovery key associated with this user.
* Verify the account recovery key associated with this user.
*
* @returns {Promise} resolves when complete.
*/
@ -1571,7 +1571,7 @@ const Account = Backbone.Model.extend(
},
/**
* This checks to see if a recovery key exists for a user.
* This checks to see if an account recovery key exists for a user.
*
* @returns {Promise} resolves with response when complete.
*
@ -1584,7 +1584,7 @@ const Account = Backbone.Model.extend(
},
/**
* This checks to see if a recovery key exists for a given
* This checks to see if an account recovery key exists for a given
* email.
*
* Response: {
@ -1602,7 +1602,7 @@ const Account = Backbone.Model.extend(
* @param {String} code
* @param {String} token
* @param {Object} [options={}] Options
* @param {String} [options.accountResetWithRecoveryKey] - perform account reset with recovery key
* @param {String} [options.accountResetWithRecoveryKey] - perform account reset with account recovery key
* @returns {Promise} resolves with response when complete.
*/
passwordForgotVerifyCode(code, token, options) {
@ -1613,7 +1613,7 @@ const Account = Backbone.Model.extend(
* Get this user's recovery bundle, which contains their `kB`.
*
* @param {String} uid - Uid of user
* @param {String} recoveryKey - Recovery key for user
* @param {String} recoveryKey - Account recovery key for user
* @returns {Promise} resolves with response when complete.
*/
getRecoveryBundle(uid, recoveryKey) {
@ -1629,7 +1629,7 @@ const Account = Backbone.Model.extend(
*
* @param {String} accountResetToken
* @param {String} password - new password
* @param {String} recoveryKeyId - recoveryKeyId that maps to recovery key
* @param {String} recoveryKeyId - recoveryKeyId that maps to account recovery key
* @param {String} kB - original kB
* @param {Object} relier - relier being signed in to.
* @param {String} emailToHashWith - has password with this email address

Просмотреть файл

@ -616,7 +616,7 @@ var User = Backbone.Model.extend({
},
/**
* Complete a password reset for the account using a recovery key. Notifies other tabs
* Complete a password reset for the account using an account recovery key. Notifies other tabs
* of signin on success.
*
* @param {Object} account - account to sign up

Просмотреть файл

@ -22,7 +22,7 @@
<header>
<h1 id="fxa-recovery-key-confirm">
<!-- L10N: For languages structured like English, the second phrase can read "to continue to %(serviceName)s" -->
{{#t}}Reset password with recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{#t}}Reset password with account recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
</h1>
</header>
@ -31,20 +31,20 @@
<form novalidate>
<p class="description">
{{#t}}Please enter the one time use recovery key you stored in a safe place to regain access to your Firefox Account.{{/t}}
{{#t}}Please enter the one time use account recovery key you stored in a safe place to regain access to your Firefox Account.{{/t}}
</p>
<p class="description">
{{#unsafeTranslate}}<span class="note">NOTE:</span> If you reset your password and don't have account recovery key saved, some of your data will be erased (including synced server data like history and bookmarks).{{/unsafeTranslate}}
</p>
<div class="input-row">
<input id="recovery-key" type="text" class="text recovery-key" placeholder="{{#t}}Enter recovery key{{/t}}" value="{{ recoveryKey }}" autofocus autocomplete="off"/>
<input id="recovery-key" type="text" class="text recovery-key" placeholder="{{#t}}Enter account recovery key{{/t}}" value="{{ recoveryKey }}" autofocus autocomplete="off"/>
</div>
<div class="button-row">
<button id="submit-btn" type="submit" class="primary-button">{{#t}}Confirm recovery key{{/t}}</button>
<button id="submit-btn" type="submit" class="primary-button">{{#t}}Confirm account recovery key{{/t}}</button>
</div>
<div class="links">
<a href="#" class="lost-recovery-key">{{#t}}Don't have a recovery key?{{/t}}</a>
<a href="#" class="lost-recovery-key">{{#t}}Don't have an account recovery key?{{/t}}</a>
</div>
</form>
</section>

Просмотреть файл

@ -47,7 +47,7 @@
{{#showAccountRecoveryInfo}}
<p class="mb-5 mt-4">
{{#t}}You have successfully restored your account using your recovery key. Create a new password to secure your data, and store it in a safe location.{{/t}}
{{#t}}You have successfully restored your account using your account recovery key. Create a new password to secure your data, and store it in a safe location.{{/t}}
</p>
{{/showAccountRecoveryInfo}}

Просмотреть файл

@ -3,10 +3,10 @@
<h1 id="fxa-add-account-recovery-header">
{{#serviceName}}
<!-- L10N: For languages structured like English, the second phrase can read "to continue to %(serviceName)s" -->
{{#t}}Protect your data with a recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{#t}}Protect your data with an account recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{/serviceName}}
{{^serviceName}}
{{#t}}Protect your data with a recovery key{{/t}}
{{#t}}Protect your data with an account recovery key{{/t}}
{{/serviceName}}
</h1>
</header>
@ -21,7 +21,7 @@
<p class="verification-message">{{#t}}Because this information is critical to your security, Firefox deletes it to protect you when your password is reset to prevent other people from accessing it.{{/t}}</p>
<form novalidate>
<div class="button-row">
<button id="submit-btn" type="submit">{{#t}}Get a Recovery Key{{/t}}</button>
<button id="submit-btn" type="submit">{{#t}}Get an Account Recovery Key{{/t}}</button>
</div>
<div class="links">
<a id="maybe-later-btn" data-flow-event="link.maybe-later">{{#t}}Maybe later{{/t}}</a>

Просмотреть файл

@ -17,7 +17,7 @@
<div class="graphic graphic-recovery-codes"></div>
<p class="verification-email-message">{{#unsafeTranslate}}Please confirm your password for %(escapedEmail)s to generate your recovery key.{{/unsafeTranslate}}</p>
<p class="verification-email-message">{{#unsafeTranslate}}Please confirm your password for %(escapedEmail)s to generate your account recovery key.{{/unsafeTranslate}}</p>
<form novalidate>
<input type="email" class="email hidden" value="{{email}}" disabled />
<div class="tooltip-container mb-5">

Просмотреть файл

@ -3,10 +3,10 @@
<h1 id="fxa-confirm-recovery-key-header">
{{#serviceName}}
<!-- L10N: For languages structured like English, the second phrase can read "to continue to %(serviceName)s" -->
{{#t}}Confirm recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{#t}}Confirm account recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{/serviceName}}
{{^serviceName}}
{{#t}}Confirm recovery key{{/t}}
{{#t}}Confirm account recovery key{{/t}}
{{/serviceName}}
</h1>
</header>
@ -17,11 +17,11 @@
<div class="graphic graphic-recovery-codes"></div>
<p class="verification-email-message">{{#t}}Enter your recovery key to confirm that you've saved a copy.{{/t}}</p>
<p class="verification-email-message">{{#t}}Enter your account recovery key to confirm that you've saved a copy.{{/t}}</p>
<form novalidate>
<div class="input-row otp-code-row">
<input id="recovery-key" type="text" class="text recovery-key tooltip-below" placeholder="{{#t}}Confirm recovery key{{/t}}" autofocus autocomplete="off"/>
<input id="recovery-key" type="text" class="text recovery-key tooltip-below" placeholder="{{#t}}Confirm account recovery key{{/t}}" autofocus autocomplete="off"/>
</div>
<div class="button-row">
<button id="submit-btn" type="submit">{{#t}}Confirm{{/t}}</button>

Просмотреть файл

@ -3,10 +3,10 @@
<h1 id="fxa-save-recovery-key-header">
{{#serviceName}}
<!-- L10N: For languages structured like English, the second phrase can read "to continue to %(serviceName)s" -->
{{#t}}Save recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{#t}}Save account recovery key{{/t}} <span class="service">{{#t}}Continue to %(serviceName)s{{/t}}</span>
{{/serviceName}}
{{^serviceName}}
{{#t}}Save recovery key{{/t}}
{{#t}}Save account recovery key{{/t}}
{{/serviceName}}
</h1>
</header>

Просмотреть файл

@ -50,7 +50,7 @@
{{#isPasswordReset}}
<div class="button-row">
<button class="primary-button btn-create-recovery-key">{{#t}}Generate a new recovery key{{/t}}</button>
<button class="primary-button btn-create-recovery-key">{{#t}}Generate a new account recovery key{{/t}}</button>
</div>
<div class="links">
<a href="#" class="btn-goto-account">{{#t}}Continue to my account{{/t}}</a>

Просмотреть файл

@ -6,7 +6,7 @@
<form novalidate>
<p class="description">
{{#t}}Enter your password to view your recovery key.{{/t}}
{{#t}}Enter your password to view your account recovery key.{{/t}}
</p>
<div class="email">{{email}}</div>

Просмотреть файл

@ -52,7 +52,7 @@ const View = FormView.extend({
// If the complete password screen was navigated from the account recovery confirm
// key view, then these properties must be set in order to recover the account
// using the recovery key.
// using the account recovery key.
if (model && model.get('recoveryKeyId')) {
this._accountRecoveryVerficationInfo =
new AccountRecoveryVerificationInfo(model.toJSON());
@ -94,7 +94,7 @@ const View = FormView.extend({
// When the user clicks the confirm password reset link from their
// email, we should check to see if they have an account recovery key.
// If so, navigate to the confirm recovery key view, else continue with
// If so, navigate to the confirm account recovery key view, else continue with
// a regular password reset.
return account.checkRecoveryKeyExistsByEmail().then((result) => {
if (result.exists) {
@ -165,7 +165,7 @@ const View = FormView.extend({
return Promise.resolve()
.then(() => {
// The account recovery verification info will be set from the
// `confirm recovery key` view. If the are not set, then perform
// `confirm account recovery key` view. If the are not set, then perform
// a regular password reset.
const accountRecoveryVerificationInfo =
this._accountRecoveryVerficationInfo;

Просмотреть файл

@ -53,7 +53,7 @@ const View = BaseView.extend({
return;
}
// Check to see if account has a recovery key and store in model.
// Check to see if account has an account recovery key and store in model.
// The password reset success messaging will change depending on if it does
return this.getAccount()
.checkRecoveryKeyExistsByEmail()

Просмотреть файл

@ -17,7 +17,7 @@ element.val = function (val) {
return this.__val(val);
}
// Recovery key is displayed to the user with spaces every 4
// Account recovery key is displayed to the user with spaces every 4
// characters, replace them with empty spaces.
return this.__val().replace(/ /g, '').toUpperCase();
};

Просмотреть файл

@ -29,11 +29,12 @@ export default function (config = {}) {
return Promise.resolve().then(() => {
if (!this.$(passwordEl).length) {
// Only attach the balloon iff there is a password element. This avoids
// problems in the reset-password screen when using the recovery key
// problems in the reset-password screen when using the account recovery key
return;
}
const passwordModel = (this.passwordModel = this._createPasswordStrengthBalloonModel());
const passwordModel = (this.passwordModel =
this._createPasswordStrengthBalloonModel());
// wait a short time after the last invalid event to log the invalid reason.
// The additional delay over when the UI updates is to minimize the
// chances of spurious warnings being logged as us helping the user.

Просмотреть файл

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Shared code used by recovery key setup step, the second part of TOTP setup.
// Shared code used by account recovery key setup step, the second part of TOTP setup.
// Shared by views in login flow and settings page.
import AuthErrors from 'lib/auth-errors';

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* Mixin to support common methods on a recovery key.
* Mixin to support common methods on an account recovery key.
*
* @mixin RecoveryKeyMixin
*/
@ -20,7 +20,7 @@ const Mixin = {
getFormatedRecoveryKeyFilename() {
const account = this.getSignedInAccount();
let formattedFilename =
account.get('email') + ' ' + t('Firefox Recovery Key');
account.get('email') + ' ' + t('Firefox Account Recovery Key');
if (formattedFilename.length > 200) {
// 200 bytes (close to filesystem max) - 4 for '.txt' extension
formattedFilename = formattedFilename.substring(0, 196);

Просмотреть файл

@ -69,7 +69,7 @@ const Mixin = {
},
print(template) {
// We dynamically create a new window with recovery key and attempt to
// We dynamically create a new window with account recovery key and attempt to
// print it.
const printWindow = this.window.open('', 'Print', 'height=600,width=800');
printWindow.document.write(template);

Просмотреть файл

@ -28,7 +28,7 @@ class AddAccountRecovery extends FormView {
return this.replaceCurrentPage('/');
}
// An account can only support one recovery key at a time
// An account can only support one account recovery key at a time
return account.checkRecoveryKeyExists().then((status) => {
if (status.exists) {
return this.navigate(

Просмотреть файл

@ -4,7 +4,7 @@
/**
* View logic for the account recovery confirm password screen.
* The recovery key generated requires the password as an
* The account recovery key generated requires the password as an
* encryption key.
*/
import _, { assign } from 'underscore';
@ -33,7 +33,7 @@ class ConfirmPassword extends FormView {
return this.replaceCurrentPage('/');
}
// An account can only support one recovery key at a time
// An account can only support one account recovery key at a time
return account.checkRecoveryKeyExists().then((status) => {
if (status.exists) {
this.navigate('/post_verify/account_recovery/verified_recovery_key');

Просмотреть файл

@ -4,7 +4,7 @@
/**
* View logic for the account recovery confirm password screen.
* The recovery key generated requires the password as an
* The account recovery key generated requires the password as an
* encryption key.
*/
import _, { assign } from 'underscore';
@ -35,7 +35,7 @@ class ConfirmRecoveryKey extends FormView {
if (!this.model.get('recoveryKeyId') || !this.model.get('recoveryKey')) {
return this.navigate('/post_verify/account_recovery/add_recovery_key');
}
// An account can only support one recovery key at a time
// An account can only support one account recovery key at a time
return account.checkRecoveryKeyExists().then((status) => {
if (status.exists) {
return this.navigate(

Просмотреть файл

@ -103,7 +103,7 @@ describe('lib/crypto/a256gcm', () => {
});
});
it('should fail to unbundle with incorrect recovery key', () => {
it('should fail to unbundle with incorrect account recovery key', () => {
return createJwkForHexKey(incorrectHexKey)
.then((incorrectJwk) => {
return a256gcm.decrypt(ciphertext, incorrectJwk);

Просмотреть файл

@ -35,10 +35,10 @@ describe('lib/crypto/base32', () => {
});
});
it('should decode base32 recovery key', () => {
it('should decode base32 account recovery key', () => {
return RecoveryKey.generateRecoveryKey(32).then((string) => {
return Base32.decode(string).then((key) => {
assert.ok(key, 'correctly decoded base32 recovery key');
assert.ok(key, 'correctly decoded base32 account recovery key');
});
});
});

Просмотреть файл

@ -21,7 +21,7 @@ const encryptionOptions = {
describe('lib/crypto/recovery-keys', () => {
describe('getRecoveryKeyVersion', () => {
it('should get current recovery key version', () => {
it('should get current account recovery key version', () => {
const version = RecoveryKeys.getCurrentRecoveryKeyVersion();
assert.equal(version, 'A', 'current version matches');
});
@ -52,7 +52,10 @@ describe('lib/crypto/recovery-keys', () => {
it('should fail for length less than 27', () => {
return RecoveryKeys.generateRecoveryKey(26).then(assert.fail, (err) => {
assert.equal(err.message, 'Recovery key length must be at least 27');
assert.equal(
err.message,
'Account recovery key length must be at least 27'
);
});
});
});
@ -160,7 +163,7 @@ describe('lib/crypto/recovery-keys', () => {
});
});
it('should fail to unbundle with incorrect recovery key', () => {
it('should fail to unbundle with incorrect account recovery key', () => {
const recoveryKey = '00000000000000000000000000';
return RecoveryKeys.getRecoveryJwk(uid, recoveryKey)
.then((recoveryJwk) => {
@ -176,7 +179,7 @@ describe('lib/crypto/recovery-keys', () => {
});
});
describe('recovery key `round trip` sanity check', () => {
describe('account recovery key `round trip` sanity check', () => {
it('performs round trip check', () => {
let recoveryKey, recoveryJwk;
return RecoveryKeys.generateRecoveryKey(32)

Просмотреть файл

@ -180,7 +180,7 @@ describe('views/account_recovery_confirm_key', () => {
});
});
describe('should display error with invalid recovery key', () => {
describe('should display error with invalid account recovery key', () => {
beforeEach(() => {
return initView().then(() => {
account = user.initAccount();
@ -214,7 +214,7 @@ describe('views/account_recovery_confirm_key', () => {
});
});
describe('should navigate to regular password reset with lost recovery key', () => {
describe('should navigate to regular password reset with lost account recovery key', () => {
beforeEach(() => {
return initView().then(() => {
sinon.spy(view, 'navigate');

Просмотреть файл

@ -441,7 +441,7 @@ describe('views/confirm_reset_password', function () {
});
});
describe('_finishPasswordResetDifferentBrowser with recovery key', () => {
describe('_finishPasswordResetDifferentBrowser with account recovery key', () => {
beforeEach(() => {
recoveryKeyExists = true;
return view.render();

Просмотреть файл

@ -62,7 +62,7 @@ describe('views/mixins/save-options-mixin', () => {
assert.include(
printDocument.document.write.args[0][0],
text,
'window contains recovery key'
'window contains account recovery key'
);
assert.equal(printDocument.print.called, true, 'called print');
});

Просмотреть файл

@ -94,7 +94,7 @@ describe('views/post_verify/account_recovery/add_recovery_key', () => {
});
});
describe('with a recovery key', () => {
describe('with an account recovery key', () => {
beforeEach(() => {
recoveryKeyExists = true;
sinon.spy(view, 'navigate');

Просмотреть файл

@ -96,7 +96,7 @@ describe('views/post_verify/account_recovery/confirm_password', () => {
});
});
describe('with a recovery key', () => {
describe('with an account recovery key', () => {
beforeEach(() => {
recoveryKeyExists = true;
sinon.spy(view, 'navigate');
@ -123,7 +123,7 @@ describe('views/post_verify/account_recovery/confirm_password', () => {
return view.submit();
});
it('redirects to save recovery key page', () => {
it('redirects to save account recovery key page', () => {
assert.isTrue(
view.navigate.calledWith(
'/post_verify/account_recovery/save_recovery_key',

Просмотреть файл

@ -100,7 +100,7 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
});
});
describe('without a recovery key', () => {
describe('without an account recovery key', () => {
beforeEach(() => {
model.unset('recoveryKey');
model.unset('recoveryKeyId');
@ -108,7 +108,7 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
return view.render();
});
it('redirects to add recovery key view', () => {
it('redirects to add account recovery key view', () => {
assert.isTrue(
view.navigate.calledWith(
'/post_verify/account_recovery/add_recovery_key'
@ -124,7 +124,7 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
return view.clickBack();
});
it('redirects to save recovery key view', () => {
it('redirects to save account recovery key view', () => {
assert.isTrue(
view.navigate.calledWith(
'/post_verify/account_recovery/save_recovery_key',
@ -148,7 +148,7 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
return view.submit();
});
it('redirects to verified recovery key view', () => {
it('redirects to verified account recovery key view', () => {
assert.isTrue(
view.navigate.calledWith(
'/post_verify/account_recovery/verified_recovery_key'
@ -160,7 +160,7 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
describe('errors', () => {
let error;
describe('with mismatch recovery key', () => {
describe('with mismatch account recovery key', () => {
beforeEach(() => {
sinon.spy(view, 'showValidationError');
error = AuthErrors.toError('INVALID_RECOVERY_KEY');
@ -172,7 +172,11 @@ describe('views/post_verify/account_recovery/confirm_recovery_key', () => {
assert.equal(view.showValidationError.args.length, 1);
const args = view.showValidationError.args[0];
assert.deepEqual(args[0], view.$('#recovery-key'));
assert.equal(args[1].errno, 159, 'throws invalid recovery key error');
assert.equal(
args[1].errno,
159,
'throws invalid account recovery key error'
);
});
});

Просмотреть файл

@ -252,7 +252,7 @@ describe('views/ready', function () {
});
});
it('shows `Create recovery key` if in recoveryKey `treatment`', () => {
it('shows `Create account recovery key` if in recoveryKey `treatment`', () => {
createView(VerificationReasons.PASSWORD_RESET);
sinon.stub(view, 'isPasswordReset').callsFake(() => true);

Просмотреть файл

@ -101,7 +101,7 @@ const EVENTS = {
event: 'signup_code_submit',
},
// Add recovery key metrics, on `post_verify/account_recovery/*`
// Add account recovery key metrics, on `post_verify/account_recovery/*`
'screen.add-recovery-key': {
group: GROUPS.activity,
event: 'add_recovery_key_view',
@ -111,7 +111,7 @@ const EVENTS = {
event: 'add_recovery_key_submit',
},
// Recovery key confirm password
// Account recovery key confirm password
'screen.confirm-password': {
group: GROUPS.activity,
event: 'recovery_key_confirm_password_view',
@ -129,7 +129,7 @@ const EVENTS = {
event: 'recovery_key_confirm_password_success',
},
// Save recovery key
// Save account recovery key
'screen.save-recovery-key': {
group: GROUPS.activity,
event: 'save_recovery_key_view',
@ -151,7 +151,7 @@ const EVENTS = {
event: 'save_recovery_key_print',
},
// Confirm recovery key
// Confirm account recovery key
'screen.confirm-recovery-key': {
group: GROUPS.activity,
event: 'confirm_recovery_key_view',
@ -169,7 +169,7 @@ const EVENTS = {
event: 'confirm_recovery_key_success',
},
// Verified recovery key
// Verified account recovery key
'screen.post-verify.account-recovery.verified-recovery-key': {
group: GROUPS.activity,
event: 'verified_recovery_key_view',
@ -192,7 +192,7 @@ const EVENTS = {
event: 'forgot_password_confirm_recovery_key_submit',
},
// Password reset with recovery key metrics
// Password reset with account recovery key metrics
'screen.account-recovery-reset-password': {
group: GROUPS.login,
event: 'forgot_password_recovery_key_view',
@ -270,7 +270,7 @@ const EVENTS = {
event: 'test_fallback_text_not_needed',
minimal: true,
},
// Recovery key
// Account recovery key
'screen.settings.account-recovery': {
group: GROUPS.settings,
event: 'account_recovery_view',

Просмотреть файл

@ -36,7 +36,7 @@ const {
const getRecoveryKey = thenify(function () {
return (
this.parent
// Extract the recovery key from form
// Extract the account recovery key from form
.findByCssSelector(selectors.POST_VERIFY_SAVE_RECOVERY_KEY.RECOVERY_KEY)
.getVisibleText()
.then((key) => {
@ -119,7 +119,7 @@ registerSuite('post_verify_account_recovery', {
.then(
testElementTextInclude(
selectors.POST_VERIFY_CONFIRM_RECOVERY_KEY.TOOLTIP,
'Invalid recovery key'
'Invalid account recovery key'
)
)
.then(

Просмотреть файл

@ -37,7 +37,7 @@ const {
type,
} = FunctionalHelpers;
registerSuite('Recovery key', {
registerSuite('Account recovery key', {
beforeEach: function () {
email = createEmail('sync{id}');
const remote = this.remote;
@ -94,7 +94,7 @@ registerSuite('Recovery key', {
},
tests: {
'can revoke recovery key': function () {
'can revoke account recovery key': function () {
const remote = this.remote;
let secondKey;
return (
@ -122,7 +122,7 @@ registerSuite('Recovery key', {
testElementTextInclude(selectors.RECOVERY_KEY.STATUS, 'Not set')
)
// create a new recovery key
// create a new account recovery key
.then(click(selectors.RECOVERY_KEY.GENERATE_KEY_BUTTON))
.then(click(selectors.RECOVERY_KEY.PASSWORD_INPUT_LABEL))
.then(type(selectors.RECOVERY_KEY.PASSWORD_INPUT, PASSWORD))
@ -176,7 +176,7 @@ registerSuite('Recovery key', {
);
},
'can reset password with recovery key': function () {
'can reset password with account recovery key': function () {
return (
this.remote
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
@ -189,7 +189,7 @@ registerSuite('Recovery key', {
)
)
// enter invalid recovery key
// enter invalid account recovery key
.then(fillOutRecoveryKey('N8TVALID'))
.then(
testElementExists(
@ -215,7 +215,7 @@ registerSuite('Recovery key', {
);
},
'can reset password when forgot recovery key': function () {
'can reset password when forgot account recovery key': function () {
return (
this.remote
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
@ -246,7 +246,7 @@ registerSuite('Recovery key', {
);
},
'can not re-use recovery key': function () {
'can not re-use account recovery key': function () {
return (
this.remote
.then(openPage(RESET_PASSWORD_URL, selectors.RESET_PASSWORD.HEADER))
@ -281,7 +281,7 @@ registerSuite('Recovery key', {
},
});
registerSuite('Recovery key - unverified session', {
registerSuite('Account recovery key - unverified session', {
beforeEach: function () {
email = createEmail('sync{id}');

Просмотреть файл

@ -40,7 +40,9 @@ export class Account {
@Field((type) => Totp)
public totp!: Totp;
@Field({ description: 'Whether the user has had a recovery key issued.' })
@Field({
description: 'Whether the user has had an account recovery key issued.',
})
public recoveryKey!: boolean;
@Field({ description: 'Whether metrics are enabled and may be reported' })

Просмотреть файл

@ -195,7 +195,7 @@ A user can't do the following in an unverified session, as determined by an `Unv
- Change their password
- All actions around secondary emails
- All actions around TOTP
- All actions around the recovery key
- All actions around the account recovery key
This means we'll need to guard around any actions allowing these interactions, links to flows for these actions, and flows themselves. We can do this with by wrapping the component containing the action in question with a `VerifiedSessionGuard` that ensures a user's session is verified before displaying the content.

Просмотреть файл

@ -1,4 +1,4 @@
## Tooltip notifications for actions performed on recovery keys or one-time use codes
## Tooltip notifications for actions performed on account recovery keys or one-time use codes
datablock-download =
.message = Downloaded

Просмотреть файл

@ -81,13 +81,16 @@ it('displays a tooltip on action', async () => {
it('sets download file name', async () => {
render(
<AppContext.Provider value={{ account }}>
<DataBlock value={multiValue} contentType="Firefox recovery key" />
<DataBlock
value={multiValue}
contentType="Firefox account recovery key"
/>
</AppContext.Provider>
);
let element = await screen.findByTestId('databutton-download');
expect(element).toBeInTheDocument();
expect(element.getAttribute('download')).toContain(
'Firefox recovery key.txt'
'Firefox account recovery key.txt'
);
});

Просмотреть файл

@ -1,8 +1,8 @@
# GetDataTrio component, part of Recovery Key flow
# GetDataTrio component, part of Account Recovery Key flow
get-data-trio-title = Recovery Codes
get-data-trio-title-firefox = Firefox
get-data-trio-title-firefox-recovery-key = Firefox recovery key
get-data-trio-title-firefox-account-recovery-key = Firefox account recovery key
get-data-trio-title-firefox-backup-verification-codes = Firefox backup verification codes
get-data-trio-download =
.title = Download

Просмотреть файл

@ -7,7 +7,7 @@ import { render, screen } from '@testing-library/react';
import { Account, AppContext } from '../../models';
import GetDataTrio from './index';
const contentType = 'Firefox recovery key';
const contentType = 'Firefox account recovery key';
const value = 'Sun Tea';
const url = 'https://mozilla.org';

Просмотреть файл

@ -11,7 +11,7 @@ import { ReactComponent as PrintIcon } from './print.svg';
import { useAccount } from '../../models';
export type DownloadContentType =
| 'Firefox recovery key'
| 'Firefox account recovery key'
| 'Firefox backup verification codes'
| 'Firefox';
@ -19,7 +19,8 @@ const DownloadContentTypeL10nMapping: Record<DownloadContentType, string> = {
Firefox: 'get-data-trio-title-firefox',
'Firefox backup verification codes':
'get-data-trio-title-firefox-backup-verification-codes',
'Firefox recovery key': 'get-data-trio-title-firefox-recovery-key',
'Firefox account recovery key':
'get-data-trio-title-firefox-account-recovery-key',
};
export type GetDataTrioProps = {

Просмотреть файл

@ -1,13 +1,13 @@
# Recovery key setup page
# Account recovery key setup page
recovery-key-cancel-button = Cancel
recovery-key-close-button = Close
recovery-key-continue-button = Continue
recovery-key-created = Your recovery key has been created. Be sure to save the key in a safe place that you can easily find later — youll need the key to regain access to your data if you forget your password.
recovery-key-created = Your account recovery key has been created. Be sure to save the key in a safe place that you can easily find later — youll need the key to regain access to your data if you forget your password.
recovery-key-enter-password =
.label = Enter password
recovery-key-page-title =
.title = Recovery key
.title = Account recovery key
recovery-key-step-1 = Step 1 of 2
recovery-key-step-2 = Step 2 of 2
recovery-key-success-alert-2 = Recovery key created
recovery-key-success-alert-2 = Account recovery key created

Просмотреть файл

@ -73,7 +73,7 @@ describe('PageRecoveryKeyAdd', () => {
expect(screen.getByTestId('continue-button')).toBeDisabled();
});
it('Generates a recovery key on submit', async () => {
it('Generates an account recovery key on submit', async () => {
renderWithRouter(
<AppContext.Provider value={mockAppContext({ account })}>
<PageRecoveryKeyAdd />
@ -132,12 +132,10 @@ describe('PageRecoveryKeyAdd', () => {
.fn()
.mockResolvedValue(new Uint8Array(20));
} else {
account.createRecoveryKey = jest
.fn()
.mockImplementation(() => {
// this is just a random key that does match a real error to keep tests passing.
throw { message: 'Example error', errno: 106 }
})
account.createRecoveryKey = jest.fn().mockImplementation(() => {
// this is just a random key that does match a real error to keep tests passing.
throw { message: 'Example error', errno: 106 };
});
}
renderWithRouter(
@ -159,7 +157,7 @@ describe('PageRecoveryKeyAdd', () => {
// Wait for page to settle
if (process) {
await screen.findByText('Your recovery key has been created.', {
await screen.findByText('Your account recovery key has been created.', {
exact: false,
});
} else {

Просмотреть файл

@ -46,7 +46,7 @@ export const PageRecoveryKeyAdd = (_: RouteComponentProps) => {
l10n.getString(
'recovery-key-success-alert-2',
null,
'Recovery key created'
'Account recovery key created'
)
);
navigate(HomePath + '#recovery-key', { replace: true });
@ -116,15 +116,16 @@ export const PageRecoveryKeyAdd = (_: RouteComponentProps) => {
return (
<Localized id="recovery-key-page-title" attrs={{ title: true }}>
<FlowContainer title="Recovery key" subtitle={subtitleText}>
<FlowContainer title="Account recovery key" subtitle={subtitleText}>
<VerifiedSessionGuard onDismiss={goHome} onError={goHome} />
{formattedRecoveryKey && (
<div className="my-2" data-testid="recover-key-confirm">
<Localized id="recovery-key-created">
<p>
Your recovery key has been created. Be sure to save the key in a
safe place that you can easily find later you'll need the key
to regain access to your data if you forget your password.
Your account recovery key has been created. Be sure to save the
key in a safe place that you can easily find later you'll need
the key to regain access to your data if you forget your
password.
</p>
</Localized>
<div className="mt-6 flex flex-col items-center h-48 justify-between">
@ -136,7 +137,7 @@ export const PageRecoveryKeyAdd = (_: RouteComponentProps) => {
`recovery-key.${type}-option`
);
}}
contentType="Firefox recovery key"
contentType="Firefox account recovery key"
></DataBlock>
<Localized id="recovery-key-close-button">
<button

Просмотреть файл

@ -28,14 +28,14 @@ describe('Security', () => {
</AppContext.Provider>
);
expect(await screen.findByText('Recovery key')).toBeTruthy();
expect(await screen.findByText('Account recovery key')).toBeTruthy();
expect(await screen.findByText('Two-step authentication')).toBeTruthy();
const result = await screen.findAllByText('Not Set');
expect(result).toHaveLength(2);
});
it('renders "enabled two factor" and "recovery key present" <Security/> with correct content', async () => {
it('renders "enabled two factor" and "account recovery key present" <Security/> with correct content', async () => {
const account = {
avatar: { url: null, id: null },
primaryEmail: {

Просмотреть файл

@ -1,19 +1,19 @@
## Recovery key sub-section on main Settings page
## Account recovery key sub-section on main Settings page
rk-header = Recovery key
rk-header = Account recovery key
rk-enabled = Enabled
rk-not-set = Not Set
rk-action-create = Create
rk-action-remove = Remove
rk-cannot-refresh = Sorry, there was a problem refreshing the recovery key.
rk-cannot-refresh = Sorry, there was a problem refreshing the account recovery key.
rk-key-removed-2 = Account recovery key removed
rk-cannot-remove-key = Your account recovery key could not be removed.
rk-refresh-key = Refresh recovery key
rk-refresh-key = Refresh account recovery key
rk-content-explain = Restore your information when you forget your password.
rk-content-reset-data = Why does resetting my password reset my data?
rk-cannot-verify-session-4 = Sorry, there was a problem confirming your session
rk-remove-modal-heading = Remove recovery key?
rk-remove-modal-heading = Remove account recovery key?
rk-remove-modal-content = In the event you reset your password, you wont be
able to use your recovery key to access your data. You cant undo this action.
rk-refresh-error = Sorry, there was a problem refreshing the recovery key.
able to use your account recovery key to access your data. You cant undo this action.
rk-refresh-error = Sorry, there was a problem refreshing the account recovery key.
rk-remove-error-2 = Your account recovery key could not be removed

Просмотреть файл

@ -11,7 +11,7 @@ import { mockAppContext, mockSession } from 'fxa-settings/src/models/mocks';
storiesOf('Components/UnitRowRecoveryKey', module)
.addDecorator((getStory) => <LocationProvider>{getStory()}</LocationProvider>)
.add('with recovery key', () => (
.add('with account recovery key', () => (
<AppContext.Provider
value={mockAppContext({
account: {
@ -22,7 +22,7 @@ storiesOf('Components/UnitRowRecoveryKey', module)
<UnitRowRecoveryKey />
</AppContext.Provider>
))
.add('no recovery key', () => (
.add('no account recovery key', () => (
<AppContext.Provider
value={mockAppContext({
account: {

Просмотреть файл

@ -22,7 +22,7 @@ const account = {
} as unknown as Account;
describe('UnitRowRecoveryKey', () => {
it('renders when recovery key is set', () => {
it('renders when account recovery key is set', () => {
renderWithRouter(
<AppContext.Provider value={mockAppContext({ account })}>
<UnitRowRecoveryKey />
@ -30,7 +30,7 @@ describe('UnitRowRecoveryKey', () => {
);
expect(
screen.getByTestId('recovery-key-unit-row-header').textContent
).toContain('Recovery key');
).toContain('Account recovery key');
expect(
screen.getByTestId('recovery-key-unit-row-header-value').textContent
).toContain('Enabled');
@ -39,11 +39,11 @@ describe('UnitRowRecoveryKey', () => {
).toContain('Remove');
expect(screen.getByTestId('recovery-key-refresh')).toHaveAttribute(
'title',
'Refresh recovery key'
'Refresh account recovery key'
);
});
it('renders when recovery key is not set', () => {
it('renders when account recovery key is not set', () => {
const account = {
hasPassword: true,
recoveryKey: false,
@ -55,7 +55,7 @@ describe('UnitRowRecoveryKey', () => {
);
expect(
screen.getByTestId('recovery-key-unit-row-header').textContent
).toContain('Recovery key');
).toContain('Account recovery key');
expect(
screen.getByTestId('recovery-key-unit-row-header-value').textContent
).toContain('Not Set');
@ -111,7 +111,7 @@ describe('UnitRowRecoveryKey', () => {
expect(account.refresh).toBeCalledWith('recovery');
});
describe('delete recovery key', () => {
describe('delete account recovery key', () => {
let logViewEventSpy: jest.SpyInstance;
beforeAll(() => {
@ -147,7 +147,7 @@ describe('UnitRowRecoveryKey', () => {
fireEvent.click(await screen.findByRole('button', { name: 'Remove' }));
fireEvent.click(
await within(
await screen.findByLabelText('Remove recovery key?')
await screen.findByLabelText('Remove account recovery key?')
).findByRole('button', { name: 'Remove' })
);
};

Просмотреть файл

@ -45,12 +45,12 @@ export const UnitRowRecoveryKey = () => {
const localizedRefreshRkText = l10n.getString(
'rk-refresh-key',
null,
'Refresh recovery key'
'Refresh account recovery key'
);
return (
<UnitRow
header={l10n.getString('rk-header', null, 'Recovery key')}
header={l10n.getString('rk-header', null, 'Account recovery key')}
headerId="recovery-key"
prefixDataTestId="recovery-key"
headerValueClassName={recoveryKey ? 'text-green-800' : ''}
@ -138,14 +138,14 @@ export const UnitRowRecoveryKey = () => {
id="recovery-key-header"
className="font-bold text-xl text-center mb-2"
>
Remove recovery key?
Remove account recovery key?
</h2>
</Localized>
<Localized id="rk-remove-modal-content">
<p id="recovery-key-desc" className="my-6 text-center">
In the event you reset your password, you won't be able to use
your recovery key to access your data. You can't undo this
action.
your account recovery key to access your data. You can't undo
this action.
</p>
</Localized>
</Modal>

Просмотреть файл

@ -29,7 +29,7 @@ se-resend-code-2 = Confirmation needed. <button>Resend confirmation code</button
se-make-primary = Make primary
se-default-content = Access your account if you cant log in to your primary email.
se-content-note = Note: a secondary email wont restore your information — youll
need a <a>recovery key</a> for that.
need a <a>account recovery key</a> for that.
# Default value for the secondary email
se-secondary-email-none = None

Просмотреть файл

@ -350,7 +350,7 @@ const SecondaryEmailDefaultContent = () => (
href="#recovery-key"
data-testid="secondary-email-link-recovery-key"
>
recovery key
account recovery key
</a>
),
}}
@ -362,7 +362,7 @@ const SecondaryEmailDefaultContent = () => (
href="#recovery-key"
data-testid="secondary-email-link-recovery-key"
>
recovery key
account recovery key
</a>{' '}
for that.
</p>

Просмотреть файл

@ -235,11 +235,11 @@ const ERRORS = {
},
RECOVERY_KEY_NOT_FOUND: {
errno: 158,
message: 'Recovery key not found',
message: 'Account recovery key not found',
},
INVALID_RECOVERY_KEY: {
errno: 159,
message: 'Invalid recovery key',
message: 'Invalid account recovery key',
},
TOTP_REQUIRED: {
errno: 160,
@ -584,7 +584,7 @@ const ERRORS = {
},
RECOVERY_KEY_REQUIRED: {
errno: 1059,
message: 'Recovery key required',
message: 'Account recovery key required',
},
OTP_CODE_REQUIRED: {
errno: 1060,

Просмотреть файл

@ -395,7 +395,7 @@ export function logExperiment(
/**
* Log when a user preference is updated. Example, two step
* authentication, adding recovery email or recovery key.
* authentication, adding recovery email or account recovery key.
*
* @param prefName - Name of preference, typically view name
*/