Initial production setup with dual-token auth
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Files Routes - SharePoint file operations
|
||||
*
|
||||
* Note: Most file operations go through /api/jobs/:id/files
|
||||
* This route provides additional file utilities
|
||||
*/
|
||||
|
||||
import { Hono } from 'hono';
|
||||
import { graphService } from '../services/graphService';
|
||||
import { tokenService } from '../services/tokenService';
|
||||
import { pocketbaseService } from '../services/pocketbaseService';
|
||||
import { authMiddleware, getUserId } from '../middleware/auth';
|
||||
import { BadRequestError, NotFoundError } from '../middleware/errorHandler';
|
||||
|
||||
const files = new Hono();
|
||||
|
||||
// All file routes require authentication
|
||||
files.use('/*', authMiddleware);
|
||||
|
||||
/**
|
||||
* GET /api/files
|
||||
* List files in a job's folder - requires jobId query param
|
||||
*/
|
||||
files.get('/', async (c) => {
|
||||
const userId = getUserId(c);
|
||||
const jobId = c.req.query('jobId');
|
||||
|
||||
if (!jobId) {
|
||||
throw new BadRequestError('jobId query parameter required');
|
||||
}
|
||||
|
||||
// Get job to find site/drive info
|
||||
const job = await pocketbaseService.getJob(jobId);
|
||||
if (!job) {
|
||||
throw new NotFoundError('Job not found');
|
||||
}
|
||||
|
||||
if (!job.site_id || !job.drive_id) {
|
||||
return c.json({ files: [] });
|
||||
}
|
||||
|
||||
const tokenResult = await tokenService.getToken(userId, 'graph');
|
||||
if (!tokenResult) {
|
||||
throw new BadRequestError('Graph token not available');
|
||||
}
|
||||
|
||||
const result = await graphService.getFiles(
|
||||
tokenResult.token,
|
||||
job.site_id,
|
||||
job.drive_id,
|
||||
job.folder_path
|
||||
);
|
||||
|
||||
return c.json({ files: result.files });
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/files/download-url
|
||||
* Get download URL for a file - requires jobId and fileId
|
||||
*/
|
||||
files.get('/download-url', async (c) => {
|
||||
const userId = getUserId(c);
|
||||
const jobId = c.req.query('jobId');
|
||||
const fileId = c.req.query('fileId');
|
||||
|
||||
if (!jobId || !fileId) {
|
||||
throw new BadRequestError('jobId and fileId query parameters required');
|
||||
}
|
||||
|
||||
// Get job to find site/drive info
|
||||
const job = await pocketbaseService.getJob(jobId);
|
||||
if (!job || !job.site_id || !job.drive_id) {
|
||||
throw new NotFoundError('Job not found or not configured for files');
|
||||
}
|
||||
|
||||
const tokenResult = await tokenService.getToken(userId, 'graph');
|
||||
if (!tokenResult) {
|
||||
throw new BadRequestError('Graph token not available');
|
||||
}
|
||||
|
||||
const url = await graphService.getFileDownloadUrl(
|
||||
tokenResult.token,
|
||||
job.site_id,
|
||||
job.drive_id,
|
||||
fileId
|
||||
);
|
||||
|
||||
if (!url) {
|
||||
throw new NotFoundError('File not found');
|
||||
}
|
||||
|
||||
return c.json({ url });
|
||||
});
|
||||
|
||||
/**
|
||||
* GET /api/files/search
|
||||
* Search files in a job's SharePoint site
|
||||
*/
|
||||
files.get('/search', async (c) => {
|
||||
const userId = getUserId(c);
|
||||
const jobId = c.req.query('jobId');
|
||||
const query = c.req.query('q');
|
||||
|
||||
if (!jobId || !query) {
|
||||
throw new BadRequestError('jobId and q query parameters required');
|
||||
}
|
||||
|
||||
// Get job to find site info
|
||||
const job = await pocketbaseService.getJob(jobId);
|
||||
if (!job || !job.site_id) {
|
||||
throw new NotFoundError('Job not found or not configured for files');
|
||||
}
|
||||
|
||||
const tokenResult = await tokenService.getToken(userId, 'graph');
|
||||
if (!tokenResult) {
|
||||
throw new BadRequestError('Graph token not available');
|
||||
}
|
||||
|
||||
const results = await graphService.searchFiles(tokenResult.token, job.site_id, query);
|
||||
|
||||
return c.json({ files: results });
|
||||
});
|
||||
|
||||
export default files;
|
||||
Reference in New Issue
Block a user