cooplan_amqp_api/api/input/
token.rs1use std::collections::HashMap;
2
3use jsonwebtoken::TokenData;
4use serde_json::Value;
5
6use crate::error::{Error, ErrorKind};
7
8const PERMISSIONS_CLAIM: &str = "permissions";
9const 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 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}