Skip to content

Commit 577d103

Browse files
committed
Add completed-state to have option to keep window open (not yet working, because of cancel-request intervening)
1 parent e31cecd commit 577d103

4 files changed

Lines changed: 43 additions & 7 deletions

File tree

credentialsd-common/src/model.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub struct Device {
4040
pub enum Operation {
4141
Create,
4242
Get,
43+
SetDevicePin,
4344
}
4445

4546
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -128,6 +129,14 @@ impl ViewUpdateFailure {
128129
}
129130
}
130131

132+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
133+
pub enum ViewUpdateSuccess {
134+
/// Success that requires the window to close
135+
CloseWindow,
136+
/// Success that requires the window to stay open
137+
KeepWindowOpen(String),
138+
}
139+
131140
#[derive(Debug, Clone, Serialize, Deserialize)]
132141
pub enum ViewUpdate {
133142
SetTitle((String, String)),
@@ -148,7 +157,7 @@ pub enum ViewUpdate {
148157
HybridConnecting,
149158
HybridConnected,
150159

151-
Completed,
160+
Completed(ViewUpdateSuccess),
152161
Cancelled,
153162
Failed(ViewUpdateFailure),
154163
}

credentialsd-ui/src/gui/view_model/gtk/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub mod device;
44
mod window;
55

66
use async_std::channel::{Receiver, Sender};
7-
use credentialsd_common::model::ViewUpdateFailure;
7+
use credentialsd_common::model::{ViewUpdateFailure, ViewUpdateSuccess};
88
use credentialsd_common::server::WindowHandle;
99
use gettextrs::{LocaleCategory, gettext, ngettext};
1010
use glib::clone;
@@ -203,10 +203,15 @@ impl ViewModel {
203203
));
204204
view_model.set_qr_spinner_visible(false);
205205
}
206-
ViewUpdate::Completed => {
206+
ViewUpdate::Completed(ViewUpdateSuccess::CloseWindow) => {
207207
view_model.set_qr_spinner_visible(false);
208208
view_model.set_completed(true);
209209
}
210+
ViewUpdate::Completed(ViewUpdateSuccess::KeepWindowOpen(text)) => {
211+
view_model.set_qr_spinner_visible(false);
212+
// These are already gettext messages
213+
view_model.set_prompt(text);
214+
}
210215
ViewUpdate::Failed(error) => {
211216
view_model.set_qr_spinner_visible(false);
212217
view_model.set_failed(true);

credentialsd-ui/src/gui/view_model/mod.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use async_std::{
77
channel::{Receiver, Sender},
88
sync::Mutex as AsyncMutex,
99
};
10-
use credentialsd_common::model::RequestingApplication;
10+
use credentialsd_common::model::{RequestingApplication, ViewUpdateSuccess};
1111
use credentialsd_common::server::ViewRequest;
1212
use gettextrs::gettext;
1313
use serde::{Deserialize, Serialize};
@@ -83,6 +83,7 @@ impl<F: FlowController + Send> ViewModel<F> {
8383
// TRANSLATORS: %s1 is the "relying party" (think: domain name) where the request is coming from
8484
gettext("Use a passkey for %s1")
8585
}
86+
Operation::SetDevicePin => gettext("Setting Pin on device"),
8687
}
8788
.to_string();
8889
title = title.replace("%s1", &self.rp_id);
@@ -102,6 +103,7 @@ impl<F: FlowController + Send> ViewModel<F> {
102103
// TRANSLATORS: %s3 is the absolute path (think: /usr/bin/firefox) of the requesting application
103104
gettext("<b>\"%s2\"</b> (process ID: %i1, binary: %s3) is asking to use a credential to sign in to \"%s1\". Only proceed if you trust this process.")
104105
}
106+
Operation::SetDevicePin => gettext("Setting Pin on device"),
105107
}
106108
.to_string();
107109
subtitle = subtitle.replace("%s1", &self.rp_id);
@@ -210,6 +212,7 @@ impl<F: FlowController + Send> ViewModel<F> {
210212
Event::View(ViewEvent::SetNewDevicePin(pin)) => {
211213
if let Some(device) = &self.selected_device {
212214
let mut cred_service = self.flow_controller.lock().await;
215+
self.operation = Operation::SetDevicePin;
213216
let resp = match device.transport {
214217
Transport::Usb => cred_service.set_usb_device_pin(pin).await,
215218
Transport::Nfc => cred_service.set_nfc_device_pin(pin).await,
@@ -276,7 +279,15 @@ impl<F: FlowController + Send> ViewModel<F> {
276279
.unwrap();
277280
}
278281
UsbState::Completed => {
279-
self.tx_update.send(ViewUpdate::Completed).await.unwrap();
282+
let t = if matches!(self.operation, Operation::SetDevicePin) {
283+
ViewUpdateSuccess::KeepWindowOpen(gettext(
284+
"Pin successfully set! Please try registering again.",
285+
))
286+
} else {
287+
ViewUpdateSuccess::CloseWindow
288+
};
289+
290+
self.tx_update.send(ViewUpdate::Completed(t)).await.unwrap();
280291
}
281292
UsbState::SelectingDevice => {
282293
self.tx_update
@@ -347,7 +358,14 @@ impl<F: FlowController + Send> ViewModel<F> {
347358
.unwrap();
348359
}
349360
NfcState::Completed => {
350-
self.tx_update.send(ViewUpdate::Completed).await.unwrap();
361+
let t = if matches!(self.operation, Operation::SetDevicePin) {
362+
ViewUpdateSuccess::KeepWindowOpen(gettext(
363+
"Pin successfully set! Please try registering again.",
364+
))
365+
} else {
366+
ViewUpdateSuccess::CloseWindow
367+
};
368+
self.tx_update.send(ViewUpdate::Completed(t)).await.unwrap();
351369
}
352370
NfcState::Idle | NfcState::Waiting => {}
353371
NfcState::SelectCredential { creds } => {
@@ -423,7 +441,10 @@ impl<F: FlowController + Send> ViewModel<F> {
423441
}
424442
HybridState::Completed => {
425443
self.hybrid_qr_code_data = None;
426-
self.tx_update.send(ViewUpdate::Completed).await.unwrap();
444+
self.tx_update
445+
.send(ViewUpdate::Completed(ViewUpdateSuccess::CloseWindow))
446+
.await
447+
.unwrap();
427448
}
428449
HybridState::UserCancelled => {
429450
self.hybrid_qr_code_data = None;

credentialsd/src/webauthn.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ pub fn format_client_data_json(
687687
let op_str = match op {
688688
Operation::Create => "webauthn.create",
689689
Operation::Get => "webauthn.get",
690+
_ => unreachable!(),
690691
};
691692
let cross_origin_str = if is_cross_origin { "true" } else { "false" };
692693
format!("{{\"type\":\"{op_str}\",\"challenge\":\"{challenge}\",\"origin\":\"{origin}\",\"crossOrigin\":{cross_origin_str}}}")

0 commit comments

Comments
 (0)