Finished settings page
@ -90,7 +90,8 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
|
||||
peer_addr = buf;
|
||||
}
|
||||
|
||||
if (IsConnectionAllowed(peer_addr))
|
||||
std::string denialReason;
|
||||
if (IsConnectionAllowed(peer_addr, denialReason))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -126,7 +127,7 @@ void HttpServer::EventHandler(mg_connection* pNc, int ev, void* p)
|
||||
else // Client is not allowed, serve error json
|
||||
{
|
||||
Json j;
|
||||
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, "Only localhost allowed!"));
|
||||
j.CloneFrom(RestResponseTemplates::GetByCode(UNAUTHORIZED, denialReason));
|
||||
ServeStringToConnection(pNc, j.Render(), UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
@ -200,13 +201,17 @@ void HttpServer::ServeDownloadeableResource(mg_connection* pNc, int ev, void* p,
|
||||
return;
|
||||
}
|
||||
|
||||
bool HttpServer::IsConnectionAllowed(std::string peer_address)
|
||||
bool HttpServer::IsConnectionAllowed(std::string peer_address, std::string& denialReason)
|
||||
{
|
||||
// Localhost is always allowed!
|
||||
if (peer_address == "127.0.0.1") return true;
|
||||
|
||||
// Peer is not localhost, but only localhost is allowed!
|
||||
else if (XGConfig::access.only_allow_localhost) return false;
|
||||
else if (XGConfig::access.only_allow_localhost)
|
||||
{
|
||||
denialReason = "Only localhost allowed!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Let's check if the whitelist is active
|
||||
else if (XGConfig::access.enable_whitelist)
|
||||
@ -219,6 +224,7 @@ bool HttpServer::IsConnectionAllowed(std::string peer_address)
|
||||
}
|
||||
|
||||
// Whitelist is enabled, but peer is NOT whitelisted
|
||||
denialReason = "Not whitelisted!";
|
||||
return false;
|
||||
}
|
||||
else // Whitelist is NOT enabled and only_allow_localhost is FALSE!
|
||||
@ -227,6 +233,7 @@ bool HttpServer::IsConnectionAllowed(std::string peer_address)
|
||||
}
|
||||
|
||||
// Should never come to this point
|
||||
denialReason = "Access denied";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ namespace Rest
|
||||
static void ServeStringToConnection(struct mg_connection* c, std::string str, int httpStatusCode = 200);
|
||||
static std::string FixUnterminatedString(const char* cstr, const std::size_t len);
|
||||
|
||||
static bool IsConnectionAllowed(std::string peer_address);
|
||||
static bool IsConnectionAllowed(std::string peer_address, std::string& denialReason);
|
||||
|
||||
|
||||
struct mg_mgr* pMgr;
|
||||
|
@ -43,6 +43,7 @@ bool RestQueryHandler::ProcessQuery(const std::string clientAdress, const Json&
|
||||
else if (requestName == "update_dep_youtubedl") return UpdateYoutubeDL(requestBody, responseBody, responseCode);
|
||||
else if (requestName == "remove_download_entry") return RemoveDownloadEntry(requestBody, responseBody, responseCode);
|
||||
else if (requestName == "update_config") return UpdateConfig(requestBody, responseBody, responseCode);
|
||||
else if (requestName == "reset_config_to_default_values") return ResetConfigDefaults(requestBody, responseBody, responseCode);
|
||||
|
||||
|
||||
|
||||
@ -440,7 +441,11 @@ bool RestQueryHandler::RemoveDownloadEntry(const JsonBlock& request, JsonBlock&
|
||||
|
||||
bool RestQueryHandler::UpdateConfig(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
|
||||
{
|
||||
if (ValidateField("config", JDType::JSON, request, responseBody))
|
||||
responseCode = OK;
|
||||
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
|
||||
|
||||
JsonBlock dummy;
|
||||
if (ValidateField("config", JDType::JSON, request, dummy))
|
||||
{
|
||||
bool prevStateConsole = XGConfig::general.show_console;
|
||||
XGConfig::LoadFromJson(request.Get("config").AsJson);
|
||||
@ -456,19 +461,38 @@ bool RestQueryHandler::UpdateConfig(const JsonBlock& request, JsonBlock& respons
|
||||
log->Flush();
|
||||
XGConfig::Save();
|
||||
|
||||
responseBody.Set("message") = "Updated no settings";
|
||||
responseBody.Set("message") = "Updated settings";
|
||||
}
|
||||
else
|
||||
{
|
||||
responseBody.Set("message") = "Updated no settings";
|
||||
}
|
||||
|
||||
responseCode = OK;
|
||||
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
|
||||
responseBody.Set("settings") = XGConfig::GetSavefileBuffer();
|
||||
responseBody.Set("config") = XGConfig::GetSavefileBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RestQueryHandler::ResetConfigDefaults(const JsonBlock& request, JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode)
|
||||
{
|
||||
log->cout << "Reset config values to default...";
|
||||
log->Flush();
|
||||
|
||||
bool prevStateConsole = XGConfig::general.show_console;
|
||||
XGConfig::LoadDefaultValues();
|
||||
XGConfig::Save();
|
||||
// Update console, if necessary
|
||||
if (XGConfig::general.show_console != prevStateConsole)
|
||||
{
|
||||
if (XGConfig::general.show_console) ConsoleManager::ShowConsole();
|
||||
else ConsoleManager::HideConsole();
|
||||
}
|
||||
|
||||
responseCode = OK;
|
||||
responseBody.CloneFrom(RestResponseTemplates::GetByCode(OK));
|
||||
responseBody.Set("message") = "Reset config to default...";
|
||||
responseBody.Set("config") = XGConfig::GetSavefileBuffer();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -35,6 +35,7 @@ namespace Rest
|
||||
static bool UpdateYoutubeDL(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
|
||||
static bool RemoveDownloadEntry(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
|
||||
static bool UpdateConfig(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
|
||||
static bool ResetConfigDefaults(const JasonPP::JsonBlock& request, JasonPP::JsonBlock& responseBody, HTTP_STATUS_CODE& responseCode);
|
||||
|
||||
static bool ValidateField(const std::string name, const JasonPP::JDType type, const JasonPP::Json& checkThat, JasonPP::JsonBlock& putErrorResponseHere);
|
||||
|
||||
|
@ -6,7 +6,7 @@ void XGConfig::PreInit()
|
||||
{
|
||||
log = new ::Logging::Logger("Config");
|
||||
|
||||
InitializeDefaultValues();
|
||||
LoadDefaultValues();
|
||||
|
||||
if (FileSystem::Exists(XGCONFIG_FILE))
|
||||
{
|
||||
@ -30,7 +30,7 @@ bool XGConfig::IsJsonFieldValid(const JsonBlock& json, const std::string key, co
|
||||
return ((json.DoesShorthandExist(key)) && (json.ShorthandGet(key).GetDataType() == type));
|
||||
}
|
||||
|
||||
void XGConfig::InitializeDefaultValues()
|
||||
void XGConfig::LoadDefaultValues()
|
||||
{
|
||||
httpServer.port = "6969";
|
||||
httpServer.polling_rate = 100;
|
||||
@ -46,11 +46,14 @@ void XGConfig::InitializeDefaultValues()
|
||||
|
||||
general.show_console = true;
|
||||
|
||||
access.only_allow_localhost = true;
|
||||
access.enable_whitelist = true;
|
||||
access.only_allow_localhost = false;
|
||||
access.enable_whitelist = false;
|
||||
access.whitelist = std::vector<std::string>();
|
||||
access.whitelist.push_back("127.0.0.1"); // Add localhost to whitelist
|
||||
|
||||
savefileBuffer.Clear();
|
||||
savefileBuffer.CloneFrom(CreateJson());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
static void PostExit();
|
||||
|
||||
static void LoadFromJson(const JasonPP::JsonBlock& json);
|
||||
static void LoadDefaultValues();
|
||||
|
||||
static XGConfig::HttpServer httpServer;
|
||||
static XGConfig::Logging logging;
|
||||
@ -60,7 +61,6 @@ private:
|
||||
static JasonPP::JsonBlock savefileBuffer;
|
||||
|
||||
static bool IsJsonFieldValid(const JasonPP::JsonBlock& json, const std::string key, const JasonPP::JDType type);
|
||||
static void InitializeDefaultValues();
|
||||
static JasonPP::JsonBlock CreateJson();
|
||||
static void Load();
|
||||
};
|
||||
|
@ -1,9 +1,9 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tubio - Video downloader</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><link data-n-head="1" rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="preload" href="/_nuxt/39f2f1c.js" as="script"><link rel="preload" href="/_nuxt/b2cccba.js" as="script"><link rel="preload" href="/_nuxt/d0a20ff.js" as="script"><link rel="preload" href="/_nuxt/ffabd53.js" as="script">
|
||||
<title>Tubio - Video downloader</title><meta data-n-head="1" charset="utf-8"><meta data-n-head="1" name="viewport" content="width=device-width,initial-scale=1"><meta data-n-head="1" data-hid="description" name="description" content=""><meta data-n-head="1" name="msapplication-TileColor" content="#031934"><meta data-n-head="1" name="theme-color" content="#031934"><link data-n-head="1" rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"><link data-n-head="1" rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"><link data-n-head="1" rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"><link data-n-head="1" rel="manifest" href="/site.webmanifest"><link data-n-head="1" rel="mask-icon" href="/safari-pinned-tab.svg" color="#031934"><link rel="preload" href="/_nuxt/b0ecca0.js" as="script"><link rel="preload" href="/_nuxt/2b1a86c.js" as="script"><link rel="preload" href="/_nuxt/d429197.js" as="script"><link rel="preload" href="/_nuxt/7e93adc.js" as="script">
|
||||
</head>
|
||||
<body>
|
||||
<div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div><script>window.__NUXT__={config:{},staticAssetsBase:"/_nuxt/static/1601497777"}</script>
|
||||
<script src="/_nuxt/39f2f1c.js"></script><script src="/_nuxt/b2cccba.js"></script><script src="/_nuxt/d0a20ff.js"></script><script src="/_nuxt/ffabd53.js"></script></body>
|
||||
<div id="__nuxt"><style>#nuxt-loading{background:#fff;visibility:hidden;opacity:0;position:absolute;left:0;right:0;top:0;bottom:0;display:flex;justify-content:center;align-items:center;flex-direction:column;animation:nuxtLoadingIn 10s ease;-webkit-animation:nuxtLoadingIn 10s ease;animation-fill-mode:forwards;overflow:hidden}@keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}@-webkit-keyframes nuxtLoadingIn{0%{visibility:hidden;opacity:0}20%{visibility:visible;opacity:0}100%{visibility:visible;opacity:1}}#nuxt-loading>div,#nuxt-loading>div:after{border-radius:50%;width:5rem;height:5rem}#nuxt-loading>div{font-size:10px;position:relative;text-indent:-9999em;border:.5rem solid #f5f5f5;border-left:.5rem solid #000;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation:nuxtLoading 1.1s infinite linear;animation:nuxtLoading 1.1s infinite linear}#nuxt-loading.error>div{border-left:.5rem solid #ff4500;animation-duration:5s}@-webkit-keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes nuxtLoading{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}</style><script>window.addEventListener("error",function(){var e=document.getElementById("nuxt-loading");e&&(e.className+=" error")})</script><div id="nuxt-loading" aria-live="polite" role="status"><div>Loading...</div></div></div><script>window.__NUXT__={config:{},staticAssetsBase:"/_nuxt/static/1601654949"}</script>
|
||||
<script src="/_nuxt/b0ecca0.js"></script><script src="/_nuxt/2b1a86c.js"></script><script src="/_nuxt/d429197.js"></script><script src="/_nuxt/7e93adc.js"></script></body>
|
||||
</html>
|
||||
|
@ -1 +0,0 @@
|
||||
!function(e){function r(data){for(var r,n,f=data[0],l=data[1],d=data[2],i=0,h=[];i<f.length;i++)n=f[i],Object.prototype.hasOwnProperty.call(o,n)&&o[n]&&h.push(o[n][0]),o[n]=0;for(r in l)Object.prototype.hasOwnProperty.call(l,r)&&(e[r]=l[r]);for(v&&v(data);h.length;)h.shift()();return c.push.apply(c,d||[]),t()}function t(){for(var e,i=0;i<c.length;i++){for(var r=c[i],t=!0,n=1;n<r.length;n++){var l=r[n];0!==o[l]&&(t=!1)}t&&(c.splice(i--,1),e=f(f.s=r[0]))}return e}var n={},o={4:0},c=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var c,script=document.createElement("script");script.charset="utf-8",script.timeout=120,f.nc&&script.setAttribute("nonce",f.nc),script.src=function(e){return f.p+""+{2:"8f02b2f",3:"56889ef"}[e]+".js"}(e);var l=new Error;c=function(r){script.onerror=script.onload=null,clearTimeout(d);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;l.message="Loading chunk "+e+" failed.\n("+n+": "+c+")",l.name="ChunkLoadError",l.type=n,l.request=c,t[1](l)}o[e]=void 0}};var d=setTimeout((function(){c({type:"timeout",target:script})}),12e4);script.onerror=script.onload=c,document.head.appendChild(script)}return Promise.all(r)},f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(object,e){return Object.prototype.hasOwnProperty.call(object,e)},f.p="/_nuxt/",f.oe=function(e){throw console.error(e),e};var l=window.webpackJsonp=window.webpackJsonp||[],d=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var v=d;t()}([]);
|
1
Tubio/frontend/_nuxt/7e93adc.js
Normal file
1
Tubio/frontend/_nuxt/b0ecca0.js
Normal file
@ -0,0 +1 @@
|
||||
!function(e){function r(data){for(var r,n,l=data[0],f=data[1],d=data[2],i=0,h=[];i<l.length;i++)n=l[i],Object.prototype.hasOwnProperty.call(o,n)&&o[n]&&h.push(o[n][0]),o[n]=0;for(r in f)Object.prototype.hasOwnProperty.call(f,r)&&(e[r]=f[r]);for(v&&v(data);h.length;)h.shift()();return c.push.apply(c,d||[]),t()}function t(){for(var e,i=0;i<c.length;i++){for(var r=c[i],t=!0,n=1;n<r.length;n++){var f=r[n];0!==o[f]&&(t=!1)}t&&(c.splice(i--,1),e=l(l.s=r[0]))}return e}var n={},o={4:0},c=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var c,script=document.createElement("script");script.charset="utf-8",script.timeout=120,l.nc&&script.setAttribute("nonce",l.nc),script.src=function(e){return l.p+""+{2:"d4b440d",3:"d7b3322"}[e]+".js"}(e);var f=new Error;c=function(r){script.onerror=script.onload=null,clearTimeout(d);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),c=r&&r.target&&r.target.src;f.message="Loading chunk "+e+" failed.\n("+n+": "+c+")",f.name="ChunkLoadError",f.type=n,f.request=c,t[1](f)}o[e]=void 0}};var d=setTimeout((function(){c({type:"timeout",target:script})}),12e4);script.onerror=script.onload=c,document.head.appendChild(script)}return Promise.all(r)},l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(object,e){return Object.prototype.hasOwnProperty.call(object,e)},l.p="/_nuxt/",l.oe=function(e){throw console.error(e),e};var f=window.webpackJsonp=window.webpackJsonp||[],d=f.push.bind(f);f.push=r,f=f.slice();for(var i=0;i<f.length;i++)r(f[i]);var v=d;t()}([]);
|
1
Tubio/frontend/_nuxt/d4b440d.js
Normal file
1
Tubio/frontend/_nuxt/d7b3322.js
Normal file
1
Tubio/frontend/_nuxt/static/1601654949/settings/state.js
Normal file
@ -0,0 +1 @@
|
||||
window.__NUXT__={staticAssetsBase:"\u002F_nuxt\u002Fstatic\u002F1601654949",layout:"default",error:null,state:{diskUsage:{usage:{}},dlcache:{cache:[]},logs:{logs:[]},serverOs:{os_name:""},settings:{config:{}}},serverRendered:true,routePath:"\u002Fsettings",config:{}};
|
1
Tubio/frontend/_nuxt/static/1601654949/state.js
Normal file
@ -0,0 +1 @@
|
||||
window.__NUXT__={staticAssetsBase:"\u002F_nuxt\u002Fstatic\u002F1601654949",layout:"default",error:null,state:{diskUsage:{usage:{}},dlcache:{cache:[]},logs:{logs:[]},serverOs:{os_name:""},settings:{config:{}}},serverRendered:true,routePath:"\u002F",config:{}};
|
BIN
Tubio/frontend/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
Tubio/frontend/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
Tubio/frontend/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
9
Tubio/frontend/browserconfig.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
Tubio/frontend/favicon-16x16.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
Tubio/frontend/favicon-32x32.png
Normal file
After Width: | Height: | Size: 948 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB |
BIN
Tubio/frontend/mstile-150x150.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
15
Tubio/frontend/safari-pinned-tab.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="595.000000pt" height="595.000000pt" viewBox="0 0 595.000000 595.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,595.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 2975 l0 -2415 2975 0 2975 0 0 2415 0 2415 -2975 0 -2975 0 0
|
||||
-2415z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 603 B |
19
Tubio/frontend/site.webmanifest
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
@ -30,9 +30,9 @@ export default {
|
||||
|
||||
mounted() {
|
||||
const that = this;
|
||||
this.$store.dispatch("dlcache/update", this);
|
||||
this.$store.dispatch("dlcache/update");
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("dlcache/update", that);
|
||||
that.$store.dispatch("dlcache/update");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ export default {
|
||||
|
||||
mounted() {
|
||||
const that = this;
|
||||
this.$store.dispatch("logs/update", this);
|
||||
this.$store.dispatch("logs/update");
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("logs/update", that);
|
||||
that.$store.dispatch("logs/update");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
@ -16,10 +16,16 @@ export default {
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: '' }
|
||||
{ hid: 'description', name: 'description', content: '' },
|
||||
{ name: 'msapplication-TileColor', content: '#031934' },
|
||||
{ name: 'theme-color', content: '#031934' },
|
||||
],
|
||||
link: [
|
||||
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
|
||||
{ rel: 'apple-touch-icon', sizes: "180x180", href: '/apple-touch-icon.png' },
|
||||
{ rel: 'icon', type: "image/png", sizes: "32x32", href: '/favicon-32x32.png' },
|
||||
{ rel: 'icon', type: "image/png", sizes: "16x16", href: '/favicon-16x16.png' },
|
||||
{ rel: 'manifest', href: '/site.webmanifest' },
|
||||
{ rel: 'mask-icon', href: '/safari-pinned-tab.svg', color: '#031934' },
|
||||
]
|
||||
},
|
||||
|
||||
|
@ -2,13 +2,20 @@
|
||||
<div>
|
||||
|
||||
<div class="hidden md:block">
|
||||
<Spacer height="0.5em" m_height="1em" />
|
||||
<Spacer height="0" m_height="1em" />
|
||||
<Logo class="logo mt-4" />
|
||||
<Spacer height="2em" m_height="2em" />
|
||||
</div>
|
||||
|
||||
<div class="flex flex-row flex-wrap md:flex-no-wrap input-flex justify-between md:justify-center">
|
||||
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full" type="url" name="video_url" id="video_url" ref="video_url" placeholder="video-url">
|
||||
<input class="flex-grow md:mr-4 mb-2 md:mb-0 w-full"
|
||||
type="url"
|
||||
name="video_url"
|
||||
id="video_url"
|
||||
ref="video_url"
|
||||
placeholder="video-url"
|
||||
v-on:keydown="keyMonitor"
|
||||
/>
|
||||
|
||||
<div class="w-full md:hidden" />
|
||||
|
||||
@ -63,7 +70,13 @@ export default {
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
keyMonitor: function(event) {
|
||||
if (event.key == "Enter") {
|
||||
this.downloadButtonClicked();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -9,24 +9,68 @@
|
||||
|
||||
<div class="w-full lg:w-1/2 border-right lg:pr-3">
|
||||
|
||||
<div v-if="typeof(getSettings().general) != 'undefined'">
|
||||
<div v-if="serverOs === 'Windows'" class="option toggle flex justify-between items-center">
|
||||
<p>Show console</p>
|
||||
<Toggle :isOn="false"/>
|
||||
<div v-on:click="setSettings_toggle_showConsole">
|
||||
<Toggle
|
||||
:isOn="getSettings().general.show_console"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Max speed</p>
|
||||
<input type="text" id="max_speed" name="max_speed" placeholder="100M">
|
||||
<input
|
||||
type="text"
|
||||
id="max_speed"
|
||||
name="max_speed"
|
||||
placeholder="100M"
|
||||
v-model="getSettings().downloader.max_dlrate_per_thread"
|
||||
v-on:focusout="setSettings_pushCurrentStore"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="option text narrow flex justify-between w-full items-center">
|
||||
<p class="mr-3">Download threads</p>
|
||||
<input type="text" id="max_threads" name="max_threads" placeholder="10">
|
||||
<input
|
||||
type="number"
|
||||
id="max_threads"
|
||||
name="max_threads"
|
||||
placeholder="10"
|
||||
v-model.number="getSettings().downloader.num_threads"
|
||||
v-on:focusout="setSettings_pushCurrentStore"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="option toggle flex justify-between items-center">
|
||||
<p>Only allow localhost</p>
|
||||
<div v-on:click="setSettings_toggle_onlyAllowLocalhost">
|
||||
<Toggle
|
||||
:isOn="getSettings().access.only_allow_localhost"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option toggle flex justify-between items-center">
|
||||
<p>Enable whitelist</p>
|
||||
<Toggle :isOn="false"/>
|
||||
<div v-on:click="setSettings_toggle_enableWhitelist">
|
||||
<Toggle
|
||||
:isOn="getSettings().access.enable_whitelist"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Spacer height="2em" />
|
||||
<div v-if="getSettings().access.enable_whitelist">
|
||||
<h2>Whitelist</h2>
|
||||
<textarea class="mt-2 w-full" ref="whitelist_input" v-on:input="whitelistInputJsonSyntaxCheck" />
|
||||
<div class="flex w-full">
|
||||
<div class="button button--small button--nowarn mt-2 mr-2" v-on:click="saveWhitelist" ref="button_saveWhitelist">Save whitelist</div>
|
||||
<div class="button button--small button--nowarn mt-2" v-on:click="updateWhitelist">Update whitelist</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@ -68,6 +112,7 @@
|
||||
</div>
|
||||
<div class="flex flex-col ml-1">
|
||||
<div class="button" v-on:click="killServer">Kill server</div>
|
||||
<div class="button mt-2" v-on:click="resetToDefaults">Reset to defaults</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -112,7 +157,7 @@ export default {
|
||||
},
|
||||
serverOs: function() {
|
||||
return this.$store.state.serverOs.os_name;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
@ -163,11 +208,112 @@ export default {
|
||||
});
|
||||
return;
|
||||
},
|
||||
|
||||
resetToDefaults: function() {
|
||||
this.$store.dispatch("settings/resetToDefaults");
|
||||
},
|
||||
|
||||
getSettings: function() {
|
||||
return this.$store.state.settings.config;
|
||||
},
|
||||
|
||||
setSettings_toggle_showConsole: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.general.show_console = !curConf.general.show_console;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
return;
|
||||
},
|
||||
setSettings_toggle_onlyAllowLocalhost: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.only_allow_localhost = !curConf.access.only_allow_localhost;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
return;
|
||||
},
|
||||
setSettings_toggle_enableWhitelist: function() {
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.enable_whitelist = !curConf.access.enable_whitelist;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
|
||||
if (curConf.access.enable_whitelist) {
|
||||
this.whitelistToInputfield();
|
||||
}
|
||||
return;
|
||||
},
|
||||
setSettings_pushCurrentStore: function() {
|
||||
this.$store.dispatch("settings/updateSet", this.getSettings());
|
||||
return;
|
||||
},
|
||||
|
||||
whitelistToInputfield: function() {
|
||||
// If this.$refs.whitelist_input is still undefined, just try again later, lmao
|
||||
if (typeof(this.$refs.whitelist_input) === "undefined") {
|
||||
setTimeout(this.whitelistToInputfield, 200);
|
||||
}
|
||||
else {
|
||||
var whitelistString = JSON.stringify(this.getSettings().access.whitelist, undefined, 2);
|
||||
this.$refs.whitelist_input.value = whitelistString;
|
||||
return whitelistString;
|
||||
}
|
||||
},
|
||||
|
||||
saveWhitelist: function() {
|
||||
const prevContent = this.$refs.whitelist_input.value;
|
||||
const element = this.$refs.whitelist_input;
|
||||
try {
|
||||
const arrayWhitelist = JSON.parse(prevContent);
|
||||
var curConf = this.getSettings();
|
||||
curConf.access.whitelist = arrayWhitelist;
|
||||
this.$store.commit("settings/updateGet", curConf); // Apply changes to frontend immediately
|
||||
this.whitelistToInputfield();
|
||||
this.$store.dispatch("settings/updateSet", curConf); // Push to server, and update frontend again after response
|
||||
element.classList.remove("inputfield--error");
|
||||
} catch (e) {
|
||||
this.$refs.whitelist_input.value = prevContent;
|
||||
element.classList.add("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.add("button--disabled");
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
updateWhitelist: function() {
|
||||
const that = this;
|
||||
this.$store.dispatch("settings/updateGet", function() {
|
||||
that.whitelistToInputfield();
|
||||
that.whitelistInputJsonSyntaxCheck();
|
||||
return;
|
||||
});
|
||||
return;
|
||||
},
|
||||
|
||||
whitelistInputJsonSyntaxCheck: function() {
|
||||
const element = this.$refs.whitelist_input;
|
||||
try {
|
||||
JSON.parse(element.value);
|
||||
element.classList.remove("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.remove("button--disabled");
|
||||
} catch (e) {
|
||||
element.classList.add("inputfield--error");
|
||||
this.$refs.button_saveWhitelist.classList.add("button--disabled");
|
||||
}
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$store.dispatch("diskUsage/update", this);
|
||||
this.$store.dispatch("serverOs/update", this);
|
||||
const that = this;
|
||||
|
||||
this.$store.dispatch("diskUsage/update");
|
||||
this.$store.dispatch("serverOs/update");
|
||||
this.$store.dispatch("settings/updateGet", function() {
|
||||
that.whitelistToInputfield();
|
||||
});
|
||||
|
||||
setInterval(function(){
|
||||
that.$store.dispatch("settings/updateGet");
|
||||
}, 1000);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -197,6 +343,19 @@ h2 {
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
color: theme("colors.purple-0");
|
||||
border-radius: 5px;
|
||||
font-size: 16pt;
|
||||
padding: 0.7em;
|
||||
min-height: 200px;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&.inputfield--error {
|
||||
background-color: #f77;
|
||||
}
|
||||
}
|
||||
|
||||
.option {
|
||||
color: theme("colors.text-gray-1");
|
||||
font-size: 18pt;
|
||||
@ -239,12 +398,30 @@ h2 {
|
||||
color: #000;
|
||||
font-family: ZillaSlab, serif;
|
||||
font-size: 18pt;
|
||||
transition: background-color 0.2s;
|
||||
width: 200px;
|
||||
transition:
|
||||
background-color 0.2s,
|
||||
opacity 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: theme("colors.text-error-1");
|
||||
}
|
||||
|
||||
&--small {
|
||||
font-size: 14pt;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
&--nowarn:hover {
|
||||
background-color: theme("colors.purple-1");
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
cursor: pointer;
|
||||
pointer-events: none;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
|
BIN
tubio-frontend-nuxt-app/static/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
tubio-frontend-nuxt-app/static/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
tubio-frontend-nuxt-app/static/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 7.2 KiB |
9
tubio-frontend-nuxt-app/static/browserconfig.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
BIN
tubio-frontend-nuxt-app/static/favicon-16x16.png
Normal file
After Width: | Height: | Size: 672 B |
BIN
tubio-frontend-nuxt-app/static/favicon-32x32.png
Normal file
After Width: | Height: | Size: 948 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB |
BIN
tubio-frontend-nuxt-app/static/mstile-150x150.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
15
tubio-frontend-nuxt-app/static/safari-pinned-tab.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="595.000000pt" height="595.000000pt" viewBox="0 0 595.000000 595.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,595.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 2975 l0 -2415 2975 0 2975 0 0 2415 0 2415 -2975 0 -2975 0 0
|
||||
-2415z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 603 B |
19
tubio-frontend-nuxt-app/static/site.webmanifest
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "",
|
||||
"short_name": "",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "get_disk_usage"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("diskUsage/update", response.data.disk_usage);
|
||||
context.commit("update", response.data.disk_usage);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "fetch_alltime_cache"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("dlcache/update", response.data.cache);
|
||||
context.commit("update", response.data.cache);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "fetch_session_logs"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("logs/update", response.data.logs);
|
||||
context.commit("update", response.data.logs);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -11,13 +11,13 @@ export const mutations = {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
update(context, instance) {
|
||||
update(context) {
|
||||
axios.post("/api", {
|
||||
request: "get_os_name"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
instance.$store.commit("serverOs/update", response.data.os_name);
|
||||
context.commit("update", response.data.os_name);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -0,0 +1,48 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export const state = () => ({
|
||||
config: {}
|
||||
});
|
||||
|
||||
export const mutations = {
|
||||
updateGet(state, data) {
|
||||
state.config = data;
|
||||
},
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
updateGet(context, callback) {
|
||||
axios.post("/api", {
|
||||
request: "update_config"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
context.commit("updateGet", response.data.config);
|
||||
if (typeof(callback) === "function") callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
updateSet(context, newConfig) {
|
||||
axios.post("/api", {
|
||||
request: "update_config",
|
||||
config: newConfig
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
// Also update the vuex store...
|
||||
context.commit("updateGet", response.data.config);
|
||||
}
|
||||
});
|
||||
},
|
||||
resetToDefaults(context) {
|
||||
axios.post("/api", {
|
||||
request: "reset_config_to_default_values"
|
||||
})
|
||||
.then(function(response) {
|
||||
if (response.data.status === "OK") {
|
||||
// Also update the vuex store...
|
||||
context.commit("updateGet", response.data.config);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|