Changeset View
Changeset View
Standalone View
Standalone View
services/identity/src/client_service.rs
pub mod client_proto { | pub mod client_proto { | ||||
tonic::include_proto!("identity.client"); | tonic::include_proto!("identity.client"); | ||||
} | } | ||||
use std::str::FromStr; | |||||
use crate::{ | use crate::{ | ||||
client_service::client_proto::{ | client_service::client_proto::{ | ||||
DeleteUserRequest, Empty, GenerateNonceResponse, KeyserverKeysRequest, | DeleteUserRequest, Empty, GenerateNonceResponse, KeyserverKeysRequest, | ||||
KeyserverKeysResponse, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, | KeyserverKeysResponse, OpaqueLoginFinishRequest, OpaqueLoginFinishResponse, | ||||
OpaqueLoginStartRequest, OpaqueLoginStartResponse, | OpaqueLoginStartRequest, OpaqueLoginStartResponse, | ||||
ReceiverKeysForUserRequest, ReceiverKeysForUserResponse, | ReceiverKeysForUserRequest, ReceiverKeysForUserResponse, | ||||
RefreshUserPreKeysRequest, RegistrationFinishRequest, | RefreshUserPreKeysRequest, RegistrationFinishRequest, | ||||
RegistrationFinishResponse, RegistrationStartRequest, | RegistrationFinishResponse, RegistrationStartRequest, | ||||
RegistrationStartResponse, SenderKeysForUserRequest, | RegistrationStartResponse, SenderKeysForUserRequest, | ||||
SenderKeysForUserResponse, UpdateUserPasswordFinishRequest, | SenderKeysForUserResponse, UpdateUserPasswordFinishRequest, | ||||
UpdateUserPasswordFinishResponse, UpdateUserPasswordStartRequest, | UpdateUserPasswordFinishResponse, UpdateUserPasswordStartRequest, | ||||
UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest, | UpdateUserPasswordStartResponse, UploadOneTimeKeysRequest, | ||||
VerifyUserAccessTokenRequest, VerifyUserAccessTokenResponse, | VerifyUserAccessTokenRequest, VerifyUserAccessTokenResponse, | ||||
WalletLoginRequest, WalletLoginResponse, | WalletLoginRequest, WalletLoginResponse, | ||||
}, | }, | ||||
database::{DatabaseClient, Error as DBError}, | config::CONFIG, | ||||
database::{DatabaseClient, Error as DBError, KeyPayload}, | |||||
id::generate_uuid, | |||||
nonce::generate_nonce_data, | nonce::generate_nonce_data, | ||||
}; | }; | ||||
use aws_sdk_dynamodb::Error as DynamoDBError; | use aws_sdk_dynamodb::Error as DynamoDBError; | ||||
pub use client_proto::identity_client_service_server::{ | pub use client_proto::identity_client_service_server::{ | ||||
IdentityClientService, IdentityClientServiceServer, | IdentityClientService, IdentityClientServiceServer, | ||||
}; | }; | ||||
use moka::future::Cache; | |||||
use rand::rngs::OsRng; | use rand::rngs::OsRng; | ||||
use tonic::Response; | use tonic::Response; | ||||
use tracing::error; | use tracing::error; | ||||
#[derive(Clone)] | |||||
pub enum WorkflowInProgress { | |||||
Registration(UserRegistrationInfo), | |||||
} | |||||
#[derive(Clone)] | |||||
pub struct UserRegistrationInfo { | |||||
username: String, | |||||
device_id_key: String, | |||||
key_payload: String, | |||||
key_payload_signature: String, | |||||
identity_prekey: String, | |||||
identity_prekey_signature: String, | |||||
identity_onetime_keys: Vec<String>, | |||||
notif_prekey: String, | |||||
notif_prekey_signature: String, | |||||
notif_onetime_keys: Vec<String>, | |||||
} | |||||
#[derive(derive_more::Constructor)] | #[derive(derive_more::Constructor)] | ||||
pub struct ClientService { | pub struct ClientService { | ||||
client: DatabaseClient, | client: DatabaseClient, | ||||
cache: Cache<String, WorkflowInProgress>, | |||||
} | } | ||||
#[tonic::async_trait] | #[tonic::async_trait] | ||||
impl IdentityClientService for ClientService { | impl IdentityClientService for ClientService { | ||||
async fn register_password_user_start( | async fn register_password_user_start( | ||||
&self, | &self, | ||||
_request: tonic::Request<RegistrationStartRequest>, | request: tonic::Request<RegistrationStartRequest>, | ||||
) -> Result<tonic::Response<RegistrationStartResponse>, tonic::Status> { | ) -> Result<tonic::Response<RegistrationStartResponse>, tonic::Status> { | ||||
unimplemented!(); | let message = request.into_inner(); | ||||
let username_taken = self | |||||
.client | |||||
.username_taken(message.username.clone()) | |||||
.await | |||||
.map_err(handle_db_error)?; | |||||
if username_taken { | |||||
return Err(tonic::Status::already_exists("username already exists")); | |||||
} | |||||
if CONFIG.reserved_usernames.contains(&message.username) { | |||||
return Err(tonic::Status::invalid_argument("username reserved")); | |||||
} | |||||
if let client_proto::RegistrationStartRequest { | |||||
opaque_registration_request: register_message, | |||||
username, | |||||
device_key_upload: | |||||
Some(client_proto::DeviceKeyUpload { | |||||
device_key_info: | |||||
Some(client_proto::IdentityKeyInfo { | |||||
payload, | |||||
payload_signature, | |||||
social_proof: _social_proof, | |||||
}), | |||||
identity_upload: | |||||
Some(client_proto::PreKey { | |||||
pre_key: identity_prekey, | |||||
pre_key_signature: identity_prekey_signature, | |||||
}), | |||||
notif_upload: | |||||
Some(client_proto::PreKey { | |||||
pre_key: notif_prekey, | |||||
pre_key_signature: notif_prekey_signature, | |||||
}), | |||||
onetime_identity_prekeys, | |||||
onetime_notif_prekeys, | |||||
}), | |||||
} = message | |||||
{ | |||||
let server_registration = comm_opaque2::server::Registration::new(); | |||||
let server_message = server_registration | |||||
.start(&CONFIG.server_setup, ®ister_message, username.as_bytes()) | |||||
.map_err(comm_opaque2::grpc::protocol_error_to_grpc_status)?; | |||||
let key_info = KeyPayload::from_str(&payload) | |||||
.map_err(|_| tonic::Status::invalid_argument("malformed payload"))?; | |||||
let registration_state = UserRegistrationInfo { | |||||
username, | |||||
device_id_key: key_info.primary_identity_public_keys.curve25519, | |||||
key_payload: payload, | |||||
key_payload_signature: payload_signature, | |||||
identity_prekey, | |||||
identity_prekey_signature, | |||||
identity_onetime_keys: onetime_identity_prekeys, | |||||
notif_prekey, | |||||
notif_prekey_signature, | |||||
notif_onetime_keys: onetime_notif_prekeys, | |||||
}; | |||||
let session_id = generate_uuid(); | |||||
self | |||||
.cache | |||||
.insert( | |||||
session_id.clone(), | |||||
WorkflowInProgress::Registration(registration_state), | |||||
) | |||||
.await; | |||||
let response = RegistrationStartResponse { | |||||
session_id, | |||||
opaque_registration_response: server_message, | |||||
}; | |||||
Ok(Response::new(response)) | |||||
} else { | |||||
Err(tonic::Status::invalid_argument("unexpected message data")) | |||||
} | |||||
} | } | ||||
async fn register_password_user_finish( | async fn register_password_user_finish( | ||||
&self, | &self, | ||||
_request: tonic::Request<RegistrationFinishRequest>, | _request: tonic::Request<RegistrationFinishRequest>, | ||||
) -> Result<tonic::Response<RegistrationFinishResponse>, tonic::Status> { | ) -> Result<tonic::Response<RegistrationFinishResponse>, tonic::Status> { | ||||
unimplemented!(); | unimplemented!(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 120 Lines • Show Last 20 Lines |