Skip to content

Commit

Permalink
feat: add name to user, and endpoint for setting profile (#279)
Browse files Browse the repository at this point in the history
* feat: add name to users table
  • Loading branch information
Cifko authored Mar 9, 2025
1 parent 615ea0d commit 7f94548
Show file tree
Hide file tree
Showing 9 changed files with 301 additions and 101 deletions.
41 changes: 22 additions & 19 deletions atoma-auth/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::google::{self, fetch_google_public_keys};
use crate::{AtomaAuthConfig, Sui};
use anyhow::anyhow;
use atoma_state::{
types::{AtomaAtomaStateManagerEvent, TokenResponse},
types::{AtomaAtomaStateManagerEvent, TokenResponse, UserProfile},
AtomaStateManagerError,
};
use atoma_utils::hashing::blake2b_hash;
Expand Down Expand Up @@ -317,16 +317,20 @@ impl Auth {
hex::encode(hash_result)
}

/// Register user with username/password.
/// This method will register a new user with a username and password
/// Register user with email/password.
/// This method will register a new user with a email and password
/// The password is hashed and stored in the DB
/// The method will generate a new refresh and access token
#[instrument(level = "info", skip(self, password))]
pub async fn register(&self, username: &str, password: &str) -> Result<(String, String)> {
pub async fn register(
&self,
user_profile: &UserProfile,
password: &str,
) -> Result<(String, String)> {
let (result_sender, result_receiver) = oneshot::channel();
self.state_manager_sender
.send(AtomaAtomaStateManagerEvent::RegisterUserWithPassword {
username: username.to_string(),
user_profile: user_profile.clone(),
password: self.hash_string(password),
result_sender,
})?;
Expand All @@ -346,17 +350,16 @@ impl Auth {
#[instrument(level = "info", skip(self, password))]
pub async fn check_user_password(
&self,
username: &str,
email: &str,
password: &str,
) -> Result<(String, String)> {
let (result_sender, result_receiver) = oneshot::channel();
self.state_manager_sender.send(
AtomaAtomaStateManagerEvent::GetUserIdByUsernamePassword {
username: username.to_string(),
self.state_manager_sender
.send(AtomaAtomaStateManagerEvent::GetUserIdByEmailPassword {
email: email.to_string(),
password: self.hash_string(password),
result_sender,
},
)?;
})?;
let user_id = result_receiver
.await??
.map(|user_id| user_id as u64)
Expand Down Expand Up @@ -388,7 +391,7 @@ impl Auth {
};
self.state_manager_sender
.send(AtomaAtomaStateManagerEvent::OAuth {
username: email,
email,
result_sender,
})?;
let user_id = result_receiver.await??;
Expand Down Expand Up @@ -1059,20 +1062,20 @@ active_address: "0x939cfcc7fcbc71ce983203bcb36fa498901932ab9293dfa2b271203e71603
#[tokio::test]
async fn test_token_flow() {
let user_id = 123;
let username = "user";
let email = "email";
let password = "top_secret";
let (auth, receiver) = setup_test().await;
let hash_password = auth.hash_string(password);
let mock_handle = tokio::task::spawn(async move {
// First event is for the user to log in to get the tokens
let event = receiver.recv_async().await.unwrap();
match event {
AtomaAtomaStateManagerEvent::GetUserIdByUsernamePassword {
username: event_username,
AtomaAtomaStateManagerEvent::GetUserIdByEmailPassword {
email: event_email,
password: event_password,
result_sender,
} => {
assert_eq!(username, event_username);
assert_eq!(email, event_email);
assert_eq!(hash_password, event_password);
result_sender.send(Ok(Some(user_id))).unwrap();
}
Expand Down Expand Up @@ -1115,7 +1118,7 @@ active_address: "0x939cfcc7fcbc71ce983203bcb36fa498901932ab9293dfa2b271203e71603
}
});
let (refresh_token, access_token) =
auth.check_user_password(username, password).await.unwrap();
auth.check_user_password(email, password).await.unwrap();
// Refresh token should not have refresh token hash
let claims = auth.validate_token(&refresh_token, true).unwrap();
assert_eq!(claims.user_id, user_id);
Expand Down Expand Up @@ -1149,10 +1152,10 @@ active_address: "0x939cfcc7fcbc71ce983203bcb36fa498901932ab9293dfa2b271203e71603
let event = receiver.recv_async().await.unwrap();
match event {
AtomaAtomaStateManagerEvent::OAuth {
username: event_username,
email: event_email,
result_sender,
} => {
assert_eq!(event_username, "email");
assert_eq!(event_email, "email");
result_sender.send(Ok(1)).unwrap();
}
_ => panic!("Unexpected event"),
Expand Down
106 changes: 85 additions & 21 deletions atoma-proxy-service/docs/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ paths:
* `proxy_service_state` - The shared state containing the state manager
* `headers` - The headers of the request
* `body` - The request body containing the API token to revoke
* `body` - The request body containing the API token id to revoke
# Returns
Expand Down Expand Up @@ -98,7 +98,7 @@ paths:
# Arguments
* `proxy_service_state` - The shared state containing the state manager
* `body` - The request body containing the username and password of the new user
* `body` - The request body containing the email and password of the new user
# Returns
Expand All @@ -108,15 +108,15 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRequest'
$ref: '#/components/schemas/RegisterAuthRequest'
required: true
responses:
'200':
description: Registers a new user
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRequest'
$ref: '#/components/schemas/RegisterAuthRequest'
'500':
description: Failed to register user
/login:
Expand All @@ -128,7 +128,7 @@ paths:
# Arguments
* `proxy_service_state` - The shared state containing the state manager
* `body` - The request body containing the username and password of the user
* `body` - The request body containing the email and password of the user
# Returns
Expand All @@ -138,15 +138,15 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRequest'
$ref: '#/components/schemas/LoginAuthRequest'
required: true
responses:
'200':
description: Logs in a user
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRequest'
$ref: '#/components/schemas/RegisterAuthRequest'
'500':
description: Failed to login user
/api_tokens:
Expand Down Expand Up @@ -355,6 +355,41 @@ paths:
description: Failed to get user profile
security:
- bearerAuth: []
/set_user_profile:
get:
tags:
- Auth
summary: Retrieves the user profile for the user.
description: |-
# Arguments
* `proxy_service_state` - The shared state containing the state manager
* `headers` - The headers of the request
# Returns
* `Result<Json<Value>>` - A JSON response containing the user profile
# Errors
* If the user ID cannot be retrieved from the token, returns a 401 Unauthorized error
* If the user profile cannot be retrieved, returns a 500 Internal Server Error
operationId: set_user_profile
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UserProfile'
required: true
responses:
'200':
description: Sets the user profile for the user
'401':
description: Unauthorized request
'500':
description: Failed to set user profile
security:
- bearerAuth: []
/salt:
get:
tags:
Expand Down Expand Up @@ -641,19 +676,6 @@ paths:
description: Failed to get graph data
components:
schemas:
AuthRequest:
type: object
description: Request payload for user authentication
required:
- username
- password
properties:
password:
type: string
description: The user's password
username:
type: string
description: The user's unique identifier
CreateTokenRequest:
type: object
description: |-
Expand All @@ -665,6 +687,20 @@ components:
properties:
name:
type: string
description: The name of the token
LoginAuthRequest:
type: object
description: Request payload for user authentication
required:
- email
- password
properties:
email:
type: string
description: The user's unique identifier
password:
type: string
description: The user's password
ProofRequest:
type: object
description: |-
Expand All @@ -677,6 +713,19 @@ components:
signature:
type: string
description: The signature of the user to prove ownership of the sui address
RegisterAuthRequest:
type: object
description: Request payload for user authentication
required:
- user_profile
- password
properties:
password:
type: string
description: The user's password
user_profile:
$ref: '#/components/schemas/UserProfile'
description: The user's unique identifier
RevokeApiTokenRequest:
type: object
description: Request payload for revoking an API token
Expand All @@ -686,7 +735,7 @@ components:
api_token_id:
type: integer
format: int64
description: The API token to be revoked
description: The API token id to be revoked
UsdcPaymentRequest:
type: object
description: |-
Expand All @@ -704,6 +753,21 @@ components:
transaction_digest:
type: string
description: The transaction digest of the payment
UserProfile:
type: object
description: |-
Represents a user profile
This struct is used to represent the response for the get_user_profile endpoint.
required:
- email
- name
properties:
email:
type: string
description: The user's email
name:
type: string
description: The user's name
securitySchemes:
bearerAuth:
type: http
Expand Down
10 changes: 6 additions & 4 deletions atoma-proxy-service/src/components/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ use crate::{
handlers::{
auth::{
GenerateApiTokenOpenApi, GetAllApiTokensOpenApi, GetBalance, GetSalt, GetSuiAddress,
GetUserProfile, LoginOpenApi, RegisterOpenApi, RevokeApiTokenOpenApi, UpdateSuiAddress,
UsdcPayment, GENERATE_API_TOKEN_PATH, GET_ALL_API_TOKENS_PATH, GET_BALANCE_PATH,
GET_SALT_PATH, GET_SUI_ADDRESS_PATH, GET_USER_PROFILE_PATH, LOGIN_PATH, REGISTER_PATH,
REVOKE_API_TOKEN_PATH, UPDATE_SUI_ADDRESS_PATH, USDC_PAYMENT_PATH,
GetUserProfile, LoginOpenApi, RegisterOpenApi, RevokeApiTokenOpenApi, SetUserProfile,
UpdateSuiAddress, UsdcPayment, GENERATE_API_TOKEN_PATH, GET_ALL_API_TOKENS_PATH,
GET_BALANCE_PATH, GET_SALT_PATH, GET_SUI_ADDRESS_PATH, GET_USER_PROFILE_PATH,
LOGIN_PATH, REGISTER_PATH, REVOKE_API_TOKEN_PATH, SET_USER_PROFILE_PATH,
UPDATE_SUI_ADDRESS_PATH, USDC_PAYMENT_PATH,
},
stacks::{
GetCurrentStacksOpenApi, GetStacksByUserId, GET_ALL_STACKS_FOR_USER_PATH,
Expand Down Expand Up @@ -49,6 +50,7 @@ pub fn openapi_router() -> Router {
(path = GET_ALL_STACKS_FOR_USER_PATH, api = GetStacksByUserId, tags = ["Stacks"]),
(path = GET_BALANCE_PATH, api = GetBalance, tags = ["Auth"]),
(path = GET_USER_PROFILE_PATH, api = GetUserProfile, tags = ["Auth"]),
(path = SET_USER_PROFILE_PATH, api = SetUserProfile, tags = ["Auth"]),
(path = GET_SALT_PATH, api = GetSalt, tags = ["Auth"]),
(path = TASKS_PATH, api = GetAllTasksOpenApi, tags = ["Tasks"]),
(path = COMPUTE_UNITS_PROCESSED_PATH, api = GetComputeUnitsProcessed, tags = ["Stats"]),
Expand Down
Loading

0 comments on commit 7f94548

Please sign in to comment.