working pre-update

This commit is contained in:
code002lover 2025-04-26 03:20:54 +02:00
parent 2233b4a44c
commit 27a1817595
20 changed files with 134 additions and 1175 deletions

11
.dockerignore Normal file
View File

@ -0,0 +1,11 @@
node_modules
npm-debug.log
.git
.gitignore
.env
*.md
logs
*.log
cookiesecret.txt
mysql_password.txt
views/

18
Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM node:slim
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy application code
COPY . .
# Expose ports
EXPOSE 80
# Start the application
CMD ["node", "server.js"]

35
docker-compose.yml Normal file
View File

@ -0,0 +1,35 @@
services:
app:
build: .
ports:
- "23080:80"
environment:
- MYSQL_HOST=db
- MYSQL_USER=ipost
- MYSQL_PASSWORD=ipost_password
- MYSQL_DATABASE=ipost
depends_on:
- db
volumes:
- ./logs:/app/logs
- ./server_config.json:/app/server_config.json
- ./cookiesecret.txt:/app/cookiesecret.txt
- ./mysql_password.txt:/app/mysql_password.txt
restart: unless-stopped
db:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=ipost
- MYSQL_USER=ipost
- MYSQL_PASSWORD=ipost_password
volumes:
- mysql_data:/var/lib/mysql
- ./createSchema.sql:/docker-entrypoint-initdb.d/createSchema.sql
ports:
- "3306:3306"
restart: unless-stopped
volumes:
mysql_data:

View File

