Skip to main content
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

id
Long
required
Unique identifier for the user
code
String
required
Unique code assigned to the user
username
String
required
Username for authentication and display
email
String
required
User’s email address
role
UserRole
required
User’s role determining permissions (ADMIN, OPERATOR, or VIEWER)
tenantId
Long
required
ID of the tenant/client this user belongs to
isActive
Boolean
default:"true"
Whether the user account is active
lastLogin
String
default:"null"
ISO 8601 timestamp of the user’s last login
createdAt
String
default:"null"
ISO 8601 timestamp when the user was created
updatedAt
String
default:"null"
ISO 8601 timestamp when the user was last updated

Computed Properties

initial
String
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

displayName
String
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

fromString
(String) -> UserRole
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
String
Role as a string (“ADMIN”, “OPERATOR”, or “VIEWER”) - converted to UserRole enum in domain model
toUser
() -> User
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
)
username
String
required
Desired username for the new user
email
String
required
Email address for the new user
passwordRaw
String
required
Plain text password (will be hashed by the backend)
role
String
required
Role string (“ADMIN”, “OPERATOR”, or “VIEWER”)
isActive
Boolean
default:"true"
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
)
username
String
default:"null"
Updated username
email
String
default:"null"
Updated email address
passwordRaw
String
default:"null"
Updated password (plain text, will be hashed)
role
String
default:"null"
Updated role string
isActive
Boolean
default:"null"
Updated active status

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")
}

Build docs developers (and LLMs) love