diff --git a/services/identity/src/database.rs b/services/identity/src/database.rs --- a/services/identity/src/database.rs +++ b/services/identity/src/database.rs @@ -4,14 +4,14 @@ use aws_sdk_dynamodb::model::AttributeValue; use aws_sdk_dynamodb::output::{ - GetItemOutput, PutItemOutput, QueryOutput, UpdateItemOutput, + DeleteItemOutput, GetItemOutput, PutItemOutput, QueryOutput, UpdateItemOutput, }; use aws_sdk_dynamodb::types::Blob; use aws_sdk_dynamodb::{Client, Error as DynamoDBError}; use aws_types::sdk_config::SdkConfig; use chrono::{DateTime, Utc}; use opaque_ke::{errors::ProtocolError, ServerRegistration}; -use tracing::{error, info, warn}; +use tracing::{debug, error, info, warn}; use crate::constants::{ ACCESS_TOKEN_SORT_KEY, ACCESS_TOKEN_TABLE, @@ -180,6 +180,34 @@ .map_err(|e| Error::AwsSdk(e.into())) } + pub async fn delete_user( + &self, + user_id: String, + ) -> Result { + debug!("Attempting to delete user: {}", user_id); + + match self + .client + .delete_item() + .table_name(USERS_TABLE) + .key( + USERS_TABLE_PARTITION_KEY, + AttributeValue::S(user_id.clone()), + ) + .send() + .await + { + Ok(out) => { + info!("User has been deleted {}", user_id); + Ok(out) + } + Err(e) => { + error!("DynamoDB client failed to delete user {}", user_id); + Err(Error::AwsSdk(e.into())) + } + } + } + pub async fn get_access_token_data( &self, user_id: String, diff --git a/services/identity/src/service.rs b/services/identity/src/service.rs --- a/services/identity/src/service.rs +++ b/services/identity/src/service.rs @@ -40,9 +40,10 @@ registration_request::Data::PakeRegistrationRequestAndUserId, registration_request::Data::PakeRegistrationUploadAndCredentialRequest, registration_response::Data::PakeLoginResponse as PakeRegistrationLoginResponse, - registration_response::Data::PakeRegistrationResponse, GetUserIdRequest, - GetUserIdResponse, GetUserPublicKeyRequest, GetUserPublicKeyResponse, - LoginRequest, LoginResponse, PakeLoginRequest as PakeLoginRequestStruct, + registration_response::Data::PakeRegistrationResponse, DeleteUserRequest, + DeleteUserResponse, GetUserIdRequest, GetUserIdResponse, + GetUserPublicKeyRequest, GetUserPublicKeyResponse, LoginRequest, + LoginResponse, PakeLoginRequest as PakeLoginRequestStruct, PakeLoginResponse as PakeLoginResponseStruct, RegistrationRequest, RegistrationResponse, VerifyUserTokenRequest, VerifyUserTokenResponse, WalletLoginRequest as WalletLoginRequestStruct, @@ -235,6 +236,18 @@ let response = Response::new(GetUserPublicKeyResponse { public_key }); Ok(response) } + + #[instrument(skip(self))] + async fn delete_user( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + let message = request.into_inner(); + match self.client.delete_user(message.user_id).await { + Ok(_) => Ok(Response::new(DeleteUserResponse {})), + Err(e) => Err(handle_db_error(e)), + } + } } async fn put_token_helper( diff --git a/shared/protos/identity.proto b/shared/protos/identity.proto --- a/shared/protos/identity.proto +++ b/shared/protos/identity.proto @@ -18,6 +18,8 @@ // and device ID rpc GetUserPublicKey(GetUserPublicKeyRequest) returns (GetUserPublicKeyResponse) {} + + rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse) {} } // Helper types @@ -153,3 +155,13 @@ message GetUserPublicKeyResponse { string publicKey = 1; } + +// DeleteUser + +message DeleteUserRequest { + string userID = 1; +} + +// Need to respond with a message to show success, an +// empty reponse should work just fine +message DeleteUserResponse {}