cooplan_amqp_api/api/input/
token.rs

1use std::collections::HashMap;
2
3use jsonwebtoken::TokenData;
4use serde_json::Value;
5
6use crate::error::{Error, ErrorKind};
7
8const PERMISSIONS_CLAIM: &str = "permissions";
9/// Custom claim used in order to support easy assignations of permissions to users
10/// without having to figure out a way to edit Auth0's permissions claim.
11/// USED ONLY WHENEVER THE AUTH0'S PERMISSIONS CLAIM IS EMPTY.
12const CUSTOM_PERMISSIONS_CLAIM: &str = "permission";
13
14pub const USER_ID_CLAIM: &str = "sub";
15pub const ORGANIZATION_ID_CLAIM: &str = "organization_id";
16
17#[derive(Debug)]
18pub struct Token {
19    token_data: TokenData<HashMap<String, Value>>,
20    permissions: Vec<String>,
21}
22
23impl Token {
24    pub fn try_new(token_data: TokenData<HashMap<String, Value>>) -> Result<Token, Error> {
25        let mut permissions = get_permissions_from_claim(&token_data, PERMISSIONS_CLAIM)?;
26
27        // Use custom permissions claim *ONLY* if Auth0's permission claim is empty.
28        if permissions.is_empty() {
29            permissions = get_permissions_from_claim(&token_data, CUSTOM_PERMISSIONS_CLAIM)?;
30        }
31
32        Ok(Token {
33            token_data,
34            permissions,
35        })
36    }
37
38    pub fn has_permission(&self, permission: &String) -> Result<(), Error> {
39        if !self.permissions.contains(permission) {
40            return Err(Error::new(
41                ErrorKind::PermissionNotFound,
42                format!("permission '{}' could not be found", permission),
43            ));
44        }
45
46        Ok(())
47    }
48
49    pub fn get(&self, key: &str) -> Option<&Value> {
50        self.token_data.claims.get(key)
51    }
52}
53
54fn get_permissions_from_claim(
55    token_data: &TokenData<HashMap<String, Value>>,
56    claim: &str,
57) -> Result<Vec<String>, Error> {
58    let permissions = match token_data.claims.get(claim) {
59        Some(permissions) => match serde_json::from_value::<Vec<String>>(permissions.clone()) {
60            Ok(permissions) => permissions,
61            Err(error) => {
62                return Err(Error::new(
63                    ErrorKind::MalformedToken,
64                    format!(
65                        "failed to deserialize permissions as a strings vector: {}",
66                        error
67                    ),
68                ))
69            }
70        },
71        None => {
72            return Err(Error::new(
73                ErrorKind::MalformedToken,
74                "'permissions' claim is missing",
75            ))
76        }
77    };
78
79    Ok(permissions)
80}