1
0

setup_db.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import pymysql
  2. import getpass
  3. import os
  4. def run_db_setup():
  5. """
  6. This Python script prompts for passwords securely and executes CREATE USER / GRANT
  7. statements to provision the MySQL server dynamically without config files.
  8. """
  9. print("Welcome to Local Food AI Initial Setup.")
  10. print("WARNING: This will configure your MySQL server. You must know the MySQL root password.\n")
  11. # Automatically fetch passwords for secure CI/CD deployment or fallback for exam/local setup
  12. root_password = os.environ.get("MYSQL_ROOT_PASSWORD", "")
  13. owner_pass = os.environ.get("DB_OWNER_PASS", "BTSai123")
  14. reader_pass = os.environ.get("DB_READER_PASS", "BTSai123")
  15. loader_pass = os.environ.get("DB_LOADER_PASS", "BTSai123")
  16. app_auth_pass = os.environ.get("DB_AUTH_PASS", "BTSai123")
  17. print("\nConnecting as root to configure server...")
  18. try:
  19. # Connect using the local unix socket which allows seamless auth_socket root login on Ubuntu
  20. conn = pymysql.connect(
  21. unix_socket='/var/run/mysqld/mysqld.sock',
  22. user='root',
  23. password=root_password,
  24. autocommit=True
  25. )
  26. cursor = conn.cursor()
  27. except Exception as e:
  28. print(f"Failed to connect: {e}")
  29. return
  30. queries = [
  31. "CREATE DATABASE IF NOT EXISTS food_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;",
  32. # Owner User
  33. f"CREATE USER IF NOT EXISTS 'db_owner'@'%' IDENTIFIED BY '{owner_pass}';",
  34. "GRANT ALL PRIVILEGES ON food_db.* TO 'db_owner'@'%' WITH GRANT OPTION;",
  35. # Reader User
  36. f"CREATE USER IF NOT EXISTS 'db_reader'@'%' IDENTIFIED BY '{reader_pass}';",
  37. "GRANT USAGE ON *.* TO 'db_reader'@'%';",
  38. # Loader User
  39. f"CREATE USER IF NOT EXISTS 'db_loader'@'%' IDENTIFIED BY '{loader_pass}';",
  40. "GRANT USAGE ON *.* TO 'db_loader'@'%';",
  41. "GRANT FILE ON *.* TO 'db_loader'@'%';",
  42. # App Auth User (PoLP)
  43. f"CREATE USER IF NOT EXISTS 'db_app_auth'@'%' IDENTIFIED BY '{app_auth_pass}';",
  44. "GRANT USAGE ON *.* TO 'db_app_auth'@'%';",
  45. "FLUSH PRIVILEGES;"
  46. ]
  47. for q in queries:
  48. print(f"Executing: {q[:60]}...")
  49. cursor.execute(q)
  50. # Now create the table logic safely
  51. print("\nCreating Tables and Granting Table-Specific Access...")
  52. # 1. Users Table
  53. cursor.execute("""
  54. CREATE TABLE IF NOT EXISTS food_db.users (
  55. id INT AUTO_INCREMENT PRIMARY KEY,
  56. username VARCHAR(100) UNIQUE NOT NULL,
  57. password_hash VARCHAR(255) NOT NULL,
  58. created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  59. ) ENGINE=InnoDB;
  60. """)
  61. # 2. Products Table (Dynamic Drop)
  62. # We drop the strict schema completely. `ingest_csv.py` will use pandas to automatically
  63. # generate the table with 100% of the CSV columns dynamically defined as TEXT fields.
  64. cursor.execute("DROP TABLE IF EXISTS food_db.products;")
  65. # Table Context Grants (SoD)
  66. cursor.execute("GRANT SELECT, INSERT, UPDATE ON food_db.users TO 'db_app_auth'@'%';")
  67. # Note: Reader/Loader grants on products table will be handled or applied at the database level
  68. # since the table won't exist until pandas creates it. Granting at db-level for these specific users.
  69. cursor.execute("GRANT SELECT ON food_db.* TO 'db_reader'@'%';")
  70. cursor.execute("GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, ALTER, INDEX ON food_db.* TO 'db_loader'@'%';")
  71. cursor.execute("FLUSH PRIVILEGES;")
  72. print("\n✅ Database, Users, and Tables created successfully!")
  73. cursor.close()
  74. conn.close()
  75. print("\n🎉 Setup Complete.")
  76. print("\n!!! IMPORTANT NEXT STEPS !!!")
  77. print("Now, use `mysql_config_editor` to store these passwords locally so the app can use them:")
  78. print(" mysql_config_editor set --login-path=app_reader --host=127.0.0.1 --user=db_reader --password")
  79. print(" mysql_config_editor set --login-path=app_auth --host=127.0.0.1 --user=db_app_auth --password")
  80. if __name__ == "__main__":
  81. run_db_setup()