server: allow fallback to default or last destination

This commit is contained in:
Jesse Chan
2020-11-13 02:16:11 +08:00
parent 7542ad51e1
commit aeefd6954d
5 changed files with 38 additions and 11 deletions

View File

@@ -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);
}),
);

View File

@@ -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());

View File

@@ -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(

View File

@@ -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();
}

View File

@@ -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]