latterworks commited on
Commit
059111e
·
verified ·
1 Parent(s): 1256743

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +199 -7
app.py CHANGED
@@ -10,7 +10,7 @@ import shodan
10
  import time
11
  from datasets import load_dataset, Dataset
12
  from huggingface_hub import HfApi, login
13
- from huggingface_hub import secrets
14
  from typing import List, Dict, Any, Optional, Tuple
15
  import pandas as pd
16
 
@@ -48,7 +48,7 @@ def get_dataset() -> Dataset:
48
  """Get the dataset with Ollama instances and models."""
49
  try:
50
  # Try to load the existing dataset
51
- hf_token = secrets.get_secret("HF_TOKEN")
52
  dataset = load_dataset(DATASET_NAME, use_auth_token=hf_token)
53
  logger.info(f"Loaded existing dataset: {DATASET_NAME}")
54
  return dataset["train"]
@@ -70,7 +70,7 @@ def get_dataset() -> Dataset:
70
  def push_dataset(dataset: Dataset) -> None:
71
  """Push the dataset to the Hub."""
72
  try:
73
- hf_token = secrets.get_secret("HF_TOKEN")
74
  dataset.push_to_hub(DATASET_NAME, token=hf_token)
75
  logger.info(f"Pushed dataset to Hub: {DATASET_NAME}")
76
  except Exception as e:
@@ -203,8 +203,13 @@ async def scan_ollama_instances(progress=None) -> Tuple[str, Dataset]:
203
 
204
  # Get secrets
205
  try:
206
- shodan_api_key = secrets.get_secret("SHODAN_API_KEY")
207
- shodan_query = secrets.get_secret("SHODAN_QUERY")
 
 
 
 
 
208
  except Exception as e:
209
  logger.error(f"Failed to get secrets: {e}")
210
  return "Error: Failed to retrieve secrets", None
@@ -370,10 +375,195 @@ def get_unique_values(dataset: Dataset) -> Tuple[List[str], List[str]]:
370
  def login_submit(password: str) -> Tuple[bool, str, str]:
371
  """Handle admin login."""
372
  try:
373
- stored_password = secrets.get_secret("ADMIN_PASSWORD")
 
 
 
 
374
 
375
  # Check if stored password is already hashed
376
- if stored_password.startswith('$2b$'):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
  is_valid = verify_password(password, stored_password)
378
  else:
379
  # Compare directly for first-time setup
@@ -383,6 +573,8 @@ def login_submit(password: str) -> Tuple[bool, str, str]:
383
  if is_valid:
384
  hashed_password = hash_password(stored_password)
385
  logger.info("Hashed admin password for future use")
 
 
386
 
387
  if is_valid:
388
  return True, "success", "Login successful! You now have admin access."
 
10
  import time
11
  from datasets import load_dataset, Dataset
12
  from huggingface_hub import HfApi, login
13
+ import os
14
  from typing import List, Dict, Any, Optional, Tuple
15
  import pandas as pd
16
 
 
48
  """Get the dataset with Ollama instances and models."""
49
  try:
50
  # Try to load the existing dataset
51
+ hf_token = os.getenv("HF_TOKEN")
52
  dataset = load_dataset(DATASET_NAME, use_auth_token=hf_token)
53
  logger.info(f"Loaded existing dataset: {DATASET_NAME}")
54
  return dataset["train"]
 
70
  def push_dataset(dataset: Dataset) -> None:
71
  """Push the dataset to the Hub."""
72
  try:
73
+ hf_token = os.getenv("HF_TOKEN")
74
  dataset.push_to_hub(DATASET_NAME, token=hf_token)
75
  logger.info(f"Pushed dataset to Hub: {DATASET_NAME}")
76
  except Exception as e:
 
203
 
204
  # Get secrets
205
  try:
