diff --git a/common/proto/auth.proto b/common/proto/auth.proto index bcb30df..9c5221e 100644 --- a/common/proto/auth.proto +++ b/common/proto/auth.proto @@ -14,6 +14,7 @@ message RegisterRequest { string email = 2; string password = 3; string password_confirmation = 4; + string role = 5; } message AuthResponse { diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index edd4e4a..56166bc 100644 Binary files a/common/src/proto/descriptor.bin and b/common/src/proto/descriptor.bin differ diff --git a/common/src/proto/multieko2.auth.rs b/common/src/proto/multieko2.auth.rs index ff60458..22bd8ff 100644 --- a/common/src/proto/multieko2.auth.rs +++ b/common/src/proto/multieko2.auth.rs @@ -9,6 +9,8 @@ pub struct RegisterRequest { pub password: ::prost::alloc::string::String, #[prost(string, tag = "4")] pub password_confirmation: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub role: ::prost::alloc::string::String, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct AuthResponse { diff --git a/server/src/auth/docs/role_added.txt b/server/src/auth/docs/role_added.txt new file mode 100644 index 0000000..27072ff --- /dev/null +++ b/server/src/auth/docs/role_added.txt @@ -0,0 +1,37 @@ +❯ grpcurl -plaintext -d '{ + "username": "testuser_default_role", + "email": "default@example.com", + "password": "password", + "password_confirmation": "password" +}' localhost:50051 multieko2.auth.AuthService/Register +{ + "id": "73017288-af41-49d8-b4cb-2ac2109b38a1", + "username": "testuser_default_role", + "email": "default@example.com", + "role": "accountant" +} +❯ grpcurl -plaintext -d '{ + "username": "testuser_admin_role", + "email": "admin@example.com", + "password": "password", + "password_confirmation": "password", + "role": "admin" +}' localhost:50051 multieko2.auth.AuthService/Register +{ + "id": "9437e318-818b-4c34-822d-c2d6601b835e", + "username": "testuser_admin_role", + "email": "admin@example.com", + "role": "admin" +} +❯ grpcurl -plaintext -d '{ + "username": "testuser_invalid_role", + "email": "invalid@example.com", + "password": "password", + "password_confirmation": "password", + "role": "invalid_role_name" +}' localhost:50051 multieko2.auth.AuthService/Register +ERROR: + Code: InvalidArgument + Message: Invalid role specified: 'invalid_role_name' +╭─    ~/Doc/pr/multieko2/server    main +3 !1  +╰─ diff --git a/server/src/auth/handlers/register.rs b/server/src/auth/handlers/register.rs index d9dc761..e88c95b 100644 --- a/server/src/auth/handlers/register.rs +++ b/server/src/auth/handlers/register.rs @@ -5,6 +5,8 @@ use common::proto::multieko2::auth::{RegisterRequest, AuthResponse}; use crate::db::PgPool; use crate::auth::models::AuthError; +const DEFAULT_ROLE: &str = "accountant"; + pub async fn register( pool: &PgPool, payload: RegisterRequest, @@ -18,20 +20,28 @@ pub async fn register( let password_hash = hash(payload.password, DEFAULT_COST) .map_err(|e| Status::internal(AuthError::HashingError(e.to_string()).to_string()))?; + let role_to_insert = if payload.role.is_empty() { DEFAULT_ROLE } else { &payload.role }; + // Insert user let user = sqlx::query!( r#" INSERT INTO users (username, email, password_hash, role) - VALUES ($1, $2, $3, 'accountant') + VALUES ($1, $2, $3, $4) RETURNING id, username, email, role "#, payload.username, payload.email, - password_hash + password_hash, + role_to_insert ) .fetch_one(pool) .await .map_err(|e| { + if let Some(db_err) = e.as_database_error() { + if db_err.constraint() == Some("valid_roles") { + return Status::invalid_argument(format!("Invalid role specified: '{}'", role_to_insert)); + } + } if e.to_string().contains("duplicate key") { Status::already_exists(AuthError::UserExists.to_string()) } else {