forked from ppfun/pixelplanet
remove HOSTURL variable and instead get host from header
This commit is contained in:
parent
cfbae41817
commit
ba144c3b8a
28
README.md
28
README.md
|
@ -65,8 +65,6 @@ Configuration takes place in the environment variables that are defined in ecosy
|
|||
|
||||
| Variable | Description | Example |
|
||||
|----------------|:-------------------------|------------------------:|
|
||||
| HOSTURL | URL of the canvas | "http://localhost" |
|
||||
| ASSET_SERVER | URL for assets | "http://localhost" |
|
||||
| PORT | Port | 80 |
|
||||
| REDIS_URL | URL:PORT of redis server | "http://localhost:6379" |
|
||||
| MYSQL_HOST | MySql Host | "localhost" |
|
||||
|
@ -76,16 +74,18 @@ Configuration takes place in the environment variables that are defined in ecosy
|
|||
|
||||
#### Optional Configuration
|
||||
|
||||
| Variable | Description | Example |
|
||||
|-------------------|:--------------------------------------|-------------|
|
||||
| USE_PROXYCHECK | Check users for Proxies | 0 |
|
||||
| APISOCKET_KEY | Key for API Socket for SpecialAccess™ | "SDfasife3" |
|
||||
| ADMIN_IDS | Ids of users with Admin rights | "1,12,3" |
|
||||
| RECAPTCHA_SECRET | reCaptcha secret key | "asdieewff" |
|
||||
| RECAPTCHA_SITEKEY | reCaptcha site key | "23ksdfssd" |
|
||||
| RECAPTCHA_TIME | time in minutes between captchas | 30 |
|
||||
| SESSION_SECRET | random sting for expression sessions | "ayylmao" |
|
||||
| LOG_MYSQL | if sql queries should get logged | 0 |
|
||||
| Variable | Description | Example |
|
||||
|-------------------|:--------------------------------------|--------------------|
|
||||
| ASSET_SERVER | URL for assets | "http://localhost" |
|
||||
| USE_PROXYCHECK | Check users for Proxies | 0 |
|
||||
| APISOCKET_KEY | Key for API Socket for SpecialAccess™ | "SDfasife3" |
|
||||
| ADMIN_IDS | Ids of users with Admin rights | "1,12,3" |
|
||||
| RECAPTCHA_SECRET | reCaptcha secret key | "asdieewff" |
|
||||
| RECAPTCHA_SITEKEY | reCaptcha site key | "23ksdfssd" |
|
||||
| RECAPTCHA_TIME | time in minutes between captchas | 30 |
|
||||
| SESSION_SECRET | random sting for expression sessions | "ayylmao" |
|
||||
| LOG_MYSQL | if sql queries should get logged | 0 |
|
||||
| USE_XREALIP | see cloudflare section | 1 |
|
||||
|
||||
Notes:
|
||||
|
||||
|
@ -156,10 +156,12 @@ pm2 log flush
|
|||
pm2 stop web
|
||||
```
|
||||
|
||||
### If using Cloudflare
|
||||
### If using Cloudflare / Reverse Proxy
|
||||
In order to get the real IP and not use the cloudflare Proxy IP for placing pixels, we filter those out. The cloudflare IPs are in src/utils/cloudflareip.js and used in src/utils/ip.js. If for some reason cloudflare ads more IPs to it, you can see them at https://www.cloudflare.com/ips/ and add them.
|
||||
If you use any other Reverse Proxy, you can define it's IPs there too.
|
||||
|
||||
If USE\_XREALIP is set, we take the IP from the X-Real-Ip header without checking for cloudflare IPs. Use this if you have pixelplanet running behind nginx use the nginx set\_realip module to give us the client ip on the X-Real-Ip header. And be sure to also forward X-Forwarded-Port and set X-Forwarded-Proto.
|
||||
|
||||
### Auto-Start
|
||||
To have the canvas with all it's components autostart at systemstart,
|
||||
enable mysql, redis (and probably nginx if you use it) according to your system (`systemctl enable ...`)
|
||||
|
|
|
@ -7,20 +7,20 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom/server';
|
||||
import Html from './Html';
|
||||
|
||||
const RedirectionPage = ({ text }) => (
|
||||
const RedirectionPage = ({ text, host }) => (
|
||||
<div>
|
||||
<h3>{text}</h3>
|
||||
<p>You will be automatically redirected after 5s</p>
|
||||
<p>Or <a href="https://pixelplanet.fun">Click here</a> to go back to pixelplanet</p>
|
||||
<p>Or <a href={host}>Click here</a> to go back to pixelplanet</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export function getHtml(description, text) {
|
||||
export function getHtml(description, text, host) {
|
||||
const data = {
|
||||
title: 'PixelPlanet.fun Accounts',
|
||||
description,
|
||||
body: <RedirectionPage text={text} />,
|
||||
code: 'window.setTimeout(function(){window.location.href="https://pixelplanet.fun";},4000)',
|
||||
body: <RedirectionPage text={text} host ={host} />,
|
||||
code: `window.setTimeout(function(){window.location.href="${host}";},4000)`,
|
||||
};
|
||||
const index = `<!doctype html>${ReactDOM.renderToStaticMarkup(<Html {...data} />)}`;
|
||||
return index;
|
||||
|
|
|
@ -7,8 +7,6 @@ if (process.env.BROWSER) {
|
|||
throw new Error('Do not import `config.js` from inside the client-side code.');
|
||||
}
|
||||
|
||||
export const HOSTURL = process.env.HOSTURL || 'https://pixelplanet.fun';
|
||||
|
||||
export const PORT = process.env.PORT || 80;
|
||||
|
||||
const TILE_FOLDER_REL = process.env.TILE_FOLDER || 'tiles';
|
||||
|
@ -16,6 +14,8 @@ export const TILE_FOLDER = path.join(__dirname, `./${TILE_FOLDER_REL}`);
|
|||
|
||||
export const ASSET_SERVER = process.env.ASSET_SERVER || '.';
|
||||
|
||||
export const USE_XREALIP = process.env.USE_XREALIP || false;
|
||||
|
||||
// Proxycheck
|
||||
export const USE_PROXYCHECK = parseInt(process.env.USE_PROXYCHECK, 10) || false;
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ import nodemailer from 'nodemailer';
|
|||
|
||||
import logger from './logger';
|
||||
import { HOUR, MINUTE } from './constants';
|
||||
import { HOSTURL } from './config';
|
||||
import { DailyCron, HourlyCron } from '../utils/cron';
|
||||
|
||||
import RegUser from '../data/models/RegUser';
|
||||
|
@ -37,7 +36,7 @@ class MailProvider {
|
|||
DailyCron.hook(MailProvider.cleanUsers);
|
||||
}
|
||||
|
||||
sendVerifyMail(to, name) {
|
||||
sendVerifyMail(to, name, host) {
|
||||
const pastMail = this.verifyCodes[to];
|
||||
if (pastMail) {
|
||||
const minLeft = Math.floor(
|
||||
|
@ -53,7 +52,7 @@ class MailProvider {
|
|||
}
|
||||
logger.info(`Sending verification mail to ${to} / ${name}`);
|
||||
const code = this.setCode(to);
|
||||
const verifyUrl = `${HOSTURL}/api/auth/verify?token=${code}`;
|
||||
const verifyUrl = `${host}/api/auth/verify?token=${code}`;
|
||||
transporter.sendMail({
|
||||
from: 'donotreply@pixelplanet.fun',
|
||||
to,
|
||||
|
@ -70,7 +69,7 @@ class MailProvider {
|
|||
return null;
|
||||
}
|
||||
|
||||
async sendPasswdResetMail(to, ip) {
|
||||
async sendPasswdResetMail(to, ip, host) {
|
||||
const pastMail = this.verifyCodes[to];
|
||||
if (pastMail) {
|
||||
if (Date.now() < pastMail.timestamp + 15 * MINUTE) {
|
||||
|
@ -100,7 +99,7 @@ class MailProvider {
|
|||
|
||||
logger.info(`Sending Password reset mail to ${to}`);
|
||||
const code = this.setCode(to);
|
||||
const restoreUrl = `${HOSTURL}/reset_password?token=${code}`;
|
||||
const restoreUrl = `${host}/reset_password?token=${code}`;
|
||||
transporter.sendMail({
|
||||
from: 'donotreply@pixelplanet.fun',
|
||||
to,
|
||||
|
|
|
@ -16,7 +16,7 @@ import { sanitizeName } from '../utils/validation';
|
|||
|
||||
import logger from './logger';
|
||||
import { User, RegUser } from '../data/models';
|
||||
import { auth, HOSTURL } from './config';
|
||||
import { auth } from './config';
|
||||
import { compareToHash } from '../utils/hash';
|
||||
|
||||
|
||||
|
@ -105,7 +105,8 @@ async function oauth_login(email, name, discordid = null) {
|
|||
*/
|
||||
passport.use(new FacebookStrategy({
|
||||
...auth.facebook,
|
||||
callbackURL: `${HOSTURL}/api/auth/facebook/return`,
|
||||
callbackURL: `/api/auth/facebook/return`,
|
||||
proxy: true,
|
||||
profileFields: ['displayName', 'email'],
|
||||
}, async (req, accessToken, refreshToken, profile, done) => {
|
||||
const { displayName: name, emails } = profile;
|
||||
|
@ -119,7 +120,8 @@ passport.use(new FacebookStrategy({
|
|||
*/
|
||||
passport.use(new DiscordStrategy({
|
||||
...auth.discord,
|
||||
callbackURL: `${HOSTURL}/api/auth/discord/return`,
|
||||
callbackURL: `/api/auth/discord/return`,
|
||||
proxy: true,
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
// TODO get discord id
|
||||
console.log({ profile, refreshToken, accessToken });
|
||||
|
@ -133,7 +135,8 @@ passport.use(new DiscordStrategy({
|
|||
*/
|
||||
passport.use(new GoogleStrategy({
|
||||
...auth.google,
|
||||
callbackURL: `${HOSTURL}/api/auth/google/return`,
|
||||
callbackURL: `/api/auth/google/return`,
|
||||
proxy: true,
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
const { displayName: name, emails } = profile;
|
||||
const email = emails[0].value;
|
||||
|
@ -146,7 +149,8 @@ passport.use(new GoogleStrategy({
|
|||
*/
|
||||
passport.use(new RedditStrategy({
|
||||
...auth.reddit,
|
||||
callbackURL: `${HOSTURL}/api/auth/reddit/return`,
|
||||
callbackURL: `/api/auth/reddit/return`,
|
||||
proxy: true,
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
console.log({ profile, refreshToken, accessToken });
|
||||
const redditid = profile.id;
|
||||
|
@ -177,7 +181,8 @@ passport.use(new RedditStrategy({
|
|||
*/
|
||||
passport.use(new VkontakteStrategy({
|
||||
...auth.vk,
|
||||
callbackURL: `${HOSTURL}/api/auth/vk/return`,
|
||||
callbackURL: `/api/auth/vk/return`,
|
||||
proxy: true,
|
||||
scope: ['email'],
|
||||
profileFields: ['displayName', 'email'],
|
||||
}, async (accessToken, refreshToken, params, profile, done) => {
|
||||
|
|
|
@ -8,6 +8,7 @@ import type { Request, Response } from 'express';
|
|||
import mailProvider from '../../../core/mail';
|
||||
|
||||
import { validatePassword, validateEMail } from '../../../utils/validation';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
import { compareToHash } from '../../../utils/hash';
|
||||
|
||||
function validate(email, password) {
|
||||
|
@ -55,7 +56,8 @@ export default async (req: Request, res: Response) => {
|
|||
mailVerified: false,
|
||||
});
|
||||
|
||||
mailProvider.sendVerifyMail(email, user.regUser.name);
|
||||
const host = getHostFromRequest(req);
|
||||
mailProvider.sendVerifyMail(email, user.regUser.name, host);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import express from 'express';
|
||||
|
||||
import logger from '../../../core/logger';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
|
||||
import register from './register';
|
||||
import verify from './verify';
|
||||
|
@ -67,7 +68,8 @@ export default (passport) => {
|
|||
res.set({
|
||||
'Content-Type': 'text/html',
|
||||
});
|
||||
const index = getHtml('OAuth Authentification', 'LogIn failed :(, please try again later or register a new account with Mail.');
|
||||
const host = getHostFromRequest(req);
|
||||
const index = getHtml('OAuth Authentification', 'LogIn failed :(, please try again later or register a new account with Mail.', host);
|
||||
res.status(200).send(index);
|
||||
});
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import Sequelize from 'sequelize';
|
|||
import { RegUser } from '../../../data/models';
|
||||
import mailProvider from '../../../core/mail';
|
||||
import getMe from '../../../core/me';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
import {
|
||||
validateEMail,
|
||||
validateName,
|
||||
|
@ -73,7 +74,8 @@ export default async (req: Request, res: Response) => {
|
|||
});
|
||||
return;
|
||||
}
|
||||
mailProvider.sendVerifyMail(email, name);
|
||||
const host = getHostFromRequest(req);
|
||||
mailProvider.sendVerifyMail(email, name, host);
|
||||
res.status(200);
|
||||
res.json({
|
||||
success: true,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import type { Request, Response } from 'express';
|
||||
|
||||
import mailProvider from '../../../core/mail';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { user } = req;
|
||||
|
@ -27,7 +28,9 @@ export default async (req: Request, res: Response) => {
|
|||
return;
|
||||
}
|
||||
|
||||
const error = mailProvider.sendVerifyMail(email, name);
|
||||
const host = getHostFromRequest(req);
|
||||
|
||||
const error = mailProvider.sendVerifyMail(email, name, host);
|
||||
if (error) {
|
||||
res.status(400);
|
||||
res.json({
|
||||
|
|
|
@ -8,6 +8,7 @@ import type { Request, Response } from 'express';
|
|||
|
||||
import mailProvider from '../../../core/mail';
|
||||
import { validateEMail } from '../../../utils/validation';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
|
||||
async function validate(email) {
|
||||
const errors = [];
|
||||
|
@ -29,7 +30,8 @@ export default async (req: Request, res: Response) => {
|
|||
});
|
||||
return;
|
||||
}
|
||||
const error = await mailProvider.sendPasswdResetMail(email, ip);
|
||||
const host = getHostFromRequest(req);
|
||||
const error = await mailProvider.sendPasswdResetMail(email, ip, host);
|
||||
if (error) {
|
||||
res.status(400);
|
||||
res.json({
|
||||
|
|
|
@ -6,17 +6,19 @@
|
|||
import type { Request, Response } from 'express';
|
||||
|
||||
import { getHtml } from '../../../components/RedirectionPage';
|
||||
import { getHostFromRequest } from '../../../utils/ip';
|
||||
import mailProvider from '../../../core/mail';
|
||||
|
||||
export default async (req: Request, res: Response) => {
|
||||
const { token } = req.query;
|
||||
const success = await mailProvider.verify(token);
|
||||
const host = getHostFromRequest(req);
|
||||
if (success) {
|
||||
const index = getHtml('Mail verification', 'You are now verified :)');
|
||||
const index = getHtml('Mail verification', 'You are now verified :)', host);
|
||||
res.status(200).send(index);
|
||||
} else {
|
||||
// eslint-disable-next-line max-len
|
||||
const index = getHtml('Mail verification', 'Your mail verification code is invalid or already expired :(, please request a new one.');
|
||||
const index = getHtml('Mail verification', 'Your mail verification code is invalid or already expired :(, please request a new one.', host);
|
||||
res.status(400).send(index);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -7,6 +7,8 @@ import isCloudflareIp from './cloudflareip';
|
|||
|
||||
import logger from '../core/logger';
|
||||
|
||||
import { USE_XREALIP } from '../core/config';
|
||||
|
||||
|
||||
function isTrustedProxy(ip: string): boolean {
|
||||
if (ip === '::ffff:127.0.0.1' || ip === '127.0.0.1' || isCloudflareIp(ip)) {
|
||||
|
@ -15,15 +17,24 @@ function isTrustedProxy(ip: string): boolean {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: nginx should handle that,
|
||||
* it's not neccessary to do that ourself
|
||||
*/
|
||||
export function getHostFromRequest(req): ?string {
|
||||
const { headers } = req;
|
||||
const host = headers['x-forwarded-host'] || headers['host'];
|
||||
const proto = headers['x-forwarded-proto'] || 'http';
|
||||
|
||||
return `${proto}://${host}`;
|
||||
}
|
||||
|
||||
export async function getIPFromRequest(req): ?string {
|
||||
const { socket, connection, headers } = req;
|
||||
|
||||
const conip = (connection ? connection.remoteAddress : socket.remoteAddress);
|
||||
|
||||
if (USE_XREALIP) {
|
||||
const ip = headers['x-real-ip'];
|
||||
return ip || conip;
|
||||
}
|
||||
|
||||
if (!headers['x-forwarded-for'] || !isTrustedProxy(conip)) {
|
||||
// eslint-disable-next-line max-len
|
||||
logger.warn(`Connection not going through nginx and cloudflare! IP: ${conip}`, headers);
|
||||
|
|
Loading…
Reference in New Issue
Block a user