1use anyhow::Result;
2use hmac::{Hmac, Mac};
3use jwt::SignWithKey;
4use serde::Serialize;
5use sha2::Sha256;
6use std::{
7 ops::Add,
8 time::{Duration, SystemTime, UNIX_EPOCH},
9};
10
11static DEFAULT_TTL: Duration = Duration::from_secs(6 * 60 * 60); // 6 hours
12
13#[derive(Default, Serialize)]
14#[serde(rename_all = "camelCase")]
15struct ClaimGrants<'a> {
16 iss: &'a str,
17 sub: &'a str,
18 iat: u64,
19 exp: u64,
20 nbf: u64,
21 jwtid: &'a str,
22 video: VideoGrant<'a>,
23}
24
25#[derive(Default, Serialize)]
26#[serde(rename_all = "camelCase")]
27struct VideoGrant<'a> {
28 room_create: Option<bool>,
29 room_join: Option<bool>,
30 room_list: Option<bool>,
31 room_record: Option<bool>,
32 room_admin: Option<bool>,
33 room: Option<&'a str>,
34 can_publish: Option<bool>,
35 can_subscribe: Option<bool>,
36 can_publish_data: Option<bool>,
37 hidden: Option<bool>,
38 recorder: Option<bool>,
39}
40
41pub fn create_token(
42 api_key: &str,
43 secret_key: &str,
44 room_name: &str,
45 participant_name: &str,
46) -> Result<String> {
47 let secret_key: Hmac<Sha256> = Hmac::new_from_slice(secret_key.as_bytes())?;
48
49 let now = SystemTime::now();
50
51 let claims = ClaimGrants {
52 iss: api_key,
53 sub: participant_name,
54 iat: now.duration_since(UNIX_EPOCH).unwrap().as_secs(),
55 exp: now
56 .add(DEFAULT_TTL)
57 .duration_since(UNIX_EPOCH)
58 .unwrap()
59 .as_secs(),
60 nbf: 0,
61 jwtid: participant_name,
62 video: VideoGrant {
63 room: Some(room_name),
64 room_join: Some(true),
65 can_publish: Some(true),
66 can_subscribe: Some(true),
67 ..Default::default()
68 },
69 };
70 Ok(claims.sign_with_key(&secret_key)?)
71}