guts_types/
identity.rs

1//! Identity types for Guts using Ed25519 signatures.
2
3use commonware_cryptography::ed25519;
4use serde::{Deserialize, Serialize};
5
6/// Ed25519 public key used for peer identity.
7pub type PublicKey = ed25519::PublicKey;
8
9/// Ed25519 signature.
10pub type Signature = ed25519::Signature;
11
12/// A user identity in the Guts network.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct Identity {
15    /// The user's public key (hex encoded).
16    pub public_key: String,
17    /// Optional username.
18    pub username: Option<String>,
19    /// Optional display name.
20    pub display_name: Option<String>,
21}
22
23impl Identity {
24    /// Creates a new identity from a public key.
25    pub fn new(public_key: impl Into<String>) -> Self {
26        Self {
27            public_key: public_key.into(),
28            username: None,
29            display_name: None,
30        }
31    }
32
33    /// Sets the username.
34    pub fn with_username(mut self, username: impl Into<String>) -> Self {
35        self.username = Some(username.into());
36        self
37    }
38
39    /// Sets the display name.
40    pub fn with_display_name(mut self, display_name: impl Into<String>) -> Self {
41        self.display_name = Some(display_name.into());
42        self
43    }
44}
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_identity_creation() {
52        let identity = Identity::new("abc123")
53            .with_username("alice")
54            .with_display_name("Alice");
55
56        assert_eq!(identity.public_key, "abc123");
57        assert_eq!(identity.username, Some("alice".to_string()));
58        assert_eq!(identity.display_name, Some("Alice".to_string()));
59    }
60
61    #[test]
62    fn test_identity_without_optional_fields() {
63        let identity = Identity::new("pubkey123");
64
65        assert_eq!(identity.public_key, "pubkey123");
66        assert!(identity.username.is_none());
67        assert!(identity.display_name.is_none());
68    }
69
70    #[test]
71    fn test_identity_with_only_username() {
72        let identity = Identity::new("key").with_username("user");
73
74        assert_eq!(identity.username, Some("user".to_string()));
75        assert!(identity.display_name.is_none());
76    }
77
78    #[test]
79    fn test_identity_with_only_display_name() {
80        let identity = Identity::new("key").with_display_name("Display Name");
81
82        assert!(identity.username.is_none());
83        assert_eq!(identity.display_name, Some("Display Name".to_string()));
84    }
85
86    #[test]
87    fn test_identity_accepts_string_types() {
88        // Test with String
89        let identity1 = Identity::new(String::from("key1"));
90        assert_eq!(identity1.public_key, "key1");
91
92        // Test with &str
93        let identity2 = Identity::new("key2");
94        assert_eq!(identity2.public_key, "key2");
95    }
96
97    #[test]
98    fn test_identity_serialization() {
99        let identity = Identity::new("abc123")
100            .with_username("alice")
101            .with_display_name("Alice");
102
103        let json = serde_json::to_string(&identity).unwrap();
104        let parsed: Identity = serde_json::from_str(&json).unwrap();
105
106        assert_eq!(parsed.public_key, identity.public_key);
107        assert_eq!(parsed.username, identity.username);
108        assert_eq!(parsed.display_name, identity.display_name);
109    }
110
111    #[test]
112    fn test_identity_clone() {
113        let original = Identity::new("key").with_username("user");
114        let cloned = original.clone();
115
116        assert_eq!(cloned.public_key, original.public_key);
117        assert_eq!(cloned.username, original.username);
118    }
119
120    #[test]
121    fn test_identity_empty_strings() {
122        // Empty strings should be accepted (validation is at higher layer)
123        let identity = Identity::new("").with_username("").with_display_name("");
124
125        assert_eq!(identity.public_key, "");
126        assert_eq!(identity.username, Some(String::new()));
127        assert_eq!(identity.display_name, Some(String::new()));
128    }
129
130    #[test]
131    fn test_identity_unicode() {
132        let identity = Identity::new("key")
133            .with_username("用户")
134            .with_display_name("名前 🎉");
135
136        assert_eq!(identity.username, Some("用户".to_string()));
137        assert_eq!(identity.display_name, Some("名前 🎉".to_string()));
138    }
139}