Skip to content

Commit

Permalink
feat(Onboarding): implement the new UnlockWithPukFlow
Browse files Browse the repository at this point in the history
- integrate the PUK unlock flow into the Onboarding and added a
dedicated SB page for it
- TODO: integrate into Login screen
- 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 committed Jan 21, 2025
1 parent d0f840d commit 159544b
Show file tree
Hide file tree
Showing 20 changed files with 548 additions and 71 deletions.
6 changes: 5 additions & 1 deletion storybook/pages/KeycardEnterPukPagePage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ 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)
Expand Down
3 changes: 2 additions & 1 deletion storybook/pages/KeycardIntroPagePage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ Item {
{ value: Onboarding.KeycardState.WrongKeycard, text: "WrongKeycard" },
{ value: Onboarding.KeycardState.NotKeycard, text: "NotKeycard" },
{ value: Onboarding.KeycardState.MaxPairingSlotsReached, text: "MaxPairingSlotsReached" },
{ value: Onboarding.KeycardState.Locked, text: "Locked" },
{ value: Onboarding.KeycardState.BlockedPIN, text: "BlockedPIN" },
{ value: Onboarding.KeycardState.BlockedPUK, text: "BlockedPUK" },
{ value: Onboarding.KeycardState.NotEmpty, text: "NotEmpty" },
{ value: Onboarding.KeycardState.Empty, text: "Empty" }
]
Expand Down
22 changes: 11 additions & 11 deletions storybook/pages/LoginScreenPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ SplitView {

// keycard
property int keycardState: Onboarding.KeycardState.NoPCSCService
property int keycardRemainingPinAttempts: ctrlUnlockWithPuk.checked ? 1 : 5
property int keycardRemainingPinAttempts: 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
}
Expand Down Expand Up @@ -111,6 +111,7 @@ SplitView {
onUnlockWithSeedphraseRequested: logs.logEvent("onUnlockWithSeedphraseRequested")
onUnlockWithPukRequested: logs.logEvent("onUnlockWithPukRequested")
onLostKeycard: logs.logEvent("onLostKeycard")
onKeycardFactoryResetRequested: logs.logEvent("onKeycardFactoryResetRequested")

// mocks
QtObject {
Expand Down Expand Up @@ -229,11 +230,6 @@ SplitView {
enabled: ctrlBiometrics.checked
checked: ctrlBiometrics.checked
}
Switch {
id: ctrlUnlockWithPuk
text: "Unlock with PUK available"
checked: true
}
}

RowLayout {
Expand Down Expand Up @@ -264,11 +260,15 @@ SplitView {
{ value: Onboarding.KeycardState.WrongKeycard, text: "WrongKeycard" },
{ value: Onboarding.KeycardState.NotKeycard, text: "NotKeycard" },
{ value: Onboarding.KeycardState.MaxPairingSlotsReached, text: "MaxPairingSlotsReached" },
{ value: Onboarding.KeycardState.Locked, text: "Locked" },
{ value: Onboarding.KeycardState.BlockedPIN, text: "BlockedPIN" },
{ value: Onboarding.KeycardState.BlockedPUK, text: "BlockedPUK" },
{ value: Onboarding.KeycardState.NotEmpty, text: "NotEmpty" },
{ value: Onboarding.KeycardState.Empty, text: "Empty" }
]
onActivated: store.keycardState = currentValue
onActivated: {
store.keycardState = currentValue
store.keycardRemainingPinAttempts = 3
}
Component.onCompleted: currentIndex = Qt.binding(() => indexOfValue(store.keycardState))
}
}
Expand Down
53 changes: 40 additions & 13 deletions storybook/pages/OnboardingLayoutPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,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 @@ -96,17 +97,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 @@ -187,7 +201,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 @@ -263,13 +281,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 @@ -483,19 +513,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 All @@ -522,7 +548,8 @@ SplitView {
{ value: Onboarding.KeycardState.WrongKeycard, text: "WrongKeycard" },
{ value: Onboarding.KeycardState.NotKeycard, text: "NotKeycard" },
{ value: Onboarding.KeycardState.MaxPairingSlotsReached, text: "MaxPairingSlotsReached" },
{ value: Onboarding.KeycardState.Locked, text: "Locked" },
{ value: Onboarding.KeycardState.BlockedPIN, text: "BlockedPIN" },
{ value: Onboarding.KeycardState.BlockedPUK, text: "BlockedPUK" },
{ value: Onboarding.KeycardState.NotEmpty, text: "NotEmpty" },
{ value: Onboarding.KeycardState.Empty, text: "Empty" }
]
Expand Down
Loading

0 comments on commit 159544b

Please sign in to comment.