Skip to content

Commit

Permalink
feat: backup and restore
Browse files Browse the repository at this point in the history
  • Loading branch information
ellite committed Apr 26, 2024
1 parent 65cc376 commit 4a76db5
Show file tree
Hide file tree
Showing 25 changed files with 314 additions and 89 deletions.
2 changes: 2 additions & 0 deletions .tmp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.gitignore
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ WORKDIR /var/www/html

# Update packages and install dependencies
RUN apk upgrade --no-cache && \
apk add --no-cache sqlite-dev libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev freetype freetype-dev curl autoconf libgomp icu-dev nginx dcron tzdata imagemagick imagemagick-dev && \
apk add --no-cache sqlite-dev libpng libpng-dev libjpeg-turbo libjpeg-turbo-dev freetype freetype-dev curl autoconf libgomp icu-dev nginx dcron tzdata imagemagick imagemagick-dev libzip-dev && \
docker-php-ext-install pdo pdo_sqlite && \
docker-php-ext-enable pdo pdo_sqlite && \
docker-php-ext-configure gd --with-freetype --with-jpeg && \
docker-php-ext-install -j$(nproc) gd intl && \
docker-php-ext-install -j$(nproc) gd intl zip && \
apk add --no-cache --virtual .build-deps $PHPIZE_DEPS && \
pecl install imagick && \
docker-php-ext-enable imagick && \
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ See instructions to run Wallos below.
- intl
- openssl
- sqlite3
- zip

#### Docker

Expand Down
68 changes: 68 additions & 0 deletions endpoints/db/backup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php
require_once '../../includes/connect_endpoint.php';
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}

function addFolderToZip($dir, $zipArchive, $zipdir = ''){
if (is_dir($dir)) {
if ($dh = opendir($dir)) {
//Add the directory
if(!empty($zipdir)) $zipArchive->addEmptyDir($zipdir);
while (($file = readdir($dh)) !== false) {
// Skip '.' and '..'
if ($file == "." || $file == "..") {
continue;
}
//If it's a folder, run the function again!
if(is_dir($dir . $file)){
$newdir = $dir . $file . '/';
addFolderToZip($newdir, $zipArchive, $zipdir . $file . '/');
}else{
//Add the files
$zipArchive->addFile($dir . $file, $zipdir . $file);
}
}
}
} else {
die(json_encode([
"success" => false,
"message" => "Directory does not exist: $dir"
]));
}
}

$zip = new ZipArchive();
$zipname = "../../.tmp/backup.zip";

if ($zip->open($zipname, ZipArchive::CREATE)!==TRUE) {
die(json_encode([
"success" => false,
"message" => translate('cannot_open_zip', $i18n)
]));
}

addFolderToZip('../../db/', $zip);
addFolderToZip('../../images/uploads/', $zip);

$numberOfFilesAdded = $zip->numFiles;

if ($zip->close() === false) {
die(json_encode([
"success" => false,
"message" => "Failed to finalize the zip file"
]));
} else {
die(json_encode([
"success" => true,
"message" => "Zip file created successfully",
"numFiles" => $numberOfFilesAdded
]));
}


