+ Приведены все функции приложения в рабочий вид

+ Наведен порядок в файлах проекта
+ Наведен порядок в документации
+ Настроены скрипты установки, развертки и так далее, расширен MakeFile
This commit is contained in:
2025-11-02 06:09:55 +09:00
parent 367e1c932e
commit 2e535513b5
6103 changed files with 7040 additions and 1027861 deletions

605
setup.sh Executable file → Normal file
View File

@@ -1,128 +1,521 @@
#!/usr/bin/env bash
set -e
#!/bin/bash
# Запустите этот скрипт из корня вашего репозитория (~/links)
# CatLink Setup Script
# ====================
# Автоматическая настройка среды разработки
# Переменные
BACKEND_DIR="backend"
FRONTEND_DIR="frontend"
APPS=("users" "links" "customization")
set -e # Остановить при ошибке
# 1. Создаем .gitignore и README
cat > .gitignore << 'EOF'
__pycache__/
*.pyc
.env
media/
node_modules/
dist/
.venv/
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Функции для цветного вывода
print_header() {
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}$1${NC}"
echo -e "${BLUE}========================================${NC}"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
# Проверка зависимостей
check_dependencies() {
print_header "Проверка зависимостей"
# Проверка Docker
if ! command -v docker &> /dev/null; then
print_error "Docker не установлен"
print_info "Установите Docker: https://docs.docker.com/get-docker/"
exit 1
fi
print_success "Docker найден: $(docker --version)"
# Проверка Docker Compose
if ! command -v docker-compose &> /dev/null; then
print_error "Docker Compose не установлен"
print_info "Установите Docker Compose: https://docs.docker.com/compose/install/"
exit 1
fi
print_success "Docker Compose найден: $(docker-compose --version)"
# Проверка Git
if ! command -v git &> /dev/null; then
print_warning "Git не установлен (рекомендуется для обновлений)"
else
print_success "Git найден: $(git --version)"
fi
# Проверка Make
if ! command -v make &> /dev/null; then
print_warning "Make не установлен (рекомендуется для удобства)"
print_info "Установите: sudo apt-get install make"
else
print_success "Make найден: $(make --version | head -1)"
fi
}
# Создание .env файла
create_env_file() {
print_header "Создание конфигурации (.env)"
if [ -f .env ]; then
print_info ".env файл уже существует"
read -p "Пересоздать? (y/N): " recreate
if [[ ! $recreate =~ ^[Yy]$ ]]; then
print_info "Пропуск создания .env"
return
fi
fi
# Генерация SECRET_KEY
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_urlsafe(50))" 2>/dev/null || openssl rand -base64 32)
# Запрос данных от пользователя
echo ""
read -p "Имя базы данных [links_db]: " DB_NAME
DB_NAME=${DB_NAME:-links_db}
read -p "Пользователь БД [links_user]: " DB_USER
DB_USER=${DB_USER:-links_user}
read -p "Пароль БД [links_password]: " DB_PASSWORD
DB_PASSWORD=${DB_PASSWORD:-links_password}
read -p "Хост БД [db]: " DB_HOST
DB_HOST=${DB_HOST:-db}
read -p "Порт БД [5432]: " DB_PORT
DB_PORT=${DB_PORT:-5432}
read -p "Домен для продакшена [localhost]: " DOMAIN
DOMAIN=${DOMAIN:-localhost}
read -p "Email для SSL сертификатов: " SSL_EMAIL
# Создание .env файла
cat > .env << EOF
# Django Configuration
SECRET_KEY=$SECRET_KEY
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1,$DOMAIN
# Database Configuration
DATABASE_URL=postgresql://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$DB_NAME
DB_NAME=$DB_NAME
DB_USER=$DB_USER
DB_PASSWORD=$DB_PASSWORD
DB_HOST=$DB_HOST
DB_PORT=$DB_PORT
# Production Settings
DOMAIN=$DOMAIN
SSL_EMAIL=$SSL_EMAIL
# CORS Settings
CORS_ALLOWED_ORIGINS=http://localhost:3000,https://$DOMAIN
# File Upload Settings
MAX_UPLOAD_SIZE=10485760
MEDIA_ROOT=/app/storage
# Cache Settings
CACHE_TTL=300
# Email Settings (optional)
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
EMAIL_HOST=
EMAIL_PORT=587
EMAIL_USE_TLS=True
EMAIL_HOST_USER=
EMAIL_HOST_PASSWORD=
# Redis Settings (optional)
REDIS_URL=redis://redis:6379/0
# Logging
LOG_LEVEL=INFO
EOF
print_success ".env файл создан"
}
if [ ! -f README.md ]; then
echo "# Клон Linktr.ee на Django" > README.md
fi
echo "Настраиваем backend-проект"
# 2. Создаем backend-проект
mkdir -p $BACKEND_DIR && cd $BACKEND_DIR
# Виртуальное окружение
python3 -m venv .venv
source .venv/bin/activate
# Устанавливаем зависимости
pip install Django psycopg2-binary djangorestframework pillow django-tailwind whitenoise gunicorn
# Инициализируем Django-проект (если не создан)
if [ ! -f config/manage.py ]; then
django-admin startproject config .
fi
# Создаем приложения, если их нет
for app in "${APPS[@]}"; do
if [ ! -d "$app" ]; then
python manage.py startapp $app
fi
done
# Генерируем requirements.txt
pip freeze > requirements.txt
deactivate
cd ..
# 3. Dockerfile для backend
cat > $BACKEND_DIR/Dockerfile << 'EOF'
FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
EOF
echo "Создаем docker-compose.yml"
# 4. docker-compose.yml в корне
cat > docker-compose.yml << 'EOF'
# Создание продакшен конфигурации
create_production_config() {
print_header "Создание продакшен конфигурации"
if [ ! -f docker-compose.prod.yml ]; then
cat > docker-compose.prod.yml << 'EOF'
version: '3.8'
services:
web:
build: ./backend
environment:
- DEBUG=False
- DJANGO_SETTINGS_MODULE=backend.settings
volumes:
- ./backend:/app
- media_volume:/app/media
env_file:
- .env
ports:
- "8000:8000"
depends_on:
- db
- ./storage:/app/storage
- ./logs:/app/logs
restart: unless-stopped
frontend:
environment:
- NODE_ENV=production
- NEXT_TELEMETRY_DISABLED=1
restart: unless-stopped
db:
image: postgres:14
restart: unless-stopped
volumes:
- postgres_data:/var/lib/postgresql/data/
env_file:
- .env
- postgres_data:/var/lib/postgresql/data
- ./backups:/backups
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
- ./storage:/var/www/storage:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
- web
- frontend
restart: unless-stopped
volumes:
postgres_data:
media_volume:
EOF
print_success "docker-compose.prod.yml создан"
else
print_info "docker-compose.prod.yml уже существует"
fi
}
echo "Настраиваем frontend-проект"
# 5. Frontend: инициализация
mkdir -p $FRONTEND_DIR && cd $FRONTEND_DIR
# Создание nginx конфигурации
create_nginx_config() {
print_header "Создание конфигурации Nginx"
if [ ! -f nginx.conf ]; then
cat > nginx.conf << 'EOF'
events {
worker_connections 1024;
}
if [ ! -f package.json ]; then
npm init -y
npm install axios react react-dom
fi
mkdir -p public src/components src/pages src/services src/styles
# public/index.html
cat > public/index.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Linktr Clone</title>
</head>
<body>
<div id="root"></div>
<script src="../src/index.js"></script>
</body>
</html>
http {
upstream backend {
server web:8000;
}
upstream frontend {
server frontend:3000;
}
# Redirect HTTP to HTTPS
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
# HTTPS Server
server {
listen 443 ssl http2;
server_name _;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Frontend
location / {
proxy_pass http://frontend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Backend API
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Admin
location /admin/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Static files
location /storage/ {
alias /var/www/storage/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
}
}
EOF
print_success "nginx.conf создан"
else
print_info "nginx.conf уже существует"
fi
}
# src/index.js
cat > src/index.js << 'EOF'
import React from 'react';
import ReactDOM from 'react-dom';
# Создание директорий
create_directories() {
print_header "Создание необходимых директорий"
directories=(
"storage"
"storage/avatars"
"storage/images"
"storage/images/links"
"storage/images/link_groups"
"storage/customization"
"backups"
"logs"
"ssl"
)
for dir in "${directories[@]}"; do
if [ ! -d "$dir" ]; then
mkdir -p "$dir"
print_success "Создана директория: $dir"
else
print_info "Директория уже существует: $dir"
fi
done
# Установка прав доступа
chmod 755 storage
chmod -R 755 storage/
print_success "Права доступа установлены"
}
# Сборка и запуск контейнеров
build_and_start() {
print_header "Сборка и запуск контейнеров"
print_info "Остановка существующих контейнеров..."
docker-compose down 2>/dev/null || true
print_info "Сборка контейнеров..."
docker-compose build --no-cache
print_info "Запуск контейнеров..."
docker-compose up -d
print_info "Ожидание запуска сервисов..."
sleep 10
print_success "Контейнеры запущены"
}
# Инициализация базы данных
initialize_database() {
print_header "Инициализация базы данных"
print_info "Ожидание готовности базы данных..."
sleep 5
print_info "Выполнение миграций..."
docker-compose exec -T web python manage.py migrate
print_info "Сбор статических файлов..."
docker-compose exec -T web python manage.py collectstatic --noinput
print_success "База данных инициализирована"
}
# Создание суперпользователя
create_superuser() {
print_header "Создание суперпользователя"
echo ""
read -p "Создать суперпользователя? (Y/n): " create_user
if [[ ! $create_user =~ ^[Nn]$ ]]; then
print_info "Создание суперпользователя..."
docker-compose exec web python manage.py createsuperuser
print_success "Суперпользователь создан"
else
print_info "Пропуск создания суперпользователя"
print_info "Вы можете создать его позже командой: make superuser"
fi
}
# Проверка здоровья системы
health_check() {
print_header "Проверка здоровья системы"
print_info "Проверка frontend..."
if curl -s http://localhost:3000 > /dev/null; then
print_success "Frontend доступен: http://localhost:3000"
else
print_error "Frontend недоступен"
fi
print_info "Проверка backend..."
if curl -s http://localhost:8000 > /dev/null; then
print_success "Backend доступен: http://localhost:8000"
else
print_error "Backend недоступен"
fi
print_info "Проверка базы данных..."
if docker-compose exec -T db pg_isready -U links_user > /dev/null 2>&1; then
print_success "База данных готова"
else
print_error "База данных недоступна"
fi
}
# Создание документации
create_documentation() {
print_header "Создание документации"
if [ ! -f DEPLOYMENT.md ]; then
cat > DEPLOYMENT.md << 'EOF'
# CatLink Deployment Guide
## Быстрый старт
```bash
# Первый запуск
make install
# Режим разработки
make dev
# Продакшен
make deploy
```
## Полезные команды
```bash
# Статус сервисов
make status
# Логи
make logs
# Перезапуск
make restart
# Создание суперпользователя
make superuser
# Бэкап базы данных
make backup
# SSL настройка
make ssl
```
## Структура проекта
- `frontend/` - Next.js приложение
- `backend/` - Django API
- `storage/` - Загруженные файлы
- `backups/` - Бэкапы базы данных
- `logs/` - Логи приложения
## Продакшен
1. Настройте домен в `.env`
2. Запустите `make ssl` для настройки HTTPS
3. Используйте `make deploy` для развертывания
ReactDOM.render(<h1>Linktr Clone</h1>, document.getElementById('root'));
EOF
print_success "DEPLOYMENT.md создан"
else
print_info "DEPLOYMENT.md уже существует"
fi
}
cd ..
# Финальный вывод
print_final_info() {
print_header "Установка завершена!"
echo ""
echo -e "${GREEN}🎉 CatLink успешно установлен!${NC}"
echo ""
echo -e "${BLUE}📱 Frontend:${NC} http://localhost:3000"
echo -e "${BLUE}🔧 Backend API:${NC} http://localhost:8000/api/"
echo -e "${BLUE}📊 Admin панель:${NC} http://localhost:8000/admin/"
echo ""
echo -e "${YELLOW}📚 Полезные команды:${NC}"
echo " make help - Все доступные команды"
echo " make status - Статус сервисов"
echo " make logs - Просмотр логов"
echo " make restart - Перезапуск"
echo " make superuser - Создать суперпользователя"
echo " make backup - Создать бэкап"
echo ""
echo -e "${BLUE}📖 Документация:${NC} DEPLOYMENT.md"
echo ""
}
echo "Проект настроен успешно!"
# Основная функция
main() {
print_header "CatLink Setup Script v2.0"
# Проверка, что мы в правильной директории
if [ ! -f "docker-compose.yml" ]; then
print_error "docker-compose.yml не найден. Убедитесь, что вы в корневой директории проекта."
exit 1
fi
check_dependencies
create_env_file
create_production_config
create_nginx_config
create_directories
build_and_start
initialize_database
create_superuser
health_check
create_documentation
print_final_info
}
# Обработка ошибок
trap 'print_error "Произошла ошибка. Установка прервана."' ERR
# Запуск основной функции
main "$@"