mirror of
https://github.com/HabitRPG/habitica.git
synced 2026-04-24 11:40:11 -05:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ed48e5e34c | |||
| c17db4ebcd | |||
| 7cc0696ee4 | |||
| 4532105749 | |||
| 0ae19d9107 | |||
| 68bfebcf30 | |||
| 3e93911e70 | |||
| 4ea8636f03 |
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"version": "5.44.3",
|
||||
"version": "5.45.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "habitica",
|
||||
"version": "5.44.3",
|
||||
"version": "5.45.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.22.10",
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "habitica",
|
||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||
"version": "5.44.3",
|
||||
"version": "5.45.0",
|
||||
"main": "./website/server/index.js",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.22.10",
|
||||
|
||||
@@ -43,6 +43,14 @@
|
||||
<p class="purple-600">
|
||||
{{ $t('usernameLimitations') }}
|
||||
</p>
|
||||
<input
|
||||
v-if="needsEmailField"
|
||||
id="emailInput"
|
||||
v-model="email"
|
||||
class="form-control dark"
|
||||
type="text"
|
||||
:placeholder="$t('email')"
|
||||
>
|
||||
<div class="custom-control custom-checkbox mb-4">
|
||||
<input
|
||||
id="privacyTOS"
|
||||
@@ -165,6 +173,7 @@ export default {
|
||||
registrationMethod: null,
|
||||
username: '',
|
||||
usernameIssues: [],
|
||||
needsEmailField: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -183,22 +192,30 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
if (window.sessionStorage.getItem('apple-token')) {
|
||||
this.registrationMethod = 'apple';
|
||||
} else if (!this.$store.state.registrationOptions.registrationMethod) {
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.registrationMethod = this.$store.state.registrationOptions.registrationMethod;
|
||||
}
|
||||
this.authData = this.$store.state.registrationOptions.authData;
|
||||
this.email = this.$store.state.registrationOptions.email;
|
||||
this.username = this.$store.state.registrationOptions.username;
|
||||
this.password = this.$store.state.registrationOptions.password;
|
||||
this.passwordConfirm = this.$store.state.registrationOptions.passwordConfirm;
|
||||
|
||||
if (!this.email) {
|
||||
if (window.sessionStorage.getItem('apple-token')) {
|
||||
this.registrationMethod = 'apple';
|
||||
if (!this.email) {
|
||||
this.email = window.sessionStorage.getItem('apple-email');
|
||||
}
|
||||
} else if (!this.$store.state.registrationOptions.registrationMethod) {
|
||||
this.$router.push('/');
|
||||
} else {
|
||||
this.registrationMethod = this.$store.state.registrationOptions.registrationMethod;
|
||||
}
|
||||
|
||||
if (!this.email && this.registrationMethod !== 'apple') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!this.email || this.email === '') && this.registrationMethod === 'apple') {
|
||||
this.needsEmailField = true;
|
||||
}
|
||||
const usernameToCheck = this.email.split('@')[0].replace(/[^a-zA-Z0-9\-_]/g, '');
|
||||
this.$store.dispatch('auth:verifyUsername', {
|
||||
username: usernameToCheck,
|
||||
@@ -237,6 +254,7 @@ export default {
|
||||
idToken: window.sessionStorage.getItem('apple-token'),
|
||||
name: window.sessionStorage.getItem('apple-name'),
|
||||
username: this.username,
|
||||
email: this.email,
|
||||
allowRegister: true,
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -37,6 +37,7 @@ export default {
|
||||
window.location.href = '/';
|
||||
} else {
|
||||
window.sessionStorage.setItem('apple-token', response.idToken);
|
||||
window.sessionStorage.setItem('apple-email', response.email);
|
||||
window.location.href = '/username';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<strong>{{ $t('equipment') }}:</strong>
|
||||
<span :class="{ 'positive-stat': statsComputed.gearBonus[stat] !== 0 }">
|
||||
{{ statsComputed.gearBonus[stat] !== 0 ? '+' : '' }}{{
|
||||
statsComputed.gearBonus[stat]
|
||||
statsComputed.gearBonus[stat] + statsComputed.classBonus[stat]
|
||||
}}
|
||||
</span>
|
||||
</li>
|
||||
|
||||
@@ -122,7 +122,7 @@ export default defineConfig({
|
||||
},
|
||||
rollupOptions: {
|
||||
output: {
|
||||
experimentalMinChunkSize: 1000
|
||||
experimentalMinChunkSize: 20000
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import {
|
||||
disableCache,
|
||||
} from '../../middlewares/cache';
|
||||
import SERVER_STATUS from '../../libs/serverStatus';
|
||||
|
||||
const api = {};
|
||||
|
||||
/**
|
||||
* @api {get} /api/v3/ready Get Habitica's Server readiness status
|
||||
* @apiName GetReady
|
||||
* @apiGroup Status
|
||||
*
|
||||
* @apiSuccess {String} data.status 'ready' if everything is ok
|
||||
*
|
||||
* @apiSuccessExample {JSON} Server is Ready
|
||||
* {
|
||||
* 'status': 'ready',
|
||||
* }
|
||||
*/
|
||||
api.getReady = {
|
||||
method: 'GET',
|
||||
url: '/ready',
|
||||
// explicitly disable caching so that the server is always checked
|
||||
middlewares: [disableCache],
|
||||
async handler (req, res) {
|
||||
// This allows kubernetes to determine if the server is ready to receive traffic
|
||||
if (!SERVER_STATUS.MONGODB || !SERVER_STATUS.REDIS || !SERVER_STATUS.EXPRESS) {
|
||||
res.respond(503, {
|
||||
status: 'not ready',
|
||||
});
|
||||
} else {
|
||||
res.respond(200, {
|
||||
status: 'ready',
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default api;
|
||||
@@ -44,9 +44,13 @@ export async function appleProfile (req) {
|
||||
|
||||
const verifiedPayload = await jwt.verify(idToken, applePublicKey, { algorithms: 'RS256' });
|
||||
|
||||
let { email } = verifiedPayload;
|
||||
if ((!email || email === '') && req.body.email) {
|
||||
email = req.body.email;
|
||||
}
|
||||
return {
|
||||
id: verifiedPayload.sub,
|
||||
emails: [{ value: verifiedPayload.email }],
|
||||
emails: [{ value: email }],
|
||||
name: verifiedPayload.name || req.body.name || req.query.name,
|
||||
idToken,
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import winston from 'winston';
|
||||
import { Loggly } from 'winston-loggly-bulk';
|
||||
import nconf from 'nconf';
|
||||
import _ from 'lodash';
|
||||
import os from 'os';
|
||||
import {
|
||||
CustomError,
|
||||
} from './errors';
|
||||
@@ -65,9 +66,8 @@ if (IS_PROD) {
|
||||
),
|
||||
}));
|
||||
}
|
||||
|
||||
if (LOGGLY_TOKEN && LOGGLY_SUBDOMAIN) {
|
||||
const tags = ['Winston-NodeJS'];
|
||||
const tags = ['Winston-NodeJS', os.hostname()];
|
||||
if (nconf.get('SERVER_EMOJI')) {
|
||||
tags.push(nconf.get('SERVER_EMOJI'));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
getDevelopmentConnectionUrl,
|
||||
getDefaultConnectionOptions,
|
||||
} from './mongodb';
|
||||
import SERVER_STATUS from './serverStatus';
|
||||
|
||||
const IS_PROD = nconf.get('IS_PROD');
|
||||
const MAINTENANCE_MODE = nconf.get('MAINTENANCE_MODE');
|
||||
@@ -24,6 +25,13 @@ const connectionUrl = IS_PROD ? DB_URI : getDevelopmentConnectionUrl(DB_URI);
|
||||
export default async function connectToMongoDB () {
|
||||
// Do not connect to MongoDB when in maintenance mode
|
||||
if (MAINTENANCE_MODE !== 'true') {
|
||||
mongoose.connection.on('open', () => {
|
||||
SERVER_STATUS.MONGODB = true;
|
||||
});
|
||||
mongoose.connection.on('disconnected', () => {
|
||||
SERVER_STATUS.MONGODB = false;
|
||||
});
|
||||
|
||||
return mongoose.connect(connectionUrl, mongooseOptions).then(() => {
|
||||
logger.info('Connected with Mongoose.');
|
||||
});
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
const SERVER_STATUS = {
|
||||
MONGODB: false,
|
||||
REDIS: false,
|
||||
EXPRESS: false,
|
||||
};
|
||||
|
||||
export default SERVER_STATUS;
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
} from '../libs/errors';
|
||||
import logger from '../libs/logger';
|
||||
import { apiError } from '../libs/apiError';
|
||||
import SERVER_STATUS from '../libs/serverStatus';
|
||||
|
||||
// Middleware to rate limit requests to the API
|
||||
|
||||
@@ -47,6 +48,14 @@ if (RATE_LIMITER_ENABLED) {
|
||||
enable_offline_queue: false,
|
||||
});
|
||||
|
||||
redisClient.on('ready', () => {
|
||||
SERVER_STATUS.REDIS = true;
|
||||
});
|
||||
|
||||
redisClient.on('reconnecting', () => {
|
||||
SERVER_STATUS.REDIS = false;
|
||||
});
|
||||
|
||||
redisClient.on('error', error => {
|
||||
logger.error(error, 'Redis Error');
|
||||
});
|
||||
@@ -56,6 +65,8 @@ if (RATE_LIMITER_ENABLED) {
|
||||
storeClient: redisClient,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
SERVER_STATUS.REDIS = true;
|
||||
}
|
||||
|
||||
function setResponseHeaders (res, rateLimiterRes) {
|
||||
|
||||
@@ -41,7 +41,7 @@ export const logRequestData = (req, res, next) => {
|
||||
|
||||
export const logSlowRequests = (req, res, next) => {
|
||||
req.requestStartTime = Date.now();
|
||||
req.on('close', () => {
|
||||
req.once('close', () => {
|
||||
const requestTime = Date.now() - req.requestStartTime;
|
||||
if (requestTime > SLOW_REQUEST_THRESHOLD) {
|
||||
const data = buildBaseLogData(req);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import nconf from 'nconf';
|
||||
import express from 'express';
|
||||
import http from 'http';
|
||||
import mongoose from 'mongoose';
|
||||
import redis from 'redis';
|
||||
import logger from './libs/logger';
|
||||
|
||||
// Setup translations
|
||||
@@ -18,12 +20,22 @@ import './libs/setupFirebase';
|
||||
import './models/challenge';
|
||||
import './models/group';
|
||||
import './models/user';
|
||||
import SERVER_STATUS from './libs/serverStatus';
|
||||
|
||||
connectToMongoDB();
|
||||
|
||||
const server = http.createServer();
|
||||
const app = express();
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('SIGTERM signal received: closing HTTP server');
|
||||
server.close(async () => {
|
||||
await mongoose.disconnect();
|
||||
await redis.quit();
|
||||
process.exit(0);
|
||||
});
|
||||
});
|
||||
|
||||
app.set('port', nconf.get('PORT'));
|
||||
|
||||
attachMiddlewares(app, server);
|
||||
@@ -31,6 +43,7 @@ attachMiddlewares(app, server);
|
||||
server.on('request', app);
|
||||
server.listen(app.get('port'), () => {
|
||||
logger.info(`Express server listening on port ${app.get('port')}`);
|
||||
SERVER_STATUS.EXPRESS = true;
|
||||
});
|
||||
|
||||
export default server;
|
||||
|
||||
Reference in New Issue
Block a user