?>
111 changes: 111 additions & 0 deletions endpoints/db/restore.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
require_once '../../includes/connect_endpoint.php';
session_start();
if (!isset($_SESSION['loggedin']) || $_SESSION['loggedin'] !== true) {
die(json_encode([
"success" => false,
"message" => translate('session_expired', $i18n)
]));
}

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_FILES['file'])) {
$file = $_FILES['file'];
$fileTmpName = $file['tmp_name'];
$fileError = $file['error'];

if ($fileError === 0) {
// Handle the uploaded file here
// The uploaded file will be stored as restore.zip
$fileDestination = '../../.tmp/restore.zip';
move_uploaded_file($fileTmpName, $fileDestination);

// Unzip the uploaded file
$zip = new ZipArchive();
if ($zip->open($fileDestination) === true) {
$zip->extractTo('../../.tmp/restore/');
$zip->close();
}

// Check if wallos.db file exists in the restore folder
if (file_exists('../../.tmp/restore/wallos.db')) {
// Replace the wallos.db file in the db directory with the wallos.db file in the restore directory
if (file_exists('../../db/wallos.db')) {
unlink('../../db/wallos.db');
}
rename('../../.tmp/restore/wallos.db', '../../db/wallos.db');

// Check if restore/logos/ directory exists
if (file_exists('../../.tmp/restore/logos/')) {
// Delete the files and folders in the uploaded logos directory
$dir = '../../images/uploads/logos/';

// Create recursive directory iterator
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);

// Create recursive iterator iterator in Child First Order
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);

// For each item in the recursive iterator
foreach ( $ri as $file ) {
// If the item is a directory
if ( $file->isDir() ) {
// Remove the directory
rmdir($file->getPathname());
} else {
// If the item is a file
// Remove the file
unlink($file->getPathname());
}
}

// Copy the contents of restore/logos/ directory to the ../../images/uploads/logos/ directory
$dir = new RecursiveDirectoryIterator('../../.tmp/restore/logos/');
$ite = new RecursiveIteratorIterator($dir);
$allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp'];

foreach ($ite as $filePath) {
if (in_array(pathinfo($filePath, PATHINFO_EXTENSION), $allowedExtensions)) {
$destination = str_replace('../../.tmp/restore/', '../../images/uploads/', $filePath);
$destinationDir = pathinfo($destination, PATHINFO_DIRNAME);

if (!is_dir($destinationDir)) {
mkdir($destinationDir, 0755, true);
}

copy($filePath, $destination);
}
}
}

echo json_encode([
"success" => true,
"message" => "File uploaded and wallos.db exists"
]);
} else {
die(json_encode([
"success" => false,
"message" => "wallos.db does not exist in the backup file"
]));
}


} else {
echo json_encode([
"success" => false,
"message" => "Failed to upload file"
]);
}
} else {
echo json_encode([
"success" => false,
"message" => "No file uploaded"
]);
}
} else {
echo json_encode([
"success" => false,
"message" => "Invalid request method"
]);
}
?>
48 changes: 0 additions & 48 deletions endpoints/subscriptions/export.php

This file was deleted.

6 changes: 6 additions & 0 deletions includes/footer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,11 @@
<div class="progress success"></div>
</div>

<?php
if (isset($db)) {
$db->close();
}
?>

</body>
</html>
6 changes: 4 additions & 2 deletions includes/i18n/de.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Hinzufügen",
"save" => "Speichern",
"reset" => "Zurücksetzen",
"export_subscriptions" => "Abonnements exportieren",
"export_to_json" => "Nach JSON exportieren",
"backup_and_restore" => "Backup und Wiederherstellung",
"backup" => "Backup",
"restore" => "Wiederherstellen",
"restore_info" => "Durch die Wiederherstellung der Datenbank werden alle aktuellen Daten überschrieben. Nach der Wiederherstellung werden Sie abgemeldet.",
// Filters menu
"filter" => "Filter",
"clear" => "Leeren",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/el.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Προσθήκη",
"save" => "Αποθήκευση",
"reset" => "Επαναφορά",
"export_subscriptions" => "Εξαγωγή συνδρομών",
"export_to_json" => "Εξαγωγή σε JSON",
"backup_and_restore" => "Αντίγραφο ασφαλείας και επαναφορά",
"backup" => "Αντίγραφο ασφαλείας",
"restore" => "Επαναφορά",
"restore_info" => "Η επαναφορά της βάσης δεδομένων θα ακυρώσει όλα τα τρέχοντα δεδομένα. Μετά την επαναφορά θα αποσυνδεθείτε.",
// Filters menu
"filter" => "Φίλτρο",
"clear" => "Καθαρισμός",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/en.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Add",
"save" => "Save",
"reset" => "Reset",
"export_subscriptions" => "Export Subscriptions",
"export_to_json" => "Export to JSON",
"backup_and_restore" => "Backup and Restore",
"backup" => "Backup",
"restore" => "Restore",
"restore_info" => "Restoring the database will override all current data. You will be signed out after the restore.",
// Filters menu
"filter" => "Filter",
"clear" => "Clear",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/es.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Agregar",
"save" => "Guardar",
"reset" => "Restablecer",
"export_subscriptions" => "Exportar suscripciones",
"export_to_json" => "Exportar a JSON",
"backup_and_restore" => "Copia de Seguridad y Restauración",
"backup" => "Copia de Seguridad",
"restore" => "Restaurar",
"restore_info" => "La restauración de la base de datos anulará todos los datos actuales. Se cerrará la sesión después de la restauración.",
// Filters menu
"filter" => "Filtrar",
"clear" => "Limpiar",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/fr.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Ajouter",
"save" => "Enregistrer",
"reset" => "Réinitialiser",
"export_subscriptions" => "Exporter les abonnements",
"export_to_json" => "Exporter en JSON",
"backup_and_restore" => "Sauvegarde et restauration",
"backup" => "Sauvegarde",
"restore" => "Restauration",
"restore_info" => "La restauration de la base de données annulera toutes les données actuelles. Vous serez déconnecté après la restauration.",
// Menu des filtes
"filter" => "Filtre",
"clear" => "Effacer",
Expand Down
7 changes: 4 additions & 3 deletions includes/i18n/it.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,10 @@
'add' => 'Aggiungi',
'save' => 'Salva',
"reset" => 'Ripristina',
'export_subscriptions' => 'Esporta abbonamenti',
'export_to_json' => 'Esporta in JSON',

"backup_and_restore" => 'Backup e ripristino',
"backup" => 'Backup',
"restore" => 'Ripristina',
"restore_info" => "Il ripristino del database annullerà tutti i dati correnti. Al termine del ripristino, l'utente verrà disconnesso.",
// Filters
'filter' => 'Filtra',
'clear' => 'Pulisci',
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/jp.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "追加",
"save" => "保存",
"reset" => "リセット",
"export_subscriptions" => "購読をエクスポート",
"export_to_json" => "JSONにエクスポート",
"backup_and_restore" => "バックアップとリストア",
"backup" => "バックアップ",
"restore" => "リストア",
"restore_info" => "データベースをリストアすると、現在のデータがすべて上書きされます。リストア後はサインアウトされます。",
// Filters menu
"filter" => "フィルタ",
"clear" => "クリア",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/pl.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Dodaj",
"save" => "Zapisz",
"reset" => "Resetuj",
"export_subscriptions" => "Eksportuj subskrypcje",
"export_to_json" => "Eksportuj do JSON",
"backup_and_restore" => "Kopia zapasowa i przywracanie",
"backup" => "Kopia zapasowa",
"restore" => "Przywróć",
"restore_info" => "Przywrócenie bazy danych zastąpi wszystkie bieżące dane. Po przywróceniu zostaniesz wylogowany.",
// Filters menu
"filter" => "Filtr",
"clear" => "Wyczyść",
Expand Down
6 changes: 4 additions & 2 deletions includes/i18n/pt.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,10 @@
"add" => "Adicionar",
"save" => "Guardar",
"reset" => "Repor",
"export_subscriptions" => "Exportar Subscrições",
"export_to_json" => "Exportar para JSON",
"backup_and_restore" => "Backup e Restauro",
"backup" => "Backup",
"restore" => "Restauro",
"restore_info" => "O restauro da base de dados apagará todos os dados actuais. A sua sessão irá terminar após o restauro.",
// Filters menu
"filter" => "Filtro",
"clear" => "Limpar",
Expand Down
Loading

0 comments on commit 4a76db5

Please sign in to comment.