UX: Minor fixes to passkey handling (#23947)

- don't try to guess the name of the manager (too many options)
- improve error message when registration is not allowed
- output error in console when registration fails
- minor fix to rename dialog layout
- hides action buttons in DiscourseHub (because adding passkeys there is not possible)
- adds acceptance test to ensure action buttons are hidden for admins seeing another user's profile
This commit is contained in:
Penar Musaraj 2023-10-18 11:46:51 -04:00 committed by GitHub
parent 585bb0df27
commit a125c9e63e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 23 deletions

View File

@ -25,20 +25,11 @@ export default class UserPasskeys extends Component {
lastUsedPrefix = I18n.t("user.passkeys.last_used_prefix");
neverUsed = I18n.t("user.passkeys.never_used");
isCurrentUser() {
return this.currentUser.id === this.args.model.id;
}
passkeyDefaultName() {
if (this.capabilities.isSafari) {
return I18n.t("user.passkeys.name.icloud_keychain");
}
if (this.capabilities.isAndroid || this.capabilities.isChrome) {
return I18n.t("user.passkeys.name.google_password_manager");
}
return I18n.t("user.passkeys.name.default");
get showActions() {
return (
this.currentUser.id === this.args.model.id &&
!this.capabilities.isAppWebview
);
}
async createPasskey() {
@ -89,7 +80,7 @@ export default class UserPasskeys extends Component {
type: credential.type,
attestation: bufferToBase64(credential.response.attestationObject),
clientData: bufferToBase64(credential.response.clientDataJSON),
name: this.passkeyDefaultName(),
name: I18n.t("user.passkeys.name.default"),
};
const registrationResponse = await this.args.model.registerPasskey(
@ -111,6 +102,8 @@ export default class UserPasskeys extends Component {
bodyComponentModel: registrationResponse,
});
} catch (error) {
// eslint-disable-next-line no-console
console.error(error);
this.errorMessage =
error.name === "InvalidStateError"
? I18n.t("user.passkeys.already_added_error")
@ -221,7 +214,7 @@ export default class UserPasskeys extends Component {
{{/if}}
</div>
</div>
{{#if this.isCurrentUser}}
{{#if this.showActions}}
<div class="passkey-right">
<div class="actions">
<PasskeyOptionsDropdown
@ -239,15 +232,15 @@ export default class UserPasskeys extends Component {
{{/each}}
</div>
<div class="controls pref-passkeys__add">
{{#if this.isCurrentUser}}
{{#if this.showActions}}
<div class="controls pref-passkeys__add">
<DButton
@action={{this.addPasskey}}
@icon="plus"
@label="user.passkeys.add_passkey"
/>
{{/if}}
</div>
</div>
{{/if}}
</div>
</template>
}

View File

@ -177,4 +177,33 @@ acceptance("User Preferences - Security", function (needs) {
"displays a dialog to confirm the user's identity before adding a passkey"
);
});
test("Viewing Passkeys - another user has a key", async function (assert) {
this.siteSettings.experimental_passkeys = true;
// user charlie has passkeys in fixtures
await visit("/u/charlie/preferences/security");
assert.strictEqual(
query(".pref-passkeys__rows .row-passkey__name").innerText.trim(),
"iCloud Keychain",
"displays the passkey name"
);
assert
.dom(".row-passkey__created-date")
.exists("displays the created at date for the passkey");
assert
.dom(".row-passkey__used-date")
.exists("displays the last used at date for the passkey");
assert
.dom(".pref-passkeys__add")
.doesNotExist("does not show add passkey button");
assert
.dom(".passkey-options-dropdown")
.doesNotExist("does not show passkey options dropdown");
});
});

View File

@ -2724,6 +2724,14 @@ export default {
text_size_seq: 0,
timezone: "America/Los_Angeles",
},
user_passkeys: [
{
id: 2,
name: "iCloud Keychain",
last_used: "2023-10-10T20:03:20.986Z",
created_at: "2023-10-09T20:01:37.578Z",
},
],
},
},
"/u/charlie/card.json": {

View File

@ -806,3 +806,8 @@
max-width: 500px;
}
}
.rename-passkey__message {
max-width: 500px;
margin-bottom: 2em;
}

View File

@ -1518,15 +1518,13 @@ en:
rename_passkey_instructions: "Pick a passkey name that will easily identify it for you, for example, use the name of your password manager."
name:
default: "Main Passkey"
google_password_manager: "Google Password Manager"
icloud_keychain: "iCloud Keychain"
save: "Save"
title: "Passkeys"
short_description: "Passkeys are password replacements that validate your identity biometrically (e.g. touch, faceID) or via a device PIN/password."
added_prefix: "Added"
last_used_prefix: "Last Used"
never_used: "Never Used"
not_allowed_error: "The passkey registration process either timed out or was cancelled."
not_allowed_error: "The passkey registration process either timed out, was cancelled or is not allowed."
already_added_error: "You have already registered this passkey. You dont have to register it again."
change_about: