mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
implement backend for the proxy misc configuration
This commit is contained in:
parent
d48bf91ffa
commit
8df429e98f
6 changed files with 265 additions and 1 deletions
|
|
@ -1,9 +1,11 @@
|
|||
mod ignore;
|
||||
mod misc;
|
||||
mod rule;
|
||||
|
||||
use anyhow::Result;
|
||||
use gtk::gio::{ProxyResolver, SimpleProxyResolver};
|
||||
use ignore::Ignore;
|
||||
use misc::Misc;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use rule::Rule;
|
||||
|
|
@ -11,6 +13,7 @@ use rule::Rule;
|
|||
pub struct Proxy {
|
||||
pub ignore: Ignore,
|
||||
pub rule: Rule,
|
||||
pub misc: Misc,
|
||||
}
|
||||
|
||||
impl Proxy {
|
||||
|
|
@ -19,6 +22,7 @@ impl Proxy {
|
|||
pub fn init(database_pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
Ok(Self {
|
||||
ignore: Ignore::init(database_pool, profile_id)?,
|
||||
misc: Misc::init(database_pool, profile_id)?,
|
||||
rule: Rule::init(database_pool, profile_id)?,
|
||||
})
|
||||
}
|
||||
|
|
@ -26,8 +30,9 @@ impl Proxy {
|
|||
// Actions
|
||||
|
||||
pub fn save(&self) -> Result<()> {
|
||||
self.rule.save()?;
|
||||
self.ignore.save()?;
|
||||
self.misc.save()?;
|
||||
self.rule.save()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +68,7 @@ pub fn migrate(tx: &sqlite::Transaction) -> Result<()> {
|
|||
|
||||
// Delegate migration to childs
|
||||
ignore::migrate(tx)?;
|
||||
misc::migrate(tx)?;
|
||||
rule::migrate(tx)?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
81
src/profile/proxy/misc.rs
Normal file
81
src/profile/proxy/misc.rs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
mod database;
|
||||
mod memory;
|
||||
|
||||
use anyhow::Result;
|
||||
use database::Database;
|
||||
use memory::Memory;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use std::{cell::RefCell, collections::HashSet};
|
||||
|
||||
pub struct Misc {
|
||||
database: Database,
|
||||
memory: RefCell<HashSet<Memory>>,
|
||||
}
|
||||
|
||||
impl Misc {
|
||||
// Constructors
|
||||
|
||||
pub fn init(database_pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
let database = Database::init(database_pool, profile_id);
|
||||
|
||||
let rows = database.rows()?;
|
||||
let memory = RefCell::new(HashSet::with_capacity(rows.len()));
|
||||
|
||||
{
|
||||
// build in-memory index...
|
||||
let mut m = memory.borrow_mut();
|
||||
// create initial preset (populate index with the default values)
|
||||
assert!(m.insert(Memory::highlight_request_entry(true)));
|
||||
|
||||
// update values from the DB (if exists)
|
||||
for row in rows {
|
||||
assert!(!m.insert(Memory::from_db_row(&row.key, row.value.as_deref()).unwrap()))
|
||||
// * panics if the DB was malformed or changed unexpectedly
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self { database, memory })
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
pub fn save(&self) -> Result<()> {
|
||||
for k in self.memory.take() {
|
||||
self.database.set(k.into_db_row())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_highlight_request_entry(&self, value: bool) {
|
||||
assert!(
|
||||
self.memory
|
||||
.borrow_mut()
|
||||
.insert(Memory::highlight_request_entry(value)),
|
||||
)
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn is_highlight_request_entry(&self) -> bool {
|
||||
if let Some(k) = self.memory.borrow().iter().next() {
|
||||
match k {
|
||||
Memory::HighlightRequestEntry(v) => return v.is_true(),
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Tools
|
||||
|
||||
pub fn migrate(tx: &sqlite::Transaction) -> Result<()> {
|
||||
// Migrate self components
|
||||
database::init(tx)?;
|
||||
|
||||
// Delegate migration to childs
|
||||
// nothing yet...
|
||||
|
||||
// Success
|
||||
Ok(())
|
||||
}
|
||||
99
src/profile/proxy/misc/database.rs
Normal file
99
src/profile/proxy/misc/database.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
mod row;
|
||||
|
||||
use anyhow::Result;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use row::Row;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Database {
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
profile_id: i64,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
// Constructors
|
||||
|
||||
pub fn init(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Self {
|
||||
Self {
|
||||
pool: pool.clone(),
|
||||
profile_id,
|
||||
}
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
pub fn rows(&self) -> Result<Vec<Row>> {
|
||||
rows(&self.pool.get()?.unchecked_transaction()?, self.profile_id)
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
||||
pub fn set(&self, (key, value): (String, String)) -> Result<i64> {
|
||||
let mut c = self.pool.get()?;
|
||||
let tx = c.transaction()?;
|
||||
let id = set(&tx, self.profile_id, key, value)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_proxy_misc`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
`profile_id` INTEGER NOT NULL,
|
||||
`key` VARCHAR(255) NOT NULL,
|
||||
`value` TEXT NULL,
|
||||
|
||||
FOREIGN KEY (`profile_id`) REFERENCES `profile` (`id`),
|
||||
UNIQUE (`key`)
|
||||
)",
|
||||
[],
|
||||
)?)
|
||||
}
|
||||
|
||||
fn set(tx: &Transaction, profile_id: i64, key: String, value: String) -> Result<i64> {
|
||||
tx.execute(
|
||||
"INSERT INTO `profile_proxy_misc` (
|
||||
`profile_id`,
|
||||
`key`,
|
||||
`value`
|
||||
) VALUES (?, ?, ?) ON CONFLICT (`key`) DO UPDATE SET `value` = `excluded`.`value`",
|
||||
(profile_id, key, value),
|
||||
)?;
|
||||
Ok(tx.last_insert_rowid())
|
||||
}
|
||||
|
||||
fn rows(tx: &Transaction, profile_id: i64) -> Result<Vec<Row>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`profile_id`,
|
||||
`key`,
|
||||
`value`
|
||||
|
||||
FROM `profile_proxy_misc`
|
||||
WHERE `profile_id` = ?",
|
||||
)?;
|
||||
|
||||
let result = stmt.query_map([profile_id], |row| {
|
||||
Ok(Row {
|
||||
//id: row.get(0)?,
|
||||
//profile_id: row.get(1)?,
|
||||
key: row.get(2)?,
|
||||
value: row.get(3)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
let mut rows = Vec::new();
|
||||
|
||||
for r in result {
|
||||
let row = r?;
|
||||
rows.push(row);
|
||||
}
|
||||
|
||||
Ok(rows)
|
||||
}
|
||||
6
src/profile/proxy/misc/database/row.rs
Normal file
6
src/profile/proxy/misc/database/row.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
pub struct Row {
|
||||
//pub id: i64,
|
||||
//pub profile_id: i64,
|
||||
pub key: String,
|
||||
pub value: Option<String>,
|
||||
}
|
||||
37
src/profile/proxy/misc/memory.rs
Normal file
37
src/profile/proxy/misc/memory.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
mod bool;
|
||||
use bool::Bool;
|
||||
|
||||
// Shared values
|
||||
|
||||
const HIGHLIGHT_REQUEST_ENTRY: &str = "highlight_request_entry";
|
||||
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
pub enum Memory {
|
||||
HighlightRequestEntry(Bool),
|
||||
}
|
||||
|
||||
impl Memory {
|
||||
// Constructors
|
||||
|
||||
pub fn from_db_row(key: &str, value: Option<&str>) -> Option<Self> {
|
||||
if key == HIGHLIGHT_REQUEST_ENTRY {
|
||||
Some(Self::HighlightRequestEntry(Bool::from_db_value(value)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn highlight_request_entry(value: bool) -> Self {
|
||||
Memory::HighlightRequestEntry(Bool::from(value))
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
pub fn into_db_row(self) -> (String, String) {
|
||||
match self {
|
||||
Self::HighlightRequestEntry(value) => {
|
||||
(HIGHLIGHT_REQUEST_ENTRY.to_string(), value.into_db_value())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
src/profile/proxy/misc/memory/bool.rs
Normal file
35
src/profile/proxy/misc/memory/bool.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
const TRUE: &str = "1";
|
||||
const FALSE: &str = "0";
|
||||
|
||||
#[derive(Eq, Hash, PartialEq, Default)]
|
||||
pub enum Bool {
|
||||
True,
|
||||
#[default]
|
||||
False,
|
||||
}
|
||||
|
||||
impl Bool {
|
||||
pub fn from(value: bool) -> Self {
|
||||
if value { Self::True } else { Self::False }
|
||||
}
|
||||
|
||||
pub fn from_db_value(key: Option<&str>) -> Self {
|
||||
if key.is_some_and(|k| k == TRUE) {
|
||||
Self::True
|
||||
} else {
|
||||
Self::False
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_db_value(self) -> String {
|
||||
match self {
|
||||
Self::True => TRUE,
|
||||
Self::False => FALSE,
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn is_true(&self) -> bool {
|
||||
matches!(self, Self::True)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue