Files
lagos-back/src/controllers/template.controller.ts
T
mstfyldzandClaude Sonnet 5 af5a03db92 feat: add template upload/download/delete endpoints
Belge Şablonları now stores real files: POST /api/templates/upload
(multer -> Supabase Storage under templates/<user>/, then a templates
row), GET /api/templates/:id/download-url (short-lived signed URL),
and DELETE /api/templates/:id. Mounted at /api/templates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-09 19:50:46 +03:00

104 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Response } from 'express';
import { supabase } from '../lib/supabase';
import { AuthenticatedRequest } from '../middleware/auth';
// Belge Şablonları: avukatın büro genelinde kullandığı dilekçe/evrak şablonları.
// Ayrı bir Storage bucket açmaya gerek kalmasın diye documents'ın kullandığı
// "case-documents" bucket'ı "templates/" öneki altında paylaşılıyor.
export const uploadTemplate = async (req: AuthenticatedRequest, res: Response) => {
try {
const file = req.file;
const userId = req.user?.id;
const { category, name, description } = req.body || {};
if (!file || !userId || !name) {
return res.status(400).json({ error: 'file ve name zorunludur.' });
}
const storagePath = `templates/${userId}/${Date.now()}_${file.originalname}`;
const { error: uploadError } = await supabase.storage
.from('case-documents')
.upload(storagePath, file.buffer, { contentType: file.mimetype });
if (uploadError) {
console.error('Template Storage Upload Error:', uploadError);
return res.status(500).json({ error: 'Şablon dosyası yüklenemedi.' });
}
const { data, error } = await supabase
.from('templates')
.insert([{
user_id: userId,
category: category || null,
name: String(name).slice(0, 200),
description: description || null,
storage_path: storagePath,
file_size: file.size,
mime_type: file.mimetype,
}])
.select()
.single();
if (error) throw error;
res.json({ template: data });
} catch (error: any) {
console.error('Upload Template Error:', error);
res.status(500).json({ error: error.message || 'Internal Server Error' });
}
};
// İndirme için kısa ömürlü bir imzalı URL üretir — bucket public değil.
export const getTemplateDownloadUrl = async (req: AuthenticatedRequest, res: Response) => {
try {
const { templateId } = req.params;
const userId = req.user?.id;
const { data: template, error: fetchError } = await supabase
.from('templates')
.select('storage_path, user_id')
.eq('id', templateId)
.single();
if (fetchError || !template) {
return res.status(404).json({ error: 'Şablon bulunamadı.' });
}
if (template.user_id !== userId) {
return res.status(403).json({ error: 'Bu şablona erişim yetkiniz yok.' });
}
const { data, error } = await supabase.storage
.from('case-documents')
.createSignedUrl(template.storage_path, 60);
if (error || !data) throw error || new Error('İmzalı URL üretilemedi.');
res.json({ url: data.signedUrl });
} catch (error: any) {
console.error('Get Template Download URL Error:', error);
res.status(500).json({ error: error.message || 'Internal Server Error' });
}
};
export const deleteTemplate = async (req: AuthenticatedRequest, res: Response) => {
try {
const { templateId } = req.params;
const userId = req.user?.id;
const { data: template, error: fetchError } = await supabase
.from('templates')
.select('storage_path, user_id')
.eq('id', templateId)
.single();
if (fetchError || !template) {
return res.status(404).json({ error: 'Şablon bulunamadı.' });
}
if (template.user_id !== userId) {
return res.status(403).json({ error: 'Bu şablonu silme yetkiniz yok.' });
}
await supabase.storage.from('case-documents').remove([template.storage_path]);
const { error } = await supabase.from('templates').delete().eq('id', templateId);
if (error) throw error;
res.json({ ok: true });
} catch (error: any) {
console.error('Delete Template Error:', error);
res.status(500).json({ error: error.message || 'Internal Server Error' });
}
};