mirror of
https://github.com/TheBinaryNinja/tvapp2.git
synced 2026-06-04 02:35:42 -04:00
feat: add env variable API_KEY for restart / resync triggering
This commit is contained in:
@@ -111,7 +111,6 @@ const USERAGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
|
||||
http://127.0.0.1:4124/health
|
||||
*/
|
||||
|
||||
const subdomainRestart = [ 'restart', 'sync', 'resync' ];
|
||||
const subdomainGZP = [ 'gzip', 'gz' ];
|
||||
const subdomainM3U = [ 'playlist', 'm3u', 'm3u8' ];
|
||||
const subdomainEPG = [ 'guide', 'epg', 'xml' ];
|
||||
@@ -599,6 +598,7 @@ async function serveKey( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 400,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -631,6 +631,7 @@ async function serveKey( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 500,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -793,6 +794,7 @@ async function serveM3UPlaylist( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 404,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -847,6 +849,7 @@ async function serveM3UPlaylist( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 500,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -887,6 +890,7 @@ async function serveM3UPlaylist( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 500,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -926,6 +930,7 @@ async function serveHealthCheck( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 200,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -933,7 +938,7 @@ async function serveHealthCheck( req, res )
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
Log.ok( `health`, chalk.yellow( `[api]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `health check returned` ), chalk.greenBright( `${ statusCheck.status }` ), chalk.blueBright( `<statusCode>` ), chalk.gray( `${ statusCheck.code }` ), chalk.blueBright( `<uptime>` ), chalk.gray( `${ process.uptime() }` ) );
|
||||
Log.ok( `health`, chalk.yellow( `[api]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `health check returned` ), chalk.greenBright( `${ statusCheck.status }` ), chalk.blueBright( `<client>` ), chalk.gray( `${ clientIp( req ) }` ), chalk.blueBright( `<statusCode>` ), chalk.gray( `${ statusCheck.code }` ), chalk.blueBright( `<uptime>` ), chalk.gray( Math.round( process.uptime() ) ) );
|
||||
|
||||
res.end( JSON.stringify( statusCheck ) );
|
||||
return;
|
||||
@@ -953,6 +958,7 @@ async function serveHealthCheck( req, res )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 503,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -1042,6 +1048,7 @@ async function serveM3U( res, req )
|
||||
ref: req.url,
|
||||
method: req.method || 'GET',
|
||||
code: 500,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -1187,7 +1194,7 @@ async function initialize()
|
||||
FILE_GZP_MODIFIED = getFileModified( FILE_GZP );
|
||||
|
||||
const end = performance.now();
|
||||
Log.info( `core`, chalk.yellow( `[init]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `TVApp2 container is ready` ), chalk.blueBright( `took ${ end - start }ms` ), chalk.blueBright( `<message>` ), chalk.gray( `TVApp2 container is ready; took ${ end - start }ms` ), chalk.blueBright( `<ip>` ), chalk.gray( `${ envIpContainer }` ), chalk.blueBright( `<gateway>` ), chalk.gray( `${ envIpGateway }` ), chalk.blueBright( `<port>` ), chalk.gray( `${ envWebPort }` ) );
|
||||
Log.info( `core`, chalk.yellow( `[init]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `TVApp2 container is ready` ), chalk.blueBright( `took ${ end - start }ms` ), chalk.blueBright( `<ip>` ), chalk.gray( `${ envIpContainer }` ), chalk.blueBright( `<gateway>` ), chalk.gray( `${ envIpGateway }` ), chalk.blueBright( `<port>` ), chalk.gray( `${ envWebPort }` ) );
|
||||
}
|
||||
catch ( err )
|
||||
{
|
||||
@@ -1245,6 +1252,66 @@ const server = http.createServer( ( request, response ) =>
|
||||
|
||||
if ( subdomainRestart.some( ( urlKeyword ) => loadFile.startsWith( urlKeyword ) ) )
|
||||
{
|
||||
/*
|
||||
Not highly technical, but good enough for starting out until Express is integrated.
|
||||
if restart command is triggered using website, allow it to pass through without an API key.
|
||||
if restart command is triggered by using
|
||||
|
||||
referer = if activated from webpage via clicking icon
|
||||
no referer = if activated using URL
|
||||
|
||||
referer is check just as an added aspect of the api key, but really this doesn't even need to be here
|
||||
as the referer can be easily spoofed. remove once express and the new api system are added. right now
|
||||
it does no harm for a user to even bypass this.
|
||||
|
||||
@todo integrate real api system after express replaces node http
|
||||
*/
|
||||
|
||||
const apiKey = new URL( request.url, `http://${ request.headers.host }` ).searchParams.get( 'key' );
|
||||
const referer = request.headers.referer || null;
|
||||
|
||||
if ( ( !referer && envApiKey && !apiKey ) || ( referer && !referer.includes( request.headers.host ) ) )
|
||||
{
|
||||
const statusCheck =
|
||||
{
|
||||
ip: envIpContainer, gateway: envIpGateway, client: clientIp( request ),
|
||||
message: `must specify api key: http://${ request.headers.host }/api/restart?key=XXXXXXXX`,
|
||||
status: `unauthorized`, ref: request.url, method: method || 'GET', code: 401,
|
||||
uptime: Math.round( process.uptime() ), timestamp: Date.now()
|
||||
};
|
||||
|
||||
response.writeHead( statusCheck.code, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
Log.error( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.redBright( `unauthorized (401): restart attempt did not specify api key using ?key=XXX parameter` ), chalk.blueBright( `<type>` ), chalk.gray( `api/restart` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
response.end( JSON.stringify( statusCheck ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
no referer, api key in url specified, api key set up with tvapp2 do not match
|
||||
*/
|
||||
|
||||
if ( !referer && ( envApiKey !== apiKey ) )
|
||||
{
|
||||
const statusCheck =
|
||||
{
|
||||
ip: envIpContainer, gateway: envIpGateway, client: clientIp( request ),
|
||||
message: `incorrect api key specified: http://${ request.headers.host }/api/restart?key=XXXXXXXX`,
|
||||
status: `unauthorized`, ref: request.url, method: method || 'GET', code: 401,
|
||||
uptime: Math.round( process.uptime() ), timestamp: Date.now()
|
||||
};
|
||||
|
||||
response.writeHead( statusCheck.code, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
|
||||
Log.error( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.redBright( `unauthorized (401): incorrect api key specified` ), chalk.blueBright( `<type>` ), chalk.gray( `api/restart` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
response.end( JSON.stringify( statusCheck ) );
|
||||
}
|
||||
|
||||
await initialize();
|
||||
|
||||
const statusCheck =
|
||||
@@ -1257,6 +1324,7 @@ const server = http.createServer( ( request, response ) =>
|
||||
ref: request.url,
|
||||
method: method || 'GET',
|
||||
code: 200,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -1265,12 +1333,19 @@ const server = http.createServer( ( request, response ) =>
|
||||
});
|
||||
|
||||
Log.info( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<type>` ), chalk.gray( `api/restart` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
|
||||
response.end( JSON.stringify( statusCheck ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( subdomainHealth.some( ( urlKeyword ) => loadFile.startsWith( urlKeyword ) ) && method === 'GET' )
|
||||
{
|
||||
Log.info( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<type>` ), chalk.gray( `api` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
|
||||
await serveHealthCheck( request, response );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( subdomainM3U.some( ( urlKeyword ) => loadFile.startsWith( urlKeyword ) ) && method === 'GET' )
|
||||
{
|
||||
Log.info( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<type>` ), chalk.gray( `m3u playlist` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
@@ -1311,14 +1386,6 @@ const server = http.createServer( ( request, response ) =>
|
||||
return;
|
||||
}
|
||||
|
||||
if ( subdomainHealth.some( ( urlKeyword ) => loadFile.startsWith( urlKeyword ) ) && method === 'GET' )
|
||||
{
|
||||
Log.info( `www`, chalk.yellow( `[req]` ), chalk.white( `→` ), chalk.blueBright( `<type>` ), chalk.gray( `api` ), chalk.blueBright( `<file>` ), chalk.gray( `${ loadFile }` ), chalk.blueBright( `<method>` ), chalk.gray( `${ method }` ) );
|
||||
|
||||
await serveHealthCheck( request, response );
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
General Template & .html / .css / .js
|
||||
read the loaded asset file
|
||||
@@ -1403,6 +1470,7 @@ const server = http.createServer( ( request, response ) =>
|
||||
ref: request.url,
|
||||
method: method || 'GET',
|
||||
code: 404,
|
||||
uptime: Math.round( process.uptime() ),
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
@@ -1435,9 +1503,9 @@ const server = http.createServer( ( request, response ) =>
|
||||
( async() =>
|
||||
{
|
||||
if ( !envApiKey )
|
||||
{
|
||||
Log.warn( `core`, chalk.yellow( `[api]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `API_KEY environment variable not defined for api, leaving blank` ) );
|
||||
}
|
||||
else
|
||||
Log.ok( `core`, chalk.yellow( `[api]` ), chalk.white( `→` ), chalk.blueBright( `<message>` ), chalk.gray( `API_KEY environment variable successfully assigned` ) );
|
||||
|
||||
await initialize();
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Header Notification: description -->
|
||||
<div class="container">
|
||||
<div class="container header-container">
|
||||
@@ -147,7 +147,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="modalTvapp2" tabindex="-1" data-bs-backdrop="static" aria-labelledby="modalTvapp2Label" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
@@ -239,7 +239,7 @@
|
||||
$('#tvapp2Toast').toast("show");
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Notify > Localhost
|
||||
*/
|
||||
@@ -421,7 +421,7 @@
|
||||
iconResync[0].classList.add('restart'); // normal spinner class
|
||||
document.location.reload() // reload page
|
||||
}, 5000 ); // how long until refresh page
|
||||
}, 1000 ); // how long until dimmer is removed / reload page activated (also on delay)
|
||||
}, 1000 ); // how long until dimmer is removed / reload page activated (also on delay)
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -429,7 +429,7 @@
|
||||
/*
|
||||
Health check > Show time remaining as tooltip
|
||||
*/
|
||||
|
||||
|
||||
function runTooltipCountdown( )
|
||||
{
|
||||
let timerHours, timerMins, timerRemainsLS;
|
||||
@@ -450,7 +450,7 @@
|
||||
{
|
||||
const timerElapsedMS = Date.now() - timerStartMS; // ( 2091 )
|
||||
const timerRemainsMS = timerDelayMS - timerElapsedMS; // ( 7909 ) divide by 1000 for seconds
|
||||
|
||||
|
||||
timerRemainsLS = new Date( timerRemainsMS ); // (Wed Dec 31 1969 10:01:42 (Coordinated Universal Time))
|
||||
timerHours = timerRemainsLS.getUTCHours(); // ( 0 )
|
||||
timerMins = timerRemainsLS.getUTCMinutes(); // ( 9 )
|
||||
@@ -463,7 +463,7 @@
|
||||
.attr('data-original-title', `Health check in ${ timeLeft }`)
|
||||
.attr('aria-label', `Health check in ${ timeLeft }`)
|
||||
.attr('data-bs-original-title', `Health check in ${ timeLeft }`)
|
||||
});
|
||||
});
|
||||
|
||||
const Heart = document.getElementsByClassName('fa-heart');
|
||||
Heart[0].style.color = '#FFF';
|
||||
@@ -486,7 +486,7 @@
|
||||
updateTooltipCountdown();
|
||||
}, timerRemainsLS.getUTCMilliseconds() + 500 );
|
||||
}
|
||||
|
||||
|
||||
updateTooltipCountdown();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user