Compare commits
2 Commits
b1937d42a2
...
d5eee04d7a
| Author | SHA1 | Date | |
|---|---|---|---|
| d5eee04d7a | |||
| 579e54f7d3 |
@@ -19,7 +19,7 @@ impl TokenID {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct TokenRight {
|
pub struct TokenRight {
|
||||||
verb: TokenVerb,
|
verb: TokenVerb,
|
||||||
path: String,
|
path: String,
|
||||||
@@ -28,6 +28,24 @@ pub struct TokenRight {
|
|||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct TokenRights(Vec<TokenRight>);
|
pub struct TokenRights(Vec<TokenRight>);
|
||||||
|
|
||||||
|
impl TokenRights {
|
||||||
|
pub fn check_error(&self) -> Option<&'static str> {
|
||||||
|
for r in &self.0 {
|
||||||
|
if !r.path.starts_with("/api/") {
|
||||||
|
return Some("All API rights shall start with /api/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contains(&self, verb: TokenVerb, path: &str) -> bool {
|
||||||
|
self.0.contains(&TokenRight {
|
||||||
|
verb,
|
||||||
|
path: path.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone)]
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
pub id: TokenID,
|
pub id: TokenID,
|
||||||
@@ -121,17 +139,6 @@ pub struct NewToken {
|
|||||||
pub delete_after_inactivity: Option<u64>,
|
pub delete_after_inactivity: Option<u64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenRights {
|
|
||||||
pub fn check_error(&self) -> Option<&'static str> {
|
|
||||||
for r in &self.0 {
|
|
||||||
if !r.path.starts_with("/api/") {
|
|
||||||
return Some("All API rights shall start with /api/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NewToken {
|
impl NewToken {
|
||||||
/// Check for error in token
|
/// Check for error in token
|
||||||
pub fn check_error(&self) -> Option<&'static str> {
|
pub fn check_error(&self) -> Option<&'static str> {
|
||||||
@@ -210,6 +217,14 @@ pub async fn update_rights(id: TokenID, rights: TokenRights) -> anyhow::Result<(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set last_used value of token
|
||||||
|
pub async fn refresh_last_used(id: TokenID) -> anyhow::Result<()> {
|
||||||
|
let mut token = get_single(id).await?;
|
||||||
|
token.last_used = time();
|
||||||
|
token.save()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Delete an API token
|
/// Delete an API token
|
||||||
pub async fn delete(id: TokenID) -> anyhow::Result<()> {
|
pub async fn delete(id: TokenID) -> anyhow::Result<()> {
|
||||||
let path = AppConfig::get().api_token_definition_path(id);
|
let path = AppConfig::get().api_token_definition_path(id);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use crate::api_tokens;
|
|||||||
use crate::utils::jwt_utils;
|
use crate::utils::jwt_utils;
|
||||||
use crate::utils::time_utils::time;
|
use crate::utils::time_utils::time;
|
||||||
use actix_web::dev::Payload;
|
use actix_web::dev::Payload;
|
||||||
use actix_web::error::ErrorBadRequest;
|
use actix_web::error::{ErrorBadRequest, ErrorUnauthorized};
|
||||||
use actix_web::{Error, FromRequest, HttpRequest};
|
use actix_web::{Error, FromRequest, HttpRequest};
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
@@ -108,13 +108,25 @@ impl FromRequest for ApiAuthExtractor {
|
|||||||
return Err(ErrorBadRequest("JWT method mismatch!"));
|
return Err(ErrorBadRequest("JWT method mismatch!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : check if route is authorized with token
|
if !token.rights.contains(claims.verb, req.path()) {
|
||||||
|
log::error!(
|
||||||
|
"Attempt to use a token for an unauthorized route! (token_id={})",
|
||||||
|
token.id.0
|
||||||
|
);
|
||||||
|
return Err(ErrorUnauthorized(
|
||||||
|
"Token cannot be used to query this route!",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// TODO : check for ip restriction
|
// TODO : check for ip restriction
|
||||||
|
|
||||||
// TODO : manually validate all checks
|
// TODO : manually validate all checks
|
||||||
|
|
||||||
if token.should_update_last_activity() {
|
if token.should_update_last_activity() {
|
||||||
// TODO : update last activity
|
if let Err(e) = api_tokens::refresh_last_used(token.id).await {
|
||||||
|
log::error!("Could not update token last activity! {e}");
|
||||||
|
return Err(ErrorBadRequest("Couldn't refresh token last activity!"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ApiAuthExtractor { token, claims })
|
Ok(ApiAuthExtractor { token, claims })
|
||||||
|
|||||||
Reference in New Issue
Block a user