Enhance publiser password management tool
Add support for multiple users in the password utility. New features allow listing existing users and removing specific users from the `.htpasswd` file without overwriting others.
This commit is contained in:
parent
747e730366
commit
6525b561c2
2 changed files with 59 additions and 14 deletions
|
|
@ -1,14 +1,18 @@
|
||||||
#!/usr/bin/env php
|
#!/usr/bin/env php
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Set or reset the Basic Auth login for /publiser.
|
* Add, update, or remove a Basic Auth login for /publiser.
|
||||||
*
|
*
|
||||||
* Writes a bcrypt-hashed .htpasswd file (no dependency on the `htpasswd`
|
* Writes bcrypt-hashed entries to .htpasswd (no dependency on the
|
||||||
* binary being installed - Apache's mod_authn_file accepts $2y$ hashes).
|
* `htpasswd` binary being installed - Apache's mod_authn_file accepts
|
||||||
|
* $2y$ hashes). Existing users are preserved: re-running with a known
|
||||||
|
* username updates just that line, any other username is appended.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* php custom/tools/set-publiser-password.php <username> <password>
|
* php custom/tools/set-publiser-password.php <username> <password>
|
||||||
* php custom/tools/set-publiser-password.php (interactive)
|
* php custom/tools/set-publiser-password.php (interactive)
|
||||||
|
* php custom/tools/set-publiser-password.php --remove <username>
|
||||||
|
* php custom/tools/set-publiser-password.php --list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$htpasswdPath = dirname(__DIR__, 2) . '/content/publiser/.htpasswd';
|
$htpasswdPath = dirname(__DIR__, 2) . '/content/publiser/.htpasswd';
|
||||||
|
|
@ -31,8 +35,50 @@ function promptHidden(string $question): string {
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readUsers(string $path): array {
|
||||||
|
if (!is_file($path)) return [];
|
||||||
|
$users = [];
|
||||||
|
foreach (file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [] as $line) {
|
||||||
|
[$user, $hash] = array_pad(explode(':', $line, 2), 2, '');
|
||||||
|
if ($user !== '') $users[$user] = $hash;
|
||||||
|
}
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeUsers(string $path, array $users): void {
|
||||||
|
$lines = [];
|
||||||
|
foreach ($users as $user => $hash) {
|
||||||
|
$lines[] = "$user:$hash";
|
||||||
|
}
|
||||||
|
file_put_contents($path, $lines ? implode("\n", $lines) . "\n" : '');
|
||||||
|
// World-readable: the web server user (www-data, varies by host/container)
|
||||||
|
// needs read access. This is safe - Apache denies direct HTTP access to
|
||||||
|
// this exact filename (content/publiser/.htaccess), and reaching it any
|
||||||
|
// other way already requires shell/filesystem access to the server.
|
||||||
|
chmod($path, 0644);
|
||||||
|
}
|
||||||
|
|
||||||
$args = array_slice($argv, 1);
|
$args = array_slice($argv, 1);
|
||||||
|
|
||||||
|
if (($args[0] ?? '') === '--list') {
|
||||||
|
$users = array_keys(readUsers($htpasswdPath));
|
||||||
|
echo $users ? implode("\n", $users) . "\n" : "No users configured yet.\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($args[0] ?? '') === '--remove') {
|
||||||
|
$username = $args[1] ?? prompt('Username to remove: ');
|
||||||
|
$users = readUsers($htpasswdPath);
|
||||||
|
if (!isset($users[$username])) {
|
||||||
|
fwrite(STDERR, "No such user: $username\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
unset($users[$username]);
|
||||||
|
writeUsers($htpasswdPath, $users);
|
||||||
|
echo "Removed \"$username\". " . count($users) . " user(s) remain.\n";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
$username = $args[0] ?? prompt('Username: ');
|
$username = $args[0] ?? prompt('Username: ');
|
||||||
$password = $args[1] ?? promptHidden('Password: ');
|
$password = $args[1] ?? promptHidden('Password: ');
|
||||||
|
|
||||||
|
|
@ -46,12 +92,9 @@ if (str_contains($username, ':')) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash = password_hash($password, PASSWORD_BCRYPT);
|
$users = readUsers($htpasswdPath);
|
||||||
file_put_contents($htpasswdPath, "$username:$hash\n");
|
$isNew = !isset($users[$username]);
|
||||||
// World-readable: the web server user (www-data, varies by host/container)
|
$users[$username] = password_hash($password, PASSWORD_BCRYPT);
|
||||||
// needs read access. This is safe - Apache denies direct HTTP access to
|
writeUsers($htpasswdPath, $users);
|
||||||
// this exact filename (content/publiser/.htaccess), and reaching it any
|
|
||||||
// other way already requires shell/filesystem access to the server.
|
|
||||||
chmod($htpasswdPath, 0644);
|
|
||||||
|
|
||||||
echo "Wrote $htpasswdPath for user \"$username\".\n";
|
echo ($isNew ? 'Added' : 'Updated') . " \"$username\". " . count($users) . " user(s) total in $htpasswdPath.\n";
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,15 @@ Standalone admin app for authoring, managing, and scheduling `content/nyheter/`
|
||||||
|
|
||||||
`content/publiser/.htaccess` sets `DirectorySlash On` (the site-wide default is `Off` - see Critical section below) and forwards the `Authorization` header via `RewriteRule ... [E=HTTP_AUTHORIZATION:...]` for SAPIs (LSAPI/CGI/FastCGI, used on cPanel) that strip it by default.
|
`content/publiser/.htaccess` sets `DirectorySlash On` (the site-wide default is `Off` - see Critical section below) and forwards the `Authorization` header via `RewriteRule ... [E=HTTP_AUTHORIZATION:...]` for SAPIs (LSAPI/CGI/FastCGI, used on cPanel) that strip it by default.
|
||||||
|
|
||||||
Auth itself is checked in PHP (`publiserRequireAuth()` in `index.php`), not via Apache's `AuthUserFile` - that directive needs an absolute path that differs between the podman dev container and cPanel, so a bcrypt `.htpasswd` (same format `mod_authn_file` would use) is read and verified manually instead. Set the login with:
|
Auth itself is checked in PHP (`publiserRequireAuth()` in `index.php`), not via Apache's `AuthUserFile` - that directive needs an absolute path that differs between the podman dev container and cPanel, so a bcrypt `.htpasswd` (same format `mod_authn_file` would use) is read and verified manually instead. Manage logins with:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
php custom/tools/set-publiser-password.php <username> <password>
|
php custom/tools/set-publiser-password.php <username> <password> # add, or update if it exists
|
||||||
|
php custom/tools/set-publiser-password.php --list
|
||||||
|
php custom/tools/set-publiser-password.php --remove <username>
|
||||||
```
|
```
|
||||||
|
|
||||||
This writes `content/publiser/.htpasswd` (gitignored, `0644` - see comment in the script for why world-readable is fine here).
|
Supports multiple users - adding/updating one username preserves everyone else's entry in `content/publiser/.htpasswd` (gitignored, `0644` - see comment in the script for why world-readable is fine here). There's no per-user attribution anywhere in the tool (all edits are just "whoever is logged in"); this only lets more than one person log in.
|
||||||
|
|
||||||
## Content Model
|
## Content Model
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue