Fix critical issues: gallery authentication and photo duplication
- Fix gallery-specific authentication for images - Update AuthenticatedImage component to use gallery-specific tokens - Add isGallery prop to distinguish between admin and gallery contexts - Update PhotoGrid and PhotoLightbox to pass isGallery prop - Fix photo duplication issue in fileWatcher service - Add check to prevent duplicate photo entries when backend restarts - File watcher now verifies if photo exists before inserting - Cleaned up 176 duplicate photos from database These fixes resolve: 1. Gallery images not loading due to auth token errors 2. Photo count increasing without new uploads due to duplicates 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -63,17 +63,26 @@ async function processNewPhoto(filePath) {
|
||||
// Calculate relative thumbnail path
|
||||
const relativeThumbPath = thumbnailPath; // thumbnailPath is already relative to storage root
|
||||
|
||||
// Add to database
|
||||
await db('photos').insert({
|
||||
event_id: event.id,
|
||||
filename: path.basename(filePath),
|
||||
path: relativePath,
|
||||
thumbnail_path: relativeThumbPath,
|
||||
type: photoType,
|
||||
size_bytes: stats.size
|
||||
});
|
||||
// Check if photo already exists
|
||||
const existingPhoto = await db('photos')
|
||||
.where({ event_id: event.id, filename: path.basename(filePath) })
|
||||
.first();
|
||||
|
||||
logger.info(`Added new photo: ${relativePath}`);
|
||||
if (!existingPhoto) {
|
||||
// Add to database
|
||||
await db('photos').insert({
|
||||
event_id: event.id,
|
||||
filename: path.basename(filePath),
|
||||
path: relativePath,
|
||||
thumbnail_path: relativeThumbPath,
|
||||
type: photoType,
|
||||
size_bytes: stats.size
|
||||
});
|
||||
|
||||
logger.info(`Added new photo: ${relativePath}`);
|
||||
} else {
|
||||
logger.debug(`Photo already exists: ${relativePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function removePhoto(filePath) {
|
||||
|
||||
@@ -5,6 +5,7 @@ interface AuthenticatedImageProps extends React.ImgHTMLAttributes<HTMLImageEleme
|
||||
src: string;
|
||||
fallbackSrc?: string;
|
||||
useWatermark?: boolean;
|
||||
isGallery?: boolean;
|
||||
}
|
||||
|
||||
export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
||||
@@ -12,6 +13,7 @@ export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
||||
fallbackSrc,
|
||||
alt,
|
||||
useWatermark = false,
|
||||
isGallery = false,
|
||||
...props
|
||||
}) => {
|
||||
const [imageSrc, setImageSrc] = useState<string>('');
|
||||
@@ -21,7 +23,20 @@ export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
||||
useEffect(() => {
|
||||
let objectUrl: string | null = null;
|
||||
|
||||
const token = getAuthToken();
|
||||
// Determine which token to use based on context
|
||||
let token: string | undefined;
|
||||
|
||||
if (isGallery) {
|
||||
// For gallery images, get the gallery-specific token
|
||||
const pathParts = window.location.pathname.split('/');
|
||||
if (pathParts[1] === 'gallery' && pathParts[2]) {
|
||||
const gallerySlug = pathParts[2];
|
||||
token = localStorage.getItem(`gallery_token_${gallerySlug}`) || undefined;
|
||||
}
|
||||
} else {
|
||||
// For admin images, use the admin token
|
||||
token = getAuthToken(true);
|
||||
}
|
||||
|
||||
if (!src) {
|
||||
setImageSrc(fallbackSrc || '');
|
||||
@@ -89,7 +104,7 @@ export const AuthenticatedImage: React.FC<AuthenticatedImageProps> = ({
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
}
|
||||
};
|
||||
}, [src, fallbackSrc, useWatermark]);
|
||||
}, [src, fallbackSrc, useWatermark, isGallery]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
|
||||
@@ -237,6 +237,7 @@ const PhotoThumbnail: React.FC<PhotoThumbnailProps> = ({
|
||||
alt={photo.filename}
|
||||
className="w-full h-full object-cover rounded-lg transition-transform duration-200 group-hover:scale-105"
|
||||
loading="lazy"
|
||||
isGallery={true}
|
||||
/>
|
||||
|
||||
{/* Overlay on hover */}
|
||||
|
||||
@@ -252,6 +252,7 @@ export const PhotoLightbox: React.FC<PhotoLightboxProps> = ({
|
||||
}}
|
||||
draggable={false}
|
||||
useWatermark={true}
|
||||
isGallery={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user