domain: add cross-cutting value objects (SystemId, DateTimeStamp, Checksum, StructuredData)
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
use async_trait::async_trait;
|
||||
use chrono::Utc;
|
||||
use domain::{errors::DomainError, ports::TokenIssuer, value_objects::{Role, UserId}};
|
||||
use domain::{errors::DomainError, ports::TokenIssuer, value_objects::SystemId};
|
||||
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Claims {
|
||||
@@ -30,7 +29,7 @@ impl JwtTokenIssuer {
|
||||
|
||||
#[async_trait]
|
||||
impl TokenIssuer for JwtTokenIssuer {
|
||||
async fn issue(&self, user_id: &UserId, role: &Role) -> Result<String, DomainError> {
|
||||
async fn issue(&self, user_id: &SystemId, role: &str) -> Result<String, DomainError> {
|
||||
let claims = Claims {
|
||||
sub: user_id.to_string(),
|
||||
role: role.to_string(),
|
||||
@@ -40,14 +39,12 @@ impl TokenIssuer for JwtTokenIssuer {
|
||||
.map_err(|e| DomainError::Internal(e.to_string()))
|
||||
}
|
||||
|
||||
async fn verify(&self, token: &str) -> Result<(UserId, Role), DomainError> {
|
||||
async fn verify(&self, token: &str) -> Result<(SystemId, String), DomainError> {
|
||||
let data = decode::<Claims>(token, &self.decoding_key, &Validation::default())
|
||||
.map_err(|_| DomainError::Unauthorized("Invalid or expired token".to_string()))?;
|
||||
let uuid = uuid::Uuid::parse_str(&data.claims.sub)
|
||||
.map_err(|_| DomainError::Unauthorized("Invalid token subject".to_string()))?;
|
||||
let role = Role::from_str(&data.claims.role)
|
||||
.map_err(|_| DomainError::Unauthorized("Invalid role in token".to_string()))?;
|
||||
Ok((UserId::from_uuid(uuid), role))
|
||||
Ok((SystemId::from_uuid(uuid), data.claims.role))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,11 +55,11 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn issue_and_verify_roundtrip() {
|
||||
let issuer = JwtTokenIssuer::new("test-secret-key-long-enough-32chars!!");
|
||||
let user_id = UserId::new();
|
||||
let token = issuer.issue(&user_id, &Role::User).await.unwrap();
|
||||
let user_id = SystemId::new();
|
||||
let token = issuer.issue(&user_id, "user").await.unwrap();
|
||||
let (verified_id, verified_role) = issuer.verify(&token).await.unwrap();
|
||||
assert_eq!(verified_id, user_id);
|
||||
assert_eq!(verified_role, Role::User);
|
||||
assert_eq!(verified_role, "user");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
Reference in New Issue
Block a user