backend/cookie/
validation.rs1use std::sync::Arc;
2
3use axum::{
4 Json,
5 body::Body,
6 extract::State,
7 http::{Request, StatusCode, header},
8 middleware::Next,
9 response::IntoResponse,
10};
11use axum_extra::extract::CookieJar;
12use jsonwebtoken::DecodingKey;
13use serde_json::json;
14
15use crate::{AppState, cookie::jwt::decode_token, handlers::auth::filter_user, models::User};
16
17pub async fn validate_token(
38 cookies: CookieJar,
39 State(data): State<Arc<AppState>>,
40 mut request: Request<Body>,
41 next: Next,
42) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
43 let token = cookies
44 .get("token")
45 .map(|cookie| cookie.value().to_string())
46 .or_else(|| {
47 request
48 .headers()
49 .get(header::AUTHORIZATION)
50 .and_then(|header| header.to_str().ok())
51 .and_then(|value| {
52 if value.starts_with("Bearer ") {
53 Some(value[7..].to_owned())
54 } else {
55 None
56 }
57 })
58 });
59
60 let token = token.ok_or_else(|| {
61 let error = json!({
62 "status": "error",
63 "message": "Please provide a valid token"
64 });
65 (StatusCode::UNAUTHORIZED, Json(error))
66 })?;
67
68 let claims = decode_token(
69 token,
70 &DecodingKey::from_secret(data.env.token_secret.as_ref()),
71 )
72 .map_err(|(status, json_err)| {
73 let error = json!({
74 "status": json_err.status,
75 "message": json_err.message
76 });
77 (status, Json(error))
78 })?;
79
80 let uuid = (&claims.sub).parse::<i16>().map_err(|_| {
81 let error = json!({
82 "status": "error",
83 "message": "Invalid user id"
84 });
85 (StatusCode::UNAUTHORIZED, Json(error))
86 })?;
87
88 let user = sqlx::query_as::<_, User>(r#"SELECT * FROM users WHERE id = $1"#)
89 .bind(uuid)
90 .fetch_optional(&data.db)
91 .await
92 .map_err(|e| {
93 let error = json!({
94 "status": "error",
95 "message": format!("Database error: {}", e)
96 });
97 (StatusCode::INTERNAL_SERVER_ERROR, Json(error))
98 })?;
99
100 let user = user.ok_or_else(|| {
101 let error = json!({
102 "status": "error",
103 "message": "Invalid user"
104 });
105 (StatusCode::UNAUTHORIZED, Json(error))
106 })?;
107
108 request.extensions_mut().insert(filter_user(&user));
109 Ok(next.run(request).await)
110}
111
112pub async fn validate_admin(
133 cookies: CookieJar,
134 State(data): State<Arc<AppState>>,
135 mut request: Request<Body>,
136 next: Next,
137) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
138 let token = cookies
139 .get("token")
140 .map(|cookie| cookie.value().to_string())
141 .or_else(|| {
142 request
143 .headers()
144 .get(header::AUTHORIZATION)
145 .and_then(|header| header.to_str().ok())
146 .and_then(|value| {
147 if value.starts_with("Bearer ") {
148 Some(value[7..].to_owned())
149 } else {
150 None
151 }
152 })
153 });
154
155 let token = token.ok_or_else(|| {
156 let error = json!({
157 "status": "error",
158 "message": "Please provide a valid token"
159 });
160 (StatusCode::UNAUTHORIZED, Json(error))
161 })?;
162
163 let claims = decode_token(
164 token,
165 &DecodingKey::from_secret(data.env.token_secret.as_ref()),
166 )
167 .map_err(|(status, json_err)| {
168 let error = json!({
169 "status": json_err.status,
170 "message": json_err.message
171 });
172 (status, Json(error))
173 })?;
174
175 let uuid = (&claims.sub).parse::<i16>().map_err(|_| {
176 let error = json!({
177 "status": "error",
178 "message": "Invalid user id"
179 });
180 (StatusCode::UNAUTHORIZED, Json(error))
181 })?;
182
183 let user = sqlx::query_as::<_, User>(r#"SELECT * FROM users WHERE id = $1"#)
184 .bind(uuid)
185 .fetch_optional(&data.db)
186 .await
187 .map_err(|e| {
188 let error = json!({
189 "status": "error",
190 "message": format!("Database error: {}", e)
191 });
192 (StatusCode::INTERNAL_SERVER_ERROR, Json(error))
193 })?;
194
195 let user = user.ok_or_else(|| {
196 let error = json!({
197 "status": "error",
198 "message": "Invalid user"
199 });
200 (StatusCode::UNAUTHORIZED, Json(error))
201 })?;
202
203 if !user.is_admin {
204 let error = json!({
205 "status": "error",
206 "message": "Admin access required"
207 });
208 return Err((StatusCode::FORBIDDEN, Json(error)));
209 }
210
211 request.extensions_mut().insert(filter_user(&user));
212 Ok(next.run(request).await)
213}