Class ProfileManager#

Inheritance Relationships#

Base Type#

  • public QObject

Class Documentation#

class ProfileManager : public QObject#

Manages the on-disk profile manifest and per-profile settings directories.

See also

Profile, AppSettings

Storage layout
~/.config/CSRU/mosaic/
  profiles.json          ← auth manifest (hashed credentials)
  profiles/
    <username>/
      settings.json      ← per-group AppSettings
      mosaic.log
Password security

PBKDF2-HMAC-SHA256, 100 000 iterations, 32-byte output key, 32-byte random salt per profile. This protects against accidental profile collisions on a shared workstation; it is not designed to protect against an attacker with file-system access.

Example
ProfileManager mgr;
mgr.load();

using Res = ProfileManager::RegisterResult;
if (mgr.register_profile("cognitive_lab", "Cognitive Science Lab", "secret")
        == Res::Ok) {
    qDebug() << "profile created at" << ProfileManager::profile_dir("cognitive_lab");
}

if (mgr.verify("cognitive_lab", "secret")) {
    mgr.touch("cognitive_lab");
    auto path = ProfileManager::settings_path("cognitive_lab");
}

Public Types

enum class RegisterResult#

Possible outcomes of register_profile().

Values:

enumerator Ok#

Profile was created successfully.

enumerator UsernameTaken#

A profile with that username already exists.

enumerator UsernameInvalid#

Username does not match [a-z0-9_]{3,32}.

enumerator PasswordTooShort#

Non-empty password is shorter than 4 characters.

Public Functions

explicit ProfileManager(QObject *parent = nullptr)#
~ProfileManager() override#
void load()#

Loads the profiles manifest from disk.

Creates an empty manifest if the file does not exist yet. Safe to call multiple times — each call replaces the in-memory list.

std::vector<Profile> profiles() const#
Returns:

A copy of all currently loaded profiles.

bool has_profile(const QString &username) const#
Parameters:

username – Username to look up (case-sensitive).

Returns:

true if a profile with this username exists.

const Profile *find(const QString &username) const#
Parameters:

username – Username to look up.

Returns:

Pointer to the matching Profile, or nullptr.

Note

The returned pointer is invalidated the next time the profile list is modified (register, delete). Copy if you need to keep it.

RegisterResult register_profile(const QString &username, const QString &displayName, const QString &password, Profile::Role role = Profile::Role::User)#

Registers a new research-group profile.

Creates the profile directory, hashes the password (if non-empty), appends the profile to the manifest, and saves it to disk.

Parameters:
  • username – Unique login key — [a-z0-9_]{3,32}.

  • displayName – Human-readable group name (any Unicode string).

  • password – Plain-text password. Pass an empty string for a password-free profile.

  • role – Privilege level for the new profile (default: User).

Returns:

RegisterResult::Ok on success, or an error code.

bool has_admin() const#
Returns:

true if at least one profile with Admin role exists.

bool verify(const QString &username, const QString &password) const#

Verifies a password against the stored hash.

Parameters:
  • usernameProfile to authenticate.

  • password – Plain-text password entered by the user.

Returns:

true if the password matches, or if the profile has no password set. false if the profile does not exist or the password is wrong.

void touch(const QString &username)#

Updates the lastLogin timestamp and saves the manifest.

Call this immediately after a successful login so the login dialog can display accurate “last seen” information.

Parameters:

username – The profile that just logged in.

bool delete_profile(const QString &username)#

Permanently deletes a profile from the manifest.

Parameters:

usernameProfile to delete.

Returns:

true if the profile was found and removed.

Note

This does not delete the profile directory or its settings. The data remains on disk so it can be manually recovered.

bool rename_display(const QString &username, const QString &newDisplay)#

Renames a profile’s display name without changing its username.

Parameters:
  • usernameProfile to update.

  • newDisplay – New human-readable name.

Returns:

true if the profile was found and updated.

bool change_password(const QString &username, const QString &newPassword)#

Changes a profile’s password. Pass empty to remove password protection.

Parameters:
  • usernameProfile to update.

  • newPassword – New plain-text password, or empty string to clear.

Returns:

true on success.

bool set_role(const QString &username, Profile::Role role)#

Updates a profile’s privilege role.

Parameters:
  • usernameProfile to update.

  • role – New role.

Returns:

true on success.

bool set_institution(const QString &username, const QString &institution)#

Updates a profile’s institution / lab name.

Parameters:
  • usernameProfile to update.

  • institution – New institution string (any Unicode).

Returns:

true on success.

Signals

void profiles_changed()#

Emitted after any change to the profile list (register, delete, rename).

Public Static Functions

static QString root_dir()#
Returns:

The root config directory: ~/.config/CSRU/mosaic.

static QString profile_dir(const QString &username)#
Parameters:

usernameProfile username.

Returns:

The profile-specific directory: ~/.config/CSRU/mosaic/profiles/<username>.

static QString settings_path(const QString &username)#
Parameters:

usernameProfile username.

Returns:

Full path to the profile’s settings file: <profile_dir>/settings.json.

static QString log_path(const QString &username)#
Parameters:

usernameProfile username.

Returns:

Full path to the profile’s log file: <profile_dir>/mosaic.log.

static QString next_accent_colour(int profileIndex)#

Returns the hex accent colour for a given position in the palette.

Colours are assigned round-robin so consecutive profiles get distinct colours.

Parameters:

profileIndex – Zero-based index (wraps around the 8-colour palette).

Returns:

A hex RGB string like "#5566dd".