Skip to content
Snippets Groups Projects
Commit 89bde1dd authored by Nicolas80's avatar Nicolas80
Browse files

* Re-did the mapping of DbAccountId so that we don't have to rely on derive...

* Re-did the mapping of DbAccountId so that we don't have to rely on derive macro FromJsonQueryResult that resulted in using JSON_TEXT in database column instead of VARCHAR
   * Tricky part I missed the first time was in impl of sea_orm::TryGetable::try_get_by where we should return Err TryGetError::Null in case the value is not present
   * Was otherwise throwing an exception whenever `parent` field (Option<DbAccountId>) was None when trying to persist the case in DB.
parent 07ea8692
No related branches found
No related tags found
1 merge request!41Adding db persistence for all SecretFormat of vault keys as well as supporting derivations
......@@ -2,18 +2,19 @@ use crate::commands::{cesium, vault};
use crate::runtime_config::AccountId;
use crate::utils::GcliError;
use anyhow::anyhow;
use sea_orm::entity::prelude::*;
use sea_orm::prelude::async_trait::async_trait;
use sea_orm::prelude::StringLen;
use sea_orm::ActiveValue::Set;
use sea_orm::PaginatorTrait;
use sea_orm::QueryFilter;
use sea_orm::TryGetError;
use sea_orm::{
ActiveModelBehavior, ColumnTrait, DbErr, DeriveEntityModel, DerivePrimaryKey, EnumIter, Linked,
ModelTrait, QueryOrder, RelationDef, RelationTrait, TryFromU64,
};
use sea_orm::{ActiveModelTrait, ConnectionTrait, PrimaryKeyTrait};
use sea_orm::{DeriveActiveEnum, EntityTrait};
use sea_orm::{FromJsonQueryResult, PaginatorTrait};
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Display;
......@@ -112,41 +113,58 @@ impl Display for Model {
}
}
/// Necessary to create a wrapper over AccountId32 to implement sea-orm traits
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, FromJsonQueryResult)]
/// Necessary to create a wrapper over AccountId to implement sea-orm traits
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DbAccountId(pub AccountId);
impl FromStr for DbAccountId {
type Err = GcliError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
AccountId::from_str(s)
.map(DbAccountId)
.map_err(|_| GcliError::Input("Invalid AccountId format".to_string()))
/// All the next methods are necessary to support the proper mapping of the DbAccountId from/to String in DB and
/// to allow using it as primaryKey
impl sea_orm::sea_query::Nullable for DbAccountId {
fn null() -> Value {
Value::String(None)
}
}
impl Display for DbAccountId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
impl sea_orm::TryGetable for DbAccountId {
/// Had to really pay attention to return proper TryGetError type when value not present => TryGetError::Null
///
/// as otherwise, when using `Option<DbAccountId>` with a None value it was crashing (when no "parent")
fn try_get_by<I: sea_orm::ColIdx>(res: &QueryResult, idx: I) -> Result<Self, TryGetError> {
let value: String = res
.try_get_by(idx)
.map_err(|e| TryGetError::Null(e.to_string()))?;
Ok(DbAccountId(AccountId::from_str(&value).map_err(|e| {
TryGetError::DbErr(DbErr::Custom(e.to_string()))
})?))
}
}
impl From<AccountId> for DbAccountId {
fn from(account_id: AccountId) -> Self {
DbAccountId(account_id)
impl sea_orm::sea_query::ValueType for DbAccountId {
fn try_from(v: Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> {
match v {
Value::String(Some(value)) => Ok(DbAccountId(
AccountId::from_str(&value).map_err(|_| sea_orm::sea_query::ValueTypeErr)?,
)),
_ => Err(sea_orm::sea_query::ValueTypeErr),
}
}
}
impl From<DbAccountId> for AccountId {
fn from(db_account_id: DbAccountId) -> Self {
db_account_id.0
fn type_name() -> String {
stringify!(DbAccountId).to_owned()
}
fn array_type() -> sea_orm::sea_query::ArrayType {
sea_orm::sea_query::ArrayType::String
}
fn column_type() -> ColumnType {
ColumnType::String(StringLen::None)
}
}
impl From<String> for DbAccountId {
fn from(s: String) -> Self {
DbAccountId(AccountId::from_str(&s).expect("Invalid AccountId format"))
impl From<DbAccountId> for Value {
fn from(account_id: DbAccountId) -> Self {
Value::String(Some(Box::new(account_id.0.to_string())))
}
}
......@@ -159,6 +177,40 @@ impl TryFromU64 for DbAccountId {
}
}
impl Display for DbAccountId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl FromStr for DbAccountId {
type Err = GcliError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(DbAccountId(
AccountId::from_str(s).map_err(|e| GcliError::Input(e.to_string()))?,
))
}
}
impl From<String> for DbAccountId {
fn from(s: String) -> Self {
DbAccountId(AccountId::from_str(&s).expect("Invalid AccountId format"))
}
}
impl From<AccountId> for DbAccountId {
fn from(account_id: AccountId) -> Self {
DbAccountId(account_id)
}
}
impl From<DbAccountId> for AccountId {
fn from(db_account_id: DbAccountId) -> Self {
db_account_id.0
}
}
/// Didn't want to pollute the keys::CryptoScheme enum with sea-orm specific derivations
///
/// created a separate enum for the database with conversions between the two
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment