* Add a user. * * @param string $username * @param string $password * @param string $isAdmin "1" or "0" * @param bool $setupMode overwrite file if true */
($username, $password, $isAdmin, $setupMode)
| 288 | * @param bool $setupMode overwrite file if true |
| 289 | */ |
| 290 | public static function addUser($username, $password, $isAdmin, $setupMode) |
| 291 | { |
| 292 | $usersFile = USERS_DIR . USERS_FILE; |
| 293 | |
| 294 | // Defense in depth |
| 295 | if (!preg_match(REGEX_USER, $username)) { |
| 296 | return ["error" => "Invalid username"]; |
| 297 | } |
| 298 | if (!is_string($password) || $password === '') { |
| 299 | return ["error" => "Password required"]; |
| 300 | } |
| 301 | $isAdmin = $isAdmin === '1' ? '1' : '0'; |
| 302 | |
| 303 | if (!file_exists($usersFile)) { |
| 304 | @file_put_contents($usersFile, '', LOCK_EX); |
| 305 | } |
| 306 | |
| 307 | // Check duplicates |
| 308 | $existingUsers = file($usersFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []; |
| 309 | foreach ($existingUsers as $line) { |
| 310 | $parts = explode(':', trim($line)); |
| 311 | if (isset($parts[0]) && strcasecmp($username, $parts[0]) === 0) { |
| 312 | return ["error" => "User already exists"]; |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | $hashedPassword = password_hash($password, PASSWORD_BCRYPT); |
| 317 | $newUserLine = $username . ":" . $hashedPassword . ":" . $isAdmin . PHP_EOL; |
| 318 | |
| 319 | if ($setupMode) { |
| 320 | if (file_put_contents($usersFile, $newUserLine, LOCK_EX) === false) { |
| 321 | return ["error" => "Failed to write users file"]; |
| 322 | } |
| 323 | if (!self::markSetupComplete()) { |
| 324 | error_log('FileRise: initial admin was created but setup-complete marker could not be written.'); |
| 325 | } |
| 326 | } else { |
| 327 | if (file_put_contents($usersFile, $newUserLine, FILE_APPEND | LOCK_EX) === false) { |
| 328 | return ["error" => "Failed to write users file"]; |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | return ["success" => "User added successfully"]; |
| 333 | } |
| 334 | |
| 335 | /** |
| 336 | * Remove a user and update encrypted userPermissions.json. |
no test coverage detected