Replace profile_* with userid_*
Add a missing dot in the errormessage Require mxc:// to be present at the start of an avatar_url Update mxc check TODO Show displayname or avatar_url if either is available when getting the profile Endpoint Return the correct data in case of a empty displayname or an empty avatar_url Took 50 minutes Took 34 seconds
This commit is contained in:
		
							parent
							
								
									062c5521f0
								
							
						
					
					
						commit
						b1284fd509
					
				
					 3 changed files with 91 additions and 52 deletions
				
			
		
							
								
								
									
										18
									
								
								src/data.rs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/data.rs
									
									
									
									
									
								
							|  | @ -60,10 +60,15 @@ impl Data { | |||
|             .map(|bytes| utils::string_from_bytes(&bytes)) | ||||
|     } | ||||
| 
 | ||||
|     /// Removes a displayname.
 | ||||
|     pub fn displayname_remove(&self, user_id: &UserId) { | ||||
|         self.db.userid_displayname.remove(user_id).unwrap(); | ||||
|     } | ||||
| 
 | ||||
|     /// Set a new displayname.
 | ||||
|     pub fn displayname_set(&self, user_id: &UserId, displayname: Option<String>) { | ||||
|         self.db | ||||
|             .profile_displayname | ||||
|             .userid_displayname | ||||
|             .insert(user_id.to_string(), &*displayname.unwrap_or_default()) | ||||
|             .unwrap(); | ||||
|     } | ||||
|  | @ -71,16 +76,21 @@ impl Data { | |||
|     /// Get a the displayname of a user.
 | ||||
|     pub fn displayname_get(&self, user_id: &UserId) -> Option<String> { | ||||
|         self.db | ||||
|             .profile_displayname | ||||
|             .userid_displayname | ||||
|             .get(user_id.to_string()) | ||||
|             .unwrap() | ||||
|             .map(|bytes| utils::string_from_bytes(&bytes)) | ||||
|     } | ||||
| 
 | ||||
|     /// Removes a avatar_url.
 | ||||
|     pub fn avatar_url_remove(&self, user_id: &UserId) { | ||||
|         self.db.userid_avatar_url.remove(user_id).unwrap(); | ||||
|     } | ||||
| 
 | ||||
|     /// Set a new avatar_url.
 | ||||
|     pub fn avatar_url_set(&self, user_id: &UserId, avatar_url: String) { | ||||
|         self.db | ||||
|             .profile_avatar_url | ||||
|             .userid_avatar_url | ||||
|             .insert(user_id.to_string(), &*avatar_url) | ||||
|             .unwrap(); | ||||
|     } | ||||
|  | @ -88,7 +98,7 @@ impl Data { | |||
|     /// Get a the avatar_url of a user.
 | ||||
|     pub fn avatar_url_get(&self, user_id: &UserId) -> Option<String> { | ||||
|         self.db | ||||
|             .profile_avatar_url | ||||
|             .userid_avatar_url | ||||
|             .get(user_id.to_string()) | ||||
|             .unwrap() | ||||
|             .map(|bytes| utils::string_from_bytes(&bytes)) | ||||
|  |  | |||
|  | @ -52,8 +52,8 @@ impl MultiValue { | |||
| pub struct Database { | ||||
|     pub userid_password: sled::Tree, | ||||
|     pub userid_deviceids: MultiValue, | ||||
|     pub profile_displayname: sled::Tree, | ||||
|     pub profile_avatar_url: sled::Tree, | ||||
|     pub userid_displayname: sled::Tree, | ||||
|     pub userid_avatar_url: sled::Tree, | ||||
|     pub deviceid_token: sled::Tree, | ||||
|     pub token_userid: sled::Tree, | ||||
|     pub pduid_pdus: sled::Tree, | ||||
|  | @ -77,8 +77,8 @@ impl Database { | |||
|         Self { | ||||
|             userid_password: db.open_tree("userid_password").unwrap(), | ||||
|             userid_deviceids: MultiValue(db.open_tree("userid_deviceids").unwrap()), | ||||
|             profile_displayname: db.open_tree("profile_displayname").unwrap(), | ||||
|             profile_avatar_url: db.open_tree("profile_avatar_url").unwrap(), | ||||
|             userid_displayname: db.open_tree("userid_displayname").unwrap(), | ||||
|             userid_avatar_url: db.open_tree("userid_avatar_url").unwrap(), | ||||
|             deviceid_token: db.open_tree("deviceid_token").unwrap(), | ||||
|             token_userid: db.open_tree("token_userid").unwrap(), | ||||
|             pduid_pdus: db.open_tree("pduid_pdus").unwrap(), | ||||
|  | @ -108,7 +108,7 @@ impl Database { | |||
|             ); | ||||
|         } | ||||
|         println!("# AccountData -> Displayname:"); | ||||
|         for (k, v) in self.profile_displayname.iter().map(|r| r.unwrap()) { | ||||
|         for (k, v) in self.userid_displayname.iter().map(|r| r.unwrap()) { | ||||
|             println!( | ||||
|                 "{:?} -> {:?}", | ||||
|                 String::from_utf8_lossy(&k), | ||||
|  | @ -116,7 +116,7 @@ impl Database { | |||
|             ); | ||||
|         } | ||||
|         println!("# AccountData -> AvatarURL:"); | ||||
|         for (k, v) in self.profile_avatar_url.iter().map(|r| r.unwrap()) { | ||||
|         for (k, v) in self.userid_avatar_url.iter().map(|r| r.unwrap()) { | ||||
|             println!( | ||||
|                 "{:?} -> {:?}", | ||||
|                 String::from_utf8_lossy(&k), | ||||
|  |  | |||
							
								
								
									
										113
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								src/main.rs
									
									
									
									
									
								
							|  | @ -1,4 +1,5 @@ | |||
| #![feature(proc_macro_hygiene, decl_macro)] | ||||
| 
 | ||||
| mod data; | ||||
| mod database; | ||||
| mod pdu; | ||||
|  | @ -88,7 +89,7 @@ fn register_route( | |||
|             .unwrap_or_else(|| utils::random_string(GUEST_NAME_LENGTH)), | ||||
|         data.hostname() | ||||
|     )) | ||||
|     .try_into() | ||||
|         .try_into() | ||||
|     { | ||||
|         Err(_) => { | ||||
|             debug!("Username invalid"); | ||||
|  | @ -152,7 +153,7 @@ fn login_route(data: State<Data>, body: Ruma<login::Request>) -> MatrixResult<lo | |||
|     // Validate login method
 | ||||
|     let user_id = | ||||
|         if let (login::UserInfo::MatrixId(mut username), login::LoginInfo::Password { password }) = | ||||
|             (body.user.clone(), body.login_info.clone()) | ||||
|         (body.user.clone(), body.login_info.clone()) | ||||
|         { | ||||
|             if !username.contains(':') { | ||||
|                 username = format!("@{}:{}", username, data.hostname()); | ||||
|  | @ -229,8 +230,8 @@ fn get_pushrules_all_route() -> MatrixResult<get_pushrules_all::Response> { | |||
| } | ||||
| 
 | ||||
| #[get(
 | ||||
|     "/_matrix/client/r0/user/<_user_id>/filter/<_filter_id>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/user/<_user_id>/filter/<_filter_id>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn get_filter_route( | ||||
|     body: Ruma<get_filter::Request>, | ||||
|  | @ -261,8 +262,8 @@ fn create_filter_route( | |||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|     "/_matrix/client/r0/user/<_user_id>/account_data/<_type>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/user/<_user_id>/account_data/<_type>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn set_global_account_data_route( | ||||
|     body: Ruma<set_global_account_data::Request>, | ||||
|  | @ -274,8 +275,8 @@ fn set_global_account_data_route( | |||
| } | ||||
| 
 | ||||
| #[get(
 | ||||
|     "/_matrix/client/r0/user/<_user_id>/account_data/<_type>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/user/<_user_id>/account_data/<_type>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn get_global_account_data_route( | ||||
|     body: Ruma<get_global_account_data::Request>, | ||||
|  | @ -297,25 +298,35 @@ fn set_displayname_route( | |||
|     _user_id: String, | ||||
| ) -> MatrixResult<set_display_name::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
| 
 | ||||
|     // Send error on None and accept Some("") as valid username
 | ||||
|     // Synapse returns a parsing error but the spec doesn't require this
 | ||||
|     if body.displayname.is_none() { | ||||
|         debug!("Request was missing the displayname payload."); | ||||
|         return MatrixResult(Err(Error { | ||||
|             kind: ErrorKind::MissingParam, | ||||
|             message: "Missing displayname".to_owned(), | ||||
|             message: "Missing displayname.".to_owned(), | ||||
|             status_code: http::StatusCode::BAD_REQUEST, | ||||
|         })); | ||||
|     } | ||||
| 
 | ||||
|     data.displayname_set(&user_id, body.displayname.clone()); | ||||
|     // TODO send a new m.room.member join event with the updated displayname
 | ||||
|     // TODO send a new m.presence event with the updated displayname
 | ||||
|     if let Some(displayname) = body.displayname { | ||||
|         if displayname == "" { | ||||
|             data.displayname_remove(&user_id); | ||||
|         } else { | ||||
|             data.displayname_set(&user_id, body.displayname.clone()); | ||||
|             // TODO send a new m.room.member join event with the updated displayname
 | ||||
|             // TODO send a new m.presence event with the updated displayname
 | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     MatrixResult(Ok(set_display_name::Response)) | ||||
| } | ||||
| 
 | ||||
| #[get(
 | ||||
|     "/_matrix/client/r0/profile/<user_id_raw>/displayname", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/profile/<user_id_raw>/displayname", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn get_displayname_route( | ||||
|     data: State<Data>, | ||||
|  | @ -323,20 +334,26 @@ fn get_displayname_route( | |||
|     user_id_raw: String, | ||||
| ) -> MatrixResult<get_display_name::Response> { | ||||
|     let user_id = (*body).user_id.clone(); | ||||
|     if !data.user_exists(&user_id) { | ||||
|         // Return 404 if we don't have a profile for this id
 | ||||
|         debug!("Profile was not found."); | ||||
|         MatrixResult(Err(Error { | ||||
|             kind: ErrorKind::NotFound, | ||||
|             message: "Profile was not found".to_owned(), | ||||
|             status_code: http::StatusCode::NOT_FOUND, | ||||
|         })) | ||||
|     } | ||||
|     if let Some(displayname) = data.displayname_get(&user_id) { | ||||
|         return MatrixResult(Ok(get_display_name::Response { | ||||
|             displayname: Some(displayname), | ||||
|         })); | ||||
|     } | ||||
| 
 | ||||
|     // Return 404 if we don't have any
 | ||||
|     debug!("Profile was not found."); | ||||
|     MatrixResult(Err(Error { | ||||
|         kind: ErrorKind::NotFound, | ||||
|         message: "Profile was not found".to_owned(), | ||||
|         status_code: http::StatusCode::NOT_FOUND, | ||||
|     MatrixResult(Ok(get_display_name::Response { | ||||
|         displayname: None, | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
| #[put("/_matrix/client/r0/profile/<_user_id>/avatar_url", data = "<body>")] | ||||
| fn set_avatar_url_route( | ||||
|     data: State<Data>, | ||||
|  | @ -344,21 +361,28 @@ fn set_avatar_url_route( | |||
|     _user_id: String, | ||||
| ) -> MatrixResult<set_avatar_url::Response> { | ||||
|     let user_id = body.user_id.clone().expect("user is authenticated"); | ||||
|     if body.avatar_url == "" { | ||||
|         debug!("Request was missing the avatar_url payload."); | ||||
| 
 | ||||
|     if !body.avatar_url.starts_with("mxc://") { | ||||
|         debug!("Request contains an invalid avatar_url."); | ||||
|         return MatrixResult(Err(Error { | ||||
|             kind: ErrorKind::MissingParam, | ||||
|             kind: ErrorKind::InvalidParam, | ||||
|             message: "Missing avatar_url".to_owned(), | ||||
|             status_code: http::StatusCode::BAD_REQUEST, | ||||
|         })); | ||||
|     } | ||||
| 
 | ||||
|     // TODO in the future when we can handle media uploads make sure that this url is our own server
 | ||||
|     // TODO also make sure this is mxc:// format
 | ||||
|     // TODO also make sure this is valid mxc:// format (not only starting with it)
 | ||||
| 
 | ||||
|     data.avatar_url_set(&user_id, body.avatar_url.clone()); | ||||
|     // TODO send a new m.room.member join event with the updated avatar_url
 | ||||
|     // TODO send a new m.presence event with the updated avatar_url
 | ||||
| 
 | ||||
|     if body.avatar_url == "" { | ||||
|         data.avatar_url_remove(&user_id); | ||||
|     } else { | ||||
|         data.avatar_url_set(&user_id, body.displayname.clone()); | ||||
|         // TODO send a new m.room.member join event with the updated avatar_url
 | ||||
|         // TODO send a new m.presence event with the updated avatar_url
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     MatrixResult(Ok(set_avatar_url::Response)) | ||||
| } | ||||
|  | @ -370,18 +394,23 @@ fn get_avatar_url_route( | |||
|     user_id_raw: String, | ||||
| ) -> MatrixResult<get_avatar_url::Response> { | ||||
|     let user_id = (*body).user_id.clone(); | ||||
|     if !data.user_exists(&user_id) { | ||||
|         // Return 404 if we don't have a profile for this id
 | ||||
|         debug!("Profile was not found."); | ||||
|         MatrixResult(Err(Error { | ||||
|             kind: ErrorKind::NotFound, | ||||
|             message: "Profile was not found".to_owned(), | ||||
|             status_code: http::StatusCode::NOT_FOUND, | ||||
|         })) | ||||
|     } | ||||
|     if let Some(avatar_url) = data.avatar_url_get(&user_id) { | ||||
|         return MatrixResult(Ok(get_avatar_url::Response { | ||||
|             avatar_url: Some(avatar_url), | ||||
|         })); | ||||
|     } | ||||
| 
 | ||||
|     // Return 404 if we don't have a profile for this id
 | ||||
|     debug!("Profile was not found."); | ||||
|     MatrixResult(Err(Error { | ||||
|         kind: ErrorKind::NotFound, | ||||
|         message: "Profile was not found".to_owned(), | ||||
|         status_code: http::StatusCode::NOT_FOUND, | ||||
|     MatrixResult(Ok(get_avatar_url::Response { | ||||
|         avatar_url: None, | ||||
|     })) | ||||
| } | ||||
| 
 | ||||
|  | @ -395,7 +424,7 @@ fn get_profile_route( | |||
|     let avatar_url = data.avatar_url_get(&user_id); | ||||
|     let displayname = data.displayname_get(&user_id); | ||||
| 
 | ||||
|     if avatar_url.is_some() && displayname.is_some() { | ||||
|     if avatar_url.is_some() || displayname.is_some() { | ||||
|         return MatrixResult(Ok(get_profile::Response { | ||||
|             avatar_url, | ||||
|             displayname, | ||||
|  | @ -498,8 +527,8 @@ fn get_alias_route(room_alias: String) -> MatrixResult<get_alias::Response> { | |||
|             })); | ||||
|         } | ||||
|     } | ||||
|     .try_into() | ||||
|     .unwrap(); | ||||
|         .try_into() | ||||
|         .unwrap(); | ||||
| 
 | ||||
|     MatrixResult(Ok(get_alias::Response { | ||||
|         room_id, | ||||
|  | @ -606,8 +635,8 @@ fn get_protocols_route( | |||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|     "/_matrix/client/r0/rooms/<_room_id>/send/<_event_type>/<_txn_id>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/rooms/<_room_id>/send/<_event_type>/<_txn_id>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn create_message_event_route( | ||||
|     data: State<Data>, | ||||
|  | @ -631,8 +660,8 @@ fn create_message_event_route( | |||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|     "/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>/<_state_key>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>/<_state_key>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn create_state_event_for_key_route( | ||||
|     data: State<Data>, | ||||
|  | @ -654,8 +683,8 @@ fn create_state_event_for_key_route( | |||
| } | ||||
| 
 | ||||
| #[put(
 | ||||
|     "/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>", | ||||
|     data = "<body>" | ||||
| "/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>", | ||||
| data = "<body>" | ||||
| )] | ||||
| fn create_state_event_for_empty_key_route( | ||||
|     data: State<Data>, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue