main
//! 内部 RPC 的 chat 域:只做协议转换,权限判定在 `ChatService`。
use internal::Gate;
use internal::server::InternalRouter;
use proto::internal::v1::chat_authorization_service_server::{
ChatAuthorizationService as ChatAuthorizationTrait, ChatAuthorizationServiceServer,
};
use proto::internal::v1::{AuthorizationDecision, AuthorizeRoomRequest};
use tonic::{Request, Response, Status};
use crate::errors::ChatError;
use crate::services::service::ChatService;
pub fn register(router: InternalRouter, service: &ChatService, gate: Gate) -> InternalRouter {
router.add_service(ChatAuthorizationServiceServer::with_interceptor(
ChatRpc {
service: service.clone(),
},
gate,
))
}
#[derive(Clone)]
struct ChatRpc {
service: ChatService,
}
#[tonic::async_trait]
impl ChatAuthorizationTrait for ChatRpc {
async fn authorize_room(
&self,
request: Request<AuthorizeRoomRequest>,
) -> Result<Response<AuthorizationDecision>, Status> {
let _meta = internal::interceptor::meta(&request)?;
let request = request.into_inner();
let room_id = request
.room_id
.parse()
.map_err(|_| Status::invalid_argument("room_id must be a UUID"))?;
let allowed = self
.service
.authorize_internal_room(request.user_id, room_id, &request.action)
.await
.map_err(status_of)?;
Ok(Response::new(AuthorizationDecision {
allowed,
reason: String::new(),
resource_id: request.room_id,
}))
}
}
fn status_of(error: ChatError) -> Status {
match error {
ChatError::Unauthorized => Status::unauthenticated("chat authorization rejected"),
ChatError::Forbidden | ChatError::NotFound => Status::permission_denied("not allowed"),
ChatError::BadRequest(message) => Status::invalid_argument(message),
ChatError::RateLimited(message) => Status::resource_exhausted(message),
other => {
tracing::warn!(%other, "internal chat authorization failed");
Status::internal("chat authorization failed")
}
}
}