@@ -2,7 +2,6 @@ use std::fs::OpenOptions;
22use rocket:: serde:: json:: Json ;
33use std:: io:: { Cursor , Read } ;
44use anyhow:: anyhow;
5- use base64:: engine:: general_purpose;
65use image:: ImageFormat ;
76use rocket:: form:: { Contextual , Form } ;
87use rocket:: http:: { ContentType , Status } ;
@@ -121,7 +120,7 @@ struct EventFormValues<'v> {
121120// need, do not use `Contextual`. Use the equivalent of `Form<Submit<'_>>`.
122121#[ post( "/event" , data = "<form>" ) ]
123122async fn post_event < ' r > ( form : Form < Contextual < ' r , EventFormValues < ' r > > > , session_id : QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Redirect , Custom < String > > {
124- let user = user_info ( session_id, state) . await ?;
123+ let user = user_info ( & session_id, state) . await ?;
125124 let vals = form. value . as_ref ( ) . ok_or ( Custom ( Status :: BadRequest , "Form data invalid" . to_string ( ) ) ) ?;
126125 let start_time = QxDateTime :: parse_from_iso ( vals. start_time )
127126 . map_err ( |e| Custom ( Status :: BadRequest , format ! ( "Unrecognized date-time string: {}, error: {e}" , vals. start_time) ) ) ?;
@@ -149,32 +148,51 @@ async fn post_event<'r>(form: Form<Contextual<'r, EventFormValues<'r>>>, session
149148 let event_id = save_event ( & event, db) . await . map_err ( |e| Custom ( Status :: BadRequest , e. to_string ( ) ) ) ?;
150149 Ok ( Redirect :: to ( format ! ( "/event/{event_id}" ) ) )
151150}
152- pub async fn user_info ( session_id : QxSessionId , state : & State < SharedQxState > ) -> Result < UserInfo , Custom < String > > {
151+ pub async fn user_info ( session_id : & QxSessionId , state : & State < SharedQxState > ) -> Result < UserInfo , Custom < String > > {
153152 state. read ( ) . await
154153 . sessions . get ( & session_id) . map ( |s| s. user_info . clone ( ) ) . ok_or ( Custom ( Status :: Unauthorized , "Invalid session ID" . to_string ( ) ) )
155154}
156- pub async fn user_info_opt ( session_id : MaybeSessionId , state : & State < SharedQxState > ) -> anyhow:: Result < Option < UserInfo > > {
157- match session_id {
158- MaybeSessionId :: None => Ok ( None ) ,
159- MaybeSessionId :: Some ( session_id) => {
160- let user_info = state. read ( ) . await
161- . sessions . get ( & session_id) . map ( |s| s. user_info . clone ( ) ) ;
162- Ok ( user_info)
155+ pub async fn user_info_opt ( session_id : Option < & QxSessionId > , state : & State < SharedQxState > ) -> anyhow:: Result < Option < UserInfo > > {
156+ match & session_id {
157+ None => Ok ( None ) ,
158+ Some ( session_id) => {
159+ get_user_info ( session_id, state) . await
163160 }
164161 }
165162}
166163
167- pub async fn user_and_event_owner_opt ( event_id : EventId , session_id : MaybeSessionId , state : & State < SharedQxState > , gdb : & State < DbPool > ) -> anyhow:: Result < Option < UserInfo > > {
164+ pub async fn get_user_info ( session_id : & QxSessionId , state : & State < SharedQxState > ) -> anyhow:: Result < Option < UserInfo > > {
165+ let user_info = state. read ( ) . await
166+ . sessions . get ( session_id) . map ( |s| s. user_info . clone ( ) ) ;
167+ Ok ( user_info)
168+ }
169+
170+ pub async fn event_owner_opt ( event_id : EventId , session_id : MaybeSessionId , state : & State < SharedQxState > , gdb : & State < DbPool > ) -> anyhow:: Result < Option < UserInfo > > {
168171 let event = load_event ( event_id, gdb) . await ?;
169- let user = user_info_opt ( session_id, state) . await ?
172+ let user = user_info_opt ( session_id. 0 . as_ref ( ) , state) . await ?
170173 . and_then ( |user| if user. email == event. owner { Some ( user) } else { None } ) ;
171174 Ok ( user)
172175}
173176
174- async fn event_edit_insert ( event_id : Option < EventId > , session_id : QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Template , Custom < String > > {
175- let user = user_info ( session_id, state) . await ?;
177+ pub fn is_event_owner ( event : & EventRecord , user : Option < & UserInfo > ) -> bool {
178+ if let Some ( user) = user {
179+ user. email == event. owner
180+ } else {
181+ false
182+ }
183+ }
184+
185+ async fn event_edit_insert ( event_id : Option < EventId > , session_id : & QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Template , Custom < String > > {
186+ let user = get_user_info ( session_id, state) . await
187+ . and_then ( |u| if let Some ( u) = u { Ok ( u) } else { Err ( anyhow ! ( "Invalid session ID" ) ) } )
188+ . map_err ( anyhow_to_custom_error) ?;
176189 let event = if let Some ( event_id) = event_id {
177- load_event_info ( event_id, db) . await ?
190+ let event = load_event_info ( event_id, db) . await ?;
191+ if is_event_owner ( & event, Some ( & user) ) {
192+ event
193+ } else {
194+ return Err ( Custom ( Status :: Unauthorized , "Event owner mismatch" . to_string ( ) ) )
195+ }
178196 } else {
179197 EventRecord :: new ( & user. email )
180198 } ;
@@ -186,7 +204,7 @@ async fn event_edit_insert(event_id: Option<EventId>, session_id: QxSessionId, s
186204 let mut cursor = Cursor :: new ( & mut buffer) ;
187205 image. write_to ( & mut cursor, ImageFormat :: Png ) . unwrap ( ) ;
188206 // Encode the image buffer to base64
189- general_purpose:: STANDARD . encode ( & buffer)
207+ base64 :: engine :: general_purpose:: STANDARD . encode ( & buffer)
190208 } ;
191209 Ok ( Template :: render ( "event-edit" , context ! {
192210 event_id,
@@ -205,15 +223,15 @@ async fn event_drop(event_id: EventId, db: &State<DbPool>) -> Result<(), anyhow:
205223}
206224#[ get( "/event/create" ) ]
207225async fn event_create ( session_id : QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Template , Custom < String > > {
208- event_edit_insert ( None , session_id, state, db) . await
226+ event_edit_insert ( None , & session_id, state, db) . await
209227}
210228#[ get( "/event/<event_id>/edit" ) ]
211229async fn event_edit ( event_id : EventId , session_id : QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Template , Custom < String > > {
212- event_edit_insert ( Some ( event_id) , session_id, state, db) . await
230+ event_edit_insert ( Some ( event_id) , & session_id, state, db) . await
213231}
214232#[ get( "/event/<event_id>/delete" ) ]
215233async fn event_delete ( event_id : EventId , session_id : QxSessionId , state : & State < SharedQxState > , db : & State < DbPool > ) -> Result < Redirect , Custom < String > > {
216- let user = user_info ( session_id, state) . await ?;
234+ let user = user_info ( & session_id, state) . await ?;
217235 let event = load_event_info ( event_id, db) . await ?;
218236 if event. owner == user. email {
219237 event_drop ( event_id, db) . await . map_err ( |e| Custom ( Status :: InternalServerError , e. to_string ( ) ) ) ?;
@@ -226,10 +244,12 @@ async fn event_delete(event_id: EventId, session_id: QxSessionId, state: &State<
226244#[ get( "/event/<event_id>" ) ]
227245async fn get_event ( event_id : EventId , session_id : MaybeSessionId , state : & State < SharedQxState > , gdb : & State < DbPool > ) -> Result < Template , Custom < String > > {
228246 let event = load_event_info ( event_id, gdb) . await ?;
229- let user = user_and_event_owner_opt ( event_id, session_id, state, gdb) . await . map_err ( anyhow_to_custom_error) ?;
247+ let user = user_info_opt ( session_id. 0 . as_ref ( ) , state) . await . map_err ( anyhow_to_custom_error) ?;
248+ let is_event_owner = is_event_owner ( & event, user. as_ref ( ) ) ;
230249 let files = files:: list_files ( event_id, state) . await ?;
231250 Ok ( Template :: render ( "event" , context ! {
232251 user,
252+ is_event_owner,
233253 event,
234254 files,
235255 } ) )
@@ -262,8 +282,10 @@ async fn post_api_event_current(api_token: QxApiToken, posted_event: Json<Posted
262282
263283#[ get( "/event/<event_id>/startlist?<class_name>" ) ]
264284async fn get_event_start_list ( event_id : EventId , session_id : MaybeSessionId , class_name : Option < & str > , state : & State < SharedQxState > , gdb : & State < DbPool > ) -> Result < Template , Custom < String > > {
285+ info ! ( "GET session_id: {session_id:?}" ) ;
265286 let event = load_event_info ( event_id, gdb) . await ?;
266- let user = user_and_event_owner_opt ( event_id, session_id, state, gdb) . await . map_err ( anyhow_to_custom_error) ?;
287+ let user = user_info_opt ( session_id. 0 . as_ref ( ) , state) . await . map_err ( anyhow_to_custom_error) ?;
288+ info ! ( "GET user: {user:?}" ) ;
267289 let edb = get_event_db ( event_id, state) . await . map_err ( anyhow_to_custom_error) ?;
268290 let classes = sqlx:: query_as :: < _ , ClassesRecord > ( "SELECT * FROM classes ORDER BY name" )
269291 . fetch_all ( & edb) . await . map_err ( sqlx_to_custom_error) ?;
@@ -350,7 +372,7 @@ async fn upload_start_list(qx_api_token: QxApiToken, data: Data<'_>, content_typ
350372}
351373#[ post( "/api/event/<event_id>/upload/startlist" , data = "<data>" ) ]
352374async fn upload_start_list_user ( event_id : EventId , data : Data < ' _ > , content_type : & ContentType , session_id : MaybeSessionId , state : & State < SharedQxState > , gdb : & State < DbPool > ) -> Result < String , Custom < String > > {
353- let Some ( _user ) = user_and_event_owner_opt ( event_id, session_id, state, gdb) . await . map_err ( anyhow_to_custom_error) ? else {
375+ let Some ( _event_owner ) = event_owner_opt ( event_id, session_id, state, gdb) . await . map_err ( anyhow_to_custom_error) ? else {
354376 return Err ( Custom ( Status :: Unauthorized , String :: from ( "Session expired or not valid" ) ) ) ;
355377 } ;
356378 let event_info = load_event_info ( event_id, gdb) . await ?;
0 commit comments