timegraph_identity/
identity.rs1extern crate base64;
2extern crate hex;
3use crate::{bytes_decode, bytes_encode, Signer, SIGNING_CONTEXT};
4
5#[derive(Debug, Clone)]
6pub enum Identity {
7 User {
8 subgraph_id: u64,
12 user_id: u64, key: String, expiration: u64,
16 origins: String,
17 signature: String, },
19 ApiKey {
20 subgraph_id: u64,
21 key: String, expiration: u64,
23 origins: String,
24 signature: String, },
26}
27
28pub const DEFAULT_SUBGRAPH: u64 = 0;
31pub const ANONYMOUS_USER: u64 = 0; pub const WALLET_USER: u64 = 1; pub const FRONTEND_USER: u64 = 2; pub const NO_SUBGRAPH: i64 = -1;
39pub const NO_USER: i64 = -1;
40
41impl Identity {
45 pub fn from_ssk(ssk: &str) -> anyhow::Result<Identity> {
46 let elms: Vec<&str> = ssk.split(";").collect();
47 if elms.len() != 6 {
48 anyhow::bail!("invalid count of elements is the session key")
49 }
50 let identity = if elms[4].len() < 1 {
51 Identity::ApiKey {
52 subgraph_id: elms[0].parse()?,
53 key: elms[1].to_string(),
54 expiration: elms[2].parse()?,
55 origins: elms[3].to_string(),
56 signature: elms[5].to_string(),
57 }
58 } else {
59 Identity::User {
60 subgraph_id: elms[0].parse()?,
61 user_id: elms[4].parse()?,
62 key: elms[1].to_string(),
63 expiration: elms[2].parse()?,
64 origins: elms[3].to_string(),
65 signature: elms[5].to_string(),
66 }
67 };
68 identity.verify()?;
69 Ok(identity)
70 }
71
72 pub fn to_ssk(&self) -> anyhow::Result<String> {
73 let (ssk_str, sign) = self.stringify_as_ssk()?;
74 Ok(ssk_str + sign)
75 }
76
77 pub fn stringify_as_ssk(&self) -> anyhow::Result<(String, &str)> {
78 Ok(match self {
79 Identity::User {
80 subgraph_id,
81 user_id,
82 key,
83 expiration,
84 origins,
85 signature,
86 } => (
87 format!("{subgraph_id};{key};{expiration};{origins};{user_id};"),
88 signature,
89 ),
90 Identity::ApiKey {
91 subgraph_id,
92 key,
93 expiration,
94 origins,
95 signature,
96 } => (
97 format!("{subgraph_id};{key};{expiration};{origins};;"),
98 signature,
99 ),
100 })
101 }
102
103 pub fn sign(&mut self, secret: &str) -> anyhow::Result<()> {
104 let sk = bytes_decode(secret)?;
105 let signer = Signer::from_bytes(&sk)?;
106 self.sign_with(&signer)
107 }
108
109 pub fn sign_with(&mut self, signer: &Signer) -> anyhow::Result<()> {
110 let (ssk, _) = self.stringify_as_ssk()?;
111 let msg = ssk.as_bytes();
112 let s = bytes_encode(&signer.sign_msg(msg, SIGNING_CONTEXT)?.to_bytes())?;
113 match self {
114 Identity::User {
115 ref mut signature, ..
116 } => *signature = s,
117 Identity::ApiKey {
118 ref mut signature, ..
119 } => *signature = s,
120 }
121 Ok(())
122 }
123
124 pub fn verify(&self) -> anyhow::Result<()> {
125 let verifier = Signer::verifier_from_bytes(&match self {
126 Identity::User { key, .. } => bytes_decode(key)?,
127 Identity::ApiKey { key, .. } => bytes_decode(key)?,
128 })?;
129 let (ssk, signature) = self.stringify_as_ssk()?;
130 let signature = Signer::signature_from_bytes(&bytes_decode(signature)?)?;
131 verifier
132 .verify_msg(&ssk.as_bytes(), SIGNING_CONTEXT, &signature)
133 .or_else(|_| {
134 let bytes_start = b"<Bytes>";
135 let bytes_end = b"</Bytes>";
136 let wrapped_bytes =
137 [&bytes_start[..], &ssk.as_bytes()[..], &bytes_end[..]].concat();
138 verifier.verify_msg(&wrapped_bytes, SIGNING_CONTEXT, &signature)
139 })
140 }
141
142 pub fn origin(&self) -> &str {
143 match self {
144 Identity::User { origins, .. } | Identity::ApiKey { origins, .. } => &origins,
145 }
146 }
147}