[WIP] 0.3.0 mtp update
This commit is contained in:
parent
94278630bf
commit
b814c3776d
19 changed files with 1009 additions and 278 deletions
|
|
@ -1,10 +1,15 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
state::AccountChallengeOperation,
|
||||
};
|
||||
use mtp::{codec::{CommunicationType, CommunicationValue, DataType, DataValue}, crypto::{verify_ed25519, verify_ml_dsa}};
|
||||
use mtp::{
|
||||
codec::{CommunicationType, CommunicationValue, DataType, DataValue},
|
||||
crypto::{verify_ed25519, verify_ml_dsa},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
async fn delete(
|
||||
|
|
@ -67,14 +72,22 @@ pub async fn release_from_iota(
|
|||
let previous_iota = user.iota_id;
|
||||
match user_repo::change_iota_id(user.id, None).await {
|
||||
Ok(()) => {
|
||||
if let Some(iota) = previous_iota { crate::transport::omikron_manager::publish_iota_user_snapshot(iota.0).await; }
|
||||
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,
|
||||
if let Some(iota) = previous_iota {
|
||||
crate::transport::omikron_manager::publish_iota_user_snapshot(iota.0).await;
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,43 +100,121 @@ fn lifecycle_payload(domain: &[u8], user_id: i64, iota_id: i64, nonce: u64) -> V
|
|||
payload
|
||||
}
|
||||
|
||||
pub async fn attach_begin(connection: Arc<OmikronConnection>, value: CommunicationValue) -> OmikronResult<()> {
|
||||
let Some(user_id) = value.get_data(DataType::UserId).as_signed_number().and_then(|v| i64::try_from(v).ok()).filter(|v| *v > 0) else {
|
||||
return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId).await;
|
||||
pub async fn attach_begin(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(user_id) = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_signed_number()
|
||||
.and_then(|v| i64::try_from(v).ok())
|
||||
.filter(|v| *v > 0)
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId)
|
||||
.await;
|
||||
};
|
||||
if user_repo::get_by_user_id(UserId::from(user_id)).await.is_err() {
|
||||
return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotFound).await;
|
||||
if user_repo::get_by_user_id(UserId::from(user_id))
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
}
|
||||
let requester = value.get_sender() as i64;
|
||||
let nonce = connection.state().issue_challenge(AccountChallengeOperation::Attach, user_id, requester);
|
||||
connection.send(&CommunicationValue::new(CommunicationType::AttachUserChallenge).with_id(value.get_id())
|
||||
.add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id.into()))
|
||||
.add_typed_default(DataType::ServerNonce, DataValue::SignedNumber(nonce.into()))).await
|
||||
let nonce =
|
||||
connection
|
||||
.state()
|
||||
.issue_challenge(AccountChallengeOperation::Attach, user_id, requester);
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::AttachUserChallenge)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id.into()))
|
||||
.add_typed_default(DataType::ServerNonce, DataValue::SignedNumber(nonce.into())),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn attach_complete(connection: Arc<OmikronConnection>, value: CommunicationValue) -> OmikronResult<()> {
|
||||
let Some(user_id) = value.get_data(DataType::UserId).as_signed_number().and_then(|v| i64::try_from(v).ok()).filter(|v| *v > 0) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId).await; };
|
||||
pub async fn attach_complete(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(user_id) = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_signed_number()
|
||||
.and_then(|v| i64::try_from(v).ok())
|
||||
.filter(|v| *v > 0)
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId)
|
||||
.await;
|
||||
};
|
||||
let requester = value.get_sender() as i64;
|
||||
let Some(nonce) = value.get_data(DataType::ServerNonce).as_signed_number().and_then(|v| u64::try_from(v).ok()) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; };
|
||||
let Some(nonce) = value
|
||||
.get_data(DataType::ServerNonce)
|
||||
.as_signed_number()
|
||||
.and_then(|v| u64::try_from(v).ok())
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
};
|
||||
let signature = value.get_data(DataType::Signature).as_bytes();
|
||||
let pq_signature = value.get_data(DataType::PqSignature).as_bytes();
|
||||
let (Some(signature), Some(pq_signature)) = (signature, pq_signature) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; };
|
||||
if !connection.state().consume_challenge(AccountChallengeOperation::Attach, user_id, requester, nonce) { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; }
|
||||
let Ok(user) = user_repo::get_by_user_id(UserId::from(user_id)).await else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotFound).await; };
|
||||
let (Some(signature), Some(pq_signature)) = (signature, pq_signature) else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
};
|
||||
if !connection.state().consume_challenge(
|
||||
AccountChallengeOperation::Attach,
|
||||
user_id,
|
||||
requester,
|
||||
nonce,
|
||||
) {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
}
|
||||
let Ok(user) = user_repo::get_by_user_id(UserId::from(user_id)).await else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
};
|
||||
let payload = lifecycle_payload(b"tensamin:user-attach:v1\0", user_id, requester, nonce);
|
||||
if verify_ed25519(&user.public_key.sig_cl_public_key, &payload, &signature).is_err() || verify_ml_dsa(&user.public_key.sig_pq_public_key, &payload, &pq_signature).is_err() { return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated).await; }
|
||||
if verify_ed25519(&user.public_key.sig_cl_public_key, &payload, &signature).is_err()
|
||||
|| verify_ml_dsa(&user.public_key.sig_pq_public_key, &payload, &pq_signature).is_err()
|
||||
{
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated)
|
||||
.await;
|
||||
}
|
||||
let previous_iota = user.iota_id;
|
||||
match user_repo::change_iota_id(user.id, Some(IotaId::from(requester))).await {
|
||||
Ok(()) => {
|
||||
if let Some(iota) = previous_iota.filter(|id| id.0 != requester) { crate::transport::omikron_manager::publish_iota_user_snapshot(iota.0).await; }
|
||||
if let Some(iota) = previous_iota.filter(|id| id.0 != requester) {
|
||||
crate::transport::omikron_manager::publish_iota_user_snapshot(iota.0).await;
|
||||
}
|
||||
crate::transport::omikron_manager::publish_iota_user_snapshot(requester).await;
|
||||
connection.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id())).await
|
||||
},
|
||||
Err(_) => connection.send_error_response(value.get_id(), CommunicationType::ErrorInternal).await,
|
||||
connection
|
||||
.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id()))
|
||||
.await
|
||||
}
|
||||
Err(_) => {
|
||||
connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInternal)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn complete_delete(connection: Arc<OmikronConnection>, value: CommunicationValue, user_id: UserId) -> OmikronResult<()> {
|
||||
async fn complete_delete(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
user_id: UserId,
|
||||
) -> OmikronResult<()> {
|
||||
match user_repo::delete_user_with_pending_erasure(user_id).await {
|
||||
Ok(iota_id) => {
|
||||
let cleanup_pending = iota_id.is_some();
|
||||
|
|
@ -131,45 +222,160 @@ async fn complete_delete(connection: Arc<OmikronConnection>, value: Communicatio
|
|||
crate::transport::omikron_manager::publish_iota_user_snapshot(iota_id.0).await;
|
||||
crate::transport::omikron_manager::deliver_pending_erasures(iota_id.0).await;
|
||||
}
|
||||
connection.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id())
|
||||
.add_typed_default(DataType::CleanupPending, DataValue::Bool(cleanup_pending))).await
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::Success)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(
|
||||
DataType::CleanupPending,
|
||||
DataValue::Bool(cleanup_pending),
|
||||
),
|
||||
)
|
||||
.await
|
||||
}
|
||||
Err(crate::error::OmegaError::NotFound) => {
|
||||
connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.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
|
||||
}
|
||||
Err(crate::error::OmegaError::NotFound) => connection.send_error_response(value.get_id(), CommunicationType::ErrorNotFound).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 delete_credential_begin(connection: Arc<OmikronConnection>, value: CommunicationValue) -> OmikronResult<()> {
|
||||
let Some(user_id) = value.get_data(DataType::UserId).as_signed_number().and_then(|v| i64::try_from(v).ok()).filter(|v| *v > 0) else {
|
||||
return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId).await;
|
||||
pub async fn delete_credential_begin(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(user_id) = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_signed_number()
|
||||
.and_then(|v| i64::try_from(v).ok())
|
||||
.filter(|v| *v > 0)
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId)
|
||||
.await;
|
||||
};
|
||||
if user_repo::get_by_user_id(UserId::from(user_id)).await.is_err() { return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotFound).await; }
|
||||
if user_repo::get_by_user_id(UserId::from(user_id))
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
}
|
||||
let requester = value.get_sender() as i64;
|
||||
let nonce = connection.state().issue_challenge(AccountChallengeOperation::Delete, user_id, requester);
|
||||
connection.send(&CommunicationValue::new(CommunicationType::DeleteUserCredentialChallenge).with_id(value.get_id())
|
||||
.add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id.into()))
|
||||
.add_typed_default(DataType::ServerNonce, DataValue::SignedNumber(nonce.into()))).await
|
||||
let nonce =
|
||||
connection
|
||||
.state()
|
||||
.issue_challenge(AccountChallengeOperation::Delete, user_id, requester);
|
||||
connection
|
||||
.send(
|
||||
&CommunicationValue::new(CommunicationType::DeleteUserCredentialChallenge)
|
||||
.with_id(value.get_id())
|
||||
.add_typed_default(DataType::UserId, DataValue::SignedNumber(user_id.into()))
|
||||
.add_typed_default(DataType::ServerNonce, DataValue::SignedNumber(nonce.into())),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_credential_complete(connection: Arc<OmikronConnection>, value: CommunicationValue) -> OmikronResult<()> {
|
||||
let Some(user_id) = value.get_data(DataType::UserId).as_signed_number().and_then(|v| i64::try_from(v).ok()).filter(|v| *v > 0) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId).await; };
|
||||
pub async fn delete_credential_complete(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(user_id) = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_signed_number()
|
||||
.and_then(|v| i64::try_from(v).ok())
|
||||
.filter(|v| *v > 0)
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId)
|
||||
.await;
|
||||
};
|
||||
let requester = value.get_sender() as i64;
|
||||
let Some(nonce) = value.get_data(DataType::ServerNonce).as_signed_number().and_then(|v| u64::try_from(v).ok()) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; };
|
||||
let (Some(signature), Some(pq_signature)) = (value.get_data(DataType::Signature).as_bytes(), value.get_data(DataType::PqSignature).as_bytes()) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; };
|
||||
if !connection.state().consume_challenge(AccountChallengeOperation::Delete, user_id, requester, nonce) { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge).await; }
|
||||
let Ok(user) = user_repo::get_by_user_id(UserId::from(user_id)).await else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotFound).await; };
|
||||
let Some(nonce) = value
|
||||
.get_data(DataType::ServerNonce)
|
||||
.as_signed_number()
|
||||
.and_then(|v| u64::try_from(v).ok())
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
};
|
||||
let (Some(signature), Some(pq_signature)) = (
|
||||
value.get_data(DataType::Signature).as_bytes(),
|
||||
value.get_data(DataType::PqSignature).as_bytes(),
|
||||
) else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
};
|
||||
if !connection.state().consume_challenge(
|
||||
AccountChallengeOperation::Delete,
|
||||
user_id,
|
||||
requester,
|
||||
nonce,
|
||||
) {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidChallenge)
|
||||
.await;
|
||||
}
|
||||
let Ok(user) = user_repo::get_by_user_id(UserId::from(user_id)).await else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotFound)
|
||||
.await;
|
||||
};
|
||||
let payload = lifecycle_payload(b"tensamin:user-delete:v1\0", user_id, requester, nonce);
|
||||
if verify_ed25519(&user.public_key.sig_cl_public_key, &payload, &signature).is_err() || verify_ml_dsa(&user.public_key.sig_pq_public_key, &payload, &pq_signature).is_err() { return connection.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated).await; }
|
||||
if verify_ed25519(&user.public_key.sig_cl_public_key, &payload, &signature).is_err()
|
||||
|| verify_ml_dsa(&user.public_key.sig_pq_public_key, &payload, &pq_signature).is_err()
|
||||
{
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated)
|
||||
.await;
|
||||
}
|
||||
complete_delete(connection, value, user.id).await
|
||||
}
|
||||
|
||||
pub async fn erase_hosted_user_data_ack(connection: Arc<OmikronConnection>, value: CommunicationValue) -> OmikronResult<()> {
|
||||
let Some(user_id) = value.get_data(DataType::UserId).as_signed_number().and_then(|v| i64::try_from(v).ok()).filter(|v| *v > 0) else { return connection.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId).await; };
|
||||
pub async fn erase_hosted_user_data_ack(
|
||||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(user_id) = value
|
||||
.get_data(DataType::UserId)
|
||||
.as_signed_number()
|
||||
.and_then(|v| i64::try_from(v).ok())
|
||||
.filter(|v| *v > 0)
|
||||
else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidUserId)
|
||||
.await;
|
||||
};
|
||||
let iota_id = IotaId::from(value.get_sender() as i64);
|
||||
match user_repo::acknowledge_pending_erasure(UserId::from(user_id), iota_id).await {
|
||||
Ok(true) => connection.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id())).await,
|
||||
Ok(false) => connection.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated).await,
|
||||
Err(_) => connection.send_error_response(value.get_id(), CommunicationType::ErrorInternal).await,
|
||||
Ok(true) => {
|
||||
connection
|
||||
.send(&CommunicationValue::new(CommunicationType::Success).with_id(value.get_id()))
|
||||
.await
|
||||
}
|
||||
Ok(false) => {
|
||||
connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorNotAuthenticated)
|
||||
.await
|
||||
}
|
||||
Err(_) => {
|
||||
connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInternal)
|
||||
.await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::server::short_link::add_short_link;
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use std::sync::Arc;
|
||||
|
|
@ -7,8 +9,8 @@ pub async fn shorten(
|
|||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let link = value
|
||||
.get_data(DataType::Link)
|
||||
let link_data = value.get_data(DataType::Link);
|
||||
let link = link_data
|
||||
.as_str()
|
||||
.ok_or(crate::error::OmegaError::InvalidResponse)?;
|
||||
let short = add_short_link(link)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::{db::notification_repo, log, models::UserId};
|
||||
use mtp::codec::{CommunicationType, CommunicationValue, DataType, DataValue};
|
||||
use mtp::type_map::TypeMap;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::{
|
||||
db::user_repo, log_in, models::IotaId, sql::connection_status::UserStatus, state::OmegaState,
|
||||
};
|
||||
|
|
@ -19,7 +21,7 @@ fn parse_subscription(value: &CommunicationValue) -> Result<(i64, i64, Vec<i64>)
|
|||
.and_then(|id| i64::try_from(id).ok())
|
||||
.filter(|id| *id > 0)
|
||||
.ok_or("session_id")?;
|
||||
let DataValue::Array(values) = value.get_data(DataType::UserIds) else {
|
||||
let Some(DataValue::Array(values)) = value.get_data(DataType::UserIds) else {
|
||||
return Err("user_ids");
|
||||
};
|
||||
|
||||
|
|
@ -51,9 +53,10 @@ fn states_for_users(state: &OmegaState, users: &[crate::models::User]) -> HashMa
|
|||
.map(|user| {
|
||||
(
|
||||
user.id.0,
|
||||
state
|
||||
.presence
|
||||
.resolve_public_state(user.id.0, user.iota_id.map(|id| id.0).unwrap_or_default()),
|
||||
state.presence.resolve_public_state(
|
||||
user.id.0,
|
||||
user.iota_id.map(|id| id.0).unwrap_or_default(),
|
||||
),
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -349,7 +352,7 @@ pub async fn set_user_state(
|
|||
.send_error_response(value.get_id(), CommunicationType::ErrorNoUserId)
|
||||
.await;
|
||||
};
|
||||
if let Some(requested_user) = value.get_data_opt(DataType::UserId) {
|
||||
if let Some(requested_user) = value.get_data(DataType::UserId) {
|
||||
let Some(requested_user_id) = requested_user
|
||||
.as_number()
|
||||
.and_then(|id| i64::try_from(id).ok())
|
||||
|
|
@ -538,12 +541,12 @@ pub async fn sync_status(
|
|||
omikron_id: i64,
|
||||
) -> OmikronResult<()> {
|
||||
let request_id = value.get_id();
|
||||
let DataValue::Array(iota_values) = value.get_data(DataType::IotaIds) else {
|
||||
let Some(DataValue::Array(iota_values)) = value.get_data(DataType::IotaIds) else {
|
||||
return connection
|
||||
.send_error_response(request_id, CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
};
|
||||
let DataValue::Array(session_values) = value.get_data(DataType::UserStates) else {
|
||||
let Some(DataValue::Array(session_values)) = value.get_data(DataType::UserStates) else {
|
||||
return connection
|
||||
.send_error_response(request_id, CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
|
|
@ -572,7 +575,7 @@ pub async fn sync_status(
|
|||
}
|
||||
|
||||
if !connection.peer_capabilities().session_snapshot_v1 {
|
||||
let DataValue::Array(user_values) = value.get_data(DataType::UserIds) else {
|
||||
let Some(DataValue::Array(user_values)) = value.get_data(DataType::UserIds) else {
|
||||
return connection
|
||||
.send_error_response(request_id, CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::db::user_repo;
|
||||
use mtp::{
|
||||
codec::{CommunicationType, CommunicationValue, DataType, DataValue},
|
||||
|
|
@ -29,7 +31,7 @@ pub async fn get(
|
|||
) -> OmikronResult<()> {
|
||||
let state = connection.state();
|
||||
let legacy_peer = !connection.peer_capabilities().client_state_push_v1;
|
||||
let DataValue::Array(ids) = value.get_data(DataType::UserIds) else {
|
||||
let Some(DataValue::Array(ids)) = value.get_data(DataType::UserIds) else {
|
||||
return send_error(
|
||||
connection,
|
||||
value.get_id(),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
use super::super::omikron_connection::{OmikronConnection, OmikronResult};
|
||||
use super::super::connection::{
|
||||
MtpValueCompat, OmikronConnection, OmikronResult, OptionalDataValueCompat,
|
||||
};
|
||||
use crate::{
|
||||
db::{iota_repo, user_repo},
|
||||
models::{IotaId, UserId},
|
||||
|
|
@ -91,7 +93,9 @@ pub async fn get_user(
|
|||
}
|
||||
state.presence.resolve_private_state(id)
|
||||
} else {
|
||||
iota_id.map(|iota_id| state.presence.resolve_public_state(id, iota_id)).unwrap_or(crate::sql::connection_status::UserStatus::user_offline)
|
||||
iota_id
|
||||
.map(|iota_id| state.presence.resolve_public_state(id, iota_id))
|
||||
.unwrap_or(crate::sql::connection_status::UserStatus::user_offline)
|
||||
};
|
||||
response = response
|
||||
.add_typed_default(
|
||||
|
|
@ -100,10 +104,13 @@ pub async fn get_user(
|
|||
)
|
||||
.add_typed_default(
|
||||
DataType::OmikronConnections,
|
||||
iota_id.map(|iota_id| connections(&connection, iota_id)).unwrap_or_else(|| DataValue::Array(Vec::new())),
|
||||
iota_id
|
||||
.map(|iota_id| connections(&connection, iota_id))
|
||||
.unwrap_or_else(|| DataValue::Array(Vec::new())),
|
||||
);
|
||||
if let Some(iota_id) = iota_id {
|
||||
response = response.add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()));
|
||||
response =
|
||||
response.add_typed_default(DataType::IotaId, DataValue::SignedNumber(iota_id.into()));
|
||||
}
|
||||
if let Some(route) = route {
|
||||
response = response.add_typed_default(
|
||||
|
|
@ -138,10 +145,14 @@ pub async fn get_iota(
|
|||
} else if let Some(name) = value.get_data(DataType::Username).as_str() {
|
||||
if let Ok(user) = user_repo::get_by_username(name).await {
|
||||
match user.iota_id {
|
||||
Some(iota_id) => iota_repo::get_iota_by_id(iota_id)
|
||||
.await
|
||||
.ok()
|
||||
.map(|iota| (iota.id.0, iota.public_key, Some(user.id.0), Some(name.to_owned()))),
|
||||
Some(iota_id) => iota_repo::get_iota_by_id(iota_id).await.ok().map(|iota| {
|
||||
(
|
||||
iota.id.0,
|
||||
iota.public_key,
|
||||
Some(user.id.0),
|
||||
Some(name.to_owned()),
|
||||
)
|
||||
}),
|
||||
None => None,
|
||||
}
|
||||
} else {
|
||||
|
|
@ -245,12 +256,14 @@ pub async fn change_iota(
|
|||
connection: Arc<OmikronConnection>,
|
||||
value: CommunicationValue,
|
||||
) -> OmikronResult<()> {
|
||||
let Some(reset) = value.get_data(DataType::ResetToken).as_str() else {
|
||||
let reset_data = value.get_data(DataType::ResetToken);
|
||||
let Some(reset) = reset_data.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 {
|
||||
let new_token_data = value.get_data(DataType::NewToken);
|
||||
let Some(new_token) = new_token_data.as_str() else {
|
||||
return connection
|
||||
.send_error_response(value.get_id(), CommunicationType::ErrorInvalidData)
|
||||
.await;
|
||||
|
|
@ -270,7 +283,9 @@ pub async fn change_iota(
|
|||
.await;
|
||||
}
|
||||
let result =
|
||||
match user_repo::change_iota_id(user_id, Some(IotaId::from(value.get_sender() as i64))).await {
|
||||
match user_repo::change_iota_id(user_id, Some(IotaId::from(value.get_sender() as i64)))
|
||||
.await
|
||||
{
|
||||
Ok(()) => user_repo::change_token(user_id, new_token.to_owned()).await,
|
||||
Err(error) => Err(error),
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue