|
|
|
|
@@ -1,162 +1,575 @@
|
|
|
|
|
//! # Key-value configuration management
|
|
|
|
|
|
|
|
|
|
use strum::{EnumProperty, IntoEnumIterator};
|
|
|
|
|
use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
use strum::IntoEnumIterator;
|
|
|
|
|
use strum_macros::{AsRefStr, Display, EnumDiscriminants, EnumIter, EnumString};
|
|
|
|
|
|
|
|
|
|
use crate::blob::BlobObject;
|
|
|
|
|
use crate::constants::DC_VERSION_STR;
|
|
|
|
|
use crate::context::Context;
|
|
|
|
|
use crate::dc_tools::*;
|
|
|
|
|
use crate::error::Error;
|
|
|
|
|
use crate::job::*;
|
|
|
|
|
use crate::stock::StockMessage;
|
|
|
|
|
|
|
|
|
|
/// The available configuration keys.
|
|
|
|
|
#[derive(
|
|
|
|
|
Debug, Clone, Copy, PartialEq, Eq, Display, EnumString, AsRefStr, EnumIter, EnumProperty,
|
|
|
|
|
)]
|
|
|
|
|
/// The available configuration items.
|
|
|
|
|
///
|
|
|
|
|
/// There is also an enum called `ConfigKey` which has the same enum
|
|
|
|
|
/// variants but does not carry any data.
|
|
|
|
|
#[derive(Debug, Clone, Display, PartialEq, Eq, EnumDiscriminants, EnumProperty, AsRefStr)]
|
|
|
|
|
#[strum(serialize_all = "snake_case")]
|
|
|
|
|
pub enum Config {
|
|
|
|
|
Addr,
|
|
|
|
|
MailServer,
|
|
|
|
|
MailUser,
|
|
|
|
|
MailPw,
|
|
|
|
|
MailPort,
|
|
|
|
|
ImapCertificateChecks,
|
|
|
|
|
SendServer,
|
|
|
|
|
SendUser,
|
|
|
|
|
SendPw,
|
|
|
|
|
SendPort,
|
|
|
|
|
SmtpCertificateChecks,
|
|
|
|
|
ServerFlags,
|
|
|
|
|
#[strum(props(default = "INBOX"))]
|
|
|
|
|
ImapFolder,
|
|
|
|
|
Displayname,
|
|
|
|
|
Selfstatus,
|
|
|
|
|
Selfavatar,
|
|
|
|
|
#[strum(props(default = "0"))]
|
|
|
|
|
BccSelf,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
E2eeEnabled,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
MdnsEnabled,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
InboxWatch,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
SentboxWatch,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
MvboxWatch,
|
|
|
|
|
#[strum(props(default = "1"))]
|
|
|
|
|
MvboxMove,
|
|
|
|
|
#[strum(props(default = "0"))] // also change ShowEmails.default() on changes
|
|
|
|
|
ShowEmails,
|
|
|
|
|
SaveMimeHeaders,
|
|
|
|
|
ConfiguredAddr,
|
|
|
|
|
ConfiguredMailServer,
|
|
|
|
|
ConfiguredMailUser,
|
|
|
|
|
ConfiguredMailPw,
|
|
|
|
|
ConfiguredMailPort,
|
|
|
|
|
ConfiguredMailSecurity,
|
|
|
|
|
ConfiguredImapCertificateChecks,
|
|
|
|
|
ConfiguredSendServer,
|
|
|
|
|
ConfiguredSendUser,
|
|
|
|
|
ConfiguredSendPw,
|
|
|
|
|
ConfiguredSendPort,
|
|
|
|
|
ConfiguredSmtpCertificateChecks,
|
|
|
|
|
ConfiguredServerFlags,
|
|
|
|
|
ConfiguredSendSecurity,
|
|
|
|
|
ConfiguredE2EEEnabled,
|
|
|
|
|
Configured,
|
|
|
|
|
// Deprecated
|
|
|
|
|
#[strum(serialize = "sys.version")]
|
|
|
|
|
SysVersion,
|
|
|
|
|
#[strum(serialize = "sys.msgsize_max_recommended")]
|
|
|
|
|
SysMsgsizeMaxRecommended,
|
|
|
|
|
#[strum(serialize = "sys.config_keys")]
|
|
|
|
|
SysConfigKeys,
|
|
|
|
|
#[strum_discriminants(
|
|
|
|
|
name(ConfigKey),
|
|
|
|
|
derive(Display, EnumString, EnumIter),
|
|
|
|
|
strum(serialize_all = "snake_case")
|
|
|
|
|
)]
|
|
|
|
|
pub enum ConfigItem<'a> {
|
|
|
|
|
Addr(String),
|
|
|
|
|
BccSelf(String),
|
|
|
|
|
Configured(String),
|
|
|
|
|
ConfiguredAddr(String),
|
|
|
|
|
ConfiguredE2EEEnabled(String),
|
|
|
|
|
ConfiguredImapCertificateChecks(String),
|
|
|
|
|
ConfiguredMailPort(String),
|
|
|
|
|
ConfiguredMailPw(String),
|
|
|
|
|
ConfiguredMailSecurity(String),
|
|
|
|
|
ConfiguredMailServer(String),
|
|
|
|
|
ConfiguredMailUser(String),
|
|
|
|
|
ConfiguredSendPort(String),
|
|
|
|
|
ConfiguredSendPw(String),
|
|
|
|
|
ConfiguredSendSecurity(String),
|
|
|
|
|
ConfiguredSendServer(String),
|
|
|
|
|
ConfiguredSendUser(String),
|
|
|
|
|
ConfiguredServerFlags(String),
|
|
|
|
|
ConfiguredSmtpCertificateChecks(String),
|
|
|
|
|
Displayname(String),
|
|
|
|
|
E2eeEnabled(String),
|
|
|
|
|
ImapCertificateChecks(String),
|
|
|
|
|
ImapFolder(String),
|
|
|
|
|
InboxWatch(bool),
|
|
|
|
|
MailPort(String),
|
|
|
|
|
MailPw(String),
|
|
|
|
|
MailServer(String),
|
|
|
|
|
MailUser(String),
|
|
|
|
|
MdnsEnabled(String),
|
|
|
|
|
MvboxMove(String),
|
|
|
|
|
MvboxWatch(String),
|
|
|
|
|
SaveMimeHeaders(String),
|
|
|
|
|
Selfavatar(BlobObject<'a>),
|
|
|
|
|
Selfstatus(String),
|
|
|
|
|
SendPort(String),
|
|
|
|
|
SendPw(String),
|
|
|
|
|
SendServer(String),
|
|
|
|
|
SendUser(String),
|
|
|
|
|
SentboxWatch(String),
|
|
|
|
|
ServerFlags(String),
|
|
|
|
|
ShowEmails(String),
|
|
|
|
|
SmtpCertificateChecks(String),
|
|
|
|
|
SysConfigKeys(String),
|
|
|
|
|
SysMsgsizeMaxRecommended(String),
|
|
|
|
|
SysVersion(String),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
|
/// Get a configuration key. Returns `None` if no value is set, and no default value found.
|
|
|
|
|
pub fn get_config(&self, key: Config) -> Option<String> {
|
|
|
|
|
let value = match key {
|
|
|
|
|
Config::Selfavatar => {
|
|
|
|
|
let rel_path = self.sql.get_raw_config(self, key);
|
|
|
|
|
rel_path.map(|p| dc_get_abs_path(self, &p).to_string_lossy().into_owned())
|
|
|
|
|
}
|
|
|
|
|
Config::SysVersion => Some((&*DC_VERSION_STR).clone()),
|
|
|
|
|
Config::SysMsgsizeMaxRecommended => Some(format!("{}", 24 * 1024 * 1024 / 4 * 3)),
|
|
|
|
|
Config::SysConfigKeys => Some(get_config_keys_string()),
|
|
|
|
|
_ => self.sql.get_raw_config(self, key),
|
|
|
|
|
};
|
|
|
|
|
// Transitional: support the old name for ConfigKey.
|
|
|
|
|
pub type Config = ConfigKey;
|
|
|
|
|
|
|
|
|
|
if value.is_some() {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Default values
|
|
|
|
|
match key {
|
|
|
|
|
Config::Selfstatus => Some(self.stock_str(StockMessage::StatusLine).into_owned()),
|
|
|
|
|
_ => key.get_str("default").map(|s| s.to_string()),
|
|
|
|
|
impl ConfigKey {
|
|
|
|
|
/// Creates a [ConfigKey] from a string.
|
|
|
|
|
///
|
|
|
|
|
/// Use this rather than [ConfigKey::from_str].
|
|
|
|
|
pub fn from_key_str(s: &str) -> Result<ConfigKey, strum::ParseError> {
|
|
|
|
|
match s {
|
|
|
|
|
"sys.config_keys" => Ok(ConfigKey::SysConfigKeys),
|
|
|
|
|
"sys.msgsize_max_recommended" => Ok(ConfigKey::SysMsgsizeMaxRecommended),
|
|
|
|
|
"sys.version" => Ok(ConfigKey::SysVersion),
|
|
|
|
|
_ => ConfigKey::from_str(s),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a string version of the [ConfigKey].
|
|
|
|
|
///
|
|
|
|
|
/// Use this rather than [ConfigKey::to_string].
|
|
|
|
|
pub fn to_key_string(&self) -> String {
|
|
|
|
|
let mut s = self.to_string();
|
|
|
|
|
if s.starts_with("sys_") {
|
|
|
|
|
s = s.replacen("sys_", "sys.", 1);
|
|
|
|
|
}
|
|
|
|
|
s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Default values for configuration options.
|
|
|
|
|
///
|
|
|
|
|
/// These are returned in case there is no value stored in the
|
|
|
|
|
/// database.
|
|
|
|
|
fn default_item<'a>(&self, context: &Context) -> Option<ConfigItem<'a>> {
|
|
|
|
|
match self {
|
|
|
|
|
Self::BccSelf => Some(ConfigItem::BccSelf(String::from("0"))),
|
|
|
|
|
Self::E2eeEnabled => Some(ConfigItem::E2eeEnabled(String::from("1"))),
|
|
|
|
|
Self::ImapFolder => Some(ConfigItem::ImapFolder(String::from("INBOX"))),
|
|
|
|
|
Self::InboxWatch => Some(ConfigItem::InboxWatch(true)),
|
|
|
|
|
Self::MdnsEnabled => Some(ConfigItem::MdnsEnabled(String::from("1"))),
|
|
|
|
|
Self::MvboxMove => Some(ConfigItem::MvboxMove(String::from("1"))),
|
|
|
|
|
Self::MvboxWatch => Some(ConfigItem::MvboxWatch(String::from("1"))),
|
|
|
|
|
Self::Selfstatus => Some(ConfigItem::Selfstatus(
|
|
|
|
|
context.stock_str(StockMessage::StatusLine).into_owned(),
|
|
|
|
|
)),
|
|
|
|
|
Self::SentboxWatch => Some(ConfigItem::SentboxWatch(String::from("1"))),
|
|
|
|
|
Self::ShowEmails => Some(ConfigItem::ShowEmails(String::from("0"))),
|
|
|
|
|
Self::SysConfigKeys => Some(ConfigItem::SysConfigKeys(get_config_keys_string())),
|
|
|
|
|
Self::SysMsgsizeMaxRecommended => Some(ConfigItem::SysMsgsizeMaxRecommended(format!(
|
|
|
|
|
"{}",
|
|
|
|
|
24 * 1024 * 1024 / 4 * 3
|
|
|
|
|
))),
|
|
|
|
|
Self::SysVersion => Some(ConfigItem::SysVersion((&*DC_VERSION_STR).clone())),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> rusqlite::types::ToSql for ConfigItem<'a> {
|
|
|
|
|
fn to_sql(&self) -> rusqlite::Result<rusqlite::types::ToSqlOutput> {
|
|
|
|
|
let sql_obj = match self {
|
|
|
|
|
ConfigItem::Selfavatar(blob) => {
|
|
|
|
|
rusqlite::types::Value::Text(blob.as_name().to_string())
|
|
|
|
|
}
|
|
|
|
|
ConfigItem::InboxWatch(value) => rusqlite::types::Value::Integer(*value as i64),
|
|
|
|
|
ConfigItem::Addr(value)
|
|
|
|
|
| ConfigItem::BccSelf(value)
|
|
|
|
|
| ConfigItem::Configured(value)
|
|
|
|
|
| ConfigItem::ConfiguredAddr(value)
|
|
|
|
|
| ConfigItem::ConfiguredE2EEEnabled(value)
|
|
|
|
|
| ConfigItem::ConfiguredImapCertificateChecks(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailPort(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailPw(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailSecurity(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailServer(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailUser(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendPort(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendPw(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendSecurity(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendServer(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendUser(value)
|
|
|
|
|
| ConfigItem::ConfiguredServerFlags(value)
|
|
|
|
|
| ConfigItem::ConfiguredSmtpCertificateChecks(value)
|
|
|
|
|
| ConfigItem::Displayname(value)
|
|
|
|
|
| ConfigItem::E2eeEnabled(value)
|
|
|
|
|
| ConfigItem::ImapCertificateChecks(value)
|
|
|
|
|
| ConfigItem::ImapFolder(value)
|
|
|
|
|
| ConfigItem::MailPort(value)
|
|
|
|
|
| ConfigItem::MailPw(value)
|
|
|
|
|
| ConfigItem::MailServer(value)
|
|
|
|
|
| ConfigItem::MailUser(value)
|
|
|
|
|
| ConfigItem::MdnsEnabled(value)
|
|
|
|
|
| ConfigItem::MvboxMove(value)
|
|
|
|
|
| ConfigItem::MvboxWatch(value)
|
|
|
|
|
| ConfigItem::SaveMimeHeaders(value)
|
|
|
|
|
| ConfigItem::Selfstatus(value)
|
|
|
|
|
| ConfigItem::SendPort(value)
|
|
|
|
|
| ConfigItem::SendPw(value)
|
|
|
|
|
| ConfigItem::SendServer(value)
|
|
|
|
|
| ConfigItem::SendUser(value)
|
|
|
|
|
| ConfigItem::SentboxWatch(value)
|
|
|
|
|
| ConfigItem::ServerFlags(value)
|
|
|
|
|
| ConfigItem::ShowEmails(value)
|
|
|
|
|
| ConfigItem::SmtpCertificateChecks(value)
|
|
|
|
|
| ConfigItem::SysConfigKeys(value)
|
|
|
|
|
| ConfigItem::SysMsgsizeMaxRecommended(value)
|
|
|
|
|
| ConfigItem::SysVersion(value) => rusqlite::types::Value::Text(value.to_string()),
|
|
|
|
|
};
|
|
|
|
|
let out = rusqlite::types::ToSqlOutput::Owned(sql_obj);
|
|
|
|
|
Ok(out)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
|
/// Gets a configuration option.
|
|
|
|
|
///
|
|
|
|
|
/// If there is no value set in the database returns the default
|
|
|
|
|
/// value from [ConfigKey::default_item]. Any `Sys*` key should
|
|
|
|
|
/// always end up with the default.
|
|
|
|
|
pub fn get_config_item(&self, key: ConfigKey) -> Option<ConfigItem> {
|
|
|
|
|
let res = self.sql.query_row(
|
|
|
|
|
"SELECT value FROM config WHERE keyname=?;",
|
|
|
|
|
params![key.to_key_string()],
|
|
|
|
|
|row| {
|
|
|
|
|
row.get_raw_checked(0)
|
|
|
|
|
.map(|valref| self.sql_raw_to_config_item(key, valref))
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
match res {
|
|
|
|
|
Ok(item) => item,
|
|
|
|
|
Err(Error::Sql(rusqlite::Error::QueryReturnedNoRows)) => key.default_item(self),
|
|
|
|
|
Err(err) => {
|
|
|
|
|
warn!(self, "get_config: Failed SQL query: {}", err);
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is effectively the FromSql impl for ConfigItem, but we
|
|
|
|
|
// need to know the ConfigKey which the trait does not give us.
|
|
|
|
|
fn sql_raw_to_config_item(
|
|
|
|
|
&self,
|
|
|
|
|
key: ConfigKey,
|
|
|
|
|
raw: rusqlite::types::ValueRef,
|
|
|
|
|
) -> Option<ConfigItem> {
|
|
|
|
|
let to_string = |raw: rusqlite::types::ValueRef| -> Option<String> {
|
|
|
|
|
raw.as_str()
|
|
|
|
|
.map_err(|err| {
|
|
|
|
|
warn!(self, "ConfigItem {}; not a string: {}", key, err);
|
|
|
|
|
})
|
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
|
.ok()
|
|
|
|
|
};
|
|
|
|
|
let to_blob = |raw: rusqlite::types::ValueRef| -> Option<BlobObject> {
|
|
|
|
|
// from_path() case because there was a time when
|
|
|
|
|
// rust-core inserted absolute filenames into the database
|
|
|
|
|
// and we want to gracefully recover from this.
|
|
|
|
|
to_string(raw).and_then(|s| {
|
|
|
|
|
BlobObject::from_name(&self, s.clone())
|
|
|
|
|
.or_else(|_| BlobObject::from_path(&self, s))
|
|
|
|
|
.ok()
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
let to_int = |raw: rusqlite::types::ValueRef| -> Option<i64> {
|
|
|
|
|
match raw {
|
|
|
|
|
// Current way this is stored.
|
|
|
|
|
rusqlite::types::ValueRef::Integer(val) => Some(val),
|
|
|
|
|
// Backward compatibility.
|
|
|
|
|
rusqlite::types::ValueRef::Text(val) => std::str::from_utf8(val)
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
warn!(self, "ConfigItem {}; not UTF-8: {}", key, e);
|
|
|
|
|
})
|
|
|
|
|
.ok()
|
|
|
|
|
.and_then(|v| match v.parse::<i64>() {
|
|
|
|
|
Ok(i) => Some(i),
|
|
|
|
|
Err(e) => {
|
|
|
|
|
warn!(self, "ConfigItem {}; not parsed as int: {}", key, e);
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
_ => {
|
|
|
|
|
warn!(self, "ConfigItem {}; bad SQLite type: {:?}", key, raw);
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let to_bool = |raw: rusqlite::types::ValueRef| -> Option<bool> {
|
|
|
|
|
to_int(raw).and_then(|i| match i {
|
|
|
|
|
0 => Some(false),
|
|
|
|
|
1 => Some(true),
|
|
|
|
|
v => {
|
|
|
|
|
warn!(self, "ConfigItem {}; bad bool value: {}", key, v);
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
match key {
|
|
|
|
|
ConfigKey::Addr => to_string(raw).map(|val| ConfigItem::Addr(val)),
|
|
|
|
|
ConfigKey::BccSelf => to_string(raw).map(|val| ConfigItem::BccSelf(val)),
|
|
|
|
|
ConfigKey::Configured => to_string(raw).map(|val| ConfigItem::Configured(val)),
|
|
|
|
|
ConfigKey::ConfiguredAddr => to_string(raw).map(|val| ConfigItem::ConfiguredAddr(val)),
|
|
|
|
|
ConfigKey::ConfiguredE2EEEnabled => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredE2EEEnabled(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredImapCertificateChecks => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredImapCertificateChecks(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailPort => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredMailPort(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailPw => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredMailPw(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailSecurity => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredMailSecurity(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailServer => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredMailServer(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailUser => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredMailUser(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSendPort => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSendPort(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSendPw => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSendPw(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSendSecurity => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSendSecurity(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSendServer => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSendServer(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSendUser => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSendUser(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredServerFlags => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredServerFlags(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredSmtpCertificateChecks => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ConfiguredSmtpCertificateChecks(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::Displayname => to_string(raw).map(|val| ConfigItem::Displayname(val)),
|
|
|
|
|
ConfigKey::E2eeEnabled => to_string(raw).map(|val| ConfigItem::E2eeEnabled(val)),
|
|
|
|
|
ConfigKey::ImapCertificateChecks => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::ImapCertificateChecks(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ImapFolder => to_string(raw).map(|val| ConfigItem::ImapFolder(val)),
|
|
|
|
|
ConfigKey::InboxWatch => to_bool(raw).map(|val| ConfigItem::InboxWatch(val)),
|
|
|
|
|
ConfigKey::MailPort => to_string(raw).map(|val| ConfigItem::MailPort(val)),
|
|
|
|
|
ConfigKey::MailPw => to_string(raw).map(|val| ConfigItem::MailPw(val)),
|
|
|
|
|
ConfigKey::MailServer => to_string(raw).map(|val| ConfigItem::MailServer(val)),
|
|
|
|
|
ConfigKey::MailUser => to_string(raw).map(|val| ConfigItem::MailUser(val)),
|
|
|
|
|
ConfigKey::MdnsEnabled => to_string(raw).map(|val| ConfigItem::MdnsEnabled(val)),
|
|
|
|
|
ConfigKey::MvboxMove => to_string(raw).map(|val| ConfigItem::MvboxMove(val)),
|
|
|
|
|
ConfigKey::MvboxWatch => to_string(raw).map(|val| ConfigItem::MvboxWatch(val)),
|
|
|
|
|
ConfigKey::SaveMimeHeaders => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::SaveMimeHeaders(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::Selfavatar => to_blob(raw).map(|val| ConfigItem::Selfavatar(val)),
|
|
|
|
|
ConfigKey::Selfstatus => to_string(raw).map(|val| ConfigItem::Selfstatus(val)),
|
|
|
|
|
ConfigKey::SendPort => to_string(raw).map(|val| ConfigItem::SendPort(val)),
|
|
|
|
|
ConfigKey::SendPw => to_string(raw).map(|val| ConfigItem::SendPw(val)),
|
|
|
|
|
ConfigKey::SendServer => to_string(raw).map(|val| ConfigItem::SendServer(val)),
|
|
|
|
|
ConfigKey::SendUser => to_string(raw).map(|val| ConfigItem::SendUser(val)),
|
|
|
|
|
ConfigKey::SentboxWatch => to_string(raw).map(|val| ConfigItem::SentboxWatch(val)),
|
|
|
|
|
ConfigKey::ServerFlags => to_string(raw).map(|val| ConfigItem::ServerFlags(val)),
|
|
|
|
|
ConfigKey::ShowEmails => to_string(raw).map(|val| ConfigItem::ShowEmails(val)),
|
|
|
|
|
ConfigKey::SmtpCertificateChecks => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::SmtpCertificateChecks(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::SysConfigKeys => to_string(raw).map(|val| ConfigItem::SysConfigKeys(val)),
|
|
|
|
|
ConfigKey::SysMsgsizeMaxRecommended => {
|
|
|
|
|
to_string(raw).map(|val| ConfigItem::SysMsgsizeMaxRecommended(val))
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::SysVersion => to_string(raw).map(|val| ConfigItem::SysVersion(val)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Stores a configuration item in the database.
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// You can not store any of the [ConfigItem::SysVersion],
|
|
|
|
|
/// [ConfigItem::SysMsgsizemaxrecommended] or
|
|
|
|
|
/// [ConfigItem::SysConfigkeys] variants.
|
|
|
|
|
pub fn set_config_item<'a>(&self, item: ConfigItem<'a>) -> Result<ConfigItem<'a>, Error> {
|
|
|
|
|
match item {
|
|
|
|
|
ConfigItem::SysConfigKeys(_)
|
|
|
|
|
| ConfigItem::SysMsgsizeMaxRecommended(_)
|
|
|
|
|
| ConfigItem::SysVersion(_) => bail!("Can not set config item {}", item),
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
let keyname = ConfigKey::from(&item).to_key_string();
|
|
|
|
|
// Would prefer to use INSERT OR REPLACE but this needs a
|
|
|
|
|
// uniqueness constraint on the keyname column which does not
|
|
|
|
|
// yet exist.
|
|
|
|
|
if self.sql.exists(
|
|
|
|
|
"SELECT value FROM config WHERE keyname=?;",
|
|
|
|
|
params![keyname],
|
|
|
|
|
)? {
|
|
|
|
|
self.sql.execute(
|
|
|
|
|
"UPDATE config SET value=? WHERE keyname=?",
|
|
|
|
|
params![item, keyname],
|
|
|
|
|
)?;
|
|
|
|
|
} else {
|
|
|
|
|
self.sql.execute(
|
|
|
|
|
"INSERT INTO config (keyname, value) VALUES (?, ?)",
|
|
|
|
|
params![keyname, item],
|
|
|
|
|
)?;
|
|
|
|
|
}
|
|
|
|
|
match item {
|
|
|
|
|
ConfigItem::InboxWatch(_) => interrupt_inbox_idle(self, true),
|
|
|
|
|
ConfigItem::SentboxWatch(_) => interrupt_sentbox_idle(self),
|
|
|
|
|
ConfigItem::MvboxWatch(_) => interrupt_mvbox_idle(self),
|
|
|
|
|
_ => (),
|
|
|
|
|
};
|
|
|
|
|
Ok(item)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Deletes a configuration option.
|
|
|
|
|
///
|
|
|
|
|
/// Returns `true` if the option was deleted, `false` if it wasn't
|
|
|
|
|
/// present in the first place.
|
|
|
|
|
pub fn del_config_item(&self, key: ConfigKey) -> Result<bool, Error> {
|
|
|
|
|
match self.sql.execute(
|
|
|
|
|
"DELETE FROM config WHERE keyname=?;",
|
|
|
|
|
params![key.to_string()],
|
|
|
|
|
) {
|
|
|
|
|
Ok(0) => Ok(false),
|
|
|
|
|
Ok(_) => Ok(true),
|
|
|
|
|
Err(err) => Err(err),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Transitional: migrate to get_config_item.
|
|
|
|
|
///
|
|
|
|
|
/// This will migrate to the FFI once nothing in the core uses
|
|
|
|
|
/// this anymore.
|
|
|
|
|
pub fn get_config(&self, key: Config) -> Option<String> {
|
|
|
|
|
if let Some(item) = self.get_config_item(key) {
|
|
|
|
|
let value = match item {
|
|
|
|
|
// Bool values.
|
|
|
|
|
ConfigItem::InboxWatch(value) => format!("{}", value as u32),
|
|
|
|
|
// String values.
|
|
|
|
|
ConfigItem::Addr(value)
|
|
|
|
|
| ConfigItem::BccSelf(value)
|
|
|
|
|
| ConfigItem::Configured(value)
|
|
|
|
|
| ConfigItem::ConfiguredAddr(value)
|
|
|
|
|
| ConfigItem::ConfiguredE2EEEnabled(value)
|
|
|
|
|
| ConfigItem::ConfiguredImapCertificateChecks(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailPort(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailPw(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailSecurity(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailServer(value)
|
|
|
|
|
| ConfigItem::ConfiguredMailUser(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendPort(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendPw(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendSecurity(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendServer(value)
|
|
|
|
|
| ConfigItem::ConfiguredSendUser(value)
|
|
|
|
|
| ConfigItem::ConfiguredServerFlags(value)
|
|
|
|
|
| ConfigItem::ConfiguredSmtpCertificateChecks(value)
|
|
|
|
|
| ConfigItem::Displayname(value)
|
|
|
|
|
| ConfigItem::E2eeEnabled(value)
|
|
|
|
|
| ConfigItem::ImapCertificateChecks(value)
|
|
|
|
|
| ConfigItem::ImapFolder(value)
|
|
|
|
|
| ConfigItem::MailPort(value)
|
|
|
|
|
| ConfigItem::MailPw(value)
|
|
|
|
|
| ConfigItem::MailServer(value)
|
|
|
|
|
| ConfigItem::MailUser(value)
|
|
|
|
|
| ConfigItem::MdnsEnabled(value)
|
|
|
|
|
| ConfigItem::MvboxMove(value)
|
|
|
|
|
| ConfigItem::MvboxWatch(value)
|
|
|
|
|
| ConfigItem::SaveMimeHeaders(value)
|
|
|
|
|
| ConfigItem::Selfstatus(value)
|
|
|
|
|
| ConfigItem::SendPort(value)
|
|
|
|
|
| ConfigItem::SendPw(value)
|
|
|
|
|
| ConfigItem::SendServer(value)
|
|
|
|
|
| ConfigItem::SendUser(value)
|
|
|
|
|
| ConfigItem::SentboxWatch(value)
|
|
|
|
|
| ConfigItem::ServerFlags(value)
|
|
|
|
|
| ConfigItem::ShowEmails(value)
|
|
|
|
|
| ConfigItem::SmtpCertificateChecks(value)
|
|
|
|
|
| ConfigItem::SysConfigKeys(value)
|
|
|
|
|
| ConfigItem::SysMsgsizeMaxRecommended(value)
|
|
|
|
|
| ConfigItem::SysVersion(value) => value,
|
|
|
|
|
// Blob values
|
|
|
|
|
ConfigItem::Selfavatar(blob) => blob.to_abs_path().to_string_lossy().into_owned(),
|
|
|
|
|
};
|
|
|
|
|
Some(value)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Transitional: migrate to get_config_item.
|
|
|
|
|
pub fn get_config_int(&self, key: Config) -> i32 {
|
|
|
|
|
self.get_config(key)
|
|
|
|
|
.and_then(|s| s.parse().ok())
|
|
|
|
|
.unwrap_or_default()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Transitional: migrate to get_config_item.
|
|
|
|
|
pub fn get_config_bool(&self, key: Config) -> bool {
|
|
|
|
|
self.get_config_int(key) != 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Set the given config key.
|
|
|
|
|
/// If `None` is passed as a value the value is cleared and set to the default if there is one.
|
|
|
|
|
///
|
|
|
|
|
/// Transitional: migrate to set_config_item/del_config_item.
|
|
|
|
|
///
|
|
|
|
|
/// If `None` is passed as a value the value is cleared and set to
|
|
|
|
|
/// the default if there is one.
|
|
|
|
|
pub fn set_config(&self, key: Config, value: Option<&str>) -> Result<(), Error> {
|
|
|
|
|
match key {
|
|
|
|
|
Config::Selfavatar if value.is_some() => {
|
|
|
|
|
let blob = BlobObject::create_from_path(&self, value.unwrap())?;
|
|
|
|
|
self.sql.set_raw_config(self, key, Some(blob.as_name()))
|
|
|
|
|
}
|
|
|
|
|
Config::InboxWatch => {
|
|
|
|
|
let ret = self.sql.set_raw_config(self, key, value);
|
|
|
|
|
interrupt_inbox_idle(self, true);
|
|
|
|
|
ret
|
|
|
|
|
}
|
|
|
|
|
Config::SentboxWatch => {
|
|
|
|
|
let ret = self.sql.set_raw_config(self, key, value);
|
|
|
|
|
interrupt_sentbox_idle(self);
|
|
|
|
|
ret
|
|
|
|
|
}
|
|
|
|
|
Config::MvboxWatch => {
|
|
|
|
|
let ret = self.sql.set_raw_config(self, key, value);
|
|
|
|
|
interrupt_mvbox_idle(self);
|
|
|
|
|
ret
|
|
|
|
|
}
|
|
|
|
|
let maybe_val = match key {
|
|
|
|
|
Config::Selfstatus => {
|
|
|
|
|
let def = self.stock_str(StockMessage::StatusLine);
|
|
|
|
|
let val = if value.is_none() || value.unwrap() == def {
|
|
|
|
|
if value.is_none() || value.unwrap() == def {
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
value
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.sql.set_raw_config(self, key, val)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => self.sql.set_raw_config(self, key, value),
|
|
|
|
|
_ => value,
|
|
|
|
|
};
|
|
|
|
|
if let Some(val) = maybe_val {
|
|
|
|
|
let v = val.to_string();
|
|
|
|
|
let item = match key {
|
|
|
|
|
ConfigKey::Addr => ConfigItem::Addr(v),
|
|
|
|
|
ConfigKey::BccSelf => ConfigItem::BccSelf(v),
|
|
|
|
|
ConfigKey::Configured => ConfigItem::Configured(v),
|
|
|
|
|
ConfigKey::ConfiguredAddr => ConfigItem::ConfiguredAddr(v),
|
|
|
|
|
ConfigKey::ConfiguredE2EEEnabled => ConfigItem::ConfiguredE2EEEnabled(v),
|
|
|
|
|
ConfigKey::ConfiguredImapCertificateChecks => {
|
|
|
|
|
ConfigItem::ConfiguredImapCertificateChecks(v)
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::ConfiguredMailPort => ConfigItem::ConfiguredMailPort(v),
|
|
|
|
|
ConfigKey::ConfiguredMailPw => ConfigItem::ConfiguredMailPw(v),
|
|
|
|
|
ConfigKey::ConfiguredMailSecurity => ConfigItem::ConfiguredMailSecurity(v),
|
|
|
|
|
ConfigKey::ConfiguredMailServer => ConfigItem::ConfiguredMailServer(v),
|
|
|
|
|
ConfigKey::ConfiguredMailUser => ConfigItem::ConfiguredMailUser(v),
|
|
|
|
|
ConfigKey::ConfiguredSendPort => ConfigItem::ConfiguredSendPort(v),
|
|
|
|
|
ConfigKey::ConfiguredSendPw => ConfigItem::ConfiguredSendPw(v),
|
|
|
|
|
ConfigKey::ConfiguredSendSecurity => ConfigItem::ConfiguredSendSecurity(v),
|
|
|
|
|
ConfigKey::ConfiguredSendServer => ConfigItem::ConfiguredSendServer(v),
|
|
|
|
|
ConfigKey::ConfiguredSendUser => ConfigItem::ConfiguredSendUser(v),
|
|
|
|
|
ConfigKey::ConfiguredServerFlags => ConfigItem::ConfiguredServerFlags(v),
|
|
|
|
|
ConfigKey::ConfiguredSmtpCertificateChecks => {
|
|
|
|
|
ConfigItem::ConfiguredSmtpCertificateChecks(v)
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::Displayname => ConfigItem::Displayname(v),
|
|
|
|
|
ConfigKey::E2eeEnabled => ConfigItem::E2eeEnabled(v),
|
|
|
|
|
ConfigKey::ImapCertificateChecks => ConfigItem::ImapCertificateChecks(v),
|
|
|
|
|
ConfigKey::ImapFolder => ConfigItem::ImapFolder(v),
|
|
|
|
|
ConfigKey::InboxWatch => {
|
|
|
|
|
let val = match v.parse::<u32>() {
|
|
|
|
|
Ok(0) => false,
|
|
|
|
|
Ok(1) => true,
|
|
|
|
|
_ => bail!("set_config for {}: not a bool: {}", key, v),
|
|
|
|
|
};
|
|
|
|
|
ConfigItem::InboxWatch(val)
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::MailPort => ConfigItem::MailPort(v),
|
|
|
|
|
ConfigKey::MailPw => ConfigItem::MailPw(v),
|
|
|
|
|
ConfigKey::MailServer => ConfigItem::MailServer(v),
|
|
|
|
|
ConfigKey::MailUser => ConfigItem::MailUser(v),
|
|
|
|
|
ConfigKey::MdnsEnabled => ConfigItem::MdnsEnabled(v),
|
|
|
|
|
ConfigKey::MvboxMove => ConfigItem::MvboxMove(v),
|
|
|
|
|
ConfigKey::MvboxWatch => ConfigItem::MvboxWatch(v),
|
|
|
|
|
ConfigKey::SaveMimeHeaders => ConfigItem::SaveMimeHeaders(v),
|
|
|
|
|
ConfigKey::Selfavatar => {
|
|
|
|
|
ConfigItem::Selfavatar(BlobObject::create_from_path(self, v)?)
|
|
|
|
|
}
|
|
|
|
|
ConfigKey::Selfstatus => ConfigItem::Selfstatus(v),
|
|
|
|
|
ConfigKey::SendPort => ConfigItem::SendPort(v),
|
|
|
|
|
ConfigKey::SendPw => ConfigItem::SendPw(v),
|
|
|
|
|
ConfigKey::SendServer => ConfigItem::SendServer(v),
|
|
|
|
|
ConfigKey::SendUser => ConfigItem::SendUser(v),
|
|
|
|
|
ConfigKey::SentboxWatch => ConfigItem::SentboxWatch(v),
|
|
|
|
|
ConfigKey::ServerFlags => ConfigItem::ServerFlags(v),
|
|
|
|
|
ConfigKey::ShowEmails => ConfigItem::ShowEmails(v),
|
|
|
|
|
ConfigKey::SmtpCertificateChecks => ConfigItem::SmtpCertificateChecks(v),
|
|
|
|
|
ConfigKey::SysConfigKeys => ConfigItem::SysConfigKeys(v),
|
|
|
|
|
ConfigKey::SysMsgsizeMaxRecommended => ConfigItem::SysMsgsizeMaxRecommended(v),
|
|
|
|
|
ConfigKey::SysVersion => ConfigItem::SysVersion(v),
|
|
|
|
|
};
|
|
|
|
|
self.set_config_item(item).map(|_| ())
|
|
|
|
|
} else {
|
|
|
|
|
self.del_config_item(key).map(|_| ())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns all available configuration keys concated together.
|
|
|
|
|
fn get_config_keys_string() -> String {
|
|
|
|
|
let keys = Config::iter().fold(String::new(), |mut acc, key| {
|
|
|
|
|
acc += key.as_ref();
|
|
|
|
|
let keys = ConfigKey::iter().fold(String::new(), |mut acc, key| {
|
|
|
|
|
acc += &key.to_key_string();
|
|
|
|
|
acc += " ";
|
|
|
|
|
acc
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
format!(" {} ", keys)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -164,26 +577,78 @@ fn get_config_keys_string() -> String {
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
use std::string::ToString;
|
|
|
|
|
|
|
|
|
|
use crate::test_utils::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_to_string() {
|
|
|
|
|
assert_eq!(Config::MailServer.to_string(), "mail_server");
|
|
|
|
|
assert_eq!(Config::from_str("mail_server"), Ok(Config::MailServer));
|
|
|
|
|
|
|
|
|
|
assert_eq!(Config::SysConfigKeys.to_string(), "sys.config_keys");
|
|
|
|
|
fn test_string_conversions() {
|
|
|
|
|
assert_eq!(ConfigKey::MailServer.to_key_string(), "mail_server");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
Config::from_str("sys.config_keys"),
|
|
|
|
|
Ok(Config::SysConfigKeys)
|
|
|
|
|
ConfigKey::from_key_str("mail_server"),
|
|
|
|
|
Ok(ConfigKey::MailServer)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert_eq!(ConfigKey::SysConfigKeys.to_key_string(), "sys.config_keys");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
ConfigKey::from_key_str("sys.config_keys"),
|
|
|
|
|
Ok(ConfigKey::SysConfigKeys)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_default_prop() {
|
|
|
|
|
assert_eq!(Config::ImapFolder.get_str("default"), Some("INBOX"));
|
|
|
|
|
fn test_sys_config_keys() {
|
|
|
|
|
let t = dummy_context();
|
|
|
|
|
if let Some(ConfigItem::SysConfigKeys(s)) = t.ctx.get_config_item(ConfigKey::SysConfigKeys)
|
|
|
|
|
{
|
|
|
|
|
assert!(s.contains(" sys.msgsize_max_recommended "));
|
|
|
|
|
assert!(s.contains(" sys.version "));
|
|
|
|
|
assert!(s.contains(" imap_folder "));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_config_item() {
|
|
|
|
|
let t = test_context(Some(Box::new(logging_cb)));
|
|
|
|
|
|
|
|
|
|
// An item which has a default.
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::ImapFolder);
|
|
|
|
|
assert_eq!(opt, Some(ConfigItem::ImapFolder("INBOX".into())));
|
|
|
|
|
|
|
|
|
|
// Set a different value.
|
|
|
|
|
t.ctx
|
|
|
|
|
.set_config_item(ConfigItem::ImapFolder("DeltaChat".into()))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::ImapFolder);
|
|
|
|
|
assert_eq!(opt, Some(ConfigItem::ImapFolder("DeltaChat".into())));
|
|
|
|
|
|
|
|
|
|
// Set another value, testing update.
|
|
|
|
|
t.ctx
|
|
|
|
|
.set_config_item(ConfigItem::ImapFolder("Chat".into()))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::ImapFolder);
|
|
|
|
|
assert_eq!(opt, Some(ConfigItem::ImapFolder("Chat".into())));
|
|
|
|
|
|
|
|
|
|
// Reset to the default.
|
|
|
|
|
t.ctx.del_config_item(ConfigKey::ImapFolder).unwrap();
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::ImapFolder);
|
|
|
|
|
assert_eq!(opt, Some(ConfigItem::ImapFolder("INBOX".into())));
|
|
|
|
|
|
|
|
|
|
// An item without default.
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::Addr);
|
|
|
|
|
assert!(opt.is_none());
|
|
|
|
|
|
|
|
|
|
// Set the item.
|
|
|
|
|
t.ctx
|
|
|
|
|
.set_config_item(ConfigItem::Addr("me@example.com".into()))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::Addr);
|
|
|
|
|
assert_eq!(opt, Some(ConfigItem::Addr("me@example.com".into())));
|
|
|
|
|
|
|
|
|
|
// Delete the item.
|
|
|
|
|
t.ctx.del_config_item(ConfigKey::Addr).unwrap();
|
|
|
|
|
let opt = t.ctx.get_config_item(ConfigKey::Addr);
|
|
|
|
|
assert!(opt.is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
@@ -213,4 +678,48 @@ mod tests {
|
|
|
|
|
assert_eq!(avatar_cfg, avatar_src.to_str().map(|s| s.to_string()));
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_config_item_bool() {
|
|
|
|
|
let t = test_context(Some(Box::new(logging_cb)));
|
|
|
|
|
|
|
|
|
|
// Backwards compatible value.
|
|
|
|
|
t.ctx
|
|
|
|
|
.sql
|
|
|
|
|
.execute(
|
|
|
|
|
"INSERT INTO config (keyname, value) VALUES (?, ?)",
|
|
|
|
|
params![ConfigKey::InboxWatch.to_string(), "0"],
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
let item = t.ctx.get_config_item(ConfigKey::InboxWatch).unwrap();
|
|
|
|
|
assert_eq!(item, ConfigItem::InboxWatch(false));
|
|
|
|
|
t.ctx
|
|
|
|
|
.sql
|
|
|
|
|
.execute(
|
|
|
|
|
"UPDATE config SET value=? WHERE keyname=?",
|
|
|
|
|
params!["1", ConfigKey::InboxWatch.to_string()],
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
let item = t.ctx.get_config_item(ConfigKey::InboxWatch).unwrap();
|
|
|
|
|
assert_eq!(item, ConfigItem::InboxWatch(true));
|
|
|
|
|
t.ctx
|
|
|
|
|
.sql
|
|
|
|
|
.execute(
|
|
|
|
|
"UPDATE config SET value=? WHERE keyname=?",
|
|
|
|
|
params!["bad", ConfigKey::InboxWatch.to_string()],
|
|
|
|
|
)
|
|
|
|
|
.unwrap();
|
|
|
|
|
let item = t.ctx.get_config_item(ConfigKey::InboxWatch);
|
|
|
|
|
assert!(item.is_none());
|
|
|
|
|
|
|
|
|
|
// Normal value.
|
|
|
|
|
t.ctx.set_config_item(ConfigItem::InboxWatch(true)).unwrap();
|
|
|
|
|
let item = t.ctx.get_config_item(ConfigKey::InboxWatch).unwrap();
|
|
|
|
|
assert_eq!(item, ConfigItem::InboxWatch(true));
|
|
|
|
|
t.ctx
|
|
|
|
|
.set_config_item(ConfigItem::InboxWatch(false))
|
|
|
|
|
.unwrap();
|
|
|
|
|
let item = t.ctx.get_config_item(ConfigKey::InboxWatch).unwrap();
|
|
|
|
|
assert_eq!(item, ConfigItem::InboxWatch(false));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|