Skip to main content
OpenEyes implements a comprehensive role-based access control (RBAC) system for managing user permissions across the application.

User Management

Accessing User Administration

The admin interface is accessible at /admin/users and is managed by the AdminController:
1

Navigate to Admin Section

Access via main menu → Admin → Users
2

Search for Users

Use the search box to filter by name, ID, or username
3

Add or Edit Users

Click “Add User” or select an existing user to modify

User Model Structure

The User model (protected/models/User.php) contains:
id
integer
Unique user identifier
first_name
string
required
User’s first name (max 40 characters)
last_name
string
required
User’s last name (max 40 characters)
email
string
required
User’s email address (max 80 characters)
title
string
Professional title (Dr, Mr, Mrs, Ms, etc.)
global_firm_rights
boolean
default:"1"
Whether user has access to all firms/contexts
is_consultant
boolean
Mark user as a consultant
is_surgeon
boolean
Mark user as a surgeon (requires additional fields)
doctor_grade_id
integer
Doctor grade (required if is_surgeon = 1)
registration_code
string
Professional registration code (required for surgeons)
contact_id
integer
Link to contact record with full details

Creating a New User

When creating a user, the system requires:
  1. Basic Information: Name, title, email
  2. Authentication: At least one institution authentication
  3. Roles: One or more system roles
  4. Context Access: Firm assignments (if global_firm_rights = 0)
// protected/controllers/AdminController.php:947
public function actionEditUser($id = null)
{
    $user = $id ? User::model()->findByPk($id) : new User();
    
    if ($request->getIsPostRequest()) {
        // Validate and save user
        $user->attributes = $request->getPost('User');
        
        if ($user->save()) {
            // Save contact
            $contact->save();
            
            // Save roles
            $user->saveRoles($user_attributes['roles']);
            
            // Save firm assignments
            $user->saveFirms($user_attributes['firms']);
            
            // Save authentication entries
            foreach ($user_auths_attributes as $auth) {
                $user_auth->save();
            }
        }
    }
}
When global_firm_rights is set to 0 (No), at least one firm must be assigned to the user or validation will fail.

User Authentication

OpenEyes supports multiple authentication methods per user through the UserAuthentication model.

Authentication Types

Local database authentication with password management.Features:
  • Password complexity requirements
  • Password expiration
  • Account lockout after failed attempts
  • Password history tracking
Configured via AUTH_SOURCE=BASIC environment variable.

UserAuthentication Model

File: protected/models/UserAuthentication.php
id
integer
Authentication record ID
user_id
integer
required
Reference to user
institution_authentication_id
integer
required
Links to institution’s authentication method
username
string
required
Login username (max 40 characters)
password_hash
string
Hashed password (for BASIC auth only)
password_salt
string
Password salt (legacy, being phased out)
password_status
string
Status: current, expired, stale, or softlocked
password_failed_tries
integer
Failed login attempt counter
password_last_changed_date
datetime
Last password change timestamp
active
boolean
default:"true"
Whether authentication is active

Password Management

// protected/models/UserAuthentication.php:244
public function verifyPassword($password)
{
    // Modern password_verify method
    if (!$this->password_salt) {
        return password_verify($password, $this->password_hash);
    }
    
    // Legacy method (auto-upgrades to modern)
    if (PasswordUtils::hashPassword($password, $this->password_salt) 
        === $this->password_hash) {
        // Re-hash with modern method
        $this->password_salt = null;
        $this->password_hash = PasswordUtils::hashPassword($password, null);
        $this->save();
        return true;
    }
    
    return false;
}
OpenEyes automatically upgrades legacy password hashes to the modern password_hash() method on successful login.

Role-Based Access Control (RBAC)

OpenEyes uses Yii’s built-in RBAC system with three database tables:
  • authitem - Roles, tasks, and operations
  • authitemchild - Role hierarchy
  • authassignment - User role assignments

Default Roles

admin

System AdministratorFull access to all system features including:
  • User management
  • System settings
  • All institutions
  • Module administration

User

Standard UserBasic clinical access:
  • Patient records
  • Event creation
  • Clinical notes
  • Limited to assigned contexts

Prescribe

