secret: Serialize secret as JSON
MessagePack creates issues with Secret Service providers that expect a valid string. We don't really care about saving a few bytes when storing secrets.
This commit is contained in:
parent
d534071ad2
commit
2e86784161
1 changed files with 39 additions and 43 deletions
|
@ -13,14 +13,14 @@ use ruma::{DeviceId, OwnedDeviceId, OwnedUserId, UserId};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::error::Error as JsonError;
|
||||
use thiserror::Error;
|
||||
use tracing::{debug, error, warn};
|
||||
use tracing::{debug, error, info};
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
application::AppProfile, gettext_f, prelude::*, spawn_tokio, utils::matrix, APP_ID, PROFILE,
|
||||
};
|
||||
|
||||
pub const CURRENT_VERSION: u8 = 4;
|
||||
pub const CURRENT_VERSION: u8 = 5;
|
||||
const SCHEMA_ATTRIBUTE: &str = "xdg:schema";
|
||||
|
||||
static DATA_PATH: Lazy<PathBuf> = Lazy::new(|| {
|
||||
|
@ -275,21 +275,21 @@ impl StoredSession {
|
|||
};
|
||||
let secret = match item.secret().await {
|
||||
Ok(secret) => {
|
||||
if version == 0 {
|
||||
match Secret::from_utf8(&secret) {
|
||||
if version <= 4 {
|
||||
match rmp_serde::from_slice::<Secret>(&secret) {
|
||||
Ok(secret) => secret,
|
||||
Err(error) => {
|
||||
error!("Could not parse secret in stored session: {error:?}");
|
||||
error!("Could not parse secret in stored session: {error}");
|
||||
return Err(SecretError::Invalid(gettext(
|
||||
"Malformed secret in stored session",
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match rmp_serde::from_slice::<Secret>(&secret) {
|
||||
match serde_json::from_slice(&secret) {
|
||||
Ok(secret) => secret,
|
||||
Err(error) => {
|
||||
error!("Could not parse secret in stored session: {error}");
|
||||
error!("Could not parse secret in stored session: {error:?}");
|
||||
return Err(SecretError::Invalid(gettext(
|
||||
"Malformed secret in stored session",
|
||||
)));
|
||||
|
@ -407,7 +407,7 @@ impl StoredSession {
|
|||
|
||||
let attrs = self.attributes();
|
||||
let attributes = attrs.iter().map(|(k, v)| (*k, v.as_ref())).collect();
|
||||
let secret = rmp_serde::to_vec_named(&self.secret).unwrap();
|
||||
let secret = serde_json::to_string(&self.secret).unwrap();
|
||||
|
||||
keyring
|
||||
.create_item(
|
||||
|
@ -478,34 +478,30 @@ impl StoredSession {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Migrate this session to version 4.
|
||||
///
|
||||
/// This implies moving the database under Fractal's directory.
|
||||
pub async fn migrate_to_v4(&mut self, item: Item) {
|
||||
warn!(
|
||||
"Session {} with version {} found for user {}, migrating to version 4…",
|
||||
self.id(),
|
||||
self.version,
|
||||
self.user_id,
|
||||
);
|
||||
/// Migrate this session to the current version.
|
||||
pub async fn apply_migrations(&mut self, item: Item) {
|
||||
if self.version < 4 {
|
||||
info!("Migrating to version 4…");
|
||||
|
||||
let target_path = DATA_PATH.join(self.id());
|
||||
let target_path = DATA_PATH.join(self.id());
|
||||
|
||||
if self.path != target_path {
|
||||
debug!("Moving database to: {}", target_path.to_string_lossy());
|
||||
if self.path != target_path {
|
||||
debug!("Moving database to: {}", target_path.to_string_lossy());
|
||||
|
||||
if let Err(error) = fs::create_dir_all(&target_path) {
|
||||
error!("Failed to create new directory: {error}");
|
||||
if let Err(error) = fs::create_dir_all(&target_path) {
|
||||
error!("Failed to create new directory: {error}");
|
||||
}
|
||||
|
||||
if let Err(error) = fs::rename(&self.path, &target_path) {
|
||||
error!("Failed to move database: {error}");
|
||||
}
|
||||
|
||||
self.path = target_path;
|
||||
}
|
||||
|
||||
if let Err(error) = fs::rename(&self.path, &target_path) {
|
||||
error!("Failed to move database: {error}");
|
||||
}
|
||||
|
||||
self.path = target_path;
|
||||
}
|
||||
|
||||
self.version = 4;
|
||||
info!("Migrating to version 5…");
|
||||
self.version = 5;
|
||||
|
||||
let clone = self.clone();
|
||||
spawn_tokio!(async move {
|
||||
|
@ -548,14 +544,6 @@ pub struct Secret {
|
|||
pub passphrase: String,
|
||||
}
|
||||
|
||||
impl Secret {
|
||||
/// Converts a vector of bytes to a `Secret`.
|
||||
pub fn from_utf8(slice: &[u8]) -> Result<Self, FromUtf8SecretError> {
|
||||
let s = String::from_utf8(slice.to_owned())?;
|
||||
Ok(serde_json::from_str(&s)?)
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves all sessions stored to the `SecretService`
|
||||
pub async fn restore_sessions() -> Result<Vec<StoredSession>, SecretError> {
|
||||
let keyring = Keyring::new().await?;
|
||||
|
@ -575,15 +563,23 @@ pub async fn restore_sessions() -> Result<Vec<StoredSession>, SecretError> {
|
|||
Ok(session) => sessions.push(session),
|
||||
Err(SecretError::OldVersion { item, mut session }) => {
|
||||
if session.version == 0 {
|
||||
warn!(
|
||||
"Found old session for {} with sled store, removing…",
|
||||
info!(
|
||||
"Found old session for user {} with sled store, removing…",
|
||||
session.user_id
|
||||
);
|
||||
session.delete(Some(item), true).await;
|
||||
} else if session.version < 4 {
|
||||
session.migrate_to_v4(item).await;
|
||||
sessions.push(session);
|
||||
continue;
|
||||
}
|
||||
|
||||
info!(
|
||||
"Found session {} for user {} with old version {}, applying migrations…",
|
||||
session.id(),
|
||||
session.user_id,
|
||||
session.version,
|
||||
);
|
||||
session.apply_migrations(item).await;
|
||||
|
||||
sessions.push(session);
|
||||
}
|
||||
Err(SecretError::WrongProfile) => {}
|
||||
Err(error) => {
|
||||
|
|
Loading…
Reference in a new issue