TMC HRIS temporarily unavailable
Please try again shortly or use the desktop HRIS.
$_SESSION['user'] = $user; // Version 20260929.04 { $db = Database::connection(); $stmt = $db->prepare('SELECT * FROM web_users WHERE username = ? AND active = 1 LIMIT 1'); $stmt->execute([$username]); $user = $stmt->fetch(); // Explicitly provisioned web administrators do not use MySQL root or // a desktop employee identity. All other accounts remain desktop-backed. if ($user && ($user['account_type'] ?? '') === 'web_admin') { if (!self::isWebAdministrator($user) || !password_verify($password, (string)$user['password_hash'])) return false; return self::startSession($user); } if ($user && Permissions::isExternalViewer($user)) { if (!password_verify($password,(string)$user['password_hash']) || !Permissions::externalModuleKeys($user)) return false; return self::startSession($user); } // TMC's desktop account remains authoritative for password, activation // and access level. A cached web hash must never bypass a desktop reset. if (!$user) { $disabled=$db->prepare('SELECT id FROM web_users WHERE username=? AND active=0 LIMIT 1'); $disabled->execute([$username]); if($disabled->fetchColumn())return false; } // Accept the rolling-key variants produced by historical Delphi builds. $legacy = $db->prepare("SELECT u.UserID,u.LoginName,u.Password,u.Emp_ID_Str,u.Access_Restrictions,u.Auth, COALESCE(e.first_name,'') first_name,COALESCE(e.last_name,'') last_name FROM users u LEFT JOIN emp_info e ON e.Employee_ID_Str=u.Emp_ID_Str WHERE u.LoginName=? AND u.Active=1 LIMIT 1"); $legacy->execute([$username]); $desktop = $legacy->fetch(); if (!$desktop || !self::verifyDesktopPassword($password,(string)$desktop['Password'])) return false; $level = (int)$desktop['Access_Restrictions']; if (!array_key_exists($level, Permissions::LEVELS)) return false; if(!self::parallelLevelAllowed($level))return false; $firstName = trim((string)$desktop['first_name']); $lastName = trim((string)$desktop['last_name']); if ($firstName==='' && $lastName==='') $firstName=(string)$desktop['LoginName']; $linked = $db->prepare('SELECT * FROM web_users WHERE legacy_user_id=? OR username=? ORDER BY legacy_user_id=? DESC LIMIT 1'); $linked->execute([(int)$desktop['UserID'],$desktop['LoginName'],(int)$desktop['UserID']]); $user = $linked->fetch(); $hash = password_hash($password,PASSWORD_DEFAULT); $role = Permissions::roleForLevel($level); if ($user) { $db->prepare('UPDATE web_users SET legacy_user_id=?,employee_id_str=?,username=?,password_hash=?,first_name=?,last_name=?,role=?,access_level=?,legacy_auth=?,active=1 WHERE id=?') ->execute([(int)$desktop['UserID'],$desktop['Emp_ID_Str'],$desktop['LoginName'],$hash,$firstName,$lastName,$role,$level,(int)$desktop['Auth'],(int)$user['id']]); $userId=(int)$user['id']; } else { $db->prepare('INSERT INTO web_users (legacy_user_id,employee_id_str,username,password_hash,first_name,last_name,role,access_level,legacy_auth,active) VALUES (?,?,?,?,?,?,?,?,?,1)') ->execute([(int)$desktop['UserID'],$desktop['Emp_ID_Str'],$desktop['LoginName'],$hash,$firstName,$lastName,$role,$level,(int)$desktop['Auth']]); $userId=(int)$db->lastInsertId(); } $fresh=$db->prepare('SELECT * FROM web_users WHERE id=?'); $fresh->execute([$userId]); return self::startSession($fresh->fetch()); } private static function verifyDesktopPassword(string $plain,string $stored): bool { $stored=strtoupper(trim($stored)); $plain=trim($plain); foreach(['zero','high','low'] as $mode){ if(hash_equals($stored,self::desktopEncrypt($plain,$mode))) return true; } return false; } private static function desktopEncrypt(string $plain,string $mode): string { $bytes=unpack('C*',$plain)?:[]; $key=223; $out=''; foreach($bytes as $byte){ $mask=match($mode){'high'=>($key>>8)&255,'low'=>$key&255,default=>0}; $encrypted=$byte^$mask; $out.=sprintf('%02X',$encrypted); $key=(($encrypted+$key)*17619+91671)&0xffff; } return $out; } private static function startSession(array $user): bool { $db=Database::connection(); $employeeId=trim((string)($user['employee_id_str']??'')); if($employeeId!==''){ $active=$db->prepare("SELECT 1 FROM emp_activestat WHERE Emp_ID_Str=? AND Active_Stat=1 AND Date_Eff_Frm<=CURRENT_DATE AND (Date_Eff_to IS NULL OR Date_Eff_to>=CURRENT_DATE) ORDER BY Date_Eff_Frm DESC LIMIT 1"); $active->execute([$employeeId]); if(!$active->fetchColumn()) return false; } if(self::isWebAdministrator($user)){ $user['business_unit_id']=null; }elseif(!Permissions::isExternalViewer($user)){ $legacy = $db->prepare('SELECT Auth FROM users WHERE LoginName = ? OR (? IS NOT NULL AND Emp_ID_Str = ?) ORDER BY Active DESC LIMIT 1'); $legacy->execute([$user['username'], $user['employee_id_str'] ?? null, $user['employee_id_str'] ?? null]); $legacyAuth = $legacy->fetchColumn(); if ($legacyAuth !== false) $user['legacy_auth'] = (int)$legacyAuth; $unit=$db->prepare("SELECT eb.Bus_Unit_Id_Str FROM emp_bus_unit eb WHERE eb.Emp_ID_Str=? AND eb.Date_Eff_Frm<=CURRENT_DATE AND (eb.Date_Eff_to>=CURRENT_DATE OR eb.Date_Eff_to IS NULL) ORDER BY eb.Date_Eff_Frm DESC LIMIT 1"); $unit->execute([$user['employee_id_str']??'']); $user['business_unit_id']=$unit->fetchColumn()?:null; }else{ $user['business_unit_id']=$user['view_business_unit_id']??null; $user['legacy_auth']=0; } session_regenerate_id(true); unset($user['password_hash']); $_SESSION['user'] = $user; $_SESSION['_last_activity'] = time(); $_SESSION['workflow_login_notice_pending'] = 1; $db->prepare('UPDATE web_users SET last_login_at = NOW() WHERE id = ?')->execute([$user['id']]); return true; } public static function user(): ?array { return $_SESSION['user'] ?? null; } private static function isWebAdministrator(array $user): bool { return ($user['account_type'] ?? '') === 'web_admin' && (int)($user['active'] ?? 0) === 1 && (int)($user['access_level'] ?? -1) === 0 && ($user['role'] ?? '') === 'administrator' && empty($user['legacy_user_id']) && empty($user['employee_id_str']); } public static function check(): bool { return isset($_SESSION['user']); } public static function requireLogin(): void { if (!self::check()) redirect('/login'); // Refresh linked desktop permissions and revocation on every request. $current=self::user(); if(($current['account_type']??'')==='web_admin'){ $statement=Database::connection()->prepare('SELECT * FROM web_users WHERE id=? LIMIT 1'); $statement->execute([$current['id']]); $fresh=$statement->fetch(); if(!$fresh || !self::isWebAdministrator($fresh)){self::logout();redirect('/login');} unset($fresh['password_hash']); $fresh['business_unit_id']=null; $_SESSION['user']=$fresh; } if(Permissions::isExternalViewer($current)){ $statement=Database::connection()->prepare("SELECT * FROM web_users WHERE id=? AND active=1 AND account_type='external_view_only'"); $statement->execute([$current['id']]);$fresh=$statement->fetch(); if(!$fresh || !Permissions::externalModuleKeys($fresh)){self::logout();redirect('/login');} unset($fresh['password_hash']);$fresh['business_unit_id']=$fresh['view_business_unit_id'];$_SESSION['user']=$fresh; } if(!empty($current['legacy_user_id'])){ $statement=Database::connection()->prepare('SELECT Active,Access_Restrictions,Auth,Emp_ID_Str FROM users WHERE UserID=? LIMIT 1'); $statement->execute([$current['legacy_user_id']]); $desktop=$statement->fetch(); if(!$desktop || !(int)$desktop['Active'] || !isset(Permissions::LEVELS[(int)$desktop['Access_Restrictions']])){ self::logout();redirect('/login'); } $_SESSION['user']['access_level']=(int)$desktop['Access_Restrictions']; $_SESSION['user']['employee_id_str']=$desktop['Emp_ID_Str']; $_SESSION['user']['role']=Permissions::roleForLevel((int)$desktop['Access_Restrictions']); $_SESSION['user']['legacy_auth']=(int)$desktop['Auth']; if(!self::parallelLevelAllowed((int)$desktop['Access_Restrictions'])){self::logout();redirect('/login');} } $timeout=60; try{$timeout=SettingsService::getInt(Database::connection(),'security.session_timeout_minutes',60);}catch(\Throwable){} $last=(int)($_SESSION['_last_activity']??time()); if($timeout>0 && time()-$last>($timeout*60)){ self::logout(); flash('error','Your HRIS session expired because of inactivity. Please sign in again.'); redirect('/login'); } $_SESSION['_last_activity']=time(); } public static function parallelLevelAllowed(int $level):bool { return config('TMC_PARALLEL_ROLES','false')==='true'?in_array($level,[0,3,4,9,10],true):(config('TMC_VALIDATION_ADMIN_ONLY','true')!=='true'||$level===0); } public static function isAdministrator(): bool { return Permissions::level() === 0; } public static function requireAdministrator(): void { if (!self::isAdministrator()) { http_response_code(403); exit('Administrator access is required.'); } } public static function logout(): void { $_SESSION = []; session_regenerate_id(true); } }
Please try again shortly or use the desktop HRIS.