This commit is contained in:
2025-04-22 12:53:17 +04:00
parent cad285fd59
commit 1708e6dd06
116 changed files with 1919 additions and 81 deletions

View File

@@ -0,0 +1,35 @@
# Circles Core Models
This directory contains the core data structures used in the herolib circles module. These models serve as the foundation for the circles functionality, providing essential data structures for circles and name management.
## Overview
The core models implement the Serde traits (Serialize/Deserialize) and crate database traits (Storable, SledModel), which allows them to be stored and retrieved using the generic SledDB implementation. Each model provides:
- A struct definition with appropriate fields
- Serde serialization through derive macros
- Methods for database integration through the SledModel trait
- Utility methods for common operations
## Core Models
### Circle (`circle.rs`)
The Circle model represents a collection of members (users or other circles):
- **Circle**: Main struct with fields for identification and member management
- **Member**: Represents a member of a circle with personal information and role
- **Role**: Enum for possible member roles (Admin, Stakeholder, Member, Contributor, Guest)
### Name (`name.rs`)
The Name model provides DNS record management:
- **Name**: Main struct for domain management with records and administrators
- **Record**: Represents a DNS record with name, text, category, and addresses
- **RecordType**: Enum for DNS record types (A, AAAA, CNAME, MX, etc.)
## Usage
These models are used by the circles module to manage circles and DNS records. They are typically accessed through the database handlers that implement the generic SledDB interface.

View File

@@ -0,0 +1,43 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Circle represents a collection of members (users or other circles)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Circle {
pub id: u32, // unique id
pub name: String, // name of the circle
pub description: String, // optional description
}
impl Circle {
/// Create a new circle
pub fn new(id: u32, name: String, description: String) -> Self {
Self {
id,
name,
description,
}
}
/// Returns a map of index keys for this circle
pub fn index_keys(&self) -> HashMap<String, String> {
let mut keys = HashMap::new();
keys.insert("name".to_string(), self.name.clone());
keys
}
}
// Implement Storable trait
impl Storable for Circle {}
// Implement Model trait
impl Model for Circle {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"circle"
}
}

View File

@@ -0,0 +1,9 @@
pub mod circle;
pub mod name;
// Re-export all model types for convenience
pub use circle::{Circle, Member, Role};
pub use name::{Name, Record, RecordType};
// Re-export database components
pub use crate::db::{DB, DBBuilder, Model, Storable, DbError, DbResult, ModelRegistration, ModelRegistrar};

View File

@@ -0,0 +1,83 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Role represents the role of a member in a circle
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Role {
Admin,
Stakeholder,
Member,
Contributor,
Guest,
}
/// Member represents a member of a circle
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Member {
pub id: u32, // unique id
pub emails: Vec<String>, // list of emails
pub name: String, // name of the member
pub description: String, // optional description
pub role: Role, // role of the member in the circle
pub contact_ids: Vec<u32>, // IDs of contacts linked to this member
pub wallet_ids: Vec<u32>, // IDs of wallets owned by this member
}
impl Member {
/// Create a new member
pub fn new(id: u32, name: String, description: String, role: Role) -> Self {
Self {
id,
emails: Vec::new(),
name,
description,
role,
contact_ids: Vec::new(),
wallet_ids: Vec::new(),
}
}
/// Add an email to this member
pub fn add_email(&mut self, email: String) {
if !self.emails.contains(&email) {
self.emails.push(email);
}
}
/// Link a contact to this member
pub fn link_contact(&mut self, contact_id: u32) {
if !self.contact_ids.contains(&contact_id) {
self.contact_ids.push(contact_id);
}
}
/// Link a wallet to this member
pub fn link_wallet(&mut self, wallet_id: u32) {
if !self.wallet_ids.contains(&wallet_id) {
self.wallet_ids.push(wallet_id);
}
}
/// Returns a map of index keys for this member
pub fn index_keys(&self) -> HashMap<String, String> {
let mut keys = HashMap::new();
keys.insert("name".to_string(), self.name.clone());
keys
}
}
// Implement Storable trait
impl Storable for Member {
}
// Implement Model trait
impl Model for Member {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"member"
}
}

View File

@@ -0,0 +1,13 @@
pub mod circle;
pub mod member;
pub mod name;
pub mod wallet;
// Re-export all model types for convenience
pub use circle::Circle;
pub use member::{Member, Role};
pub use name::{Name, Record, RecordType};
pub use wallet::{Wallet, Asset};
// Re-export database components from db module
pub use crate::db::{DB, DBBuilder, Model, Storable, DbError, DbResult, ModelRegistration, ModelRegistrar};

View File

@@ -0,0 +1,73 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable, DbError, DbResult};
/// Record types for a DNS record
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RecordType {
A,
AAAA,
CNAME,
MX,
NS,
PTR,
SOA,
SRV,
TXT,
}
/// Represents a DNS record
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Record {
pub name: String, // name of the record
pub text: String,
pub category: RecordType, // role of the member in the circle
pub addr: Vec<String>, // the multiple ipaddresses for this record
}
/// Name represents a DNS domain and its records
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Name {
pub id: u32, // unique id
pub domain: String,
pub description: String, // optional description
pub records: Vec<Record>, // DNS records
pub admins: Vec<String>, // pubkeys who can change it
}
impl Name {
/// Create a new domain name entry
pub fn new(id: u32, domain: String, description: String) -> Self {
Self {
id,
domain,
description,
records: Vec::new(),
admins: Vec::new(),
}
}
/// Add a record to this domain name
pub fn add_record(&mut self, record: Record) {
self.records.push(record);
}
/// Add an admin pubkey
pub fn add_admin(&mut self, pubkey: String) {
self.admins.push(pubkey);
}
}
// Implement Storable trait
impl Storable for Name {
}
// Implement Model trait
impl Model for Name {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"name"
}
}

View File

@@ -0,0 +1,85 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Asset represents a cryptocurrency asset in a wallet
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Asset {
pub name: String, // Asset name (e.g., "USDC")
pub amount: f64, // Amount of the asset
}
impl Asset {
/// Create a new asset
pub fn new(name: String, amount: f64) -> Self {
Self {
name,
amount,
}
}
}
/// Wallet represents a cryptocurrency wallet
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Wallet {
pub id: u32, // unique id
pub name: String, // name of the wallet
pub description: String, // optional description
pub blockchain_name: String, // name of the blockchain
pub pubkey: String, // public key of the wallet
pub assets: Vec<Asset>, // assets in the wallet
}
impl Wallet {
/// Create a new wallet
pub fn new(id: u32, name: String, description: String, blockchain_name: String, pubkey: String) -> Self {
Self {
id,
name,
description,
blockchain_name,
pubkey,
assets: Vec::new(),
}
}
/// Set an asset in the wallet (replaces if exists, adds if not)
pub fn set_asset(&mut self, name: String, amount: f64) {
// Check if the asset already exists
if let Some(asset) = self.assets.iter_mut().find(|a| a.name == name) {
// Update the amount
asset.amount = amount;
} else {
// Add a new asset
self.assets.push(Asset::new(name, amount));
}
}
/// Get the total value of all assets in the wallet
pub fn total_value(&self) -> f64 {
self.assets.iter().map(|a| a.amount).sum()
}
/// Returns a map of index keys for this wallet
pub fn index_keys(&self) -> HashMap<String, String> {
let mut keys = HashMap::new();
keys.insert("name".to_string(), self.name.clone());
keys.insert("blockchain".to_string(), self.blockchain_name.clone());
keys
}
}
// Implement Storable trait
impl Storable for Wallet {
}
// Implement Model trait
impl Model for Wallet {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"wallet"
}
}