cw_auth_types/
sessions.rs

1use std::str::FromStr;
2
3use actions::SessionActionName;
4use saa_schema::saa_type;
5use smart_account_auth::{cosmwasm_std::Env, ensure, msgs::{AllowedActions, ActionDerivation}, CredentialId, CredentialRecord, Expiration};
6use strum::IntoEnumIterator;
7use crate::errors::SessionError;
8
9
10pub mod queries;
11pub mod actions;
12
13type GranteeInfo = CredentialRecord;
14
15#[saa_type]
16pub struct SessionInfo  {
17    pub grantee     :       GranteeInfo,
18    pub granter     :       Option<CredentialId>,
19    pub expiration  :       Option<Expiration>,
20}
21
22
23
24
25impl SessionInfo {
26    pub fn checked_params(
27        &self, 
28        env: &Env,
29        actions: Option<&AllowedActions>
30    ) -> Result<(CredentialId, CredentialRecord, Expiration, AllowedActions), SessionError> {
31        let granter = self.granter.clone().unwrap_or_default();
32        let (id, info) = self.grantee.clone();
33        ensure!(!id.is_empty(), SessionError::InvalidGrantee);
34        let expiration = self.expiration.clone().unwrap_or_default();
35        ensure!(!expiration.is_expired(&env.block), SessionError::Expired);
36        if let Some(granter) = &self.granter {
37            ensure!(!granter.is_empty() && *granter != id, SessionError::InvalidGranter);
38        }
39        let actions : AllowedActions = match actions {
40            Some(actions) => {
41                if let AllowedActions::Include(ref actions) = actions {
42                    ensure!(actions.len() > 0, SessionError::EmptyCreateActions);
43
44                    let validity_ok = actions
45                        .iter()
46                        .enumerate()
47                        .all(|(i, action)| {
48                            let ok = !action.result.is_empty() 
49                                &&  actions
50                                    .into_iter()
51                                    .skip(i + 1)
52                                    .filter(|action2| action == *action2)
53                                    .count() == 0;
54                            ok
55                        });
56                    ensure!(validity_ok, SessionError::InvalidActions);
57
58                    let no_inner_sessions = actions
59                        .iter()
60                        .all(|action| {
61                            match action.method {
62                                ActionDerivation::Json => !action.result.contains("\"session_actions\"") &&
63                                                            !action.result.contains("\"session_info\""),
64                                                            
65                                _ => !is_session_action_name(action.result.as_str())
66                                
67                            }
68                        });
69
70                    ensure!(no_inner_sessions, SessionError::InnerSessionAction);
71                }
72                actions.clone()
73            },
74            None => AllowedActions::All {},
75        };
76        Ok((granter, (id, info), expiration, actions))
77    }
78}
79
80
81
82pub(crate) fn is_session_action_name(name: &str) -> bool {
83    SessionActionName::iter()
84        .any(|action| {
85            if action.as_ref() == name {
86                return true;
87            }
88            if let Ok(act) = SessionActionName::from_str(name) {
89                return action == act;
90            }
91            false
92        })
93}