mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 23:27:26 +01:00
Squashed commit of the following:
commitcc6a35e61dAuthor: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 17:27:50 2025 -0600 fix(CSP): more Amazon domains commit985b86c29aAuthor: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 17:18:08 2025 -0600 fix(csp): more loggly allowance commit166bd31527Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 17:12:00 2025 -0600 fix(csp): data, inline, some refactoring commit1a0a6c1806Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 17:05:44 2025 -0600 fix(CSP): override default script-src commit023d9886c8Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:56:24 2025 -0600 fix(CSP): unsafe-eval in default-src commitf51f0a0c93Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:52:14 2025 -0600 fix(CSP): move trusted list to default-src commit83b2ba7688Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:38:05 2025 -0600 fix(CSP): explicit habitica/aws in script-src commitd5ca5172d5Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:31:38 2025 -0600 fix(CSP): need escaped single quotes commitc677a1ffefAuthor: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:27:46 2025 -0600 fix(CSP): unsafe-eval commit6ef35c3f72Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 16:15:07 2025 -0600 fix(CSP): might need to skip entirely in dev but try no 'self' commit5759fb37d8Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 12 15:51:26 2025 -0600 fix(csp): permit AWS in default-src commit9f238abf93Author: Kalista Payne <kalista@habitica.com> Date: Fri Dec 5 17:22:25 2025 -0600 fix(csp): update helmet version to latest commit9462e90f4fAuthor: Kalista Payne <kalista@habitica.com> Date: Tue Nov 25 09:27:05 2025 -0600 feat(security): implement CSP commit72539f9ba3Author: Kalista Payne <kalista@habitica.com> Date: Wed Dec 10 14:16:53 2025 -0600 5.42.2 commitdabd466719Author: Kalista Payne <kalista@habitica.com> Date: Wed Dec 10 14:16:48 2025 -0600 Revert "Chat optimization (#15545)" This reverts commit2917955ef0. commit8bf2304330Author: Kalista Payne <kalista@habitica.com> Date: Wed Dec 10 14:15:48 2025 -0600 chore(event): G1G1 date tweaks commit6937dc4e4eAuthor: Kalista Payne <kalista@habitica.com> Date: Mon Dec 8 16:37:04 2025 -0600 fix(subscription): couple more layout tweaks
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"version": "5.42.1",
|
"version": "5.42.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"version": "5.42.1",
|
"version": "5.42.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.22.10",
|
"@babel/core": "^7.22.10",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "habitica",
|
"name": "habitica",
|
||||||
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
|
||||||
"version": "5.42.1",
|
"version": "5.42.2",
|
||||||
"main": "./website/server/index.js",
|
"main": "./website/server/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.22.10",
|
"@babel/core": "^7.22.10",
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ describe('GET /inbox/messages', () => {
|
|||||||
it('returns four messages when using page-query ', async () => {
|
it('returns four messages when using page-query ', async () => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
for (let i = 0; i < 50; i += 1) {
|
for (let i = 0; i < 10; i += 1) {
|
||||||
promises.push(user.post('/members/send-private-message', {
|
promises.push(user.post('/members/send-private-message', {
|
||||||
toUserId: user.id,
|
toUserId: user.id,
|
||||||
message: 'fourth',
|
message: 'fourth',
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ describe('GET /inbox/conversations', () => {
|
|||||||
it('returns five messages when using page-query ', async () => {
|
it('returns five messages when using page-query ', async () => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
for (let i = 0; i < 50; i += 1) {
|
for (let i = 0; i < 10; i += 1) {
|
||||||
promises.push(user.post('/members/send-private-message', {
|
promises.push(user.post('/members/send-private-message', {
|
||||||
toUserId: user.id,
|
toUserId: user.id,
|
||||||
message: 'fourth',
|
message: 'fourth',
|
||||||
|
|||||||
@@ -396,32 +396,6 @@
|
|||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
@click="makeAdmin()"
|
@click="makeAdmin()"
|
||||||
>Make Admin</a>
|
>Make Admin</a>
|
||||||
<div class="d-flex align-items-center mt-2">
|
|
||||||
<input
|
|
||||||
v-model.number="partyChatCount"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="form-control form-control-sm mr-2"
|
|
||||||
style="width: 80px;"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="btn btn-secondary"
|
|
||||||
@click="seedPartyChat()"
|
|
||||||
>Send Party Chat Messages</a>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex align-items-center mt-2">
|
|
||||||
<input
|
|
||||||
v-model.number="inboxCount"
|
|
||||||
type="number"
|
|
||||||
min="1"
|
|
||||||
class="form-control form-control-sm mr-2"
|
|
||||||
style="width: 80px;"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
class="btn btn-secondary"
|
|
||||||
@click="seedInbox()"
|
|
||||||
>Send Inbox Messages</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -912,8 +886,6 @@ export default {
|
|||||||
DEBUG_ENABLED,
|
DEBUG_ENABLED,
|
||||||
TIME_TRAVEL_ENABLED,
|
TIME_TRAVEL_ENABLED,
|
||||||
lastTimeJump: null,
|
lastTimeJump: null,
|
||||||
partyChatCount: 450,
|
|
||||||
inboxCount: 450,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -1032,32 +1004,6 @@ export default {
|
|||||||
// Reload the website then go to Help > Admin Panel to set contributor level, etc.');
|
// Reload the website then go to Help > Admin Panel to set contributor level, etc.');
|
||||||
// @TODO: sync()
|
// @TODO: sync()
|
||||||
},
|
},
|
||||||
async seedPartyChat () {
|
|
||||||
try {
|
|
||||||
const count = this.partyChatCount;
|
|
||||||
if (!Number.isInteger(count) || count < 1) {
|
|
||||||
window.alert('Please enter a positive integer'); // eslint-disable-line no-alert
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await axios.post('/api/v4/debug/seed-party-chat', { messageCount: count });
|
|
||||||
window.alert(`Successfully sent ${count} messages to your party chat!`); // eslint-disable-line no-alert
|
|
||||||
} catch (e) {
|
|
||||||
window.alert(e.response?.data?.message || 'Error sending party chat messages'); // eslint-disable-line no-alert
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async seedInbox () {
|
|
||||||
try {
|
|
||||||
const count = this.inboxCount;
|
|
||||||
if (!Number.isInteger(count) || count < 1) {
|
|
||||||
window.alert('Please enter a positive integer'); // eslint-disable-line no-alert
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await axios.post('/api/v4/debug/seed-inbox', { messageCount: count });
|
|
||||||
window.alert(`Successfully sent ${count} messages to your inbox!`); // eslint-disable-line no-alert
|
|
||||||
} catch (e) {
|
|
||||||
window.alert(e.response?.data?.message || 'Error sending inbox messages'); // eslint-disable-line no-alert
|
|
||||||
}
|
|
||||||
},
|
|
||||||
donate () {
|
donate () {
|
||||||
this.$root.$emit('bv::show::modal', 'buy-gems', { alreadyTracked: true });
|
this.$root.$emit('bv::show::modal', 'buy-gems', { alreadyTracked: true });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -52,7 +52,7 @@
|
|||||||
<div
|
<div
|
||||||
v-if="!group.purchased.plan.dateTerminated
|
v-if="!group.purchased.plan.dateTerminated
|
||||||
&& group.purchased.plan.paymentMethod === 'Stripe'"
|
&& group.purchased.plan.paymentMethod === 'Stripe'"
|
||||||
class="btn btn-primary"
|
class="btn btn-primary mb-3"
|
||||||
@click="redirectToStripeEdit({groupId: group.id})"
|
@click="redirectToStripeEdit({groupId: group.id})"
|
||||||
>
|
>
|
||||||
{{ $t('subUpdateCard') }}
|
{{ $t('subUpdateCard') }}
|
||||||
|
|||||||
@@ -189,6 +189,7 @@
|
|||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
|
v-if="paymentMethodLogo.icon"
|
||||||
class="svg svg-icon mb-4"
|
class="svg svg-icon mb-4"
|
||||||
:class="paymentMethodLogo.class"
|
:class="paymentMethodLogo.class"
|
||||||
v-html="paymentMethodLogo.icon"
|
v-html="paymentMethodLogo.icon"
|
||||||
@@ -207,6 +208,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-once
|
v-once
|
||||||
|
v-if="!hasGroupPlan"
|
||||||
class="small text-center mb-4"
|
class="small text-center mb-4"
|
||||||
>
|
>
|
||||||
{{ $t('subscriptionBillingFYIShort') }}
|
{{ $t('subscriptionBillingFYIShort') }}
|
||||||
|
|||||||
@@ -679,7 +679,7 @@ import NotificationMixins from '@/mixins/notifications';
|
|||||||
|
|
||||||
// extract to a shared path
|
// extract to a shared path
|
||||||
const CONVERSATIONS_PER_PAGE = 10;
|
const CONVERSATIONS_PER_PAGE = 10;
|
||||||
const PM_PER_PAGE = 50;
|
const PM_PER_PAGE = 10;
|
||||||
|
|
||||||
const UI_STATES = Object.freeze({
|
const UI_STATES = Object.freeze({
|
||||||
LOADING: 'LOADING',
|
LOADING: 'LOADING',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Vue from 'vue';
|
|||||||
import * as Analytics from '@/libs/analytics';
|
import * as Analytics from '@/libs/analytics';
|
||||||
|
|
||||||
export async function getChat (store, payload) {
|
export async function getChat (store, payload) {
|
||||||
const response = await axios.get(`/api/v4/groups/${payload.groupId}/chat?limit=400`);
|
const response = await axios.get(`/api/v4/groups/${payload.groupId}/chat`);
|
||||||
|
|
||||||
return response.data.data;
|
return response.data.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ export const REPEATING_EVENTS = {
|
|||||||
foodSeason: 'Pie',
|
foodSeason: 'Pie',
|
||||||
},
|
},
|
||||||
giftOneGetOne: {
|
giftOneGetOne: {
|
||||||
start: new Date('1970-12-18T04:00-05:00'),
|
start: new Date('1970-12-16T04:00-05:00'),
|
||||||
end: new Date('1970-01-05T23:59-05:00'),
|
end: new Date('1970-01-09T23:59-05:00'),
|
||||||
promo: 'g1g1',
|
promo: 'g1g1',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -64,8 +64,6 @@ function textContainsBannedSlur (message) {
|
|||||||
*
|
*
|
||||||
* @apiParam (Path) {String} groupId The group _id ('party' for the user party and
|
* @apiParam (Path) {String} groupId The group _id ('party' for the user party and
|
||||||
* 'habitrpg' for tavern are accepted).
|
* 'habitrpg' for tavern are accepted).
|
||||||
* @apiParam (Query) {Number} [limit=50] The number of messages to fetch (max 400).
|
|
||||||
* @apiParam (Query) {String} [before] Fetch messages older than this message ID.
|
|
||||||
*
|
*
|
||||||
* @apiSuccess {Array} data An array of <a href='https://github.com/HabitRPG/habitica/blob/develop/website/server/models/group.js#L51' target='_blank'>chat messages</a>
|
* @apiSuccess {Array} data An array of <a href='https://github.com/HabitRPG/habitica/blob/develop/website/server/models/group.js#L51' target='_blank'>chat messages</a>
|
||||||
*
|
*
|
||||||
@@ -80,21 +78,18 @@ api.getChat = {
|
|||||||
const { user } = res.locals;
|
const { user } = res.locals;
|
||||||
|
|
||||||
req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
|
req.checkParams('groupId', apiError('groupIdRequired')).notEmpty();
|
||||||
req.checkQuery('before').optional().isUUID();
|
|
||||||
|
|
||||||
const validationErrors = req.validationErrors();
|
const validationErrors = req.validationErrors();
|
||||||
if (validationErrors) throw validationErrors;
|
if (validationErrors) throw validationErrors;
|
||||||
|
|
||||||
const { groupId } = req.params;
|
const { groupId } = req.params;
|
||||||
const limit = req.query.limit ? Math.min(parseInt(req.query.limit, 10), 400) : 50;
|
|
||||||
const { before } = req.query;
|
|
||||||
const group = await Group.getGroup({ user, groupId, fields: 'chat privacy' });
|
const group = await Group.getGroup({ user, groupId, fields: 'chat privacy' });
|
||||||
if (!group) throw new NotFound(res.t('groupNotFound'));
|
if (!group) throw new NotFound(res.t('groupNotFound'));
|
||||||
if (group.privacy === 'public') {
|
if (group.privacy === 'public') {
|
||||||
throw new BadRequest(res.t('featureRetired'));
|
throw new BadRequest(res.t('featureRetired'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupChat = await Group.toJSONCleanChat(group, user, { limit, before });
|
const groupChat = await Group.toJSONCleanChat(group, user);
|
||||||
res.respond(200, groupChat.chat);
|
res.respond(200, groupChat.chat);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import mongoose from 'mongoose';
|
|||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { v4 as uuid } from 'uuid';
|
|
||||||
import { authWithHeaders } from '../../middlewares/auth';
|
import { authWithHeaders } from '../../middlewares/auth';
|
||||||
import ensureDevelopmentMode from '../../middlewares/ensureDevelopmentMode';
|
import ensureDevelopmentMode from '../../middlewares/ensureDevelopmentMode';
|
||||||
import ensureTimeTravelMode from '../../middlewares/ensureTimeTravelMode';
|
import ensureTimeTravelMode from '../../middlewares/ensureTimeTravelMode';
|
||||||
@@ -12,7 +11,6 @@ import {
|
|||||||
model as Group,
|
model as Group,
|
||||||
// basicFields as basicGroupFields,
|
// basicFields as basicGroupFields,
|
||||||
} from '../../models/group';
|
} from '../../models/group';
|
||||||
import { chatModel as Chat, inboxModel as Inbox } from '../../models/message';
|
|
||||||
import connectToMongoDB from '../../libs/mongoose';
|
import connectToMongoDB from '../../libs/mongoose';
|
||||||
|
|
||||||
const { content } = common;
|
const { content } = common;
|
||||||
@@ -313,93 +311,4 @@ api.timeTravelAdjust = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
api.seedPartyChat = {
|
|
||||||
method: 'POST',
|
|
||||||
url: '/debug/seed-party-chat',
|
|
||||||
middlewares: [ensureDevelopmentMode, authWithHeaders()],
|
|
||||||
async handler (req, res) {
|
|
||||||
const { user } = res.locals;
|
|
||||||
const messageCount = Number(req.body.messageCount);
|
|
||||||
|
|
||||||
if (!Number.isInteger(messageCount) || messageCount < 1) {
|
|
||||||
throw new BadRequest('messageCount must be a positive integer.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.party._id) {
|
|
||||||
throw new BadRequest('You are not in a party.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const party = await Group.findOne({ _id: user.party._id, type: 'party' }).exec();
|
|
||||||
if (!party) {
|
|
||||||
throw new BadRequest('Party not found.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = [];
|
|
||||||
const baseTimestamp = Date.now();
|
|
||||||
|
|
||||||
for (let i = 1; i <= messageCount; i += 1) {
|
|
||||||
const id = uuid();
|
|
||||||
messages.push({
|
|
||||||
_id: id,
|
|
||||||
id,
|
|
||||||
groupId: party._id,
|
|
||||||
text: `#${i}`,
|
|
||||||
unformattedText: `#${i}`,
|
|
||||||
timestamp: new Date(baseTimestamp - (messageCount - i) * 1000),
|
|
||||||
likes: {},
|
|
||||||
flags: {},
|
|
||||||
flagCount: 0,
|
|
||||||
uuid: 'system',
|
|
||||||
user: 'System',
|
|
||||||
client: 'debug-seed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await Chat.insertMany(messages);
|
|
||||||
|
|
||||||
res.respond(200, { messageCount });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Messaging ourselves for testing
|
|
||||||
api.seedInbox = {
|
|
||||||
method: 'POST',
|
|
||||||
url: '/debug/seed-inbox',
|
|
||||||
middlewares: [ensureDevelopmentMode, authWithHeaders()],
|
|
||||||
async handler (req, res) {
|
|
||||||
const { user } = res.locals;
|
|
||||||
const messageCount = Number(req.body.messageCount);
|
|
||||||
|
|
||||||
if (!Number.isInteger(messageCount) || messageCount < 1) {
|
|
||||||
throw new BadRequest('messageCount must be a positive integer.');
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = [];
|
|
||||||
const baseTimestamp = Date.now();
|
|
||||||
|
|
||||||
for (let i = 1; i <= messageCount; i += 1) {
|
|
||||||
const id = uuid();
|
|
||||||
messages.push({
|
|
||||||
_id: id,
|
|
||||||
id,
|
|
||||||
ownerId: user._id,
|
|
||||||
uuid: user._id,
|
|
||||||
user: user.profile.name,
|
|
||||||
text: `#${i}`,
|
|
||||||
unformattedText: `#${i}`,
|
|
||||||
timestamp: new Date(baseTimestamp - (messageCount - i) * 1000),
|
|
||||||
likes: {},
|
|
||||||
flags: {},
|
|
||||||
flagCount: 0,
|
|
||||||
sent: true,
|
|
||||||
client: 'debug-seed',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await Inbox.insertMany(messages);
|
|
||||||
|
|
||||||
res.respond(200, { messageCount });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default api;
|
export default api;
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ import { // eslint-disable-line import/no-cycle
|
|||||||
const questScrolls = shared.content.quests;
|
const questScrolls = shared.content.quests;
|
||||||
|
|
||||||
// @TODO: Don't use this method when the group can be saved.
|
// @TODO: Don't use this method when the group can be saved.
|
||||||
export async function getGroupChat (group, options = {}) {
|
export async function getGroupChat (group) {
|
||||||
const { limit, before } = options;
|
|
||||||
|
|
||||||
let maxChatCount = MAX_CHAT_COUNT;
|
let maxChatCount = MAX_CHAT_COUNT;
|
||||||
if (group.chatLimitCount && group.chatLimitCount >= MAX_CHAT_COUNT) {
|
if (group.chatLimitCount && group.chatLimitCount >= MAX_CHAT_COUNT) {
|
||||||
maxChatCount = group.chatLimitCount;
|
maxChatCount = group.chatLimitCount;
|
||||||
@@ -19,19 +17,10 @@ export async function getGroupChat (group, options = {}) {
|
|||||||
maxChatCount = MAX_SUBBED_GROUP_CHAT_COUNT;
|
maxChatCount = MAX_SUBBED_GROUP_CHAT_COUNT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const effectiveLimit = limit !== undefined ? Math.min(limit, maxChatCount) : maxChatCount;
|
const groupChat = await Chat.find({ groupId: group._id })
|
||||||
|
.limit(maxChatCount)
|
||||||
let query = Chat.find({ groupId: group._id })
|
.sort('-timestamp')
|
||||||
.sort('-timestamp');
|
.exec();
|
||||||
|
|
||||||
if (before) {
|
|
||||||
const beforeMessage = await Chat.findOne({ _id: before }).exec();
|
|
||||||
if (beforeMessage) {
|
|
||||||
query = query.where('timestamp').lt(beforeMessage.timestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const groupChat = await query.limit(effectiveLimit).exec();
|
|
||||||
|
|
||||||
// @TODO: Concat old chat to keep continuity of chat stored on group object
|
// @TODO: Concat old chat to keep continuity of chat stored on group object
|
||||||
const currentGroupChat = group.chat || [];
|
const currentGroupChat = group.chat || [];
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ export async function sentMessage (sender, receiver, message, translate) {
|
|||||||
|
|
||||||
return messageSent;
|
return messageSent;
|
||||||
}
|
}
|
||||||
// Paginate per every 50
|
const PM_PER_PAGE = 10;
|
||||||
const PM_PER_PAGE = 50;
|
|
||||||
const MAX_PM_COUNT = 400;
|
|
||||||
|
|
||||||
const getUserInboxDefaultOptions = {
|
const getUserInboxDefaultOptions = {
|
||||||
asArray: true,
|
asArray: true,
|
||||||
@@ -63,18 +61,12 @@ export async function getUserInbox (user, optionParams = getUserInboxDefaultOpti
|
|||||||
.sort({ timestamp: -1 });
|
.sort({ timestamp: -1 });
|
||||||
|
|
||||||
if (typeof options.page !== 'undefined') {
|
if (typeof options.page !== 'undefined') {
|
||||||
const page = Number(options.page);
|
|
||||||
const skip = PM_PER_PAGE * page;
|
|
||||||
if (skip >= MAX_PM_COUNT) {
|
|
||||||
return options.asArray ? [] : {};
|
|
||||||
}
|
|
||||||
const remainingAllowed = MAX_PM_COUNT - skip;
|
|
||||||
const limit = Math.min(PM_PER_PAGE, remainingAllowed);
|
|
||||||
query = query
|
query = query
|
||||||
.skip(skip)
|
.skip(PM_PER_PAGE * Number(options.page))
|
||||||
.limit(limit);
|
.limit(PM_PER_PAGE);
|
||||||
} else {
|
} else {
|
||||||
query = query.limit(MAX_PM_COUNT);
|
// Limit for legacy calls that are not paginated to prevent database issues
|
||||||
|
query = query.limit(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
const messages = (await query.lean().exec()).map(msgObj => {
|
const messages = (await query.lean().exec()).map(msgObj => {
|
||||||
|
|||||||
@@ -68,13 +68,29 @@ export default function attachMiddlewares (app, server) {
|
|||||||
// New middlewares added by default in Helmet 4 are disabled
|
// New middlewares added by default in Helmet 4 are disabled
|
||||||
contentSecurityPolicy: {
|
contentSecurityPolicy: {
|
||||||
directives: {
|
directives: {
|
||||||
imgSrc: null,
|
defaultSrc: [
|
||||||
|
'*.habitica.com',
|
||||||
|
'*.amazon.com',
|
||||||
|
'*.amazonaws.com',
|
||||||
|
'*.loggly.com',
|
||||||
|
'*.payments-amazon.com',
|
||||||
|
'*.stripe.com',
|
||||||
|
'*.stripe.network',
|
||||||
|
],
|
||||||
|
imgSrc: [
|
||||||
|
'*',
|
||||||
|
'data:',
|
||||||
|
],
|
||||||
scriptSrc: [
|
scriptSrc: [
|
||||||
'\'self\'',
|
'\'unsafe-eval\'',
|
||||||
'cloudfront.loggly.com',
|
'\'unsafe-inline\'',
|
||||||
'js.stripe.com',
|
'*.habitica.com',
|
||||||
'm.stripe.network',
|
'*.amazon.com',
|
||||||
'static-na.payments-amazon.com',
|
'*.amazonaws.com',
|
||||||
|
'*.loggly.com',
|
||||||
|
'*.payments-amazon.com',
|
||||||
|
'*.stripe.com',
|
||||||
|
'*.stripe.network',
|
||||||
],
|
],
|
||||||
upgradeInsecureRequests: IS_PROD ? [] : null,
|
upgradeInsecureRequests: IS_PROD ? [] : null,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -345,12 +345,12 @@ schema.statics.getGroups = async function getGroups (options = {}) {
|
|||||||
// unless the user is an admin or said chat is posted by that user
|
// unless the user is an admin or said chat is posted by that user
|
||||||
// Not putting into toJSON because there we can't access user
|
// Not putting into toJSON because there we can't access user
|
||||||
// It also removes the _meta field that can be stored inside a chat message
|
// It also removes the _meta field that can be stored inside a chat message
|
||||||
schema.statics.toJSONCleanChat = async function groupToJSONCleanChat (group, user, options = {}) {
|
schema.statics.toJSONCleanChat = async function groupToJSONCleanChat (group, user) {
|
||||||
// @TODO: Adding this here for support the old chat,
|
// @TODO: Adding this here for support the old chat,
|
||||||
// but we should depreciate accessing chat like this
|
// but we should depreciate accessing chat like this
|
||||||
// Also only return chat if requested, eventually we don't want to return chat here
|
// Also only return chat if requested, eventually we don't want to return chat here
|
||||||
if (group && group.chat) {
|
if (group && group.chat) {
|
||||||
await getGroupChat(group, options);
|
await getGroupChat(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupToJson = group.toJSON();
|
const groupToJson = group.toJSON();
|
||||||
|
|||||||
Reference in New Issue
Block a user