forest/rpc/methods/
auth.rs1use crate::{
5 KeyStore,
6 auth::*,
7 lotus_json::lotus_json_with_self,
8 rpc::{ApiPaths, Ctx, Permission, RpcMethod, ServerError},
9};
10use anyhow::Result;
11use chrono::Duration;
12use enumflags2::BitFlags;
13use fvm_ipld_blockstore::Blockstore;
14use schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16use serde_with::{DurationSeconds, serde_as};
17
18pub enum AuthNew {}
20
21impl AuthNew {
22 pub fn create_token(
23 keystore: &KeyStore,
24 token_exp: Duration,
25 permissions: Vec<String>,
26 ) -> anyhow::Result<String> {
27 let ki = keystore.get(JWT_IDENTIFIER)?;
28 Ok(create_token(permissions, ki.private_key(), token_exp)?)
29 }
30}
31
32impl RpcMethod<2> for AuthNew {
33 const NAME: &'static str = "Filecoin.AuthNew";
34 const N_REQUIRED_PARAMS: usize = 1;
35 const PARAM_NAMES: [&'static str; 2] = ["permissions", "expiration_secs"];
37 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
38 const PERMISSION: Permission = Permission::Admin;
39 type Params = (Vec<String>, Option<i64>);
40 type Ok = Vec<u8>;
41 async fn handle(
42 ctx: Ctx<impl Blockstore>,
43 (permissions, expiration_secs): Self::Params,
44 ) -> Result<Self::Ok, ServerError> {
45 let ks = ctx.keystore.read();
46 let token_exp = expiration_secs
50 .map(chrono::Duration::seconds)
51 .unwrap_or_else(|| chrono::Duration::days(365 * 100));
52 let token = Self::create_token(&ks, token_exp, permissions)?;
53 Ok(token.as_bytes().to_vec())
54 }
55}
56
57pub enum AuthVerify {}
58impl RpcMethod<1> for AuthVerify {
59 const NAME: &'static str = "Filecoin.AuthVerify";
60 const PARAM_NAMES: [&'static str; 1] = ["header_raw"];
61 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
62 const PERMISSION: Permission = Permission::Read;
63 type Params = (String,);
64 type Ok = Vec<String>;
65 async fn handle(
66 ctx: Ctx<impl Blockstore>,
67 (header_raw,): Self::Params,
68 ) -> Result<Self::Ok, ServerError> {
69 let ks = ctx.keystore.read();
70 let token = header_raw.trim_start_matches("Bearer ");
71 let ki = ks.get(JWT_IDENTIFIER)?;
72 let perms = verify_token(token, ki.private_key())?;
73 Ok(perms)
74 }
75}
76
77#[serde_as]
78#[derive(Clone, Deserialize, Serialize, JsonSchema)]
79pub struct AuthNewParams {
80 pub perms: Vec<String>,
81 #[serde_as(as = "DurationSeconds<i64>")]
82 #[schemars(with = "i64")]
83 pub token_exp: Duration,
84}
85lotus_json_with_self!(AuthNewParams);
86
87impl AuthNewParams {
88 pub fn process_perms(perm: String) -> Result<Vec<String>, ServerError> {
89 Ok(match perm.to_lowercase().as_str() {
90 "admin" => ADMIN,
91 "sign" => SIGN,
92 "write" => WRITE,
93 "read" => READ,
94 _ => return Err(ServerError::invalid_params("unknown permission", None)),
95 }
96 .iter()
97 .map(ToString::to_string)
98 .collect())
99 }
100}
101
102impl From<AuthNewParams> for (Vec<String>, Option<i64>) {
103 fn from(value: AuthNewParams) -> Self {
104 (value.perms, Some(value.token_exp.num_seconds()))
105 }
106}