236 lines
9.1 KiB
Bash
236 lines
9.1 KiB
Bash
#!/usr/bin/env python3
|
||
"""
|
||
Wesal Social Media App - Installation Script
|
||
This script sets up all necessary configuration files and secrets for the Wesal app.
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
import secrets
|
||
import string
|
||
import shutil
|
||
from pathlib import Path
|
||
from typing import Optional
|
||
|
||
# ANSI color codes
|
||
class Colors:
|
||
BLUE = '\033[94m'
|
||
GREEN = '\033[92m'
|
||
YELLOW = '\033[93m'
|
||
RED = '\033[91m'
|
||
BOLD = '\033[1m'
|
||
END = '\033[0m'
|
||
|
||
def print_ascii_logo():
|
||
"""Print the Wesal logo in ASCII art with blue color"""
|
||
logo = """
|
||
██╗ ██╗███████╗███████╗ █████╗ ██╗
|
||
██║ ██║██╔════╝██╔════╝██╔══██╗██║
|
||
██║ █╗ ██║█████╗ ███████╗███████║██║
|
||
██║███╗██║██╔══╝ ╚════██║██╔══██║██║
|
||
╚███╔███╔╝███████╗███████║██║ ██║███████╗
|
||
╚══╝╚══╝ ╚══════╝╚══════╝╚═╝ ╚═╝╚══════╝
|
||
|
||
Installation Script
|
||
"""
|
||
print(f"{Colors.BLUE}{Colors.BOLD}{logo}{Colors.END}")
|
||
|
||
def generate_complex_password(length: int = 20) -> str:
|
||
"""Generate a complex password with specified requirements"""
|
||
# Define character sets
|
||
lowercase = string.ascii_lowercase
|
||
uppercase = string.ascii_uppercase
|
||
digits = string.digits
|
||
special_chars = "*@!"
|
||
|
||
# Ensure at least one character from each category
|
||
password_chars = [
|
||
secrets.choice(lowercase),
|
||
secrets.choice(uppercase),
|
||
secrets.choice(digits),
|
||
secrets.choice(special_chars)
|
||
]
|
||
|
||
# Fill the rest randomly
|
||
all_chars = lowercase + uppercase + digits + special_chars
|
||
for _ in range(length - 4):
|
||
password_chars.append(secrets.choice(all_chars))
|
||
|
||
# Shuffle the password
|
||
secrets.SystemRandom().shuffle(password_chars)
|
||
return ''.join(password_chars)
|
||
|
||
def get_user_input(prompt: str, default: Optional[str] = None) -> str:
|
||
"""Get user input with optional default value"""
|
||
if default:
|
||
full_prompt = f"{Colors.YELLOW}{prompt} (default: {default}): {Colors.END}"
|
||
else:
|
||
full_prompt = f"{Colors.YELLOW}{prompt}: {Colors.END}"
|
||
|
||
user_input = input(full_prompt).strip()
|
||
return user_input if user_input else (default or "")
|
||
|
||
def print_success(message: str):
|
||
"""Print success message in green"""
|
||
print(f"{Colors.GREEN}✓ {message}{Colors.END}")
|
||
|
||
def print_error(message: str):
|
||
"""Print error message in red"""
|
||
print(f"{Colors.RED}✗ {message}{Colors.END}")
|
||
|
||
def print_info(message: str):
|
||
"""Print info message in blue"""
|
||
print(f"{Colors.BLUE}ℹ {message}{Colors.END}")
|
||
|
||
def create_env_files(hostname: str, port: str, db_name: str, password: str):
|
||
"""Create .env and env.properties files"""
|
||
# Create backend resources directory if it doesn't exist
|
||
resources_dir = Path("backend/src/main/resources")
|
||
resources_dir.mkdir(parents=True, exist_ok=True)
|
||
|
||
# Prepare the environment variables content
|
||
env_content = f"""DB_URL=jdbc:postgresql://{hostname}:{port}/{db_name}
|
||
DB_USER=wesaladmin
|
||
DB_PASSWORD={password}
|
||
DB_DB={db_name}"""
|
||
|
||
# Write .env file in TOP LEVEL (root directory)
|
||
env_file_path = Path(".env")
|
||
with open(env_file_path, 'w') as f:
|
||
f.write(env_content)
|
||
print_success(f"Created {env_file_path} (top level)")
|
||
|
||
# Write env.properties file in resources directory
|
||
env_properties_path = resources_dir / "env.properties"
|
||
with open(env_properties_path, 'w') as f:
|
||
f.write(env_content)
|
||
print_success(f"Created {env_properties_path}")
|
||
|
||
def setup_database_config():
|
||
"""Setup database configuration"""
|
||
print(f"\n{Colors.BOLD}📊 Database Configuration{Colors.END}")
|
||
print("Setting up PostgreSQL connection parameters...")
|
||
|
||
hostname = get_user_input("Database hostname", "db")
|
||
port = get_user_input("Database port", "5432")
|
||
db_name = get_user_input("Database name", "prod")
|
||
|
||
# Ask if user wants to generate password or provide their own
|
||
generate_pass = get_user_input("Generate complex password automatically? (y/n)", "y").lower()
|
||
|
||
if generate_pass in ['y', 'yes', '']:
|
||
password = generate_complex_password()
|
||
print_info(f"Generated password: {password}")
|
||
else:
|
||
password = get_user_input("Enter database password")
|
||
if not password:
|
||
print_error("Password cannot be empty. Generating one automatically...")
|
||
password = generate_complex_password()
|
||
print_info(f"Generated password: {password}")
|
||
|
||
create_env_files(hostname, port, db_name, password)
|
||
return password
|
||
|
||
def setup_firebase_credentials():
|
||
"""Setup Firebase service account credentials"""
|
||
print(f"\n{Colors.BOLD}🔥 Firebase Configuration{Colors.END}")
|
||
|
||
# Ask if user needs guidance
|
||
need_help = get_user_input("Do you need help finding the Firebase Service Account JSON file? (y/n)", "n").lower()
|
||
|
||
if need_help in ['y', 'yes']:
|
||
print(f"\n{Colors.BLUE}📋 Steps to get Firebase Service Account JSON:{Colors.END}")
|
||
print("1. Go to https://console.firebase.google.com/")
|
||
print("2. Select your project")
|
||
print("3. Click on the gear icon (Project Settings)")
|
||
print("4. Go to the 'Service accounts' tab")
|
||
print("5. Click 'Generate new private key'")
|
||
print("6. Download the JSON file")
|
||
print("7. Save it in the current directory and name it 'firebase-service-account.json'")
|
||
print()
|
||
|
||
print_info("Please place your Firebase Service Account JSON file in the current directory")
|
||
print_info("Name the file: 'firebase-service-account.json'")
|
||
|
||
while True:
|
||
input(f"{Colors.YELLOW}Press Enter when the file is ready...{Colors.END}")
|
||
|
||
firebase_file = Path("firebase-service-account.json")
|
||
if firebase_file.exists():
|
||
print_success("Firebase service account file found!")
|
||
break
|
||
else:
|
||
print_error("File 'firebase-service-account.json' not found in current directory.")
|
||
retry = get_user_input("Try again? (y/n)", "y").lower()
|
||
if retry not in ['y', 'yes', '']:
|
||
print_error("Skipping Firebase setup...")
|
||
return False
|
||
|
||
# Copy to backend resources
|
||
backend_resources = Path("backend/src/main/resources")
|
||
backend_resources.mkdir(parents=True, exist_ok=True)
|
||
backend_firebase_path = backend_resources / "firebase-service-account.json"
|
||
|
||
shutil.copy2(firebase_file, backend_firebase_path)
|
||
print_success(f"Copied Firebase credentials to {backend_firebase_path}")
|
||
|
||
# Copy to frontend directory (the specified path)
|
||
frontend_firebase_path = Path("/Users/bubshait/Desktop/My life/2025/SWA/wesal_app/frontend/firebase-service-account.json")
|
||
|
||
try:
|
||
# Create parent directories if they don't exist
|
||
frontend_firebase_path.parent.mkdir(parents=True, exist_ok=True)
|
||
shutil.copy2(firebase_file, frontend_firebase_path)
|
||
print_success(f"Copied Firebase credentials to {frontend_firebase_path}")
|
||
except Exception as e:
|
||
print_error(f"Could not copy to frontend directory: {e}")
|
||
print_info("You may need to manually copy the file to the frontend directory")
|
||
|
||
return True
|
||
|
||
|
||
|
||
def print_summary():
|
||
"""Print installation summary"""
|
||
print(f"\n{Colors.BOLD}{Colors.GREEN}🎉 Installation Complete!{Colors.END}")
|
||
print(f"\n{Colors.BOLD}Files created:{Colors.END}")
|
||
print("• .env (top level)")
|
||
print("• backend/src/main/resources/env.properties")
|
||
print("• backend/src/main/resources/firebase-service-account.json")
|
||
print(f"\n{Colors.BOLD}Next steps:{Colors.END}")
|
||
print("1. Run: docker-compose up --build")
|
||
print("2. Access your app at: http://localhost:6060")
|
||
print("3. Access Adminer (DB admin) at: http://localhost:8100")
|
||
print("4. API will be available at: http://localhost:4044")
|
||
print(f"\n{Colors.BLUE}Happy coding! 🚀{Colors.END}")
|
||
|
||
def main():
|
||
"""Main installation function"""
|
||
try:
|
||
# Print logo
|
||
print_ascii_logo()
|
||
|
||
print("Welcome to the Wesal Social Media App installer!")
|
||
print("This script will help you set up all necessary configuration files.\n")
|
||
|
||
# Setup database
|
||
db_password = setup_database_config()
|
||
|
||
# Setup Firebase
|
||
firebase_success = setup_firebase_credentials()
|
||
|
||
# Print summary
|
||
print_summary()
|
||
|
||
if not firebase_success:
|
||
print(f"\n{Colors.YELLOW}⚠️ Note: Firebase setup was skipped. You'll need to set it up manually later.{Colors.END}")
|
||
|
||
except KeyboardInterrupt:
|
||
print(f"\n{Colors.RED}Installation cancelled by user.{Colors.END}")
|
||
sys.exit(1)
|
||
except Exception as e:
|
||
print_error(f"An error occurred: {e}")
|
||
sys.exit(1)
|
||
|
||
if __name__ == "__main__":
|
||
main() |