Skip to main content

Overview

The UsersRepository provides CRUD operations for managing users within a tenant. Users have roles, credentials, and can be activated or deactivated. All methods are suspend functions that return Result<T> for consistent error handling.

Methods

getUsersByTenantId()

Fetches all users for a specific tenant.
suspend fun getUsersByTenantId(tenantId: Long): Result<List<User>>
Parameters
tenantId
Long
required
The tenant ID to filter users by
Returns
Result<List<User>>
Result
Result containing a list of User objects or an error

createUser()

Creates a new user for a tenant.
suspend fun createUser(
    tenantId: Long,
    username: String,
    email: String,
    password: String,
    role: UserRole,
    isActive: Boolean = true
): Result<User>
Parameters
tenantId
Long
required
The tenant ID the user belongs to
username
String
required
The username for login
email
String
required
The user’s email address
password
String
required
The raw password (will be hashed by backend)
role
UserRole
required
The user’s role
isActive
Boolean
default:"true"
Whether the user is active
Returns
Result<User>
Result
Result containing the created User object or an error

updateUser()

Updates an existing user. All update fields are optional for partial updates.
suspend fun updateUser(
    tenantId: Long,
    userId: Long,
    username: String? = null,
    email: String? = null,
    password: String? = null,
    role: UserRole? = null,
    isActive: Boolean? = null
): Result<User>
Parameters
tenantId
Long
required
The tenant ID the user belongs to
userId
Long
required
The user ID to update
username
String
default:"null"
New username (optional)
email
String
default:"null"
New email (optional)
password
String
default:"null"
New password (optional)
role
UserRole
default:"null"
New role (optional)
isActive
Boolean
default:"null"
New active status (optional)
Returns
Result<User>
Result
Result containing the updated User object or an error

deleteUser()

Deletes a user by ID.
suspend fun deleteUser(tenantId: Long, userId: Long): Result<Unit>
Parameters
tenantId
Long
required
The tenant ID the user belongs to
userId
Long
required
The user ID to delete
Returns
Result<Unit>
Result
Result indicating success or error

Usage Example

class UsersViewModel(
    private val usersRepository: UsersRepository
) : ViewModel() {
    
    private val _users = MutableStateFlow<List<User>>(emptyList())
    val users: StateFlow<List<User>> = _users.asStateFlow()
    
    private val _error = MutableStateFlow<String?>(null)
    val error: StateFlow<String?> = _error.asStateFlow()
    
    fun loadUsers(tenantId: Long) {
        viewModelScope.launch {
            usersRepository.getUsersByTenantId(tenantId)
                .onSuccess { _users.value = it }
                .onFailure { _error.value = it.message }
        }
    }
    
    fun createUser(
        tenantId: Long,
        username: String,
        email: String,
        password: String,
        role: UserRole
    ) {
        viewModelScope.launch {
            usersRepository.createUser(
                tenantId = tenantId,
                username = username,
                email = email,
                password = password,
                role = role,
                isActive = true
            )
                .onSuccess { loadUsers(tenantId) }
                .onFailure { _error.value = it.message }
        }
    }
    
    fun updateUserRole(
        tenantId: Long,
        userId: Long,
        newRole: UserRole
    ) {
        viewModelScope.launch {
            usersRepository.updateUser(
                tenantId = tenantId,
                userId = userId,
                role = newRole
            )
                .onSuccess { loadUsers(tenantId) }
                .onFailure { _error.value = it.message }
        }
    }
    
    fun toggleUserActive(
        tenantId: Long,
        userId: Long,
        isActive: Boolean
    ) {
        viewModelScope.launch {
            usersRepository.updateUser(
                tenantId = tenantId,
                userId = userId,
                isActive = isActive
            )
                .onSuccess { loadUsers(tenantId) }
                .onFailure { _error.value = it.message }
        }
    }
}

Dependency Injection

Inject the repository using Koin in your Composables:
import org.koin.compose.viewmodel.koinViewModel

@Composable
fun UsersScreen(tenantId: Long) {
    val viewModel: UsersViewModel = koinViewModel()
    val users by viewModel.users.collectAsState()
    
    LaunchedEffect(tenantId) {
        viewModel.loadUsers(tenantId)
    }
    
    // UI implementation
}

Build docs developers (and LLMs) love