use crate::{
crypto::AeadPack,
encoding::{decode_uuid, encoding_error},
events::{AccountEvent, DeviceEvent, EventKind, LogEvent, WriteEvent},
VaultCommit, VaultFlags,
};
#[cfg(feature = "files")]
use crate::{events::FileEvent, SecretPath};
use std::io::{Error, ErrorKind, Result};
use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
use async_trait::async_trait;
use binary_stream::futures::{
BinaryReader, BinaryWriter, Decodable, Encodable,
};
#[async_trait]
impl Encodable for EventKind {
async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
&self,
writer: &mut BinaryWriter<W>,
) -> Result<()> {
let value: u16 = self.into();
writer.write_u16(value).await?;
Ok(())
}
}
#[async_trait]
impl Decodable for EventKind {
async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
&mut self,
reader: &mut BinaryReader<R>,
) -> Result<()> {
let op = reader.read_u16().await?;
*self = op.try_into().map_err(|_| {
Error::new(ErrorKind::Other, format!("unknown event kind {}", op))
})?;
Ok(())
}
}
#[async_trait]
impl Encodable for WriteEvent {
async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
&self,
writer: &mut BinaryWriter<W>,
) -> Result<()> {
let op = self.event_kind();
op.encode(&mut *writer).await?;
match self {
WriteEvent::Noop => {
panic!("attempt to encode a noop")
}
WriteEvent::CreateVault(vault) => {
writer.write_u32(vault.len() as u32).await?;
writer.write_bytes(vault).await?;
}
WriteEvent::SetVaultName(name) => {
writer.write_string(name).await?;
}
WriteEvent::SetVaultFlags(flags) => {
writer.write_u64(flags.bits()).await?;
}
WriteEvent::SetVaultMeta(meta) => {
meta.encode(&mut *writer).await?;
}
WriteEvent::CreateSecret(uuid, value) => {
writer.write_bytes(uuid.as_bytes()).await?;
value.encode(&mut *writer).await?;
}
WriteEvent::UpdateSecret(uuid, value) => {
writer.write_bytes(uuid.as_bytes()).await?;
value.encode(&mut *writer).await?;
}
WriteEvent::DeleteSecret(uuid) => {
writer.write_bytes(uuid.as_bytes()).await?;
}
}
Ok(())
}
}
#[async_trait]
impl Decodable for WriteEvent {
async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
&mut self,
reader: &mut BinaryReader<R>,
) -> Result<()> {
let mut op: EventKind = Default::default();
op.decode(&mut *reader).await?;
match op {
EventKind::Noop => panic!("attempt to decode a noop"),
EventKind::CreateVault => {
let length = reader.read_u32().await?;
let buffer = reader.read_bytes(length as usize).await?;
*self = WriteEvent::CreateVault(buffer);
}
EventKind::SetVaultName => {
let name = reader.read_string().await?;
*self = WriteEvent::SetVaultName(name);
}
EventKind::SetVaultFlags => {
let flags = reader.read_u64().await?;
let flags =
VaultFlags::from_bits(flags).ok_or_else(|| {
Error::new(
ErrorKind::Other,
format!("invalid vault flags {}", flags),
)
})?;
*self = WriteEvent::SetVaultFlags(flags);
}
EventKind::SetVaultMeta => {
let mut aead_pack: AeadPack = Default::default();
aead_pack.decode(&mut *reader).await?;
*self = WriteEvent::SetVaultMeta(aead_pack);
}
EventKind::CreateSecret => {
let id = decode_uuid(&mut *reader).await?;
let mut commit: VaultCommit = Default::default();
commit.decode(&mut *reader).await?;
*self = WriteEvent::CreateSecret(id, commit);
}
EventKind::UpdateSecret => {
let id = decode_uuid(&mut *reader).await?;
let mut commit: VaultCommit = Default::default();
commit.decode(&mut *reader).await?;
*self = WriteEvent::UpdateSecret(id, commit);
}
EventKind::DeleteSecret => {
let id = decode_uuid(&mut *reader).await?;
*self = WriteEvent::DeleteSecret(id);
}
_ => {
return Err(Error::new(
ErrorKind::Other,
format!("unknown event kind {}", op),
));
}
}
Ok(())
}
}
#[async_trait]
impl Encodable for AccountEvent {
async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
&self,
writer: &mut BinaryWriter<W>,
) -> Result<()> {
let op = self.event_kind();
op.encode(&mut *writer).await?;
match self {
AccountEvent::Noop => panic!("attempt to encode a noop"),
AccountEvent::RenameAccount(name) => {
writer.write_string(name).await?;
}
AccountEvent::UpdateIdentity(buffer) => {
writer.write_u32(buffer.len() as u32).await?;
writer.write_bytes(buffer).await?;
}
AccountEvent::UpdateFolder(id, buffer)
| AccountEvent::CompactFolder(id, buffer)
| AccountEvent::ChangeFolderPassword(id, buffer)
| AccountEvent::CreateFolder(id, buffer) => {
writer.write_bytes(id.as_bytes()).await?;
writer.write_u32(buffer.len() as u32).await?;
writer.write_bytes(buffer).await?;
}
AccountEvent::RenameFolder(id, name) => {
writer.write_bytes(id.as_bytes()).await?;
writer.write_string(name).await?;
}
AccountEvent::DeleteFolder(id) => {
writer.write_bytes(id.as_bytes()).await?;
}
}
Ok(())
}
}
#[async_trait]
impl Decodable for AccountEvent {
async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
&mut self,
reader: &mut BinaryReader<R>,
) -> Result<()> {
let mut op: EventKind = Default::default();
op.decode(&mut *reader).await?;
match op {
EventKind::Noop => panic!("attempt to decode a noop"),
EventKind::RenameAccount => {
*self =
AccountEvent::RenameAccount(reader.read_string().await?);
}
EventKind::UpdateIdentity => {
let len = reader.read_u32().await?;
let buffer = reader.read_bytes(len as usize).await?;
*self = AccountEvent::UpdateIdentity(buffer)
}
EventKind::CreateVault => {
let id = decode_uuid(&mut *reader).await?;
let len = reader.read_u32().await?;
let buffer = reader.read_bytes(len as usize).await?;
*self = AccountEvent::CreateFolder(id, buffer)
}
EventKind::ChangePassword => {
let id = decode_uuid(&mut *reader).await?;
let len = reader.read_u32().await?;
let buffer = reader.read_bytes(len as usize).await?;
*self = AccountEvent::ChangeFolderPassword(id, buffer)
}
EventKind::UpdateVault => {
let id = decode_uuid(&mut *reader).await?;
let len = reader.read_u32().await?;
let buffer = reader.read_bytes(len as usize).await?;
*self = AccountEvent::UpdateFolder(id, buffer)
}
EventKind::CompactVault => {
let id = decode_uuid(&mut *reader).await?;
let len = reader.read_u32().await?;
let buffer = reader.read_bytes(len as usize).await?;
*self = AccountEvent::CompactFolder(id, buffer)
}
EventKind::SetVaultName => {
let id = decode_uuid(&mut *reader).await?;
let name = reader.read_string().await?;
*self = AccountEvent::RenameFolder(id, name);
}
EventKind::DeleteVault => {
let id = decode_uuid(&mut *reader).await?;
*self = AccountEvent::DeleteFolder(id);
}
_ => {
return Err(Error::new(
ErrorKind::Other,
format!("unknown account event kind {}", op),
));
}
}
Ok(())
}
}
#[async_trait]
impl Encodable for DeviceEvent {
async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
&self,
writer: &mut BinaryWriter<W>,
) -> Result<()> {
let op = self.event_kind();
op.encode(&mut *writer).await?;
match self {
DeviceEvent::Noop => panic!("attempt to encode a noop"),
DeviceEvent::Trust(device) => {
let buf = serde_json::to_vec(device)?;
writer.write_u32(buf.len() as u32).await?;
writer.write_bytes(&buf).await?;
}
DeviceEvent::Revoke(public_key) => {
writer.write_bytes(public_key.as_ref()).await?;
}
}
Ok(())
}
}
#[async_trait]
impl Decodable for DeviceEvent {
async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
&mut self,
reader: &mut BinaryReader<R>,
) -> Result<()> {
use crate::device::{DevicePublicKey, TrustedDevice};
let mut op: EventKind = Default::default();
op.decode(&mut *reader).await?;
match op {
EventKind::Noop => panic!("attempt to decode a noop"),
EventKind::TrustDevice => {
let len = reader.read_u32().await?;
let buf = reader.read_bytes(len as usize).await?;
let device: TrustedDevice = serde_json::from_slice(&buf)?;
*self = DeviceEvent::Trust(device);
}
EventKind::RevokeDevice => {
let public_key: [u8; DevicePublicKey::SIZE] = reader
.read_bytes(DevicePublicKey::SIZE)
.await?
.as_slice()
.try_into()
.map_err(encoding_error)?;
*self = DeviceEvent::Revoke(public_key.into());
}
_ => {
return Err(Error::new(
ErrorKind::Other,
format!("unknown device event kind {}", op),
));
}
}
Ok(())
}
}
#[cfg(feature = "files")]
#[async_trait]
impl Encodable for FileEvent {
async fn encode<W: AsyncWrite + AsyncSeek + Unpin + Send>(
&self,
writer: &mut BinaryWriter<W>,
) -> Result<()> {
let op = self.event_kind();
op.encode(&mut *writer).await?;
match self {
FileEvent::Noop => panic!("attempt to encode a noop"),
FileEvent::CreateFile(owner, name)
| FileEvent::DeleteFile(owner, name) => {
writer.write_bytes(owner.0.as_bytes()).await?;
writer.write_bytes(owner.1.as_bytes()).await?;
writer.write_bytes(name.as_ref()).await?;
}
FileEvent::MoveFile { name, from, dest } => {
writer.write_bytes(name.as_ref()).await?;
writer.write_bytes(from.0.as_bytes()).await?;
writer.write_bytes(from.1.as_bytes()).await?;
writer.write_bytes(dest.0.as_bytes()).await?;
writer.write_bytes(dest.1.as_bytes()).await?;
}
}
Ok(())
}
}
#[cfg(feature = "files")]
#[async_trait]
impl Decodable for FileEvent {
async fn decode<R: AsyncRead + AsyncSeek + Unpin + Send>(
&mut self,
reader: &mut BinaryReader<R>,
) -> Result<()> {
let mut op: EventKind = Default::default();
op.decode(&mut *reader).await?;
match op {
EventKind::Noop => panic!("attempt to decode a noop"),
EventKind::CreateFile => {
let folder_id = decode_uuid(&mut *reader).await?;
let secret_id = decode_uuid(&mut *reader).await?;
let name = reader.read_bytes(32).await?;
let name: [u8; 32] =
name.as_slice().try_into().map_err(encoding_error)?;
*self = FileEvent::CreateFile(
SecretPath(folder_id, secret_id),
name.into(),
)
}
EventKind::DeleteFile => {
let folder_id = decode_uuid(&mut *reader).await?;
let secret_id = decode_uuid(&mut *reader).await?;
let name = reader.read_bytes(32).await?;
let name: [u8; 32] =
name.as_slice().try_into().map_err(encoding_error)?;
*self = FileEvent::DeleteFile(
SecretPath(folder_id, secret_id),
name.into(),
)
}
EventKind::MoveFile => {
let name = reader.read_bytes(32).await?;
let name: [u8; 32] =
name.as_slice().try_into().map_err(encoding_error)?;
let from = SecretPath(
decode_uuid(&mut *reader).await?,
decode_uuid(&mut *reader).await?,
);
let dest = SecretPath(
decode_uuid(&mut *reader).await?,
decode_uuid(&mut *reader).await?,
);
*self = FileEvent::MoveFile {
name: name.into(),
from,
dest,
}
}
_ => {
return Err(Error::new(
ErrorKind::Other,
format!("unknown file event kind {}", op),
));
}
}
Ok(())
}
}