mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-14 13:17:24 +01:00
Squashed commit of the following:
commit d30dff2311087ff2fe5f3e2a913c594abeee6b0e Author: Sabe Jones <sabe@habitica.com> Date: Tue Feb 27 16:01:11 2024 -0600 fix(challenge): move isOfficial to mount process commit ae52dca3cd0b4fd490f07b1979049803ce2f1e2f Merge: 2b20ff1e462c6e82a58aAuthor: Sabe Jones <sabe@habitica.com> Date: Tue Feb 27 15:20:40 2024 -0600 Merge branch 'release' into phillip/challenges_official commit 2b20ff1e46b1447eac3f9dbdf29566154c9fa656 Author: Sabe Jones <sabe@habitica.com> Date: Wed Feb 14 15:31:22 2024 -0600 fix(tests): correct lint and TypeError commit 5dae5c716f11db4c652e423eab43805ddfac3455 Merge: 29d9edc7aa1a3c2f64e4Author: Sabe Jones <sabe@habitica.com> Date: Wed Feb 14 15:01:18 2024 -0600 Merge branch 'release' into phillip/challenges_official commit 29d9edc7aa7445d24f5be24ca923719a4ab5f70d Author: Sabe Jones <sabe@habitica.com> Date: Wed Feb 14 14:41:16 2024 -0600 fix(challenges): don't momentarily show Report on official commit f994d12775107cba7ec816ee522cfeb0c69ef567 Author: Phillip Thelen <phillip@habitica.com> Date: Tue Feb 13 10:08:08 2024 +0100 hide report button for official challenges commit ac06dcaca701b91913d5fc5307626b1616a9e0e8 Author: Phillip Thelen <phillip@habitica.com> Date: Tue Feb 13 10:04:49 2024 +0100 prevent official challenges from being flagged commit a07ce1e6de66a2c833c6f392cf396a7743ca0f97 Author: Phillip Thelen <phillip@habitica.com> Date: Mon Feb 5 19:12:17 2024 +0100 test shouldn’t be exclusive commit 4c2436a1a0fa905530b7e1cd66f75a2b07be5810 Author: Phillip Thelen <phillip@habitica.com> Date: Mon Feb 5 19:11:20 2024 +0100 remove log commit 292f3a578d51fd08c572afc574cc73d08356f46a Author: Phillip Thelen <phillip@habitica.com> Date: Mon Feb 5 19:10:13 2024 +0100 Automatically set official field on challenges if habitica_official cateogory is set
This commit is contained in:
@@ -7,6 +7,7 @@ import {
|
|||||||
|
|
||||||
describe('POST /challenges/:challengeId/flag', () => {
|
describe('POST /challenges/:challengeId/flag', () => {
|
||||||
let user;
|
let user;
|
||||||
|
let challengeGroup;
|
||||||
let challenge;
|
let challenge;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@@ -20,6 +21,7 @@ describe('POST /challenges/:challengeId/flag', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
user = groupLeader;
|
user = groupLeader;
|
||||||
|
challengeGroup = group;
|
||||||
|
|
||||||
challenge = await generateChallenge(user, group);
|
challenge = await generateChallenge(user, group);
|
||||||
});
|
});
|
||||||
@@ -59,4 +61,19 @@ describe('POST /challenges/:challengeId/flag', () => {
|
|||||||
message: t('messageChallengeFlagAlreadyReported'),
|
message: t('messageChallengeFlagAlreadyReported'),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns an error when user tries to flag an official challenge', async () => {
|
||||||
|
await user.updateOne({
|
||||||
|
permissions: {
|
||||||
|
challengeAdmin: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
challenge = await generateChallenge(user, challengeGroup, { official: true });
|
||||||
|
await expect(user.post(`/challenges/${challenge._id}/flag`))
|
||||||
|
.to.eventually.be.rejected.and.eql({
|
||||||
|
code: 404,
|
||||||
|
error: 'NotFound',
|
||||||
|
message: t('messageChallengeFlagOfficial'),
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -331,5 +331,71 @@ describe('POST /challenges', () => {
|
|||||||
|
|
||||||
expect(updatedChallenge.summary).to.eql(summary);
|
expect(updatedChallenge.summary).to.eql(summary);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sets categories for challenges', async () => {
|
||||||
|
const testCategory = { _id: '65c1172997c0b24600371ea9', slug: 'test', name: 'Test' };
|
||||||
|
const challenge = await groupLeader.post('/challenges', {
|
||||||
|
group: group._id,
|
||||||
|
name: 'Test Challenge',
|
||||||
|
shortName: 'TC Label',
|
||||||
|
categories: [testCategory],
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedChallenge = await groupLeader.get(`/challenges/${challenge._id}`);
|
||||||
|
|
||||||
|
expect(updatedChallenge.categories).to.eql([testCategory]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not set habitica_official category for non-admins', async () => {
|
||||||
|
const testCategory = { _id: '65c1172997c0b24600371ea9', slug: 'habitica_official', name: 'habitica_official' };
|
||||||
|
await expect(groupLeader.post('/challenges', {
|
||||||
|
group: group._id,
|
||||||
|
name: 'Test Challenge',
|
||||||
|
shortName: 'TC Label',
|
||||||
|
categories: [testCategory],
|
||||||
|
})).to.eventually.be.rejected.and.eql({
|
||||||
|
code: 401,
|
||||||
|
error: 'NotAuthorized',
|
||||||
|
message: t('noPrivAccess'),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets habitica_official category for admins', async () => {
|
||||||
|
await groupLeader.updateOne({
|
||||||
|
permissions: {
|
||||||
|
challengeAdmin: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const testCategory = { _id: '65c1172997c0b24600371ea9', slug: 'habitica_official', name: 'habitica_official' };
|
||||||
|
const challenge = await groupLeader.post('/challenges', {
|
||||||
|
group: group._id,
|
||||||
|
name: 'Test Challenge',
|
||||||
|
shortName: 'TC Label',
|
||||||
|
categories: [testCategory],
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedChallenge = await groupLeader.get(`/challenges/${challenge._id}`);
|
||||||
|
expect(updatedChallenge.categories).to.eql([testCategory]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets official if the habitica_official category is set for admins', async () => {
|
||||||
|
await groupLeader.updateOne({
|
||||||
|
permissions: {
|
||||||
|
challengeAdmin: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const testCategory = { _id: '65c1172997c0b24600371ea9', slug: 'habitica_official', name: 'habitica_official' };
|
||||||
|
const challenge = await groupLeader.post('/challenges', {
|
||||||
|
group: group._id,
|
||||||
|
name: 'Test Challenge',
|
||||||
|
shortName: 'TC Label',
|
||||||
|
categories: [testCategory],
|
||||||
|
});
|
||||||
|
|
||||||
|
const updatedChallenge = await groupLeader.get(`/challenges/${challenge._id}`);
|
||||||
|
expect(updatedChallenge.official).to.eql(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -223,6 +223,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
v-if="!isOfficial"
|
||||||
class="button-container"
|
class="button-container"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@@ -433,6 +434,7 @@ export default {
|
|||||||
taskFormPurpose: 'create',
|
taskFormPurpose: 'create',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
memberResults: [],
|
memberResults: [],
|
||||||
|
isOfficial: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -478,9 +480,11 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted () {
|
async mounted () {
|
||||||
if (!this.searchId) this.searchId = this.challengeId;
|
if (!this.searchId) this.searchId = this.challengeId;
|
||||||
if (!this.challenge._id) this.loadChallenge();
|
if (!this.challenge._id) await this.loadChallenge();
|
||||||
|
this.isOfficial = this.challenge.official
|
||||||
|
|| this.challenge.categories?.some(category => category.name === 'habitica_official');
|
||||||
this.handleExternalLinks();
|
this.handleExternalLinks();
|
||||||
},
|
},
|
||||||
updated () {
|
updated () {
|
||||||
@@ -640,9 +644,6 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
async exportChallengeCsv () {
|
async exportChallengeCsv () {
|
||||||
// let response = await this.$store.dispatch('challenges:exportChallengeCsv', {
|
|
||||||
// challengeId: this.searchId,
|
|
||||||
// });
|
|
||||||
window.location = `/api/v4/challenges/${this.searchId}/export/csv`;
|
window.location = `/api/v4/challenges/${this.searchId}/export/csv`;
|
||||||
},
|
},
|
||||||
cloneChallenge () {
|
cloneChallenge () {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@
|
|||||||
"yourReward": "Your Reward",
|
"yourReward": "Your Reward",
|
||||||
"wonChallengeDesc": "<%= challengeName %> selected you as the winner! Your win has been recorded in your Achievements.",
|
"wonChallengeDesc": "<%= challengeName %> selected you as the winner! Your win has been recorded in your Achievements.",
|
||||||
"messageChallengeFlagAlreadyReported": "You have already reported this Challenge.",
|
"messageChallengeFlagAlreadyReported": "You have already reported this Challenge.",
|
||||||
|
"messageChallengeFlagOfficial": "Official Challenges can not be reported.",
|
||||||
"flaggedNotHidden": "Challenge flagged once, not hidden",
|
"flaggedNotHidden": "Challenge flagged once, not hidden",
|
||||||
"flaggedAndHidden": "Challenge flagged and hidden",
|
"flaggedAndHidden": "Challenge flagged and hidden",
|
||||||
"resetFlagCount": "Reset Flag Count",
|
"resetFlagCount": "Reset Flag Count",
|
||||||
|
|||||||
@@ -61,6 +61,14 @@ export async function createChallenge (user, req, res) {
|
|||||||
}
|
}
|
||||||
req.body.leader = user._id;
|
req.body.leader = user._id;
|
||||||
req.body.official = !!(user.hasPermission('challengeAdmin') && req.body.official);
|
req.body.official = !!(user.hasPermission('challengeAdmin') && req.body.official);
|
||||||
|
const categories = req.body.categories || [];
|
||||||
|
categories.forEach(category => {
|
||||||
|
if (category.slug === 'habitica_official' && !user.hasPermission('challengeAdmin')) {
|
||||||
|
throw new NotAuthorized(res.t('noPrivAccess'));
|
||||||
|
} else if (category.slug === 'habitica_official' && user.hasPermission('challengeAdmin')) {
|
||||||
|
req.body.official = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
const challenge = new Challenge(Challenge.sanitize(req.body));
|
const challenge = new Challenge(Challenge.sanitize(req.body));
|
||||||
|
|
||||||
// First validate challenge so we don't save group if it's invalid (only runs sync validators)
|
// First validate challenge so we don't save group if it's invalid (only runs sync validators)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export async function notifyOfFlaggedChallenge (challenge, user, userComment) {
|
|||||||
|
|
||||||
export async function flagChallenge (challenge, user, res) {
|
export async function flagChallenge (challenge, user, res) {
|
||||||
if (challenge.flags[user._id] && !user.contributor.admin) throw new NotFound(res.t('messageChallengeFlagAlreadyReported'));
|
if (challenge.flags[user._id] && !user.contributor.admin) throw new NotFound(res.t('messageChallengeFlagAlreadyReported'));
|
||||||
|
if (challenge.official) throw new NotFound(res.t('messageChallengeFlagOfficial'));
|
||||||
|
|
||||||
challenge.flags[user._id] = true;
|
challenge.flags[user._id] = true;
|
||||||
challenge.markModified('flags');
|
challenge.markModified('flags');
|
||||||
|
|||||||
Reference in New Issue
Block a user