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
The tenant ID to filter users by
Returns
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
The tenant ID the user belongs to
The raw password (will be hashed by backend)
Whether the user is active
Returns
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
The tenant ID the user belongs to
New active status (optional)
Returns
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
The tenant ID the user belongs to
Returns
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
}