mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 06:07:21 +01:00
allow admins to manipulate time on test servers
This commit is contained in:
committed by
Sabe Jones
parent
1b12e9d8b7
commit
593524905e
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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')}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user