Skip to content

Commit

Permalink
Updates tweaks and bug fixes (#10089)
Browse files Browse the repository at this point in the history
* fix: lost update when audience is set to NO_ONE

* refact: allow isChangelog to be updated

* refact: expose drafts in Account.updates resolver

* refact: allow notificationAudience to be pre-set and saved with drafts
  • Loading branch information
kewitz committed May 14, 2024
1 parent 151c646 commit 611dc51
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
5 changes: 4 additions & 1 deletion server/graphql/common/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export async function createUpdate(_, args, req) {
CreatedByUserId: req.remoteUser.id,
FromCollectiveId: req.remoteUser.CollectiveId,
makePublicOn: args.update.makePublicOn,
notificationAudience: args.update.notificationAudience,
});

purgeCacheForCollective(collective.slug);
Expand Down Expand Up @@ -76,7 +77,7 @@ export async function publishUpdate(_, args, req) {
checkRemoteUserCanUseUpdates(req);

let update = await fetchUpdateForEdit(args.id, req);
update = await update.publish(req.remoteUser, args.notificationAudience);
update = await update.publish(req.remoteUser, args.notificationAudience || update.notificationAudience);
if (update.isChangelog) {
cache.delete('latest_changelog_publish_date');
}
Expand Down Expand Up @@ -149,6 +150,8 @@ export async function canSeeUpdate(update, req): Promise<boolean> {
canSeeUpdateForFinancialContributors(req, update.collective) ||
canSeeUpdateForCollectiveAdmins(req, update.collective)
);
case UPDATE_NOTIFICATION_AUDIENCE.NO_ONE:
return req.remoteUser.isAdminOfCollective(update.collective);
default:
return false; // Audience type is NO_ONE or unknown
}
Expand Down
3 changes: 3 additions & 0 deletions server/graphql/v2/input/UpdateCreateInput.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { GraphQLBoolean, GraphQLInputObjectType, GraphQLNonNull, GraphQLString } from 'graphql';
import { GraphQLDateTime } from 'graphql-scalars';

import { GraphQLUpdateAudienceType } from '../enum';

import { GraphQLAccountReferenceInput } from './AccountReferenceInput';

export const GraphQLUpdateCreateInput = new GraphQLInputObjectType({
Expand All @@ -14,5 +16,6 @@ export const GraphQLUpdateCreateInput = new GraphQLInputObjectType({
html: { type: new GraphQLNonNull(GraphQLString) },
fromAccount: { type: GraphQLAccountReferenceInput },
account: { type: new GraphQLNonNull(GraphQLAccountReferenceInput) },
notificationAudience: { type: GraphQLUpdateAudienceType },
}),
});
4 changes: 4 additions & 0 deletions server/graphql/v2/input/UpdateUpdateInput.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { GraphQLBoolean, GraphQLInputObjectType, GraphQLNonNull, GraphQLString } from 'graphql';
import { GraphQLDateTime } from 'graphql-scalars';

import { GraphQLUpdateAudienceType } from '../enum';

import { GraphQLAccountReferenceInput } from './AccountReferenceInput';

export const GraphQLUpdateUpdateInput = new GraphQLInputObjectType({
Expand All @@ -11,8 +13,10 @@ export const GraphQLUpdateUpdateInput = new GraphQLInputObjectType({
slug: { type: GraphQLString },
title: { type: GraphQLString },
isPrivate: { type: GraphQLBoolean },
isChangelog: { type: GraphQLBoolean },
makePublicOn: { type: GraphQLDateTime },
html: { type: GraphQLString },
fromAccount: { type: GraphQLAccountReferenceInput },
notificationAudience: { type: GraphQLUpdateAudienceType },
}),
});
11 changes: 10 additions & 1 deletion server/graphql/v2/interface/Account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,20 +488,29 @@ const accountFieldsDefinition = () => ({
defaultValue: false,
description: 'Only return published updates.',
},
isDraft: {
type: GraphQLBoolean,
},
onlyChangelogUpdates: { type: GraphQLBoolean },
orderBy: {
type: new GraphQLNonNull(GraphQLUpdateChronologicalOrderInput),
defaultValue: UPDATE_CHRONOLOGICAL_ORDER_INPUT_DEFAULT_VALUE,
},
searchTerm: { type: GraphQLString },
},
async resolve(collective, { limit, offset, onlyPublishedUpdates, onlyChangelogUpdates, orderBy, searchTerm }, req) {
async resolve(
collective,
{ limit, offset, onlyPublishedUpdates, isDraft, onlyChangelogUpdates, orderBy, searchTerm },
req,
) {
let where = {
CollectiveId: collective.id,
[Op.and]: [],
};
if (onlyPublishedUpdates || !req.remoteUser?.isAdminOfCollective(collective) || !checkScope(req, 'updates')) {
where = assign(where, { publishedAt: { [Op.ne]: null } });
} else if (isDraft) {
where = assign(where, { publishedAt: null });
}
if (onlyChangelogUpdates) {
where = assign(where, { isChangelog: true });
Expand Down
19 changes: 18 additions & 1 deletion server/models/Update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,24 @@ class Update extends Model<InferAttributes<Update>, InferCreationAttributes<Upda
}
}

const editableAttributes = ['TierId', 'title', 'html', 'tags', 'isPrivate', 'isChangelog', 'makePublicOn'];
if (
this.publishedAt &&
newUpdateData.notificationAudience &&
newUpdateData.notificationAudience !== this.notificationAudience
) {
throw new errors.ValidationFailed('Cannot change the notification audience of a published update');
}

const editableAttributes = [
'TierId',
'title',
'html',
'tags',
'isPrivate',
'isChangelog',
'makePublicOn',
'notificationAudience',
];

return await this.update({
...pick(newUpdateData, editableAttributes),
Expand Down
22 changes: 22 additions & 0 deletions test/server/graphql/v2/mutation/UpdateMutations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,27 @@ describe('server/graphql/v2/mutation/UpdateMutations', () => {
expect(result.data.editUpdate.slug).to.equal('new-title');
});

it('fails if user tries to update notificationAudience of a published update', async () => {
await models.Update.update(
{ slug: 'first-update-and-love', publishedAt: new Date(), notificationAudience: 'FINANCIAL_CONTRIBUTORS' },
{ where: { id: update1.id } },
);
const result = await utils.graphqlQueryV2(
editUpdateMutation,
{
update: {
id: idEncode(update1.id, IDENTIFIER_TYPES.UPDATE),
title: 'new title',
notificationAudience: 'NO_ONE',
},
},
user1,
);

expect(result.errors).to.exist;
expect(result.errors[0].message).to.equal('Cannot change the notification audience of a published update');
});

it("edits an update successfully and doesn't change the slug if published", async () => {
await models.Update.update(
{ slug: 'first-update-and-love', publishedAt: new Date() },
Expand All @@ -339,6 +360,7 @@ describe('server/graphql/v2/mutation/UpdateMutations', () => {
{ update: { id: idEncode(update1.id, IDENTIFIER_TYPES.UPDATE), title: 'new title' } },
user1,
);
result.errors && console.error(result.errors[0]);
expect(result.errors).to.not.exist;
expect(result.data.editUpdate.slug).to.equal('first-update-and-love');
await models.Update.update({ publishedAt: null }, { where: { id: update1.id } });
Expand Down

0 comments on commit 611dc51

Please sign in to comment.