- add: logout grpc function
- add: logout packet handler - add: connection state and service for storing connection data - add: session service calls to auth-service - fix: compile error on database service due to moved redis cache
This commit is contained in:
@@ -25,6 +25,7 @@ rand = "0.8.5"
|
||||
warp = "0.3.7"
|
||||
reqwest = { version = "0.12.9", features = ["json"] }
|
||||
utils = { path = "../utils" }
|
||||
uuid = "1.11.0"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.12.3"
|
||||
|
||||
@@ -11,6 +11,6 @@ fn main() {
|
||||
tonic_build::configure()
|
||||
.build_server(false) // Generate gRPC client code
|
||||
.compile_well_known_types(true)
|
||||
.compile_protos(&["../proto/user_db_api.proto"], &["../proto"])
|
||||
.compile_protos(&["../proto/user_db_api.proto", "../proto/session_service_api.proto"], &["../proto"])
|
||||
.unwrap_or_else(|e| panic!("Failed to compile protos {:?}", e));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use std::sync::Arc;
|
||||
use crate::auth::auth_service_server::AuthService;
|
||||
use crate::auth::{LoginRequest, LoginResponse, PasswordResetRequest, PasswordResetResponse, RegisterRequest, RegisterResponse, ResetPasswordRequest, ResetPasswordResponse, ValidateTokenRequest, ValidateTokenResponse};
|
||||
use crate::database_client::{DatabaseClientTrait};
|
||||
use crate::auth::{LoginRequest, LoginResponse, PasswordResetRequest, PasswordResetResponse, RegisterRequest, RegisterResponse, ResetPasswordRequest, ResetPasswordResponse, ValidateTokenRequest, ValidateTokenResponse, ValidateSessionRequest, ValidateSessionResponse, Empty, LogoutRequest};
|
||||
use crate::database_client::{DatabaseClient, DatabaseClientTrait};
|
||||
use crate::session::session_service_client::SessionServiceClient;
|
||||
use crate::session::{CreateSessionRequest, GetSessionRequest, DeleteSessionRequest};
|
||||
use crate::jwt::{generate_token, validate_token};
|
||||
use crate::users::{hash_password, verify_user};
|
||||
use chrono::{Duration, Utc};
|
||||
@@ -8,12 +11,13 @@ use rand::Rng;
|
||||
use tonic::{Request, Response, Status};
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
pub struct MyAuthService<T: DatabaseClientTrait + Clone> {
|
||||
pub db_client: T,
|
||||
pub struct MyAuthService {
|
||||
pub db_client: Arc<DatabaseClient>,
|
||||
pub session_client: Arc<SessionServiceClient<tonic::transport::Channel>>,
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyAuthService<T> {
|
||||
impl AuthService for MyAuthService {
|
||||
async fn login(
|
||||
&self,
|
||||
request: Request<LoginRequest>,
|
||||
@@ -22,17 +26,49 @@ impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyA
|
||||
|
||||
info!("Login attempt for username: {}", req.username);
|
||||
|
||||
if let Some(user_id) = verify_user(self.db_client.clone(), &req.username, &req.password).await {
|
||||
if let Some(user_id) = verify_user(self.db_client.as_ref().clone(), &req.username, &req.password).await {
|
||||
let token = generate_token(&user_id, vec!["user".to_string()])
|
||||
.map_err(|_| Status::internal("Token generation failed"))?;
|
||||
|
||||
let session_id = uuid::Uuid::new_v4().to_string();
|
||||
let response = self
|
||||
.session_client.as_ref().clone()
|
||||
.create_session(CreateSessionRequest {
|
||||
session_id: session_id.clone(),
|
||||
user_id: user_id.parse().unwrap(),
|
||||
username: req.username.to_string(),
|
||||
character_id: 0,
|
||||
ip_address: req.ip_address.to_string(),
|
||||
})
|
||||
.await;
|
||||
|
||||
let session = match response {
|
||||
Ok(session) => session,
|
||||
Err(_) => return Err(Status::internal("Session creation failed")),
|
||||
};
|
||||
let session_id = session.into_inner().session_id;
|
||||
|
||||
info!("Login successful for username: {}", req.username);
|
||||
Ok(Response::new(LoginResponse { token, user_id }))
|
||||
Ok(Response::new(LoginResponse { token, user_id, session_id }))
|
||||
} else {
|
||||
warn!("Invalid login attempt for username: {}", req.username);
|
||||
Err(Status::unauthenticated("Invalid credentials"))
|
||||
}
|
||||
}
|
||||
|
||||
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 {}))
|
||||
}
|
||||
|
||||
async fn validate_token(
|
||||
&self,
|
||||
@@ -52,6 +88,30 @@ impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyA
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate_session(
|
||||
&self,
|
||||
request: Request<ValidateSessionRequest>,
|
||||
) -> Result<Response<ValidateSessionResponse>, Status> {
|
||||
let req = request.into_inner();
|
||||
let response = self
|
||||
.session_client.as_ref().clone()
|
||||
.get_session(GetSessionRequest {
|
||||
session_id: req.session_id,
|
||||
})
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(res) => {
|
||||
println!("Session valid: {:?}", res.into_inner());
|
||||
Ok(Response::new(ValidateSessionResponse { valid: true }))
|
||||
}
|
||||
Err(_) => {
|
||||
println!("Session invalid or not found");
|
||||
Ok(Response::new(ValidateSessionResponse { valid: false }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn register(
|
||||
&self,
|
||||
request: Request<RegisterRequest>,
|
||||
@@ -62,7 +122,7 @@ impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyA
|
||||
let hashed_password = hash_password(&req.password);
|
||||
|
||||
// Create user in the database
|
||||
let result = self.db_client.clone().create_user(&req.username, &req.email, &hashed_password)
|
||||
let result = self.db_client.as_ref().clone().create_user(&req.username, &req.email, &hashed_password)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
@@ -83,7 +143,7 @@ impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyA
|
||||
) -> Result<Response<PasswordResetResponse>, Status> {
|
||||
let email = request.into_inner().email;
|
||||
|
||||
let user = self.db_client.clone().get_user_by_email(&email).await;
|
||||
let user = self.db_client.as_ref().clone().get_user_by_email(&email).await;
|
||||
|
||||
// Check if the email exists
|
||||
if user.ok().is_some() {
|
||||
@@ -98,14 +158,14 @@ impl<T: DatabaseClientTrait + Send + Sync + Clone + 'static> AuthService for MyA
|
||||
let expires_at = Utc::now() + Duration::hours(1);
|
||||
|
||||
// Store the reset token in the database
|
||||
self.db_client.clone()
|
||||
self.db_client.as_ref().clone()
|
||||
.store_password_reset(&email, &reset_token, expires_at)
|
||||
.await
|
||||
.map_err(|e| Status::internal(format!("Database error: {}", e)))?;
|
||||
|
||||
// Send the reset email
|
||||
// send_email(&email, "Password Reset Request", &format!(
|
||||
// "Click the link to reset your password: https://example.com/reset?token={}",
|
||||
// "Click the link to reset your password: https://azgstudio.com/reset?token={}",
|
||||
// reset_token
|
||||
// ))
|
||||
// .map_err(|e| Status::internal(format!("Email error: {}", e)))?;
|
||||
|
||||
@@ -4,10 +4,14 @@ pub mod database_client;
|
||||
|
||||
pub mod users;
|
||||
pub mod auth {
|
||||
tonic::include_proto!("auth"); // Path matches the package name in auth.proto
|
||||
tonic::include_proto!("auth");
|
||||
}
|
||||
pub mod database {
|
||||
tonic::include_proto!("user_db_api"); // Matches package name in user_db_api.proto
|
||||
tonic::include_proto!("user_db_api");
|
||||
}
|
||||
|
||||
pub mod session {
|
||||
tonic::include_proto!("session_service_api");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
use auth_service::auth::auth_service_server::AuthServiceServer;
|
||||
use auth_service::database_client::DatabaseClient;
|
||||
use auth_service::database_client::DatabaseClientTrait;
|
||||
use auth_service::session::session_service_client::SessionServiceClient;
|
||||
use auth_service::grpc::MyAuthService;
|
||||
use dotenv::dotenv;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use tokio::{select, signal};
|
||||
use tonic::transport::Server;
|
||||
use tracing::log::debug;
|
||||
use tracing::{info, Level};
|
||||
use utils::consul_registration;
|
||||
use utils::service_discovery::get_service_address;
|
||||
use warp::Filter;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
@@ -36,6 +35,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let health_check_url = format!("http://{}:{}/health", service_address, health_port);
|
||||
let health_check_endpoint_addr = format!("{}:{}", service_address, health_port);
|
||||
let db_nodes = get_service_address(&consul_url, "database-service").await?;
|
||||
let session_nodes = get_service_address(&consul_url, "session-service").await?;
|
||||
|
||||
// Register service with Consul
|
||||
let service_id = consul_registration::get_or_generate_service_id();
|
||||
@@ -58,12 +58,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
|
||||
let db_address = db_nodes.get(0).unwrap();
|
||||
let db_url = format!("http://{}:{}", db_address.ServiceAddress, db_address.ServicePort);
|
||||
let database_client = DatabaseClient::connect(&db_url).await?;
|
||||
let db_client = Arc::new(DatabaseClient::connect(&db_url).await?);
|
||||
|
||||
let session_address = session_nodes.get(0).unwrap();
|
||||
let session_address = format!("http://{}:{}", session_address.ServiceAddress, session_address.ServicePort);
|
||||
let session_client = Arc::new(SessionServiceClient::connect(session_address).await?);
|
||||
|
||||
let full_addr = format!("{}:{}", &addr, port);
|
||||
let address = full_addr.parse().expect("Invalid address");
|
||||
let auth_service = MyAuthService {
|
||||
db_client: database_client,
|
||||
db_client,
|
||||
session_client
|
||||
};
|
||||
|
||||
println!("Authentication Service running on {}", addr);
|
||||
|
||||
Reference in New Issue
Block a user