1use jsonwebtoken::{decode, DecodingKey, EncodingKey, Header, Validation};
2use serde::{Deserialize, Serialize};
3use tide::{Middleware, Next, Request, Response, StatusCode};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Claims {
7 pub sub: String,
8 pub username: String,
9 pub uid: String,
10 pub exp: u64,
11 pub login_time: u64,
12}
13
14#[derive(Clone)]
15pub struct ApiKeyMiddleware {
16 secret_key: String,
17}
18
19impl ApiKeyMiddleware {
20 pub fn new(secret_key: &str) -> Self {
21 Self {
22 secret_key: secret_key.to_string(),
23 }
24 }
25
26 pub fn gen_token(
27 &self,
28 sub: &str,
29 username: &str,
30 uid: &str,
31 exp: u64,
32 login_time: u64,
33 ) -> Result<String, jsonwebtoken::errors::Error> {
34 let claims = Claims {
35 sub: sub.to_string(),
36 username: username.to_string(),
37 uid: uid.to_string(),
38 exp,
39 login_time,
40 };
41 jsonwebtoken::encode(
42 &Header::default(),
43 &claims,
44 &EncodingKey::from_secret(&self.secret_key.as_bytes()),
45 )
46 }
47}
48
49#[async_trait::async_trait]
50impl<State: Clone + Send + Sync + 'static> Middleware<State> for ApiKeyMiddleware {
51 async fn handle(&self, mut req: Request<State>, next: Next<'_, State>) -> tide::Result {
52 if let Some(api_key) = req.header("x-api-key") {
53 let token_data = decode::<Claims>(
54 &api_key.as_str(),
55 &DecodingKey::from_secret(self.secret_key.as_bytes()),
56 &Validation::default(),
57 );
58
59 match token_data {
60 Ok(data) => {
61 let claims = data.claims;
62 req.set_ext(claims);
64 Ok(next.run(req).await)
65 }
66 Err(_) => {
67 let mut res = Response::new(StatusCode::Unauthorized);
68 res.set_body("Invalid API key");
69 Ok(res)
70 }
71 }
72 } else {
73 let mut res = Response::new(StatusCode::Unauthorized);
74 res.set_body("API key missing");
75 Ok(res)
76 }
77 }
78}