134 lines
3.4 KiB
Rust

use tonic::{Request, Response, Status, transport::Server};
use std::sync::Arc;
use shared_proto::user::{
user_service_server::{UserService, UserServiceServer},
GetUsersRequest, UserListResponse, User, GetUserRequest, CreateUserRequest, UserResponse,
};
use tracing_subscriber;
use audit_logger::{ActionType, AuditLogger, InMemoryAuditStore};
pub struct UserServiceImpl {
audit_logger: Arc<AuditLogger>,
}
fn create_audit_logger() -> AuditLogger {
let store = Arc::new(InMemoryAuditStore::new());
AuditLogger::new(store, "user_service")
}
#[tonic::async_trait]
impl UserService for UserServiceImpl {
async fn get_users(
&self,
_request: Request<GetUsersRequest>,
) -> Result<Response<UserListResponse>, Status> {
let _ = self
.audit_logger
.log_action(
None,
ActionType::Read,
"users".to_string(),
"/GetUsers".to_string(),
)
.await;
tracing::info!("GetUsers called");
let users = vec![
User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
},
User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
},
];
Ok(Response::new(UserListResponse { users }))
}
async fn get_user(
&self,
request: Request<GetUserRequest>,
) -> Result<Response<UserResponse>, Status> {
let user_id = request.into_inner().id;
let _ = self
.audit_logger
.log_detailed(
None,
ActionType::Read,
"users".to_string(),
"/GetUser".to_string(),
None,
None,
Some(format!("Getting user {}", user_id)),
)
.await;
tracing::info!("GetUser called with id: {}", user_id);
Ok(Response::new(UserResponse {
id: user_id,
name: "User".to_string(),
email: format!("user{}@example.com", user_id),
}))
}
async fn create_user(
&self,
request: Request<CreateUserRequest>,
) -> Result<Response<UserResponse>, Status> {
let req = request.into_inner();
let _ = self
.audit_logger
.log_detailed(
None,
ActionType::Create,
"users".to_string(),
"/CreateUser".to_string(),
None,
None,
Some(format!("Creating user: {}", req.name)),
)
.await;
tracing::info!("CreateUser called with name: {}", req.name);
Ok(Response::new(UserResponse {
id: 3,
name: req.name,
email: req.email,
}))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
let audit_logger = Arc::new(create_audit_logger());
let addr = "127.0.0.1:13001".parse()?;
let user_service = UserServiceImpl {
audit_logger: audit_logger.clone(),
};
tracing::info!("User Service gRPC server listening on {}", addr);
tracing::info!("Audit logging enabled!");
Server::builder()
.add_service(UserServiceServer::new(user_service))
.serve(addr)
.await?;
Ok(())
}