Import source: backend/src/routes/analytics
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import express from 'express';
|
||||
import { HttpError } from '../middleware/errorHandler.js';
|
||||
import { store } from '../services/store.js';
|
||||
import { getSessionId } from '../middleware/session.js';
|
||||
import { getDailyBreakdown, getTopReferrers, recordEvent } from '../services/analytics.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
/**
|
||||
* GET /api/v1/files/:id/analytics
|
||||
* Retrieve detailed analytics for a specific file owned by the user.
|
||||
*/
|
||||
router.get('/files/:id/analytics', async (req, res, next) => {
|
||||
try {
|
||||
const sid = getSessionId(req);
|
||||
const db = await store.read();
|
||||
const file = db.files.find((f) => f.id === req.params.id && f.status === 'uploaded');
|
||||
|
||||
if (!file) {
|
||||
throw new HttpError(404, 'FILE_NOT_FOUND', 'File not found');
|
||||
}
|
||||
if (file.sessionId !== sid) {
|
||||
throw new HttpError(403, 'ACCESS_DENIED', 'Access denied to this file analytics');
|
||||
}
|
||||
|
||||
const dailyBreakdown = await getDailyBreakdown(file.linkId);
|
||||
const topReferrers = await getTopReferrers(file.linkId);
|
||||
|
||||
res.json({
|
||||
data: {
|
||||
fileId: file.id,
|
||||
linkId: file.linkId,
|
||||
views: file.views,
|
||||
downloads: file.downloads,
|
||||
dailyBreakdown,
|
||||
topReferrers,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* POST /api/v1/events
|
||||
* Record an event (view or download) on a shared link.
|
||||
*/
|
||||
router.post('/events', async (req, res, next) => {
|
||||
try {
|
||||
const { linkId, type } = req.body;
|
||||
|
||||
if (!linkId || !type || (type !== 'view' && type !== 'download')) {
|
||||
throw new HttpError(400, 'INVALID_INPUT', 'Missing or invalid linkId or type');
|
||||
}
|
||||
|
||||
const db = await store.read();
|
||||
const file = db.files.find((f) => f.linkId === linkId && f.status === 'uploaded');
|
||||
|
||||
if (!file) {
|
||||
throw new HttpError(404, 'LINK_NOT_FOUND', 'Active shared link not found');
|
||||
}
|
||||
|
||||
const ip = req.ip;
|
||||
const userAgent = req.headers['user-agent'] as string;
|
||||
const referrer = (req.headers.referer || req.headers.referrer) as string;
|
||||
|
||||
await recordEvent(linkId, type, ip, userAgent, referrer);
|
||||
|
||||
res.status(201).json({
|
||||
data: {
|
||||
status: 'recorded',
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
export { router as analyticsRouter };
|
||||
Reference in New Issue
Block a user