mirror of
https://github.com/zoriya/flood.git
synced 2025-12-06 07:16:18 +00:00
server: allow fallback to default or last destination
This commit is contained in:
@@ -252,7 +252,7 @@ describe('POST /api/torrents/add-files', () => {
|
||||
|
||||
await Promise.all(
|
||||
addedTorrents.map(async (torrent) => {
|
||||
expect(torrent.directory.startsWith(addTorrentByFileOptions.destination)).toBe(true);
|
||||
expect(torrent.directory.startsWith(addTorrentByFileOptions.destination as string)).toBe(true);
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -25,10 +25,33 @@ import {accessDeniedError, isAllowedPath, sanitizePath} from '../../util/fileUti
|
||||
import {getResponseFn, validationError} from '../../util/ajaxUtil';
|
||||
import {getTempPath} from '../../models/TemporaryStorage';
|
||||
|
||||
const getDestination = (destination: string): string | undefined => {
|
||||
const getDestination = async (
|
||||
services: Express.Request['services'],
|
||||
{destination}: {destination?: string},
|
||||
): Promise<string | undefined> => {
|
||||
let autoDestination = destination === '' ? undefined : destination;
|
||||
|
||||
// Use default destination of torrent client
|
||||
if (autoDestination == null) {
|
||||
const {directoryDefault} = (await services?.clientGatewayService?.getClientSettings().catch(() => undefined)) || {};
|
||||
autoDestination = directoryDefault;
|
||||
}
|
||||
|
||||
// Use last download destination
|
||||
if (autoDestination == null) {
|
||||
await services?.settingService.get('torrentDestination').then(
|
||||
({torrentDestination}) => {
|
||||
if (torrentDestination != null) {
|
||||
autoDestination = torrentDestination;
|
||||
}
|
||||
},
|
||||
() => undefined,
|
||||
);
|
||||
}
|
||||
|
||||
let sanitizedPath: string | null = null;
|
||||
try {
|
||||
sanitizedPath = sanitizePath(destination);
|
||||
sanitizedPath = sanitizePath(autoDestination);
|
||||
if (!isAllowedPath(sanitizedPath)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -75,7 +98,7 @@ router.get('/', (req, res) => {
|
||||
* @return {object} 200 - success response - application/json
|
||||
* @return {Error} 500 - failure response - application/json
|
||||
*/
|
||||
router.post<unknown, unknown, AddTorrentByURLOptions>('/add-urls', (req, res) => {
|
||||
router.post<unknown, unknown, AddTorrentByURLOptions>('/add-urls', async (req, res) => {
|
||||
const callback = getResponseFn(res);
|
||||
|
||||
const parsedResult = addTorrentByURLSchema.safeParse(req.body);
|
||||
@@ -87,7 +110,9 @@ router.post<unknown, unknown, AddTorrentByURLOptions>('/add-urls', (req, res) =>
|
||||
|
||||
const {urls, cookies, destination, tags, isBasePath, isCompleted, start} = parsedResult.data;
|
||||
|
||||
const finalDestination = getDestination(destination);
|
||||
const finalDestination = await getDestination(req.services, {
|
||||
destination,
|
||||
});
|
||||
|
||||
if (finalDestination == null) {
|
||||
callback(null, accessDeniedError());
|
||||
@@ -123,7 +148,7 @@ router.post<unknown, unknown, AddTorrentByURLOptions>('/add-urls', (req, res) =>
|
||||
* @return {object} 200 - success response - application/json
|
||||
* @return {Error} 500 - failure response - application/json
|
||||
*/
|
||||
router.post<unknown, unknown, AddTorrentByFileOptions>('/add-files', (req, res) => {
|
||||
router.post<unknown, unknown, AddTorrentByFileOptions>('/add-files', async (req, res) => {
|
||||
const callback = getResponseFn(res);
|
||||
|
||||
const parsedResult = addTorrentByFileSchema.safeParse(req.body);
|
||||
@@ -135,7 +160,9 @@ router.post<unknown, unknown, AddTorrentByFileOptions>('/add-files', (req, res)
|
||||
|
||||
const {files, destination, tags, isBasePath, isCompleted, start} = parsedResult.data;
|
||||
|
||||
const finalDestination = getDestination(destination);
|
||||
const finalDestination = await getDestination(req.services, {
|
||||
destination,
|
||||
});
|
||||
|
||||
if (finalDestination == null) {
|
||||
callback(null, accessDeniedError());
|
||||
|
||||
@@ -29,7 +29,7 @@ class SettingService extends BaseService<SettingServiceEvents> {
|
||||
return database;
|
||||
}
|
||||
|
||||
async get(property: string | null): Promise<Partial<FloodSettings>> {
|
||||
async get(property: keyof FloodSettings | null): Promise<Partial<FloodSettings>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.db
|
||||
.find(
|
||||
|
||||
@@ -43,7 +43,7 @@ export const isAllowedPath = (resolvedPath: string) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const sanitizePath = (input: string): string => {
|
||||
export const sanitizePath = (input?: string): string => {
|
||||
if (typeof input !== 'string') {
|
||||
throw accessDeniedError();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export const addTorrentByURLSchema = object({
|
||||
// Cookies to attach to requests, arrays of strings in the format "name=value" with domain as key
|
||||
cookies: record(array(string())).optional(),
|
||||
// Path of destination
|
||||
destination: string(),
|
||||
destination: string().optional(),
|
||||
// Tags
|
||||
tags: array(string()).optional(),
|
||||
// Whether destination is the base path [default: false]
|
||||
@@ -27,7 +27,7 @@ export const addTorrentByFileSchema = object({
|
||||
// Torrent files in base64
|
||||
files: array(string()).nonempty(),
|
||||
// Path of destination
|
||||
destination: string(),
|
||||
destination: string().optional(),
|
||||
// Tags
|
||||
tags: array(string()).optional(),
|
||||
// Whether destination is the base path [default: false]
|
||||
|
||||
Reference in New Issue
Block a user