webserver_rs/web_core/
authorization.rs1use jsonwebtoken::{self, EncodingKey};
2use salvo::jwt_auth::{ConstDecoder, JwtTokenFinder};
3use salvo::prelude::*;
4use serde::de::DeserializeOwned;
5use serde::Serialize;
6
7use crate::web_core::http_error::AnyHttpError;
8use crate::HttpErrorKind;
9
10#[allow(dead_code)]
11pub fn gen_jwt_auth<T: Send + Sync + DeserializeOwned + 'static>(
13 secret_key: String,
14 finders: Vec<Box<dyn JwtTokenFinder>>,
15) -> JwtAuth<T, ConstDecoder> {
16 JwtAuth::new(ConstDecoder::from_secret(secret_key.as_bytes()))
17 .finders(finders)
18 .force_passed(true)
19}
20
21#[allow(dead_code)]
22pub fn gen_token<T: Serialize + Send + Sync + 'static>(
24 secret_key: String,
25 claim: T,
26) -> Result<String, jsonwebtoken::errors::Error> {
27 jsonwebtoken::encode(
28 &jsonwebtoken::Header::default(),
29 &claim,
30 &EncodingKey::from_secret(secret_key.as_bytes()),
31 )
32}
33
34pub struct AuthGuard<F: Fn(JwtAuthState) -> AnyHttpError + Send + Sync + 'static> {
36 f: F,
37}
38#[allow(dead_code)]
39impl<F> AuthGuard<F>
40where
41 F: Fn(JwtAuthState) -> AnyHttpError + Send + Sync + 'static,
42{
43 pub fn new(f: F) -> Self {
45 Self { f }
46 }
47}
48#[async_trait]
49impl<F> Handler for AuthGuard<F>
50where
51 F: Fn(JwtAuthState) -> AnyHttpError + Send + Sync + 'static,
52{
53 async fn handle(
54 &self,
55 req: &mut Request,
56 depot: &mut Depot,
57 res: &mut Response,
58 ctrl: &mut FlowCtrl,
59 ) {
60 match depot.jwt_auth_state() {
61 JwtAuthState::Authorized => {
62 ctrl.call_next(req, depot, res).await;
63 }
64 JwtAuthState::Unauthorized => {
65 res.status_code(StatusCode::UNAUTHORIZED);
66 match (self.f)(JwtAuthState::Unauthorized).1 {
67 HttpErrorKind::Html(v) => {
68 res.render(Text::Html(v));
69 }
70 HttpErrorKind::Json(v) => {
71 res.render(Text::Json(v.to_string()));
72 }
73 };
74 ctrl.skip_rest();
75 }
76 JwtAuthState::Forbidden => {
77 res.status_code(StatusCode::FORBIDDEN);
78 match (self.f)(JwtAuthState::Forbidden).1 {
79 HttpErrorKind::Html(v) => {
80 res.render(Text::Html(v));
81 }
82 HttpErrorKind::Json(v) => {
83 res.render(Text::Json(v.to_string()));
84 }
85 };
86 ctrl.skip_rest();
87 }
88 };
89 }
90}
91
92#[macro_export]
94macro_rules! expire_time {
95 (Days($day:expr)) => {{
96 use $crate::time::{Duration, OffsetDateTime};
97 let tmp = OffsetDateTime::now_utc() + Duration::days($day);
98 tmp.unix_timestamp()
99 }};
100 (Weeks($w:expr)) => {{
101 use $crate::time::{Duration, OffsetDateTime};
102 let tmp = OffsetDateTime::now_utc() + Duration::weeks($w);
103 tmp.unix_timestamp()
104 }};
105 (Hours($h:expr)) => {{
106 use $crate::time::{Duration, OffsetDateTime};
107 let tmp = OffsetDateTime::now_utc() + Duration::hours($h);
108 tmp.unix_timestamp()
109 }};
110 (Minutes($m:expr)) => {{
111 use $crate::time::{Duration, OffsetDateTime};
112 let tmp = OffsetDateTime::now_utc() + Duration::minutes($m);
113 tmp.unix_timestamp()
114 }};
115 (Seconds($s:expr)) => {{
116 use $crate::time::{Duration, OffsetDateTime};
117 let tmp = OffsetDateTime::now_utc() + Duration::seconds($s);
118 tmp.unix_timestamp()
119 }};
120}