initial commit
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
import { pool } from '../db.js';
|
||||
|
||||
/**
|
||||
* Repository для работы с метаданными файлов пользователей
|
||||
*/
|
||||
export const userFileRepository = {
|
||||
/**
|
||||
* Создать запись о файле
|
||||
*/
|
||||
async create({ userId, s3Key, originalFilename, fileSize, contentType, fileType = 'image', folder = 'images_input', generationUuid = null, generationStepId = null, status = 'uploaded', uploadId = null }) {
|
||||
const query = `
|
||||
INSERT INTO uno_bff.user_files (user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, status, upload_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||
RETURNING id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, status, upload_id, created_at, updated_at
|
||||
`;
|
||||
const values = [userId, s3Key, originalFilename, fileSize, contentType, fileType, folder, generationUuid, generationStepId, status, uploadId];
|
||||
|
||||
const result = await pool.query(query, values);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Обновить файл
|
||||
*/
|
||||
async update(fileId, updates) {
|
||||
const allowedFields = ['status', 'upload_id', 'file_size', 'updated_at'];
|
||||
const setClauses = [];
|
||||
const values = [fileId];
|
||||
let paramIndex = 2;
|
||||
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
if (allowedFields.includes(key)) {
|
||||
setClauses.push(`${key} = $${paramIndex}`);
|
||||
values.push(value);
|
||||
paramIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (setClauses.length === 0) {
|
||||
throw new Error('No valid fields to update');
|
||||
}
|
||||
|
||||
const query = `
|
||||
UPDATE uno_bff.user_files
|
||||
SET ${setClauses.join(', ')}
|
||||
WHERE id = $1
|
||||
RETURNING id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, status, upload_id, created_at, updated_at
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, values);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Удалить файл по ID
|
||||
*/
|
||||
async delete(fileId) {
|
||||
const query = `
|
||||
DELETE FROM uno_bff.user_files
|
||||
WHERE id = $1
|
||||
RETURNING id
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [fileId]);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Найти файл по ID и проверить владение
|
||||
*/
|
||||
async findByIdAndOwner(fileId, userId) {
|
||||
const query = `
|
||||
SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
|
||||
FROM uno_bff.user_files
|
||||
WHERE id = $1 AND user_id = $2
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [fileId, userId]);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Найти файл по S3 ключу и проверить владение
|
||||
*/
|
||||
async findByKeyAndOwner(s3Key, userId) {
|
||||
const query = `
|
||||
SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
|
||||
FROM uno_bff.user_files
|
||||
WHERE s3_key = $1 AND user_id = $2
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [s3Key, userId]);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Получить список файлов пользователя
|
||||
*/
|
||||
async findByUser(userId, options = {}) {
|
||||
const {
|
||||
fileType = 'image',
|
||||
folder = 'images_input',
|
||||
limit = 50,
|
||||
offset = 0,
|
||||
orderBy = 'created_at',
|
||||
order = 'DESC',
|
||||
} = options;
|
||||
|
||||
const validOrderColumns = ['created_at', 'original_filename', 'file_size'];
|
||||
const validOrders = ['ASC', 'DESC'];
|
||||
const safeOrderBy = validOrderColumns.includes(orderBy) ? orderBy : 'created_at';
|
||||
const safeOrder = validOrders.includes(order?.toUpperCase()) ? order.toUpperCase() : 'DESC';
|
||||
|
||||
const query = `
|
||||
SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, created_at
|
||||
FROM uno_bff.user_files
|
||||
WHERE user_id = $1
|
||||
AND ($2::VARCHAR IS NULL OR file_type = $2)
|
||||
AND ($3::VARCHAR IS NULL OR folder = $3)
|
||||
ORDER BY ${safeOrderBy} ${safeOrder}
|
||||
LIMIT $4 OFFSET $5
|
||||
`;
|
||||
|
||||
const values = [
|
||||
userId,
|
||||
fileType || null,
|
||||
folder || null,
|
||||
limit,
|
||||
offset,
|
||||
];
|
||||
|
||||
const result = await pool.query(query, values);
|
||||
return result.rows;
|
||||
},
|
||||
|
||||
/**
|
||||
* Получить общее количество файлов пользователя
|
||||
*/
|
||||
async countByUser(userId, options = {}) {
|
||||
const { fileType = 'image', folder = 'images_input' } = options;
|
||||
|
||||
const query = `
|
||||
SELECT COUNT(*) as total
|
||||
FROM uno_bff.user_files
|
||||
WHERE user_id = $1
|
||||
AND ($2::VARCHAR IS NULL OR file_type = $2)
|
||||
AND ($3::VARCHAR IS NULL OR folder = $3)
|
||||
`;
|
||||
|
||||
const values = [userId, fileType || null, folder || null];
|
||||
const result = await pool.query(query, values);
|
||||
return parseInt(result.rows[0].total, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* Удалить запись о файле (по ID и владельцу)
|
||||
*/
|
||||
async deleteByIdAndOwner(fileId, userId) {
|
||||
const query = `
|
||||
DELETE FROM uno_bff.user_files
|
||||
WHERE id = $1 AND user_id = $2
|
||||
RETURNING s3_key
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [fileId, userId]);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Удалить запись о файле по S3 ключу
|
||||
*/
|
||||
async deleteByKeyAndOwner(s3Key, userId) {
|
||||
const query = `
|
||||
DELETE FROM uno_bff.user_files
|
||||
WHERE s3_key = $1 AND user_id = $2
|
||||
RETURNING s3_key
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [s3Key, userId]);
|
||||
return result.rows[0];
|
||||
},
|
||||
|
||||
/**
|
||||
* Получить файлы генерации
|
||||
*/
|
||||
async findByGeneration(generationUuid, userId) {
|
||||
const query = `
|
||||
SELECT id, user_id, s3_key, original_filename, file_size, content_type, file_type, folder, generation_uuid, generation_step_id, created_at
|
||||
FROM uno_bff.user_files
|
||||
WHERE generation_uuid = $1 AND user_id = $2
|
||||
ORDER BY created_at ASC
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [generationUuid, userId]);
|
||||
return result.rows;
|
||||
},
|
||||
|
||||
/**
|
||||
* Получить файлы шага генерации
|
||||
*/
|
||||
async findByGenerationStep(generationUuid, stepId, userId) {
|
||||
const query = `
|
||||
SELECT f.id, f.user_id, f.s3_key, f.original_filename, f.file_size, f.content_type, f.file_type, f.folder, f.generation_uuid, f.generation_step_id, f.created_at
|
||||
FROM uno_bff.user_files f
|
||||
INNER JOIN uno_bff.generation_steps gs ON f.generation_step_id = gs.id
|
||||
WHERE f.generation_uuid = $1 AND gs.step_id = $2 AND f.user_id = $3
|
||||
ORDER BY f.created_at ASC
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [generationUuid, stepId, userId]);
|
||||
return result.rows;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user