Store cookie jars in euph vault

This commit is contained in:
Joscha 2022-07-24 18:08:45 +02:00
parent 282609916a
commit 7d32a7ebe0
5 changed files with 117 additions and 16 deletions

11
Cargo.lock generated
View file

@ -155,6 +155,16 @@ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
[[package]]
name = "cookie"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
dependencies = [
"time",
"version_check",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.3" version = "0.9.3"
@ -178,6 +188,7 @@ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
"clap", "clap",
"cookie",
"crossterm", "crossterm",
"directories", "directories",
"edit", "edit",

View file

@ -22,6 +22,7 @@ thiserror = "1.0.31"
tokio = { version = "1.20.0", features = ["full"] } tokio = { version = "1.20.0", features = ["full"] }
unicode-segmentation = "1.9.0" unicode-segmentation = "1.9.0"
unicode-width = "0.1.9" unicode-width = "0.1.9"
cookie = "0.16.0"
[dependencies.time] [dependencies.time]
version = "0.3.11" version = "0.3.11"

View file

@ -19,7 +19,7 @@ enum Request {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Vault { pub struct Vault {
tx: mpsc::UnboundedSender<Request>, pub(self) tx: mpsc::UnboundedSender<Request>,
} }
impl Vault { impl Vault {
@ -37,7 +37,7 @@ impl Vault {
pub fn euph(&self, room: String) -> EuphVault { pub fn euph(&self, room: String) -> EuphVault {
EuphVault { EuphVault {
tx: self.tx.clone(), vault: self.clone(),
room, room,
} }
} }

View file

@ -1,10 +1,12 @@
use std::mem; use std::mem;
use std::str::FromStr;
use async_trait::async_trait; use async_trait::async_trait;
use cookie::{Cookie, CookieJar};
use rusqlite::types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef}; use rusqlite::types::{FromSql, FromSqlError, ToSqlOutput, Value, ValueRef};
use rusqlite::{named_params, params, Connection, OptionalExtension, ToSql, Transaction}; use rusqlite::{named_params, params, Connection, OptionalExtension, ToSql, Transaction};
use time::OffsetDateTime; use time::OffsetDateTime;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::oneshot;
use toss::styled::Styled; use toss::styled::Styled;
use crate::euph; use crate::euph;
@ -85,6 +87,19 @@ impl From<EuphRequest> for Request {
} }
impl Vault { impl Vault {
pub async fn euph_cookies(&self) -> CookieJar {
// TODO vault::Error
let (tx, rx) = oneshot::channel();
let request = EuphRequest::GetCookies { result: tx };
let _ = self.tx.send(request.into());
rx.await.unwrap()
}
pub async fn set_euph_cookies(&self, cookies: CookieJar) {
let request = EuphRequest::SetCookies { cookies };
let _ = self.tx.send(request.into());
}
pub async fn euph_rooms(&self) -> Vec<String> { pub async fn euph_rooms(&self) -> Vec<String> {
// TODO vault::Error // TODO vault::Error
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
@ -96,11 +111,15 @@ impl Vault {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EuphVault { pub struct EuphVault {
pub(super) tx: mpsc::UnboundedSender<Request>, pub(super) vault: Vault,
pub(super) room: String, pub(super) room: String,
} }
impl EuphVault { impl EuphVault {
pub fn vault(&self) -> &Vault {
&self.vault
}
pub fn room(&self) -> &str { pub fn room(&self) -> &str {
&self.room &self.room
} }
@ -110,12 +129,12 @@ impl EuphVault {
room: self.room.clone(), room: self.room.clone(),
time, time,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub fn delete(self) { pub fn delete(self) {
let request = EuphRequest::Delete { room: self.room }; let request = EuphRequest::Delete { room: self.room };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub fn add_message(&self, msg: Message, prev_msg: Option<Snowflake>) { pub fn add_message(&self, msg: Message, prev_msg: Option<Snowflake>) {
@ -124,7 +143,7 @@ impl EuphVault {
msg, msg,
prev_msg, prev_msg,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub fn add_messages(&self, msgs: Vec<Message>, next_msg: Option<Snowflake>) { pub fn add_messages(&self, msgs: Vec<Message>, next_msg: Option<Snowflake>) {
@ -133,7 +152,7 @@ impl EuphVault {
msgs, msgs,
next_msg, next_msg,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
} }
pub async fn last_span(&self) -> Option<(Option<Snowflake>, Option<Snowflake>)> { pub async fn last_span(&self) -> Option<(Option<Snowflake>, Option<Snowflake>)> {
@ -143,7 +162,7 @@ impl EuphVault {
room: self.room.clone(), room: self.room.clone(),
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
} }
@ -158,7 +177,7 @@ impl MsgStore<EuphMsg> for EuphVault {
id: *id, id: *id,
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
@ -170,7 +189,7 @@ impl MsgStore<EuphMsg> for EuphVault {
root: *root, root: *root,
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
@ -182,7 +201,7 @@ impl MsgStore<EuphMsg> for EuphVault {
root: *root, root: *root,
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
@ -194,7 +213,7 @@ impl MsgStore<EuphMsg> for EuphVault {
root: *root, root: *root,
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
@ -205,7 +224,7 @@ impl MsgStore<EuphMsg> for EuphVault {
room: self.room.clone(), room: self.room.clone(),
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
@ -216,12 +235,22 @@ impl MsgStore<EuphMsg> for EuphVault {
room: self.room.clone(), room: self.room.clone(),
result: tx, result: tx,
}; };
let _ = self.tx.send(request.into()); let _ = self.vault.tx.send(request.into());
rx.await.unwrap() rx.await.unwrap()
} }
} }
pub(super) enum EuphRequest { pub(super) enum EuphRequest {
/////////////
// Cookies //
/////////////
GetCookies {
result: oneshot::Sender<CookieJar>,
},
SetCookies {
cookies: CookieJar,
},
/////////// ///////////
// Rooms // // Rooms //
/////////// ///////////
@ -286,6 +315,8 @@ pub(super) enum EuphRequest {
impl EuphRequest { impl EuphRequest {
pub(super) fn perform(self, conn: &mut Connection) { pub(super) fn perform(self, conn: &mut Connection) {
let result = match self { let result = match self {
EuphRequest::GetCookies { result } => Self::get_cookies(conn, result),
EuphRequest::SetCookies { cookies } => Self::set_cookies(conn, cookies),
EuphRequest::GetRooms { result } => Self::get_rooms(conn, result), EuphRequest::GetRooms { result } => Self::get_rooms(conn, result),
EuphRequest::Join { room, time } => Self::join(conn, room, time), EuphRequest::Join { room, time } => Self::join(conn, room, time),
EuphRequest::Delete { room } => Self::delete(conn, room), EuphRequest::Delete { room } => Self::delete(conn, room),
@ -324,6 +355,54 @@ impl EuphRequest {
} }
} }
fn get_cookies(
conn: &mut Connection,
result: oneshot::Sender<CookieJar>,
) -> rusqlite::Result<()> {
let cookies = conn
.prepare(
"
SELECT cookie
FROM euph_cookies
",
)?
.query_map([], |row| {
let cookie_str: String = row.get(0)?;
Ok(Cookie::from_str(&cookie_str).expect("cookie in db is valid"))
})?
.collect::<rusqlite::Result<Vec<_>>>()?;
let mut cookie_jar = CookieJar::new();
for cookie in cookies {
cookie_jar.add_original(cookie);
}
let _ = result.send(cookie_jar);
Ok(())
}
fn set_cookies(conn: &mut Connection, cookies: CookieJar) -> rusqlite::Result<()> {
let tx = conn.transaction()?;
// Since euphoria sets all cookies on every response, we can just delete
// all previous cookies.
tx.execute_batch("DELETE FROM euph_cookies")?;
let mut insert_cookie = tx.prepare(
"
INSERT INTO euph_cookies (cookie)
VALUES (?)
",
)?;
for cookie in cookies.iter() {
insert_cookie.execute([format!("{cookie}")])?;
}
drop(insert_cookie);
tx.commit()?;
Ok(())
}
fn get_rooms( fn get_rooms(
conn: &mut Connection, conn: &mut Connection,
result: oneshot::Sender<Vec<String>>, result: oneshot::Sender<Vec<String>>,

View file

@ -16,7 +16,7 @@ pub fn migrate(conn: &mut Connection) -> rusqlite::Result<()> {
tx.commit() tx.commit()
} }
const MIGRATIONS: [fn(&mut Transaction) -> rusqlite::Result<()>; 1] = [m1]; const MIGRATIONS: [fn(&mut Transaction) -> rusqlite::Result<()>; 2] = [m1, m2];
fn m1(tx: &mut Transaction) -> rusqlite::Result<()> { fn m1(tx: &mut Transaction) -> rusqlite::Result<()> {
tx.execute_batch( tx.execute_batch(
@ -75,3 +75,13 @@ fn m1(tx: &mut Transaction) -> rusqlite::Result<()> {
", ",
) )
} }
fn m2(tx: &mut Transaction) -> rusqlite::Result<()> {
tx.execute_batch(
"
CREATE TABLE euph_cookies (
cookie TEXT NOT NULL
) STRICT;
",
)
}