User models represent authenticated users within the system. Each user belongs to a tenant and has a specific role that determines their permissions.
User
Domain model representing a user in the application.
@Serializable
data class User(
val id: Long,
val code: String,
val username: String,
val email: String,
val role: UserRole,
val tenantId: Long,
val isActive: Boolean = true,
val lastLogin: String? = null,
val createdAt: String? = null,
val updatedAt: String? = null
)
Fields
Unique identifier for the user
Unique code assigned to the user
Username for authentication and display
User’s role determining permissions (ADMIN, OPERATOR, or VIEWER)
ID of the tenant/client this user belongs to
Whether the user account is active
ISO 8601 timestamp of the user’s last login
ISO 8601 timestamp when the user was created
ISO 8601 timestamp when the user was last updated
Computed Properties
Returns the first letter of the username in uppercase for avatar display, or ”?” if username is empty.val initial: String
get() = username.firstOrNull()?.uppercaseChar()?.toString() ?: "?"
Example: “john.doe” → “J”, "" → ”?”
UserRole
Enum representing user roles supported by the system.
enum class UserRole {
ADMIN,
OPERATOR,
VIEWER
}
Values
- ADMIN: Full administrative access to all features and settings
- OPERATOR: Can manage devices, sectors, and view data
- VIEWER: Read-only access to view data and dashboards
Computed Properties
Returns a human-readable display name for the role.val displayName: String
get() = name.lowercase().replaceFirstChar { it.uppercase() }
Example: ADMIN → “Admin”, OPERATOR → “Operator”, VIEWER → “Viewer”
Companion Object Methods
Safely parses a role string to UserRole, defaulting to VIEWER if unknown.fun fromString(value: String): UserRole {
return entries.find { it.name.equals(value, ignoreCase = true) } ?: VIEWER
}
Example: fromString("admin") → UserRole.ADMIN, fromString("invalid") → UserRole.VIEWER
API DTOs
UserResponse
API response DTO for user data from the backend.
@Serializable
data class UserResponse(
val id: Long,
val code: String,
val username: String,
val email: String,
val role: String,
val tenantId: Long,
val isActive: Boolean,
val lastLogin: String? = null,
val createdAt: String,
val updatedAt: String
)
Role as a string (“ADMIN”, “OPERATOR”, or “VIEWER”) - converted to UserRole enum in domain model
Converts UserResponse to User domain model.fun UserResponse.toUser() = User(
id = id,
code = code,
username = username,
email = email,
role = UserRole.fromString(role),
tenantId = tenantId,
isActive = isActive,
lastLogin = lastLogin,
createdAt = createdAt,
updatedAt = updatedAt
)
UserCreateRequest
Request DTO for creating a new user.
@Serializable
data class UserCreateRequest(
val username: String,
val email: String,
val passwordRaw: String,
val role: String,
val isActive: Boolean = true
)
Desired username for the new user
Email address for the new user
Plain text password (will be hashed by the backend)
Role string (“ADMIN”, “OPERATOR”, or “VIEWER”)
Whether the user should be active upon creation
UserUpdateRequest
Request DTO for updating an existing user. All fields are optional for partial updates.
@Serializable
data class UserUpdateRequest(
val username: String? = null,
val email: String? = null,
val passwordRaw: String? = null,
val role: String? = null,
val isActive: Boolean? = null
)
Updated password (plain text, will be hashed)
Usage Examples
Creating a User
val user = User(
id = 1L,
code = "USR001",
username = "john.doe",
email = "[email protected]",
role = UserRole.OPERATOR,
tenantId = 1L,
isActive = true,
lastLogin = "2024-03-01T14:30:00Z",
createdAt = "2024-01-15T10:00:00Z",
updatedAt = "2024-03-01T14:30:00Z"
)
println(user.initial) // "J"
println(user.role.displayName) // "Operator"
Creating a User via API
val createRequest = UserCreateRequest(
username = "jane.smith",
email = "[email protected]",
passwordRaw = "SecurePassword123!",
role = "ADMIN",
isActive = true
)
val response: UserResponse = apiClient.createUser(
tenantId = 1L,
request = createRequest
)
val user: User = response.toUser()
Updating a User
val updateRequest = UserUpdateRequest(
role = "ADMIN", // Promote to admin
isActive = true
)
val response: UserResponse = apiClient.updateUser(
tenantId = 1L,
userId = 1L,
request = updateRequest
)
Role-Based Access Control
fun canEditSettings(user: User): Boolean {
return when (user.role) {
UserRole.ADMIN -> true
UserRole.OPERATOR -> false
UserRole.VIEWER -> false
}
}
fun canViewData(user: User): Boolean {
return user.isActive && user.role in listOf(
UserRole.ADMIN,
UserRole.OPERATOR,
UserRole.VIEWER
)
}
val user = getUser(1L)
if (canEditSettings(user)) {
// Show settings UI
}
Filtering Users by Role
val users = getUsers(tenantId = 1L)
val admins = users.filter { it.role == UserRole.ADMIN }
val operators = users.filter { it.role == UserRole.OPERATOR }
val viewers = users.filter { it.role == UserRole.VIEWER }
println("Admins: ${admins.size}")
println("Operators: ${operators.size}")
println("Viewers: ${viewers.size}")
Parsing Role from String
val roleString = "operator"
val role = UserRole.fromString(roleString)
println(role.displayName) // "Operator"
// Safe parsing with invalid input
val invalidRole = UserRole.fromString("invalid")
println(invalidRole) // UserRole.VIEWER (default)
Checking Last Login
val user = getUser(1L)
if (user.lastLogin != null) {
println("Last login: ${user.lastLogin}")
} else {
println("User has never logged in")
}