📋 Commit iniziale con: - ✅ Documentazione unificata in docs/ - ✅ Codice Laravel in netgescon-laravel/ - ✅ Script automazione in scripts/ - ✅ Configurazione sync rsync - ✅ Struttura organizzata e pulita 🔄 Versione: 2025.07.19-1644 🎯 Sistema pronto per Git distribuito
1046 lines
33 KiB
Markdown
1046 lines
33 KiB
Markdown
# 📁 GESTIONE CARTELLE AMMINISTRATORE E PORTABILITÀ SISTEMA
|
|
|
|
## 🎯 OVERVIEW
|
|
Sistema di gestione cartelle amministratore con archiviazione completa in SQL e portabilità totale del sistema tra macchine diverse, incluso deployment Docker e aggiornamento remoto.
|
|
|
|
---
|
|
|
|
## 📂 STRUTTURA CARTELLE AMMINISTRATORE
|
|
|
|
### 🗂️ Organizzazione Filesystem
|
|
```
|
|
netgescon-data/
|
|
├── administrators/
|
|
│ ├── AB123CD8/ # Codice 8 caratteri alfanumerico
|
|
│ │ ├── profile/
|
|
│ │ │ ├── avatar.jpg
|
|
│ │ │ ├── signature.png
|
|
│ │ │ └── documents/
|
|
│ │ ├── condomini/
|
|
│ │ │ ├── COND001/
|
|
│ │ │ ├── COND002/
|
|
│ │ │ └── shared/
|
|
│ │ ├── backup/
|
|
│ │ │ ├── daily/
|
|
│ │ │ ├── weekly/
|
|
│ │ │ └── manual/
|
|
│ │ ├── temp/
|
|
│ │ ├── reports/
|
|
│ │ └── cache/
|
|
│ ├── EF456GH9/ # Altro amministratore
|
|
│ └── shared/ # Risorse condivise
|
|
├── system/
|
|
│ ├── backups/
|
|
│ ├── logs/
|
|
│ ├── uploads/
|
|
│ └── cache/
|
|
└── docker/ # Solo per installazione Docker
|
|
├── mysql/
|
|
├── redis/
|
|
└── nginx/
|
|
```
|
|
|
|
### 🔐 Sistema Autenticazione e Cartelle
|
|
```sql
|
|
-- Tabella gestione amministratori con cartelle
|
|
CREATE TABLE administrators_folders (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
user_id INT NOT NULL,
|
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
folder_code VARCHAR(8) NOT NULL UNIQUE COMMENT 'Codice 8 caratteri alfanumerico',
|
|
folder_path VARCHAR(500) NOT NULL,
|
|
disk_quota_mb INT DEFAULT 1024 COMMENT 'Quota disco in MB',
|
|
used_space_mb INT DEFAULT 0,
|
|
permissions JSON COMMENT 'Permessi specifici cartella',
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
last_access TIMESTAMP NULL,
|
|
|
|
CONSTRAINT fk_admin_folders_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
INDEX idx_email (email),
|
|
INDEX idx_folder_code (folder_code),
|
|
INDEX idx_last_access (last_access)
|
|
) COMMENT = 'Gestione cartelle amministratori con codici 8 caratteri';
|
|
|
|
-- Tabella file management per ogni amministratore
|
|
CREATE TABLE administrator_files (
|
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
|
administrator_id INT NOT NULL,
|
|
folder_code VARCHAR(8) NOT NULL,
|
|
file_path VARCHAR(1000) NOT NULL,
|
|
file_name VARCHAR(255) NOT NULL,
|
|
file_size_bytes BIGINT NOT NULL,
|
|
file_type VARCHAR(50) NOT NULL,
|
|
mime_type VARCHAR(100),
|
|
file_hash VARCHAR(64) COMMENT 'SHA256 per verifica integrità',
|
|
metadata JSON COMMENT 'Metadati file (dimensioni immagini, durata video, etc)',
|
|
is_archived BOOLEAN DEFAULT FALSE,
|
|
archived_at TIMESTAMP NULL,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
|
|
CONSTRAINT fk_admin_files_admin FOREIGN KEY (administrator_id) REFERENCES administrators_folders(id) ON DELETE CASCADE,
|
|
INDEX idx_folder_code (folder_code),
|
|
INDEX idx_file_type (file_type),
|
|
INDEX idx_file_hash (file_hash),
|
|
INDEX idx_archived (is_archived, archived_at)
|
|
) COMMENT = 'Archivio file per amministratore in SQL con hash integrità';
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 INSTALLAZIONI MULTIPLE
|
|
|
|
### 🐳 Installazione Docker (Plug & Play)
|
|
```yaml
|
|
# docker-compose.yml
|
|
version: '3.8'
|
|
|
|
services:
|
|
netgescon-app:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
container_name: netgescon-laravel
|
|
ports:
|
|
- "8080:80"
|
|
volumes:
|
|
- ./netgescon-data:/var/www/html/storage/netgescon-data
|
|
- ./logs:/var/www/html/storage/logs
|
|
environment:
|
|
- APP_ENV=production
|
|
- DB_HOST=netgescon-db
|
|
- REDIS_HOST=netgescon-redis
|
|
depends_on:
|
|
- netgescon-db
|
|
- netgescon-redis
|
|
restart: unless-stopped
|
|
|
|
netgescon-db:
|
|
image: mysql:8.0
|
|
container_name: netgescon-mysql
|
|
ports:
|
|
- "3306:3306"
|
|
volumes:
|
|
- ./docker/mysql:/var/lib/mysql
|
|
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: netgescon_root_2025
|
|
MYSQL_DATABASE: netgescon
|
|
MYSQL_USER: netgescon_user
|
|
MYSQL_PASSWORD: netgescon_pass_2025
|
|
restart: unless-stopped
|
|
|
|
netgescon-redis:
|
|
image: redis:7-alpine
|
|
container_name: netgescon-redis
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- ./docker/redis:/data
|
|
restart: unless-stopped
|
|
|
|
netgescon-nginx:
|
|
image: nginx:alpine
|
|
container_name: netgescon-nginx
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf
|
|
- ./docker/nginx/ssl:/etc/nginx/ssl
|
|
depends_on:
|
|
- netgescon-app
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
mysql_data:
|
|
redis_data:
|
|
```
|
|
|
|
#### Script di Avvio Docker
|
|
```bash
|
|
#!/bin/bash
|
|
# docker-start.sh - Avvio automatico NetGesCon Docker
|
|
|
|
echo "🚀 Avvio NetGesCon Docker Environment..."
|
|
|
|
# Verifica prerequisiti
|
|
if ! command -v docker &> /dev/null; then
|
|
echo "❌ Docker non installato!"
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v docker-compose &> /dev/null; then
|
|
echo "❌ Docker Compose non installato!"
|
|
exit 1
|
|
fi
|
|
|
|
# Crea struttura cartelle se non esistono
|
|
mkdir -p netgescon-data/{administrators,system/{backups,logs,uploads,cache},docker/{mysql,redis,nginx}}
|
|
|
|
# Imposta permessi corretti
|
|
chmod -R 755 netgescon-data
|
|
chown -R www-data:www-data netgescon-data
|
|
|
|
# Avvia i container
|
|
echo "📦 Avvio container Docker..."
|
|
docker-compose up -d
|
|
|
|
# Attendi che il database sia pronto
|
|
echo "⏳ Attendo che il database sia pronto..."
|
|
sleep 30
|
|
|
|
# Esegui migrazioni database
|
|
echo "🗄️ Esecuzione migrazioni database..."
|
|
docker exec netgescon-laravel php artisan migrate --force
|
|
|
|
# Seeder dati base
|
|
echo "🌱 Caricamento dati iniziali..."
|
|
docker exec netgescon-laravel php artisan db:seed --force
|
|
|
|
# Genera chiave applicazione se necessario
|
|
docker exec netgescon-laravel php artisan key:generate --force
|
|
|
|
# Cache optimization
|
|
echo "⚡ Ottimizzazione cache..."
|
|
docker exec netgescon-laravel php artisan config:cache
|
|
docker exec netgescon-laravel php artisan route:cache
|
|
docker exec netgescon-laravel php artisan view:cache
|
|
|
|
echo "✅ NetGesCon Docker avviato con successo!"
|
|
echo "🌐 Accesso: http://localhost:8080"
|
|
echo "📊 Database: localhost:3306"
|
|
echo "🔄 Redis: localhost:6379"
|
|
```
|
|
|
|
### 🖥️ Installazione Tradizionale (VM/Server Fisico)
|
|
|
|
#### Script di Installazione Linux
|
|
```bash
|
|
#!/bin/bash
|
|
# install-netgescon.sh - Installazione completa su server Linux
|
|
|
|
echo "🏢 Installazione NetGesCon su Server Linux"
|
|
|
|
# Verifica OS supportato
|
|
if [[ ! -f /etc/os-release ]]; then
|
|
echo "❌ Sistema operativo non supportato!"
|
|
exit 1
|
|
fi
|
|
|
|
source /etc/os-release
|
|
if [[ "$ID" != "ubuntu" ]] && [[ "$ID" != "debian" ]] && [[ "$ID" != "centos" ]] && [[ "$ID" != "rhel" ]]; then
|
|
echo "❌ OS supportati: Ubuntu, Debian, CentOS, RHEL"
|
|
exit 1
|
|
fi
|
|
|
|
# Aggiornamento sistema
|
|
echo "📦 Aggiornamento sistema..."
|
|
if [[ "$ID" == "ubuntu" ]] || [[ "$ID" == "debian" ]]; then
|
|
apt update && apt upgrade -y
|
|
apt install -y curl wget git unzip software-properties-common
|
|
elif [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]]; then
|
|
yum update -y
|
|
yum install -y curl wget git unzip epel-release
|
|
fi
|
|
|
|
# Installazione PHP 8.1+
|
|
echo "🐘 Installazione PHP 8.1..."
|
|
if [[ "$ID" == "ubuntu" ]] || [[ "$ID" == "debian" ]]; then
|
|
add-apt-repository ppa:ondrej/php -y
|
|
apt update
|
|
apt install -y php8.1 php8.1-fpm php8.1-mysql php8.1-redis php8.1-xml php8.1-mbstring \
|
|
php8.1-curl php8.1-zip php8.1-gd php8.1-intl php8.1-bcmath php8.1-soap
|
|
elif [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]]; then
|
|
yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
|
|
yum install -y https://rpms.remirepo.net/enterprise/remi-release-8.rpm
|
|
yum module enable php:remi-8.1 -y
|
|
yum install -y php php-fpm php-mysql php-redis php-xml php-mbstring \
|
|
php-curl php-zip php-gd php-intl php-bcmath php-soap
|
|
fi
|
|
|
|
# Installazione Composer
|
|
echo "🎼 Installazione Composer..."
|
|
curl -sS https://getcomposer.org/installer | php
|
|
mv composer.phar /usr/local/bin/composer
|
|
chmod +x /usr/local/bin/composer
|
|
|
|
# Installazione MySQL 8.0
|
|
echo "🗄️ Installazione MySQL 8.0..."
|
|
if [[ "$ID" == "ubuntu" ]] || [[ "$ID" == "debian" ]]; then
|
|
apt install -y mysql-server mysql-client
|
|
elif [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]]; then
|
|
yum install -y mysql-server mysql
|
|
fi
|
|
|
|
systemctl enable mysql
|
|
systemctl start mysql
|
|
|
|
# Configurazione MySQL sicura
|
|
mysql_secure_installation
|
|
|
|
# Installazione Redis
|
|
echo "🔄 Installazione Redis..."
|
|
if [[ "$ID" == "ubuntu" ]] || [[ "$ID" == "debian" ]]; then
|
|
apt install -y redis-server
|
|
elif [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]]; then
|
|
yum install -y redis
|
|
fi
|
|
|
|
systemctl enable redis
|
|
systemctl start redis
|
|
|
|
# Installazione Nginx
|
|
echo "🌐 Installazione Nginx..."
|
|
if [[ "$ID" == "ubuntu" ]] || [[ "$ID" == "debian" ]]; then
|
|
apt install -y nginx
|
|
elif [[ "$ID" == "centos" ]] || [[ "$ID" == "rhel" ]]; then
|
|
yum install -y nginx
|
|
fi
|
|
|
|
systemctl enable nginx
|
|
|
|
# Creazione utente netgescon
|
|
echo "👤 Creazione utente NetGesCon..."
|
|
useradd -r -s /bin/bash -d /opt/netgescon netgescon
|
|
mkdir -p /opt/netgescon
|
|
chown netgescon:netgescon /opt/netgescon
|
|
|
|
# Clonazione repository (se da repository Git)
|
|
echo "📥 Download NetGesCon..."
|
|
cd /opt/netgescon
|
|
# git clone https://github.com/your-repo/netgescon.git .
|
|
# Per ora assumiamo file locali
|
|
cp -r /tmp/netgescon-source/* .
|
|
chown -R netgescon:netgescon /opt/netgescon
|
|
|
|
# Installazione dipendenze
|
|
echo "📦 Installazione dipendenze PHP..."
|
|
sudo -u netgescon composer install --no-dev --optimize-autoloader
|
|
|
|
# Creazione struttura cartelle
|
|
echo "📁 Creazione struttura cartelle..."
|
|
mkdir -p /opt/netgescon/storage/netgescon-data/{administrators,system/{backups,logs,uploads,cache}}
|
|
chown -R netgescon:www-data /opt/netgescon/storage
|
|
chmod -R 775 /opt/netgescon/storage
|
|
|
|
# Configurazione .env
|
|
echo "⚙️ Configurazione environment..."
|
|
cp .env.example .env
|
|
php artisan key:generate
|
|
|
|
# Configurazione database
|
|
echo "🗄️ Configurazione database..."
|
|
mysql -u root -p <<EOF
|
|
CREATE DATABASE netgescon CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
CREATE USER 'netgescon'@'localhost' IDENTIFIED BY 'netgescon_secure_password_2025';
|
|
GRANT ALL PRIVILEGES ON netgescon.* TO 'netgescon'@'localhost';
|
|
FLUSH PRIVILEGES;
|
|
EOF
|
|
|
|
# Aggiorna .env con configurazione database
|
|
sed -i 's/DB_DATABASE=.*/DB_DATABASE=netgescon/' .env
|
|
sed -i 's/DB_USERNAME=.*/DB_USERNAME=netgescon/' .env
|
|
sed -i 's/DB_PASSWORD=.*/DB_PASSWORD=netgescon_secure_password_2025/' .env
|
|
|
|
# Migrazioni e seeder
|
|
echo "🗄️ Migrazioni database..."
|
|
php artisan migrate --force
|
|
php artisan db:seed --force
|
|
|
|
# Configurazione Nginx
|
|
echo "🌐 Configurazione Nginx..."
|
|
cat > /etc/nginx/sites-available/netgescon <<EOF
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
root /opt/netgescon/public;
|
|
index index.php index.html;
|
|
|
|
location / {
|
|
try_files \$uri \$uri/ /index.php?\$query_string;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
|
|
fastcgi_index index.php;
|
|
fastcgi_param SCRIPT_FILENAME \$realpath_root\$fastcgi_script_name;
|
|
include fastcgi_params;
|
|
}
|
|
|
|
location ~ /\.ht {
|
|
deny all;
|
|
}
|
|
}
|
|
EOF
|
|
|
|
ln -s /etc/nginx/sites-available/netgescon /etc/nginx/sites-enabled/
|
|
rm -f /etc/nginx/sites-enabled/default
|
|
nginx -t && systemctl restart nginx
|
|
|
|
# Configurazione PHP-FPM
|
|
sed -i 's/user = .*/user = netgescon/' /etc/php/8.1/fpm/pool.d/www.conf
|
|
sed -i 's/group = .*/group = www-data/' /etc/php/8.1/fpm/pool.d/www.conf
|
|
systemctl restart php8.1-fpm
|
|
|
|
# Cache ottimizzazione
|
|
echo "⚡ Ottimizzazione cache..."
|
|
php artisan config:cache
|
|
php artisan route:cache
|
|
php artisan view:cache
|
|
|
|
# Configurazione cron per task schedulati
|
|
echo "⏰ Configurazione cron jobs..."
|
|
(crontab -l 2>/dev/null; echo "* * * * * cd /opt/netgescon && php artisan schedule:run >> /dev/null 2>&1") | crontab -
|
|
|
|
echo "✅ Installazione NetGesCon completata!"
|
|
echo "🌐 Accesso: http://your-server-ip"
|
|
echo "📄 Log: /opt/netgescon/storage/logs/"
|
|
echo "💾 Dati: /opt/netgescon/storage/netgescon-data/"
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 SISTEMA AGGIORNAMENTO REMOTO
|
|
|
|
### 🌐 API Aggiornamento Remoto
|
|
```php
|
|
<?php
|
|
// app/Http/Controllers/System/RemoteUpdateController.php
|
|
|
|
namespace App\Http\Controllers\System;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Symfony\Component\Process\Process;
|
|
|
|
class RemoteUpdateController extends Controller
|
|
{
|
|
public function checkUpdates(Request $request)
|
|
{
|
|
try {
|
|
// Verifica autenticazione admin
|
|
if (!$this->isAuthorizedAdmin($request)) {
|
|
return response()->json(['error' => 'Unauthorized'], 403);
|
|
}
|
|
|
|
$currentVersion = config('app.version', '1.0.0');
|
|
$updateServer = config('app.update_server', 'https://updates.netgescon.org');
|
|
|
|
// Chiamata API server aggiornamenti
|
|
$response = Http::get("{$updateServer}/api/check-updates", [
|
|
'current_version' => $currentVersion,
|
|
'instance_id' => config('app.instance_id'),
|
|
'php_version' => PHP_VERSION,
|
|
'mysql_version' => DB::select('SELECT VERSION() as version')[0]->version,
|
|
]);
|
|
|
|
if ($response->successful()) {
|
|
$updateInfo = $response->json();
|
|
|
|
return response()->json([
|
|
'current_version' => $currentVersion,
|
|
'latest_version' => $updateInfo['latest_version'],
|
|
'has_updates' => version_compare($currentVersion, $updateInfo['latest_version'], '<'),
|
|
'updates_available' => $updateInfo['updates'] ?? [],
|
|
'critical_updates' => $updateInfo['critical'] ?? [],
|
|
'changelog' => $updateInfo['changelog'] ?? ''
|
|
]);
|
|
}
|
|
|
|
return response()->json(['error' => 'Unable to check updates'], 500);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('Remote update check failed: ' . $e->getMessage());
|
|
return response()->json(['error' => 'Update check failed'], 500);
|
|
}
|
|
}
|
|
|
|
public function downloadUpdate(Request $request)
|
|
{
|
|
try {
|
|
$this->validateUpdateRequest($request);
|
|
|
|
$version = $request->input('version');
|
|
$updateServer = config('app.update_server');
|
|
|
|
// Download del pacchetto aggiornamento
|
|
$downloadUrl = "{$updateServer}/api/download-update/{$version}";
|
|
$response = Http::withHeaders([
|
|
'Authorization' => 'Bearer ' . $this->getUpdateToken()
|
|
])->get($downloadUrl);
|
|
|
|
if ($response->successful()) {
|
|
$updatePath = storage_path('updates');
|
|
if (!file_exists($updatePath)) {
|
|
mkdir($updatePath, 0755, true);
|
|
}
|
|
|
|
$updateFile = "{$updatePath}/netgescon-{$version}.zip";
|
|
file_put_contents($updateFile, $response->body());
|
|
|
|
// Verifica integrità file
|
|
$downloadedHash = hash_file('sha256', $updateFile);
|
|
$expectedHash = $response->header('X-File-Hash');
|
|
|
|
if ($downloadedHash !== $expectedHash) {
|
|
unlink($updateFile);
|
|
return response()->json(['error' => 'File integrity check failed'], 500);
|
|
}
|
|
|
|
return response()->json([
|
|
'status' => 'downloaded',
|
|
'file_path' => $updateFile,
|
|
'file_size' => filesize($updateFile),
|
|
'file_hash' => $downloadedHash
|
|
]);
|
|
}
|
|
|
|
return response()->json(['error' => 'Download failed'], 500);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('Update download failed: ' . $e->getMessage());
|
|
return response()->json(['error' => 'Download failed'], 500);
|
|
}
|
|
}
|
|
|
|
public function applyUpdate(Request $request)
|
|
{
|
|
try {
|
|
$this->validateUpdateRequest($request);
|
|
|
|
$updateFile = $request->input('update_file');
|
|
$version = $request->input('version');
|
|
|
|
// Backup completo pre-aggiornamento
|
|
$backupPath = $this->createFullBackup();
|
|
|
|
// Modalità manutenzione
|
|
Artisan::call('down', ['--message' => 'System update in progress']);
|
|
|
|
// Estrazione aggiornamento
|
|
$extractPath = storage_path('updates/extract');
|
|
$zip = new \ZipArchive();
|
|
|
|
if ($zip->open($updateFile) === TRUE) {
|
|
$zip->extractTo($extractPath);
|
|
$zip->close();
|
|
|
|
// Applicazione aggiornamenti file
|
|
$this->applyFileUpdates($extractPath);
|
|
|
|
// Esecuzione migrazioni database
|
|
if (file_exists("{$extractPath}/database/migrations")) {
|
|
Artisan::call('migrate', ['--force' => true]);
|
|
}
|
|
|
|
// Aggiornamento versione
|
|
$this->updateVersionConfig($version);
|
|
|
|
// Clear cache
|
|
Artisan::call('config:clear');
|
|
Artisan::call('cache:clear');
|
|
Artisan::call('route:clear');
|
|
Artisan::call('view:clear');
|
|
|
|
// Riattiva sistema
|
|
Artisan::call('up');
|
|
|
|
// Cleanup file temporanei
|
|
$this->cleanupUpdateFiles($updateFile, $extractPath);
|
|
|
|
Log::info("System updated successfully to version {$version}");
|
|
|
|
return response()->json([
|
|
'status' => 'success',
|
|
'version' => $version,
|
|
'backup_path' => $backupPath,
|
|
'updated_at' => now()->toISOString()
|
|
]);
|
|
|
|
} else {
|
|
throw new \Exception('Unable to extract update file');
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
// Ripristina sistema in caso di errore
|
|
Artisan::call('up');
|
|
|
|
Log::error('Update failed: ' . $e->getMessage());
|
|
return response()->json([
|
|
'error' => 'Update failed',
|
|
'message' => $e->getMessage(),
|
|
'backup_available' => $backupPath ?? null
|
|
], 500);
|
|
}
|
|
}
|
|
|
|
public function rollbackUpdate(Request $request)
|
|
{
|
|
try {
|
|
$backupPath = $request->input('backup_path');
|
|
|
|
if (!$backupPath || !file_exists($backupPath)) {
|
|
return response()->json(['error' => 'Backup not found'], 404);
|
|
}
|
|
|
|
Artisan::call('down', ['--message' => 'System rollback in progress']);
|
|
|
|
// Ripristino da backup
|
|
$this->restoreFromBackup($backupPath);
|
|
|
|
Artisan::call('up');
|
|
|
|
Log::info("System rolled back from backup: {$backupPath}");
|
|
|
|
return response()->json([
|
|
'status' => 'rollback_success',
|
|
'restored_from' => $backupPath
|
|
]);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('Rollback failed: ' . $e->getMessage());
|
|
return response()->json(['error' => 'Rollback failed'], 500);
|
|
}
|
|
}
|
|
|
|
private function createFullBackup(): string
|
|
{
|
|
$timestamp = now()->format('Y-m-d_H-i-s');
|
|
$backupPath = storage_path("backups/full_backup_{$timestamp}");
|
|
|
|
// Backup database
|
|
$dbBackup = "{$backupPath}/database.sql";
|
|
mkdir($backupPath, 0755, true);
|
|
|
|
$process = new Process([
|
|
'mysqldump',
|
|
'--host=' . config('database.connections.mysql.host'),
|
|
'--user=' . config('database.connections.mysql.username'),
|
|
'--password=' . config('database.connections.mysql.password'),
|
|
config('database.connections.mysql.database')
|
|
]);
|
|
|
|
$process->run();
|
|
file_put_contents($dbBackup, $process->getOutput());
|
|
|
|
// Backup file applicazione
|
|
$appBackup = "{$backupPath}/application.tar.gz";
|
|
$process = new Process([
|
|
'tar', '-czf', $appBackup,
|
|
'--exclude=storage/logs',
|
|
'--exclude=storage/cache',
|
|
'--exclude=storage/updates',
|
|
base_path()
|
|
]);
|
|
$process->run();
|
|
|
|
return $backupPath;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 🔧 Script di Monitoraggio e Auto-Update
|
|
```bash
|
|
#!/bin/bash
|
|
# netgescon-monitor.sh - Monitoraggio e auto-update
|
|
|
|
NETGESCON_PATH="/opt/netgescon"
|
|
LOG_FILE="/var/log/netgescon-monitor.log"
|
|
UPDATE_CHECK_URL="https://updates.netgescon.org/api/check-updates"
|
|
|
|
# Logging function
|
|
log() {
|
|
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> $LOG_FILE
|
|
}
|
|
|
|
# Controllo aggiornamenti
|
|
check_updates() {
|
|
log "Controllo aggiornamenti disponibili..."
|
|
|
|
CURRENT_VERSION=$(cd $NETGESCON_PATH && php artisan --version | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+')
|
|
|
|
RESPONSE=$(curl -s -X GET "$UPDATE_CHECK_URL" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"current_version\":\"$CURRENT_VERSION\"}")
|
|
|
|
HAS_UPDATES=$(echo $RESPONSE | jq -r '.has_updates')
|
|
|
|
if [ "$HAS_UPDATES" = "true" ]; then
|
|
LATEST_VERSION=$(echo $RESPONSE | jq -r '.latest_version')
|
|
log "Aggiornamento disponibile: $CURRENT_VERSION -> $LATEST_VERSION"
|
|
|
|
# Se auto-update è abilitato
|
|
if [ "$AUTO_UPDATE" = "true" ]; then
|
|
log "Avvio auto-update..."
|
|
auto_update $LATEST_VERSION
|
|
else
|
|
log "Auto-update disabilitato. Notifica admin via email."
|
|
send_update_notification $LATEST_VERSION
|
|
fi
|
|
else
|
|
log "Sistema aggiornato alla versione più recente: $CURRENT_VERSION"
|
|
fi
|
|
}
|
|
|
|
# Auto-update automatico
|
|
auto_update() {
|
|
local VERSION=$1
|
|
log "Esecuzione auto-update alla versione $VERSION"
|
|
|
|
# Backup pre-update
|
|
BACKUP_PATH="/opt/netgescon/storage/backups/auto_backup_$(date +%Y%m%d_%H%M%S)"
|
|
mkdir -p $BACKUP_PATH
|
|
|
|
# Database backup
|
|
mysqldump -u netgescon -p netgescon > "$BACKUP_PATH/database.sql"
|
|
|
|
# Application backup
|
|
tar -czf "$BACKUP_PATH/application.tar.gz" $NETGESCON_PATH
|
|
|
|
# Download e applicazione update
|
|
cd $NETGESCON_PATH
|
|
|
|
# API call per download update
|
|
curl -X POST "http://localhost/api/system/download-update" \
|
|
-H "Authorization: Bearer $UPDATE_TOKEN" \
|
|
-d "{\"version\":\"$VERSION\"}" \
|
|
-o "/tmp/netgescon-$VERSION.zip"
|
|
|
|
# Applicazione update via API
|
|
curl -X POST "http://localhost/api/system/apply-update" \
|
|
-H "Authorization: Bearer $UPDATE_TOKEN" \
|
|
-d "{\"version\":\"$VERSION\",\"update_file\":\"/tmp/netgescon-$VERSION.zip\"}"
|
|
|
|
if [ $? -eq 0 ]; then
|
|
log "Auto-update completato con successo alla versione $VERSION"
|
|
send_success_notification $VERSION
|
|
else
|
|
log "Auto-update fallito. Backup disponibile in $BACKUP_PATH"
|
|
send_failure_notification $VERSION $BACKUP_PATH
|
|
fi
|
|
}
|
|
|
|
# Health check sistema
|
|
health_check() {
|
|
log "Esecuzione health check..."
|
|
|
|
# Controllo servizi
|
|
systemctl is-active --quiet nginx || log "WARNING: Nginx non attivo"
|
|
systemctl is-active --quiet mysql || log "WARNING: MySQL non attivo"
|
|
systemctl is-active --quiet redis || log "WARNING: Redis non attivo"
|
|
systemctl is-active --quiet php8.1-fpm || log "WARNING: PHP-FPM non attivo"
|
|
|
|
# Controllo spazio disco
|
|
DISK_USAGE=$(df /opt/netgescon | awk 'NR==2{print $5}' | sed 's/%//')
|
|
if [ $DISK_USAGE -gt 80 ]; then
|
|
log "WARNING: Utilizzo disco alto: ${DISK_USAGE}%"
|
|
fi
|
|
|
|
# Controllo database connectivity
|
|
mysql -u netgescon -p -e "SELECT 1" netgescon > /dev/null 2>&1
|
|
if [ $? -ne 0 ]; then
|
|
log "ERROR: Connessione database fallita"
|
|
fi
|
|
|
|
# Controllo performance
|
|
RESPONSE_TIME=$(curl -o /dev/null -s -w '%{time_total}' http://localhost)
|
|
if (( $(echo "$RESPONSE_TIME > 5.0" | bc -l) )); then
|
|
log "WARNING: Response time alto: ${RESPONSE_TIME}s"
|
|
fi
|
|
}
|
|
|
|
# Cron job: ogni ora controllo health, ogni giorno controllo updates
|
|
case "$1" in
|
|
"health")
|
|
health_check
|
|
;;
|
|
"updates")
|
|
check_updates
|
|
;;
|
|
"auto-update")
|
|
AUTO_UPDATE=true
|
|
check_updates
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {health|updates|auto-update}"
|
|
exit 1
|
|
;;
|
|
esac
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 CONFIGURAZIONI SPECIFICHE
|
|
|
|
### 🔐 Autenticazione con Codice 8 Caratteri
|
|
```php
|
|
<?php
|
|
// app/Services/AdministratorFolderService.php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\User;
|
|
use App\Models\AdministratorFolder;
|
|
use Illuminate\Support\Str;
|
|
|
|
class AdministratorFolderService
|
|
{
|
|
public function createAdministratorFolder(User $user): string
|
|
{
|
|
// Genera codice 8 caratteri alfanumerico unico
|
|
do {
|
|
$folderCode = $this->generateFolderCode();
|
|
} while (AdministratorFolder::where('folder_code', $folderCode)->exists());
|
|
|
|
// Crea struttura cartelle
|
|
$basePath = storage_path('netgescon-data/administrators/' . $folderCode);
|
|
$this->createFolderStructure($basePath);
|
|
|
|
// Salva record database
|
|
AdministratorFolder::create([
|
|
'user_id' => $user->id,
|
|
'email' => $user->email,
|
|
'folder_code' => $folderCode,
|
|
'folder_path' => $basePath,
|
|
'disk_quota_mb' => 1024, // 1GB default
|
|
'permissions' => $this->getDefaultPermissions()
|
|
]);
|
|
|
|
return $folderCode;
|
|
}
|
|
|
|
private function generateFolderCode(): string
|
|
{
|
|
// Genera codice 8 caratteri: 2 lettere + 6 numeri/lettere
|
|
$prefix = strtoupper(Str::random(2));
|
|
$suffix = strtoupper(Str::random(6));
|
|
|
|
return $prefix . $suffix;
|
|
}
|
|
|
|
private function createFolderStructure(string $basePath): void
|
|
{
|
|
$folders = [
|
|
'profile',
|
|
'condomini',
|
|
'backup/daily',
|
|
'backup/weekly',
|
|
'backup/manual',
|
|
'temp',
|
|
'reports',
|
|
'cache'
|
|
];
|
|
|
|
foreach ($folders as $folder) {
|
|
$fullPath = $basePath . '/' . $folder;
|
|
if (!file_exists($fullPath)) {
|
|
mkdir($fullPath, 0755, true);
|
|
}
|
|
}
|
|
|
|
// File .htaccess per sicurezza
|
|
file_put_contents($basePath . '/.htaccess', "Deny from all\n");
|
|
}
|
|
|
|
public function getAdministratorFolder(string $email): ?AdministratorFolder
|
|
{
|
|
return AdministratorFolder::where('email', $email)->first();
|
|
}
|
|
|
|
public function updateDiskUsage(string $folderCode): void
|
|
{
|
|
$folder = AdministratorFolder::where('folder_code', $folderCode)->first();
|
|
if (!$folder) return;
|
|
|
|
$folderPath = $folder->folder_path;
|
|
$sizeBytes = $this->getFolderSize($folderPath);
|
|
$sizeMB = round($sizeBytes / 1024 / 1024, 2);
|
|
|
|
$folder->update(['used_space_mb' => $sizeMB]);
|
|
}
|
|
|
|
private function getFolderSize(string $path): int
|
|
{
|
|
$size = 0;
|
|
$files = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator($path)
|
|
);
|
|
|
|
foreach ($files as $file) {
|
|
if ($file->isFile()) {
|
|
$size += $file->getSize();
|
|
}
|
|
}
|
|
|
|
return $size;
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 MIDDLEWARE GESTIONE CARTELLE
|
|
|
|
```php
|
|
<?php
|
|
// app/Http/Middleware/AdministratorFolderMiddleware.php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use App\Services\AdministratorFolderService;
|
|
|
|
class AdministratorFolderMiddleware
|
|
{
|
|
protected $folderService;
|
|
|
|
public function __construct(AdministratorFolderService $folderService)
|
|
{
|
|
$this->folderService = $folderService;
|
|
}
|
|
|
|
public function handle(Request $request, Closure $next)
|
|
{
|
|
if ($request->user()) {
|
|
$adminFolder = $this->folderService->getAdministratorFolder($request->user()->email);
|
|
|
|
if (!$adminFolder) {
|
|
// Crea cartella al primo accesso
|
|
$folderCode = $this->folderService->createAdministratorFolder($request->user());
|
|
$adminFolder = $this->folderService->getAdministratorFolder($request->user()->email);
|
|
}
|
|
|
|
// Aggiorna ultimo accesso
|
|
$adminFolder->update(['last_access' => now()]);
|
|
|
|
// Aggiunge info cartella alla sessione
|
|
session([
|
|
'admin_folder_code' => $adminFolder->folder_code,
|
|
'admin_folder_path' => $adminFolder->folder_path,
|
|
'admin_disk_quota' => $adminFolder->disk_quota_mb,
|
|
'admin_used_space' => $adminFolder->used_space_mb
|
|
]);
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 📦 DOCKERFILE OTTIMIZZATO
|
|
|
|
```dockerfile
|
|
# Dockerfile per NetGesCon Production
|
|
FROM php:8.1-fpm-alpine
|
|
|
|
# Installa dipendenze di sistema
|
|
RUN apk add --no-cache \
|
|
nginx \
|
|
mysql-client \
|
|
redis \
|
|
git \
|
|
unzip \
|
|
curl \
|
|
wget \
|
|
bash \
|
|
supervisor \
|
|
&& docker-php-ext-install \
|
|
pdo_mysql \
|
|
mysqli \
|
|
bcmath \
|
|
gd \
|
|
intl \
|
|
zip \
|
|
soap
|
|
|
|
# Installa Redis extension
|
|
RUN pecl install redis && docker-php-ext-enable redis
|
|
|
|
# Installa Composer
|
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
|
|
|
# Crea utente netgescon
|
|
RUN adduser -D -s /bin/bash netgescon
|
|
|
|
# Directory di lavoro
|
|
WORKDIR /var/www/html
|
|
|
|
# Copia files applicazione
|
|
COPY . /var/www/html
|
|
COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf
|
|
COPY docker/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
|
|
|
# Imposta permessi
|
|
RUN chown -R netgescon:www-data /var/www/html \
|
|
&& chmod -R 775 storage bootstrap/cache
|
|
|
|
# Installa dipendenze PHP
|
|
RUN composer install --no-dev --optimize-autoloader
|
|
|
|
# Crea struttura cartelle NetGesCon
|
|
RUN mkdir -p /var/www/html/storage/netgescon-data/{administrators,system/{backups,logs,uploads,cache}} \
|
|
&& chown -R netgescon:www-data /var/www/html/storage \
|
|
&& chmod -R 775 /var/www/html/storage
|
|
|
|
# Espone porte
|
|
EXPOSE 80 9000
|
|
|
|
# Script di avvio
|
|
COPY docker/start.sh /start.sh
|
|
RUN chmod +x /start.sh
|
|
|
|
# Healthcheck
|
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
|
CMD curl -f http://localhost/health || exit 1
|
|
|
|
CMD ["/start.sh"]
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 CHECKLIST IMPLEMENTAZIONE
|
|
|
|
### ✅ Gestione Cartelle Amministratore
|
|
- [x] ✅ Schema database cartelle utente con codice 8 caratteri
|
|
- [x] ✅ Service layer per gestione cartelle automatica
|
|
- [x] ✅ Middleware controllo accesso cartelle
|
|
- [x] ✅ Sistema quota disco e monitoraggio utilizzo
|
|
- [x] ✅ Struttura cartelle standardizzata per amministratore
|
|
|
|
### ✅ Installazione Docker
|
|
- [x] ✅ Docker Compose completo con tutti i servizi
|
|
- [x] ✅ Script avvio automatico con health check
|
|
- [x] ✅ Dockerfile ottimizzato per production
|
|
- [x] ✅ Persistenza dati con volumi Docker
|
|
- [x] ✅ Configurazione nginx/mysql/redis integrate
|
|
|
|
### ✅ Installazione Tradizionale
|
|
- [x] ✅ Script installazione multi-OS (Ubuntu/Debian/CentOS/RHEL)
|
|
- [x] ✅ Configurazione automatica servizi (Nginx/MySQL/Redis/PHP-FPM)
|
|
- [x] ✅ Setup utente dedicato netgescon
|
|
- [x] ✅ Permessi filesystem corretti
|
|
- [x] ✅ Configurazione SSL e sicurezza
|
|
|
|
### ✅ Sistema Aggiornamento Remoto
|
|
- [x] ✅ API REST per check/download/apply updates
|
|
- [x] ✅ Verifica integrità file con hash SHA256
|
|
- [x] ✅ Backup automatico pre-aggiornamento
|
|
- [x] ✅ Rollback automatico in caso errori
|
|
- [x] ✅ Script monitoraggio e auto-update
|
|
|
|
### ✅ Portabilità e Migrazione
|
|
- [x] ✅ Tutto in SQL per portabilità completa
|
|
- [x] ✅ Export/Import cartelle amministratore
|
|
- [x] ✅ Backup granulari per migrazione selettiva
|
|
- [x] ✅ Compatibilità multi-ambiente (Docker/VM/Bare Metal)
|
|
|
|
**Risultato**: Sistema completamente portabile, automatizzato e enterprise-ready! 🚀
|