Skip to content

Commit b2ca568

Browse files
committed
fix(api-headless-cms-scheduler): validate if entries can be updated
1 parent 628450d commit b2ca568

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

packages/api-headless-cms-scheduler/src/scheduler/actions/PublishScheduleAction.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ import {
88
} from "~/scheduler/types.js";
99
import { createScheduleRecord, transformScheduleEntry } from "~/scheduler/ScheduleRecord.js";
1010
import { convertException } from "@webiny/utils";
11-
import type { CmsIdentity, CmsModel, HeadlessCms } from "@webiny/api-headless-cms/types";
11+
import type {
12+
CmsEntry,
13+
CmsEntryValues,
14+
CmsIdentity,
15+
CmsModel,
16+
HeadlessCms
17+
} from "@webiny/api-headless-cms/types";
1218
import type { ISchedulerService } from "~/service/types.js";
1319
import { dateToISOString } from "~/scheduler/dates.js";
1420
import { NotFoundError } from "@webiny/handler-graphql";
1521
import { dateInTheFuture } from "~/utils/dateInTheFuture.js";
22+
import { WebinyError } from "@webiny/error/index";
1623

1724
export type PublishScheduleActionCms = Pick<
1825
HeadlessCms,
@@ -49,7 +56,8 @@ export class PublishScheduleAction implements IScheduleAction {
4956
public async schedule(params: IScheduleActionScheduleParams): Promise<IScheduleRecord> {
5057
const { targetId, input, scheduleRecordId } = params;
5158

52-
const targetEntry = await this.cms.getEntryById(this.targetModel, targetId);
59+
const targetEntry = await this.getUpdateableTargetEntry(targetId);
60+
5361
const title = targetEntry.values[this.targetModel.titleFieldId] || "Unknown entry title";
5462
const identity = this.getIdentity();
5563

@@ -138,16 +146,23 @@ export class PublishScheduleAction implements IScheduleAction {
138146
): Promise<IScheduleRecord> {
139147
const currentDate = new Date();
140148
const targetId = original.targetId;
149+
150+
const targetEntry = await this.getUpdateableTargetEntry(targetId);
151+
141152
/**
142153
* There are two cases when we can immediately publish the entry:
143154
* 1. If the user requested it.
144155
* 2. If the entry is scheduled for a date in the past.
145156
*/
146157
if (input.immediately || input.scheduleOn < currentDate) {
147-
const updatedTargetEntry = await this.cms.updateEntry(this.targetModel, targetId, {
148-
lastPublishedOn: input.dateOn ? input.dateOn.toISOString() : undefined,
149-
lastPublishedBy: this.getIdentity()
150-
});
158+
const updatedTargetEntry = await this.cms.updateEntry(
159+
this.targetModel,
160+
targetEntry.id,
161+
{
162+
lastPublishedOn: input.dateOn ? input.dateOn.toISOString() : undefined,
163+
lastPublishedBy: this.getIdentity()
164+
}
165+
);
151166

152167
const publishedEntry = await this.cms.publishEntry(
153168
this.targetModel,
@@ -227,4 +242,18 @@ export class PublishScheduleAction implements IScheduleAction {
227242
throw ex;
228243
}
229244
}
245+
246+
private async getUpdateableTargetEntry<T = CmsEntryValues>(id: string): Promise<CmsEntry<T>> {
247+
const entry = await this.cms.getEntryById<T>(this.targetModel, id);
248+
if (entry.locked) {
249+
throw new WebinyError(
250+
`Cannot schedule a publish action for entry "${entry.id}" because it is locked.`,
251+
"ENTRY_LOCKED",
252+
{
253+
entryId: entry.id
254+
}
255+
);
256+
}
257+
return entry;
258+
}
230259
}

packages/api-headless-cms-scheduler/src/scheduler/actions/UnpublishScheduleAction.ts

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ import {
88
} from "~/scheduler/types.js";
99
import { createScheduleRecord, transformScheduleEntry } from "~/scheduler/ScheduleRecord.js";
1010
import { convertException } from "@webiny/utils";
11-
import type { CmsIdentity, CmsModel, HeadlessCms } from "@webiny/api-headless-cms/types";
11+
import type {
12+
CmsEntry,
13+
CmsEntryValues,
14+
CmsIdentity,
15+
CmsModel,
16+
HeadlessCms
17+
} from "@webiny/api-headless-cms/types";
1218
import type { ISchedulerService } from "~/service/types.js";
1319
import { dateToISOString } from "~/scheduler/dates.js";
1420
import { NotFoundError } from "@webiny/handler-graphql";
1521
import { dateInTheFuture } from "~/utils/dateInTheFuture.js";
22+
import { WebinyError } from "@webiny/error";
1623

1724
export type UnpublishScheduleActionCms = Pick<
1825
HeadlessCms,
@@ -49,7 +56,7 @@ export class UnpublishScheduleAction implements IScheduleAction {
4956
public async schedule(params: IScheduleActionScheduleParams): Promise<IScheduleRecord> {
5057
const { targetId, input, scheduleRecordId } = params;
5158

52-
const targetEntry = await this.cms.getEntryById(this.targetModel, targetId);
59+
const targetEntry = await this.getUpdateableTargetEntry(targetId);
5360
const title = targetEntry.values[this.targetModel.titleFieldId] || "Unknown entry title";
5461
const identity = this.getIdentity();
5562

@@ -131,13 +138,15 @@ export class UnpublishScheduleAction implements IScheduleAction {
131138
): Promise<IScheduleRecord> {
132139
const currentDate = new Date();
133140
const targetId = original.targetId;
141+
142+
const targetEntry = await this.getUpdateableTargetEntry(targetId);
134143
/**
135144
* There are two cases when we can immediately publish the entry:
136145
* 1. If the user requested it.
137146
* 2. If the entry is scheduled for a date in the past.
138147
*/
139148
if (input.immediately || dateInTheFuture(input.scheduleOn)) {
140-
const publishedEntry = await this.cms.unpublishEntry(this.targetModel, targetId);
149+
const publishedEntry = await this.cms.unpublishEntry(this.targetModel, targetEntry.id);
141150
/**
142151
* We can safely cancel the original schedule entry and the event.
143152
*
@@ -217,4 +226,18 @@ export class UnpublishScheduleAction implements IScheduleAction {
217226
throw ex;
218227
}
219228
}
229+
230+
private async getUpdateableTargetEntry<T = CmsEntryValues>(id: string): Promise<CmsEntry<T>> {
231+
const entry = await this.cms.getEntryById<T>(this.targetModel, id);
232+
if (entry.locked) {
233+
throw new WebinyError(
234+
`Cannot schedule a unpublish action for entry "${entry.id}" because it is locked.`,
235+
"ENTRY_LOCKED",
236+
{
237+
entryId: entry.id
238+
}
239+
);
240+
}
241+
return entry;
242+
}
220243
}

0 commit comments

Comments
 (0)