use base64::{Engine as _, engine::general_purpose::STANDARD};
use pubky_common::session::CookieSessionRecord;
use super::credential::CookieCredential;
use crate::actors::session::core::PubkySession;
#[derive(Debug)]
pub struct CookieSessionView<'a> {
session: &'a PubkySession,
credential: &'a CookieCredential,
}
impl PubkySession {
#[must_use]
pub fn as_cookie(&self) -> Option<CookieSessionView<'_>> {
self.try_downcast_credential::<CookieCredential>()
.map(|c| CookieSessionView::new(self, c))
}
}
impl<'a> CookieSessionView<'a> {
pub(crate) const fn new(session: &'a PubkySession, credential: &'a CookieCredential) -> Self {
Self {
session,
credential,
}
}
#[must_use]
pub fn session_info(&self) -> CookieSessionRecord {
self.credential.cookie_record()
}
#[must_use]
pub fn export(&self) -> String {
let record = self.session_info();
crate::cross_log!(info, "Exporting session for {}", record.public_key());
STANDARD.encode(record.serialize())
}
#[must_use]
pub fn export_secret(&self) -> Option<String> {
let public_key = self.session.info().public_key().z32();
let cookie = self.credential.cookie_secret()?;
crate::cross_log!(info, "Exporting session secret for {}", public_key);
Some(format!("{public_key}:{cookie}"))
}
#[cfg(not(target_arch = "wasm32"))]
pub fn write_secret_file<P: AsRef<std::path::Path>>(
&self,
secret_file_path: P,
) -> std::io::Result<()> {
let token = self.export_secret().ok_or_else(|| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"no cookie secret captured for this session",
)
})?;
let p = secret_file_path.as_ref();
let target = match p.extension().and_then(|e| e.to_str()) {
Some("sess") => p.to_path_buf(),
Some(_) => {
let mut out = p.to_path_buf();
let fname = p.file_name().and_then(|n| n.to_str()).unwrap_or("session");
out.set_file_name(format!("{fname}.sess"));
out
}
None => {
let mut out = p.to_path_buf();
out.set_extension("sess");
out
}
};
std::fs::write(&target, token)?;
crate::cross_log!(
info,
"Wrote session secret for {} to {}",
self.session.info().public_key(),
target.display()
);
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&target, std::fs::Permissions::from_mode(0o600))?;
};
Ok(())
}
}