- removed: api-service

- removed: session-service
- updated: moved health check out of consul registration
- updated: get service info to pull the service from the default namespace for the service account
- updated: the rest of the services to be able to handle the new database tables
This commit is contained in:
2025-03-20 22:53:49 -04:00
parent b9ebdd7080
commit 4046f56191
60 changed files with 233 additions and 30588 deletions

View File

@@ -14,7 +14,7 @@ fn main() {
.compile_protos(
&[
"../proto/user_db_api.proto",
"../proto/session_service_api.proto",
"../proto/session_db_api.proto",
],
&["../proto"],
)

View File

@@ -1,6 +1,4 @@
use crate::database::{
user_service_client::UserServiceClient, GetUserByEmailRequest, GetUserByUsernameRequest, GetUserRequest, GetUserResponse,
};
use crate::database::{user_service_client::UserServiceClient, GetUserByEmailRequest, GetUserByUsernameRequest, GetUserRequest, GetUserResponse};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use std::error::Error;

View File

@@ -6,9 +6,8 @@ use crate::auth::{
};
use crate::common::Empty;
use crate::database_client::{DatabaseClient, DatabaseClientTrait};
use crate::jwt::{generate_token, validate_token};
use crate::session::session_service_client::SessionServiceClient;
use crate::session::{CreateSessionRequest, DeleteSessionRequest, GetSessionRequest};
use crate::session::{GetSessionRequest};
use crate::users::{hash_password, verify_user};
use chrono::{Duration, Utc};
use rand::Rng;
@@ -32,13 +31,6 @@ impl AuthService for MyAuthService {
async fn logout(&self, request: Request<LogoutRequest>) -> Result<Response<Empty>, Status> {
let req = request.into_inner();
self.session_client
.as_ref()
.clone()
.delete_session(DeleteSessionRequest {
session_id: req.session_id.clone(),
})
.await?;
Ok(Response::new(Empty {}))
}
@@ -47,43 +39,11 @@ impl AuthService for MyAuthService {
&self,
request: Request<ValidateTokenRequest>,
) -> Result<Response<ValidateTokenResponse>, Status> {
let req = request.into_inner();
match validate_token(&req.token) {
Ok(user_data) => {
let response = self
.session_client
.as_ref()
.clone()
.get_session(GetSessionRequest {
session_id: user_data.1.clone(),
})
.await;
match response {
Ok(res) => {
debug!("Session valid: {:?}", res.into_inner());
Ok(Response::new(ValidateTokenResponse {
valid: true,
user_id: user_data.0,
session_id: user_data.1,
}))
}
Err(_) => {
debug!("Session invalid or not found");
Ok(Response::new(ValidateTokenResponse {
valid: false,
user_id: "".to_string(),
session_id: "".to_string(),
}))
}
}
}
Err(_) => Ok(Response::new(ValidateTokenResponse {
valid: false,
user_id: "".to_string(),
session_id: "".to_string(),
})),
}
Ok(Response::new(ValidateTokenResponse {
valid: false,
user_id: "".to_string(),
session_id: "".to_string(),
}))
}
async fn validate_session(
@@ -91,14 +51,10 @@ impl AuthService for MyAuthService {
request: Request<ValidateSessionRequest>,
) -> Result<Response<ValidateSessionResponse>, Status> {
let req = request.into_inner();
let response = self
.session_client
.as_ref()
.clone()
let response = self.session_client.as_ref().clone()
.get_session(GetSessionRequest {
session_id: req.session_id,
})
.await;
}).await;
match response {
Ok(res) => {
@@ -106,8 +62,8 @@ impl AuthService for MyAuthService {
debug!("Session valid: {:?}", res);
Ok(Response::new(ValidateSessionResponse { valid: true, session_id: res.session_id.to_string(), user_id: res.user_id.to_string() }))
}
Err(_) => {
debug!("Session invalid or not found");
Err(error) => {
debug!("Session invalid or not found: {error}");
Ok(Response::new(ValidateSessionResponse { valid: false, session_id: "".to_string(), user_id: "".to_string() }))
}
}
@@ -122,7 +78,7 @@ impl AuthService for MyAuthService {
.session_client
.as_ref()
.clone()
.refresh_session(GetSessionRequest {
.get_session(GetSessionRequest {
session_id: req.session_id,
})
.await;
@@ -131,10 +87,10 @@ impl AuthService for MyAuthService {
Ok(res) => {
let res = res.into_inner();
debug!("Session valid: {:?}", res);
Ok(Response::new(RefreshSessionResponse { valid: res.valid }))
Ok(Response::new(RefreshSessionResponse { valid: true }))
}
Err(_) => {
debug!("Session invalid or not found");
debug!("Unable to refresh session");
Ok(Response::new(RefreshSessionResponse { valid: false }))
}
}

View File

@@ -1,46 +0,0 @@
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
use std::env;
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String, // Subject (user ID)
session_id: String, // Session ID
roles: Vec<String>, // Roles/permissions
exp: usize, // Expiration time
}
pub fn generate_token(
user_id: &str,
session_id: &str,
roles: Vec<String>,
) -> Result<String, jsonwebtoken::errors::Error> {
let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
let expiration = chrono::Utc::now()
.checked_add_signed(chrono::Duration::days(1))
.expect("valid timestamp")
.timestamp() as usize;
let claims = Claims {
sub: user_id.to_owned(),
session_id: session_id.to_owned(),
roles,
exp: expiration,
};
encode(
&Header::default(),
&claims,
&EncodingKey::from_secret(secret.as_ref()),
)
}
pub fn validate_token(token: &str) -> Result<(String, String), jsonwebtoken::errors::Error> {
let secret = env::var("JWT_SECRET").expect("JWT_SECRET must be set");
let token_data = decode::<Claims>(
token,
&DecodingKey::from_secret(secret.as_ref()),
&Validation::default(),
)?;
Ok((token_data.claims.sub, token_data.claims.session_id))
}

View File

@@ -1,7 +1,7 @@
pub mod database_client;
pub mod grpc;
pub mod jwt;
pub mod session_client;
pub mod grpc;
pub mod users;
pub mod common {
@@ -11,12 +11,13 @@ pub mod common {
pub mod auth {
tonic::include_proto!("auth");
}
pub mod database {
tonic::include_proto!("user_db_api");
}
pub mod session {
tonic::include_proto!("session_service_api");
tonic::include_proto!("session_db_api");
}
#[cfg(test)]

View File

@@ -18,22 +18,21 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
dotenv().ok();
let app_name = env!("CARGO_PKG_NAME");
logging::setup_logging(app_name);
logging::setup_logging(app_name, &["auth_service"]);
// Set the gRPC server address
let addr = env::var("LISTEN_ADDR").unwrap_or_else(|_| "0.0.0.0".to_string());
let port = env::var("SERVICE_PORT").unwrap_or_else(|_| "50051".to_string());
let db_url = format!("http://{}",get_kube_service_endpoints_by_dns("database-service","tcp","database-service").await?.get(0).unwrap());
let session_service_address = format!("http://{}",get_kube_service_endpoints_by_dns("session-service","tcp","session-service").await?.get(0).unwrap());
let db_client = Arc::new(DatabaseClient::connect(&db_url).await?);
let session_client = Arc::new(SessionServiceClient::connect(session_service_address).await?);
let session_client = Arc::new(SessionServiceClient::connect(db_url).await?);
let full_addr = format!("{}:{}", &addr, port);
let address = full_addr.parse().expect("Invalid address");
let auth_service = MyAuthService {
db_client,
session_client,
session_client
};
let (mut health_reporter, health_service) = tonic_health::server::health_reporter();

View File

@@ -0,0 +1,34 @@
use crate::session::{session_service_client::SessionServiceClient, GetSessionRequest, GetSessionResponse};
use async_trait::async_trait;
use chrono::{DateTime, Utc};
use std::error::Error;
use tonic::transport::Channel;
#[async_trait]
pub trait SessionClientTrait: Sized {
async fn connect(endpoint: &str) -> Result<Self, Box<dyn std::error::Error>>;
async fn get_session(
&mut self,
session_id: String,
) -> Result<GetSessionResponse, Box<dyn std::error::Error>>;
}
#[derive(Clone)]
pub struct SessionClient {
client: SessionServiceClient<Channel>,
}
#[async_trait]
impl SessionClientTrait for SessionClient {
async fn connect(endpoint: &str) -> Result<Self, Box<dyn std::error::Error>> {
let client = SessionServiceClient::connect(endpoint.to_string()).await?;
Ok(Self { client })
}
async fn get_session(&mut self, session_id: String) -> Result<GetSessionResponse, Box<dyn Error>> {
let request = tonic::Request::new(GetSessionRequest {
session_id,
});
let response = self.client.get_session(request).await?;
Ok(response.into_inner())
}
}