Skip to main content

rings_core/session/
builder.rs

1use rings_derive::wasm_export;
2
3use super::model::pack_session;
4use super::Account;
5use super::Session;
6use super::SessionSk;
7use crate::consts::DEFAULT_SESSION_TTL_MS;
8use crate::ecc::SecretKey;
9use crate::error::Result;
10use crate::utils;
11
12/// Builds a [`SessionSk`] from an external account authorization.
13#[wasm_export]
14pub struct SessionSkBuilder {
15    sk: SecretKey,
16    account_entity: String,
17    account_type: String,
18    ttl_ms: u64,
19    ts_ms: u128,
20    sig: Vec<u8>,
21}
22
23#[wasm_export]
24impl SessionSkBuilder {
25    /// Create a new `SessionSkBuilder`.
26    ///
27    /// `account_type` is the lowercase account algorithm name and `account_entity` is the encoded
28    /// entity accepted by that account algorithm.
29    pub fn new(account_entity: String, account_type: String) -> SessionSkBuilder {
30        let sk = SecretKey::random();
31        Self {
32            sk,
33            account_entity,
34            account_type,
35            ttl_ms: DEFAULT_SESSION_TTL_MS,
36            ts_ms: utils::get_epoch_ms(),
37            sig: vec![],
38        }
39    }
40
41    /// Return whether the configured account type and entity form a valid account.
42    pub fn validate_account(&self) -> bool {
43        Account::try_from((self.account_entity.clone(), self.account_type.clone()))
44            .map_err(|error| {
45                tracing::debug!(?error, "session account validation failed");
46                error
47            })
48            .is_ok()
49    }
50
51    /// Construct the proof string that the external account must sign.
52    pub fn unsigned_proof(&self) -> String {
53        pack_session(self.sk.address().into(), self.ts_ms, self.ttl_ms)
54    }
55
56    /// Set the account signature authorizing this session.
57    pub fn set_session_sig(mut self, sig: Vec<u8>) -> Self {
58        self.sig = sig;
59        self
60    }
61
62    /// Set the session lifetime.
63    pub fn set_ttl(mut self, ttl_ms: u64) -> Self {
64        self.ttl_ms = ttl_ms;
65        self
66    }
67
68    /// Verify the authorization and build the session key.
69    pub fn build(self) -> Result<SessionSk> {
70        let account = Account::try_from((self.account_entity, self.account_type))?;
71        let session = Session {
72            session_id: self.sk.address().into(),
73            account,
74            ttl_ms: self.ttl_ms,
75            ts_ms: self.ts_ms,
76            sig: self.sig,
77        };
78
79        session.verify_self()?;
80        Ok(SessionSk::from_parts(session, self.sk))
81    }
82}