allow admins to manipulate time on test servers

This commit is contained in:
Phillip Thelen
2024-02-15 13:09:46 +01:00
committed by Sabe Jones
parent 1b12e9d8b7
commit 593524905e
6 changed files with 109 additions and 37 deletions

View File

@@ -87,5 +87,6 @@
"REDIS_HOST": "aaabbbcccdddeeefff", "REDIS_HOST": "aaabbbcccdddeeefff",
"REDIS_PORT": "1234", "REDIS_PORT": "1234",
"REDIS_PASSWORD": "12345678", "REDIS_PASSWORD": "12345678",
"TRUSTED_DOMAINS": "localhost,https://habitica.com" "TRUSTED_DOMAINS": "localhost,https://habitica.com",
"ENABLE_TIME_TRAVEL": "false"
} }

View File

@@ -290,6 +290,31 @@
>{{ $t('terms') }}</a> >{{ $t('terms') }}</a>
</div> </div>
<div
v-if="ENABLE_TIME_TRAVEL && user.permissions.fullAccess">
<a
class="btn btn-secondary mr-1"
@click="jumpTime(-1)">-1 Day</a>
<a
class="btn btn-secondary mr-1"
@click="jumpTime(-7)">-7 Days</a>
<a
class="btn btn-secondary mr-1"
@click="jumpTime(-30)">-30 Days</a>
<div class="my-2">
Time Traveling! It is {{ new Date().toLocaleString() }}
</div>
<a
class="btn btn-secondary mr-1"
@click="jumpTime(1)">+1 Day</a>
<a
class="btn btn-secondary mr-1"
@click="jumpTime(7)">+7 Days</a>
<a
class="btn btn-secondary mr-1"
@click="jumpTime(30)">+30 Days</a>
</div>
<div <div
v-if="!IS_PRODUCTION && isUserLoaded" v-if="!IS_PRODUCTION && isUserLoaded"
class="debug-toggle" class="debug-toggle"
@@ -300,9 +325,6 @@
> >
Toggle Debug Menu Toggle Debug Menu
</button> </button>
<div>
Today is {{ new Date() }}
</div>
<div <div
v-if="debugMenuShown" v-if="debugMenuShown"
class="debug-toggle debug-group" class="debug-toggle debug-group"
@@ -775,6 +797,7 @@ h3 {
// modules // modules
import axios from 'axios'; import axios from 'axios';
import moment from 'moment'; import moment from 'moment';
import Vue from 'vue';
// images // images
import melior from '@/assets/svg/melior.svg'; import melior from '@/assets/svg/melior.svg';
@@ -790,6 +813,7 @@ import buyGemsModal from './payments/buyGemsModal.vue';
import reportBug from '@/mixins/reportBug.js'; import reportBug from '@/mixins/reportBug.js';
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
const ENABLE_TIME_TRAVEL = process.env.ENABLE_TIME_TRAVEL === 'true'; // eslint-disable-line no-process-env
export default { export default {
components: { components: {
buyGemsModal, buyGemsModal,
@@ -807,6 +831,7 @@ export default {
}), }),
debugMenuShown: false, debugMenuShown: false,
IS_PRODUCTION, IS_PRODUCTION,
ENABLE_TIME_TRAVEL,
}; };
}, },
computed: { computed: {
@@ -868,6 +893,15 @@ export default {
'stats.mp': this.user.stats.mp + 10000, 'stats.mp': this.user.stats.mp + 10000,
}); });
}, },
async jumpTime (amount) {
const response = await axios.post('/api/v4/debug/jump-time', { offsetDays: amount });
console.log(response.data.data);
if (amount > 0) {
Vue.config.clock.jump(amount * 24 * 60 * 60 * 1000);
} else {
Vue.config.clock.setSystemTime(moment().add(amount, 'days').toDate());
}
},
addExp () { addExp () {
// @TODO: Name these variables better // @TODO: Name these variables better
let exp = 0; let exp = 0;

View File

@@ -1,5 +1,4 @@
import Vue from 'vue'; import Vue from 'vue';
import sinon from 'sinon';
import BootstrapVue from 'bootstrap-vue'; import BootstrapVue from 'bootstrap-vue';
import Fragment from 'vue-fragment'; import Fragment from 'vue-fragment';
import AppComponent from './app'; import AppComponent from './app';
@@ -14,7 +13,6 @@ import './filters/registerGlobals';
import i18n from './libs/i18n'; import i18n from './libs/i18n';
import 'smartbanner.js/dist/smartbanner'; import 'smartbanner.js/dist/smartbanner';
let jumped = false;
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env
// Configure Vue global options, see https://vuejs.org/v2/api/#Global-Config // Configure Vue global options, see https://vuejs.org/v2/api/#Global-Config
@@ -37,20 +35,21 @@ setUpLogging();
setupAnalytics(); // just create queues for analytics, no scripts loaded at this time setupAnalytics(); // just create queues for analytics, no scripts loaded at this time
const store = getStore(); const store = getStore();
const time = new Date(2024, 2, 18); if (process.env.ENABLE_TIME_TRAVEL) {
const clock = sinon.useFakeTimers({ (async () => {
now: time, const sinon = await import('sinon');
shouldAdvanceTime: true, const axios = await import('axios');
}); const response = await axios.get('/api/v4/debug/time-travel-time');
console.log(response.data.data.time);
const time = new Date(response.data.data.time);
Vue.config.clock = sinon.useFakeTimers({
now: time,
shouldAdvanceTime: true,
});
setInterval(() => { console.log('Time travel mode activated. It is now', new Date());
if (jumped) { })();
jumped = false; }
return;
}
jumped = true;
clock.jump(36000);
}, 1000);
const vueInstance = new Vue({ const vueInstance = new Vue({
el: '#app', el: '#app',

View File

@@ -28,6 +28,7 @@ const envVars = [
'AMPLITUDE_KEY', 'AMPLITUDE_KEY',
'LOGGLY_CLIENT_TOKEN', 'LOGGLY_CLIENT_TOKEN',
'TRUSTED_DOMAINS', 'TRUSTED_DOMAINS',
'ENABLE_TIME_TRAVEL',
// TODO necessary? if yes how not to mess up with vue cli? 'NODE_ENV' // TODO necessary? if yes how not to mess up with vue cli? 'NODE_ENV'
]; ];

View File

@@ -1,4 +1,6 @@
import _ from 'lodash'; import _ from 'lodash';
import nconf from 'nconf';
import moment from 'moment';
import { authWithHeaders } from '../../middlewares/auth'; import { authWithHeaders } from '../../middlewares/auth';
import ensureDevelpmentMode from '../../middlewares/ensureDevelpmentMode'; import ensureDevelpmentMode from '../../middlewares/ensureDevelpmentMode';
import { BadRequest } from '../../libs/errors'; import { BadRequest } from '../../libs/errors';
@@ -201,4 +203,57 @@ api.questProgress = {
}, },
}; };
let clock;
if (nconf.get('ENABLE_TIME_TRAVEL')) {
(async () => {
const sinon = await import('sinon');
const time = new Date();
clock = sinon.useFakeTimers({
now: time,
shouldAdvanceTime: true,
});
})();
api.timeTravelTime = {
method: 'GET',
url: '/debug/time-travel-time',
middlewares: [authWithHeaders()],
async handler (req, res) {
const { user } = res.locals;
if (!user.permissions.fullAccess) {
throw new BadRequest('You do not have permission to time travel.');
}
res.respond(200, {
time: new Date(),
});
},
}
api.timeTravelAdjust = {
method: 'POST',
url: '/debug/jump-time',
middlewares: [authWithHeaders()],
async handler (req, res) {
const { user } = res.locals;
if (!user.permissions.fullAccess) {
throw new BadRequest('You do not have permission to time travel.');
}
const { offsetDays } = req.body;
if (offsetDays > 0) {
clock.jump(offsetDays * 24 * 60 * 60 * 1000)
} else {
clock.setSystemTime(moment().add(offsetDays, 'days').toDate());
}
res.respond(200, {
time: new Date(),
});
},
}
}
export default api; export default api;

View File

@@ -2,7 +2,6 @@ import nconf from 'nconf';
import express from 'express'; import express from 'express';
import http from 'http'; import http from 'http';
import logger from './libs/logger'; import logger from './libs/logger';
import sinon from 'sinon';
// Setup translations // Setup translations
// Must come before attach middlewares so Mongoose validations can use translations // Must come before attach middlewares so Mongoose validations can use translations
@@ -26,23 +25,6 @@ app.set('port', nconf.get('PORT'));
attachMiddlewares(app, server); attachMiddlewares(app, server);
const time = new Date(2024, 2, 18);
const clock = sinon.useFakeTimers({
now: time,
shouldAdvanceTime: true,
});
var jumped = false;
setInterval(() => {
if (jumped) {
jumped = false;
return;
}
jumped = true;
console.log('Jumping time');
clock.jump(36000);
}, 1000);
server.on('request', app); server.on('request', app);
server.listen(app.get('port'), () => { server.listen(app.get('port'), () => {
logger.info(`Express server listening on port ${app.get('port')}`); logger.info(`Express server listening on port ${app.get('port')}`);