diff --git a/.changeset/grumpy-seals-fail.md b/.changeset/grumpy-seals-fail.md new file mode 100644 index 0000000..8be4fc2 --- /dev/null +++ b/.changeset/grumpy-seals-fail.md @@ -0,0 +1,11 @@ +--- +"@saleor/app-sdk": minor +--- + +Added new actions and events for dynamic permissions request. + +Now App can ask Dashboard to grant more permissions than originally assigned. + +Operation can be approved or rejected by the user. + +This feature is available in Saleor 3.15 and higher diff --git a/docs/app-bridge.md b/docs/app-bridge.md index 1550f58..5830c9e 100644 --- a/docs/app-bridge.md +++ b/docs/app-bridge.md @@ -176,13 +176,14 @@ handleRedirect(); ### Available actions -| Action | Arguments | Description | -| :-------------- | :--------------------------------------------------------------- | :--------------------------------------- | -| `Redirect` | `to` (string) - relative (inside Dashboard) or absolute URL path | | -| | `newContext` (boolean) - should open in a new browsing context | | -| `Notification` | `status` (`info` / `success` / `warning` / `error` / undefined) | | -| | `title` (string / undefined) - title of the notification | | -| | `text` (string / undefined) - content of the notification | | -| | `apiMessage` (string / undefined) - error log from api | | -| `NotifyReady` | | Inform Dashboard that AppBridge is ready | -| `UpdateRouting` | `newRoute` - current path of App to be set in URL | | +| Action | Arguments | Description | +| :---------------------------- | :----------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Redirect` | `to` (string) - relative (inside Dashboard) or absolute URL path | | +| | `newContext` (boolean) - should open in a new browsing context | | +| `Notification` | `status` (`info` / `success` / `warning` / `error` / undefined) | | +| | `title` (string / undefined) - title of the notification | | +| | `text` (string / undefined) - content of the notification | | +| | `apiMessage` (string / undefined) - error log from api | | +| `NotifyReady` | | Inform Dashboard that AppBridge is ready | +| `UpdateRouting` | `newRoute` - current path of App to be set in URL | | +| `RequestPermissions` (>=3.15) | `permissions` - array of AppPermission, `redirectPath` - path app will be redirected to after operation ends | Ask Dashboard to give more permissions to the app. Dashboard will unmount app. After user approves or denies, Dashboard will redirect to `redirectPath`. If operation fails, `?error=REASON` will be appended | diff --git a/src/app-bridge/actions.ts b/src/app-bridge/actions.ts index b1fa206..8a665b5 100644 --- a/src/app-bridge/actions.ts +++ b/src/app-bridge/actions.ts @@ -1,5 +1,6 @@ import { v4 as uuidv4 } from "uuid"; +import { AppPermission } from "../types"; import { Values } from "./helpers"; // Using constants over Enums, more info: https://fettblog.eu/tidy-typescript-avoid-enums/ @@ -20,6 +21,12 @@ export const ActionType = { * Inform Dashboard that AppBridge is ready */ notifyReady: "notifyReady", + /** + * Request one or more permissions from the Dashboard + * + * Available from 3.15 + */ + requestPermission: "requestPermissions", } as const; export type ActionType = Values; @@ -110,11 +117,38 @@ function createNotifyReadyAction(): NotifyReady { }); } -export type Actions = RedirectAction | NotificationAction | UpdateRouting | NotifyReady; +export type RequestPermissions = ActionWithId< + "requestPermissions", + { + permissions: AppPermission[]; + redirectPath: string; + } +>; + +function createRequestPermissionsAction( + permissions: AppPermission[], + redirectPath: string +): RequestPermissions { + return withActionId({ + type: "requestPermissions", + payload: { + permissions, + redirectPath, + }, + }); +} + +export type Actions = + | RedirectAction + | NotificationAction + | UpdateRouting + | NotifyReady + | RequestPermissions; export const actions = { Redirect: createRedirectAction, Notification: createNotificationAction, UpdateRouting: createUpdateRoutingAction, NotifyReady: createNotifyReadyAction, + RequestPermissions: createRequestPermissionsAction, }; diff --git a/src/app-bridge/app-bridge.ts b/src/app-bridge/app-bridge.ts index f1b360e..8c31f9a 100644 --- a/src/app-bridge/app-bridge.ts +++ b/src/app-bridge/app-bridge.ts @@ -19,8 +19,6 @@ type SubscribeMap = { const debug = debugPkg.debug("app-sdk:AppBridge"); function eventStateReducer(state: AppBridgeState, event: Events) { - debug("Event reducer received event: %j", event); - switch (event.type) { case EventType.handshake: { const userJwtPayload = extractUserFromJwt(event.payload.token);