unit client app
This commit is contained in:
2
nkode-rs
2
nkode-rs
Submodule nkode-rs updated: e5712b4a92...a81a09ac86
@@ -2,20 +2,20 @@ use std::marker::PhantomData;
|
|||||||
use crate::client::client_auth_api::ClientAuth;
|
use crate::client::client_auth_api::ClientAuth;
|
||||||
use crate::client::opaque::{ServerConnectionLogin, ServerConnectionRegister};
|
use crate::client::opaque::{ServerConnectionLogin, ServerConnectionRegister};
|
||||||
use crate::client::repo::ClientRepo;
|
use crate::client::repo::ClientRepo;
|
||||||
use crate::client::states::{KeyLogin, KeyRegister, UserStateCodeLogin, UserStateCodeRegister, UserStateKey};
|
use crate::client::states::{DisplayKeypad, KeyLogin, KeyRegister, UserStateCodeLogin, UserStateCodeRegister, UserStateKey};
|
||||||
use crate::shared::models::app::{Icon, IconID};
|
use crate::shared::models::app::{Icon, IconID};
|
||||||
use crate::shared::email::Email;
|
use crate::shared::email::Email;
|
||||||
use crate::shared::opaque::UserSecretKey;
|
use crate::shared::opaque::UserSecretKey;
|
||||||
use crate::shared::user_api::UserAPI;
|
use crate::shared::user_api::UserAPI;
|
||||||
|
|
||||||
pub struct ClientApp<'a,'b ,State, K,C, U, R>
|
pub struct ClientApp<'a,'b, 'c,State, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
R: ClientRepo
|
R: ClientRepo
|
||||||
{
|
{
|
||||||
auth_api: ClientAuth<'a,'b ,K,C, U>,
|
auth_api: ClientAuth<'a,'b,'c ,K,C, U>,
|
||||||
client_repo: R,
|
client_repo: R,
|
||||||
code_reg: Option<UserStateCodeRegister>,
|
code_reg: Option<UserStateCodeRegister>,
|
||||||
key_login: Option<UserStateKey<KeyLogin>>,
|
key_login: Option<UserStateKey<KeyLogin>>,
|
||||||
@@ -25,14 +25,14 @@ where
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl <'a,'b ,State, K,C, U, R>ClientApp<'a,'b ,State, K,C, U, R>
|
impl <'a,'b,'c ,State, K,C, U, R>ClientApp<'a,'b,'c ,State, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
R: ClientRepo,
|
R: ClientRepo,
|
||||||
{
|
{
|
||||||
pub fn new(auth_api: ClientAuth<'a,'b , K,C, U>, client_repo: R) -> Self {
|
pub fn new(auth_api: ClientAuth<'a,'b,'c, K,C, U>, client_repo: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
auth_api,
|
auth_api,
|
||||||
client_repo,
|
client_repo,
|
||||||
@@ -43,7 +43,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_state<NextState>(self) -> ClientApp<'a,'b, NextState, K,C, U, R> {
|
fn into_state<NextState>(self) -> ClientApp<'a,'b,'c, NextState, K,C, U, R> {
|
||||||
ClientApp {
|
ClientApp {
|
||||||
auth_api: self.auth_api,
|
auth_api: self.auth_api,
|
||||||
client_repo: self.client_repo,
|
client_repo: self.client_repo,
|
||||||
@@ -56,24 +56,24 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewUserRegisterKey;
|
pub struct NewUserRegisterKey;
|
||||||
impl <'a,'b, K, C, U, R> ClientApp<'a,'b, NewUserRegisterKey, K,C, U, R>
|
impl <'a,'b, 'c,K, C, U, R> ClientApp<'a,'b,'c, NewUserRegisterKey, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
R: ClientRepo,
|
R: ClientRepo,
|
||||||
{
|
{
|
||||||
pub async fn new_user(mut self, email: Email, secret_key: UserSecretKey) -> Result<ClientApp<'a,'b, NewUserRegisterCode, K,C, U, R>, String> {
|
pub async fn new_user(mut self, email: Email, secret_key: UserSecretKey) -> Result<ClientApp<'a,'b,'c, NewUserRegisterCode, K,C, U, R>, String> {
|
||||||
let key_register = UserStateKey::<KeyRegister>::new(email.clone(), secret_key.clone());
|
let key_register = UserStateKey::<KeyRegister>::new(email.clone(), secret_key.clone());
|
||||||
self.client_repo.add_secret_key(email.clone(), secret_key.clone()).await?;
|
self.client_repo.add_secret_key(email.clone(), secret_key.clone()).await?;
|
||||||
let key_login = match key_register.register(&self.auth_api).await.map_err(|e| format!("error: {e:?}")) {
|
let key_login = match key_register.register(&self.auth_api).await.map_err(|e| format!("error key reg: {e:?}")) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.client_repo.remove_secret_key(&email).await.expect("couldn't delete");
|
self.client_repo.remove_secret_key(&email).await.expect("couldn't delete");
|
||||||
return Err(format!("error registering key {}", e))
|
return Err(format!("error registering key {}", e))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let key_logged_in = key_login.login(&self.auth_api).await.map_err(|e| format!("error: {e:?}"))?;
|
let key_logged_in = key_login.login(&self.auth_api).await.map_err(|e| format!("error key login: {e:?}"))?;
|
||||||
let code_register = key_logged_in.to_register_code(&self.auth_api).await?;
|
let code_register = key_logged_in.to_register_code(&self.auth_api).await?;
|
||||||
self.code_reg = Some(code_register);
|
self.code_reg = Some(code_register);
|
||||||
Ok(self.into_state::<NewUserRegisterCode>())
|
Ok(self.into_state::<NewUserRegisterCode>())
|
||||||
@@ -82,7 +82,7 @@ where
|
|||||||
|
|
||||||
pub struct NewUserRegisterCode;
|
pub struct NewUserRegisterCode;
|
||||||
|
|
||||||
impl <'a,'b, K, C, U, R> ClientApp<'a,'b, NewUserRegisterCode, K,C, U, R>
|
impl <'a,'b,'c, K, C, U, R> ClientApp<'a,'b,'c, NewUserRegisterCode, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
@@ -98,7 +98,7 @@ where
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_user_register_code(mut self, selected_icons: Vec<IconID>) -> Result<ClientApp<'a,'b, UserCodeLogin, K,C, U, R>, String> {
|
pub async fn new_user_register_code(mut self, selected_icons: Vec<IconID>) -> Result<ClientApp<'a,'b,'c, UserCodeLogin, K,C, U, R>, String> {
|
||||||
let code_register = self.code_reg.ok_or("no code register".to_string())?;
|
let code_register = self.code_reg.ok_or("no code register".to_string())?;
|
||||||
self.code_reg = None;
|
self.code_reg = None;
|
||||||
self.code_login = Some(code_register.clone().register(&self.auth_api,selected_icons).await?);
|
self.code_login = Some(code_register.clone().register(&self.auth_api,selected_icons).await?);
|
||||||
@@ -109,14 +109,14 @@ where
|
|||||||
|
|
||||||
pub struct UserKeyLogin;
|
pub struct UserKeyLogin;
|
||||||
|
|
||||||
impl <'a,'b, K, C, U, R> ClientApp<'a,'b, UserKeyLogin, K,C, U, R>
|
impl <'a,'b, 'c,K, C, U, R> ClientApp<'a,'b, 'c,UserKeyLogin, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
R: ClientRepo,
|
R: ClientRepo,
|
||||||
{
|
{
|
||||||
pub async fn login(mut self, email: Email, secret_key: UserSecretKey) -> Result<ClientApp<'a,'b, UserCodeLogin,K,C, U, R>, String> {
|
pub async fn login(mut self, email: Email, secret_key: UserSecretKey) -> Result<ClientApp<'a,'b, 'c,UserCodeLogin,K,C, U, R>, String> {
|
||||||
self.code_login = Some(
|
self.code_login = Some(
|
||||||
UserStateKey::<KeyLogin>::new(email, secret_key)
|
UserStateKey::<KeyLogin>::new(email, secret_key)
|
||||||
.login(&self.auth_api).await?
|
.login(&self.auth_api).await?
|
||||||
@@ -127,20 +127,20 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserCodeLogin;
|
pub struct UserCodeLogin;
|
||||||
impl <'a,'b, K, C, U, R> ClientApp<'a,'b, UserCodeLogin, K,C, U, R>
|
impl <'a,'b,'c, K, C, U, R> ClientApp<'a,'b,'c, UserCodeLogin, K,C, U, R>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
R: ClientRepo,
|
R: ClientRepo,
|
||||||
{
|
{
|
||||||
pub async fn get_keypad(&self) -> Result<Vec<Vec<Icon>>, String> {
|
pub fn get_keypad(&self) -> Result<DisplayKeypad, String> {
|
||||||
let code_login = self.code_login.clone().ok_or("no code login")?;
|
let code_login = self.code_login.clone().ok_or("no code login")?;
|
||||||
Ok(code_login.get_keypad().await)
|
Ok(code_login.get_keypad())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login(self, key_selection: Vec<usize>) -> Result<(), String> {
|
pub async fn login(self, key_selection: &Vec<usize>) -> Result<(), String> {
|
||||||
let code_login = self.code_login.unwrap().login(&self.auth_api, &key_selection).await?;
|
let code_login = self.code_login.unwrap().login(&self.auth_api, key_selection).await?;
|
||||||
self.client_repo.add_code_logged_in(code_login.0.email.clone(), code_login).await
|
self.client_repo.add_code_logged_in(code_login.0.email.clone(), code_login).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::client::opaque::{OpaqueAuthData, OpaqueAuth, ServerConnectionLogin, S
|
|||||||
use crate::shared::signed_session_data::SignedSessionData;
|
use crate::shared::signed_session_data::SignedSessionData;
|
||||||
use crate::shared::user_api::UserAPI;
|
use crate::shared::user_api::UserAPI;
|
||||||
|
|
||||||
pub struct ClientAuth<'a,'b, K,C, U>
|
pub struct ClientAuth<'a,'b,'c, K,C, U>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
@@ -19,16 +19,16 @@ where
|
|||||||
opaque_key_login: OpaqueAuth<'a, K>,
|
opaque_key_login: OpaqueAuth<'a, K>,
|
||||||
opaque_code_register: OpaqueAuth<'b, C>,
|
opaque_code_register: OpaqueAuth<'b, C>,
|
||||||
opaque_code_login: OpaqueAuth<'b, C>,
|
opaque_code_login: OpaqueAuth<'b, C>,
|
||||||
user_api: U
|
user_api: &'c U
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a,'b, K,C, U> ClientAuth<'a,'b, K,C, U>
|
impl<'a,'b,'c, K,C, U> ClientAuth<'a,'b,'c, K,C, U>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
U: UserAPI,
|
U: UserAPI,
|
||||||
{
|
{
|
||||||
pub fn new(key_connection: &'a K, code_connection: &'b C, user_api: U) -> Self {
|
pub fn new(key_connection: &'a K, code_connection: &'b C, user_api: &'c U) -> Self {
|
||||||
Self{
|
Self{
|
||||||
opaque_key_register: OpaqueAuth::new(key_connection),
|
opaque_key_register: OpaqueAuth::new(key_connection),
|
||||||
opaque_key_login: OpaqueAuth::new(key_connection),
|
opaque_key_login: OpaqueAuth::new(key_connection),
|
||||||
@@ -41,7 +41,7 @@ where
|
|||||||
|
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl<'a,'b, K,C, U> AuthAPI for ClientAuth<'a,'b, K,C, U>
|
impl<'a,'b,'c, K,C, U> AuthAPI for ClientAuth<'a,'b,'c, K,C, U>
|
||||||
where
|
where
|
||||||
K: ServerConnectionRegister + ServerConnectionLogin,
|
K: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
C: ServerConnectionRegister + ServerConnectionLogin,
|
C: ServerConnectionRegister + ServerConnectionLogin,
|
||||||
@@ -53,6 +53,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn register_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, register_code_data: RegisterCodeData) -> Result<(), String> {
|
async fn register_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, register_code_data: RegisterCodeData) -> Result<(), String> {
|
||||||
|
println!("register passcode: {:?}", passcode.to_vec());
|
||||||
let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode);
|
let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode);
|
||||||
self.opaque_code_register.register(&auth_data).await.map_err(|e| format!("error: {}", e))?;
|
self.opaque_code_register.register(&auth_data).await.map_err(|e| format!("error: {}", e))?;
|
||||||
let signed_session = SignedSessionData::new(
|
let signed_session = SignedSessionData::new(
|
||||||
@@ -70,6 +71,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn login_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, keypad: Keypad) -> Result<CodeLoggedInSession, String> {
|
async fn login_code(&self, email: &Email, passcode: &[u64], key_login_session: &KeyLoggedInSession, keypad: Keypad) -> Result<CodeLoggedInSession, String> {
|
||||||
|
println!("login passcode: {:?}", passcode.to_vec());
|
||||||
let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode);
|
let auth_data = OpaqueAuthData::from_code(email.as_str(), passcode);
|
||||||
let signed_session = SignedSessionData::new(
|
let signed_session = SignedSessionData::new(
|
||||||
key_login_session.0.session_id,
|
key_login_session.0.session_id,
|
||||||
@@ -77,7 +79,7 @@ where
|
|||||||
&key_login_session.0.session_key
|
&key_login_session.0.session_key
|
||||||
).map_err(|e| format!("error: {e:?}"))?;
|
).map_err(|e| format!("error: {e:?}"))?;
|
||||||
self.user_api.update_keypad(signed_session).await?;
|
self.user_api.update_keypad(signed_session).await?;
|
||||||
let session = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("error: {}", e))?;
|
let session = self.opaque_code_login.login(&auth_data).await.map_err(|e| format!("opaque code login error: {}", e))?;
|
||||||
Ok(CodeLoggedInSession(session))
|
Ok(CodeLoggedInSession(session))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl UserStateCodeRegister {
|
|||||||
let (cipher, cipher_nonce) = NKodeCipher::new(policy, &secret_key);
|
let (cipher, cipher_nonce) = NKodeCipher::new(policy, &secret_key);
|
||||||
let passcode_idx: Vec<usize> = selected_icons
|
let passcode_idx: Vec<usize> = selected_icons
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|x1| self.icons.iter().position(|x| x.id() == x1))
|
.filter_map(|x1| self.icons.iter().position(|x| x.id == *x1))
|
||||||
.collect();
|
.collect();
|
||||||
let ciphered_nkode = cipher.encipher(&passcode_idx).unwrap();
|
let ciphered_nkode = cipher.encipher(&passcode_idx).unwrap();
|
||||||
let data = CodeLoginData{
|
let data = CodeLoginData{
|
||||||
@@ -143,6 +143,10 @@ impl UserStateCodeRegister {
|
|||||||
self.icons.clone()
|
self.icons.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub struct DisplayKeypad {
|
||||||
|
pub sorted_icons: Vec<Icon>,
|
||||||
|
pub keypad: Keypad,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct UserStateCodeLogin {
|
pub struct UserStateCodeLogin {
|
||||||
@@ -169,7 +173,10 @@ impl UserStateCodeLogin {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_keypad(&self) -> Vec<Vec<Icon>> {
|
pub fn get_keypad(&self) -> DisplayKeypad {
|
||||||
todo!()
|
DisplayKeypad{
|
||||||
|
sorted_icons: self.sort_icons(),
|
||||||
|
keypad: self.keypad.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ pub struct ServerApp<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> {
|
|||||||
server_setup: NKodeServerSetup,
|
server_setup: NKodeServerSetup,
|
||||||
opaque_db: R,
|
opaque_db: R,
|
||||||
opaque_sess: S,
|
opaque_sess: S,
|
||||||
user_db: U,
|
pub user_db: U,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U> {
|
impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U> {
|
||||||
@@ -85,7 +85,7 @@ impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U
|
|||||||
Ok(OpaqueLoginSession { session_id: cache.session_id, response: start.message })
|
Ok(OpaqueLoginSession { session_id: cache.session_id, response: start.message })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn login_finish(
|
pub async fn login_finish<K: CredKind>(
|
||||||
&self,
|
&self,
|
||||||
session_id: &Uuid,
|
session_id: &Uuid,
|
||||||
finalize: CredentialFinalization<NKodeCipherSuite>,
|
finalize: CredentialFinalization<NKodeCipherSuite>,
|
||||||
@@ -93,7 +93,6 @@ impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U
|
|||||||
let cache = self.opaque_sess
|
let cache = self.opaque_sess
|
||||||
.get_login_session(session_id).await
|
.get_login_session(session_id).await
|
||||||
.map_err(|e| format!("get login session: {e}"))?;
|
.map_err(|e| format!("get login session: {e}"))?;
|
||||||
|
|
||||||
let finish = cache.server_login
|
let finish = cache.server_login
|
||||||
.finish(finalize, ServerLoginParameters::default())
|
.finish(finalize, ServerLoginParameters::default())
|
||||||
.map_err(|e| format!("opaque login finish: {e:?}"))?;
|
.map_err(|e| format!("opaque login finish: {e:?}"))?;
|
||||||
@@ -101,11 +100,13 @@ impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U
|
|||||||
.clear_login_session(session_id).await
|
.clear_login_session(session_id).await
|
||||||
.map_err(|e| format!("clear login session: {e}"))?;
|
.map_err(|e| format!("clear login session: {e}"))?;
|
||||||
let session_key = OpaqueSessionKey::from_bytes(&finish.session_key.to_vec()).unwrap();
|
let session_key = OpaqueSessionKey::from_bytes(&finish.session_key.to_vec()).unwrap();
|
||||||
Ok(LoggedInSession{
|
let session = LoggedInSession{
|
||||||
session_id: Uuid::new_v4(),
|
session_id: Uuid::new_v4(),
|
||||||
email: Email::from_bytes(cache.identifiers.as_slice()).unwrap(),
|
email: Email::from_bytes(cache.identifiers.as_slice()).unwrap(),
|
||||||
session_key
|
session_key
|
||||||
})
|
};
|
||||||
|
K::set_session(&self.user_db, session.clone()).await?;
|
||||||
|
Ok(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn key_login_finish(
|
pub async fn key_login_finish(
|
||||||
@@ -113,7 +114,7 @@ impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U
|
|||||||
session_id: &Uuid,
|
session_id: &Uuid,
|
||||||
finalize: CredentialFinalization<NKodeCipherSuite>,
|
finalize: CredentialFinalization<NKodeCipherSuite>,
|
||||||
) -> Result<KeyLoggedInSession, String> {
|
) -> Result<KeyLoggedInSession, String> {
|
||||||
let session = KeyLoggedInSession(self.login_finish(session_id, finalize).await?);
|
let session = KeyLoggedInSession(self.login_finish::<Key>(session_id, finalize).await?);
|
||||||
self.user_db.set_key_session(session.clone()).await?;
|
self.user_db.set_key_session(session.clone()).await?;
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ impl<R: OpaqueDatabaseRepo, S: OpaqueSessionRepo, U: UserRepo> ServerApp<R, S, U
|
|||||||
session_id: &Uuid,
|
session_id: &Uuid,
|
||||||
finalize: CredentialFinalization<NKodeCipherSuite>,
|
finalize: CredentialFinalization<NKodeCipherSuite>,
|
||||||
) -> Result<CodeLoggedInSession, String> {
|
) -> Result<CodeLoggedInSession, String> {
|
||||||
let session = CodeLoggedInSession(self.login_finish(session_id, finalize).await?);
|
let session = CodeLoggedInSession(self.login_finish::<Code>(session_id, finalize).await?);
|
||||||
self.user_db.set_code_session(session.clone()).await?;
|
self.user_db.set_code_session(session.clone()).await?;
|
||||||
Ok(session)
|
Ok(session)
|
||||||
}
|
}
|
||||||
@@ -162,6 +163,10 @@ impl CredKind for Key {
|
|||||||
async fn set_password_file<R: OpaqueDatabaseRepo>(repo: &R, id: &[u8], pf: PasswordFile) -> Result<(), AuthRepoError> {
|
async fn set_password_file<R: OpaqueDatabaseRepo>(repo: &R, id: &[u8], pf: PasswordFile) -> Result<(), AuthRepoError> {
|
||||||
repo.new_key(id, pf).await
|
repo.new_key(id, pf).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_session<R: UserRepo>(repo: &R, session: LoggedInSession) -> Result<(), String> {
|
||||||
|
repo.set_key_session(KeyLoggedInSession(session)).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@@ -182,4 +187,8 @@ impl CredKind for Code {
|
|||||||
Err(AuthRepoError::KeyNotRegistered)
|
Err(AuthRepoError::KeyNotRegistered)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn set_session<R: UserRepo>(repo: &R, session: LoggedInSession) -> Result<(), String> {
|
||||||
|
repo.set_code_session(CodeLoggedInSession(session)).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ use async_trait::async_trait;
|
|||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use opaque_ke::ServerLogin;
|
use opaque_ke::ServerLogin;
|
||||||
use crate::server::repository::opaque_repo::{AuthRepoError, OpaqueDatabaseRepo};
|
use crate::server::repository::opaque_repo::{AuthRepoError, OpaqueDatabaseRepo};
|
||||||
|
use crate::server::repository::user_repo::UserRepo;
|
||||||
|
use crate::shared::models::app::LoggedInSession;
|
||||||
use crate::shared::opaque::{NKodeCipherSuite, PasswordFile};
|
use crate::shared::opaque::{NKodeCipherSuite, PasswordFile};
|
||||||
|
|
||||||
pub struct RegCache {
|
pub struct RegCache {
|
||||||
@@ -23,4 +25,5 @@ pub trait CredKind: Send + Sync {
|
|||||||
async fn prereq_for_register<R: OpaqueDatabaseRepo>(_repo: &R, _id: &[u8]) -> Result<(), AuthRepoError> {
|
async fn prereq_for_register<R: OpaqueDatabaseRepo>(_repo: &R, _id: &[u8]) -> Result<(), AuthRepoError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
async fn set_session<R: UserRepo>(repo: &R, session: LoggedInSession) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ where
|
|||||||
) -> Result<LoggedInSession, ClientAuthError> {
|
) -> Result<LoggedInSession, ClientAuthError> {
|
||||||
Ok(self
|
Ok(self
|
||||||
.auth_db
|
.auth_db
|
||||||
.login_finish(session_id, message.clone())
|
.login_finish::<K>(session_id, message.clone())
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ClientAuthError::Transport(e))?
|
.map_err(|e| ClientAuthError::Transport(e))?
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -44,28 +44,28 @@ impl UserRepo for InMemoryUserDB {
|
|||||||
self.key_session.lock().await
|
self.key_session.lock().await
|
||||||
.get(&session_id)
|
.get(&session_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| format!("key session not found for session_id={}", session_id))
|
.ok_or(format!("key session not found for session_id={}", session_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_code_session(&self, session_id: &Uuid) -> Result<CodeLoggedInSession, String> {
|
async fn get_code_session(&self, session_id: &Uuid) -> Result<CodeLoggedInSession, String> {
|
||||||
self.code_session.lock().await
|
self.code_session.lock().await
|
||||||
.get(&session_id)
|
.get(&session_id)
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or_else(|| format!("code session not found for session_id={}", session_id))
|
.ok_or(format!("code session not found for session_id={}", session_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_key_session(&self, session: KeyLoggedInSession) -> Result<(), String> {
|
async fn set_key_session(&self, session: KeyLoggedInSession) -> Result<(), String> {
|
||||||
self.key_session.lock().await.insert(session.0.session_id, session).ok_or("couldn't set key session".to_string())?;
|
self.key_session.lock().await.insert(session.0.session_id, session);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_code_session(&self, session: CodeLoggedInSession) -> Result<(), String> {
|
async fn set_code_session(&self, session: CodeLoggedInSession) -> Result<(), String> {
|
||||||
self.code_session.lock().await.insert(session.0.session_id, session).ok_or("couldn't set code session".to_string())?;
|
self.code_session.lock().await.insert(session.0.session_id, session);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_code_login_data(&self, email: Email, data: CodeLoginData) -> Result<(), String> {
|
async fn set_code_login_data(&self, email: Email, data: CodeLoginData) -> Result<(), String> {
|
||||||
self.code_data_store.lock().await.insert(email, data).ok_or("couldn't set code login data")?;
|
self.code_data_store.lock().await.insert(email, data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,11 +114,11 @@ impl UserAPI for InMemoryUserDB {
|
|||||||
async fn set_code_login_data(&self, session: SignedSessionData<RegisterCodeData>) -> Result<(), String> {
|
async fn set_code_login_data(&self, session: SignedSessionData<RegisterCodeData>) -> Result<(), String> {
|
||||||
let key_session = self.get_key_session(&session.session_id).await?;
|
let key_session = self.get_key_session(&session.session_id).await?;
|
||||||
session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?;
|
session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?;
|
||||||
self.code_data_store.lock().await.insert(session.data.code_login_data.email.clone(), session.data.code_login_data).ok_or("couldn't set code data".to_string())?;
|
self.code_data_store.lock().await.insert(session.data.code_login_data.email.clone(), session.data.code_login_data);
|
||||||
let mut owned_icons = self.owned_icons.lock().await;
|
let mut owned_icons = self.owned_icons.lock().await;
|
||||||
for icon in session.data.icons {
|
for icon in session.data.icons {
|
||||||
let icon_id = icon.id().clone();
|
let icon_id = icon.id.clone();
|
||||||
owned_icons.insert(icon_id.clone(), icon).ok_or(format!("error inserting icon into owned icons {}", icon_id))?;
|
owned_icons.insert(icon_id.clone(), icon);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -130,7 +130,7 @@ impl UserAPI for InMemoryUserDB {
|
|||||||
let mut code_data_store = self.code_data_store.lock().await;
|
let mut code_data_store = self.code_data_store.lock().await;
|
||||||
let mut code_data = code_data_store.remove(&email).ok_or("user doesn't have code data".to_string())?;
|
let mut code_data = code_data_store.remove(&email).ok_or("user doesn't have code data".to_string())?;
|
||||||
code_data.keypad = session.data;
|
code_data.keypad = session.data;
|
||||||
code_data_store.insert(email, code_data).ok_or("couldn't update keypad")?;
|
code_data_store.insert(email, code_data);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,8 +149,8 @@ impl UserAPI for InMemoryUserDB {
|
|||||||
session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?;
|
session.verify(&key_session.0.session_key).map_err(|e| format!("session error: {e:?}"))?;
|
||||||
let mut owned_icons = self.owned_icons.lock().await;
|
let mut owned_icons = self.owned_icons.lock().await;
|
||||||
for icon in session.data {
|
for icon in session.data {
|
||||||
let icon_id = icon.id().clone();
|
let icon_id = icon.id.clone();
|
||||||
owned_icons.insert(icon_id.clone(), icon).ok_or(format!("error inserting icon into owned icons {}", icon_id))?;
|
owned_icons.insert(icon_id.clone(), icon);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use std::fmt;
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use nkode_rs::nkode_core::chacha20prng::Nonce; use nkode_rs::nkode_core::keypad::Keypad;
|
use nkode_rs::nkode_core::chacha20prng::Nonce; use nkode_rs::nkode_core::keypad::Keypad;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use getset::Getters;
|
|
||||||
use nkode_rs::from_bytes::FromBytes;
|
use nkode_rs::from_bytes::FromBytes;
|
||||||
use nkode_rs::nkode_core::policy::NKodePolicy;
|
use nkode_rs::nkode_core::policy::NKodePolicy;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
@@ -24,7 +23,7 @@ pub struct CodeLoggedInSession(pub(crate) LoggedInSession);
|
|||||||
|
|
||||||
pub const ICON_ID_SIZE: usize = 32;
|
pub const ICON_ID_SIZE: usize = 32;
|
||||||
#[derive(Debug, Clone, PartialEq, Eq,Hash, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq,Hash, Serialize, Deserialize)]
|
||||||
pub struct IconID([u8; 32]);
|
pub struct IconID(pub [u8; 32]);
|
||||||
|
|
||||||
impl fmt::Display for IconID {
|
impl fmt::Display for IconID {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
@@ -41,12 +40,10 @@ impl FromBytes<ICON_ID_SIZE> for IconID {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Getters)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Icon {
|
pub struct Icon {
|
||||||
#[get = "pub"]
|
pub id: IconID,
|
||||||
id: IconID,
|
pub data: Vec<u8>,
|
||||||
#[get = "pub"]
|
|
||||||
data: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Icon {
|
impl Icon {
|
||||||
|
|||||||
@@ -8,26 +8,37 @@ use nkode_protocol::server::repository::in_memory::in_memory_opaque_session::InM
|
|||||||
use nkode_protocol::server::repository::in_memory::in_memory_transport::{InMemoryCodeServer, InMemoryKeyServer, InMemoryServerTransport};
|
use nkode_protocol::server::repository::in_memory::in_memory_transport::{InMemoryCodeServer, InMemoryKeyServer, InMemoryServerTransport};
|
||||||
use nkode_protocol::server::repository::in_memory::in_memory_user_db::InMemoryUserDB;
|
use nkode_protocol::server::repository::in_memory::in_memory_user_db::InMemoryUserDB;
|
||||||
use nkode_protocol::shared::email::Email;
|
use nkode_protocol::shared::email::Email;
|
||||||
use nkode_protocol::shared::models::app::IconID;
|
use nkode_protocol::shared::models::app::{Icon, IconID, ICON_ID_SIZE};
|
||||||
use nkode_protocol::shared::opaque::{NKodeServerSetup, UserSecretKey};
|
use nkode_protocol::shared::opaque::{NKodeServerSetup, UserSecretKey};
|
||||||
|
use nkode_protocol::shared::user_api::IconPoolAPI;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn in_memory_client_app() {
|
async fn in_memory_client_app() {
|
||||||
|
|
||||||
let mut rng = OsRng;
|
let mut rng = OsRng;
|
||||||
let server_setup = NKodeServerSetup::new(&mut rng);
|
let server_setup = NKodeServerSetup::new(&mut rng);
|
||||||
|
let user_db = InMemoryUserDB::new();
|
||||||
|
let n: usize = 200;
|
||||||
|
let mut new_icons: Vec<Icon> = Vec::with_capacity(n);
|
||||||
|
for i in 0u8..(n as u8) {
|
||||||
|
let id = IconID([i; ICON_ID_SIZE]); // [0; 32], [1; 32], ... [199; 32]
|
||||||
|
new_icons.push(Icon {
|
||||||
|
id,
|
||||||
|
data: vec![i], // dummy payload; adjust as needed
|
||||||
|
});
|
||||||
|
}
|
||||||
|
user_db.add_icons(new_icons).await.unwrap();
|
||||||
let server = ServerApp::new(
|
let server = ServerApp::new(
|
||||||
server_setup,
|
server_setup,
|
||||||
InMemoryOpaqueDB::new(),
|
InMemoryOpaqueDB::new(),
|
||||||
InMemoryOpaqueSession::new(),
|
InMemoryOpaqueSession::new(),
|
||||||
InMemoryUserDB::new()
|
user_db,
|
||||||
);
|
);
|
||||||
let key_transport: InMemoryKeyServer = InMemoryServerTransport::new(&server);
|
let key_transport: InMemoryKeyServer = InMemoryServerTransport::new(&server);
|
||||||
let code_transport: InMemoryCodeServer = InMemoryServerTransport::new(&server);
|
let code_transport: InMemoryCodeServer = InMemoryServerTransport::new(&server);
|
||||||
let user_db = InMemoryUserDB::new();
|
let client_auth = ClientAuth::new(&key_transport, &code_transport, &server.user_db);
|
||||||
let client_auth = ClientAuth::new(&key_transport, &code_transport, user_db);
|
|
||||||
let client_repo = InMemoryClientRepo::new();
|
let client_repo = InMemoryClientRepo::new();
|
||||||
let client_app_new_user: ClientApp<
|
let new_user: ClientApp<
|
||||||
|
'_,
|
||||||
'_,
|
'_,
|
||||||
'_,
|
'_,
|
||||||
NewUserRegisterKey,
|
NewUserRegisterKey,
|
||||||
@@ -38,12 +49,15 @@ async fn in_memory_client_app() {
|
|||||||
> = ClientApp::new(client_auth, client_repo);
|
> = ClientApp::new(client_auth, client_repo);
|
||||||
let user_email = Email::new("a@b.com").unwrap();
|
let user_email = Email::new("a@b.com").unwrap();
|
||||||
let user_secret_key = UserSecretKey::new();
|
let user_secret_key = UserSecretKey::new();
|
||||||
let client_app_register_code = client_app_new_user.new_user(user_email, user_secret_key).await.unwrap();
|
let register_code = new_user.new_user(user_email, user_secret_key).await.unwrap();
|
||||||
let _: Vec<IconID> = client_app_register_code
|
let icons: Vec<Icon> = register_code.get_new_user_icons().await.unwrap();
|
||||||
.get_new_user_icons().await.unwrap()
|
let icon_ids:Vec<IconID> = icons.iter().map(|el| el.id.clone()).collect();
|
||||||
.iter()
|
let selected_icons = icon_ids[0..4].to_vec();
|
||||||
.map(
|
let code_login = register_code.new_user_register_code(selected_icons.clone()).await.unwrap();
|
||||||
|el| el.id().clone()
|
let display_keypad = code_login.get_keypad().unwrap();
|
||||||
).collect();
|
let icon_idxs: Vec<usize> = selected_icons.iter().map(|x| {
|
||||||
// let client_app_user_login = client_app_register_code.new_user_register_code(icons[0..4].to_vec()).await.unwrap();
|
display_keypad.sorted_icons.iter().position(|x1| {x1.id == *x}).unwrap()
|
||||||
|
}).collect();
|
||||||
|
let selected_keys = display_keypad.keypad.select_keys(&icon_idxs).unwrap();
|
||||||
|
code_login.login(&selected_keys).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user