Program Listing for File profile.hpp#
↰ Return to documentation for file (src/auth/profile.hpp)
#pragma once
#include <QDateTime>
#include <QString>
namespace mosaic {
/// @brief A single research-group profile stored in the profiles manifest.
///
/// Passwords are **never** stored in plain text. Only the PBKDF2-SHA256
/// hash and the random salt used to compute it are persisted.
///
/// Profiles are loaded from and saved to
/// ``~/.config/CSRU/mosaic/profiles.json`` by ProfileManager.
///
/// @see ProfileManager
struct Profile {
/// @brief Privilege level for this profile.
enum class Role : uint8_t {
User = 0, ///< Regular research-group profile.
Admin = 1, ///< Full administrator — can manage all profiles and global settings.
};
/// Unique login key — lowercase alphanumeric + underscore, 3–32 chars.
QString username;
/// Human-readable group name shown in the login dialog and session metadata.
/// Example: ``"Cognitive Science Lab"``.
QString displayName;
/// One or two uppercase letters derived from displayName, shown inside
/// the avatar circle. Example: ``"CL"`` for *Cognitive Lab*.
QString initials;
/// Hex RGB colour for the avatar background.
/// Assigned round-robin from a fixed palette on registration.
/// Example: ``"#5566dd"``.
QString accentColour;
/// Hex-encoded random 32-byte salt used in the password hash.
/// Empty string means no password was set.
QString salt;
/// Hex-encoded PBKDF2-HMAC-SHA256 output (100 000 iterations, 32-byte key).
/// Empty string means no password was set — any login attempt succeeds.
QString passwordHash;
/// UTC timestamp of the most recent successful login.
QDateTime lastLogin;
/// UTC timestamp when this profile was first created.
QDateTime created;
/// Privilege level — only Admin profiles open the admin panel after login.
Role role = Role::User;
/// Optional lab / university / department name (shown in admin panel and status bar).
QString institution;
/// @returns @c true if this is the built-in unauthenticated guest session.
[[nodiscard]] bool is_guest() const noexcept { return username == "guest"; }
/// @returns @c true if a password hash is stored for this profile.
/// Profiles without a password always pass authentication.
[[nodiscard]] bool has_password() const noexcept { return !passwordHash.isEmpty(); }
/// @returns @c true if this profile has administrator privileges.
[[nodiscard]] bool is_admin() const noexcept { return role == Role::Admin; }
};
} // namespace mosaic