1- use axum:: { Json , http:: StatusCode , response:: IntoResponse } ;
1+ use axum:: { Json , extract :: Path , http:: StatusCode , response:: IntoResponse } ;
22use fortifier:: { Validate , ValidationErrors } ;
3+ use serde:: Deserialize ;
34use thiserror:: Error ;
5+ use utoipa:: IntoParams ;
46use utoipa_axum:: { router:: OpenApiRouter , routes} ;
57use uuid:: Uuid ;
68
7- use crate :: user:: {
8- entities:: user,
9- schemas:: { CreateUser , CreateUserValidationError } ,
9+ use crate :: {
10+ email_address:: entities:: email_address,
11+ user:: {
12+ entities:: user,
13+ schemas:: {
14+ CreateUser , CreateUserValidationError , UpdateUser , UpdateUserValidationError ,
15+ UserWithEmailAddresses ,
16+ } ,
17+ } ,
1018} ;
1119
1220pub struct UserRoutes ;
@@ -16,7 +24,9 @@ impl UserRoutes {
1624 where
1725 S : Clone + Send + Sync + ' static ,
1826 {
19- OpenApiRouter :: new ( ) . routes ( routes ! ( create_user) )
27+ OpenApiRouter :: new ( )
28+ . routes ( routes ! ( create_user) )
29+ . routes ( routes ! ( user, update_user, delete_user) )
2030 }
2131}
2232
@@ -28,7 +38,11 @@ enum CreateUserError {
2838
2939impl IntoResponse for CreateUserError {
3040 fn into_response ( self ) -> axum:: response:: Response {
31- todo ! ( )
41+ match self {
42+ CreateUserError :: UnprocessableContent ( errors) => {
43+ ( StatusCode :: UNPROCESSABLE_ENTITY , Json ( errors) ) . into_response ( )
44+ }
45+ }
3246 }
3347}
3448
@@ -41,21 +55,149 @@ impl IntoResponse for CreateUserError {
4155 tags = [ "User" ] ,
4256 request_body = CreateUser ,
4357 responses(
44- ( status = 201 , description = "The created user." , body = user:: Model ) ,
45- ( status = 400 , description = "Validation error." , body = ValidationErrors <CreateUserValidationError >) ,
46- // (status = 500, description = "Internal server error.", body = ErrorBody),
58+ ( status = CREATED , description = "The created user." , body = UserWithEmailAddresses ) ,
59+ ( status = UNPROCESSABLE_ENTITY , description = "Validation error." , body = ValidationErrors <CreateUserValidationError >) ,
4760 )
4861) ]
4962async fn create_user (
5063 Json ( data) : Json < CreateUser > ,
51- ) -> Result < ( StatusCode , Json < user :: Model > ) , CreateUserError > {
64+ ) -> Result < ( StatusCode , Json < UserWithEmailAddresses > ) , CreateUserError > {
5265 data. validate ( ) . await ?;
5366
5467 let user = user:: Model {
5568 id : Uuid :: now_v7 ( ) ,
56- email_address : data. email_address ,
5769 name : data. name ,
5870 } ;
5971
60- Ok ( ( StatusCode :: CREATED , Json ( user) ) )
72+ let mut email_addresses = Vec :: with_capacity ( data. email_addresses . len ( ) ) ;
73+ for email_address_data in data. email_addresses {
74+ email_addresses. push ( email_address:: Model {
75+ id : Uuid :: now_v7 ( ) ,
76+ email_addres : email_address_data. email_address ,
77+ label : email_address_data. label ,
78+ } ) ;
79+ }
80+
81+ Ok ( (
82+ StatusCode :: CREATED ,
83+ Json ( UserWithEmailAddresses {
84+ model : user,
85+ email_addresses,
86+ } ) ,
87+ ) )
88+ }
89+
90+ #[ derive( Deserialize , IntoParams ) ]
91+ #[ serde( rename_all = "camelCase" ) ]
92+ pub struct UserPathParams {
93+ user_id : Uuid ,
94+ }
95+
96+ #[ utoipa:: path(
97+ get,
98+ path = "/users/{userId}" ,
99+ operation_id = "getUser" ,
100+ summary = "Get user" ,
101+ description = "Get a user." ,
102+ tags = [ "User" ] ,
103+ params(
104+ UserPathParams ,
105+ ) ,
106+ responses(
107+ ( status = OK , description = "The user." , body = UserWithEmailAddresses ) ,
108+ ( status = NOT_FOUND , description = "Not found error." ) ,
109+ )
110+ ) ]
111+ async fn user (
112+ Path ( UserPathParams { user_id } ) : Path < UserPathParams > ,
113+ ) -> Result < Json < UserWithEmailAddresses > , StatusCode > {
114+ // TODO
115+
116+ let user = user:: Model {
117+ id : user_id,
118+ name : "" . to_owned ( ) ,
119+ } ;
120+
121+ let email_addresses = vec ! [ ] ;
122+
123+ Ok ( Json ( UserWithEmailAddresses {
124+ model : user,
125+ email_addresses,
126+ } ) )
127+ }
128+
129+ #[ derive( Debug , Error ) ]
130+ enum UpdateUserError {
131+ #[ error( transparent) ]
132+ UnprocessableContent ( #[ from] ValidationErrors < UpdateUserValidationError > ) ,
133+ }
134+
135+ impl IntoResponse for UpdateUserError {
136+ fn into_response ( self ) -> axum:: response:: Response {
137+ match self {
138+ UpdateUserError :: UnprocessableContent ( errors) => {
139+ ( StatusCode :: UNPROCESSABLE_ENTITY , Json ( errors) ) . into_response ( )
140+ }
141+ }
142+ }
143+ }
144+
145+ #[ utoipa:: path(
146+ patch,
147+ path = "/users/{userId}" ,
148+ operation_id = "updateUser" ,
149+ summary = "Update user" ,
150+ description = "Update a user." ,
151+ tags = [ "User" ] ,
152+ params(
153+ UserPathParams ,
154+ ) ,
155+ request_body = UpdateUser ,
156+ responses(
157+ ( status = OK , description = "The updated user." , body = UserWithEmailAddresses ) ,
158+ ( status = UNPROCESSABLE_ENTITY , description = "Validation error." , body = ValidationErrors <UpdateUserValidationError >) ,
159+ )
160+ ) ]
161+ async fn update_user (
162+ Path ( UserPathParams { user_id } ) : Path < UserPathParams > ,
163+ Json ( data) : Json < UpdateUser > ,
164+ ) -> Result < Json < UserWithEmailAddresses > , UpdateUserError > {
165+ data. validate ( ) . await ?;
166+
167+ // TODO
168+
169+ let user = user:: Model {
170+ id : user_id,
171+ name : "" . to_owned ( ) ,
172+ } ;
173+
174+ let email_addresses = vec ! [ ] ;
175+
176+ Ok ( Json ( UserWithEmailAddresses {
177+ model : user,
178+ email_addresses,
179+ } ) )
180+ }
181+
182+ #[ utoipa:: path(
183+ delete,
184+ path = "/users/{userId}" ,
185+ operation_id = "deleteUser" ,
186+ summary = "Delete user" ,
187+ description = "Delete a user." ,
188+ tags = [ "User" ] ,
189+ params(
190+ UserPathParams ,
191+ ) ,
192+ responses(
193+ ( status = NO_CONTENT , description = "The user was deleted." , ) ,
194+ ( status = NOT_FOUND , description = "Not found error." ) ,
195+ )
196+ ) ]
197+ async fn delete_user (
198+ Path ( UserPathParams { user_id : _user_id } ) : Path < UserPathParams > ,
199+ ) -> Result < StatusCode , StatusCode > {
200+ // TODO
201+
202+ Ok ( StatusCode :: NO_CONTENT )
61203}
0 commit comments