Fix Clippy warnings blocking release checks
Some checks failed
Validate authentication / Validate authentication (push) Failing after 1s
Some checks failed
Validate authentication / Validate authentication (push) Failing after 1s
This commit is contained in:
parent
e71d9c3118
commit
976ffde7a8
42 changed files with 315 additions and 346 deletions
|
|
@ -20,6 +20,8 @@ use uuid::Uuid;
|
||||||
// Waiting Task System
|
// Waiting Task System
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
type WaitingTask = Box<dyn Fn(Arc<ClientConnection>, CommunicationValue) -> bool + Send + Sync>;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub struct ClientConnection {
|
pub struct ClientConnection {
|
||||||
sender: Arc<RwLock<Option<Arc<Sender>>>>,
|
sender: Arc<RwLock<Option<Arc<Sender>>>>,
|
||||||
|
|
@ -27,8 +29,7 @@ pub struct ClientConnection {
|
||||||
connection_loop_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
connection_loop_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
||||||
pub connection_id: Uuid,
|
pub connection_id: Uuid,
|
||||||
shutdown_tx: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
shutdown_tx: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
||||||
pub waiting_tasks:
|
pub waiting_tasks: DashMap<u32, WaitingTask>,
|
||||||
DashMap<u32, Box<dyn Fn(Arc<ClientConnection>, CommunicationValue) -> bool + Send + Sync>>,
|
|
||||||
shutdown: Arc<RwLock<bool>>,
|
shutdown: Arc<RwLock<bool>>,
|
||||||
keyring: Arc<RwLock<Option<Arc<Keyring>>>>,
|
keyring: Arc<RwLock<Option<Arc<Keyring>>>>,
|
||||||
}
|
}
|
||||||
|
|
@ -40,10 +41,7 @@ impl ClientConnection {
|
||||||
connection_loop_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
connection_loop_handle: Arc<Mutex<Option<JoinHandle<()>>>>,
|
||||||
connection_id: Uuid,
|
connection_id: Uuid,
|
||||||
shutdown_tx: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
shutdown_tx: Arc<Mutex<Option<watch::Sender<bool>>>>,
|
||||||
waiting_tasks: DashMap<
|
waiting_tasks: DashMap<u32, WaitingTask>,
|
||||||
u32,
|
|
||||||
Box<dyn Fn(Arc<ClientConnection>, CommunicationValue) -> bool + Send + Sync>,
|
|
||||||
>,
|
|
||||||
shutdown: Arc<RwLock<bool>>,
|
shutdown: Arc<RwLock<bool>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
@ -357,7 +355,6 @@ impl ClientConnection {
|
||||||
.add_typed_default(DataType::Settings, DataValue::Array(settings_json));
|
.add_typed_default(DataType::Settings, DataValue::Array(settings_json));
|
||||||
|
|
||||||
self.send_message(&response).await;
|
self.send_message(&response).await;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +371,7 @@ impl ClientConnection {
|
||||||
|
|
||||||
if let Some(solved) = solved {
|
if let Some(solved) = solved {
|
||||||
let response = CommunicationValue::new(CommunicationType::ChallengeResponse)
|
let response = CommunicationValue::new(CommunicationType::ChallengeResponse)
|
||||||
.with_request_id(&cv)
|
.with_request_id(cv)
|
||||||
.add_typed_default(DataType::Challenge, DataValue::Str(solved));
|
.add_typed_default(DataType::Challenge, DataValue::Str(solved));
|
||||||
|
|
||||||
self.send_message(&response).await;
|
self.send_message(&response).await;
|
||||||
|
|
|
||||||
|
|
@ -488,13 +488,12 @@ impl InteractableElement for ConsoleCard {
|
||||||
if !key
|
if !key
|
||||||
.modifiers
|
.modifiers
|
||||||
.intersects(KeyModifiers::CONTROL | KeyModifiers::ALT)
|
.intersects(KeyModifiers::CONTROL | KeyModifiers::ALT)
|
||||||
|
&& let Some(c) = key.code.as_char()
|
||||||
{
|
{
|
||||||
if let Some(c) = key.code.as_char() {
|
|
||||||
self.insert_at_cursor(c);
|
self.insert_at_cursor(c);
|
||||||
self.message = None;
|
self.message = None;
|
||||||
return IotaInteraction::Changed;
|
return IotaInteraction::Changed;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
IotaInteraction::Unhandled
|
IotaInteraction::Unhandled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,7 @@ impl JoinableElement for LogCard {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_element(&self) -> &(dyn Element + 'static) {
|
fn as_element(&self) -> &(dyn Element + 'static) {
|
||||||
&*self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_element_mut(&mut self) -> &mut (dyn Element + 'static) {
|
fn as_element_mut(&mut self) -> &mut (dyn Element + 'static) {
|
||||||
|
|
@ -461,7 +461,7 @@ impl InteractableElement for LogCard {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_element(&self) -> &(dyn Element + 'static) {
|
fn as_element(&self) -> &(dyn Element + 'static) {
|
||||||
&*self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_element_mut(&mut self) -> &mut (dyn Element + 'static) {
|
fn as_element_mut(&mut self) -> &mut (dyn Element + 'static) {
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,12 @@ impl HelpOverlay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for HelpOverlay {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IotaScreen for HelpOverlay {
|
impl IotaScreen for HelpOverlay {
|
||||||
fn render_legacy(&self, f: &mut Frame, rect: Rect, theme: &ResolvedTheme, _hits: &mut HitMap) {
|
fn render_legacy(&self, f: &mut Frame, rect: Rect, theme: &ResolvedTheme, _hits: &mut HitMap) {
|
||||||
let area = ratatool::layout::centered_rect(
|
let area = ratatool::layout::centered_rect(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
#![allow(
|
||||||
|
clippy::module_inception,
|
||||||
|
reason = "preserve existing public module paths"
|
||||||
|
)]
|
||||||
|
|
||||||
pub mod elements {
|
pub mod elements {
|
||||||
pub mod console_card;
|
pub mod console_card;
|
||||||
pub mod elements;
|
pub mod elements;
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ fn table_to_lines(table: Vec<Vec<String>>, theme: &ResolvedTheme) -> Vec<Display
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(h_len)
|
.unwrap_or(h_len)
|
||||||
} else {
|
} else {
|
||||||
let max = (3 * h_len) as usize;
|
let max = 3 * h_len;
|
||||||
max.max(h_len)
|
max.max(h_len)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ impl IotaScreen for TermsCheckerScreen {
|
||||||
}
|
}
|
||||||
|
|
||||||
while size.height - 5 < text_lines.len() as u16 {
|
while size.height - 5 < text_lines.len() as u16 {
|
||||||
if optional_lines.len() == 0 {
|
if optional_lines.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
text_lines.remove(optional_lines[0] as usize);
|
text_lines.remove(optional_lines[0] as usize);
|
||||||
|
|
@ -232,7 +232,7 @@ impl IotaScreen for TermsCheckerScreen {
|
||||||
Line::from(vec![
|
Line::from(vec![
|
||||||
Span::raw("Height: "),
|
Span::raw("Height: "),
|
||||||
Span::styled(format!("{}", size.height), height_style),
|
Span::styled(format!("{}", size.height), height_style),
|
||||||
Span::raw(format!(" / 13")),
|
Span::raw(" / 13".to_string()),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -241,7 +241,7 @@ impl IotaScreen for TermsCheckerScreen {
|
||||||
.block(
|
.block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title(format!("UI Too Small [Q to Quit]")),
|
.title("UI Too Small [Q to Quit]".to_string()),
|
||||||
);
|
);
|
||||||
f.render_widget(warning, size);
|
f.render_widget(warning, size);
|
||||||
return;
|
return;
|
||||||
|
|
@ -249,7 +249,7 @@ impl IotaScreen for TermsCheckerScreen {
|
||||||
|
|
||||||
let consent_block = Paragraph::new(Text::from(text_lines)).block(
|
let consent_block = Paragraph::new(Text::from(text_lines)).block(
|
||||||
Block::default()
|
Block::default()
|
||||||
.title(format!(" Tensamin User Consent [Q to Quit] ",))
|
.title(" Tensamin User Consent [Q to Quit] ".to_string())
|
||||||
.borders(Borders::ALL),
|
.borders(Borders::ALL),
|
||||||
);
|
);
|
||||||
f.render_widget(consent_block, chunks[0]);
|
f.render_widget(consent_block, chunks[0]);
|
||||||
|
|
|
||||||
|
|
@ -513,7 +513,7 @@ impl IotaScreen for TermsUpdaterScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
while size.height - 5 < text_lines.len() as u16 {
|
while size.height - 5 < text_lines.len() as u16 {
|
||||||
if optional_lines.len() == 0 {
|
if optional_lines.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
text_lines.remove(optional_lines[0] as usize);
|
text_lines.remove(optional_lines[0] as usize);
|
||||||
|
|
@ -632,7 +632,7 @@ impl IotaScreen for TermsUpdaterScreen {
|
||||||
if let Some(sender) = self.sender.take() {
|
if let Some(sender) = self.sender.take() {
|
||||||
let _ = sender.send(UserChoice::Deny);
|
let _ = sender.send(UserChoice::Deny);
|
||||||
}
|
}
|
||||||
return IotaInteraction::Pop;
|
IotaInteraction::Pop
|
||||||
}
|
}
|
||||||
KeyCode::Enter | KeyCode::Char(' ') => match self.focus {
|
KeyCode::Enter | KeyCode::Char(' ') => match self.focus {
|
||||||
Focus::Eula => {
|
Focus::Eula => {
|
||||||
|
|
@ -678,9 +678,7 @@ impl IotaScreen for TermsUpdaterScreen {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(terms_type) = terms_type {
|
if let Some(terms_type) = terms_type {
|
||||||
return IotaInteraction::Effect(IotaEffect::LoadNewestTerms {
|
IotaInteraction::Effect(IotaEffect::LoadNewestTerms { kind: terms_type })
|
||||||
kind: terms_type,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
IotaInteraction::Unhandled
|
IotaInteraction::Unhandled
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -698,7 +698,7 @@ impl IotaScreen for UsersScreen {
|
||||||
}
|
}
|
||||||
Err(error) => self.message = Some(error),
|
Err(error) => self.message = Some(error),
|
||||||
}
|
}
|
||||||
return IotaInteraction::Changed;
|
IotaInteraction::Changed
|
||||||
}
|
}
|
||||||
UiEvent::Message(IotaMessage::Event(AppEvent::UserOperationFinished(result))) => {
|
UiEvent::Message(IotaMessage::Event(AppEvent::UserOperationFinished(result))) => {
|
||||||
self.pending = false;
|
self.pending = false;
|
||||||
|
|
@ -706,7 +706,7 @@ impl IotaScreen for UsersScreen {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(error) => error,
|
Err(error) => error,
|
||||||
});
|
});
|
||||||
return self.refresh();
|
self.refresh()
|
||||||
}
|
}
|
||||||
UiEvent::Message(IotaMessage::Event(AppEvent::CredentialExportFinished(result))) => {
|
UiEvent::Message(IotaMessage::Event(AppEvent::CredentialExportFinished(result))) => {
|
||||||
self.pending = false;
|
self.pending = false;
|
||||||
|
|
@ -714,7 +714,7 @@ impl IotaScreen for UsersScreen {
|
||||||
Ok(message) => message,
|
Ok(message) => message,
|
||||||
Err(error) => error,
|
Err(error) => error,
|
||||||
});
|
});
|
||||||
return IotaInteraction::Changed;
|
IotaInteraction::Changed
|
||||||
}
|
}
|
||||||
UiEvent::Message(IotaMessage::Event(AppEvent::TuInspected(result))) => {
|
UiEvent::Message(IotaMessage::Event(AppEvent::TuInspected(result))) => {
|
||||||
if let Some(UsersOverlay::Add(flow)) = self.overlay.as_mut() {
|
if let Some(UsersOverlay::Add(flow)) = self.overlay.as_mut() {
|
||||||
|
|
@ -727,7 +727,7 @@ impl IotaScreen for UsersScreen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return IotaInteraction::Changed;
|
IotaInteraction::Changed
|
||||||
}
|
}
|
||||||
UiEvent::Paste(text) => {
|
UiEvent::Paste(text) => {
|
||||||
if let Some(UsersOverlay::Add(flow)) = self.overlay.as_mut() {
|
if let Some(UsersOverlay::Add(flow)) = self.overlay.as_mut() {
|
||||||
|
|
@ -753,7 +753,7 @@ impl IotaScreen for UsersScreen {
|
||||||
self.restore_selection();
|
self.restore_selection();
|
||||||
return IotaInteraction::Changed;
|
return IotaInteraction::Changed;
|
||||||
}
|
}
|
||||||
return IotaInteraction::Unhandled;
|
IotaInteraction::Unhandled
|
||||||
}
|
}
|
||||||
UiEvent::Key(key) => {
|
UiEvent::Key(key) => {
|
||||||
if let Some(overlay) = &mut self.overlay {
|
if let Some(overlay) = &mut self.overlay {
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ impl UiConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load() -> Result<Self, io::Error> {
|
pub fn load() -> Result<Self, io::Error> {
|
||||||
let path = match (|| std::panic::catch_unwind(|| Self::path()))() {
|
let path = match std::panic::catch_unwind(Self::path) {
|
||||||
Ok(path) => path,
|
Ok(path) => path,
|
||||||
Err(_) => Self::fallback_path().ok_or_else(|| {
|
Err(_) => Self::fallback_path().ok_or_else(|| {
|
||||||
io::Error::new(io::ErrorKind::NotFound, "could not determine config path")
|
io::Error::new(io::ErrorKind::NotFound, "could not determine config path")
|
||||||
|
|
|
||||||
|
|
@ -129,14 +129,12 @@ pub fn resolve_with_capabilities(
|
||||||
};
|
};
|
||||||
theme.name = name;
|
theme.name = name;
|
||||||
theme.unicode = unicode_enabled;
|
theme.unicode = unicode_enabled;
|
||||||
if !unicode_enabled {
|
if !unicode_enabled && matches!(theme.console.cursor, CursorPresentation::Character { .. }) {
|
||||||
if matches!(theme.console.cursor, CursorPresentation::Character { .. }) {
|
|
||||||
theme.console.cursor = CursorPresentation::Character {
|
theme.console.cursor = CursorPresentation::Character {
|
||||||
glyph: "|",
|
glyph: "|",
|
||||||
style: theme.console.text,
|
style: theme.console.text,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
theme
|
theme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ fn choice(
|
||||||
suffix,
|
suffix,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[expect(clippy::too_many_arguments, reason = "explicit theme styles")]
|
||||||
fn base(
|
fn base(
|
||||||
name: ThemeName,
|
name: ThemeName,
|
||||||
normal: Style,
|
normal: Style,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ use crate::{
|
||||||
util::terms_focus::Focus,
|
util::terms_focus::Focus,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[expect(
|
||||||
|
clippy::too_many_arguments,
|
||||||
|
reason = "explicit button layout and styling"
|
||||||
|
)]
|
||||||
pub fn draw_buttons(
|
pub fn draw_buttons(
|
||||||
frame: &mut ratatui::Frame,
|
frame: &mut ratatui::Frame,
|
||||||
area: Rect,
|
area: Rect,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
#![allow(
|
||||||
|
clippy::result_large_err,
|
||||||
|
reason = "return protocol error frames directly to the sender"
|
||||||
|
)]
|
||||||
|
|
||||||
use crate::message_common::*;
|
use crate::message_common::*;
|
||||||
use iota_logger::{LogLevel, PrintType, log_event};
|
use iota_logger::{LogLevel, PrintType, log_event};
|
||||||
use iota_storage::util::call_envelopes::{self, CallEnvelope};
|
use iota_storage::util::call_envelopes::{self, CallEnvelope};
|
||||||
|
|
@ -1582,10 +1587,8 @@ pub fn handle_global_settings_save(cv: &CommunicationValue) -> CommunicationValu
|
||||||
.with_request_id(cv);
|
.with_request_id(cv);
|
||||||
|
|
||||||
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
||||||
response = response.add_typed_default(
|
response =
|
||||||
DataType::SessionId,
|
response.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
|
|
@ -1612,10 +1615,8 @@ pub fn handle_global_settings_load(cv: &CommunicationValue) -> CommunicationValu
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
||||||
response = response.add_typed_default(
|
response = response
|
||||||
DataType::SessionId,
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
@ -1627,10 +1628,8 @@ pub fn handle_global_settings_load(cv: &CommunicationValue) -> CommunicationValu
|
||||||
.add_typed_default(DataType::Payload, DataValue::Str(settings_value_str));
|
.add_typed_default(DataType::Payload, DataValue::Str(settings_value_str));
|
||||||
|
|
||||||
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
if let Some(session_id) = cv.get_data(DataType::SessionId).as_number() {
|
||||||
response = response.add_typed_default(
|
response =
|
||||||
DataType::SessionId,
|
response.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response
|
||||||
|
|
@ -1664,10 +1663,7 @@ pub fn handle_settings_save(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Invalid session_id".to_string()),
|
DataValue::Str("Invalid session_id".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
let Some(settings_name) = cv.get_data(DataType::SettingsName).as_str() else {
|
let Some(settings_name) = cv.get_data(DataType::SettingsName).as_str() else {
|
||||||
return CommunicationValue::new(CommunicationType::ErrorInvalidData)
|
return CommunicationValue::new(CommunicationType::ErrorInvalidData)
|
||||||
|
|
@ -1677,10 +1673,7 @@ pub fn handle_settings_save(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Missing settings_name".to_string()),
|
DataValue::Str("Missing settings_name".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
let Some(settings_value) = cv.get_data(DataType::Payload).as_str() else {
|
let Some(settings_value) = cv.get_data(DataType::Payload).as_str() else {
|
||||||
return CommunicationValue::new(CommunicationType::ErrorInvalidData)
|
return CommunicationValue::new(CommunicationType::ErrorInvalidData)
|
||||||
|
|
@ -1690,10 +1683,7 @@ pub fn handle_settings_save(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Missing settings payload".to_string()),
|
DataValue::Str("Missing settings payload".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !settings_name
|
if !settings_name
|
||||||
|
|
@ -1712,10 +1702,7 @@ pub fn handle_settings_save(
|
||||||
DataType::SettingsName,
|
DataType::SettingsName,
|
||||||
DataValue::Str(settings_name.to_string()),
|
DataValue::Str(settings_name.to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
||||||
return error_response(cv, CommunicationType::ErrorInvalidData);
|
return error_response(cv, CommunicationType::ErrorInvalidData);
|
||||||
|
|
@ -1732,10 +1719,7 @@ pub fn handle_settings_save(
|
||||||
DataType::SettingsName,
|
DataType::SettingsName,
|
||||||
DataValue::Str(settings_name.to_string()),
|
DataValue::Str(settings_name.to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id))
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_settings_load(
|
pub fn handle_settings_load(
|
||||||
|
|
@ -1766,10 +1750,7 @@ pub fn handle_settings_load(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Invalid session_id".to_string()),
|
DataValue::Str("Invalid session_id".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
||||||
return error_response(cv, CommunicationType::ErrorInvalidData);
|
return error_response(cv, CommunicationType::ErrorInvalidData);
|
||||||
|
|
@ -1782,10 +1763,7 @@ pub fn handle_settings_load(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Missing settings_name".to_string()),
|
DataValue::Str("Missing settings_name".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if !settings_name
|
if !settings_name
|
||||||
|
|
@ -1804,10 +1782,7 @@ pub fn handle_settings_load(
|
||||||
DataType::SettingsName,
|
DataType::SettingsName,
|
||||||
DataValue::Str(settings_name.to_string()),
|
DataValue::Str(settings_name.to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let Ok(settings_value) = settings::load(my_id_i64, session_id_i64, settings_name) else {
|
let Ok(settings_value) = settings::load(my_id_i64, session_id_i64, settings_name) else {
|
||||||
|
|
@ -1821,10 +1796,7 @@ pub fn handle_settings_load(
|
||||||
DataType::SettingsName,
|
DataType::SettingsName,
|
||||||
DataValue::Str(settings_name.to_string()),
|
DataValue::Str(settings_name.to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CommunicationValue::new(CommunicationType::SettingsLoad)
|
CommunicationValue::new(CommunicationType::SettingsLoad)
|
||||||
|
|
@ -1835,10 +1807,7 @@ pub fn handle_settings_load(
|
||||||
DataType::SettingsName,
|
DataType::SettingsName,
|
||||||
DataValue::Str(settings_name.to_string()),
|
DataValue::Str(settings_name.to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id))
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_settings_list(
|
pub fn handle_settings_list(
|
||||||
|
|
@ -1869,10 +1838,7 @@ pub fn handle_settings_list(
|
||||||
DataType::Message,
|
DataType::Message,
|
||||||
DataValue::Str("Invalid session_id".to_string()),
|
DataValue::Str("Invalid session_id".to_string()),
|
||||||
)
|
)
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id));
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
let Ok(session_id_i64) = i64::try_from(session_id) else {
|
||||||
return error_response(cv, CommunicationType::ErrorInvalidData);
|
return error_response(cv, CommunicationType::ErrorInvalidData);
|
||||||
|
|
@ -1886,10 +1852,7 @@ pub fn handle_settings_list(
|
||||||
.with_request_id(cv)
|
.with_request_id(cv)
|
||||||
.with_receiver(my_id)
|
.with_receiver(my_id)
|
||||||
.add_typed_default(DataType::Settings, DataValue::Array(settings_json))
|
.add_typed_default(DataType::Settings, DataValue::Array(settings_json))
|
||||||
.add_typed_default(
|
.add_typed_default(DataType::SessionId, DataValue::SignedNumber(session_id))
|
||||||
DataType::SessionId,
|
|
||||||
DataValue::SignedNumber(session_id as i128),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setting_response(
|
fn setting_response(
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ async fn get_updates() -> Option<(
|
||||||
{
|
{
|
||||||
let file = load_file("", "agreements");
|
let file = load_file("", "agreements");
|
||||||
let accepted_state = ConsentState::from_str(&file).sanitize();
|
let accepted_state = ConsentState::from_str(&file).sanitize();
|
||||||
save_file("", "agreements", &accepted_state.to_string());
|
save_file("", "agreements", &accepted_state.serialize());
|
||||||
|
|
||||||
let eula_update: UpdateDecision = if current_eula.equals_some(&accepted_state.eula) {
|
let eula_update: UpdateDecision = if current_eula.equals_some(&accepted_state.eula) {
|
||||||
if current_eula.equals(&newest_eula) {
|
if current_eula.equals(&newest_eula) {
|
||||||
|
|
@ -293,24 +293,24 @@ impl ConsentState {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_secs();
|
.as_secs();
|
||||||
|
|
||||||
if let Some(future_eula) = self.future_eula.clone() {
|
if let Some(future_eula) = self.future_eula.clone()
|
||||||
if future_eula.get_time() < current_secs {
|
&& future_eula.get_time() < current_secs
|
||||||
|
{
|
||||||
self.eula = Some(future_eula);
|
self.eula = Some(future_eula);
|
||||||
self.future_eula = None;
|
self.future_eula = None;
|
||||||
}
|
}
|
||||||
}
|
if let Some(future_tos) = self.future_tos.clone()
|
||||||
if let Some(future_tos) = self.future_tos.clone() {
|
&& future_tos.get_time() < current_secs
|
||||||
if future_tos.get_time() < current_secs {
|
{
|
||||||
self.tos = Some(future_tos);
|
self.tos = Some(future_tos);
|
||||||
self.future_tos = None;
|
self.future_tos = None;
|
||||||
}
|
}
|
||||||
}
|
if let Some(future_privacy) = self.future_privacy.clone()
|
||||||
if let Some(future_privacy) = self.future_privacy.clone() {
|
&& future_privacy.get_time() < current_secs
|
||||||
if future_privacy.get_time() < current_secs {
|
{
|
||||||
self.privacy = Some(future_privacy);
|
self.privacy = Some(future_privacy);
|
||||||
self.future_privacy = None;
|
self.future_privacy = None;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if !self.accepted_eula {
|
if !self.accepted_eula {
|
||||||
self.accepted_tos = false;
|
self.accepted_tos = false;
|
||||||
|
|
@ -325,10 +325,10 @@ impl ConsentState {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_state(&self) {
|
pub fn save_state(&self) {
|
||||||
save_file("", "agreements", &self.to_string());
|
save_file("", "agreements", &self.serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string(&self) -> String {
|
fn serialize(&self) -> String {
|
||||||
let current_secs = SystemTime::now()
|
let current_secs = SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -487,7 +487,8 @@ impl ConsentState {
|
||||||
let future_eula_time = future_eula_time.parse::<u64>().unwrap_or(0);
|
let future_eula_time = future_eula_time.parse::<u64>().unwrap_or(0);
|
||||||
let future_tos_time = future_tos_time.parse::<u64>().unwrap_or(0);
|
let future_tos_time = future_tos_time.parse::<u64>().unwrap_or(0);
|
||||||
let future_pp_time = future_pp_time.parse::<u64>().unwrap_or(0);
|
let future_pp_time = future_pp_time.parse::<u64>().unwrap_or(0);
|
||||||
let state = Self {
|
|
||||||
|
Self {
|
||||||
accepted_eula: eula,
|
accepted_eula: eula,
|
||||||
eula: Some(Doc::new(eula_version, eula_hash, Type::EULA, unix)),
|
eula: Some(Doc::new(eula_version, eula_hash, Type::EULA, unix)),
|
||||||
accepted_pp: pp,
|
accepted_pp: pp,
|
||||||
|
|
@ -525,9 +526,7 @@ impl ConsentState {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.sanitize();
|
.sanitize()
|
||||||
|
|
||||||
state
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ struct ClientSubscription {
|
||||||
metric_interval_ms: u64,
|
metric_interval_ms: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::large_enum_variant, reason = "keep queued IPC messages inline")]
|
||||||
enum WriterCommand {
|
enum WriterCommand {
|
||||||
Message(DaemonMessage),
|
Message(DaemonMessage),
|
||||||
Flush {
|
Flush {
|
||||||
|
|
@ -94,6 +95,7 @@ impl IpcServer {
|
||||||
.join("daemon.lock");
|
.join("daemon.lock");
|
||||||
let lock = File::options()
|
let lock = File::options()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
.truncate(false)
|
||||||
.mode(0o600)
|
.mode(0o600)
|
||||||
.read(true)
|
.read(true)
|
||||||
.write(true)
|
.write(true)
|
||||||
|
|
@ -478,16 +480,14 @@ async fn handle_client(
|
||||||
Ok(DaemonMessage::LogEntry(entry)) => {
|
Ok(DaemonMessage::LogEntry(entry)) => {
|
||||||
// Filter by subscribed log classes
|
// Filter by subscribed log classes
|
||||||
let log_classes = sub_rx.borrow().log_classes.clone();
|
let log_classes = sub_rx.borrow().log_classes.clone();
|
||||||
if log_classes.is_empty()
|
if (log_classes.is_empty()
|
||||||
|| log_classes.iter().any(|c| entry.sender == *c)
|
|| log_classes.contains(&entry.sender))
|
||||||
{
|
&& let Err(error) = write_client_message(&mut writer, &DaemonMessage::LogEntry(entry)).await {
|
||||||
if let Err(error) = write_client_message(&mut writer, &DaemonMessage::LogEntry(entry)).await {
|
|
||||||
eprintln!("IPC client writer stopped while sending log message: {error}");
|
eprintln!("IPC client writer stopped while sending log message: {error}");
|
||||||
session_cancellation.cancel();
|
session_cancellation.cancel();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(DaemonMessage::MetricSample(sample)) => {
|
Ok(DaemonMessage::MetricSample(sample)) => {
|
||||||
// Rate-limit metric samples based on subscription interval
|
// Rate-limit metric samples based on subscription interval
|
||||||
let now = tokio::time::Instant::now();
|
let now = tokio::time::Instant::now();
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,11 @@ use std::time::Duration;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tokio::task::JoinSet;
|
use tokio::task::JoinSet;
|
||||||
|
|
||||||
|
type TaskOutcome = (String, Result<(), String>);
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct TaskRegistry {
|
pub struct TaskRegistry {
|
||||||
tasks: Arc<Mutex<JoinSet<(String, Result<(), String>)>>>,
|
tasks: Arc<Mutex<JoinSet<TaskOutcome>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskRegistry {
|
impl TaskRegistry {
|
||||||
|
|
|
||||||
|
|
@ -322,6 +322,10 @@ pub struct ResponseEnvelope {
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
|
||||||
|
#[expect(
|
||||||
|
clippy::large_enum_variant,
|
||||||
|
reason = "keep IPC response payloads inline"
|
||||||
|
)]
|
||||||
pub enum ResponseResult {
|
pub enum ResponseResult {
|
||||||
Ok(ResponsePayload),
|
Ok(ResponsePayload),
|
||||||
Error(IpcErrorCode),
|
Error(IpcErrorCode),
|
||||||
|
|
@ -724,9 +728,10 @@ pub enum ConnectionStatus {
|
||||||
Disconnected,
|
Disconnected,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum StartupPhase {
|
pub enum StartupPhase {
|
||||||
|
#[default]
|
||||||
Starting,
|
Starting,
|
||||||
MigratingStorage,
|
MigratingStorage,
|
||||||
LoadingUsers,
|
LoadingUsers,
|
||||||
|
|
@ -793,12 +798,6 @@ pub struct ComponentHealth {
|
||||||
pub changed_at_ms: u128,
|
pub changed_at_ms: u128,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for StartupPhase {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Starting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Shared types
|
// Shared types
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -189,11 +189,11 @@ pub fn startup_with_log_dir_and_capacity(log_dir: Option<PathBuf>, queue_capacit
|
||||||
format!("{prefix}{resolved_message}")
|
format!("{prefix}{resolved_message}")
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(file) = file.as_mut() {
|
if let Some(file) = file.as_mut()
|
||||||
if let Err(error) = writeln!(file, "{line}") {
|
&& let Err(error) = writeln!(file, "{line}")
|
||||||
|
{
|
||||||
eprintln!("Unable to write Iota log file: {error}");
|
eprintln!("Unable to write Iota log file: {error}");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let _ = writeln!(std::io::stderr(), "{timestamp} {line}");
|
let _ = writeln!(std::io::stderr(), "{timestamp} {line}");
|
||||||
|
|
||||||
|
|
@ -313,11 +313,11 @@ fn report_dropped_logs(
|
||||||
let line = format!(
|
let line = format!(
|
||||||
"{timestamp_ms} level=ERROR component=general direction=internal sender=- event=logger.dropped message={message:?}"
|
"{timestamp_ms} level=ERROR component=general direction=internal sender=- event=logger.dropped message={message:?}"
|
||||||
);
|
);
|
||||||
if let Some(file) = file {
|
if let Some(file) = file
|
||||||
if let Err(error) = writeln!(file, "{line}") {
|
&& let Err(error) = writeln!(file, "{line}")
|
||||||
|
{
|
||||||
eprintln!("Unable to write Iota log file: {error}");
|
eprintln!("Unable to write Iota log file: {error}");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
eprintln!("{line}");
|
eprintln!("{line}");
|
||||||
let _ = broadcaster.send(UiLogEntry {
|
let _ = broadcaster.send(UiLogEntry {
|
||||||
timestamp_ms,
|
timestamp_ms,
|
||||||
|
|
@ -632,6 +632,36 @@ fn format_data_container(data: &[(DataTypeId, DataValue)], type_map: &TypeMap) -
|
||||||
.join(", ")
|
.join(", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_cv {
|
||||||
|
($kind:expr, $cv:expr) => {
|
||||||
|
$crate::log_cv_internal("", &$cv, Some($kind))
|
||||||
|
};
|
||||||
|
($cv:expr) => {
|
||||||
|
$crate::log_cv_internal("", &$cv, None)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_cv_in {
|
||||||
|
($kind:expr, $cv:expr) => {
|
||||||
|
$crate::log_cv_internal("> ", &$cv, Some($kind))
|
||||||
|
};
|
||||||
|
($cv:expr) => {
|
||||||
|
$crate::log_cv_internal("> ", $cv, None)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_cv_out {
|
||||||
|
($kind:expr, $cv:expr) => {
|
||||||
|
$crate::log_cv_internal("< ", &$cv, Some($kind))
|
||||||
|
};
|
||||||
|
($cv:expr) => {
|
||||||
|
$crate::log_cv_internal("< ", $cv, None)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::format_cv;
|
use super::format_cv;
|
||||||
|
|
@ -662,33 +692,3 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! log_cv {
|
|
||||||
($kind:expr, $cv:expr) => {
|
|
||||||
$crate::log_cv_internal("", &$cv, Some($kind))
|
|
||||||
};
|
|
||||||
($cv:expr) => {
|
|
||||||
$crate::log_cv_internal("", &$cv, None)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! log_cv_in {
|
|
||||||
($kind:expr, $cv:expr) => {
|
|
||||||
$crate::log_cv_internal("> ", &$cv, Some($kind))
|
|
||||||
};
|
|
||||||
($cv:expr) => {
|
|
||||||
$crate::log_cv_internal("> ", $cv, None)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! log_cv_out {
|
|
||||||
($kind:expr, $cv:expr) => {
|
|
||||||
$crate::log_cv_internal("< ", &$cv, Some($kind))
|
|
||||||
};
|
|
||||||
($cv:expr) => {
|
|
||||||
$crate::log_cv_internal("< ", $cv, None)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ mod systemd {
|
||||||
}
|
}
|
||||||
let executor: Arc<dyn CommandExecutor> = Arc::new(RealExecutor);
|
let executor: Arc<dyn CommandExecutor> = Arc::new(RealExecutor);
|
||||||
let mut manager = executor
|
let mut manager = executor
|
||||||
.output("systemctl", &["--version", &COMMON[0], &COMMON[1]])
|
.output("systemctl", &["--version", COMMON[0], COMMON[1]])
|
||||||
.await
|
.await
|
||||||
.ok()
|
.ok()
|
||||||
.filter(|r| r.success)
|
.filter(|r| r.success)
|
||||||
|
|
@ -573,11 +573,11 @@ mod systemd {
|
||||||
|
|
||||||
let deadline = tokio::time::Instant::now() + Duration::from_secs(2);
|
let deadline = tokio::time::Instant::now() + Duration::from_secs(2);
|
||||||
let pid = loop {
|
let pid = loop {
|
||||||
if let Ok(contents) = fs::read_to_string(&pid_file) {
|
if let Ok(contents) = fs::read_to_string(&pid_file)
|
||||||
if let Ok(pid) = contents.parse::<libc::pid_t>() {
|
&& let Ok(pid) = contents.parse::<libc::pid_t>()
|
||||||
|
{
|
||||||
break pid;
|
break pid;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
assert!(tokio::time::Instant::now() < deadline);
|
assert!(tokio::time::Instant::now() < deadline);
|
||||||
tokio::task::yield_now().await;
|
tokio::task::yield_now().await;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,12 @@ impl AppState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for AppState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "legacy-globals")]
|
#[cfg(feature = "legacy-globals")]
|
||||||
#[deprecated(note = "use DaemonState or ClientState")]
|
#[deprecated(note = "use DaemonState or ClientState")]
|
||||||
pub static APP_STATE: LazyLock<Arc<Mutex<AppState>>> =
|
pub static APP_STATE: LazyLock<Arc<Mutex<AppState>>> =
|
||||||
|
|
@ -228,7 +234,7 @@ pub static SHUTDOWN: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(false));
|
||||||
pub static RELOAD: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(true));
|
pub static RELOAD: Lazy<RwLock<bool>> = Lazy::new(|| RwLock::new(true));
|
||||||
#[cfg(feature = "legacy-globals")]
|
#[cfg(feature = "legacy-globals")]
|
||||||
#[deprecated(note = "use DaemonState")]
|
#[deprecated(note = "use DaemonState")]
|
||||||
pub static ACTIVE_TASKS: Lazy<DashSet<String>> = Lazy::new(|| DashSet::new());
|
pub static ACTIVE_TASKS: Lazy<DashSet<String>> = Lazy::new(DashSet::new);
|
||||||
|
|
||||||
#[cfg(feature = "legacy-globals")]
|
#[cfg(feature = "legacy-globals")]
|
||||||
pub fn setup(state: &DaemonState) {
|
pub fn setup(state: &DaemonState) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct Contact {
|
pub struct Contact {
|
||||||
pub user_id: i64,
|
pub user_id: i64,
|
||||||
pub principal: Option<iota_identity::PrincipalHandle>,
|
pub principal: Option<iota_identity::PrincipalHandle>,
|
||||||
|
|
@ -9,20 +9,6 @@ pub struct Contact {
|
||||||
pub notifications_read_at: i64,
|
pub notifications_read_at: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Contact {
|
|
||||||
fn default() -> Self {
|
|
||||||
Contact {
|
|
||||||
user_id: 0,
|
|
||||||
principal: None,
|
|
||||||
user_name: None,
|
|
||||||
created_at: 0,
|
|
||||||
last_message_at: None,
|
|
||||||
notifications: 0,
|
|
||||||
notifications_read_at: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Contact {
|
impl Contact {
|
||||||
pub fn new(user_id: i64) -> Self {
|
pub fn new(user_id: i64) -> Self {
|
||||||
let created_at = std::time::SystemTime::now()
|
let created_at = std::time::SystemTime::now()
|
||||||
|
|
|
||||||
|
|
@ -682,15 +682,15 @@ pub fn load_users_sync() -> std::io::Result<()> {
|
||||||
if content.trim().is_empty() {
|
if content.trim().is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if let Ok(parsed) = json::parse(&content) {
|
if let Ok(parsed) = json::parse(&content)
|
||||||
if let json::JsonValue::Array(arr) = parsed {
|
&& let json::JsonValue::Array(arr) = parsed
|
||||||
|
{
|
||||||
for j in arr.iter() {
|
for j in arr.iter() {
|
||||||
if let Some(up) = UserProfile::from_json(j) {
|
if let Some(up) = UserProfile::from_json(j) {
|
||||||
try_add_user(up).map_err(|error| std::io::Error::other(error.to_string()))?;
|
try_add_user(up).map_err(|error| std::io::Error::other(error.to_string()))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Rename the old file so we don't re-import
|
// Rename the old file so we don't re-import
|
||||||
let _ = std::fs::rename(
|
let _ = std::fs::rename(
|
||||||
std::path::PathBuf::from(iota_util::file_util::get_directory()).join("users.json"),
|
std::path::PathBuf::from(iota_util::file_util::get_directory()).join("users.json"),
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl UserProfile {
|
||||||
"username" => self.username.clone(),
|
"username" => self.username.clone(),
|
||||||
"public_key" => self.public_key.clone(),
|
"public_key" => self.public_key.clone(),
|
||||||
"created_at" => self.created_at,
|
"created_at" => self.created_at,
|
||||||
"storage" => used_dir_space(&format!("users/{}", self.user_id.to_string())),
|
"storage" => used_dir_space(&format!("users/{}", self.user_id)),
|
||||||
};
|
};
|
||||||
if let Some(d) = &self.display_name {
|
if let Some(d) = &self.display_name {
|
||||||
obj["display_name"] = d.clone().into();
|
obj["display_name"] = d.clone().into();
|
||||||
|
|
@ -113,7 +113,7 @@ impl UserProfile {
|
||||||
pub fn randomize_reset_token(&mut self) -> String {
|
pub fn randomize_reset_token(&mut self) -> String {
|
||||||
let mut bytes = [0u8; 192];
|
let mut bytes = [0u8; 192];
|
||||||
OsRng.fill(bytes.as_mut());
|
OsRng.fill(bytes.as_mut());
|
||||||
let new_token = general_purpose::STANDARD.encode(&bytes);
|
let new_token = general_purpose::STANDARD.encode(bytes);
|
||||||
self.reset_token = Some(new_token.clone());
|
self.reset_token = Some(new_token.clone());
|
||||||
new_token
|
new_token
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ pub struct CallEnvelope {
|
||||||
pub fn store(envelope: &CallEnvelope, now: i64) -> Result<bool, StorageError> {
|
pub fn store(envelope: &CallEnvelope, now: i64) -> Result<bool, StorageError> {
|
||||||
db::with_immediate_transaction(|tx| {
|
db::with_immediate_transaction(|tx| {
|
||||||
tx.execute("DELETE FROM call_envelopes WHERE expires_at <= ?1", [now])?;
|
tx.execute("DELETE FROM call_envelopes WHERE expires_at <= ?1", [now])?;
|
||||||
|
#[expect(clippy::type_complexity, reason = "tuple matches the selected database columns")]
|
||||||
let existing: Option<(i64, i64, i64, String, i64, Vec<u8>, Vec<u8>, String)> = tx.query_row(
|
let existing: Option<(i64, i64, i64, String, i64, Vec<u8>, Vec<u8>, String)> = tx.query_row(
|
||||||
"SELECT owner_omikron_id, inviter_id, created_at, secret_id, version_number, encrypted_secret, kem_ciphertext, wrapping_scheme FROM call_envelopes WHERE recipient_id = ?1 AND call_id = ?2",
|
"SELECT owner_omikron_id, inviter_id, created_at, secret_id, version_number, encrypted_secret, kem_ciphertext, wrapping_scheme FROM call_envelopes WHERE recipient_id = ?1 AND call_id = ?2",
|
||||||
params![envelope.recipient_id, envelope.call_id],
|
params![envelope.recipient_id, envelope.call_id],
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ impl MessageState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(
|
||||||
|
clippy::should_implement_trait,
|
||||||
|
reason = "unknown stored states fall back rather than fail parsing"
|
||||||
|
)]
|
||||||
pub fn from_str(value: &str) -> Self {
|
pub fn from_str(value: &str) -> Self {
|
||||||
match value.to_lowercase().as_str() {
|
match value.to_lowercase().as_str() {
|
||||||
"read" => MessageState::Read,
|
"read" => MessageState::Read,
|
||||||
|
|
@ -1024,6 +1028,10 @@ pub fn change_message_state_by_relay_id(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(
|
||||||
|
clippy::too_many_arguments,
|
||||||
|
reason = "explicit persisted receipt fields"
|
||||||
|
)]
|
||||||
pub fn record_message_receipt(
|
pub fn record_message_receipt(
|
||||||
storage_owner: i64,
|
storage_owner: i64,
|
||||||
target_signer_id: i64,
|
target_signer_id: i64,
|
||||||
|
|
@ -1232,7 +1240,7 @@ pub fn change_message_state(
|
||||||
tx.commit()?;
|
tx.commit()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.map_err(|e: StorageError| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))
|
.map_err(|e: StorageError| std::io::Error::other(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_reactions(
|
fn load_reactions(
|
||||||
|
|
@ -1275,10 +1283,9 @@ fn load_reactions(
|
||||||
if reactions
|
if reactions
|
||||||
.iter()
|
.iter()
|
||||||
.any(|stored: &StoredReaction| stored.reaction == row.1.reaction)
|
.any(|stored: &StoredReaction| stored.reaction == row.1.reaction)
|
||||||
|
|| reactions.len() < MAX_UNIQUE_REACTIONS_PER_MESSAGE
|
||||||
{
|
{
|
||||||
reactions.push(row.1);
|
reactions.push(row.1);
|
||||||
} else if reactions.len() < MAX_UNIQUE_REACTIONS_PER_MESSAGE {
|
|
||||||
reactions.push(row.1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(map)
|
Ok(map)
|
||||||
|
|
|
||||||
|
|
@ -127,16 +127,13 @@ pub struct RelayRouterSettings {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[derive(Default)]
|
||||||
pub enum WebMode {
|
pub enum WebMode {
|
||||||
|
#[default]
|
||||||
Disabled,
|
Disabled,
|
||||||
Loopback,
|
Loopback,
|
||||||
Network,
|
Network,
|
||||||
}
|
}
|
||||||
impl Default for WebMode {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Disabled
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
|
|
@ -340,15 +337,15 @@ pub fn save_config() {
|
||||||
|
|
||||||
pub fn save_config_to(path: &Path) {
|
pub fn save_config_to(path: &Path) {
|
||||||
if let Ok(yaml) = serde_yaml::to_string(&**CONFIG.load()) {
|
if let Ok(yaml) = serde_yaml::to_string(&**CONFIG.load()) {
|
||||||
if let Some(parent) = path.parent() {
|
if let Some(parent) = path.parent()
|
||||||
if let Err(error) = fs::create_dir_all(parent) {
|
&& let Err(error) = fs::create_dir_all(parent)
|
||||||
|
{
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Cannot create configuration directory {}: {error}",
|
"Cannot create configuration directory {}: {error}",
|
||||||
parent.display()
|
parent.display()
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if let Err(error) = iota_util::atomic_file::replace(path, yaml.as_bytes(), 3) {
|
if let Err(error) = iota_util::atomic_file::replace(path, yaml.as_bytes(), 3) {
|
||||||
eprintln!("Cannot save {}: {error}", path.display());
|
eprintln!("Cannot save {}: {error}", path.display());
|
||||||
}
|
}
|
||||||
|
|
@ -495,8 +492,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn zero_ipc_capacity_is_rejected() {
|
fn zero_ipc_capacity_is_rejected() {
|
||||||
let mut config = IotaConfig::default();
|
let config = IotaConfig {
|
||||||
config.max_ipc_clients = 0;
|
max_ipc_clients: 0,
|
||||||
|
..IotaConfig::default()
|
||||||
|
};
|
||||||
assert!(matches!(
|
assert!(matches!(
|
||||||
validate_config(&config),
|
validate_config(&config),
|
||||||
Err(ConfigError::InvalidMaxIpcClients)
|
Err(ConfigError::InvalidMaxIpcClients)
|
||||||
|
|
|
||||||
|
|
@ -2116,7 +2116,7 @@ where
|
||||||
let guard = shared
|
let guard = shared
|
||||||
.lock()
|
.lock()
|
||||||
.map_err(|e| format!("DB mutex poisoned: {:?}", e))?;
|
.map_err(|e| format!("DB mutex poisoned: {:?}", e))?;
|
||||||
f(&*guard).map_err(|e| e.to_string())
|
f(&guard).map_err(|e| e.to_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,11 @@ fn validate(user_id: i64, retention: MessageRetention) -> Result<(), StorageErro
|
||||||
"invalid message storage policy owner".into(),
|
"invalid message storage policy owner".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let MessageRetention::Duration { duration_ms } = retention {
|
if let MessageRetention::Duration { duration_ms } = retention
|
||||||
if !(MIN_RETENTION_DURATION_MS..=MAX_RETENTION_DURATION_MS).contains(&duration_ms) {
|
&& !(MIN_RETENTION_DURATION_MS..=MAX_RETENTION_DURATION_MS).contains(&duration_ms)
|
||||||
|
{
|
||||||
return Err(StorageError::Other("invalid retention duration".into()));
|
return Err(StorageError::Other("invalid retention duration".into()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn history_name(value: MessageHistoryMode) -> &'static str {
|
fn history_name(value: MessageHistoryMode) -> &'static str {
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,11 @@ fn validate(user_id: i64, blob_id: &str, blob: Option<&[u8]>) -> Result<(), Stor
|
||||||
if blob_id.is_empty() || blob_id.len() > MAX_BLOB_ID_BYTES {
|
if blob_id.is_empty() || blob_id.len() > MAX_BLOB_ID_BYTES {
|
||||||
return Err(StorageError::Other("invalid blob id".into()));
|
return Err(StorageError::Other("invalid blob id".into()));
|
||||||
}
|
}
|
||||||
if let Some(blob) = blob {
|
if let Some(blob) = blob
|
||||||
if blob.len() > MAX_BLOB_BYTES {
|
&& blob.len() > MAX_BLOB_BYTES
|
||||||
|
{
|
||||||
return Err(StorageError::Other("blob exceeds size limit".into()));
|
return Err(StorageError::Other("blob exceeds size limit".into()));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,15 @@ impl Type {
|
||||||
Self::PP => "privacy-policy",
|
Self::PP => "privacy-policy",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn to_string(&self) -> String {
|
}
|
||||||
match self {
|
|
||||||
Self::EULA => "End User License Agreement".to_string(),
|
impl std::fmt::Display for Type {
|
||||||
Self::TOS => "Terms of Service".to_string(),
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
Self::PP => "Privacy Policy".to_string(),
|
f.write_str(match self {
|
||||||
}
|
Self::EULA => "End User License Agreement",
|
||||||
|
Self::TOS => "Terms of Service",
|
||||||
|
Self::PP => "Privacy Policy",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -263,12 +263,10 @@ pub fn get_children(path: &str) -> Vec<String> {
|
||||||
};
|
};
|
||||||
let mut children = Vec::new();
|
let mut children = Vec::new();
|
||||||
if let Ok(entries) = fs::read_dir(&dir) {
|
if let Ok(entries) = fs::read_dir(&dir) {
|
||||||
for entry in entries {
|
for entry in entries.flatten() {
|
||||||
if let Ok(entry) = entry {
|
|
||||||
children.push(entry.file_name().to_string_lossy().to_string());
|
children.push(entry.file_name().to_string_lossy().to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
children
|
children
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -342,13 +340,13 @@ pub fn get_directory_size(directory: &Path) -> u64 {
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) {
|
for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.is_file() {
|
if path.is_file()
|
||||||
if let Ok(metadata) = path.metadata() {
|
&& let Ok(metadata) = path.metadata()
|
||||||
|
{
|
||||||
size += path.file_name().unwrap_or(OsStr::new("")).len() as u64;
|
size += path.file_name().unwrap_or(OsStr::new("")).len() as u64;
|
||||||
size += metadata.len();
|
size += metadata.len();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -427,11 +425,10 @@ fn extract_zip_contents_to_folder(
|
||||||
let mut file = archive.by_index(i)?;
|
let mut file = archive.by_index(i)?;
|
||||||
let entry_path = staging_dir.join(file.sanitized_name());
|
let entry_path = staging_dir.join(file.sanitized_name());
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 && (file.name().ends_with('/') || file.sanitized_name().components().count() == 1)
|
||||||
if file.name().ends_with('/') || file.sanitized_name().components().count() == 1 {
|
{
|
||||||
first_item_name = Some(file.sanitized_name());
|
first_item_name = Some(file.sanitized_name());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if file.name().ends_with('/') {
|
if file.name().ends_with('/') {
|
||||||
fs::create_dir_all(&entry_path)?;
|
fs::create_dir_all(&entry_path)?;
|
||||||
|
|
@ -461,7 +458,7 @@ fn extract_zip_contents_to_folder(
|
||||||
let src = entry.path();
|
let src = entry.path();
|
||||||
let dest = target_dir.join(entry.file_name());
|
let dest = target_dir.join(entry.file_name());
|
||||||
|
|
||||||
if let Err(_) = fs::rename(&src, &dest) {
|
if fs::rename(&src, &dest).is_err() {
|
||||||
if src.is_file() {
|
if src.is_file() {
|
||||||
fs::copy(&src, &dest)?;
|
fs::copy(&src, &dest)?;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,10 @@ impl RequiredCommunicationFields for CommunicationValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(
|
||||||
|
clippy::wrong_self_convention,
|
||||||
|
reason = "mirror DataValue accessors on optional borrowed values"
|
||||||
|
)]
|
||||||
pub trait OptionalDataValueExt<'a> {
|
pub trait OptionalDataValueExt<'a> {
|
||||||
fn as_bool(self) -> Option<bool>;
|
fn as_bool(self) -> Option<bool>;
|
||||||
fn as_str(self) -> Option<&'a str>;
|
fn as_str(self) -> Option<&'a str>;
|
||||||
|
|
|
||||||
|
|
@ -557,8 +557,8 @@ impl CliInvocation {
|
||||||
let parsed =
|
let parsed =
|
||||||
Cli::try_parse_from(std::iter::once("iota".to_owned()).chain(args)).map_err(|error| {
|
Cli::try_parse_from(std::iter::once("iota".to_owned()).chain(args)).map_err(|error| {
|
||||||
match error.kind() {
|
match error.kind() {
|
||||||
ErrorKind::DisplayHelp => return "__help__".to_owned(),
|
ErrorKind::DisplayHelp => "__help__".to_owned(),
|
||||||
ErrorKind::DisplayVersion => return "__version__".to_owned(),
|
ErrorKind::DisplayVersion => "__version__".to_owned(),
|
||||||
_ => error.to_string(),
|
_ => error.to_string(),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ impl Capabilities {
|
||||||
let once = self
|
let once = self
|
||||||
.executable
|
.executable
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|_| self.socket.as_ref())
|
.and(self.socket.as_ref())
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
.map_err(ToString::to_string);
|
.map_err(ToString::to_string);
|
||||||
let ui = once.clone();
|
let ui = once.clone();
|
||||||
|
|
@ -72,11 +72,11 @@ pub async fn run(
|
||||||
if let Ok(ipc) = IpcClient::connect(&endpoints.local).await {
|
if let Ok(ipc) = IpcClient::connect(&endpoints.local).await {
|
||||||
return Ok(ConnectionContext { ipc });
|
return Ok(ConnectionContext { ipc });
|
||||||
}
|
}
|
||||||
if endpoints.system != endpoints.local {
|
if endpoints.system != endpoints.local
|
||||||
if let Ok(ipc) = IpcClient::connect(&endpoints.system).await {
|
&& let Ok(ipc) = IpcClient::connect(&endpoints.system).await
|
||||||
|
{
|
||||||
return Ok(ConnectionContext { ipc });
|
return Ok(ConnectionContext { ipc });
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let options = caps.options();
|
let options = caps.options();
|
||||||
if !options.iter().any(|o| o.enabled) {
|
if !options.iter().any(|o| o.enabled) {
|
||||||
return Err(StartupError::Other(
|
return Err(StartupError::Other(
|
||||||
|
|
|
||||||
|
|
@ -32,15 +32,15 @@ impl LocalDaemonGuard {
|
||||||
}
|
}
|
||||||
impl Drop for LocalDaemonGuard {
|
impl Drop for LocalDaemonGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.committed {
|
if !self.committed
|
||||||
if let Some(mut child) = self.child.take() {
|
&& let Some(mut child) = self.child.take()
|
||||||
|
{
|
||||||
let _ = child.start_kill();
|
let _ = child.start_kill();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let _ = child.wait().await;
|
let _ = child.wait().await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn launch(
|
pub async fn launch(
|
||||||
|
|
|
||||||
|
|
@ -1208,7 +1208,7 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!(
|
println!(
|
||||||
"{:<15} {}",
|
"{:<15} {}",
|
||||||
"Authority",
|
"Authority",
|
||||||
format!("{:?}", invitation.authority)
|
format_args!("{:?}", invitation.authority)
|
||||||
);
|
);
|
||||||
println!("{:<15} {}", "Token", invitation.raw_token.0);
|
println!("{:<15} {}", "Token", invitation.raw_token.0);
|
||||||
println!("{:<15} {}", "Expires", invitation.expires_at);
|
println!("{:<15} {}", "Expires", invitation.expires_at);
|
||||||
|
|
@ -1298,8 +1298,8 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!("No active tasks.");
|
println!("No active tasks.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
println!("{}", "NAME");
|
println!("NAME");
|
||||||
println!("{}", "--------");
|
println!("--------");
|
||||||
for task in tasks {
|
for task in tasks {
|
||||||
println!("{}", task.name);
|
println!("{}", task.name);
|
||||||
}
|
}
|
||||||
|
|
@ -1309,8 +1309,8 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!("No component health data available.");
|
println!("No component health data available.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
println!("{:<20} {:<10} {}", "COMPONENT", "STATUS", "MESSAGE");
|
println!("{:<20} {:<10} MESSAGE", "COMPONENT", "STATUS");
|
||||||
println!("{:<20} {:<10} {}", "--------", "--------", "--------");
|
println!("{:<20} {:<10} --------", "--------", "--------");
|
||||||
for comp in components {
|
for comp in components {
|
||||||
let status_str = match comp.status {
|
let status_str = match comp.status {
|
||||||
iota_ipc::HealthStatus::Healthy => "healthy",
|
iota_ipc::HealthStatus::Healthy => "healthy",
|
||||||
|
|
@ -1331,8 +1331,8 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!("No communities.");
|
println!("No communities.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
println!("{:<20} {}", "NAME", "TITLE");
|
println!("{:<20} TITLE", "NAME");
|
||||||
println!("{:<20} {}", "--------", "--------");
|
println!("{:<20} --------", "--------");
|
||||||
for c in communities {
|
for c in communities {
|
||||||
println!("{:<20} {}", c.name, c.title);
|
println!("{:<20} {}", c.name, c.title);
|
||||||
}
|
}
|
||||||
|
|
@ -1343,12 +1343,12 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
println!(
|
println!(
|
||||||
"{:<20} {:<6} {:<12} {}",
|
"{:<20} {:<6} {:<12} MESSAGE",
|
||||||
"TIMESTAMP", "LEVEL", "SENDER", "MESSAGE"
|
"TIMESTAMP", "LEVEL", "SENDER"
|
||||||
);
|
);
|
||||||
println!(
|
println!(
|
||||||
"{:<20} {:<6} {:<12} {}",
|
"{:<20} {:<6} {:<12} --------",
|
||||||
"--------", "--------", "--------", "--------"
|
"--------", "--------", "--------"
|
||||||
);
|
);
|
||||||
for entry in &logs.entries {
|
for entry in &logs.entries {
|
||||||
let level = if entry.is_error { "ERR" } else { "INF" };
|
let level = if entry.is_error { "ERR" } else { "INF" };
|
||||||
|
|
@ -1359,8 +1359,8 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponsePayload::Status(status) => {
|
ResponsePayload::Status(status) => {
|
||||||
println!("{:<15} {}", "Field", "Value");
|
println!("{:<15} Value", "Field");
|
||||||
println!("{:<15} {}", "--------", "--------");
|
println!("{:<15} --------", "--------");
|
||||||
println!("{:<15} {}", "Phase", status.phase);
|
println!("{:<15} {}", "Phase", status.phase);
|
||||||
if !status.tasks.is_empty() {
|
if !status.tasks.is_empty() {
|
||||||
println!("{:<15} {}", "Tasks", status.tasks.join(", "));
|
println!("{:<15} {}", "Tasks", status.tasks.join(", "));
|
||||||
|
|
@ -1376,16 +1376,16 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!("{}", config.yaml);
|
println!("{}", config.yaml);
|
||||||
}
|
}
|
||||||
ResponsePayload::OmikronStatus(status) => {
|
ResponsePayload::OmikronStatus(status) => {
|
||||||
println!("{:<15} {}", "Field", "Value");
|
println!("{:<15} Value", "Field");
|
||||||
println!("{:<15} {}", "--------", "--------");
|
println!("{:<15} --------", "--------");
|
||||||
println!("{:<15} {}", "Connected", status.connected);
|
println!("{:<15} {}", "Connected", status.connected);
|
||||||
if let Some(id) = &status.iota_id {
|
if let Some(id) = &status.iota_id {
|
||||||
println!("{:<15} {}", "Iota ID", id);
|
println!("{:<15} {}", "Iota ID", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponsePayload::UpdateStatus(status) => {
|
ResponsePayload::UpdateStatus(status) => {
|
||||||
println!("{:<15} {}", "Field", "Value");
|
println!("{:<15} Value", "Field");
|
||||||
println!("{:<15} {}", "--------", "--------");
|
println!("{:<15} --------", "--------");
|
||||||
println!("{:<15} {}", "Available", status.available);
|
println!("{:<15} {}", "Available", status.available);
|
||||||
}
|
}
|
||||||
ResponsePayload::UserCreated { user_id, username } => {
|
ResponsePayload::UserCreated { user_id, username } => {
|
||||||
|
|
@ -1428,8 +1428,8 @@ fn render_table(payload: &ResponsePayload) {
|
||||||
println!("{}", message);
|
println!("{}", message);
|
||||||
}
|
}
|
||||||
ResponsePayload::UserDetail(user) => {
|
ResponsePayload::UserDetail(user) => {
|
||||||
println!("{:<15} {}", "Field", "Value");
|
println!("{:<15} Value", "Field");
|
||||||
println!("{:<15} {}", "--------", "--------");
|
println!("{:<15} --------", "--------");
|
||||||
println!("{:<15} {}", "Username", user.username);
|
println!("{:<15} {}", "Username", user.username);
|
||||||
println!("{:<15} {}", "User ID", user.user_id);
|
println!("{:<15} {}", "User ID", user.user_id);
|
||||||
if let Some(ref name) = user.display_name {
|
if let Some(ref name) = user.display_name {
|
||||||
|
|
|
||||||
|
|
@ -73,11 +73,11 @@ async fn accept(system: bool) -> Result<(), StartupError> {
|
||||||
for document in [&documents.0, &documents.1, &documents.2] {
|
for document in [&documents.0, &documents.1, &documents.2] {
|
||||||
println!(
|
println!(
|
||||||
"\n===== {} =====\nVersion: {}\nDocument hash: {}\n",
|
"\n===== {} =====\nVersion: {}\nDocument hash: {}\n",
|
||||||
document.kind().to_string(),
|
document.kind(),
|
||||||
document.version(),
|
document.version(),
|
||||||
document.hash()
|
document.hash()
|
||||||
);
|
);
|
||||||
print!("{}\n", document.content());
|
println!("{}", document.content());
|
||||||
if !confirm(document)? {
|
if !confirm(document)? {
|
||||||
return Err(StartupError::Consent(
|
return Err(StartupError::Consent(
|
||||||
"No terms were accepted. Iota remains inactive.".into(),
|
"No terms were accepted. Iota remains inactive.".into(),
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
#![allow(
|
||||||
|
clippy::result_large_err,
|
||||||
|
reason = "return protocol error frames directly to the sender"
|
||||||
|
)]
|
||||||
|
|
||||||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||||
use dashmap::{DashMap, DashSet};
|
use dashmap::{DashMap, DashSet};
|
||||||
use iota_logger::{LogLevel, PrintType, log, log_cv_in, log_cv_out, log_event, log_t};
|
use iota_logger::{LogLevel, PrintType, log, log_cv_in, log_cv_out, log_event, log_t};
|
||||||
|
|
@ -350,7 +355,7 @@ pub struct WaitingTask {
|
||||||
pub inserted_at: Instant,
|
pub inserted_at: Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static WAITING_TASKS: LazyLock<DashMap<u32, WaitingTask>> = LazyLock::new(|| DashMap::new());
|
pub static WAITING_TASKS: LazyLock<DashMap<u32, WaitingTask>> = LazyLock::new(DashMap::new);
|
||||||
|
|
||||||
pub fn start_task_cleanup_loop() {
|
pub fn start_task_cleanup_loop() {
|
||||||
tokio::spawn(async {
|
tokio::spawn(async {
|
||||||
|
|
@ -960,7 +965,7 @@ impl OmikronConnection {
|
||||||
let conf = CONFIG.load();
|
let conf = CONFIG.load();
|
||||||
match (&conf.omikron_id, &conf.omikron_host, conf.omikron_port) {
|
match (&conf.omikron_id, &conf.omikron_host, conf.omikron_port) {
|
||||||
(Some(id), Some(host), Some(port)) if !host.trim().is_empty() && port != 0 => {
|
(Some(id), Some(host), Some(port)) if !host.trim().is_empty() && port != 0 => {
|
||||||
mtp::files::load_public_key_bundle(&omikron_public_key_path(*id))
|
mtp::files::load_public_key_bundle(omikron_public_key_path(*id))
|
||||||
.ok()
|
.ok()
|
||||||
.map(|public_key| ResolvedOmikronEndpoint {
|
.map(|public_key| ResolvedOmikronEndpoint {
|
||||||
id: Some(*id),
|
id: Some(*id),
|
||||||
|
|
@ -1100,11 +1105,11 @@ impl OmikronConnection {
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if let Some((_, task)) = WAITING_TASKS.remove(&msg_id) {
|
if let Some((_, task)) = WAITING_TASKS.remove(&msg_id)
|
||||||
if (task.task)(cv.clone()) {
|
&& (task.task)(cv.clone())
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
let permit = self.handler_semaphore.clone().acquire_owned().await;
|
let permit = self.handler_semaphore.clone().acquire_owned().await;
|
||||||
let self_clone = self.clone();
|
let self_clone = self.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
|
@ -1604,8 +1609,7 @@ impl OmikronConnection {
|
||||||
Ok(response) if !response.is_type(CommunicationType::ErrorInternal) => {
|
Ok(response) if !response.is_type(CommunicationType::ErrorInternal) => {
|
||||||
if let (Some(message_id), Some(signer_id)) =
|
if let (Some(message_id), Some(signer_id)) =
|
||||||
(record.relay_message_id.as_deref(), record.relay_signer_id)
|
(record.relay_message_id.as_deref(), record.relay_signer_id)
|
||||||
{
|
&& let Err(error) =
|
||||||
if let Err(error) =
|
|
||||||
iota_storage::util::downstream_relay::reject_iota_delivery(
|
iota_storage::util::downstream_relay::reject_iota_delivery(
|
||||||
record.frame_id,
|
record.frame_id,
|
||||||
signer_principal,
|
signer_principal,
|
||||||
|
|
@ -1621,7 +1625,6 @@ impl OmikronConnection {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(response) => log!(
|
Ok(response) => log!(
|
||||||
"Pending Relay {} route returned retryable {}",
|
"Pending Relay {} route returned retryable {}",
|
||||||
record.id,
|
record.id,
|
||||||
|
|
@ -1701,11 +1704,11 @@ impl OmikronConnection {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((_, task)) = WAITING_TASKS.remove(&msg_id) {
|
if let Some((_, task)) = WAITING_TASKS.remove(&msg_id)
|
||||||
if (task.task)(cv.clone()) {
|
&& (task.task)(cv.clone())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.clone().handle_message_impl(cv).await;
|
self.clone().handle_message_impl(cv).await;
|
||||||
}
|
}
|
||||||
|
|
@ -1916,8 +1919,8 @@ impl OmikronConnection {
|
||||||
if matches!(
|
if matches!(
|
||||||
result,
|
result,
|
||||||
Ok(iota_storage::users::invitations::ProvisioningResult::MissingInvitation)
|
Ok(iota_storage::users::invitations::ProvisioningResult::MissingInvitation)
|
||||||
) {
|
) && self.sync_omega_invitations().await.is_ok()
|
||||||
if self.sync_omega_invitations().await.is_ok() {
|
{
|
||||||
result = iota_storage::users::invitations::apply_external_invitation_provisioning(
|
result = iota_storage::users::invitations::apply_external_invitation_provisioning(
|
||||||
invitation_id,
|
invitation_id,
|
||||||
invitation_revision,
|
invitation_revision,
|
||||||
|
|
@ -1925,7 +1928,6 @@ impl OmikronConnection {
|
||||||
now,
|
now,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
match result {
|
match result {
|
||||||
Ok(
|
Ok(
|
||||||
iota_storage::users::invitations::ProvisioningResult::Created
|
iota_storage::users::invitations::ProvisioningResult::Created
|
||||||
|
|
@ -2378,7 +2380,7 @@ impl OmikronConnection {
|
||||||
let port = config
|
let port = config
|
||||||
.omikron_port
|
.omikron_port
|
||||||
.ok_or_else(|| "Omikron port is unavailable".to_string())?;
|
.ok_or_else(|| "Omikron port is unavailable".to_string())?;
|
||||||
let omikron_key = mtp::files::load_public_key_bundle(&omikron_public_key_path(omikron_id))
|
let omikron_key = mtp::files::load_public_key_bundle(omikron_public_key_path(omikron_id))
|
||||||
.map_err(|error| error.to_string())?;
|
.map_err(|error| error.to_string())?;
|
||||||
let omikron_public_key = omikron_key
|
let omikron_public_key = omikron_key
|
||||||
.try_to_base64()
|
.try_to_base64()
|
||||||
|
|
@ -3150,11 +3152,7 @@ impl OmikronConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_call_envelope_store(self: Arc<Self>, cv: &CommunicationValue) {
|
async fn handle_call_envelope_store(self: Arc<Self>, cv: &CommunicationValue) {
|
||||||
let response = match CONFIG
|
let response = match CONFIG.load().omikron_id {
|
||||||
.load()
|
|
||||||
.omikron_id
|
|
||||||
.and_then(|id| i64::try_from(id).ok())
|
|
||||||
{
|
|
||||||
Some(owner) => message_handlers::handle_call_envelope_store(cv, owner),
|
Some(owner) => message_handlers::handle_call_envelope_store(cv, owner),
|
||||||
None => error_response(cv, CommunicationType::ErrorInternal),
|
None => error_response(cv, CommunicationType::ErrorInternal),
|
||||||
};
|
};
|
||||||
|
|
@ -3162,11 +3160,7 @@ impl OmikronConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_call_envelope_get(self: Arc<Self>, cv: &CommunicationValue) {
|
async fn handle_call_envelope_get(self: Arc<Self>, cv: &CommunicationValue) {
|
||||||
let response = match CONFIG
|
let response = match CONFIG.load().omikron_id {
|
||||||
.load()
|
|
||||||
.omikron_id
|
|
||||||
.and_then(|id| i64::try_from(id).ok())
|
|
||||||
{
|
|
||||||
Some(owner) => message_handlers::handle_call_envelope_get(cv, owner),
|
Some(owner) => message_handlers::handle_call_envelope_get(cv, owner),
|
||||||
None => error_response(cv, CommunicationType::ErrorInternal),
|
None => error_response(cv, CommunicationType::ErrorInternal),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,7 @@ impl OmikronConnection {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(clippy::too_many_arguments, reason = "explicit protected frame fields")]
|
||||||
pub(super) fn build_protected(
|
pub(super) fn build_protected(
|
||||||
&self,
|
&self,
|
||||||
frame: &CommunicationValue,
|
frame: &CommunicationValue,
|
||||||
|
|
|
||||||
|
|
@ -79,12 +79,12 @@ impl AttemptLease {
|
||||||
|
|
||||||
impl Drop for AttemptLease {
|
impl Drop for AttemptLease {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !self.settled {
|
if !self.settled
|
||||||
if let Some(runtime) = self.runtime.upgrade() {
|
&& let Some(runtime) = self.runtime.upgrade()
|
||||||
|
{
|
||||||
runtime.finish_attempt_cancel(self.user_id);
|
runtime.finish_attempt_cancel(self.user_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct PasswordAuthRuntime {
|
pub(crate) struct PasswordAuthRuntime {
|
||||||
|
|
@ -219,12 +219,12 @@ impl PasswordAuthRuntime {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for id in expired {
|
for id in expired {
|
||||||
if let Some((_, pending)) = self.logins.remove(&id) {
|
if let Some((_, pending)) = self.logins.remove(&id)
|
||||||
if let Some(attempt) = pending.attempt {
|
&& let Some(attempt) = pending.attempt
|
||||||
|
{
|
||||||
attempt.failure();
|
attempt.failure();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
self.enrollments
|
self.enrollments
|
||||||
.retain(|_, pending| pending.created.elapsed() < self.pending_ttl);
|
.retain(|_, pending| pending.created.elapsed() < self.pending_ttl);
|
||||||
self.attempts.retain(|_, state| {
|
self.attempts.retain(|_, state| {
|
||||||
|
|
@ -311,13 +311,13 @@ impl PasswordAuthRuntime {
|
||||||
.filter_map(|entry| (entry.user_id == user_id).then_some(*entry.key()))
|
.filter_map(|entry| (entry.user_id == user_id).then_some(*entry.key()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for id in ids {
|
for id in ids {
|
||||||
if let Some((_, pending)) = self.logins.remove(&id) {
|
if let Some((_, pending)) = self.logins.remove(&id)
|
||||||
if let Some(attempt) = pending.attempt {
|
&& let Some(attempt) = pending.attempt
|
||||||
|
{
|
||||||
attempt.cancel();
|
attempt.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
|
|
||||||
|
|
@ -386,16 +386,16 @@ pub async fn reconcile_managed_users(connection: &dyn OmikronClient) {
|
||||||
let _ = pending_operations::remove(operation.user_id);
|
let _ = pending_operations::remove(operation.user_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PendingUserOperationKind::Release if remote_iota_id != Some(local_iota_id) => {
|
PendingUserOperationKind::Release
|
||||||
if iota_storage::users::user_manager::finalize_local_release(
|
if remote_iota_id != Some(local_iota_id)
|
||||||
|
&& iota_storage::users::user_manager::finalize_local_release(
|
||||||
operation.user_id,
|
operation.user_id,
|
||||||
Some(&operation.username),
|
Some(&operation.username),
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok() =>
|
||||||
{
|
{
|
||||||
let _ = pending_operations::remove(operation.user_id);
|
let _ = pending_operations::remove(operation.user_id);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -425,11 +425,12 @@ pub async fn reconcile_managed_users(connection: &dyn OmikronClient) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if should_release {
|
if should_release
|
||||||
if let Err(error) = iota_storage::users::user_manager::finalize_local_release(
|
&& let Err(error) = iota_storage::users::user_manager::finalize_local_release(
|
||||||
user.user_id,
|
user.user_id,
|
||||||
Some(&user.username),
|
Some(&user.username),
|
||||||
) {
|
)
|
||||||
|
{
|
||||||
log!(
|
log!(
|
||||||
"Could not release local user {} after Omega reconciliation: {}",
|
"Could not release local user {} after Omega reconciliation: {}",
|
||||||
user.user_id,
|
user.user_id,
|
||||||
|
|
@ -437,7 +438,6 @@ pub async fn reconcile_managed_users(connection: &dyn OmikronClient) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_release_reconciled_user(
|
fn should_release_reconciled_user(
|
||||||
|
|
@ -598,7 +598,7 @@ pub async fn create_user(
|
||||||
|
|
||||||
let mut bytes = [0u8; 192];
|
let mut bytes = [0u8; 192];
|
||||||
OsRng.fill_bytes(&mut bytes);
|
OsRng.fill_bytes(&mut bytes);
|
||||||
let reset_token = STANDARD.encode(&bytes);
|
let reset_token = STANDARD.encode(bytes);
|
||||||
|
|
||||||
let user_profile = UserProfile::new(
|
let user_profile = UserProfile::new(
|
||||||
user_id,
|
user_id,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue