diff --git a/.github/screenshot-recipes.png b/.github/screenshot-recipes.png deleted file mode 100644 index b8b5b9acf..000000000 Binary files a/.github/screenshot-recipes.png and /dev/null differ diff --git a/.github/screenshot-recipes.webp b/.github/screenshot-recipes.webp new file mode 100644 index 000000000..878bf9d93 Binary files /dev/null and b/.github/screenshot-recipes.webp differ diff --git a/README.md b/README.md index d4d019575..eb4a9817e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ A clean, simple and powerful recipe manager web application for unforgettable family recipes, empowering you to curate and share your favorite recipes. It is focused on simplicity for the whole family to enjoy. -![Recipe page screenshot](.github/screenshot-recipes.png) +![Recipe page screenshot](.github/screenshot-recipes.webp) ## Features diff --git a/docs/website/content/about/changelog/v1.2.0.md b/docs/website/content/about/changelog/v1.2.0.md index 64ae6e5c8..921135ba6 100644 --- a/docs/website/content/about/changelog/v1.2.0.md +++ b/docs/website/content/about/changelog/v1.2.0.md @@ -1,5 +1,5 @@ --- -title: v1.2.0 (11 July 2024) +title: v1.2.0 (12 July 2024) weight: 1 --- @@ -59,6 +59,7 @@ weight: 1 exported archive is skipped. - ๐Ÿช **Redirection**: Fixed a redirection error when logging in when a session cookie exists. - ๐Ÿชน **Reload**: The page now does not reload when the search query is empty. +- ๐Ÿ“ฅ **Restore backup**: Fixed user backup restoration when optional files in the backup archive are missing. ## Changed diff --git a/docs/website/content/docs/features/admin.md b/docs/website/content/docs/features/admin.md index bd2f882de..f3440788c 100644 --- a/docs/website/content/docs/features/admin.md +++ b/docs/website/content/docs/features/admin.md @@ -6,7 +6,7 @@ weight: 1 An administrator is defined as the initial user, typically the one who set up Recipya. Only the administrator can access the admin page. -To access it, select the `admin` option from the avatar menu. +To access it, select the `Admin` option from the avatar menu. ![](images/admin-access.webp) diff --git a/docs/website/content/docs/features/backups.md b/docs/website/content/docs/features/backups.md index 37dcd68d1..2a3d2f9c5 100644 --- a/docs/website/content/docs/features/backups.md +++ b/docs/website/content/docs/features/backups.md @@ -9,46 +9,56 @@ being one month old. ### Global -A global backup is one which saves the state of the database and all the images. +A global backup is one which saves the current state of the application data. It is stored under `path/to/recipya/data/backup/global/`. Its structure is as follows: {{< filetree/container >}} {{< filetree/folder name="recipya.{year-month-day}.zip" >}} - {{< filetree/folder name="data" state="open" >}} - {{< filetree/folder name="database" state="open" >}} + {{< filetree/folder name="Recipya" state="open" >}} + {{< filetree/folder name="Database" state="open" >}} {{< filetree/file name="recipya.db" >}} {{< /filetree/folder >}} - {{< filetree/folder name="images" state="open" >}} - {{< filetree/file name="{uuid_1}.jpg" >}} - {{< filetree/file name="{uuid_2}.jpg" >}} - {{< filetree/file name="{uuid_...}.jpg" >}} - {{< filetree/file name="{uuid_N}.jpg" >}} + {{< filetree/folder name="Images" state="open" >}} + {{< filetree/folder name="Thumbnails" state="closed" >}} + {{< filetree/file name="{uuid_1}.webp" >}} + {{< filetree/file name="{uuid_2}.webp" >}} + {{< filetree/file name="{uuid_...}.webp" >}} + {{< filetree/file name="{uuid_N}.webp" >}} + {{< /filetree/folder >}} + {{< filetree/file name="{uuid_1}.webp" >}} + {{< filetree/file name="{uuid_2}.webp" >}} + {{< filetree/file name="{uuid_...}.webp" >}} + {{< filetree/file name="{uuid_N}.webp" >}} {{< /filetree/folder >}} + {{< filetree/folder name="Logs" state="open" >}} + {{< filetree/file name="recipya.log" >}} + {{< /filetree/folder >}} + {{< filetree/folder name="Videos" state="open" >}} + {{< filetree/file name="{uuid_1}.webm" >}} + {{< filetree/file name="{uuid_2}.webm" >}} + {{< filetree/file name="{uuid_...}.webm" >}} + {{< filetree/file name="{uuid_N}.webm" >}} + {{< /filetree/folder >}} + {{< filetree/file name="config.json" >}} {{< /filetree/folder >}} {{< /filetree/folder >}} {{< /filetree/container >}} ### User -A user backup is one which saves the state of a user's data. The following is saved: +A user backup is one which saves the current state of a user's data. The following is saved: - Recipes - Cookbooks - Shared recipes - Shared cookbooks -User backups are stored under `path/to/recipya/data/backup/users/{userID}`. +User backups are stored under `path/to/recipya/data/Backup/users/{userID}`. Its structure is as follows: {{< filetree/container >}} {{< filetree/folder name="recipya.{year-month-day}.zip" >}} - {{< filetree/folder name="images" state="open" >}} - {{< filetree/file name="{uuid_1}.jpg" >}} - {{< filetree/file name="{uuid_2}.jpg" >}} - {{< filetree/file name="{uuid_...}.jpg" >}} - {{< filetree/file name="{uuid_N}.jpg" >}} - {{< /filetree/folder >}} {{< filetree/file name="recipes.zip" >}} {{< filetree/file name="backup-deletes.sql" >}} {{< filetree/file name="backup-inserts.sql" >}} @@ -64,21 +74,19 @@ It is possible to restore a previous backup. The instructions on how to do so de Restoring a global backup is done only by the one who has access to the server. 1. Close the application -2. Navigate to `path/to/recipya/data/backup/global/` -3. Unzip the backup your wish to restore -4. Replace `path/to/recipya/data/databases/recipya.db` with the one from the unzipped backup -5. If applicable, delete `path/to/recipya/data/databases/recipya.db-shm` and `path/to/recipya/data/databases/recipya.db-wal` -6. Delete `path/to/recipya/data/images/` -7. Move the `images` folder from the unzipped backup to `path/to/recipya/data` -8. Start the application +2. Navigate to `path/to/recipya/data/Backup/global/` +3. Unzip the backup you wish to restore +4. Replace the content under `path/to/recipya/data/*` with the one from the unzipped backup +5. If applicable, delete `path/to/recipya/data/Database/recipya.db-shm` and `path/to/recipya/data/Database/recipya.db-wal +6. Start the application ### User Restoring a user backup is done through the web application's user interface. -1. Access the settings page -2. Click the `Advanced` tab -3. Identify the **Restore backup** setting +1. Access the settings dialog +2. Click the `Data` tab +3. Identify the **Restore from backup** setting 4. Select the backup date 5. Click the rocket launch icon diff --git a/docs/website/content/docs/features/images/admin-access.webp b/docs/website/content/docs/features/images/admin-access.webp index 9fefd8bf0..554b0c5b5 100644 Binary files a/docs/website/content/docs/features/images/admin-access.webp and b/docs/website/content/docs/features/images/admin-access.webp differ diff --git a/docs/website/content/docs/features/images/admin-overview.webp b/docs/website/content/docs/features/images/admin-overview.webp index 04ce4218a..0c8292206 100644 Binary files a/docs/website/content/docs/features/images/admin-overview.webp and b/docs/website/content/docs/features/images/admin-overview.webp differ diff --git a/docs/website/content/docs/features/images/settings-restore-backup.webp b/docs/website/content/docs/features/images/settings-restore-backup.webp index 987f2b47a..92e4b2157 100644 Binary files a/docs/website/content/docs/features/images/settings-restore-backup.webp and b/docs/website/content/docs/features/images/settings-restore-backup.webp differ diff --git a/internal/services/files.go b/internal/services/files.go index 6b002753f..b39b6bafc 100644 --- a/internal/services/files.go +++ b/internal/services/files.go @@ -216,8 +216,8 @@ func (f *Files) backupUserData(repo RepositoryService, userID int64) error { target := filepath.Join(app.BackupPath, "users", userIDStr, name) _, err := os.Stat(target) - if err == nil { - return nil + if err != nil { + return err } err = os.MkdirAll(filepath.Dir(target), os.ModePerm) @@ -1135,17 +1135,20 @@ func (f *Files) ExtractUserBackup(date string, userID int64) (*models.UserBackup } _ = rc.Close() - rc, err = insertsSQLFile.Open() - if err != nil { - return nil, err - } + var inserts []byte + if insertsSQLFile != nil { + rc, err = insertsSQLFile.Open() + if err != nil { + return nil, err + } - inserts, err := io.ReadAll(rc) - if err != nil { + inserts, err = io.ReadAll(rc) + if err != nil { + _ = rc.Close() + return nil, err + } _ = rc.Close() - return nil, err } - _ = rc.Close() rc, err = recipesFile.Open() if err != nil { diff --git a/internal/services/files_apps.go b/internal/services/files_apps.go index 35868ee14..072c2dc2b 100644 --- a/internal/services/files_apps.go +++ b/internal/services/files_apps.go @@ -350,6 +350,9 @@ func (f *Files) extractJSONRecipes(rd io.Reader) (models.Recipes, error) { } } + if r.Name == "" || len(r.Ingredients) == 0 || len(r.Instructions) == 0 { + continue + } xr = append(xr, *r) } diff --git a/internal/services/sqlite_service.go b/internal/services/sqlite_service.go index 7521ab590..3371e3d02 100644 --- a/internal/services/sqlite_service.go +++ b/internal/services/sqlite_service.go @@ -1294,11 +1294,13 @@ func (s *SQLiteService) RecipesAll(userID int64) models.Recipes { rows, err := s.DB.QueryContext(ctx, statements.SelectRecipesAll, userID) if err != nil { + slog.Error("Failed to select all recipes", "error", err, "userID", userID) return nil } recipes, err := scanRecipes(rows, false) if err != nil { + slog.Error("Failed to scan recipes", "error", err, "userID", userID) return nil }