zukhriddinai commited on
Commit
9857cf9
·
verified ·
1 Parent(s): 286c609

Deploy public authenticated AutoML gateway

Browse files
Files changed (1) hide show
  1. auth_storage.py +108 -1
auth_storage.py CHANGED
@@ -113,6 +113,110 @@ def _copy_valid_database(source: Path, destination: Path) -> bool:
113
  staged.unlink(missing_ok=True)
114
 
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  def _prepare_runtime_database() -> None:
117
  global _RUNTIME_DB_PREPARED
118
  if _RUNTIME_DB_PREPARED or not _snapshot_database_enabled():
@@ -133,7 +237,10 @@ def _prepare_runtime_database() -> None:
133
  )
134
  if any(candidate.is_file() for candidate in candidates):
135
  for candidate in candidates:
136
- if _copy_valid_database(candidate, runtime_path):
 
 
 
137
  _RUNTIME_DB_PREPARED = True
138
  return
139
  raise StorageConfigurationError(
 
113
  staged.unlink(missing_ok=True)
114
 
115
 
116
+ def _salvage_database(source: Path, destination: Path) -> bool:
117
+ """Rebuild readable application tables without trusting damaged indexes."""
118
+
119
+ if not source.is_file():
120
+ return False
121
+ staged = destination.with_suffix(destination.suffix + ".salvage")
122
+ staged.unlink(missing_ok=True)
123
+ source_conn = None
124
+ destination_conn = None
125
+ tables = (
126
+ (
127
+ "users",
128
+ frozenset(
129
+ {
130
+ "user_id",
131
+ "username",
132
+ "username_normalized",
133
+ "password_hash",
134
+ "password_salt",
135
+ }
136
+ ),
137
+ ),
138
+ (
139
+ "saved_models",
140
+ frozenset(
141
+ {
142
+ "model_id",
143
+ "user_id",
144
+ "manifest_json",
145
+ "storage_path",
146
+ "sha256",
147
+ }
148
+ ),
149
+ ),
150
+ (
151
+ "scheduled_jobs",
152
+ frozenset(
153
+ {
154
+ "request_id",
155
+ "user_id",
156
+ "idempotency_key",
157
+ "provider",
158
+ "status",
159
+ }
160
+ ),
161
+ ),
162
+ )
163
+ try:
164
+ uri = f"file:{source.resolve()}?mode=ro&immutable=1"
165
+ source_conn = sqlite3.connect(uri, uri=True, timeout=5)
166
+ source_conn.row_factory = sqlite3.Row
167
+ source_conn.execute("PRAGMA writable_schema=ON")
168
+ destination.parent.mkdir(parents=True, exist_ok=True)
169
+ destination_conn = sqlite3.connect(str(staged), timeout=30)
170
+ destination_conn.row_factory = sqlite3.Row
171
+ destination_conn.execute("PRAGMA journal_mode=DELETE")
172
+ destination_conn.execute("PRAGMA foreign_keys=ON")
173
+ _create_schema(destination_conn)
174
+
175
+ for table, required_columns in tables:
176
+ columns = [
177
+ str(row["name"])
178
+ for row in source_conn.execute(
179
+ f"PRAGMA table_info({table})"
180
+ ).fetchall()
181
+ ]
182
+ if not required_columns.issubset(columns) or any(
183
+ not re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", column)
184
+ for column in columns
185
+ ):
186
+ return False
187
+ rows = source_conn.execute(f"SELECT * FROM {table}").fetchall()
188
+ source_count = int(
189
+ source_conn.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
190
+ )
191
+ if len(rows) != source_count:
192
+ return False
193
+ if rows:
194
+ quoted_columns = ", ".join(f'"{column}"' for column in columns)
195
+ placeholders = ", ".join("?" for _ in columns)
196
+ destination_conn.executemany(
197
+ f"INSERT INTO {table} ({quoted_columns}) VALUES ({placeholders})",
198
+ [tuple(row[column] for column in columns) for row in rows],
199
+ )
200
+
201
+ if destination_conn.execute("PRAGMA foreign_key_check").fetchone():
202
+ return False
203
+ destination_conn.commit()
204
+ destination_conn.close()
205
+ destination_conn = None
206
+ if not _database_integrity_ok(staged):
207
+ return False
208
+ os.replace(staged, destination)
209
+ return True
210
+ except (OSError, sqlite3.DatabaseError, TypeError, ValueError):
211
+ return False
212
+ finally:
213
+ if source_conn is not None:
214
+ source_conn.close()
215
+ if destination_conn is not None:
216
+ destination_conn.close()
217
+ staged.unlink(missing_ok=True)
218
+
219
+
220
  def _prepare_runtime_database() -> None:
221
  global _RUNTIME_DB_PREPARED
222
  if _RUNTIME_DB_PREPARED or not _snapshot_database_enabled():
 
237
  )
238
  if any(candidate.is_file() for candidate in candidates):
239
  for candidate in candidates:
240
+ if _copy_valid_database(candidate, runtime_path) or _salvage_database(
241
+ candidate,
242
+ runtime_path,
243
+ ):
244
  _RUNTIME_DB_PREPARED = True
245
  return
246
  raise StorageConfigurationError(