mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
2 files changed
+258
-2
No files matched your search
+25
-2
@@ -3,11 +3,23 @@ FROM node:20-alpine AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Installer les outils de compilation pour bcrypt et canvas
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
make \
|
||||
g++ \
|
||||
cairo-dev \
|
||||
jpeg-dev \
|
||||
pango-dev \
|
||||
giflib-dev \
|
||||
pixman-dev
|
||||
|
||||
# Copier les fichiers de dépendances
|
||||
COPY package*.json ./
|
||||
|
||||
# Installer toutes les dépendances (dev + prod)
|
||||
RUN npm ci
|
||||
# Utiliser --legacy-peer-deps si problèmes de dépendances
|
||||
RUN npm ci --legacy-peer-deps || npm install --legacy-peer-deps
|
||||
|
||||
# Copier le reste du code source
|
||||
COPY . .
|
||||
@@ -20,9 +32,20 @@ FROM node:20-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Installer les runtime dependencies pour bcrypt et canvas
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
make \
|
||||
g++ \
|
||||
cairo \
|
||||
jpeg \
|
||||
pango \
|
||||
giflib \
|
||||
pixman
|
||||
|
||||
# Installer toutes les dépendances (drizzle-kit est nécessaire pour push)
|
||||
COPY package*.json ./
|
||||
RUN npm ci
|
||||
RUN npm ci --legacy-peer-deps --omit=dev || npm install --legacy-peer-deps --omit=dev
|
||||
|
||||
# Copier les fichiers buildés et le code serveur
|
||||
COPY --from=builder /app/dist ./dist
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
-- ============================================================
|
||||
-- MIGRATION SQL POUR SERVEUR DOCKER EXISTANT
|
||||
-- Script de mise à jour pour Social Flow
|
||||
-- ============================================================
|
||||
-- Ce fichier contient toutes les commandes SQL pour mettre à jour
|
||||
-- une base de données existante vers la dernière version du schéma
|
||||
-- ============================================================
|
||||
|
||||
-- ÉTAPE 1: Créer les ENUMs s'ils n'existent pas déjà
|
||||
-- ============================================================
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE platform AS ENUM ('facebook', 'instagram');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE post_type AS ENUM ('feed', 'story', 'both');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE post_status AS ENUM ('draft', 'scheduled', 'published', 'failed');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE media_type AS ENUM ('image', 'video');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE user_role AS ENUM ('admin', 'user');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
-- IMPORTANT: Ajouter 'both' à post_type si serveur existant
|
||||
-- Cette valeur a été ajoutée récemment
|
||||
DO $$ BEGIN
|
||||
ALTER TYPE post_type ADD VALUE IF NOT EXISTS 'both';
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
WHEN others THEN null;
|
||||
END $$;
|
||||
|
||||
-- ÉTAPE 2: Créer les tables principales
|
||||
-- ============================================================
|
||||
|
||||
-- Table users
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL,
|
||||
role user_role NOT NULL DEFAULT 'user'
|
||||
);
|
||||
|
||||
-- Table social_pages
|
||||
CREATE TABLE IF NOT EXISTS social_pages (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
platform platform NOT NULL,
|
||||
page_id TEXT NOT NULL,
|
||||
page_name TEXT NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
followers_count INTEGER DEFAULT 0,
|
||||
is_active TEXT NOT NULL DEFAULT 'true',
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table cloudinary_config
|
||||
CREATE TABLE IF NOT EXISTS cloudinary_config (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
|
||||
cloud_name TEXT NOT NULL,
|
||||
api_key TEXT NOT NULL,
|
||||
api_secret TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table openrouter_config
|
||||
CREATE TABLE IF NOT EXISTS openrouter_config (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
|
||||
api_key TEXT NOT NULL,
|
||||
model TEXT NOT NULL DEFAULT 'anthropic/claude-3.5-sonnet',
|
||||
system_prompt TEXT NOT NULL DEFAULT 'Tu es un expert en marketing des réseaux sociaux. Génère 3 variations de textes engageants pour des publications Facebook et Instagram à partir des informations produit fournies. Chaque variation doit être unique, captivante et optimisée pour l''engagement.',
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table media
|
||||
CREATE TABLE IF NOT EXISTS media (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
type media_type NOT NULL,
|
||||
cloudinary_public_id TEXT,
|
||||
original_url TEXT NOT NULL,
|
||||
facebook_landscape_url TEXT,
|
||||
facebook_feed_url TEXT,
|
||||
instagram_feed_url TEXT,
|
||||
instagram_story_url TEXT,
|
||||
file_name TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table posts
|
||||
CREATE TABLE IF NOT EXISTS posts (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
content TEXT NOT NULL,
|
||||
ai_generated TEXT NOT NULL DEFAULT 'false',
|
||||
product_info JSONB,
|
||||
status post_status NOT NULL DEFAULT 'draft',
|
||||
scheduled_for TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table post_media
|
||||
CREATE TABLE IF NOT EXISTS post_media (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
post_id VARCHAR NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
||||
media_id VARCHAR NOT NULL REFERENCES media(id) ON DELETE CASCADE,
|
||||
display_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
-- Table scheduled_posts
|
||||
CREATE TABLE IF NOT EXISTS scheduled_posts (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
post_id VARCHAR NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
|
||||
page_id VARCHAR NOT NULL REFERENCES social_pages(id) ON DELETE CASCADE,
|
||||
post_type post_type NOT NULL,
|
||||
scheduled_at TIMESTAMP NOT NULL,
|
||||
published_at TIMESTAMP,
|
||||
external_post_id TEXT,
|
||||
error TEXT
|
||||
);
|
||||
|
||||
-- Table ai_generations
|
||||
CREATE TABLE IF NOT EXISTS ai_generations (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
product_info JSONB NOT NULL,
|
||||
generated_texts JSONB NOT NULL,
|
||||
selected_text TEXT,
|
||||
created_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Table user_page_permissions
|
||||
CREATE TABLE IF NOT EXISTS user_page_permissions (
|
||||
id VARCHAR PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id VARCHAR NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
page_id VARCHAR NOT NULL REFERENCES social_pages(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
UNIQUE(user_id, page_id)
|
||||
);
|
||||
|
||||
-- ÉTAPE 3: Créer les index pour optimiser les performances
|
||||
-- ============================================================
|
||||
|
||||
-- Index pour user_page_permissions
|
||||
CREATE INDEX IF NOT EXISTS idx_user_page_permissions_user_id ON user_page_permissions(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_user_page_permissions_page_id ON user_page_permissions(page_id);
|
||||
|
||||
-- Index pour scheduled_posts
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_posts_scheduled_at ON scheduled_posts(scheduled_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_posts_post_id ON scheduled_posts(post_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_scheduled_posts_page_id ON scheduled_posts(page_id);
|
||||
|
||||
-- Index pour posts
|
||||
CREATE INDEX IF NOT EXISTS idx_posts_user_id ON posts(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_posts_status ON posts(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_posts_scheduled_for ON posts(scheduled_for);
|
||||
|
||||
-- Index pour media
|
||||
CREATE INDEX IF NOT EXISTS idx_media_user_id ON media(user_id);
|
||||
|
||||
-- ÉTAPE 4: Créer les utilisateurs par défaut
|
||||
-- ============================================================
|
||||
|
||||
-- Créer l'utilisateur admin (username: admin, password: admin)
|
||||
INSERT INTO users (id, username, password, role)
|
||||
VALUES (
|
||||
'admin-user-id',
|
||||
'admin',
|
||||
'$2b$10$mw7B1qBoTxxT7BT.Mv9uTeExX27y5nPVN4/e6L7W1VqkTNe/tGw9G',
|
||||
'admin'
|
||||
) ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
-- Créer un utilisateur demo (username: demo, password: admin)
|
||||
INSERT INTO users (id, username, password, role)
|
||||
VALUES (
|
||||
'demo-user',
|
||||
'demo',
|
||||
'$2b$10$mw7B1qBoTxxT7BT.Mv9uTeExX27y5nPVN4/e6L7W1VqkTNe/tGw9G',
|
||||
'user'
|
||||
) ON CONFLICT (username) DO NOTHING;
|
||||
|
||||
-- ÉTAPE 5: Mise à jour des posts programmés existants (si migration)
|
||||
-- ============================================================
|
||||
-- Mettre à jour le statut des posts programmés qui étaient en "draft"
|
||||
UPDATE posts
|
||||
SET status = 'scheduled'
|
||||
WHERE scheduled_for IS NOT NULL
|
||||
AND status = 'draft';
|
||||
|
||||
-- ============================================================
|
||||
-- FIN DE LA MIGRATION
|
||||
-- ============================================================
|
||||
--
|
||||
-- INSTRUCTIONS D'UTILISATION:
|
||||
--
|
||||
-- 1. Pour un NOUVEAU serveur Docker:
|
||||
-- - Rien à faire ! Le docker-compose.yml exécute automatiquement
|
||||
-- "drizzle-kit push --force" qui crée toutes les tables
|
||||
--
|
||||
-- 2. Pour un serveur Docker EXISTANT avec données:
|
||||
-- - Connectez-vous à PostgreSQL:
|
||||
-- docker exec -it socialflow-db psql -U socialflow -d socialflow
|
||||
-- - Exécutez ce fichier:
|
||||
-- \i /chemin/vers/migration-docker.sql
|
||||
--
|
||||
-- 3. Alternative avec commande directe:
|
||||
-- docker exec -i socialflow-db psql -U socialflow -d socialflow < migration-docker.sql
|
||||
--
|
||||
-- ============================================================
|
||||
Reference in new issue
Block a user