Skip to content

Commit

Permalink
feat(Onboarding): implement the new UnblockWithPukFlow
Browse files Browse the repository at this point in the history
- integrate the PUK unblock flow into the Onboarding and Login screen
- added a dedicated SB page for it
- remove the `Locked` keycard state everywhere in favor of `BlockedPIN`
and `BlockedPUK`
- fix the various "Locked" buttons, based on the context and the state
of the keycard

Fixes: #17092
  • Loading branch information
caybro authored and micieslak committed Jan 29, 2025
1 parent 2de4d3a commit df741d6
Show file tree
Hide file tree
Showing 25 changed files with 694 additions and 135 deletions.
19 changes: 16 additions & 3 deletions storybook/pages/KeycardEnterPinPagePage.qml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

import AppLayouts.Onboarding2.pages 1.0

Expand All @@ -18,6 +19,7 @@ Item {
return valid
}
remainingAttempts: 3
unblockWithPukAvailable: ctrlUnblockWithPUK.checked
onKeycardPinEntered: (pin) => {
console.warn("!!! PIN:", pin)
console.warn("!!! RESETTING FLOW")
Expand All @@ -35,10 +37,21 @@ Item {
}
}

Label {
anchors.bottom: parent.bottom
RowLayout {
anchors.right: parent.right
text: "Hint: %1".arg(root.existingPin)
anchors.bottom: parent.bottom

CheckBox {
id: ctrlUnblockWithPUK
text: "Unblock with PUK available"
checked: true
}

Item { Layout.fillWidth: true }

Label {
text: "Hint: %1".arg(root.existingPin)
}
}
}

