v0.9.54 combined merge from dev
* initial (very incomplete) work on PC Services Admin (eg csops) * primitive account listing * add ban/unban/delete functionality * fix wtv-tricks theme * fix wtv-tricks theme (cSetup) * better tricks code * fix session_data.getTicketData() * speedtest and other tricks stuff * better protection against direct access to finished url * dependancies update (run `npm update`) * Bump path-to-regexp and express in /zefie_wtvp_minisrv (#29) Bumps [path-to-regexp](https://github.com/pillarjs/path-to-regexp) to 0.1.12 and updates ancestor dependency [express](https://github.com/expressjs/express). These dependencies need to be updated together. Updates `path-to-regexp` from 0.1.10 to 0.1.12 - [Release notes](https://github.com/pillarjs/path-to-regexp/releases) - [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md) - [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.10...v0.1.12) Updates `express` from 4.21.1 to 4.21.2 - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2) --- updated-dependencies: - dependency-name: path-to-regexp dependency-type: indirect - dependency-name: express dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * fix up path functions * force version 1.2.1 of newsie due to breaking change * remove debug log print for usenet * fix account directory was broken due to previous changes * fix wtv-home:/home was hiding options bar * bump to 0.9.54 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -193,7 +193,7 @@ class WTVClientSessionData {
|
||||
}
|
||||
|
||||
getAccountStoreDirectory() {
|
||||
return this.minisrv_config.config.SessionStore + this.path.sep + "accounts";
|
||||
return this.path.resolve(this.wtvshared.getAbsolutePath() + this.path.sep + this.minisrv_config.config.SessionStore + this.path.sep + "accounts");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -356,7 +356,6 @@ class WTVNews {
|
||||
var promises = [];
|
||||
for (var article in NGArticles) {
|
||||
if (article == "getCaseInsensitiveKey" || isNaN(article)) continue;
|
||||
console.log(article);
|
||||
promises.push(new Promise((resolve, reject) => {
|
||||
this.getHeader(NGArticles[article]).then((data) => {
|
||||
if (data.article) messages.push(data.article)
|
||||
|
||||
@@ -14,7 +14,7 @@ class WTVNewsServer {
|
||||
constructor(minisrv_config, local_server_port, using_auth = false, username = null, password = null, run_server = true) {
|
||||
this.minisrv_config = minisrv_config;
|
||||
const { WTVShared } = require("./WTVShared.js");
|
||||
this.wtvshared = new WTVShared(minisrv_config);
|
||||
this.wtvshared = new WTVShared(this.minisrv_config);
|
||||
this.featuredGroups = minisrv_config.services['wtv-news'].featuredGroups;
|
||||
const nntp_server = require('nntp-server-zefie');
|
||||
var nntp_statuses = require('nntp-server-zefie/lib/status');
|
||||
@@ -23,7 +23,7 @@ class WTVNewsServer {
|
||||
this.password = password || null;
|
||||
this.using_auth = using_auth;
|
||||
this.scan_interval = minisrv_config.services['wtv-news'].groupMetaRefreshInterval || 86400;
|
||||
this.data_path = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + '/minisrv_internal_nntp');
|
||||
this.data_path = this.wtvshared.getAbsolutePath(this.minisrv_config.config.SessionStore + this.path.sep + 'minisrv_internal_nntp');
|
||||
this.createDataStore();
|
||||
|
||||
if (using_auth && (!username && !password)) {
|
||||
@@ -140,9 +140,9 @@ class WTVNewsServer {
|
||||
}
|
||||
|
||||
var tls_options = {
|
||||
ca: this.wtvshared.getServiceDep('wtv-news/localserver_ca.pem'),
|
||||
key: this.wtvshared.getServiceDep('wtv-news/localserver_key.pem'),
|
||||
cert: this.wtvshared.getServiceDep('wtv-news/localserver_cert.pem'),
|
||||
ca: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_ca.pem'),
|
||||
key: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_key.pem'),
|
||||
cert: this.wtvshared.getServiceDep('wtv-news' + this.path.sep + 'localserver_cert.pem'),
|
||||
}
|
||||
this.local_server = new nntp_server({ requireAuth: using_auth, tls: tls_options, secure: true, allow_posting: true });
|
||||
this.local_server.listen('nntps://127.0.0.1:' + local_server_port);
|
||||
|
||||
177
zefie_wtvp_minisrv/includes/classes/WTVPCAdmin.js
Normal file
177
zefie_wtvp_minisrv/includes/classes/WTVPCAdmin.js
Normal file
@@ -0,0 +1,177 @@
|
||||
class WTVPCAdmin {
|
||||
|
||||
fs = require('fs');
|
||||
path = require('path');
|
||||
minisrv_config = [];
|
||||
wtvr = null;
|
||||
wtvshared = null;
|
||||
socket = null;
|
||||
WTVClientSessionData = require("./WTVClientSessionData.js");
|
||||
service_name = "wtv-admin";
|
||||
|
||||
constructor(minisrv_config, socket, service_name) {
|
||||
this.minisrv_config = minisrv_config;
|
||||
var { WTVShared } = require("./WTVShared.js");
|
||||
var WTVRegister = require("./WTVRegister.js");
|
||||
this.socket = socket;
|
||||
this.wtvr = new WTVRegister(minisrv_config);
|
||||
this.clientAddress = socket.remoteAddress;
|
||||
this.service_name = service_name;
|
||||
}
|
||||
|
||||
|
||||
ip2long(ip) {
|
||||
var components;
|
||||
|
||||
if (components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
|
||||
var iplong = 0;
|
||||
var power = 1;
|
||||
for (var i = 4; i >= 1; i -= 1) {
|
||||
iplong += power * parseInt(components[i]);
|
||||
power *= 256;
|
||||
}
|
||||
return iplong;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
|
||||
isInSubnet(ip, subnet) {
|
||||
if (subnet.indexOf('/') == -1) {
|
||||
var mask, base_ip, long_ip = this.ip2long(ip);
|
||||
var mask2, base_ip2, long_ip2 = this.ip2long(ip);
|
||||
return (long_ip == long_ip2);
|
||||
} else {
|
||||
var mask, base_ip, long_ip = this.ip2long(ip);
|
||||
if ((mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip = this.ip2long(mask[1])) >= 0)) {
|
||||
var freedom = Math.pow(2, 32 - parseInt(mask[2]));
|
||||
return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
rejectConnection() {
|
||||
var rejectReason;
|
||||
rejectReason = this.clientAddress + " is not in the whitelist.";
|
||||
console.log(" * Request from IP", this.clientAddress, "for PC Services Admin, but that IP is not authorized.");
|
||||
return rejectReason;
|
||||
}
|
||||
|
||||
checkPassword(password) {
|
||||
if (this.minisrv_config.config.pc_admin.password) {
|
||||
return (password == this.minisrv_config.config.pc_admin.password);
|
||||
} else {
|
||||
// no password set
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
isAuthorized(justchecking = false) {
|
||||
var allowed_ip = false;
|
||||
if (this.minisrv_config.config.pc_admin.ip_whitelist) {
|
||||
var self = this;
|
||||
Object.keys(this.minisrv_config.config.pc_admin.ip_whitelist).forEach(function (k) {
|
||||
allowed_ip = self.isInSubnet(self.clientAddress, self.minisrv_config.config.pc_admin.ip_whitelist[k]);
|
||||
});
|
||||
}
|
||||
if (justchecking) {
|
||||
return allowed_ip;
|
||||
} else {
|
||||
return allowed_ip ? true : this.rejectConnection();
|
||||
}
|
||||
}
|
||||
|
||||
listRegisteredSSIDs() {
|
||||
var search_dir = this.minisrv_config.config.SessionStore + this.path.sep + "accounts";
|
||||
var self = this;
|
||||
var out = [];
|
||||
this.fs.readdirSync(search_dir).forEach(file => {
|
||||
if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory()) {
|
||||
var user = self.getAccountInfoBySSID(file);
|
||||
out.push([file,user]);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
getAccountInfo(username, directory = null) {
|
||||
var search_dir = this.minisrv_config.config.SessionStore + this.path.sep + "accounts";
|
||||
var account_data = null;
|
||||
var self = this;
|
||||
if (directory) search_dir = directory;
|
||||
this.fs.readdirSync(search_dir).forEach(file => {
|
||||
if (self.fs.lstatSync(search_dir + self.path.sep + file).isDirectory() && account_data === null) {
|
||||
account_data = self.getAccountInfo(username, search_dir + self.path.sep + file);
|
||||
}
|
||||
if (account_data !== null) return;
|
||||
if (!file.match(/.*\.json/ig)) return;
|
||||
try {
|
||||
var temp_session_data_file = self.fs.readFileSync(search_dir + self.path.sep + file, 'Utf8');
|
||||
var temp_session_data = JSON.parse(temp_session_data_file);
|
||||
|
||||
if (temp_session_data.subscriber_username.toLowerCase() == username.toLowerCase()) {
|
||||
account_data = [temp_session_data, (search_dir + self.path.sep + file).replace(this.minisrv_config.config.SessionStore + this.path.sep + "accounts", "").split(this.path.sep)[1]];
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(" # Error parsing Session Data JSON", search_dir + self.path.sep + file, e);
|
||||
}
|
||||
});
|
||||
if (account_data !== null) {
|
||||
if (account_data.ssid) return account_data;
|
||||
var account_info = {};
|
||||
account_info.ssid = account_data[1];
|
||||
account_info.username = account_data[0].subscriber_username;
|
||||
account_info.user_id = account_data[0].subscriber_userid;
|
||||
var userSession = new this.WTVClientSessionData(this.minisrv_config, account_info.ssid);
|
||||
userSession.user_id = 0;
|
||||
account_info.account_users = userSession.listPrimaryAccountUsers();
|
||||
return account_info;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getAccountInfoBySSID(ssid) {
|
||||
var account_info = {};
|
||||
var userSession = new this.WTVClientSessionData(this.minisrv_config, ssid);
|
||||
userSession.user_id = 0;
|
||||
if (userSession.isRegistered(false)) {
|
||||
account_info.ssid = ssid;
|
||||
account_info.account_users = userSession.listPrimaryAccountUsers();
|
||||
if (account_info.account_users) {
|
||||
if (account_info.account_users['subscriber']) {
|
||||
account_info.username = account_info.account_users['subscriber'].subscriber_username;
|
||||
} else {
|
||||
account_info.username = account_info.account_users[0];
|
||||
}
|
||||
} else {
|
||||
account_info.username = account_info.account_users[0];
|
||||
}
|
||||
|
||||
account_info.user_id = 0;
|
||||
return account_info;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
|
||||
getAccountBySSID(ssid) {
|
||||
var userSession = new this.WTVClientSessionData(this.minisrv_config, ssid);
|
||||
userSession.user_id = 0;
|
||||
return userSession;
|
||||
}
|
||||
|
||||
isBanned(ssid) {
|
||||
var self = this;
|
||||
var isBanned = false;
|
||||
if (this.minisrv_config.config.ssid_block_list) {
|
||||
Object.keys(this.minisrv_config.config.ssid_block_list).forEach(function (k) {
|
||||
if (self.minisrv_config.config.ssid_block_list[k] == ssid) {
|
||||
isBanned = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return isBanned;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WTVPCAdmin;
|
||||
@@ -158,6 +158,7 @@ class WTVSec {
|
||||
getTicketData(key = null) {
|
||||
if (typeof (this.ticket_store) === 'session_store') return null;
|
||||
else if (key === null) return this.ticket_store;
|
||||
else if (typeof this.ticket_store[key] !== 'undefined') return this.ticket_store[key];
|
||||
else return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,12 +19,14 @@ class WTVShared {
|
||||
debug = require('debug')('WTVShared')
|
||||
process = require('process');
|
||||
shenanigans = null;
|
||||
appdir = this.path.resolve(__dirname + this.path.sep + ".." + this.path.sep + "..");
|
||||
|
||||
minisrv_config = [];
|
||||
|
||||
constructor(minisrv_config, quiet = false) {
|
||||
if (minisrv_config == null) this.minisrv_config = this.readMiniSrvConfig(true, !quiet);
|
||||
else this.minisrv_config = minisrv_config;
|
||||
|
||||
this.shenanigans = new WTVShenanigans(this.minisrv_config);
|
||||
|
||||
if (!String.prototype.reverse) {
|
||||
@@ -370,7 +372,7 @@ class WTVShared {
|
||||
// Assuming this.path.sep is a slash (/ or \) and this.parentDirectory is set correctly
|
||||
if (!/^(?:[a-zA-Z]:)?[\\/]/.test(check_path)) {
|
||||
// It's a relative path
|
||||
check_path = this.parentDirectory + this.path.sep + check_path;
|
||||
check_path = this.path.resolve(this.parentDirectory + this.path.sep + check_path);
|
||||
}
|
||||
// Use the fixPathSlashes method to normalize the slashes
|
||||
return this.fixPathSlashes(check_path);
|
||||
@@ -398,8 +400,7 @@ class WTVShared {
|
||||
|
||||
getUserConfig() {
|
||||
try {
|
||||
var user_config_filename = this.getAbsolutePath("user_config.json", this.parentDirectory);
|
||||
|
||||
var user_config_filename = this.getAbsolutePath("user_config.json", this.appdir);
|
||||
if (this.fs.lstatSync(user_config_filename)) {
|
||||
try {
|
||||
var minisrv_user_config = this.parseJSON(this.fs.readFileSync(user_config_filename));
|
||||
@@ -885,26 +886,34 @@ class WTVShared {
|
||||
* @param {string} path
|
||||
* @param {string} directory Root directory
|
||||
*/
|
||||
getAbsolutePath(path, directory = '') {
|
||||
const pathModule = require('path');
|
||||
getAbsolutePath(path = '', directory = '.') {
|
||||
if (directory[0] == "/") {
|
||||
return this.path.resolve(directory + this.path.sep + path);
|
||||
}
|
||||
try {
|
||||
// start with our absolute path (of app.js)
|
||||
const appdir = this.path.resolve(__dirname + this.path.sep + '..' + this.path.sep + '..')
|
||||
|
||||
if (path == '' && directory == '.') {
|
||||
return appdir;
|
||||
}
|
||||
// If the directory is a valid directory, prepend it to the path
|
||||
directory = this.path.resolve(appdir + this.path.sep + directory);
|
||||
if (!path) {
|
||||
return directory;
|
||||
}
|
||||
if (directory && !path.startsWith(directory)) {
|
||||
const fs = require('fs');
|
||||
if (fs.lstatSync(directory).isDirectory()) {
|
||||
// Ensure directory has trailing separator
|
||||
if (!directory.endsWith(pathModule.sep)) {
|
||||
directory += pathModule.sep;
|
||||
}
|
||||
path = directory + path;
|
||||
if (!directory.endsWith(this.path.sep)) {
|
||||
directory += this.path.sep;
|
||||
}
|
||||
path = directory + path;
|
||||
}
|
||||
} catch (e) {
|
||||
// If there's an error accessing the directory, log it or handle as needed
|
||||
console.error('Error resolving directory:', e);
|
||||
}
|
||||
// The path.resolve method will take care of normalizing slashes
|
||||
return pathModule.resolve(path);
|
||||
return this.path.resolve(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -925,9 +934,9 @@ class WTVShared {
|
||||
* @return {string} path without gz, or unmodified path if it isnt a gz
|
||||
*/
|
||||
getFilePath(path) {
|
||||
var path_split = path.split('/');
|
||||
var path_split = path.split(this.path.sep);
|
||||
path_split.pop();
|
||||
return path_split.join('/');
|
||||
return path_split.join(this.path.sep);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1198,4 +1207,4 @@ class clientShowAlert {
|
||||
}
|
||||
|
||||
module.exports.WTVShared = WTVShared;
|
||||
module.exports.clientShowAlert = clientShowAlert;
|
||||
module.exports.clientShowAlert = clientShowAlert;
|
||||
|
||||
Reference in New Issue
Block a user