Hide downloads module sensitive data

Working thowards #259
This commit is contained in:
ajnart
2022-07-22 17:18:33 +02:00
parent a4defd330c
commit 81a7789f9c
5 changed files with 93 additions and 46 deletions

View File

@@ -15,6 +15,7 @@ import { useEffect, useState } from 'react';
import axios from 'axios'; import axios from 'axios';
import { NormalizedTorrent } from '@ctrl/shared-torrent'; import { NormalizedTorrent } from '@ctrl/shared-torrent';
import { useViewportSize } from '@mantine/hooks'; import { useViewportSize } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications';
import { IModule } from '../modules'; import { IModule } from '../modules';
import { useConfig } from '../../../tools/state'; import { useConfig } from '../../../tools/state';
import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem'; import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem';
@@ -52,12 +53,28 @@ export default function DownloadComponent() {
useEffect(() => { useEffect(() => {
setIsLoading(true); setIsLoading(true);
if (downloadServices.length === 0) return; if (downloadServices.length === 0) return;
setSafeInterval(() => { const interval = setSafeInterval(() => {
// Send one request with each download service inside // Send one request with each download service inside
axios.post('/api/modules/downloads', { config }).then((response) => { axios
setTorrents(response.data); .post('/api/modules/downloads')
setIsLoading(false); .then((response) => {
}); setTorrents(response.data);
setIsLoading(false);
})
.catch((error) => {
setTorrents([]);
// eslint-disable-next-line no-console
console.error('Error while fetching torrents', error.response.data);
setIsLoading(false);
clearInterval(interval);
showNotification({
title: 'Error fetching torrents',
autoClose: false,
color: 'red',
message:
'Please check your config for any potential errors, check the console for more info',
});
});
}, 5000); }, 5000);
}, []); }, []);

View File

@@ -6,6 +6,7 @@ import { NormalizedTorrent } from '@ctrl/shared-torrent';
import { linearGradientDef } from '@nivo/core'; import { linearGradientDef } from '@nivo/core';
import { Datum, ResponsiveLine } from '@nivo/line'; import { Datum, ResponsiveLine } from '@nivo/line';
import { useListState } from '@mantine/hooks'; import { useListState } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications';
import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem'; import { AddItemShelfButton } from '../../AppShelf/AddAppShelfItem';
import { useConfig } from '../../../tools/state'; import { useConfig } from '../../../tools/state';
import { humanFileSize } from '../../../tools/humanFileSize'; import { humanFileSize } from '../../../tools/humanFileSize';
@@ -43,10 +44,25 @@ export default function TotalDownloadsComponent() {
const totalUploadSpeed = torrents.reduce((acc, torrent) => acc + torrent.uploadSpeed, 0); const totalUploadSpeed = torrents.reduce((acc, torrent) => acc + torrent.uploadSpeed, 0);
useEffect(() => { useEffect(() => {
if (downloadServices.length === 0) return; if (downloadServices.length === 0) return;
setSafeInterval(() => { const interval = setSafeInterval(() => {
axios.post('/api/modules/downloads', { config }).then((response) => { axios
setTorrents(response.data); .post('/api/modules/downloads')
}); .then((response) => {
setTorrents(response.data);
})
.catch((error) => {
setTorrents([]);
// eslint-disable-next-line no-console
console.error('Error while fetching torrents', error.response.data);
clearInterval(interval);
showNotification({
title: 'Error fetching torrents',
autoClose: false,
color: 'red',
message:
'Please check your config for any potential errors, check the console for more info',
});
});
}, 1000); }, 1000);
}, [config.services]); }, [config.services]);

View File

@@ -1,11 +1,14 @@
// This interface is to be used in all the modules of the project // This interface is to be used in all the modules of the project
// Each module should have its own interface and call the following function: // Each module should have its own interface and call the following function:
// TODO: Add a function to register a module // TODO: Add a function to register a module
import { TablerIcon } from '@tabler/icons';
// Note: Maybe use context to keep track of the modules // Note: Maybe use context to keep track of the modules
export interface IModule { export interface IModule {
title: string; title: string;
description: string; description: string;
icon: React.ReactNode; icon: TablerIcon;
component: React.ComponentType; component: React.ComponentType;
options?: Option; options?: Option;
} }

View File

@@ -2,12 +2,15 @@ import { Deluge } from '@ctrl/deluge';
import { QBittorrent } from '@ctrl/qbittorrent'; import { QBittorrent } from '@ctrl/qbittorrent';
import { NormalizedTorrent } from '@ctrl/shared-torrent'; import { NormalizedTorrent } from '@ctrl/shared-torrent';
import { Transmission } from '@ctrl/transmission'; import { Transmission } from '@ctrl/transmission';
import { getCookie } from 'cookies-next';
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiRequest, NextApiResponse } from 'next';
import { getConfig } from '../../../tools/getConfig';
import { Config } from '../../../tools/types'; import { Config } from '../../../tools/types';
async function Post(req: NextApiRequest, res: NextApiResponse) { async function Post(req: NextApiRequest, res: NextApiResponse) {
// Get the type of service from the request url // Get the type of service from the request url
const { config }: { config: Config } = req.body; const configName = getCookie('config-name', { req });
const { config }: { config: Config } = getConfig(configName?.toString() ?? 'default').props;
const qBittorrentServices = config.services.filter((service) => service.type === 'qBittorrent'); const qBittorrentServices = config.services.filter((service) => service.type === 'qBittorrent');
const delugeServices = config.services.filter((service) => service.type === 'Deluge'); const delugeServices = config.services.filter((service) => service.type === 'Deluge');
const transmissionServices = config.services.filter((service) => service.type === 'Transmission'); const transmissionServices = config.services.filter((service) => service.type === 'Transmission');
@@ -20,40 +23,44 @@ async function Post(req: NextApiRequest, res: NextApiResponse) {
message: 'Missing services', message: 'Missing services',
}); });
} }
await Promise.all( try {
qBittorrentServices.map((service) => await Promise.all(
new QBittorrent({ qBittorrentServices.map((service) =>
baseUrl: service.url, new QBittorrent({
username: service.username, baseUrl: service.url,
password: service.password, username: service.username,
}) password: service.password,
.getAllData() })
.then((e) => torrents.push(...e.torrents)) .getAllData()
) .then((e) => torrents.push(...e.torrents))
); )
await Promise.all( );
delugeServices.map((service) => await Promise.all(
new Deluge({ delugeServices.map((service) =>
baseUrl: service.url, new Deluge({
password: 'password' in service ? service.password : '', baseUrl: service.url,
}) password: 'password' in service ? service.password : '',
.getAllData() })
.then((e) => torrents.push(...e.torrents)) .getAllData()
) .then((e) => torrents.push(...e.torrents))
); )
// Map transmissionServices );
await Promise.all( // Map transmissionServices
transmissionServices.map((service) => await Promise.all(
new Transmission({ transmissionServices.map((service) =>
baseUrl: service.url, new Transmission({
username: 'username' in service ? service.username : '', baseUrl: service.url,
password: 'password' in service ? service.password : '', username: 'username' in service ? service.username : '',
}) password: 'password' in service ? service.password : '',
.getAllData() })
.then((e) => torrents.push(...e.torrents)) .getAllData()
) .then((e) => torrents.push(...e.torrents))
); )
res.status(200).json(torrents); );
} catch (e: any) {
return res.status(401).json(e);
}
return res.status(200).json(torrents);
} }
export default async (req: NextApiRequest, res: NextApiResponse) => { export default async (req: NextApiRequest, res: NextApiResponse) => {

View File

@@ -14,7 +14,11 @@ export function getConfig(name: string) {
settings: { settings: {
searchUrl: 'https://www.google.com/search?q=', searchUrl: 'https://www.google.com/search?q=',
}, },
modules: {}, modules: {
'Search Bar': {
enabled: true,
},
},
}, },
}, },
}; };