[Add] Structure
This commit is contained in:
parent
70015c4d69
commit
826fb9ce50
44 changed files with 2210 additions and 2721 deletions
43
src/transport/handlers/account.rs
Normal file
43
src/transport/handlers/account.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use std::sync::Arc;
|
||||
|
||||
async fn delete(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
result: impl std::future::Future<Output = crate::error::Result<()>>,
|
||||
) -> OmikronResult<()> {
|
||||
let response = match result.await {
|
||||
Ok(()) => CommunicationValue::new(CommunicationType::Success),
|
||||
Err(error) => CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.add_typed_default(DataType::ErrorType, DataValue::Str(error.to_string())),
|
||||
};
|
||||
connection.send(&response.with_id(value.get_id())).await
|
||||
}
|
||||
|
||||
pub async fn user(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
delete(
|
||||
connection,
|
||||
value.clone(),
|
||||
user_repo::delete_user(UserId::from(value.get_sender() as i64)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
pub async fn iota(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
delete(
|
||||
connection,
|
||||
value.clone(),
|
||||
iota_repo::delete_iota(IotaId::from(value.get_sender() as i64)),
|
||||
)
|
||||
.await
|
||||
}
|
||||
1
src/transport/handlers/calls.rs
Normal file
1
src/transport/handlers/calls.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
/* Call and WebRTC commands are reserved for the transport extensions that define those protocol values. */
|
||||
21
src/transport/handlers/links.rs
Normal file
21
src/transport/handlers/links.rs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::server::short_link::add_short_link;
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn shorten(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let link = value
|
||||
.get_data(DataType::Link)
|
||||
.as_str()
|
||||
.ok_or(crate::error::OmegaError::InvalidResponse)?;
|
||||
let short = add_short_link(link)
|
||||
.await
|
||||
.map_err(|_| crate::error::OmegaError::Transport("short link error".to_string()))?;
|
||||
let response = CommunicationValue::new(CommunicationType::ShortenLink)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::Link, DataValue::Str(short));
|
||||
connection.send(&response).await
|
||||
}
|
||||
1
src/transport/handlers/messaging.rs
Normal file
1
src/transport/handlers/messaging.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
/* Message delivery remains in the connection dispatcher until the protocol exposes a separate message handler contract. */
|
||||
9
src/transport/handlers/mod.rs
Normal file
9
src/transport/handlers/mod.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
pub mod account;
|
||||
pub mod calls;
|
||||
pub mod links;
|
||||
pub mod messaging;
|
||||
pub mod notifications;
|
||||
pub mod presence;
|
||||
pub mod register;
|
||||
pub mod states;
|
||||
pub mod user_data;
|
||||
116
src/transport/handlers/notifications.rs
Normal file
116
src/transport/handlers/notifications.rs
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::{db::notification_repo, log, models::UserId};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use mtp::type_map::TypeMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn get(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let notifications =
|
||||
match notification_repo::get_notifications(UserId::from(value.get_sender() as i64)).await {
|
||||
Ok(items) => items
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let tm = TypeMap::latest();
|
||||
let Some(sender) = DataType::SenderId.try_to_id(&tm) else {
|
||||
return DataValue::Container(Vec::new());
|
||||
};
|
||||
let Some(amount) = DataType::Amount.try_to_id(&tm) else {
|
||||
return DataValue::Container(Vec::new());
|
||||
};
|
||||
DataValue::Container(vec![
|
||||
(sender, DataValue::SignedNumber(item.sender_id.0.into())),
|
||||
(amount, DataValue::SignedNumber(item.amount.into())),
|
||||
])
|
||||
})
|
||||
.collect(),
|
||||
Err(error) => {
|
||||
log!(
|
||||
crate::util::logger::PrintType::General,
|
||||
"SQL get_notifications error: {}",
|
||||
error
|
||||
);
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
let response = CommunicationValue::new(CommunicationType::GetNotifications)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::Notifications, DataValue::Array(notifications));
|
||||
connection.send(&response).await
|
||||
}
|
||||
|
||||
pub async fn read(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let receiver = match value.get_sender() {
|
||||
sender if sender > 0 => sender as i64,
|
||||
_ => match value.get_data(DataType::ReceiverId).as_number() {
|
||||
Some(id) => id as i64,
|
||||
None => return Ok(()),
|
||||
},
|
||||
};
|
||||
let Some(other) = value
|
||||
.get_data(DataType::SenderId)
|
||||
.as_number()
|
||||
.map(|id| id as i64)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
if let Err(error) =
|
||||
notification_repo::read_notification(UserId::from(receiver), UserId::from(other)).await
|
||||
{
|
||||
log!(
|
||||
crate::util::logger::PrintType::General,
|
||||
"SQL read_notification error: {}",
|
||||
error
|
||||
);
|
||||
} else {
|
||||
let response =
|
||||
CommunicationValue::new(CommunicationType::ReadNotification).with_id(value.get_id());
|
||||
let _ = connection.send(&response).await;
|
||||
let sync = CommunicationValue::new(CommunicationType::ReadNotification)
|
||||
.with_receiver(receiver as u64)
|
||||
.add_typed_default(DataType::SenderId, DataValue::SignedNumber(other.into()));
|
||||
crate::transport::omikron_manager::send_to_user(receiver, &sync).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn push(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let receiver = match value.get_receiver() {
|
||||
receiver if receiver > 0 => receiver as i64,
|
||||
_ => match value.get_data(DataType::ReceiverId).as_number() {
|
||||
Some(id) => id as i64,
|
||||
None => return Ok(()),
|
||||
},
|
||||
};
|
||||
let sender = value
|
||||
.get_data(DataType::SenderId)
|
||||
.as_number()
|
||||
.map(|id| id as i64)
|
||||
.unwrap_or(value.get_sender() as i64);
|
||||
if let Err(error) =
|
||||
notification_repo::add_notification(UserId::from(receiver), UserId::from(sender)).await
|
||||
{
|
||||
log!(
|
||||
crate::util::logger::PrintType::General,
|
||||
"SQL add_notification error: {}",
|
||||
error
|
||||
);
|
||||
} else {
|
||||
let response =
|
||||
CommunicationValue::new(CommunicationType::PushNotification).with_id(value.get_id());
|
||||
let _ = connection.send(&response).await;
|
||||
let push = CommunicationValue::new(CommunicationType::PushNotification)
|
||||
.with_receiver(receiver as u64)
|
||||
.add_typed_default(DataType::SenderId, DataValue::SignedNumber(sender.into()));
|
||||
crate::transport::omikron_manager::send_to_user(receiver, &push).await;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
128
src/transport/handlers/presence.rs
Normal file
128
src/transport/handlers/presence.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::{
|
||||
db::user_repo,
|
||||
log_in,
|
||||
models::IotaId,
|
||||
sql::{connection_status::UserStatus, user_online_tracker},
|
||||
};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn user_connected(
|
||||
_connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
log_in!(crate::util::logger::PrintType::Omega, "User connected");
|
||||
if let Some(user_id) = value.get_data(DataType::UserId).as_number() {
|
||||
let status = value
|
||||
.get_data(DataType::UserState)
|
||||
.as_str()
|
||||
.and_then(UserStatus::from_str)
|
||||
.unwrap_or(UserStatus::user_online);
|
||||
if let Ok(user_id) = i64::try_from(user_id) {
|
||||
user_online_tracker::track_user_status(user_id, status, omikron_id);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn user_disconnected(
|
||||
_: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
log_in!(crate::util::logger::PrintType::Omega, "User disconnected");
|
||||
if let Some(user_id) = value.get_data(DataType::UserId).as_number() {
|
||||
user_online_tracker::untrack_user_status(user_id as i64, omikron_id);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn iota_connected(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
log_in!(crate::util::logger::PrintType::Omega, "IOTA connected");
|
||||
let Some(iota_id) = value
|
||||
.get_data(DataType::IotaId)
|
||||
.as_number()
|
||||
.map(|id| id as i64)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
user_online_tracker::track_iota_connection(iota_id, omikron_id, true);
|
||||
let mut user_ids = Vec::new();
|
||||
match user_repo::get_users_by_iota_id(IotaId::from(iota_id)).await {
|
||||
Ok(users) => {
|
||||
for user in users {
|
||||
user_ids.push(DataValue::SignedNumber(user.id.0.into()));
|
||||
user_online_tracker::track_user_status(
|
||||
user.id.0,
|
||||
UserStatus::user_offline,
|
||||
omikron_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(_) => log_in!(
|
||||
crate::util::logger::PrintType::General,
|
||||
"SQL error loading users for IOTA"
|
||||
),
|
||||
}
|
||||
let response = CommunicationValue::new(CommunicationType::IotaUserData)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()))
|
||||
.add_typed_default(DataType::UserIds, DataValue::Array(user_ids));
|
||||
let _ = connection.send(&response).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn iota_disconnected(
|
||||
_: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
log_in!(crate::util::logger::PrintType::Omega, "IOTA disconnected");
|
||||
let Some(iota_id) = value
|
||||
.get_data(DataType::IotaId)
|
||||
.as_number()
|
||||
.map(|id| id as i64)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
if user_online_tracker::untrack_iota_connection(iota_id, omikron_id) {
|
||||
if let Ok(users) = user_repo::get_users_by_iota_id(IotaId::from(iota_id)).await {
|
||||
user_online_tracker::untrack_many_users(
|
||||
&users.iter().map(|user| user.id.0).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn sync_status(
|
||||
_: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
if let DataValue::Array(ids) = value.get_data(DataType::UserIds) {
|
||||
for id in ids {
|
||||
if let DataValue::SignedNumber(id) = id {
|
||||
user_online_tracker::track_user_status(
|
||||
*id as i64,
|
||||
UserStatus::user_offline,
|
||||
omikron_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let DataValue::Array(ids) = value.get_data(DataType::IotaIds) {
|
||||
for id in ids {
|
||||
if let DataValue::SignedNumber(id) = id {
|
||||
user_online_tracker::track_iota_connection(*id as i64, omikron_id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
151
src/transport/handlers/register.rs
Normal file
151
src/transport/handlers/register.rs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
};
|
||||
use mtp::{
|
||||
codec::{CommunicationType, CommunicationValue, DataType, DataValue},
|
||||
crypto::PublicKeyBundle,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn get_register(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let register_id = user_repo::get_register_id().await?;
|
||||
let response = CommunicationValue::new(CommunicationType::GetRegister)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(
|
||||
DataType::UserId,
|
||||
DataValue::SignedNumber(register_id.0.into()),
|
||||
);
|
||||
connection.send(&response).await
|
||||
}
|
||||
|
||||
pub async fn complete_iota(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let iota_id = value
|
||||
.get_data(DataType::IotaId)
|
||||
.as_number()
|
||||
.map(|id| id as i64);
|
||||
let public_key = value
|
||||
.get_data(DataType::PublicKey)
|
||||
.as_str()
|
||||
.and_then(|key| PublicKeyBundle::from_base64(key).ok());
|
||||
let Some(public_key) = public_key else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
};
|
||||
match iota_id {
|
||||
Some(iota_id) => {
|
||||
match iota_repo::register_complete_iota(IotaId::from(iota_id), public_key).await {
|
||||
Ok(()) => {
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::Success)
|
||||
.with_id(value.get_id()),
|
||||
)
|
||||
.await
|
||||
}
|
||||
Err(error) => {
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(
|
||||
DataType::ErrorType,
|
||||
DataValue::Str(error.to_string()),
|
||||
),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
None => match iota_repo::create_new_iota(public_key).await {
|
||||
Ok(id) => {
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::CompleteRegisterIota)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(
|
||||
DataType::IotaId,
|
||||
DataValue::SignedNumber(id.0.into()),
|
||||
),
|
||||
)
|
||||
.await
|
||||
}
|
||||
Err(error) => {
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(
|
||||
DataType::ErrorType,
|
||||
DataValue::Str(error.to_string()),
|
||||
),
|
||||
)
|
||||
.await
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn complete_user(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let user_id = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_number()
|
||||
.map(|id| id as i64);
|
||||
let username = value
|
||||
.get_data(DataType::Username)
|
||||
.as_str()
|
||||
.map(str::to_owned);
|
||||
let public_key = value
|
||||
.get_data(DataType::PublicKey)
|
||||
.as_str()
|
||||
.and_then(|key| PublicKeyBundle::from_base64(key).ok());
|
||||
let reset_token = value
|
||||
.get_data(DataType::ResetToken)
|
||||
.as_str()
|
||||
.map(str::to_owned);
|
||||
let Some((user_id, username, public_key, reset_token)) = user_id
|
||||
.zip(username)
|
||||
.zip(public_key)
|
||||
.zip(reset_token)
|
||||
.map(|(((id, name), key), token)| (id, name, key, token))
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
};
|
||||
match user_repo::register_complete_user(
|
||||
UserId::from(user_id),
|
||||
username,
|
||||
public_key,
|
||||
IotaId::from(value.get_sender() as i64),
|
||||
reset_token,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(()) => {
|
||||
connection
|
||||
.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id()))
|
||||
.await
|
||||
}
|
||||
Err(error) => {
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::ErrorType, DataValue::Str(error.to_string())),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/transport/handlers/states.rs
Normal file
46
src/transport/handlers/states.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::sql::{connection_status::UserStatus, user_online_tracker};
|
||||
use mtp::{
|
||||
codec::{CommunicationType, CommunicationValue, DataType, DataValue},
|
||||
type_map::TypeMap,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn get(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let DataValue::Array(ids) = value.get_data(DataType::UserIds) else {
|
||||
return Ok(());
|
||||
};
|
||||
let tm = TypeMap::latest();
|
||||
let states = ids
|
||||
.iter()
|
||||
.filter_map(|id| {
|
||||
let DataValue::SignedNumber(id) = id else {
|
||||
return None;
|
||||
};
|
||||
let status = user_online_tracker::get_user_status(*id as i64)
|
||||
.map(|status| {
|
||||
if status.connection_type == UserStatus::user_invisible {
|
||||
UserStatus::user_offline.to_string()
|
||||
} else {
|
||||
status.connection_type.to_string()
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| UserStatus::iota_offline.to_string());
|
||||
let mut map = Vec::new();
|
||||
if let Some(kind) = DataType::UserId.try_to_id(&tm) {
|
||||
map.push((kind, DataValue::SignedNumber((*id as i64).into())));
|
||||
}
|
||||
if let Some(kind) = DataType::UserState.try_to_id(&tm) {
|
||||
map.push((kind, DataValue::Str(status)));
|
||||
}
|
||||
Some(DataValue::Container(map))
|
||||
})
|
||||
.collect();
|
||||
let response = CommunicationValue::new(CommunicationType::GetStates)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::UserStates, DataValue::Array(states));
|
||||
connection.send(&response).await
|
||||
}
|
||||
271
src/transport/handlers/user_data.rs
Normal file
271
src/transport/handlers/user_data.rs
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
sql::{connection_status::UserStatus, user_online_tracker},
|
||||
};
|
||||
use base64::{Engine as _, engine::general_purpose::STANDARD};
|
||||
use mtp::{
|
||||
codec::{CommunicationType, CommunicationValue, DataType, DataValue},
|
||||
crypto::PublicKeyBundle,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
fn connections(iota_id: i64) -> DataValue {
|
||||
DataValue::Array(
|
||||
user_online_tracker::get_iota_omikron_connections(iota_id)
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|id| DataValue::SignedNumber(id.into()))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn get_user(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let user = if let Some(id) = value.get_data(DataType::UserId).as_number() {
|
||||
user_repo::get_by_user_id(UserId::from(id as i64))
|
||||
.await
|
||||
.ok()
|
||||
} else if let Some(name) = value.get_data(DataType::Username).as_str() {
|
||||
user_repo::get_by_username(name).await.ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let Some(user) = user else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
};
|
||||
let id = user.id.0;
|
||||
let iota_id = user.iota_id.0;
|
||||
let username = user.username.clone();
|
||||
let display = user
|
||||
.display
|
||||
.filter(|name| !name.is_empty())
|
||||
.unwrap_or_else(|| username.clone());
|
||||
let mut response = CommunicationValue::new(CommunicationType::GetUserData)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::Username, DataValue::Str(username))
|
||||
.add_typed_default(
|
||||
DataType::PublicKey,
|
||||
DataValue::Str(user.public_key.to_base64()),
|
||||
)
|
||||
.add_typed_default(DataType::UserId, DataValue::SignedNumber(id.into()))
|
||||
.add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()))
|
||||
.add_typed_default(DataType::Display, DataValue::Str(display))
|
||||
.add_typed_default(
|
||||
DataType::SubLevel,
|
||||
DataValue::SignedNumber(user.sub_level as i128),
|
||||
)
|
||||
.add_typed_default(
|
||||
DataType::SubEnd,
|
||||
DataValue::SignedNumber(user.sub_end.into()),
|
||||
);
|
||||
if let Some(status) = user.status.filter(|value| !value.is_empty()) {
|
||||
response = response.add_typed_default(DataType::Status, DataValue::Str(status));
|
||||
}
|
||||
if let Some(about) = user.about.filter(|value| !value.is_empty()) {
|
||||
response = response.add_typed_default(DataType::About, DataValue::Str(about));
|
||||
}
|
||||
if let Some(avatar) = user.avatar {
|
||||
response =
|
||||
response.add_typed_default(DataType::Avatar, DataValue::Str(STANDARD.encode(avatar)));
|
||||
}
|
||||
let online = user_online_tracker::get_user_status(id);
|
||||
response = response
|
||||
.add_typed_default(
|
||||
DataType::OnlineStatus,
|
||||
DataValue::Str(
|
||||
online
|
||||
.as_ref()
|
||||
.map(|status| {
|
||||
if status.connection_type == UserStatus::user_invisible {
|
||||
UserStatus::user_offline.to_string()
|
||||
} else {
|
||||
status.connection_type.to_string()
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|| UserStatus::iota_offline.to_string()),
|
||||
),
|
||||
)
|
||||
.add_typed_default(DataType::OmikronConnections, connections(iota_id));
|
||||
if let Some(status) = online {
|
||||
response = response.add_typed_default(
|
||||
DataType::OmikronId,
|
||||
DataValue::SignedNumber(status.omikron_id.into()),
|
||||
);
|
||||
}
|
||||
connection.send(&response).await
|
||||
}
|
||||
|
||||
pub async fn get_iota(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let found = if let Some(id) = value.get_data(DataType::IotaId).as_number() {
|
||||
iota_repo::get_iota_by_id(IotaId::from(id as i64))
|
||||
.await
|
||||
.ok()
|
||||
.map(|iota| (iota.id.0, iota.public_key, None, None))
|
||||
} else if let Some(id) = value.get_data(DataType::UserId).as_number() {
|
||||
if let Ok(user) = user_repo::get_by_user_id(UserId::from(id as i64)).await {
|
||||
iota_repo::get_iota_by_id(user.iota_id)
|
||||
.await
|
||||
.ok()
|
||||
.map(|iota| (iota.id.0, iota.public_key, Some(user.id.0), None))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else if let Some(name) = value.get_data(DataType::Username).as_str() {
|
||||
if let Ok(user) = user_repo::get_by_username(name).await {
|
||||
iota_repo::get_iota_by_id(user.iota_id)
|
||||
.await
|
||||
.ok()
|
||||
.map(|iota| {
|
||||
(
|
||||
iota.id.0,
|
||||
iota.public_key,
|
||||
Some(user.id.0),
|
||||
Some(name.to_owned()),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let Some((id, key, user_id, username)) = found else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
};
|
||||
let mut response = CommunicationValue::new(CommunicationType::GetIotaData)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::PublicKey, DataValue::Str(key.to_base64()))
|
||||
.add_typed_default(DataType::IotaId, DataValue::SignedNumber(id.into()))
|
||||
.add_typed_default(DataType::OmikronConnections, connections(id));
|
||||
if let Some(user_id) = user_id {
|
||||
response =
|
||||
response.add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id.into()));
|
||||
}
|
||||
if let Some(username) = username {
|
||||
response = response.add_typed_default(DataType::Username, DataValue::Str(username));
|
||||
}
|
||||
connection.send(&response).await
|
||||
}
|
||||
|
||||
async fn update_user(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let id = UserId::from(value.get_sender() as i64);
|
||||
let mut error = None;
|
||||
if let Some(name) = value.get_data(DataType::Username).as_str() {
|
||||
error = user_repo::change_username(id, name.to_owned())
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
if error.is_none() {
|
||||
if let Some(name) = value.get_data(DataType::Display).as_str() {
|
||||
error = user_repo::change_display_name(id, name.to_owned())
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
}
|
||||
if error.is_none() {
|
||||
if let Some(avatar) = value.get_data(DataType::Avatar).as_str() {
|
||||
error = user_repo::change_avatar(id, avatar.to_owned())
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
}
|
||||
if error.is_none() {
|
||||
if let Some(about) = value.get_data(DataType::About).as_str() {
|
||||
error = user_repo::change_about(id, about.to_owned())
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
}
|
||||
if error.is_none() {
|
||||
if let Some(status) = value.get_data(DataType::Status).as_str() {
|
||||
error = user_repo::change_status(id, status.to_owned())
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
}
|
||||
if error.is_none() {
|
||||
if let Some(key) = value
|
||||
.get_data(DataType::PublicKey)
|
||||
.as_str()
|
||||
.and_then(|key| PublicKeyBundle::from_base64(key).ok())
|
||||
{
|
||||
error = user_repo::change_keys(id, key)
|
||||
.await
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
}
|
||||
}
|
||||
let response = match error {
|
||||
None => CommunicationValue::new(CommunicationType::Success),
|
||||
Some(error) => CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.add_typed_default(DataType::ErrorType, DataValue::Str(error)),
|
||||
};
|
||||
connection.send(&response.with_id(value.get_id())).await
|
||||
}
|
||||
|
||||
pub async fn change_user(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
update_user(connection, value).await
|
||||
}
|
||||
|
||||
pub async fn change_iota(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(reset) = value.get_data(DataType::ResetToken).as_str() else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
};
|
||||
let Some(new_token) = value.get_data(DataType::NewToken).as_str() else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
};
|
||||
let user_id = UserId::from(value.get_sender() as i64);
|
||||
let user = match user_repo::get_by_user_id(user_id).await {
|
||||
Ok(user) => user,
|
||||
Err(_) => {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
}
|
||||
};
|
||||
if user.token != reset {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
}
|
||||
let result =
|
||||
match user_repo::change_iota_id(user_id, IotaId::from(value.get_sender() as i64)).await {
|
||||
Ok(()) => user_repo::change_token(user_id, new_token.to_owned()).await,
|
||||
Err(error) => Err(error),
|
||||
};
|
||||
let response = match result {
|
||||
Ok(()) => CommunicationValue::new(CommunicationType::Success),
|
||||
Err(error) => CommunicationValue::new(CommunicationType::ErrorInternal)
|
||||
.add_typed_default(DataType::ErrorType, DataValue::Str(error.to_string())),
|
||||
};
|
||||
connection.send(&response.with_id(value.get_id())).await
|
||||
}
|
||||
Loading…
Reference in a new issue