@webiny/api-headless-cms-scheduler 6.5.1 → 6.5.2-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.d.ts +3 -1
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.js +7 -4
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.js.map +1 -1
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.d.ts +3 -1
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.js +12 -9
- package/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.js.map +1 -1
- package/features/NamespaceHandler/NamespaceHandler.d.ts +3 -1
- package/features/NamespaceHandler/NamespaceHandler.js +13 -3
- package/features/NamespaceHandler/NamespaceHandler.js.map +1 -1
- package/package.json +14 -14
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EntryAfterDeleteEventHandler } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events";
|
|
2
2
|
import { CancelScheduledActionUseCase, ListScheduledActionsUseCase } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
3
3
|
import { Logger } from "@webiny/api-core/exports/api/logger.js";
|
|
4
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* Cancels scheduled actions when an entry is deleted
|
|
6
7
|
*
|
|
@@ -12,7 +13,8 @@ declare class CancelScheduledActionOnEntryDeleteHandlerImpl implements EntryAfte
|
|
|
12
13
|
private listScheduledActions;
|
|
13
14
|
private cancelScheduledAction;
|
|
14
15
|
private logger;
|
|
15
|
-
|
|
16
|
+
private identityContext;
|
|
17
|
+
constructor(listScheduledActions: ListScheduledActionsUseCase.Interface, cancelScheduledAction: CancelScheduledActionUseCase.Interface, logger: Logger.Interface, identityContext: IdentityContext.Interface);
|
|
16
18
|
handle(event: EntryAfterDeleteEventHandler.Event): Promise<void>;
|
|
17
19
|
private listSchedules;
|
|
18
20
|
}
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { EntryAfterDeleteEventHandler } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events";
|
|
2
2
|
import { CancelScheduledActionUseCase, ListScheduledActionsUseCase } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
3
3
|
import { Logger } from "@webiny/api-core/exports/api/logger.js";
|
|
4
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
5
|
import { createNamespace } from "../../utils/namespace.js";
|
|
5
6
|
class CancelScheduledActionOnEntryDeleteHandlerImpl {
|
|
6
|
-
constructor(listScheduledActions, cancelScheduledAction, logger){
|
|
7
|
+
constructor(listScheduledActions, cancelScheduledAction, logger, identityContext){
|
|
7
8
|
this.listScheduledActions = listScheduledActions;
|
|
8
9
|
this.cancelScheduledAction = cancelScheduledAction;
|
|
9
10
|
this.logger = logger;
|
|
11
|
+
this.identityContext = identityContext;
|
|
10
12
|
}
|
|
11
13
|
async handle(event) {
|
|
12
14
|
const { entry, model } = event.payload;
|
|
13
15
|
if (model.isPrivate) return;
|
|
14
|
-
const schedules = await this.listSchedules(model.modelId, entry.entryId);
|
|
16
|
+
const schedules = await this.identityContext.withoutAuthorization(()=>this.listSchedules(model.modelId, entry.entryId));
|
|
15
17
|
for (const action of schedules){
|
|
16
|
-
const cancelRes = await this.cancelScheduledAction.execute(action);
|
|
18
|
+
const cancelRes = await this.identityContext.withoutAuthorization(()=>this.cancelScheduledAction.execute(action));
|
|
17
19
|
cancelRes.isFail();
|
|
18
20
|
}
|
|
19
21
|
}
|
|
@@ -39,7 +41,8 @@ const CancelScheduledActionOnEntryDeleteEventHandler = EntryAfterDeleteEventHand
|
|
|
39
41
|
dependencies: [
|
|
40
42
|
ListScheduledActionsUseCase,
|
|
41
43
|
CancelScheduledActionUseCase,
|
|
42
|
-
Logger
|
|
44
|
+
Logger,
|
|
45
|
+
IdentityContext
|
|
43
46
|
]
|
|
44
47
|
});
|
|
45
48
|
export { CancelScheduledActionOnEntryDeleteEventHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.js","sources":["../../../src/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.ts"],"sourcesContent":["import { EntryAfterDeleteEventHandler } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events\";\nimport {\n CancelScheduledActionUseCase,\n ListScheduledActionsUseCase\n} from \"@webiny/api-scheduler/exports/api/scheduler.js\";\nimport { Logger } from \"@webiny/api-core/exports/api/logger.js\";\nimport { createNamespace } from \"~/utils/namespace.js\";\n\n/**\n * Cancels scheduled actions when an entry is deleted\n *\n * When a user deletes an entry, any scheduled publish/unpublish\n * actions for all of its revisions should be canceled since the entry\n * no longer exists.\n */\nclass CancelScheduledActionOnEntryDeleteHandlerImpl\n implements EntryAfterDeleteEventHandler.Interface\n{\n constructor(\n private listScheduledActions: ListScheduledActionsUseCase.Interface,\n private cancelScheduledAction: CancelScheduledActionUseCase.Interface,\n private logger: Logger.Interface\n ) {}\n\n async handle(event: EntryAfterDeleteEventHandler.Event): Promise<void> {\n const { entry, model } = event.payload;\n\n // Skip private models\n if (model.isPrivate) {\n return;\n }\n\n const schedules = await this.listSchedules(model.modelId, entry.entryId);\n for (const action of schedules) {\n const cancelRes = await this.cancelScheduledAction.execute(action);\n if (cancelRes.isFail()) {\n // Silently ignore errors - this is non-critical cleanup.\n // The entry was deleted successfully, cancelling scheduled actions is best-effort.\n }\n }\n }\n\n private async listSchedules(modelId: string, entryId: string) {\n const actionsResult = await this.listScheduledActions.execute({\n limit: 10000,\n where: {\n namespace: createNamespace({ modelId }),\n targetId_startsWith: `${entryId}#`\n }\n });\n\n if (actionsResult.isFail()) {\n this.logger.error(actionsResult.error);\n return [];\n }\n\n return actionsResult.value.items;\n }\n}\n\nexport const CancelScheduledActionOnEntryDeleteEventHandler =\n EntryAfterDeleteEventHandler.createImplementation({\n implementation: CancelScheduledActionOnEntryDeleteHandlerImpl,\n dependencies: [ListScheduledActionsUseCase
|
|
1
|
+
{"version":3,"file":"features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.js","sources":["../../../src/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnEntryDeleteEventHandler.ts"],"sourcesContent":["import { EntryAfterDeleteEventHandler } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events\";\nimport {\n CancelScheduledActionUseCase,\n ListScheduledActionsUseCase\n} from \"@webiny/api-scheduler/exports/api/scheduler.js\";\nimport { Logger } from \"@webiny/api-core/exports/api/logger.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { createNamespace } from \"~/utils/namespace.js\";\n\n/**\n * Cancels scheduled actions when an entry is deleted\n *\n * When a user deletes an entry, any scheduled publish/unpublish\n * actions for all of its revisions should be canceled since the entry\n * no longer exists.\n */\nclass CancelScheduledActionOnEntryDeleteHandlerImpl\n implements EntryAfterDeleteEventHandler.Interface\n{\n constructor(\n private listScheduledActions: ListScheduledActionsUseCase.Interface,\n private cancelScheduledAction: CancelScheduledActionUseCase.Interface,\n private logger: Logger.Interface,\n private identityContext: IdentityContext.Interface\n ) {}\n\n async handle(event: EntryAfterDeleteEventHandler.Event): Promise<void> {\n const { entry, model } = event.payload;\n\n // Skip private models\n if (model.isPrivate) {\n return;\n }\n\n /**\n * System cleanup after a delete the user was allowed to do: list and cancel every schedule\n * for the deleted target, without the caller's permission checks (the target no longer exists).\n */\n const schedules = await this.identityContext.withoutAuthorization(() => {\n return this.listSchedules(model.modelId, entry.entryId);\n });\n for (const action of schedules) {\n const cancelRes = await this.identityContext.withoutAuthorization(() => {\n return this.cancelScheduledAction.execute(action);\n });\n if (cancelRes.isFail()) {\n // Silently ignore errors - this is non-critical cleanup.\n // The entry was deleted successfully, cancelling scheduled actions is best-effort.\n }\n }\n }\n\n private async listSchedules(modelId: string, entryId: string) {\n const actionsResult = await this.listScheduledActions.execute({\n limit: 10000,\n where: {\n namespace: createNamespace({ modelId }),\n targetId_startsWith: `${entryId}#`\n }\n });\n\n if (actionsResult.isFail()) {\n this.logger.error(actionsResult.error);\n return [];\n }\n\n return actionsResult.value.items;\n }\n}\n\nexport const CancelScheduledActionOnEntryDeleteEventHandler =\n EntryAfterDeleteEventHandler.createImplementation({\n implementation: CancelScheduledActionOnEntryDeleteHandlerImpl,\n dependencies: [\n ListScheduledActionsUseCase,\n CancelScheduledActionUseCase,\n Logger,\n IdentityContext\n ]\n });\n"],"names":["CancelScheduledActionOnEntryDeleteHandlerImpl","listScheduledActions","cancelScheduledAction","logger","identityContext","event","entry","model","schedules","action","cancelRes","modelId","entryId","actionsResult","createNamespace","CancelScheduledActionOnEntryDeleteEventHandler","EntryAfterDeleteEventHandler","ListScheduledActionsUseCase","CancelScheduledActionUseCase","Logger","IdentityContext"],"mappings":";;;;;AAgBA,MAAMA;IAGF,YACYC,oBAA2D,EAC3DC,qBAA6D,EAC7DC,MAAwB,EACxBC,eAA0C,CACpD;aAJUH,oBAAoB,GAApBA;aACAC,qBAAqB,GAArBA;aACAC,MAAM,GAANA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,OAAOC,KAAyC,EAAiB;QACnE,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGF,MAAM,OAAO;QAGtC,IAAIE,MAAM,SAAS,EACf;QAOJ,MAAMC,YAAY,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IACvD,IAAI,CAAC,aAAa,CAACD,MAAM,OAAO,EAAED,MAAM,OAAO;QAE1D,KAAK,MAAMG,UAAUD,UAAW;YAC5B,MAAME,YAAY,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IACvD,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAACD;YAE1CC,UAAU,MAAM;QAIxB;IACJ;IAEA,MAAc,cAAcC,OAAe,EAAEC,OAAe,EAAE;QAC1D,MAAMC,gBAAgB,MAAM,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;YAC1D,OAAO;YACP,OAAO;gBACH,WAAWC,gBAAgB;oBAAEH;gBAAQ;gBACrC,qBAAqB,GAAGC,QAAQ,CAAC,CAAC;YACtC;QACJ;QAEA,IAAIC,cAAc,MAAM,IAAI;YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAACA,cAAc,KAAK;YACrC,OAAO,EAAE;QACb;QAEA,OAAOA,cAAc,KAAK,CAAC,KAAK;IACpC;AACJ;AAEO,MAAME,iDACTC,6BAA6B,oBAAoB,CAAC;IAC9C,gBAAgBhB;IAChB,cAAc;QACViB;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EntryAfterDeleteEventHandler } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events";
|
|
2
2
|
import { CancelScheduledActionUseCase, ListScheduledActionsUseCase } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
3
3
|
import { Logger } from "@webiny/api-core/exports/api/logger.js";
|
|
4
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* Cancels scheduled actions when an entry revision is deleted
|
|
6
7
|
*
|
|
@@ -12,7 +13,8 @@ declare class CancelScheduledActionOnDeleteHandlerImpl implements EntryAfterDele
|
|
|
12
13
|
private listScheduledActions;
|
|
13
14
|
private cancelScheduledAction;
|
|
14
15
|
private logger;
|
|
15
|
-
|
|
16
|
+
private identityContext;
|
|
17
|
+
constructor(listScheduledActions: ListScheduledActionsUseCase.Interface, cancelScheduledAction: CancelScheduledActionUseCase.Interface, logger: Logger.Interface, identityContext: IdentityContext.Interface);
|
|
16
18
|
handle(event: EntryAfterDeleteEventHandler.Event): Promise<void>;
|
|
17
19
|
}
|
|
18
20
|
export declare const CancelScheduledActionOnRevisionDeleteEventHandler: typeof CancelScheduledActionOnDeleteHandlerImpl & {
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
import { EntryAfterDeleteEventHandler } from "@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events";
|
|
2
2
|
import { CancelScheduledActionUseCase, ListScheduledActionsUseCase } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
3
3
|
import { Logger } from "@webiny/api-core/exports/api/logger.js";
|
|
4
|
+
import { IdentityContext } from "@webiny/api-core/features/security/IdentityContext/index.js";
|
|
4
5
|
import { createNamespace } from "../../utils/namespace.js";
|
|
5
6
|
class CancelScheduledActionOnDeleteHandlerImpl {
|
|
6
|
-
constructor(listScheduledActions, cancelScheduledAction, logger){
|
|
7
|
+
constructor(listScheduledActions, cancelScheduledAction, logger, identityContext){
|
|
7
8
|
this.listScheduledActions = listScheduledActions;
|
|
8
9
|
this.cancelScheduledAction = cancelScheduledAction;
|
|
9
10
|
this.logger = logger;
|
|
11
|
+
this.identityContext = identityContext;
|
|
10
12
|
}
|
|
11
13
|
async handle(event) {
|
|
12
14
|
const { entry, model } = event.payload;
|
|
13
15
|
if (model.isPrivate) return;
|
|
14
|
-
const actionsResult = await this.listScheduledActions.execute({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
const actionsResult = await this.identityContext.withoutAuthorization(()=>this.listScheduledActions.execute({
|
|
17
|
+
where: {
|
|
18
|
+
namespace: createNamespace(model),
|
|
19
|
+
targetId: entry.id
|
|
20
|
+
}
|
|
21
|
+
}));
|
|
20
22
|
if (actionsResult.isFail()) return void this.logger.error(actionsResult.error);
|
|
21
23
|
const actions = actionsResult.value.items;
|
|
22
24
|
for (const action of actions){
|
|
23
|
-
const cancelRes = await this.cancelScheduledAction.execute(action);
|
|
25
|
+
const cancelRes = await this.identityContext.withoutAuthorization(()=>this.cancelScheduledAction.execute(action));
|
|
24
26
|
cancelRes.isFail();
|
|
25
27
|
}
|
|
26
28
|
}
|
|
@@ -30,7 +32,8 @@ const CancelScheduledActionOnRevisionDeleteEventHandler = EntryAfterDeleteEventH
|
|
|
30
32
|
dependencies: [
|
|
31
33
|
ListScheduledActionsUseCase,
|
|
32
34
|
CancelScheduledActionUseCase,
|
|
33
|
-
Logger
|
|
35
|
+
Logger,
|
|
36
|
+
IdentityContext
|
|
34
37
|
]
|
|
35
38
|
});
|
|
36
39
|
export { CancelScheduledActionOnRevisionDeleteEventHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.js","sources":["../../../src/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.ts"],"sourcesContent":["import { EntryAfterDeleteEventHandler } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events\";\nimport {\n CancelScheduledActionUseCase,\n ListScheduledActionsUseCase\n} from \"@webiny/api-scheduler/exports/api/scheduler.js\";\nimport { Logger } from \"@webiny/api-core/exports/api/logger.js\";\nimport { createNamespace } from \"~/utils/namespace.js\";\n\n/**\n * Cancels scheduled actions when an entry revision is deleted\n *\n * When a user deletes an entry revision, any scheduled publish/unpublish\n * action for that revision should be canceled since the revision\n * no longer exists.\n */\nclass CancelScheduledActionOnDeleteHandlerImpl implements EntryAfterDeleteEventHandler.Interface {\n constructor(\n private listScheduledActions: ListScheduledActionsUseCase.Interface,\n private cancelScheduledAction: CancelScheduledActionUseCase.Interface,\n private logger: Logger.Interface\n ) {}\n\n async handle(event: EntryAfterDeleteEventHandler.Event): Promise<void> {\n const { entry, model } = event.payload;\n\n // Skip private models\n if (model.isPrivate) {\n return;\n }\n\n const actionsResult = await this.listScheduledActions.execute({\n
|
|
1
|
+
{"version":3,"file":"features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.js","sources":["../../../src/features/CancelScheduledActionOnEntryChange/CancelScheduledActionOnRevisionDeleteEventHandler.ts"],"sourcesContent":["import { EntryAfterDeleteEventHandler } from \"@webiny/api-headless-cms/features/contentEntry/DeleteEntry/events\";\nimport {\n CancelScheduledActionUseCase,\n ListScheduledActionsUseCase\n} from \"@webiny/api-scheduler/exports/api/scheduler.js\";\nimport { Logger } from \"@webiny/api-core/exports/api/logger.js\";\nimport { IdentityContext } from \"@webiny/api-core/features/security/IdentityContext/index.js\";\nimport { createNamespace } from \"~/utils/namespace.js\";\n\n/**\n * Cancels scheduled actions when an entry revision is deleted\n *\n * When a user deletes an entry revision, any scheduled publish/unpublish\n * action for that revision should be canceled since the revision\n * no longer exists.\n */\nclass CancelScheduledActionOnDeleteHandlerImpl implements EntryAfterDeleteEventHandler.Interface {\n constructor(\n private listScheduledActions: ListScheduledActionsUseCase.Interface,\n private cancelScheduledAction: CancelScheduledActionUseCase.Interface,\n private logger: Logger.Interface,\n private identityContext: IdentityContext.Interface\n ) {}\n\n async handle(event: EntryAfterDeleteEventHandler.Event): Promise<void> {\n const { entry, model } = event.payload;\n\n // Skip private models\n if (model.isPrivate) {\n return;\n }\n\n /**\n * System cleanup after a delete the user was allowed to do: list and cancel every schedule\n * for the deleted target, without the caller's permission checks (the target no longer exists).\n */\n const actionsResult = await this.identityContext.withoutAuthorization(() => {\n return this.listScheduledActions.execute({\n where: {\n namespace: createNamespace(model),\n targetId: entry.id\n }\n });\n });\n\n if (actionsResult.isFail()) {\n this.logger.error(actionsResult.error);\n return;\n }\n\n const actions = actionsResult.value.items;\n\n for (const action of actions) {\n const cancelRes = await this.identityContext.withoutAuthorization(() => {\n return this.cancelScheduledAction.execute(action);\n });\n if (cancelRes.isFail()) {\n // Silently ignore errors - this is non-critical cleanup.\n // Entry was deleted successfully, cancelling scheduled actions is best-effort.\n }\n }\n }\n}\n\nexport const CancelScheduledActionOnRevisionDeleteEventHandler =\n EntryAfterDeleteEventHandler.createImplementation({\n implementation: CancelScheduledActionOnDeleteHandlerImpl,\n dependencies: [\n ListScheduledActionsUseCase,\n CancelScheduledActionUseCase,\n Logger,\n IdentityContext\n ]\n });\n"],"names":["CancelScheduledActionOnDeleteHandlerImpl","listScheduledActions","cancelScheduledAction","logger","identityContext","event","entry","model","actionsResult","createNamespace","actions","action","cancelRes","CancelScheduledActionOnRevisionDeleteEventHandler","EntryAfterDeleteEventHandler","ListScheduledActionsUseCase","CancelScheduledActionUseCase","Logger","IdentityContext"],"mappings":";;;;;AAgBA,MAAMA;IACF,YACYC,oBAA2D,EAC3DC,qBAA6D,EAC7DC,MAAwB,EACxBC,eAA0C,CACpD;aAJUH,oBAAoB,GAApBA;aACAC,qBAAqB,GAArBA;aACAC,MAAM,GAANA;aACAC,eAAe,GAAfA;IACT;IAEH,MAAM,OAAOC,KAAyC,EAAiB;QACnE,MAAM,EAAEC,KAAK,EAAEC,KAAK,EAAE,GAAGF,MAAM,OAAO;QAGtC,IAAIE,MAAM,SAAS,EACf;QAOJ,MAAMC,gBAAgB,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IAC3D,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC;gBACrC,OAAO;oBACH,WAAWC,gBAAgBF;oBAC3B,UAAUD,MAAM,EAAE;gBACtB;YACJ;QAGJ,IAAIE,cAAc,MAAM,IAAI,YACxB,IAAI,CAAC,MAAM,CAAC,KAAK,CAACA,cAAc,KAAK;QAIzC,MAAME,UAAUF,cAAc,KAAK,CAAC,KAAK;QAEzC,KAAK,MAAMG,UAAUD,QAAS;YAC1B,MAAME,YAAY,MAAM,IAAI,CAAC,eAAe,CAAC,oBAAoB,CAAC,IACvD,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAACD;YAE1CC,UAAU,MAAM;QAIxB;IACJ;AACJ;AAEO,MAAMC,oDACTC,6BAA6B,oBAAoB,CAAC;IAC9C,gBAAgBd;IAChB,cAAc;QACVe;QACAC;QACAC;QACAC;KACH;AACL"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { NamespaceHandler as NamespaceHandlerAbstraction } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
2
2
|
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
3
3
|
import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById/index.js";
|
|
4
|
+
import { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
4
5
|
import type { GenericRecord } from "@webiny/api/types.js";
|
|
5
6
|
declare class NamespaceHandlerImpl implements NamespaceHandlerAbstraction.Interface<GenericRecord> {
|
|
6
7
|
private getModelUseCase;
|
|
7
8
|
private getEntryByIdUseCase;
|
|
8
|
-
|
|
9
|
+
private accessControl;
|
|
10
|
+
constructor(getModelUseCase: GetModelUseCase.Interface, getEntryByIdUseCase: GetEntryByIdUseCase.Interface, accessControl: AccessControl.Interface);
|
|
9
11
|
canHandle(namespace: string): boolean;
|
|
10
12
|
execute(params: NamespaceHandlerAbstraction.Params): NamespaceHandlerAbstraction.Response<GenericRecord>;
|
|
11
13
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { NamespaceHandler } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
1
|
+
import { NamespaceHandler, ScheduledActionTypePublish, SchedulerNotAuthorizedError } from "@webiny/api-scheduler/exports/api/scheduler.js";
|
|
2
2
|
import { extractModelIdFromNamespace } from "../../utils/namespace.js";
|
|
3
3
|
import { Result } from "@webiny/feature/exports/api.js";
|
|
4
4
|
import { GetModelUseCase } from "@webiny/api-headless-cms/features/contentModel/GetModel/index.js";
|
|
5
5
|
import { GetEntryByIdUseCase } from "@webiny/api-headless-cms/features/contentEntry/GetEntryById/index.js";
|
|
6
|
+
import { AccessControl } from "@webiny/api-headless-cms/features/shared/abstractions.js";
|
|
6
7
|
class NamespaceHandlerImpl {
|
|
7
|
-
constructor(getModelUseCase, getEntryByIdUseCase){
|
|
8
|
+
constructor(getModelUseCase, getEntryByIdUseCase, accessControl){
|
|
8
9
|
this.getModelUseCase = getModelUseCase;
|
|
9
10
|
this.getEntryByIdUseCase = getEntryByIdUseCase;
|
|
11
|
+
this.accessControl = accessControl;
|
|
10
12
|
}
|
|
11
13
|
canHandle(namespace) {
|
|
12
14
|
const modelId = extractModelIdFromNamespace(namespace);
|
|
@@ -17,9 +19,16 @@ class NamespaceHandlerImpl {
|
|
|
17
19
|
const modelResult = await this.getModelUseCase.execute(modelId);
|
|
18
20
|
if (modelResult.isFail()) return Result.fail(modelResult.error);
|
|
19
21
|
const model = modelResult.value;
|
|
22
|
+
if (model.isPrivate) return Result.fail(new SchedulerNotAuthorizedError());
|
|
20
23
|
const entryResult = await this.getEntryByIdUseCase.execute(model, params.targetId);
|
|
21
24
|
if (entryResult.isFail()) return Result.fail(entryResult.error);
|
|
22
25
|
const entry = entryResult.value;
|
|
26
|
+
const canSchedule = await this.accessControl.canAccessEntry({
|
|
27
|
+
model,
|
|
28
|
+
entry,
|
|
29
|
+
pw: params.actionType === ScheduledActionTypePublish ? "p" : "u"
|
|
30
|
+
});
|
|
31
|
+
if (!canSchedule) return Result.fail(new SchedulerNotAuthorizedError());
|
|
23
32
|
const title = entry.values[model.titleFieldId] || "Unknown entry title";
|
|
24
33
|
return Result.ok({
|
|
25
34
|
namespace: params.namespace,
|
|
@@ -36,7 +45,8 @@ const NamespaceHandler_NamespaceHandler = NamespaceHandler.createImplementation(
|
|
|
36
45
|
implementation: NamespaceHandlerImpl,
|
|
37
46
|
dependencies: [
|
|
38
47
|
GetModelUseCase,
|
|
39
|
-
GetEntryByIdUseCase
|
|
48
|
+
GetEntryByIdUseCase,
|
|
49
|
+
AccessControl
|
|
40
50
|
]
|
|
41
51
|
});
|
|
42
52
|
export { NamespaceHandler_NamespaceHandler as NamespaceHandler };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features/NamespaceHandler/NamespaceHandler.js","sources":["../../../src/features/NamespaceHandler/NamespaceHandler.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"features/NamespaceHandler/NamespaceHandler.js","sources":["../../../src/features/NamespaceHandler/NamespaceHandler.ts"],"sourcesContent":["import {\n NamespaceHandler as NamespaceHandlerAbstraction,\n SchedulerNotAuthorizedError,\n ScheduledActionTypePublish\n} from \"@webiny/api-scheduler/exports/api/scheduler.js\";\nimport { extractModelIdFromNamespace } from \"~/utils/namespace.js\";\nimport { Result } from \"@webiny/feature/exports/api.js\";\nimport { GetModelUseCase } from \"@webiny/api-headless-cms/features/contentModel/GetModel/index.js\";\nimport { GetEntryByIdUseCase } from \"@webiny/api-headless-cms/features/contentEntry/GetEntryById/index.js\";\nimport { AccessControl } from \"@webiny/api-headless-cms/features/shared/abstractions.js\";\nimport type { GenericRecord } from \"@webiny/api/types.js\";\n\nclass NamespaceHandlerImpl implements NamespaceHandlerAbstraction.Interface<GenericRecord> {\n public constructor(\n private getModelUseCase: GetModelUseCase.Interface,\n private getEntryByIdUseCase: GetEntryByIdUseCase.Interface,\n private accessControl: AccessControl.Interface\n ) {}\n\n public canHandle(namespace: string): boolean {\n const modelId = extractModelIdFromNamespace(namespace);\n\n return !!modelId;\n }\n\n public async execute(\n params: NamespaceHandlerAbstraction.Params\n ): NamespaceHandlerAbstraction.Response<GenericRecord> {\n /**\n * We know that modelId is ok because of the canHandle() method, which is always called before execute() and must return true for this handler to be executed.\n */\n const modelId = extractModelIdFromNamespace(params.namespace)!;\n // Fetch the target model\n const modelResult = await this.getModelUseCase.execute(modelId);\n if (modelResult.isFail()) {\n return Result.fail(modelResult.error as any);\n }\n\n const model = modelResult.value;\n // Private models are internal and cannot be scheduled.\n if (model.isPrivate) {\n return Result.fail(new SchedulerNotAuthorizedError());\n }\n\n // Fetch entry to get title\n const entryResult = await this.getEntryByIdUseCase.execute(model, params.targetId);\n if (entryResult.isFail()) {\n return Result.fail(entryResult.error as any);\n }\n\n const entry = entryResult.value;\n // Same check as publishing / unpublishing the entry directly, including \"own entries only\".\n const canSchedule = await this.accessControl.canAccessEntry({\n model,\n entry,\n pw: params.actionType === ScheduledActionTypePublish ? \"p\" : \"u\"\n });\n if (!canSchedule) {\n return Result.fail(new SchedulerNotAuthorizedError());\n }\n const title = entry.values[model.titleFieldId] || \"Unknown entry title\";\n\n return Result.ok({\n namespace: params.namespace,\n title,\n modelId,\n actionType: params.actionType,\n targetId: params.targetId,\n scheduleId: params.scheduleId,\n immediately: params.immediately || false\n });\n }\n}\n\nexport const NamespaceHandler = NamespaceHandlerAbstraction.createImplementation({\n implementation: NamespaceHandlerImpl,\n dependencies: [GetModelUseCase, GetEntryByIdUseCase, AccessControl]\n});\n"],"names":["NamespaceHandlerImpl","getModelUseCase","getEntryByIdUseCase","accessControl","namespace","modelId","extractModelIdFromNamespace","params","modelResult","Result","model","SchedulerNotAuthorizedError","entryResult","entry","canSchedule","ScheduledActionTypePublish","title","NamespaceHandler","NamespaceHandlerAbstraction","GetModelUseCase","GetEntryByIdUseCase","AccessControl"],"mappings":";;;;;;AAYA,MAAMA;IACF,YACYC,eAA0C,EAC1CC,mBAAkD,EAClDC,aAAsC,CAChD;aAHUF,eAAe,GAAfA;aACAC,mBAAmB,GAAnBA;aACAC,aAAa,GAAbA;IACT;IAEI,UAAUC,SAAiB,EAAW;QACzC,MAAMC,UAAUC,4BAA4BF;QAE5C,OAAO,CAAC,CAACC;IACb;IAEA,MAAa,QACTE,MAA0C,EACS;QAInD,MAAMF,UAAUC,4BAA4BC,OAAO,SAAS;QAE5D,MAAMC,cAAc,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,CAACH;QACvD,IAAIG,YAAY,MAAM,IAClB,OAAOC,OAAO,IAAI,CAACD,YAAY,KAAK;QAGxC,MAAME,QAAQF,YAAY,KAAK;QAE/B,IAAIE,MAAM,SAAS,EACf,OAAOD,OAAO,IAAI,CAAC,IAAIE;QAI3B,MAAMC,cAAc,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAACF,OAAOH,OAAO,QAAQ;QACjF,IAAIK,YAAY,MAAM,IAClB,OAAOH,OAAO,IAAI,CAACG,YAAY,KAAK;QAGxC,MAAMC,QAAQD,YAAY,KAAK;QAE/B,MAAME,cAAc,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC;YACxDJ;YACAG;YACA,IAAIN,OAAO,UAAU,KAAKQ,6BAA6B,MAAM;QACjE;QACA,IAAI,CAACD,aACD,OAAOL,OAAO,IAAI,CAAC,IAAIE;QAE3B,MAAMK,QAAQH,MAAM,MAAM,CAACH,MAAM,YAAY,CAAC,IAAI;QAElD,OAAOD,OAAO,EAAE,CAAC;YACb,WAAWF,OAAO,SAAS;YAC3BS;YACAX;YACA,YAAYE,OAAO,UAAU;YAC7B,UAAUA,OAAO,QAAQ;YACzB,YAAYA,OAAO,UAAU;YAC7B,aAAaA,OAAO,WAAW,IAAI;QACvC;IACJ;AACJ;AAEO,MAAMU,oCAAmBC,iBAAAA,oBAAgD,CAAC;IAC7E,gBAAgBlB;IAChB,cAAc;QAACmB;QAAiBC;QAAqBC;KAAc;AACvE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webiny/api-headless-cms-scheduler",
|
|
3
|
-
"version": "6.5.1",
|
|
3
|
+
"version": "6.5.2-beta.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -17,21 +17,21 @@
|
|
|
17
17
|
},
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@webiny/api": "6.5.1",
|
|
21
|
-
"@webiny/api-headless-cms": "6.5.1",
|
|
22
|
-
"@webiny/api-scheduler": "6.5.1",
|
|
23
|
-
"@webiny/feature": "6.5.1",
|
|
24
|
-
"@webiny/handler-graphql": "6.5.1"
|
|
20
|
+
"@webiny/api": "6.5.2-beta.1",
|
|
21
|
+
"@webiny/api-headless-cms": "6.5.2-beta.1",
|
|
22
|
+
"@webiny/api-scheduler": "6.5.2-beta.1",
|
|
23
|
+
"@webiny/feature": "6.5.2-beta.1",
|
|
24
|
+
"@webiny/handler-graphql": "6.5.2-beta.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@webiny/api-core": "6.5.1",
|
|
28
|
-
"@webiny/api-opensearch": "6.5.1",
|
|
29
|
-
"@webiny/build-tools": "6.5.1",
|
|
30
|
-
"@webiny/handler": "6.5.1",
|
|
31
|
-
"@webiny/handler-aws": "6.5.1",
|
|
32
|
-
"@webiny/plugins": "6.5.1",
|
|
33
|
-
"@webiny/project-utils": "6.5.1",
|
|
34
|
-
"@webiny/wcp": "6.5.1",
|
|
27
|
+
"@webiny/api-core": "6.5.2-beta.1",
|
|
28
|
+
"@webiny/api-opensearch": "6.5.2-beta.1",
|
|
29
|
+
"@webiny/build-tools": "6.5.2-beta.1",
|
|
30
|
+
"@webiny/handler": "6.5.2-beta.1",
|
|
31
|
+
"@webiny/handler-aws": "6.5.2-beta.1",
|
|
32
|
+
"@webiny/plugins": "6.5.2-beta.1",
|
|
33
|
+
"@webiny/project-utils": "6.5.2-beta.1",
|
|
34
|
+
"@webiny/wcp": "6.5.2-beta.1",
|
|
35
35
|
"typescript": "7.0.2",
|
|
36
36
|
"vitest": "5.0.5"
|
|
37
37
|
},
|