@ -1,6 +1,6 @@
const warn_messages = [ const warn_messages = [
["%cDo not paste any text in here","background: red; color: yellow; font-size: x-large"], ["%cDo not paste any text in here","background: red; color: yellow; font-size: x-large"],
["Pasting anything in here may give others access to your account.",""] ["Pasting anything in here may give others access to your account."]
] ]
function warnmessage() { function warnmessage() {
for (let message of warn_messages) { for (let message of warn_messages) {

1064
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,11 +10,9 @@
"express-useragent": "^1.0.15", "express-useragent": "^1.0.15",
"hcaptcha": "^0.1.1", "hcaptcha": "^0.1.1",
"hsts": "^2.2.0", "hsts": "^2.2.0",
"newrelic": "^9.15.0",
"html-minifier-terser": "^7.2.0", "html-minifier-terser": "^7.2.0",
"lru-cache": "^9.1.2", "lru-cache": "^9.1.2",
"mysql2": "^3.3.5", "mysql2": "^3.3.5",
"newrelic": "^9.11.0",
"sharp": "^0.30.7", "sharp": "^0.30.7",
"spdy": "^4.0.2", "spdy": "^4.0.2",
"swagger-autogen": "^2.23.1", "swagger-autogen": "^2.23.1",

View File

@ -1,17 +1,17 @@
import ejs from "ejs" import ejs from "ejs"
import { LRUCache as LRU} from "lru-cache" import { LRUCache as LRU } from "lru-cache"
import {minify as min_js} from "uglify-js" import { minify as min_js } from "uglify-js"
import Clean from 'clean-css'; import Clean from 'clean-css';
import Minifier from 'html-minifier-terser'; import Minifier from 'html-minifier-terser';
import { web_version } from "unsafe_encrypt"; import { web_version } from "unsafe_encrypt";
import {existsSync, readFileSync, readFile} from "fs" import { existsSync, readFileSync, readFile } from "fs"
export const setup = function (router, con, server) { export const setup = function (router, con, server) {
const increaseUSERCall = server.increaseUSERCall const increaseUSERCall = server.increaseUSERCall
const dir = server.dirname + "/" const dir = server.dirname + "/"
ejs.cache = new LRU({max:20}) ejs.cache = new LRU({ max: 20 })
const load_var_cache = new LRU({ const load_var_cache = new LRU({
max: 20, max: 20,
@ -27,64 +27,64 @@ export const setup = function (router, con, server) {
function load_var(filePath) { function load_var(filePath) {
if (load_var_cache.has(filePath)) { if (load_var_cache.has(filePath)) {
return load_var_cache.get(filePath); return load_var_cache.get(filePath);
} }
if (!existsSync(filePath)) { if (!existsSync(filePath)) {
console.log(1,'Tried loading non-existent file', filePath); console.log(1, 'Tried loading non-existent file', filePath);
load_var_cache.set(filePath, ''); load_var_cache.set(filePath, '');
return ''; return '';
} }
let output = readFileSync(filePath); let output = readFileSync(filePath);
if (filePath.endsWith('.js')) { if (filePath.endsWith('.js')) {
output = min_js(output.toString()).code; output = min_js(output.toString()).code;
} else if (filePath.endsWith('.css')) { } else if (filePath.endsWith('.css')) {
const { styles } = new Clean({}).minify(output.toString()); const { styles } = new Clean({}).minify(output.toString());
output = styles; output = styles;
} }
load_var_cache.set(filePath, output); load_var_cache.set(filePath, output);
return output; return output;
} }
function get_channels(){ function get_channels() {
return new Promise(function(resolve, reject) { return new Promise(function (resolve, reject) {
let sql = `select post_receiver_name from ipost.posts where post_is_private = '0' group by post_receiver_name;`; let sql = `select post_receiver_name from ipost.posts where post_is_private = '0' group by post_receiver_name;`;
con.query(sql, [], function (err, result) { con.query(sql, [], function (err, result) {
if (err)reject(err) if (err) reject(err)
let out = [] let out = []
for(let channel of result){ for (let channel of result) {
if(channel.post_receiver_name === "")continue; if (channel.post_receiver_name === "") continue;
out[out.length] = channel.post_receiver_name out[out.length] = channel.post_receiver_name
} }
resolve(out) resolve(out)
}); });
}) })
} }
const appId_Cache = new LRU({max:20,ttl: 1000 * 60 * 15}) //cache for 15 minutes const appId_Cache = new LRU({ max: 20, ttl: 1000 * 60 * 15 }) //cache for 15 minutes
function getAppWithId(appid) { function getAppWithId(appid) {
appid = Number(appid) appid = Number(appid)
return new Promise((res,rej) => { return new Promise((res, rej) => {
if(isNaN(appid)) { if (isNaN(appid)) {
res({}) res({})
return return
} }
if(appId_Cache.has(appid)) { if (appId_Cache.has(appid)) {
res(appId_Cache.get(appid) || {}) res(appId_Cache.get(appid) || {})
return return
} }
con.query("SELECT * FROM ipost.application WHERE application_id=?",[appid],(err,result) => { con.query("SELECT * FROM ipost.application WHERE application_id=?", [appid], (err, result) => {
if(err) { if (err) {
console.error(err) console.error(err)
rej({}) rej({})
return return
} }
appId_Cache.set(appid,result[0]) appId_Cache.set(appid, result[0])
res(result[0] || {}) res(result[0] || {})
}) })
}) })
@ -101,7 +101,6 @@ export const setup = function (router, con, server) {
getChannels: get_channels, getChannels: get_channels,
encryptJS: min_js(web_version().toString()).code, encryptJS: min_js(web_version().toString()).code,
cookiebanner: `<script id="cookieyes" type="text/javascript" src="https://cdn-cookieyes.com/client_data/3cf33f6b631f3587bf83813b/script.js" async></script>`, cookiebanner: `<script id="cookieyes" type="text/javascript" src="https://cdn-cookieyes.com/client_data/3cf33f6b631f3587bf83813b/script.js" async></script>`,
newrelic: load_var("./extra_modules/newrelic_monitor.html"),
getPID: server.global_page_variables.getPID, getPID: server.global_page_variables.getPID,
getDMPID: server.global_page_variables.getDMPID, getDMPID: server.global_page_variables.getDMPID,
unauthorized_description: "Chat now by creating an account on IPost", unauthorized_description: "Chat now by creating an account on IPost",
@ -109,24 +108,24 @@ export const setup = function (router, con, server) {
getAppWithId: getAppWithId getAppWithId: getAppWithId
} }
async function handleUserFiles(request, response, overrideurl) { async function handleUserFiles(request, response, overrideurl) {
if (!increaseUSERCall(request, response))return; if (!increaseUSERCall(request, response)) return;
if(typeof overrideurl !== "string")overrideurl = undefined; if (typeof overrideurl !== "string") overrideurl = undefined;
let originalUrl = overrideurl let originalUrl = overrideurl
|| request.params.file || request.params.file
|| request.originalUrl.split("?").shift(); //backup in case anything goes wrong || request.originalUrl.split("?").shift(); //backup in case anything goes wrong
let path = "" let path = ""
if (existsSync(dir + "views/" + originalUrl)) { if (existsSync(dir + "views/" + originalUrl)) {
path = dir + "views/" + originalUrl path = dir + "views/" + originalUrl
//send .txt files as plaintext to help browsers interpret it correctly //send .txt files as plaintext to help browsers interpret it correctly
if(originalUrl.endsWith(".txt")) { if (originalUrl.endsWith(".txt")) {
response.set('Content-Type', 'text/plain'); response.set('Content-Type', 'text/plain');
readFile(path,(err,data)=> { readFile(path, (err, data) => {
if(err)return if (err) return
response.send(data) response.send(data)
}) })
return return
@ -141,26 +140,26 @@ export const setup = function (router, con, server) {
if (existsSync(dir + "views" + originalUrl + ".html")) { if (existsSync(dir + "views" + originalUrl + ".html")) {
path = dir + "views" + originalUrl + ".html" path = dir + "views" + originalUrl + ".html"
} }
if(path !== "" && originalUrl !== "favicon.ico" && originalUrl !== "api_documentation" && originalUrl !== "api_documentation.html") { if (path !== "" && originalUrl !== "favicon.ico" && originalUrl !== "api_documentation" && originalUrl !== "api_documentation.html") {
console.log(originalUrl) console.log(originalUrl)
global_page_variables.user = { "username": response.locals.username, "bio": response.locals.bio, "avatar": response.locals.avatar } global_page_variables.user = { "username": response.locals.username, "bio": response.locals.bio, "avatar": response.locals.avatar }
global_page_variables.query = request.query global_page_variables.query = request.query
if(originalUrl === "authorize") { if (originalUrl === "authorize") {
global_page_variables.application = await getAppWithId(request.query.id) global_page_variables.application = await getAppWithId(request.query.id)
} }
ejs.renderFile(path,global_page_variables,{async: true},async function(err,str){ ejs.renderFile(path, global_page_variables, { async: true }, async function (err, str) {
str = await str str = await str
err = await err err = await err
if(err) { if (err) {
console.log(1,err) console.log(1, err)
response.status(500) response.status(500)
response.send("error") response.send("error")
//TODO: make error page //TODO: make error page
return return
} }
try { try {
str = await Minifier.minify(str,{ str = await Minifier.minify(str, {
removeComments: true, removeComments: true,
removeCommentsFromCDATA: true, removeCommentsFromCDATA: true,
removeCDATASectionsFromCDATA: true, removeCDATASectionsFromCDATA: true,
@ -171,36 +170,36 @@ export const setup = function (router, con, server) {
useShortDoctype: true, useShortDoctype: true,
removeEmptyAttributes: true removeEmptyAttributes: true
}) })
} catch(ignored){ } catch (ignored) {
console.log(2,"error minifying",originalUrl); console.log(2, "error minifying", originalUrl);
} }
try { try {
response.send(str) response.send(str)
} catch(err) { } catch (err) {
console.error(err) console.error(err)
} }
}) })
return; return;
} }
if(originalUrl === "api_documentation" || originalUrl === "api_documentation.html") { if (originalUrl === "api_documentation" || originalUrl === "api_documentation.html") {
response.set('Cache-Control', 'public, max-age=2592000'); response.set('Cache-Control', 'public, max-age=2592000');
response.set('Content-Type', 'text/html') response.set('Content-Type', 'text/html')
response.send(load_var("./views/api_documentation.html")) response.send(load_var("./views/api_documentation.html"))
return return
} }
if(originalUrl === "favicon.ico") { if (originalUrl === "favicon.ico") {
response.set('Cache-Control', 'public, max-age=2592000'); response.set('Cache-Control', 'public, max-age=2592000');
response.sendFile(dir + "/views/favicon.ico") response.sendFile(dir + "/views/favicon.ico")
return return
} }
console.log(5,"no file found",originalUrl); console.log(5, "no file found", originalUrl);
try { try {
response.status(404).send("No file with that name found"); response.status(404).send("No file with that name found");
} catch(err) { } catch (err) {
console.error(err) console.error(err)
} }
} }
@ -210,12 +209,12 @@ export const setup = function (router, con, server) {
*/ */
router.get("/", (req, res) => { router.get("/", (req, res) => {
req.params.file = "index" req.params.file = "index"
handleUserFiles(req,res,"/index") handleUserFiles(req, res, "/index")
}); });
router.get("/:file", handleUserFiles); router.get("/:file", handleUserFiles);
router.get("/:folder/:file", (req, res) => { router.get("/:folder/:file", (req, res) => {
req.params.file = req.params.folder+"/"+req.params.file req.params.file = req.params.folder + "/" + req.params.file
handleUserFiles(req,res) handleUserFiles(req, res)
}); });
} }

View File

@ -1,5 +1,3 @@
import "newrelic"
import http from "http"; import http from "http";
import express,{Router} from "express"; import express,{Router} from "express";
import useragent from "express-useragent"; import useragent from "express-useragent";
@ -14,7 +12,6 @@ import { readFileSync, appendFile } from "fs";
import { format } from "util"; import { format } from "util";
import { setup as SETUP_ROUTES} from "./routes/setup_all_routes.js" import { setup as SETUP_ROUTES} from "./routes/setup_all_routes.js"
import { verify as verifyHCaptcha_int } from "hcaptcha" import { verify as verifyHCaptcha_int } from "hcaptcha"
import hsts from "hsts"
import { ensureExists } from "./extra_modules/ensureExists.js" import { ensureExists } from "./extra_modules/ensureExists.js"
@ -263,24 +260,14 @@ app.use(fileUpload({
} }
})); }));
const hstsMiddleware = hsts({ app.use((_req, res, next) => {
maxAge: 31536000,
includeSubDomains: true,
preload: true
})
app.use((req, res, next) => {
res.set("x-powered-by", "ipost"); res.set("x-powered-by", "ipost");
res.set("X-Frame-Options","DENY"); res.set("X-Frame-Options","DENY");
res.set("X-XSS-Protection","1; mode=block"); res.set("X-XSS-Protection","1; mode=block");
res.set("X-Content-Type-Options","nosniff"); res.set("X-Content-Type-Options","nosniff");
res.set("Referrer-Policy","no-referrer"); res.set("Referrer-Policy","no-referrer");
if (req.secure) { next()
hstsMiddleware(req, res, next)
} else {
next()
}
}) })
app.use(bodyParser.default.json({ limit: "100mb" })); app.use(bodyParser.default.json({ limit: "100mb" }));
@ -312,18 +299,6 @@ app.use(function (_req, res, next) {
next(); next();
}); });
//auto redirect to https
app.use((req, res, next) => {
if (req.secure) {
//already secure
next();
}
else {
//redirect to https
res.redirect('https://' + req.headers.host + req.url);
}
});
app.use("/*", function (req, res, next) { app.use("/*", function (req, res, next) {
for (let i = 0; i < blocked_headers.length; i++) { for (let i = 0; i < blocked_headers.length; i++) {
if (req.header(blocked_headers[i]) !== undefined) { if (req.header(blocked_headers[i]) !== undefined) {
@ -394,21 +369,9 @@ const httpServer = http.createServer(app);
httpServer.listen(config["ports"]["http"], function () { httpServer.listen(config["ports"]["http"], function () {
console.log(5, "HTTP Server is listening"); console.log(5, "HTTP Server is listening");
}); });
const privateKey = readFileSync(config["ssl"]["privateKey"]).toString();
const certificate = readFileSync(config["ssl"]["certificate"]).toString();
const credentials = { key: privateKey, cert: certificate };
var httpsServer;
import spdy from "spdy"
httpsServer = spdy.createServer(credentials,app)
//httpsServer = https.createServer(credentials, app);
httpsServer.listen(config["ports"]["https"], function () {
console.log(5, "HTTPS Server is listening");
});
wss = new WebSocket({ wss = new WebSocket({
server: httpsServer, server: httpServer,
perMessageDeflate: { perMessageDeflate: {
zlibDeflateOptions: { zlibDeflateOptions: {
chunkSize: 1024, chunkSize: 1024,

View File

@ -4,8 +4,8 @@
"only_prefer_when_ip": "::ffff:127.0.0.1", "only_prefer_when_ip": "::ffff:127.0.0.1",
"mysql": { "mysql": {
"connections":1000, "connections":1000,
"host":"localhost", "host":"db",
"user":"root", "user":"ipost",
"password_file":"mysql_password.txt" "password_file":"mysql_password.txt"
}, },
"cookies": { "cookies": {
@ -159,8 +159,8 @@
"certificate" : "/etc/letsencrypt/live/ipost.rocks-0002/fullchain.pem" "certificate" : "/etc/letsencrypt/live/ipost.rocks-0002/fullchain.pem"
}, },
"ports": { "ports": {
"http": 9999, "http": 80,
"https": 9998 "https": 443
}, },
"disallow_proxies_by_headers": true, "disallow_proxies_by_headers": true,
"hcaptcha_secret": "0x0000000000000000000000000000000000000000", "hcaptcha_secret": "0x0000000000000000000000000000000000000000",

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>IPost Privacy Policy</title> <title>IPost Privacy Policy</title>
<meta name="description" content="IPosts PrivacyPolicy"> <meta name="description" content="IPosts PrivacyPolicy">
<%- newrelic %>
<script> <script>
<%- warnmessagejs %> <%- warnmessagejs %>
</script> </script>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>IPost Terms of Service</title> <title>IPost Terms of Service</title>
<%- newrelic %>
<meta name="description" content="IPosts Terms of Service"> <meta name="description" content="IPosts Terms of Service">
<script src="/js/addnavbar.js" charset="utf-8"></script> <script src="/js/addnavbar.js" charset="utf-8"></script>
<script src="/js/warn_message.js" charset="utf-8"></script> <script src="/js/warn_message.js" charset="utf-8"></script>

View File

@ -11,7 +11,7 @@
<% if(user.username === undefined) { %> <% if(user.username === undefined) { %>
<script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script> <script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script>
<% } %> <% } %>
<%- newrelic %>
<style> <style>
<%- globalcss %> <%- globalcss %>
<%- loadfile("./css/posts.css") %> <%- loadfile("./css/posts.css") %>

View File

@ -4,7 +4,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IPost</title> <title>IPost</title>
<meta name="description" content="<%-unauthorized_description%>"> <meta name="description" content="<%-unauthorized_description%>">
<%- newrelic %>
<style> <style>
<%- globalcss %> <%- globalcss %>
<%- loadfile("./css/logon.css") %> <%- loadfile("./css/logon.css") %>

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login | IPost</title> <title>Login | IPost</title>
<meta name="description" content="Chat on IPost by logging in today"> <meta name="description" content="Chat on IPost by logging in today">
<%- newrelic %>
<link rel="stylesheet" href="/css/logon.css"> <link rel="stylesheet" href="/css/logon.css">
<script src="/js/warn_message.js" charset="utf-8"></script> <script src="/js/warn_message.js" charset="utf-8"></script>
<script src="/js/addnavbar.js" charset="utf-8"></script> <script src="/js/addnavbar.js" charset="utf-8"></script>

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>USERS Page</title> <title>USERS Page</title>
<meta name="description" content="view other users pages on IPost today"> <meta name="description" content="view other users pages on IPost today">
<%- newrelic %>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="/css/global.css">
<script src="/js/addnavbar.js" charset="utf-8"></script> <script src="/js/addnavbar.js" charset="utf-8"></script>

View File

@ -9,7 +9,7 @@
<meta name="description" content="Chat on IPost now"> <meta name="description" content="Chat on IPost now">
<% } %> <% } %>
<title>Posts | IPost</title> <title>Posts | IPost</title>
<%- newrelic %>
<style> <style>
<%- globalcss %> <%- globalcss %>
<%- loadfile("./css/posts.css") %> <%- loadfile("./css/posts.css") %>

View File

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" dir="ltr"> <html lang="en" dir="ltr">
<head> <head>
<%- newrelic %>
<link rel="stylesheet" href="/css/logon.css"> <link rel="stylesheet" href="/css/logon.css">
<script src="/js/warn_message.js" charset="utf-8"></script> <script src="/js/warn_message.js" charset="utf-8"></script>
<script src="/js/addnavbar.js" charset="utf-8"></script> <script src="/js/addnavbar.js" charset="utf-8"></script>

View File

@ -10,7 +10,7 @@
<% } else { %> <% } else { %>
<meta name="description" content="search IPost now"> <meta name="description" content="search IPost now">
<% } %> <% } %>
<%- newrelic %>
<link rel="stylesheet" href="/css/search.css"> <link rel="stylesheet" href="/css/search.css">
<script type="text/javascript" src="/js/htmlescape.js"></script> <script type="text/javascript" src="/js/htmlescape.js"></script>
<link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="/css/global.css">

View File

@ -13,7 +13,7 @@
<% if(user.username === undefined) { %> <% if(user.username === undefined) { %>
<script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script> <script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script>
<% } %> <% } %>
<%- newrelic %>
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/global.css"> <link rel="stylesheet" href="/css/global.css">
<script src="/js/addnavbar.js" charset="utf-8"></script> <script src="/js/addnavbar.js" charset="utf-8"></script>

View File

@ -13,7 +13,7 @@
<% if(user.username === undefined) { %> <% if(user.username === undefined) { %>
<script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script> <script> document.location.href = '/no_login?r='+encodeURIComponent(document.location.pathname) </script>
<% } %> <% } %>
<%- newrelic %>
<style> <style>
<%- globalcss %> <%- globalcss %>
<%- loadfile("./css/style.css") %> <%- loadfile("./css/style.css") %>