PrescriberPermission to prescribe medications:
  • Create prescriptions
  • Manage drug lists
  • View medication history

Med Administer

Medication AdministratorPermission to administer medications:
  • Record administration
  • Document adverse reactions

Edit

EditorEnhanced editing permissions:
  • Edit locked events
  • Modify historical data

View clinical

Clinical ViewerView-only clinical access:
  • Read patient records
  • View clinical events
  • No editing capabilities

Checking User Permissions

// Check if user has specific role
if (Yii::app()->authManager->checkAccess('admin', $userId)) {
    // User is an admin
}

// Check in controller action
if (!$this->checkAccess('admin')) {
    throw new CHttpException(403, 'Access denied');
}

// Get user's roles
$roles = Yii::app()->authManager->getRoles($userId);

// Check if user has specific role (User model)
if ($user->hasRole('Prescribe')) {
    // User can prescribe
}

Managing User Roles

// protected/models/User.php:549
public function saveRoles(array $roles)
{
    $old_roles = array_map(fn($role) => $role->name, $this->roles);
    $added_roles = array_diff($roles, $old_roles);
    $removed_roles = array_diff($old_roles, $roles);
    
    // Assign new roles
    foreach ($added_roles as $role) {
        Yii::app()->authManager->assign($role, $this->id);
    }
    
    // Revoke removed roles
    foreach ($removed_roles as $role) {
        Yii::app()->authManager->revoke($role, $this->id);
    }
}

Firm/Context Management

Users can be restricted to specific firms (clinical contexts) when global_firm_rights = 0.

Firm Assignments

A “firm” in OpenEyes represents a clinical service or team, typically associated with:
  • A subspecialty (e.g., Cataract, Glaucoma, Retina)
  • A consultant or service lead
  • One or more sites
// Get user's available firms
$firms = $user->getAvailableFirms();

// Get firms for current institution only
$institutionFirms = $user->getFirmsForCurrentInstitution();

// Save firm assignments
$user->saveFirms([1, 5, 12]); // Array of firm IDs
Users without global_firm_rights must have at least one firm assigned, or they cannot access clinical functionality.

PIN Code Management

OpenEyes supports PIN-based authentication for quick actions and signing:
// Generate PIN for user
$user->generatePin();

// Regenerate existing PIN
$user->generatePin($regenerate = true);

// Verify PIN
if ($user->checkPin($pincode, $user_id, $institution_id, $site_id)) {
    // PIN verified
}

// Check if regeneration limit reached
if ($user->isPincodeRegenReachLimit()) {
    // User has reached 5 regenerations in 12 months
}
PINs can be regenerated up to 5 times within a 12-month period for security purposes (see User.php:48).

Institution-Specific Users

Non-admin users are typically restricted to their assigned institution:
// protected/controllers/AdminController.php:881
if (!$this->checkAccess('admin')) {
    // Get only users for current institution
    $institution = Yii::app()->session['selected_institution_id'];
    
    // Exclude installation admins
    $user_ids = array_diff($institution_user_ids, $admin_user_ids);
    
    $criteria->addInCondition('t.id', $user_ids);
}

API Reference

User Methods

File: protected/models/User.php
  • getFullName() - Returns “FirstName LastName”
  • getFullNameAndTitle() - Returns “Title FirstName LastName”
  • getRoles() - Returns array of CAuthItem roles
  • hasRole($targetRole) - Check if user has specific role
  • saveRoles($roles) - Assign roles to user
  • saveFirms($firms) - Assign firms to user
  • getAvailableFirms() - Get firms user can access
  • generatePin($regenerate) - Generate or regenerate PIN

UserAuthentication Methods

File: protected/models/UserAuthentication.php
  • verifyPassword($password) - Verify password hash
  • handlePassword() - Process password on save
  • setPasswordHash() - Hash password before save
  • isLocalAuth() - Check if using local authentication

Security Best Practices

Strong Passwords

Configure password complexity requirements via pw_restrictions parameters

Least Privilege

Grant users only the roles they need for their work

Regular Audits

Review user accounts and permissions regularly

Disable Inactive Users

Set active = 0 on UserAuthentication for inactive accounts

Build docs developers (and LLMs) love