@@ -96,6 +96,57 @@ def set_sqlite_pragma(dbapi_connection, connection_record):
9696 except Exception :
9797 pass # Column already exists
9898
99+ try :
100+ cols = conn .execute (text ("PRAGMA table_info(users)" )).fetchall ()
101+ # col tuple: (cid, name, type, notnull, dflt_value, pk)
102+ hp = next ((c for c in cols if c [1 ] == "hashed_password" ), None )
103+ if hp and hp [3 ]: # notnull == 1
104+ conn .execute (text ("PRAGMA foreign_keys=OFF" ))
105+ conn .execute (
106+ text (
107+ """
108+ CREATE TABLE users_new (
109+ id VARCHAR(36) PRIMARY KEY,
110+ username VARCHAR(100) NOT NULL UNIQUE,
111+ display_name VARCHAR(100),
112+ email VARCHAR(254),
113+ hashed_password VARCHAR(255),
114+ role VARCHAR(20),
115+ allow_explicit BOOLEAN,
116+ opds_token VARCHAR(64),
117+ oidc_subject VARCHAR(255),
118+ created_at DATETIME
119+ )
120+ """
121+ )
122+ )
123+ conn .execute (
124+ text (
125+ """
126+ INSERT INTO users_new
127+ SELECT id, username, display_name, email, hashed_password,
128+ role, allow_explicit, opds_token, oidc_subject, created_at
129+ FROM users
130+ """
131+ )
132+ )
133+ conn .execute (text ("DROP TABLE users" ))
134+ conn .execute (text ("ALTER TABLE users_new RENAME TO users" ))
135+ conn .execute (
136+ text (
137+ "CREATE UNIQUE INDEX IF NOT EXISTS ix_users_email ON users(email) WHERE email IS NOT NULL"
138+ )
139+ )
140+ conn .execute (
141+ text (
142+ "CREATE UNIQUE INDEX IF NOT EXISTS ix_users_oidc_subject ON users(oidc_subject) WHERE oidc_subject IS NOT NULL"
143+ )
144+ )
145+ conn .execute (text ("PRAGMA foreign_keys=ON" ))
146+ conn .commit ()
147+ except Exception :
148+ pass
149+
99150 # Normalize all stored tags to lowercase, deduplicating within each row.
100151 _normalize_tags_in_db (conn )
101152
0 commit comments