use std::collections::HashMap;
use poem_openapi::{payload::Json, types::Password, Object, OpenAPI, Response, API};
use tokio::sync::Mutex;
#[derive(Debug, Object, Clone, Eq, PartialEq)]
struct User {
#[oai(max_length = 20)]
id: String,
#[oai(max_length = 64)]
name: String,
#[oai(max_length = 32)]
password: Password,
}
#[derive(Debug, Object, Clone, Eq, PartialEq)]
struct UpdateUser {
name: Option<String>,
password: Option<Password>,
}
#[derive(Response)]
enum CreateUserResponse {
#[oai(status = 200)]
Ok,
#[oai(status = 409)]
UserAlreadyExists,
}
#[derive(Response)]
enum FindUserResponse {
#[oai(status = 200)]
Ok(Json<User>),
#[oai(status = 404)]
NotFound,
}
#[derive(Response)]
enum DeleteUserResponse {
#[oai(status = 200)]
Ok,
#[oai(status = 404)]
NotFound,
}
#[derive(Response)]
enum UpdateUserResponse {
#[oai(status = 200)]
Ok,
#[oai(status = 404)]
NotFound,
}
#[derive(Default)]
struct Api {
users: Mutex<HashMap<String, User>>,
}
#[API]
impl Api {
#[oai(path = "/users", method = "post", tag = "user")]
async fn create_user(&self, user: Json<User>) -> CreateUserResponse {
let mut users = self.users.lock().await;
if users.contains_key(&user.0.id) {
return CreateUserResponse::UserAlreadyExists;
}
users.insert(user.0.id.clone(), user.0);
CreateUserResponse::Ok
}
#[oai(path = "/users/:user_id", method = "get", tag = "user")]
async fn find_user(
&self,
#[oai(name = "user_id", in = "path", max_length = 20)] user_id: String,
) -> FindUserResponse {
let users = self.users.lock().await;
match users.get(&user_id) {
Some(user) => FindUserResponse::Ok(Json(user.clone())),
None => FindUserResponse::NotFound,
}
}
#[oai(path = "/users/:user_id", method = "delete", tag = "user")]
async fn delete_user(
&self,
#[oai(name = "user_id", in = "path", max_length = 20)] user_id: String,
) -> DeleteUserResponse {
let mut users = self.users.lock().await;
match users.remove(&user_id) {
Some(_) => DeleteUserResponse::Ok,
None => DeleteUserResponse::NotFound,
}
}
#[oai(path = "/users/:user_id", method = "put", tag = "user")]
async fn put_user(
&self,
#[oai(name = "user_id", in = "path", max_length = 20)] user_id: String,
update: Json<UpdateUser>,
) -> UpdateUserResponse {
let mut users = self.users.lock().await;
match users.get_mut(&user_id) {
Some(user) => {
if let Some(name) = update.0.name {
user.name = name;
}
if let Some(password) = update.0.password {
user.password = password;
}
UpdateUserResponse::Ok
}
None => UpdateUserResponse::NotFound,
}
}
}
#[tokio::main]
async fn main() {
poem::Server::bind("127.0.0.1:3000")
.await
.unwrap()
.run(
OpenAPI::new(Api::default())
.title("poem-openapi")
.version("0.1.0")
.server_with_description("http://localhost:3000", "localhost")
.tag_with_description("user", "Operations about user")
.ui_path("/"),
)
.await
.unwrap();
}