use postcard::{from_bytes, to_allocvec};
use serde::{Deserialize, Serialize};
extern crate alloc;
use alloc::vec::Vec;
use crate::{
capabilities::{Capabilities, Capability},
crypto::PublicKey,
timestamp::Timestamp,
};
#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
pub struct SessionInfo {
version: usize,
public_key: PublicKey,
created_at: u64,
name: String,
user_agent: String,
capabilities: Vec<Capability>,
}
impl SessionInfo {
pub fn new(
public_key: &PublicKey,
capabilities: Capabilities,
user_agent: Option<String>,
) -> Self {
Self {
version: 0,
public_key: public_key.clone(),
created_at: Timestamp::now().as_u64(),
capabilities: capabilities.into(),
user_agent: user_agent.as_deref().unwrap_or("").to_string(),
name: user_agent.as_deref().unwrap_or("").to_string(),
}
}
pub fn public_key(&self) -> &PublicKey {
&self.public_key
}
pub fn capabilities(&self) -> &[Capability] {
&self.capabilities
}
pub fn created_at(&self) -> u64 {
self.created_at
}
pub fn set_created_at(&mut self, created_at: u64) -> &mut Self {
self.created_at = created_at;
self
}
pub fn set_capabilities(&mut self, capabilities: Capabilities) -> &mut Self {
self.capabilities = capabilities.into();
self
}
pub fn serialize(&self) -> Vec<u8> {
to_allocvec(self).expect("SessionInfo::serialize")
}
pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
if bytes.is_empty() {
return Err(Error::EmptyPayload);
}
if bytes[0] > 0 {
return Err(Error::UnknownVersion);
}
Ok(from_bytes(bytes)?)
}
}
#[derive(thiserror::Error, Debug, PartialEq)]
pub enum Error {
#[error("Empty payload")]
EmptyPayload,
#[error("Unknown version")]
UnknownVersion,
#[error(transparent)]
Parsing(#[from] postcard::Error),
}
#[cfg(test)]
mod tests {
use crate::{capabilities::Capability, crypto::Keypair};
use super::*;
#[test]
fn serialize() {
let keypair = Keypair::from_secret(&[0; 32]);
let public_key = keypair.public_key();
let capabilities = Capabilities::builder().cap(Capability::root()).finish();
let session = SessionInfo {
user_agent: "foo".to_string(),
capabilities: capabilities.into(),
created_at: 0,
public_key,
version: 0,
name: "".to_string(),
};
let serialized = session.serialize();
assert_eq!(
serialized,
[
0, 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101,
50, 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41, 0, 0, 3, 102,
111, 111, 1, 4, 47, 58, 114, 119
]
);
let deserialized = SessionInfo::deserialize(&serialized).unwrap();
assert_eq!(deserialized, session)
}
#[test]
fn deserialize() {
let result = SessionInfo::deserialize(&[]);
assert_eq!(result, Err(Error::EmptyPayload));
}
}