[fix] VerNum
This commit is contained in:
parent
68cedff1d9
commit
0827882bb3
30 changed files with 1651 additions and 240 deletions
|
|
@ -3,14 +3,20 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||
|
||||
use iota_cli::screens::terms_checker::{TermsCheckerScreen, UserChoice};
|
||||
use iota_cli::ui::UI;
|
||||
use iota_terms::{Doc, TermsType as Type, get_current_docs};
|
||||
use iota_terms::{Doc, LegalDocument, TermsType as Type, get_current_docs};
|
||||
use iota_util::file_util::{load_file, save_file};
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
pub async fn check(ui: Arc<UI>) -> Result<(bool, bool), String> {
|
||||
pub struct ConsentCheck {
|
||||
pub accepted_eula: bool,
|
||||
pub accepted_services: bool,
|
||||
pub documents: [LegalDocument; 3],
|
||||
}
|
||||
|
||||
pub async fn check(ui: Arc<UI>) -> Result<ConsentCheck, String> {
|
||||
let mut state = ConsentState::load_state();
|
||||
|
||||
ensure_initial_consent(ui.clone(), &mut state).await?;
|
||||
let documents = ensure_initial_consent(ui.clone(), &mut state).await?;
|
||||
/*
|
||||
* The raw legal endpoint exposes only the current document. Restore this
|
||||
* flow when it provides future versions that users can accept early.
|
||||
|
|
@ -20,7 +26,11 @@ pub async fn check(ui: Arc<UI>) -> Result<(bool, bool), String> {
|
|||
state = state.sanitize();
|
||||
state.save_state();
|
||||
|
||||
Ok((state.accepted_eula, state.accepted_tos && state.accepted_pp))
|
||||
Ok(ConsentCheck {
|
||||
accepted_eula: state.accepted_eula,
|
||||
accepted_services: state.accepted_tos && state.accepted_pp,
|
||||
documents,
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
|
@ -38,38 +48,54 @@ pub fn non_interactive_consent() -> NonInteractiveConsent {
|
|||
}
|
||||
}
|
||||
|
||||
async fn ensure_initial_consent(ui: Arc<UI>, state: &mut ConsentState) -> Result<(), String> {
|
||||
if state.accepted_eula && state.accepted_tos && state.accepted_pp {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
async fn ensure_initial_consent(
|
||||
ui: Arc<UI>,
|
||||
state: &mut ConsentState,
|
||||
) -> Result<[LegalDocument; 3], String> {
|
||||
let (current_eula, current_tos, current_privacy) = get_current_docs().await.ok_or_else(|| {
|
||||
"Could not connect to the legal endpoint to fetch the current agreements. Please check your internet connection.".to_string()
|
||||
})?;
|
||||
|
||||
let current_eula_doc = current_eula.metadata();
|
||||
let current_tos_doc = current_tos.metadata();
|
||||
let current_privacy_doc = current_privacy.metadata();
|
||||
let documents = [current_eula, current_tos, current_privacy];
|
||||
|
||||
if state.accepts_current_docs(¤t_eula_doc, ¤t_tos_doc, ¤t_privacy_doc) {
|
||||
return Ok(documents);
|
||||
}
|
||||
|
||||
// A legacy consent file records the document hashes alongside its flags.
|
||||
// Do not carry a flag forward to the durable consent record when its
|
||||
// document has changed; the user must review and accept that revision.
|
||||
state.invalidate_mismatched_consent(¤t_eula_doc, ¤t_tos_doc, ¤t_privacy_doc);
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
ui.set_screen(Box::new(TermsCheckerScreen::new(Some(tx))))
|
||||
.await;
|
||||
ui.set_screen(Box::new(TermsCheckerScreen::new(
|
||||
Some(tx),
|
||||
documents.clone(),
|
||||
)))
|
||||
.await;
|
||||
|
||||
let result = rx.await.unwrap_or(UserChoice::Deny);
|
||||
|
||||
match result {
|
||||
UserChoice::AcceptEULA | UserChoice::AcceptAll => {
|
||||
state.accepted_eula = true;
|
||||
state.eula = Some(current_eula);
|
||||
state.eula = Some(current_eula_doc);
|
||||
|
||||
if matches!(result, UserChoice::AcceptAll) {
|
||||
state.accepted_tos = true;
|
||||
state.accepted_pp = true;
|
||||
state.tos = Some(current_tos);
|
||||
state.privacy = Some(current_privacy);
|
||||
state.tos = Some(current_tos_doc);
|
||||
state.privacy = Some(current_privacy_doc);
|
||||
}
|
||||
|
||||
let _ = &state.save_state();
|
||||
Ok(())
|
||||
Ok(documents)
|
||||
}
|
||||
UserChoice::Deny => Ok(()),
|
||||
UserChoice::Deny => Ok(documents),
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
|
@ -245,6 +271,22 @@ pub struct ConsentState {
|
|||
}
|
||||
|
||||
impl ConsentState {
|
||||
fn accepts_current_docs(&self, eula: &Doc, tos: &Doc, privacy: &Doc) -> bool {
|
||||
self.accepted_eula
|
||||
&& self.accepted_tos
|
||||
&& self.accepted_pp
|
||||
&& eula.equals_some(&self.eula)
|
||||
&& tos.equals_some(&self.tos)
|
||||
&& privacy.equals_some(&self.privacy)
|
||||
}
|
||||
|
||||
fn invalidate_mismatched_consent(&mut self, eula: &Doc, tos: &Doc, privacy: &Doc) {
|
||||
self.accepted_eula &= eula.equals_some(&self.eula);
|
||||
self.accepted_tos &= tos.equals_some(&self.tos);
|
||||
self.accepted_pp &= privacy.equals_some(&self.privacy);
|
||||
*self = self.clone().sanitize();
|
||||
}
|
||||
|
||||
fn sanitize(mut self) -> Self {
|
||||
let current_secs = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
|
|
@ -488,3 +530,60 @@ impl ConsentState {
|
|||
state
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ConsentState;
|
||||
use iota_terms::{Doc, TermsType as Type};
|
||||
|
||||
fn doc(doc_type: Type, hash: &str) -> Doc {
|
||||
Doc::new("1".to_owned(), hash.to_owned(), doc_type, 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_current_docs_requires_each_accepted_hash_to_match() {
|
||||
let eula = doc(Type::EULA, "eula-hash");
|
||||
let tos = doc(Type::TOS, "tos-hash");
|
||||
let privacy = doc(Type::PP, "privacy-hash");
|
||||
let state = ConsentState {
|
||||
eula: Some(eula.clone()),
|
||||
accepted_eula: true,
|
||||
future_eula: None,
|
||||
tos: Some(tos.clone()),
|
||||
accepted_tos: true,
|
||||
future_tos: None,
|
||||
privacy: Some(privacy.clone()),
|
||||
accepted_pp: true,
|
||||
future_privacy: None,
|
||||
};
|
||||
|
||||
assert!(state.accepts_current_docs(&eula, &tos, &privacy));
|
||||
assert!(!state.accepts_current_docs(&doc(Type::EULA, "new-eula-hash"), &tos, &privacy));
|
||||
assert!(!state.accepts_current_docs(&eula, &doc(Type::TOS, "new-tos-hash"), &privacy));
|
||||
assert!(!state.accepts_current_docs(&eula, &tos, &doc(Type::PP, "new-privacy-hash")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalidating_a_mismatched_eula_revokes_dependent_consent() {
|
||||
let eula = doc(Type::EULA, "old-eula-hash");
|
||||
let tos = doc(Type::TOS, "tos-hash");
|
||||
let privacy = doc(Type::PP, "privacy-hash");
|
||||
let mut state = ConsentState {
|
||||
eula: Some(eula),
|
||||
accepted_eula: true,
|
||||
future_eula: None,
|
||||
tos: Some(tos.clone()),
|
||||
accepted_tos: true,
|
||||
future_tos: None,
|
||||
privacy: Some(privacy.clone()),
|
||||
accepted_pp: true,
|
||||
future_privacy: None,
|
||||
};
|
||||
|
||||
state.invalidate_mismatched_consent(&doc(Type::EULA, "new-eula-hash"), &tos, &privacy);
|
||||
|
||||
assert!(!state.accepted_eula);
|
||||
assert!(!state.accepted_tos);
|
||||
assert!(!state.accepted_pp);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ async fn main() {
|
|||
let session = start_tui(ipc).expect("interactive terminal initialization failed");
|
||||
let ui = session.ui();
|
||||
|
||||
let (eula, tos_pp) = match consent_state::check(ui.clone()).await {
|
||||
let consent = match consent_state::check(ui.clone()).await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
*state.shutdown.write().await = true;
|
||||
|
|
@ -53,7 +53,7 @@ async fn main() {
|
|||
}
|
||||
};
|
||||
|
||||
if !eula {
|
||||
if !consent.accepted_eula {
|
||||
*state.shutdown.write().await = true;
|
||||
loop {
|
||||
if state.active_tasks.is_empty() {
|
||||
|
|
@ -65,7 +65,7 @@ async fn main() {
|
|||
println!("You can find this at 'agreements'!");
|
||||
return;
|
||||
}
|
||||
if !tos_pp {
|
||||
if !consent.accepted_services {
|
||||
*state.shutdown.write().await = true;
|
||||
loop {
|
||||
if state.active_tasks.is_empty() {
|
||||
|
|
@ -102,6 +102,10 @@ async fn main() {
|
|||
}
|
||||
|
||||
// USER MANAGEMENT
|
||||
if let Err(error) = iota_storage::util::db::initialize_database() {
|
||||
log!("Failed to initialize user storage: {}", error);
|
||||
return;
|
||||
}
|
||||
if let Err(_) = user_manager::load_users_sync() {
|
||||
log_t!("user_load_failed");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue