Implement TUI authentication and inactivity relock
This commit is contained in:
@@ -3,6 +3,13 @@
|
||||
use std::{
|
||||
sync::mpsc::{self, Receiver, Sender},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use ironstorage::{
|
||||
authentication::{NativeAuthenticationHandle, NativeAuthenticationSession},
|
||||
crypto::KeyInfo,
|
||||
secret_store::SecretProtectionPolicy,
|
||||
};
|
||||
|
||||
use crate::app::{AsyncPayload, AsyncResult, RequestToken};
|
||||
@@ -12,6 +19,125 @@ pub struct AsyncExecutor {
|
||||
receiver: Receiver<AsyncResult>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
pub enum AuthenticationEvent {
|
||||
Granted(String),
|
||||
Failed(String),
|
||||
Expired,
|
||||
}
|
||||
|
||||
struct AuthenticationCompletion {
|
||||
generation: u64,
|
||||
entry: String,
|
||||
result: Result<NativeAuthenticationHandle, String>,
|
||||
}
|
||||
|
||||
pub struct AuthenticationCoordinator {
|
||||
session: NativeAuthenticationSession,
|
||||
key: KeyInfo,
|
||||
handle: Option<NativeAuthenticationHandle>,
|
||||
sender: Sender<AuthenticationCompletion>,
|
||||
receiver: Receiver<AuthenticationCompletion>,
|
||||
generation: u64,
|
||||
}
|
||||
|
||||
impl AuthenticationCoordinator {
|
||||
pub fn system(
|
||||
timeout: ironstorage::authentication::AuthenticationTimeout,
|
||||
key: KeyInfo,
|
||||
) -> Result<Self, String> {
|
||||
let session =
|
||||
NativeAuthenticationSession::system(SecretProtectionPolicy::default(), timeout)
|
||||
.map_err(|error| error.to_string())?;
|
||||
let (sender, receiver) = mpsc::channel();
|
||||
Ok(Self {
|
||||
session,
|
||||
key,
|
||||
handle: None,
|
||||
sender,
|
||||
receiver,
|
||||
generation: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn request(&mut self, entry: String) {
|
||||
self.generation = self.generation.wrapping_add(1);
|
||||
let generation = self.generation;
|
||||
let session = self.session.clone();
|
||||
let key = self.key.clone();
|
||||
let sender = self.sender.clone();
|
||||
thread::spawn(move || {
|
||||
let result = session
|
||||
.authenticate(&key)
|
||||
.map_err(|error| error.to_string());
|
||||
let _ignored = sender.send(AuthenticationCompletion {
|
||||
generation,
|
||||
entry,
|
||||
result,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pub fn completion(&mut self) -> Option<AuthenticationEvent> {
|
||||
let completion = self
|
||||
.receiver
|
||||
.try_iter()
|
||||
.filter(|completion| completion.generation == self.generation)
|
||||
.last()?;
|
||||
match completion.result {
|
||||
Ok(handle) => {
|
||||
self.handle = Some(handle);
|
||||
Some(AuthenticationEvent::Granted(completion.entry))
|
||||
}
|
||||
Err(error) => {
|
||||
self.handle = None;
|
||||
Some(AuthenticationEvent::Failed(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn touch_user_activity(&mut self) -> Option<AuthenticationEvent> {
|
||||
let handle = self.handle.as_ref()?;
|
||||
if let Err(error) = handle.touch_user_activity() {
|
||||
self.handle = None;
|
||||
return Some(AuthenticationEvent::Failed(error.to_string()));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn poll_lease(&mut self) -> Option<AuthenticationEvent> {
|
||||
match self.session.expire() {
|
||||
Ok(true) => {
|
||||
self.handle = None;
|
||||
Some(AuthenticationEvent::Expired)
|
||||
}
|
||||
Ok(false) => None,
|
||||
Err(error) => {
|
||||
self.handle = None;
|
||||
Some(AuthenticationEvent::Failed(error.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remaining_time(&self) -> Option<Duration> {
|
||||
self.handle
|
||||
.as_ref()
|
||||
.and_then(|handle| handle.remaining_time().ok())
|
||||
}
|
||||
|
||||
pub fn handle(&self) -> Option<NativeAuthenticationHandle> {
|
||||
self.handle.clone()
|
||||
}
|
||||
|
||||
pub fn lock(&mut self) -> Result<(), String> {
|
||||
self.generation = self.generation.wrapping_add(1);
|
||||
self.handle = None;
|
||||
self.session
|
||||
.manual_lock()
|
||||
.map_err(|error| error.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AsyncExecutor {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
|
||||
Reference in New Issue
Block a user