mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 16:03:02 +00:00
fix: back-merge v3.1.4 hotfixes into dev (#1371)
Port the three main-only fixes onto dev's (post-rewrite) architecture:
- fix(backups): prevent recursion when the backup path sits inside the backed-up dir
- fix(share): convert budget items to the viewer's base currency instead of a flat EUR
- fix(files): surface the descriptive server error for unsupported upload types (#1363)
Cherry-picked from 819aa793 on main; the SharedTripPage and useTripPlanner
conflicts were resolved to keep dev's font-scaling and full import set while
taking the fixes' currency conversion and translateApiError wiring.
This commit is contained in:
@@ -39,7 +39,8 @@ const UPLOAD = {
|
||||
fileFilter: (_req: unknown, file: Express.Multer.File, cb: (err: Error | null, accept: boolean) => void) => {
|
||||
const ext = path.extname(file.originalname).toLowerCase();
|
||||
const reject = () => {
|
||||
const err: Error & { statusCode?: number } = new Error('File type not allowed');
|
||||
// i18n key — the client resolves it via t() (see translateApiError).
|
||||
const err: Error & { statusCode?: number } = new Error('files.uploadErrorType');
|
||||
err.statusCode = 400;
|
||||
cb(err, false);
|
||||
};
|
||||
|
||||
@@ -184,9 +184,21 @@ export async function createBackup(): Promise<BackupInfo> {
|
||||
// Exclude the place-photo and trek-memory caches: both are re-derivable
|
||||
// (re-fetched on demand, keyed on stable ids) and would otherwise dominate
|
||||
// backup size. Restores self-heal — the cache dirs are recreated at startup.
|
||||
//
|
||||
// Also exclude backups/ and restore-*/: these live under data/, not uploads/,
|
||||
// but when an install maps data and uploads to the SAME directory (a
|
||||
// misconfiguration, but a catastrophic one) the glob would otherwise sweep
|
||||
// every prior backup zip into the new archive — each run embedding all
|
||||
// previous runs, so size compounds without bound (see issue #1358). Ignoring
|
||||
// them keeps the backup bounded regardless of how the volumes are mounted.
|
||||
archive.glob(
|
||||
'**/*',
|
||||
{ cwd: uploadsDir, ignore: ['photos/google/**', 'photos/trek/**'], nodir: true, dot: true },
|
||||
{
|
||||
cwd: uploadsDir,
|
||||
ignore: ['photos/google/**', 'photos/trek/**', 'backups/**', 'restore-*/**'],
|
||||
nodir: true,
|
||||
dot: true,
|
||||
},
|
||||
{ prefix: 'uploads' },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { db, canAccessTrip } from '../db/database';
|
||||
import crypto from 'crypto';
|
||||
import { loadTagsByPlaceIds } from './queryHelpers';
|
||||
import { serveFilePath } from './placePhotoCache';
|
||||
import { getUserSettings } from './settingsService';
|
||||
|
||||
const PLACE_PHOTO_PROXY_PREFIX = '/api/maps/place-photo/';
|
||||
|
||||
@@ -219,8 +220,23 @@ export function getSharedTripData(token: string): Record<string, any> | null {
|
||||
? db.prepare('SELECT m.*, u.username, u.avatar FROM collab_messages m JOIN users u ON m.user_id = u.id WHERE m.trip_id = ? AND m.deleted = 0 ORDER BY m.created_at').all(tripId)
|
||||
: [];
|
||||
|
||||
// Display currency the share owner sees in their Costs view. A public viewer has
|
||||
// no logged-in user, so the owner's per-user `default_currency` (with the admin
|
||||
// instance default already merged in by getUserSettings) is embedded in the
|
||||
// payload and used by the client to convert every expense — otherwise guests
|
||||
// fall back to the trip's base currency and see the wrong totals (#1361).
|
||||
// getUserSettings merges admin defaults under the user's own settings, so this
|
||||
// honours per-user → admin-default; we then fall back to trip currency → EUR.
|
||||
let baseCurrency = (trip as { currency?: string }).currency || 'EUR';
|
||||
if (shareRow.created_by != null) {
|
||||
const ownerDefault = getUserSettings(shareRow.created_by)['default_currency'];
|
||||
if (typeof ownerDefault === 'string' && ownerDefault.trim()) {
|
||||
baseCurrency = ownerDefault.trim();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
trip, days, assignments, dayNotes, places, categories, permissions,
|
||||
trip, baseCurrency, days, assignments, dayNotes, places, categories, permissions,
|
||||
reservations: permissions.share_bookings ? reservations : [],
|
||||
accommodations: permissions.share_bookings ? accommodations : [],
|
||||
packing: permissions.share_packing ? packing : [],
|
||||
|
||||
Reference in New Issue
Block a user