diff --git a/app.py b/app.py index 8349d33..35dff5e 100644 --- a/app.py +++ b/app.py @@ -22,7 +22,7 @@ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # Docker tab caches stale container IDs, so the footer is the reliable way # to confirm a `docker compose up -d --build` actually took effect. # Both are env-overridable if the deploy pipeline ever injects them. -APP_VERSION = os.environ.get("APP_VERSION", "1.6.1") +APP_VERSION = os.environ.get("APP_VERSION", "1.6.0") APP_VERSION_DATE = os.environ.get("APP_VERSION_DATE", "2026-08-27") # Must point at a path that survives `docker compose up --build` — the @@ -45,19 +45,6 @@ def save_settings(data): with open(SETTINGS_FILE, "w") as f: json.dump(existing, f, indent=2) -def delete_setting(key): - """Remove a key outright. save_settings() only ever merges, so it can't - take something away — used to retire the plaintext shared password once - real accounts exist. Returns True if the key was there.""" - settings = load_settings() - if key not in settings: - return False - del settings[key] - os.makedirs(os.path.dirname(SETTINGS_FILE) or ".", exist_ok=True) - with open(SETTINGS_FILE, "w") as f: - json.dump(settings, f, indent=2) - return True - app = Flask(__name__) app.secret_key = os.environ.get("SECRET_KEY") or secrets.token_hex(32) diff --git a/manage_users.py b/manage_users.py index 22f804e..1e64dcd 100644 --- a/manage_users.py +++ b/manage_users.py @@ -12,17 +12,10 @@ Run it inside the container, where Werkzeug and the real settings.json are: docker exec -it arr-summary python3 manage_users.py add docker exec -it arr-summary python3 manage_users.py passwd docker exec -it arr-summary python3 manage_users.py remove - docker exec -it arr-summary python3 manage_users.py retire-shared-password The first `add` switches the dashboard from its single shared password to per-user logins. Until then the old LOGIN_PASSWORD keeps working, so you can't lock yourself out by deploying this. - -Once accounts exist and you've confirmed they sign in, -`retire-shared-password` deletes the old plaintext login_password from -settings.json. It refuses to run while no accounts exist, because with -nothing configured at all the dashboard treats that as dev mode and lets -anyone in without a password. """ import sys @@ -31,10 +24,7 @@ import getpass from app import ( SETTINGS_FILE, PASSWORD_HASH_METHOD, - LOGIN_PASSWORD, save_settings, - delete_setting, - load_settings, load_users, generate_password_hash, ) @@ -132,49 +122,7 @@ def cmd_remove(args): return 0 -def cmd_retire_shared_password(_args): - """Delete the plaintext login_password from settings.json. - - Guarded, because removing it while nothing else is configured makes - get_active_password() empty — and the login route reads "no credentials - at all" as dev mode and lets anyone straight in. - """ - users = load_users() - if not users: - print("Refusing: no accounts exist yet, so the shared password is still", - file=sys.stderr) - print("the only way in. Run `add ` first and check you can", - file=sys.stderr) - print("sign in with it, then run this again.", file=sys.stderr) - return 1 - - if "login_password" not in load_settings(): - print("Nothing to do — settings.json has no login_password.") - if LOGIN_PASSWORD: - print() - print("Note: LOGIN_PASSWORD is still set in the environment. It's") - print("ignored while accounts exist, but clear it from .env too if") - print("you want the old shared password gone entirely.") - return 0 - - delete_setting("login_password") - print(f"Removed the plaintext login_password from {SETTINGS_FILE}.") - print(f"{len(users)} account(s) remain in use: {', '.join(sorted(users))}") - if LOGIN_PASSWORD: - print() - print("LOGIN_PASSWORD is still set in the environment. It's ignored while") - print("accounts exist, but clear it from .env and restart to be rid of it.") - print("Don't clear it before you've confirmed the accounts work.") - return 0 - - -COMMANDS = { - "list": cmd_list, - "add": cmd_add, - "passwd": cmd_passwd, - "remove": cmd_remove, - "retire-shared-password": cmd_retire_shared_password, -} +COMMANDS = {"list": cmd_list, "add": cmd_add, "passwd": cmd_passwd, "remove": cmd_remove} def main(argv):