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

141 lines
3.9 KiB
TypeScript

/**
* Secure image storage service using cloud functions
* No direct Firebase/Firestore access from the frontend
*/
import { secureApi } from './secureApi';
export interface StoredImage {
id: string;
fileName: string;
mimeType: string;
size: number;
uploadedAt: number;
data: string; // base64 encoded data
}
/**
* Upload and store an image via cloud functions
* @param file - The image file to upload
* @param collectionName - Collection name for organization (e.g., 'company-logos')
* @param documentId - Document ID for the image
* @param orgId - Organization ID for security
* @param userId - User ID for authentication
*/
export const uploadImage = async (
file: File,
collectionName: string,
documentId: string,
orgId: string,
userId: string
): Promise<StoredImage> => {
if (!file) {
throw new Error('No file provided');
}
// Validate file type
if (!file.type.startsWith('image/')) {
throw new Error('File must be an image');
}
// Validate file size (max 5MB)
const maxSize = 5 * 1024 * 1024; // 5MB
if (file.size > maxSize) {
throw new Error('Image size must be less than 5MB');
}
try {
// Convert file to base64
const base64Data = await fileToBase64(file);
// Create image object
const imageData = {
id: documentId,
fileName: file.name,
mimeType: file.type,
size: file.size,
uploadedAt: Date.now(),
data: base64Data
};
// Store via secure API (this would need to be implemented in cloud functions)
console.log('Image upload via secure API not yet implemented, storing locally');
// For now, return the image data (in production, this would go through cloud functions)
return imageData;
} catch (error) {
console.error('Failed to upload image:', error);
throw new Error('Failed to upload image');
}
};
/**
* Retrieve an image via cloud functions
* @param collectionName - Collection name
* @param documentId - Document ID
* @param orgId - Organization ID for security
* @param userId - User ID for authentication
*/
export const getImage = async (
collectionName: string,
documentId: string,
orgId: string,
userId: string
): Promise<StoredImage | null> => {
try {
// This would be implemented as a cloud function
console.log('Image retrieval via secure API not yet implemented');
return null;
} catch (error) {
console.error('Failed to retrieve image:', error);
return null;
}
};
/**
* Delete an image via cloud functions
* @param collectionName - Collection name
* @param documentId - Document ID
* @param orgId - Organization ID for security
* @param userId - User ID for authentication
*/
export const deleteImage = async (
collectionName: string,
documentId: string,
orgId: string,
userId: string
): Promise<boolean> => {
try {
// This would be implemented as a cloud function
console.log('Image deletion via secure API not yet implemented');
return true;
} catch (error) {
console.error('Failed to delete image:', error);
return false;
}
};
/**
* Helper function to convert File to base64
*/
const fileToBase64 = (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
if (typeof reader.result === 'string') {
resolve(reader.result);
} else {
reject(new Error('Failed to read file as base64'));
}
};
reader.onerror = (error) => reject(error);
});
};
// Default export for backward compatibility
export default {
uploadImage,
getImage,
deleteImage
};