- Fix missing response on successful addTripPhotos in deprecated immich route - Fix undefined tripId in asset proxy routes (use query param instead) - Fix unquoted SQL string in migration 68 (id = memories → id = 'memories') - Add missing return after error response in synology asset streaming
132 lines
5.1 KiB
TypeScript
132 lines
5.1 KiB
TypeScript
import express, { Request, Response } from 'express';
|
|
import { authenticate } from '../../middleware/auth';
|
|
import { AuthRequest } from '../../types';
|
|
import {
|
|
getSynologySettings,
|
|
updateSynologySettings,
|
|
getSynologyStatus,
|
|
testSynologyConnection,
|
|
listSynologyAlbums,
|
|
syncSynologyAlbumLink,
|
|
searchSynologyPhotos,
|
|
getSynologyAssetInfo,
|
|
streamSynologyAsset,
|
|
} from '../../services/memories/synologyService';
|
|
import { canAccessUserPhoto, handleServiceResult, fail, success } from '../../services/memories/helpersService';
|
|
|
|
const router = express.Router();
|
|
|
|
function _parseStringBodyField(value: unknown): string {
|
|
return String(value ?? '').trim();
|
|
}
|
|
|
|
function _parseNumberBodyField(value: unknown, fallback: number): number {
|
|
const parsed = Number(value);
|
|
return Number.isFinite(parsed) ? parsed : fallback;
|
|
}
|
|
|
|
router.get('/settings', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
handleServiceResult(res, await getSynologySettings(authReq.user.id));
|
|
});
|
|
|
|
router.put('/settings', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
const body = req.body as Record<string, unknown>;
|
|
const synology_url = _parseStringBodyField(body.synology_url);
|
|
const synology_username = _parseStringBodyField(body.synology_username);
|
|
const synology_password = _parseStringBodyField(body.synology_password);
|
|
|
|
if (!synology_url || !synology_username) {
|
|
handleServiceResult(res, fail('URL and username are required', 400));
|
|
}
|
|
else {
|
|
handleServiceResult(res, await updateSynologySettings(authReq.user.id, synology_url, synology_username, synology_password));
|
|
}
|
|
});
|
|
|
|
router.get('/status', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
handleServiceResult(res, await getSynologyStatus(authReq.user.id));
|
|
});
|
|
|
|
router.post('/test', authenticate, async (req: Request, res: Response) => {
|
|
const body = req.body as Record<string, unknown>;
|
|
const synology_url = _parseStringBodyField(body.synology_url);
|
|
const synology_username = _parseStringBodyField(body.synology_username);
|
|
const synology_password = _parseStringBodyField(body.synology_password);
|
|
|
|
if (!synology_url || !synology_username || !synology_password) {
|
|
const missingFields: string[] = [];
|
|
if (!synology_url) missingFields.push('URL');
|
|
if (!synology_username) missingFields.push('Username');
|
|
if (!synology_password) missingFields.push('Password');
|
|
handleServiceResult(res, success({ connected: false, error: `${missingFields.join(', ')} ${missingFields.length > 1 ? 'are' : 'is'} required` }));
|
|
}
|
|
else{
|
|
handleServiceResult(res, await testSynologyConnection(synology_url, synology_username, synology_password));
|
|
}
|
|
});
|
|
|
|
router.get('/albums', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
handleServiceResult(res, await listSynologyAlbums(authReq.user.id));
|
|
});
|
|
|
|
router.post('/trips/:tripId/album-links/:linkId/sync', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
const { tripId, linkId } = req.params;
|
|
const sid = req.headers['x-socket-id'] as string;
|
|
|
|
handleServiceResult(res, await syncSynologyAlbumLink(authReq.user.id, tripId, linkId, sid));
|
|
});
|
|
|
|
router.post('/search', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
const body = req.body as Record<string, unknown>;
|
|
const from = _parseStringBodyField(body.from);
|
|
const to = _parseStringBodyField(body.to);
|
|
const offset = _parseNumberBodyField(body.offset, 0);
|
|
const limit = _parseNumberBodyField(body.limit, 100);
|
|
|
|
handleServiceResult(res, await searchSynologyPhotos(
|
|
authReq.user.id,
|
|
from || undefined,
|
|
to || undefined,
|
|
offset,
|
|
limit,
|
|
));
|
|
});
|
|
|
|
router.get('/assets/:tripId/:photoId/:ownerId/info', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
const { tripId, photoId, ownerId } = req.params;
|
|
|
|
if (!canAccessUserPhoto(authReq.user.id, Number(ownerId), tripId, photoId, 'synologyphotos')) {
|
|
handleServiceResult(res, fail('You don\'t have access to this photo', 403));
|
|
}
|
|
else {
|
|
handleServiceResult(res, await getSynologyAssetInfo(authReq.user.id, photoId, Number(ownerId)));
|
|
}
|
|
});
|
|
|
|
router.get('/assets/:tripId/:photoId/:ownerId/:kind', authenticate, async (req: Request, res: Response) => {
|
|
const authReq = req as AuthRequest;
|
|
const { tripId, photoId, ownerId, kind } = req.params;
|
|
const { size = "sm" } = req.query;
|
|
|
|
if (kind !== 'thumbnail' && kind !== 'original') {
|
|
return handleServiceResult(res, fail('Invalid asset kind', 400));
|
|
}
|
|
|
|
if (!canAccessUserPhoto(authReq.user.id, Number(ownerId), tripId, photoId, 'synologyphotos')) {
|
|
handleServiceResult(res, fail('You don\'t have access to this photo', 403));
|
|
}
|
|
else{
|
|
await streamSynologyAsset(res, authReq.user.id, Number(ownerId), photoId, kind as 'thumbnail' | 'original', String(size));
|
|
}
|
|
|
|
});
|
|
|
|
export default router;
|