feat: add installation script

This commit is contained in:
sBubshait 2025-08-07 04:25:45 +03:00
parent 3b50c997fa
commit 02323106de

236
install.sh Normal file
View File

@ -0,0 +1,236 @@
#!/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()