Files
auditly/src/services/imageStorageService.ts
2025-08-24 00:48:41 -07:00

182 lines
5.2 KiB
TypeScript

import { processImage, validateImageFile, generateUniqueFileName, ProcessedImage } from '../utils/imageUtils';
import { secureApi } from './secureApi';
import { useAuth } from '../contexts/AuthContext';
export interface StoredImage {
id: string;
dataUrl: string;
filename: string;
originalSize: number;
compressedSize: number;
uploadedAt: number;
width: number;
height: number;
}
/**
* Upload and store an image through secure API
* @param file - The image file to upload
* @param collectionName - Collection name (e.g., 'company-logos')
* @param documentId - Document ID (e.g., orgId)
* @param orgId - Organization ID
* @param userId - User ID for authentication
* @param maxWidth - Maximum width for resizing (default: 128)
* @param maxHeight - Maximum height for resizing (default: 128)
* @returns Promise with stored image data
*/
export const uploadImage = async (
file: File,
collectionName: string,
documentId: string,
orgId: string,
userId: string,
maxWidth: number = 128,
maxHeight: number = 128
): Promise<StoredImage> => {
// Validate the image file
const validation = validateImageFile(file);
if (!validation.valid) {
throw new Error(validation.error);
}
// Process the image
const processedImage: ProcessedImage = await processImage(file, maxWidth, maxHeight);
// Generate unique filename
const filename = generateUniqueFileName(file.name, 'logo');
// Create image data to upload
const imageData = {
collectionName,
documentId,
dataUrl: processedImage.dataUrl,
filename,
originalSize: processedImage.originalSize,
compressedSize: processedImage.compressedSize,
width: processedImage.width,
height: processedImage.height,
};
try {
const result = await secureApi.uploadImage(orgId, userId, imageData);
if (!result.success) {
throw new Error('Failed to upload image');
}
return {
id: result.imageId,
dataUrl: processedImage.dataUrl,
filename,
originalSize: processedImage.originalSize,
compressedSize: processedImage.compressedSize,
uploadedAt: Date.now(),
width: processedImage.width,
height: processedImage.height,
};
} catch (error) {
console.error('Failed to upload image through secure API:', error);
throw new Error('Failed to upload image');
}
};
/**
* Retrieve an image through secure API
* @param collectionName - Collection name
* @param documentId - Document ID
* @param orgId - Organization ID
* @param userId - User ID for authentication
* @returns Promise with stored image data or null if not found
*/
export const getImage = async (
collectionName: string,
documentId: string,
orgId: string,
userId: string
): Promise<StoredImage | null> => {
try {
const result = await secureApi.getImage(orgId, userId, collectionName, documentId);
return result; // getImage already returns StoredImage | null
} catch (error) {
console.error('Failed to retrieve image through secure API:', error);
return null;
}
};
/**
* Delete an image through secure API
* @param collectionName - Collection name
* @param documentId - Document ID
* @param orgId - Organization ID
* @param userId - User ID for authentication
* @returns Promise indicating success
*/
export const deleteImage = async (
collectionName: string,
documentId: string,
orgId: string,
userId: string
): Promise<boolean> => {
try {
const result = await secureApi.deleteImage(orgId, userId, collectionName, documentId);
return result; // deleteImage already returns boolean
} catch (error) {
console.error('Failed to delete image through secure API:', error);
return false;
}
};
/**
* Company-specific image upload (convenience function)
* Requires authentication context to get userId
*/
export const uploadCompanyLogo = async (
file: File,
orgId: string,
userId: string
): Promise<StoredImage> => {
return uploadImage(file, 'company-logos', orgId, orgId, userId, 128, 128);
};
/**
* Get company logo (convenience function)
* Requires authentication context to get userId
*/
export const getCompanyLogo = async (
orgId: string,
userId: string
): Promise<StoredImage | null> => {
return getImage('company-logos', orgId, orgId, userId);
};
/**
* Delete company logo (convenience function)
* Requires authentication context to get userId
*/
export const deleteCompanyLogo = async (
orgId: string,
userId: string
): Promise<boolean> => {
return deleteImage('company-logos', orgId, orgId, userId);
};
/**
* Hook-based convenience functions that automatically get userId from auth context
* Use these in React components where useAuth is available
*/
export const useImageStorage = () => {
// Note: This would need to be implemented in a React component context
// where useAuth() is available. For now, we provide the functions that require
// explicit userId parameter.
return {
uploadImage,
getImage,
deleteImage,
uploadCompanyLogo,
getCompanyLogo,
deleteCompanyLogo,
};
};