206
+ shodan_api_key = os.getenv("SHODAN_API_KEY")
207
+ shodan_query = os.getenv("SHODAN_QUERY")
208
+
209
+ if not shodan_api_key:
210
+ raise ValueError("SHODAN_API_KEY environment variable is not set")
211
+ if not shodan_query:
212
+ raise ValueError("SHODAN_QUERY environment variable is not set")
213
  except Exception as e:
214
  logger.error(f"Failed to get secrets: {e}")
215
  return "Error: Failed to retrieve secrets", None
 
375
  def login_submit(password: str) -> Tuple[bool, str, str]:
376
  """Handle admin login."""
377
  try:
378
+ stored_password = os.getenv("ADMIN_PASSWORD")
379
+
380
+ if not stored_password:
381
+ logger.error("ADMIN_PASSWORD environment variable is not set")
382
+ return False, "error", "Admin password is not configured. Please contact the administrator."
383
 
384
  # Check if stored password is already hashed
385
+ if stored_password.startswith('$2b
386
+
387
+ def search_models(
388
+ family: str,
389
+ parameter_size: str,
390
+ name_search: str,
391
+ is_admin: bool,
392
+ dataset: Dataset
393
+ ) -> Tuple[pd.DataFrame, List[Dict[str, Any]]]:
394
+ """Search and filter models in the dataset."""
395
+ df, details = filter_and_search_models(
396
+ dataset,
397
+ family=None if family == "All" else family,
398
+ parameter_size=None if parameter_size == "All" else parameter_size,
399
+ name_search=name_search,
400
+ is_admin=is_admin
401
+ )
402
+ return df, details
403
+
404
+ def show_model_details(evt: gr.SelectData, models: List[Dict[str, Any]]) -> Dict[str, Any]:
405
+ """Show details for a selected model."""
406
+ if not models or evt.index[0] >= len(models):
407
+ return {}
408
+
409
+ model = models[evt.index[0]]
410
+ return model
411
+
412
+ # Main Gradio application
413
+ def create_app():
414
+ with gr.Blocks(title="Ollama Scanner", theme=gr.themes.Soft()) as app:
415
+ # State variables
416
+ admin_logged_in = gr.State(False)
417
+ dataset_state = gr.State(get_dataset())
418
+ model_details_state = gr.State([])
419
+
420
+ # Header
421
+ gr.Markdown("# 🔍 Ollama Scanner")
422
+ gr.Markdown("Browse publicly accessible Ollama instances and their models")
423
+
424
+ # Login tab
425
+ with gr.Tab("Admin Login") as login_tab:
426
+ with gr.Group():
427
+ gr.Markdown("### Admin Login")
428
+ gr.Markdown("Enter the admin password to access administrative features.")
429
+
430
+ admin_password = gr.Textbox(
431
+ type="password",
432
+ label="Admin Password",
433
+ placeholder="Enter admin password"
434
+ )
435
+ login_btn = gr.Button("Login", variant="primary")
436
+ login_status = gr.Markdown("")
437
+
438
+ # Browse Models tab
439
+ with gr.Tab("Browse Models") as browse_tab:
440
+ with gr.Row():
441
+ # Filters column
442
+ with gr.Column(scale=1):
443
+ gr.Markdown("### Filters")
444
+
445
+ family_dropdown = gr.Dropdown(
446
+ choices=["All"],
447
+ value="All",
448
+ label="Model Family"
449
+ )
450
+
451
+ parameter_size_dropdown = gr.Dropdown(
452
+ choices=["All"],
453
+ value="All",
454
+ label="Parameter Size"
455
+ )
456
+
457
+ name_search = gr.Textbox(
458
+ label="Search by Name",
459
+ placeholder="Search model names..."
460
+ )
461
+
462
+ search_btn = gr.Button("Search", variant="primary")
463
+
464
+ stats_box = gr.Markdown("Loading stats...")
465
+
466
+ # Results column
467
+ with gr.Column(scale=2):
468
+ gr.Markdown("### Results")
469
+
470
+ results_table = gr.DataFrame(
471
+ label="Models",
472
+ interactive=False
473
+ )
474
+
475
+ model_json_display = gr.JSON(
476
+ label="Model Details",
477
+ visible=True
478
+ )
479
+
480
+ # Shodan Scan tab (admin only)
481
+ with gr.Tab("Shodan Scan", visible=False) as scan_tab:
482
+ with gr.Group():
483
+ gr.Markdown("### Shodan Scan")
484
+ gr.Markdown("Scan for publicly accessible Ollama instances using Shodan.")
485
+
486
+ scan_btn = gr.Button("Start Scan", variant="primary")
487
+ scan_progress = gr.Textbox(
488
+ label="Scan Status",
489
+ placeholder="Click 'Start Scan' to begin scanning...",
490
+ interactive=False
491
+ )
492
+
493
+ # Login logic
494
+ def handle_login(password):
495
+ is_admin, status, message = login_submit(password)
496
+ if is_admin:
497
+ return is_admin, message, gr.update(visible=True)
498
+ else:
499
+ return is_admin, message, gr.update(visible=False)
500
+
501
+ login_btn.click(
502
+ handle_login,
503
+ inputs=[admin_password],
504
+ outputs=[admin_logged_in, login_status, scan_tab]
505
+ )
506
+
507
+ # Search logic
508
+ def update_stats(dataset):
509
+ total_instances = len(dataset)
510
+ models_count = sum(len(instance.get('models', [])) for instance in dataset)
511
+
512
+ families, parameter_sizes = get_unique_values(dataset)
513
+ family_count = len(families) - 1 # Subtract "All"
514
+
515
+ return f"**Stats:** {total_instances} instances, {models_count} models, {family_count} families"
516
+
517
+ search_btn.click(
518
+ search_models,
519
+ inputs=[family_dropdown, parameter_size_dropdown, name_search, admin_logged_in, dataset_state],
520
+ outputs=[results_table, model_details_state]
521
+ )
522
+
523
+ # Model selection logic
524
+ results_table.select(
525
+ show_model_details,
526
+ inputs=[model_details_state],
527
+ outputs=[model_json_display]
528
+ )
529
+
530
+ # Scan logic
531
+ async def run_scan():
532
+ result, updated_dataset = await scan_ollama_instances()
533
+ if updated_dataset is not None:
534
+ return result, updated_dataset, *get_unique_values(updated_dataset), update_stats(updated_dataset)
535
+ else:
536
+ return result, None, [], [], ""
537
+
538
+ scan_btn.click(
539
+ run_scan,
540
+ inputs=[],
541
+ outputs=[scan_progress, dataset_state, family_dropdown, parameter_size_dropdown, stats_box]
542
+ )
543
+
544
+ # Initial data load
545
+ def init_ui(dataset):
546
+ families, parameter_sizes = get_unique_values(dataset)
547
+ stats = update_stats(dataset)
548
+
549
+ # Run initial search
550
+ df, details = search_models("All", "All", "", False, dataset)
551
+
552
+ return families, parameter_sizes, stats, df, details
553
+
554
+ app.load(
555
+ init_ui,
556
+ inputs=[dataset_state],
557
+ outputs=[family_dropdown, parameter_size_dropdown, stats_box, results_table, model_details_state]
558
+ )
559
+
560
+ return app
561
+
562
+ # Start the application
563
+ if __name__ == "__main__":
564
+ app = create_app()
565
+ app.launch()
566
+ ):
567
  is_valid = verify_password(password, stored_password)
568
  else:
569
  # Compare directly for first-time setup
 
573
  if is_valid:
574
  hashed_password = hash_password(stored_password)
575
  logger.info("Hashed admin password for future use")
576
+ # Note: We can't store the hashed password back to environment variables
577
+ # in a Hugging Face Space environment. This would require a different approach.
578
 
579
  if is_valid:
580
  return True, "success", "Login successful! You now have admin access."