mahjong_service/http_server/
admin.rs1#![allow(clippy::await_holding_lock)]
2use crate::auth::AuthHandler;
3use crate::game_wrapper::{CreateGameOpts, GameWrapper};
4use crate::http_server::base::{get_lock, GamesManagerData};
5pub use crate::http_server::base::{DataSocketServer, DataStorage};
6use crate::service_error::{ResponseCommon, ServiceError};
7use actix_web::{get, post, web, HttpRequest, HttpResponse};
8use mahjong_core::GameId;
9use service_contracts::{
10 AdminGetGamesResponse, AdminPostAIContinueRequest, AdminPostBreakMeldRequest,
11 AdminPostClaimTileRequest, AdminPostCreateMeldRequest, AdminPostDiscardTileRequest,
12 AdminPostSayMahjongRequest,
13};
14
15#[get("/game")]
16async fn admin_get_games(storage: DataStorage, req: HttpRequest) -> ResponseCommon {
17 AuthHandler::new(&storage, &req).verify_admin()?;
18
19 let response: AdminGetGamesResponse = storage
20 .get_player_games(&None)
21 .await
22 .map_err(|_| ServiceError::Custom("Error getting games"))?;
23
24 Ok(HttpResponse::Ok().json(response))
25}
26
27#[post("/game")]
28async fn admin_post_game(
29 storage: DataStorage,
30 srv: DataSocketServer,
31 req: HttpRequest,
32) -> ResponseCommon {
33 AuthHandler::new(&storage, &req).verify_admin()?;
34
35 let new_game_opts = CreateGameOpts::default();
36 let game_wrapper = GameWrapper::from_new_game(&storage, srv, &new_game_opts)
37 .await
38 .map_err(|_| ServiceError::Custom("Error creating game"))?;
39
40 game_wrapper.handle_admin_new_game().await
41}
42
43#[get("/game/{game_id}")]
44async fn admin_get_game_by_id(
45 storage: DataStorage,
46 manager: GamesManagerData,
47 game_id: web::Path<String>,
48 req: HttpRequest,
49) -> ResponseCommon {
50 AuthHandler::new(&storage, &req).verify_admin()?;
51
52 get_lock!(manager, game_id);
53
54 let game = storage
55 .get_game(&game_id.to_string(), true)
56 .await
57 .map_err(|_| ServiceError::Custom("Error loading game"))?;
58
59 Ok(HttpResponse::Ok().json(game))
60}
61
62#[post("/game/{game_id}/sort-hands")]
63async fn admin_post_game_sort_hands(
64 manager: GamesManagerData,
65 storage: DataStorage,
66 game_id: web::Path<String>,
67 srv: DataSocketServer,
68 req: HttpRequest,
69) -> ResponseCommon {
70 AuthHandler::new(&storage, &req).verify_admin()?;
71
72 get_lock!(manager, game_id);
73
74 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
75
76 game_wrapper.handle_sort_hands().await
77}
78
79#[post("/game/{game_id}/draw-tile")]
80async fn admin_post_game_draw_tile(
81 manager: GamesManagerData,
82 storage: DataStorage,
83 game_id: web::Path<GameId>,
84 srv: DataSocketServer,
85 req: HttpRequest,
86) -> ResponseCommon {
87 AuthHandler::new(&storage, &req).verify_admin()?;
88
89 get_lock!(manager, game_id);
90
91 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
92
93 game_wrapper.handle_admin_draw_tile().await
94}
95
96#[post("/game/{game_id}/move-player")]
97async fn admin_post_game_move_player(
98 manager: GamesManagerData,
99 storage: DataStorage,
100 game_id: web::Path<String>,
101 srv: DataSocketServer,
102 req: HttpRequest,
103) -> ResponseCommon {
104 AuthHandler::new(&storage, &req).verify_admin()?;
105
106 get_lock!(manager, game_id);
107
108 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
109
110 game_wrapper.handle_admin_move_player().await
111}
112
113#[post("/game/{game_id}/break-meld")]
114async fn admin_post_game_break_meld(
115 manager: GamesManagerData,
116 storage: DataStorage,
117 body: web::Json<AdminPostBreakMeldRequest>,
118 game_id: web::Path<String>,
119 srv: DataSocketServer,
120 req: HttpRequest,
121) -> ResponseCommon {
122 AuthHandler::new(&storage, &req).verify_admin()?;
123
124 get_lock!(manager, game_id);
125
126 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
127
128 game_wrapper.handle_admin_break_meld(&body).await
129}
130
131#[post("/game/{game_id}/create-meld")]
132async fn admin_post_game_create_meld(
133 manager: GamesManagerData,
134 storage: DataStorage,
135 body: web::Json<AdminPostCreateMeldRequest>,
136 game_id: web::Path<String>,
137 srv: DataSocketServer,
138 req: HttpRequest,
139) -> ResponseCommon {
140 AuthHandler::new(&storage, &req).verify_admin()?;
141
142 get_lock!(manager, game_id);
143
144 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
145
146 game_wrapper.handle_admin_create_meld(&body).await
147}
148
149#[post("/game/{game_id}/discard-tile")]
150async fn admin_post_game_discard_tile(
151 manager: GamesManagerData,
152 storage: DataStorage,
153 body: web::Json<AdminPostDiscardTileRequest>,
154 game_id: web::Path<String>,
155 srv: DataSocketServer,
156 req: HttpRequest,
157) -> ResponseCommon {
158 AuthHandler::new(&storage, &req).verify_admin()?;
159
160 get_lock!(manager, game_id);
161
162 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
163
164 game_wrapper.handle_discard_tile_admin(&body.tile_id).await
165}
166
167#[post("/game/{game_id}/claim-tile")]
168async fn admin_post_game_claim_tile(
169 manager: GamesManagerData,
170 storage: DataStorage,
171 body: web::Json<AdminPostClaimTileRequest>,
172 game_id: web::Path<String>,
173 srv: DataSocketServer,
174 req: HttpRequest,
175) -> ResponseCommon {
176 AuthHandler::new(&storage, &req).verify_admin()?;
177
178 get_lock!(manager, game_id);
179
180 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
181
182 game_wrapper.handle_admin_claim_tile(&body.player_id).await
183}
184
185#[post("/game/{game_id}/ai-continue")]
186async fn admin_post_game_ai_continue(
187 manager: GamesManagerData,
188 storage: DataStorage,
189 game_id: web::Path<String>,
190 body: web::Json<AdminPostAIContinueRequest>,
191 srv: DataSocketServer,
192 req: HttpRequest,
193) -> ResponseCommon {
194 AuthHandler::new(&storage, &req).verify_admin()?;
195
196 get_lock!(manager, game_id);
197
198 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
199
200 game_wrapper.handle_admin_ai_continue(&body).await
201}
202
203#[post("/game/{game_id}/say-mahjong")]
204async fn admin_post_game_say_mahjong(
205 manager: GamesManagerData,
206 storage: DataStorage,
207 body: web::Json<AdminPostSayMahjongRequest>,
208 game_id: web::Path<String>,
209 srv: DataSocketServer,
210 req: HttpRequest,
211) -> ResponseCommon {
212 AuthHandler::new(&storage, &req).verify_admin()?;
213
214 get_lock!(manager, game_id);
215
216 let mut game_wrapper = GameWrapper::from_storage(&storage, &game_id, srv, None).await?;
217
218 game_wrapper.handle_admin_say_mahjong(&body.player_id).await
219}
220
221pub fn get_admin_scope() -> actix_web::Scope {
222 web::scope("/api/v1/admin")
223 .service(admin_get_game_by_id)
224 .service(admin_get_games)
225 .service(admin_post_game)
226 .service(admin_post_game_ai_continue)
227 .service(admin_post_game_break_meld)
228 .service(admin_post_game_claim_tile)
229 .service(admin_post_game_create_meld)
230 .service(admin_post_game_discard_tile)
231 .service(admin_post_game_draw_tile)
232 .service(admin_post_game_move_player)
233 .service(admin_post_game_say_mahjong)
234 .service(admin_post_game_sort_hands)
235}