Expand Down
17 changes: 11 additions & 6 deletions storybook/pages/KeycardEnterPukPagePage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,25 @@ Item {
KeycardEnterPukPage {
id: page
anchors.fill: parent
remainingAttempts: 3
tryToSetPukFunction: (puk) => {
console.warn("!!! ATTEMPTED PUK:", puk)
return puk === root.existingPuk
const valid = puk === root.existingPuk
if (!valid)
remainingAttempts--
return valid
}
onKeycardPukEntered: (puk) => {
console.warn("!!! CORRECT PUK:", puk)
console.warn("!!! RESETTING FLOW")
state = "entering"
}
onKeycardFactoryResetRequested: {
console.warn("onKeycardFactoryResetRequested")
console.warn("!!! RESETTING FLOW")
state = "entering"
remainingAttempts = 3
}
}

Label {
Expand All @@ -31,8 +41,3 @@ Item {

// category: Onboarding
// status: good
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1281-45942&node-type=frame&m=dev
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1281-45950&node-type=frame&m=dev
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1281-45959&node-type=frame&m=dev
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1281-45966&node-type=frame&m=dev
// https://www.figma.com/design/Lw4nPYQcZOPOwTgETiiIYo/Desktop-Onboarding-Redesign?node-id=1281-45996&node-type=frame&m=dev
25 changes: 25 additions & 0 deletions storybook/pages/KeycardIntroPagePage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ Item {
id: introPage
KeycardIntroPage {
keycardState: ctrlKeycardState.currentValue
unblockWithPukAvailable: ctrlUnblockWithPUK.checked
unblockUsingSeedphraseAvailable: ctrlUnblockWithSeedphrase.checked
factoryResetAvailable: ctrlFactoryReset.checked
displayPromoBanner: ctrlDisplayPromo.checked
onEmptyKeycardDetected: console.warn("!!! EMPTY DETECTED")
onNotEmptyKeycardDetected: console.warn("!!! NOT EMPTY DETECTED")
onReloadKeycardRequested: console.warn("!!! RELOAD REQUESTED")
onOpenLink: Qt.openUrlExternally(link)
onOpenLinkWithConfirmation: Qt.openUrlExternally(link)
onKeycardFactoryResetRequested: console.warn("!!! FACTORY RESET")
onUnblockWithSeedphraseRequested: console.warn("!!! UNBLOCK WITH SEEDPHRASE")
onUnblockWithPukRequested: console.warn("!!! UNBLOCK WITH PUK")
}
}

Expand All @@ -55,6 +60,26 @@ Item {
anchors.right: parent.right
anchors.bottom: parent.bottom

CheckBox {
id: ctrlUnblockWithPUK
text: "Unblock with PUK available"
checked: true
}

CheckBox {
id: ctrlUnblockWithSeedphrase
text: "Unblock with seedphrase available"
checked: true
}

CheckBox {
id: ctrlFactoryReset
text: "Factory reset available"
checked: true
}

Item { Layout.fillWidth: true }

CheckBox {
id: ctrlDisplayPromo
text: "Promo banner"
Expand Down
41 changes: 30 additions & 11 deletions storybook/pages/LoginScreenPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,29 @@ SplitView {

// keycard
property int keycardState: Onboarding.KeycardState.NoPCSCService
property int keycardRemainingPinAttempts: ctrlUnlockWithPuk.checked ? 1 : 5
property int keycardRemainingPinAttempts: 3
property int keycardRemainingPukAttempts: 3

function setPin(pin: string) { // -> bool
logs.logEvent("OnboardingStore.setPin", ["pin"], arguments)
const valid = pin === ctrlPin.text
if (!valid)
keycardRemainingPinAttempts-- // SIMULATION: decrease the remaining PIN attempts
if (keycardRemainingPinAttempts <= 0) { // SIMULATION: "lock" the keycard
keycardState = Onboarding.KeycardState.Locked
keycardRemainingPinAttempts = ctrlUnlockWithPuk.checked ? 1 : 5
if (keycardRemainingPinAttempts <= 0) { // SIMULATION: "block" the keycard
keycardState = Onboarding.KeycardState.BlockedPIN
keycardRemainingPinAttempts = 0
}
return valid
}

function setPuk(puk) { // -> bool
logs.logEvent("OnboardingStore.setPuk", ["puk"], arguments)
const valid = puk === ctrlPuk.text
if (!valid)
keycardRemainingPukAttempts--
if (keycardRemainingPukAttempts <= 0) { // SIMULATION: "block" the keycard
keycardState = Onboarding.KeycardState.BlockedPUK
keycardRemainingPukAttempts = 0
}
return valid
}
Expand Down Expand Up @@ -72,9 +85,10 @@ SplitView {
}
onOnboardingCreateProfileFlowRequested: logs.logEvent("onOnboardingCreateProfileFlowRequested")
onOnboardingLoginFlowRequested: logs.logEvent("onOnboardingLoginFlowRequested")
onUnlockWithSeedphraseRequested: logs.logEvent("onUnlockWithSeedphraseRequested")
onUnlockWithPukRequested: logs.logEvent("onUnlockWithPukRequested")
onUnblockWithSeedphraseRequested: logs.logEvent("onUnblockWithSeedphraseRequested")
onUnblockWithPukRequested: logs.logEvent("onUnblockWithPukRequested")
onLostKeycard: logs.logEvent("onLostKeycard")
onKeycardFactoryResetRequested: logs.logEvent("onKeycardFactoryResetRequested")

// mocks
QtObject {
Expand All @@ -90,6 +104,7 @@ SplitView {
x: root.Window.width - width
password: ctrlPassword.text
pin: ctrlPin.text
selectedProfileIsKeycard: loginScreen.selectedProfileIsKeycard
onAccountLoginError: (error, wrongPassword) => store.accountLoginError(error, wrongPassword)
onObtainingPasswordSuccess: (password) => store.obtainingPasswordSuccess(password)
onObtainingPasswordError: (errorDescription, errorType, wrongFingerprint) => store.obtainingPasswordError(errorDescription, errorType, wrongFingerprint)
Expand Down Expand Up @@ -132,11 +147,6 @@ SplitView {
enabled: ctrlBiometrics.checked
checked: ctrlBiometrics.checked
}
Switch {
id: ctrlUnlockWithPuk
text: "Unlock with PUK available"
checked: true
}
}

RowLayout {
Expand All @@ -150,6 +160,15 @@ SplitView {
inputMask: "999999"
selectByMouse: true
}
Label {
text: "PUK:"
}
TextField {
id: ctrlPuk
text: "111111111111"
inputMask: "999999999999"
selectByMouse: true
}
Label {
text: "State:"
}
Expand Down
51 changes: 39 additions & 12 deletions storybook/pages/OnboardingLayoutPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ SplitView {
readonly property string mnemonic: "dog dog dog dog dog dog dog dog dog dog dog dog"
readonly property var seedWords: ["apple", "banana", "cat", "cow", "catalog", "catch", "category", "cattle", "dog", "elephant", "fish", "grape"]
readonly property string pin: "111111"
readonly property string puk: "111111111111"
readonly property string password: "somepassword"

// TODO simulation
Expand Down Expand Up @@ -62,17 +63,30 @@ SplitView {
property int addKeyPairState: Onboarding.AddKeyPairState.InProgress
property int syncState: Onboarding.SyncState.InProgress

property int keycardRemainingPinAttempts: ctrlUnlockWithPuk.checked ? 1 : 5
property int keycardRemainingPinAttempts: 2
property int keycardRemainingPukAttempts: 3

function setPin(pin: string) { // -> bool
logs.logEvent("OnboardingStore.setPin", ["pin"], arguments)
ctrlLoginResult.result = "🯄"
const valid = pin === mockDriver.pin
if (!valid)
keycardRemainingPinAttempts--
if (keycardRemainingPinAttempts <= 0) { // SIMULATION: "lock" the keycard
keycardState = Onboarding.KeycardState.Locked
keycardRemainingPinAttempts = ctrlUnlockWithPuk.checked ? 1 : 5
if (keycardRemainingPinAttempts <= 0) { // SIMULATION: "block" the keycard
keycardState = Onboarding.KeycardState.BlockedPIN
keycardRemainingPinAttempts = 0
}
return valid
}

function setPuk(puk) { // -> bool
logs.logEvent("OnboardingStore.setPuk", ["puk"], arguments)
const valid = puk === mockDriver.puk
if (!valid)
keycardRemainingPukAttempts--
if (keycardRemainingPukAttempts <= 0) { // SIMULATION: "block" the keycard
keycardState = Onboarding.KeycardState.BlockedPUK
keycardRemainingPukAttempts = 0
}
return valid
}
Expand Down Expand Up @@ -153,7 +167,11 @@ SplitView {
}
}

onReloadKeycardRequested: store.keycardState = Onboarding.KeycardState.NoPCSCService
onReloadKeycardRequested: {
store.keycardState = Onboarding.KeycardState.NoPCSCService
store.keycardRemainingPinAttempts = 2
store.keycardRemainingPukAttempts = 3
}

// mocks
QtObject {
Expand Down Expand Up @@ -229,13 +247,25 @@ SplitView {

visible: onboarding.stack.currentItem instanceof KeycardEnterPinPage ||
onboarding.stack.currentItem instanceof KeycardCreatePinPage ||
(onboarding.stack.currentItem instanceof LoginScreen && onboarding.stack.currentItem.selectedProfileIsKeycard)
(onboarding.stack.currentItem instanceof LoginScreen && onboarding.stack.currentItem.selectedProfileIsKeycard && store.keycardState === Onboarding.KeycardState.NotEmpty)

text: "Copy valid PIN (\"%1\")".arg(mockDriver.pin)
focusPolicy: Qt.NoFocus
onClicked: ClipboardUtils.setText(mockDriver.pin)
}

Button {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.margins: 10

visible: onboarding.stack.currentItem instanceof KeycardEnterPukPage

text: "Copy valid PUK (\"%1\")".arg(mockDriver.puk)
focusPolicy: Qt.NoFocus
onClicked: ClipboardUtils.setText(mockDriver.puk)
}

Button {
anchors.bottom: parent.bottom
anchors.right: parent.right
Expand Down Expand Up @@ -290,6 +320,7 @@ SplitView {
x: root.Window.width - width
password: mockDriver.password
pin: mockDriver.pin
selectedProfileIsKeycard: onboarding.stack.currentItem instanceof LoginScreen && onboarding.stack.currentItem.selectedProfileIsKeycard
onAccountLoginError: (error, wrongPassword) => store.accountLoginError(error, wrongPassword)
onObtainingPasswordSuccess: (password) => store.obtainingPasswordSuccess(password)
onObtainingPasswordError: (errorDescription, errorType, wrongFingerprint) => store.obtainingPasswordError(errorDescription, errorType, wrongFingerprint)
Expand Down Expand Up @@ -388,19 +419,15 @@ SplitView {
Switch {
id: ctrlTouchIdUser
text: "Touch ID login"
visible: ctrlLoginScreen.checked
enabled: ctrlBiometrics.checked
checked: ctrlBiometrics.checked
}

Switch {
id: ctrlUnlockWithPuk
text: "Unlock with PUK available"
checked: true
}

Text {
id: ctrlLoginResult
property string result: "🯄"
visible: ctrlLoginScreen.checked
text: "Login result: %1".arg(result)
}
}
Expand Down
Loading

0 comments on commit df741d6

Please sign in to comment.