Commit 20b7515d authored by Pascal Engélibert's avatar Pascal Engélibert 🚴
Browse files

feat(db+indexer+gql): idty_by_username

parent c8d178fd
Pipeline #13069 passed with stages
in 11 minutes and 37 seconds
......@@ -41,8 +41,8 @@ pub(crate) use duniter_core::dbs::kv_typed::db_schema;
pub(crate) use duniter_core::dbs::kv_typed::prelude::*;
pub(crate) use duniter_core::dbs::smallvec::SmallVec;
pub(crate) use duniter_core::dbs::{
bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, SourceAmountValV2, ToDumpString,
WalletConditionsV2,
bincode_db, CorruptedBytes, HashKeyV2, PubKeyKeyV2, PubKeyValV2, SourceAmountValV2,
ToDumpString, WalletConditionsV2,
};
pub(crate) use duniter_core::wallet::prelude::*;
pub(crate) use duniter_core::wot::WotId;
......@@ -67,6 +67,7 @@ db_schema!(
GvaUtxoIdDbV1,
SourceAmountValV2
],
["idty_by_username", IdtyByUsername, String, PubKeyValV2],
[
"scripts_by_pubkey",
ScriptsByPubkey,
......
......@@ -159,6 +159,11 @@ pub trait DbsReader {
bc_db: &BcV2DbRo<FileBackend>,
pubkey: PublicKey,
) -> KvResult<Option<duniter_core::dbs::IdtyDbV2>>;
fn idty_by_username(
&self,
bc_db: &BcV2DbRo<FileBackend>,
username: String,
) -> KvResult<Option<(PublicKey, duniter_core::dbs::IdtyDbV2)>>;
fn peers_and_heads<DB: 'static + NetworkV1DbReadable>(
&self,
dunp_db: &DB,
......@@ -353,6 +358,21 @@ impl DbsReader for DbsReaderImpl {
self.idty_(bc_db, pubkey)
}
fn idty_by_username(
&self,
bc_db: &BcV2DbRo<FileBackend>,
username: String,
) -> KvResult<Option<(PublicKey, duniter_core::dbs::IdtyDbV2)>> {
self.0
.idty_by_username()
.get(&username)?
.map_or(Ok(None), |pubkey| match self.idty_(bc_db, pubkey.0) {
Ok(Some(idty)) => Ok(Some((pubkey.0, idty))),
Ok(None) => Ok(None),
Err(e) => Err(e),
})
}
fn peers_and_heads<DB: 'static + NetworkV1DbReadable>(
&self,
dunp_db: &DB,
......
......@@ -13,8 +13,11 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use crate::*;
#[derive(Clone, Debug, async_graphql::SimpleObject)]
pub(crate) struct Identity {
pub is_member: bool,
pub pubkey: PubKeyGva,
pub username: String,
}
......@@ -34,6 +34,27 @@ impl IdtyQuery {
.await??
.map(|idty| Identity {
is_member: idty.is_member,
pubkey,
username: idty.username,
}))
}
/// Get identity by username
async fn idty_by_username(
&self,
ctx: &async_graphql::Context<'_>,
#[graphql(desc = "username")] username: String,
) -> async_graphql::Result<Option<Identity>> {
let data = ctx.data::<GvaSchemaData>()?;
let dbs_reader = data.dbs_reader();
Ok(data
.dbs_pool
.execute(move |dbs| dbs_reader.idty_by_username(&dbs.bc_db_ro, username))
.await??
.map(|(pubkey, idty)| Identity {
is_member: idty.is_member,
pubkey: PubKeyGva(pubkey),
username: idty.username,
}))
}
......@@ -79,4 +100,41 @@ mod tests {
);
Ok(())
}
#[tokio::test]
async fn test_idty_by_username() -> anyhow::Result<()> {
let mut dbs_reader = MockDbsReader::new();
dbs_reader
.expect_idty_by_username()
.withf(|_, s| s == &String::from("JohnDoe"))
.times(1)
.returning(|_, _| {
Ok(Some((
PublicKey::from_base58("DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP")
.expect("wrong pubkey"),
duniter_core::dbs::IdtyDbV2 {
is_member: true,
username: String::from("JohnDoe"),
..Default::default()
},
)))
});
let schema = create_schema(MockAsyncAccessor::new(), dbs_reader)?;
assert_eq!(
exec_graphql_request(
&schema,
r#"{ idtyByUsername(username: "JohnDoe") {isMember, pubkey} }"#
)
.await?,
serde_json::json!({
"data": {
"idtyByUsername": {
"isMember": true,
"pubkey": "DnjL6hYA1k7FavGHbbir79PKQbmzw63d6bsamBBdUULP"
}
}
})
);
Ok(())
}
}
......@@ -91,6 +91,7 @@ impl WalletsQuery {
balance: AmountWithBase::from(pk_with_sa.1),
idty: idty_opt.map(|idty_db| Identity {
is_member: idty_db.is_member,
pubkey: PubKeyGva(pk_with_sa.0),
username: idty_db.username,
}),
})
......@@ -136,10 +137,17 @@ impl WalletsQuery {
.map(|WalletWithIdtyOpt(script_with_sa, idty_opt)| Wallet {
script: script_with_sa.0.to_string(),
balance: AmountWithBase::from(script_with_sa.1),
idty: idty_opt.map(|idty_db| Identity {
is_member: idty_db.is_member,
username: idty_db.username,
}),
idty: if let (Some(idty_db), Some(pubkey)) =
(idty_opt, script_with_sa.0.as_single_sig())
{
Some(Identity {
is_member: idty_db.is_member,
pubkey: PubKeyGva(pubkey),
username: idty_db.username,
})
} else {
None
},
})
.collect()
})
......
......@@ -18,6 +18,7 @@ use crate::*;
pub(crate) fn update_identities<B: Backend>(
block: &DubpBlockV10,
identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>,
idty_by_username: &mut TxColRw<B::Col, IdtyByUsernameEvent>,
) -> KvResult<()> {
let mut identities_pubkeys = HashSet::new();
for idty in block.identities() {
......@@ -35,6 +36,7 @@ pub(crate) fn update_identities<B: Backend>(
wot_id,
},
);
idty_by_username.upsert(idty.username().into(), PubKeyValV2(pubkey));
}
for mb in block.joiners() {
let pubkey = mb.issuers()[0];
......@@ -70,6 +72,7 @@ pub(crate) fn update_identities<B: Backend>(
pub(crate) fn revert_identities<B: Backend>(
block: &DubpBlockV10,
identities: &mut TxColRw<B::Col, GvaIdentitiesEvent>,
idty_by_username: &mut TxColRw<B::Col, IdtyByUsernameEvent>,
) -> KvResult<()> {
for mb in block.joiners() {
let pubkey = mb.issuers()[0];
......@@ -83,6 +86,7 @@ pub(crate) fn revert_identities<B: Backend>(
}
for idty in block.identities() {
let pubkey = idty.issuers()[0];
idty_by_username.remove(idty.username().into());
identities.remove(PubKeyKeyV2(pubkey));
crate::revert_wot_id();
}
......
......@@ -41,7 +41,7 @@ use duniter_core::{
use duniter_core::{
dbs::{
bincode_db, kv_typed::prelude::*, prelude::*, smallvec::smallvec, FileBackend, HashKeyV2,
PubKeyKeyV2, SourceAmountValV2, WalletConditionsV2,
PubKeyKeyV2, PubKeyValV2, SourceAmountValV2, WalletConditionsV2,
},
wot::{WebOfTrust, WotId, MAIN_WOT},
};
......@@ -126,7 +126,11 @@ pub fn apply_block<B: Backend>(
.upsert(U64BE(block.common_time()), block.number().0);
db.blockchain_time
.upsert(U32BE(block.number().0), block.common_time());
identities::update_identities::<B>(&block, &mut db.gva_identities)?;
identities::update_identities::<B>(
&block,
&mut db.gva_identities,
&mut db.idty_by_username,
)?;
if let Some(divident_amount) = block.dividend() {
db.blocks_with_ud.upsert(U32BE(blockstamp.number.0), ());
apply_ud::<B>(
......@@ -153,7 +157,11 @@ pub fn revert_block<B: Backend>(
gva_db.write(|mut db| {
db.blocks_by_common_time.remove(U64BE(block.common_time()));
db.blockchain_time.remove(U32BE(block.number().0));
identities::revert_identities::<B>(&block, &mut db.gva_identities)?;
identities::revert_identities::<B>(
&block,
&mut db.gva_identities,
&mut db.idty_by_username,
)?;
if let Some(divident_amount) = block.dividend() {
db.blocks_with_ud.remove(U32BE(block.number().0));
revert_ud::<B>(
......@@ -331,6 +339,12 @@ mod tests {
Some(SourceAmountValV2(SourceAmount::with_base0(1000)))
);
assert_eq!(gva_db.txs_by_block().count()?, 0);
assert_eq!(
gva_db.idty_by_username().get(&String::from("elois"))?,
Some(PubKeyValV2(PublicKey::from_base58(
"D9D2zaJoWYWveii1JRYLVK3J4Z7ZH3QczoKrnQeiM6mx",
)?))
);
let b1 = DubpBlockV10::from_string_object(&DubpBlockV10Stringified {
number: 1,
......@@ -644,6 +658,10 @@ mod tests {
);
assert_eq!(gva_db.balances().get(&WalletConditionsV2(s2))?, None);
revert_block(&b0, currency_params, &gva_db)?;
assert_eq!(gva_db.idty_by_username().count()?, 0);
Ok(())
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment