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))
|
.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.
|
/// Set a new displayname.
|
||||||
pub fn displayname_set(&self, user_id: &UserId, displayname: Option<String>) {
|
pub fn displayname_set(&self, user_id: &UserId, displayname: Option<String>) {
|
||||||
self.db
|
self.db
|
||||||
.profile_displayname
|
.userid_displayname
|
||||||
.insert(user_id.to_string(), &*displayname.unwrap_or_default())
|
.insert(user_id.to_string(), &*displayname.unwrap_or_default())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -71,16 +76,21 @@ impl Data {
|
||||||
/// Get a the displayname of a user.
|
/// Get a the displayname of a user.
|
||||||
pub fn displayname_get(&self, user_id: &UserId) -> Option<String> {
|
pub fn displayname_get(&self, user_id: &UserId) -> Option<String> {
|
||||||
self.db
|
self.db
|
||||||
.profile_displayname
|
.userid_displayname
|
||||||
.get(user_id.to_string())
|
.get(user_id.to_string())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|bytes| utils::string_from_bytes(&bytes))
|
.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.
|
/// Set a new avatar_url.
|
||||||
pub fn avatar_url_set(&self, user_id: &UserId, avatar_url: String) {
|
pub fn avatar_url_set(&self, user_id: &UserId, avatar_url: String) {
|
||||||
self.db
|
self.db
|
||||||
.profile_avatar_url
|
.userid_avatar_url
|
||||||
.insert(user_id.to_string(), &*avatar_url)
|
.insert(user_id.to_string(), &*avatar_url)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -88,7 +98,7 @@ impl Data {
|
||||||
/// Get a the avatar_url of a user.
|
/// Get a the avatar_url of a user.
|
||||||
pub fn avatar_url_get(&self, user_id: &UserId) -> Option<String> {
|
pub fn avatar_url_get(&self, user_id: &UserId) -> Option<String> {
|
||||||
self.db
|
self.db
|
||||||
.profile_avatar_url
|
.userid_avatar_url
|
||||||
.get(user_id.to_string())
|
.get(user_id.to_string())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.map(|bytes| utils::string_from_bytes(&bytes))
|
.map(|bytes| utils::string_from_bytes(&bytes))
|
||||||
|
|
|
@ -52,8 +52,8 @@ impl MultiValue {
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
pub userid_password: sled::Tree,
|
pub userid_password: sled::Tree,
|
||||||
pub userid_deviceids: MultiValue,
|
pub userid_deviceids: MultiValue,
|
||||||
pub profile_displayname: sled::Tree,
|
pub userid_displayname: sled::Tree,
|
||||||
pub profile_avatar_url: sled::Tree,
|
pub userid_avatar_url: sled::Tree,
|
||||||
pub deviceid_token: sled::Tree,
|
pub deviceid_token: sled::Tree,
|
||||||
pub token_userid: sled::Tree,
|
pub token_userid: sled::Tree,
|
||||||
pub pduid_pdus: sled::Tree,
|
pub pduid_pdus: sled::Tree,
|
||||||
|
@ -77,8 +77,8 @@ impl Database {
|
||||||
Self {
|
Self {
|
||||||
userid_password: db.open_tree("userid_password").unwrap(),
|
userid_password: db.open_tree("userid_password").unwrap(),
|
||||||
userid_deviceids: MultiValue(db.open_tree("userid_deviceids").unwrap()),
|
userid_deviceids: MultiValue(db.open_tree("userid_deviceids").unwrap()),
|
||||||
profile_displayname: db.open_tree("profile_displayname").unwrap(),
|
userid_displayname: db.open_tree("userid_displayname").unwrap(),
|
||||||
profile_avatar_url: db.open_tree("profile_avatar_url").unwrap(),
|
userid_avatar_url: db.open_tree("userid_avatar_url").unwrap(),
|
||||||
deviceid_token: db.open_tree("deviceid_token").unwrap(),
|
deviceid_token: db.open_tree("deviceid_token").unwrap(),
|
||||||
token_userid: db.open_tree("token_userid").unwrap(),
|
token_userid: db.open_tree("token_userid").unwrap(),
|
||||||
pduid_pdus: db.open_tree("pduid_pdus").unwrap(),
|
pduid_pdus: db.open_tree("pduid_pdus").unwrap(),
|
||||||
|
@ -108,7 +108,7 @@ impl Database {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
println!("# AccountData -> Displayname:");
|
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!(
|
println!(
|
||||||
"{:?} -> {:?}",
|
"{:?} -> {:?}",
|
||||||
String::from_utf8_lossy(&k),
|
String::from_utf8_lossy(&k),
|
||||||
|
@ -116,7 +116,7 @@ impl Database {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
println!("# AccountData -> AvatarURL:");
|
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!(
|
println!(
|
||||||
"{:?} -> {:?}",
|
"{:?} -> {:?}",
|
||||||
String::from_utf8_lossy(&k),
|
String::from_utf8_lossy(&k),
|
||||||
|
|
113
src/main.rs
113
src/main.rs
|
@ -1,4 +1,5 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
|
||||||
mod data;
|
mod data;
|
||||||
mod database;
|
mod database;
|
||||||
mod pdu;
|
mod pdu;
|
||||||
|
@ -88,7 +89,7 @@ fn register_route(
|
||||||
.unwrap_or_else(|| utils::random_string(GUEST_NAME_LENGTH)),
|
.unwrap_or_else(|| utils::random_string(GUEST_NAME_LENGTH)),
|
||||||
data.hostname()
|
data.hostname()
|
||||||
))
|
))
|
||||||
.try_into()
|
.try_into()
|
||||||
{
|
{
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
debug!("Username invalid");
|
debug!("Username invalid");
|
||||||
|
@ -152,7 +153,7 @@ fn login_route(data: State<Data>, body: Ruma<login::Request>) -> MatrixResult<lo
|
||||||
// Validate login method
|
// Validate login method
|
||||||
let user_id =
|
let user_id =
|
||||||
if let (login::UserInfo::MatrixId(mut username), login::LoginInfo::Password { password }) =
|
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(':') {
|
if !username.contains(':') {
|
||||||
username = format!("@{}:{}", username, data.hostname());
|
username = format!("@{}:{}", username, data.hostname());
|
||||||
|
@ -229,8 +230,8 @@ fn get_pushrules_all_route() -> MatrixResult<get_pushrules_all::Response> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get(
|
#[get(
|
||||||
"/_matrix/client/r0/user/<_user_id>/filter/<_filter_id>",
|
"/_matrix/client/r0/user/<_user_id>/filter/<_filter_id>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn get_filter_route(
|
fn get_filter_route(
|
||||||
body: Ruma<get_filter::Request>,
|
body: Ruma<get_filter::Request>,
|
||||||
|
@ -261,8 +262,8 @@ fn create_filter_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put(
|
#[put(
|
||||||
"/_matrix/client/r0/user/<_user_id>/account_data/<_type>",
|
"/_matrix/client/r0/user/<_user_id>/account_data/<_type>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn set_global_account_data_route(
|
fn set_global_account_data_route(
|
||||||
body: Ruma<set_global_account_data::Request>,
|
body: Ruma<set_global_account_data::Request>,
|
||||||
|
@ -274,8 +275,8 @@ fn set_global_account_data_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get(
|
#[get(
|
||||||
"/_matrix/client/r0/user/<_user_id>/account_data/<_type>",
|
"/_matrix/client/r0/user/<_user_id>/account_data/<_type>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn get_global_account_data_route(
|
fn get_global_account_data_route(
|
||||||
body: Ruma<get_global_account_data::Request>,
|
body: Ruma<get_global_account_data::Request>,
|
||||||
|
@ -297,25 +298,35 @@ fn set_displayname_route(
|
||||||
_user_id: String,
|
_user_id: String,
|
||||||
) -> MatrixResult<set_display_name::Response> {
|
) -> MatrixResult<set_display_name::Response> {
|
||||||
let user_id = body.user_id.clone().expect("user is authenticated");
|
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() {
|
if body.displayname.is_none() {
|
||||||
debug!("Request was missing the displayname payload.");
|
debug!("Request was missing the displayname payload.");
|
||||||
return MatrixResult(Err(Error {
|
return MatrixResult(Err(Error {
|
||||||
kind: ErrorKind::MissingParam,
|
kind: ErrorKind::MissingParam,
|
||||||
message: "Missing displayname".to_owned(),
|
message: "Missing displayname.".to_owned(),
|
||||||
status_code: http::StatusCode::BAD_REQUEST,
|
status_code: http::StatusCode::BAD_REQUEST,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
data.displayname_set(&user_id, body.displayname.clone());
|
if let Some(displayname) = body.displayname {
|
||||||
// TODO send a new m.room.member join event with the updated displayname
|
if displayname == "" {
|
||||||
// TODO send a new m.presence event with the updated 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))
|
MatrixResult(Ok(set_display_name::Response))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get(
|
#[get(
|
||||||
"/_matrix/client/r0/profile/<user_id_raw>/displayname",
|
"/_matrix/client/r0/profile/<user_id_raw>/displayname",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn get_displayname_route(
|
fn get_displayname_route(
|
||||||
data: State<Data>,
|
data: State<Data>,
|
||||||
|
@ -323,20 +334,26 @@ fn get_displayname_route(
|
||||||
user_id_raw: String,
|
user_id_raw: String,
|
||||||
) -> MatrixResult<get_display_name::Response> {
|
) -> MatrixResult<get_display_name::Response> {
|
||||||
let user_id = (*body).user_id.clone();
|
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) {
|
if let Some(displayname) = data.displayname_get(&user_id) {
|
||||||
return MatrixResult(Ok(get_display_name::Response {
|
return MatrixResult(Ok(get_display_name::Response {
|
||||||
displayname: Some(displayname),
|
displayname: Some(displayname),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 404 if we don't have any
|
MatrixResult(Ok(get_display_name::Response {
|
||||||
debug!("Profile was not found.");
|
displayname: None,
|
||||||
MatrixResult(Err(Error {
|
|
||||||
kind: ErrorKind::NotFound,
|
|
||||||
message: "Profile was not found".to_owned(),
|
|
||||||
status_code: http::StatusCode::NOT_FOUND,
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/_matrix/client/r0/profile/<_user_id>/avatar_url", data = "<body>")]
|
#[put("/_matrix/client/r0/profile/<_user_id>/avatar_url", data = "<body>")]
|
||||||
fn set_avatar_url_route(
|
fn set_avatar_url_route(
|
||||||
data: State<Data>,
|
data: State<Data>,
|
||||||
|
@ -344,21 +361,28 @@ fn set_avatar_url_route(
|
||||||
_user_id: String,
|
_user_id: String,
|
||||||
) -> MatrixResult<set_avatar_url::Response> {
|
) -> MatrixResult<set_avatar_url::Response> {
|
||||||
let user_id = body.user_id.clone().expect("user is authenticated");
|
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 {
|
return MatrixResult(Err(Error {
|
||||||
kind: ErrorKind::MissingParam,
|
kind: ErrorKind::InvalidParam,
|
||||||
message: "Missing avatar_url".to_owned(),
|
message: "Missing avatar_url".to_owned(),
|
||||||
status_code: http::StatusCode::BAD_REQUEST,
|
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 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
|
if body.avatar_url == "" {
|
||||||
// TODO send a new m.presence event with the updated 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))
|
MatrixResult(Ok(set_avatar_url::Response))
|
||||||
}
|
}
|
||||||
|
@ -370,18 +394,23 @@ fn get_avatar_url_route(
|
||||||
user_id_raw: String,
|
user_id_raw: String,
|
||||||
) -> MatrixResult<get_avatar_url::Response> {
|
) -> MatrixResult<get_avatar_url::Response> {
|
||||||
let user_id = (*body).user_id.clone();
|
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) {
|
if let Some(avatar_url) = data.avatar_url_get(&user_id) {
|
||||||
return MatrixResult(Ok(get_avatar_url::Response {
|
return MatrixResult(Ok(get_avatar_url::Response {
|
||||||
avatar_url: Some(avatar_url),
|
avatar_url: Some(avatar_url),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return 404 if we don't have a profile for this id
|
MatrixResult(Ok(get_avatar_url::Response {
|
||||||
debug!("Profile was not found.");
|
avatar_url: None,
|
||||||
MatrixResult(Err(Error {
|
|
||||||
kind: ErrorKind::NotFound,
|
|
||||||
message: "Profile was not found".to_owned(),
|
|
||||||
status_code: http::StatusCode::NOT_FOUND,
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +424,7 @@ fn get_profile_route(
|
||||||
let avatar_url = data.avatar_url_get(&user_id);
|
let avatar_url = data.avatar_url_get(&user_id);
|
||||||
let displayname = data.displayname_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 {
|
return MatrixResult(Ok(get_profile::Response {
|
||||||
avatar_url,
|
avatar_url,
|
||||||
displayname,
|
displayname,
|
||||||
|
@ -498,8 +527,8 @@ fn get_alias_route(room_alias: String) -> MatrixResult<get_alias::Response> {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
MatrixResult(Ok(get_alias::Response {
|
MatrixResult(Ok(get_alias::Response {
|
||||||
room_id,
|
room_id,
|
||||||
|
@ -606,8 +635,8 @@ fn get_protocols_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put(
|
#[put(
|
||||||
"/_matrix/client/r0/rooms/<_room_id>/send/<_event_type>/<_txn_id>",
|
"/_matrix/client/r0/rooms/<_room_id>/send/<_event_type>/<_txn_id>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn create_message_event_route(
|
fn create_message_event_route(
|
||||||
data: State<Data>,
|
data: State<Data>,
|
||||||
|
@ -631,8 +660,8 @@ fn create_message_event_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put(
|
#[put(
|
||||||
"/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>/<_state_key>",
|
"/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>/<_state_key>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn create_state_event_for_key_route(
|
fn create_state_event_for_key_route(
|
||||||
data: State<Data>,
|
data: State<Data>,
|
||||||
|
@ -654,8 +683,8 @@ fn create_state_event_for_key_route(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put(
|
#[put(
|
||||||
"/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>",
|
"/_matrix/client/r0/rooms/<_room_id>/state/<_event_type>",
|
||||||
data = "<body>"
|
data = "<body>"
|
||||||
)]
|
)]
|
||||||
fn create_state_event_for_empty_key_route(
|
fn create_state_event_for_empty_key_route(
|
||||||
data: State<Data>,
|
data: State<Data>,
|
||||||
|
|
Loading…
Reference in a new issue