mirror of
https://github.com/penpot/penpot-plugins.git
synced 2025-01-06 14:50:21 -05:00
feat: basic permission system
This commit is contained in:
parent
9d2eafc1be
commit
3d45bb88f6
6 changed files with 42 additions and 5 deletions
|
@ -1,4 +1,9 @@
|
|||
{
|
||||
"name": "Example plugin",
|
||||
"code": "http://localhost:4201/plugin.js"
|
||||
"code": "http://localhost:4201/plugin.js",
|
||||
"permissions": [
|
||||
"page:read",
|
||||
"file:read",
|
||||
"selection:read"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ Create a manifes.json in /public
|
|||
```json
|
||||
{
|
||||
"name": "Example plugin",
|
||||
"code": "http://localhost:4201/plugin.js"
|
||||
"code": "http://localhost:4201/plugin.js",
|
||||
"permissions": ["page:read", "file:read", "selection:read"]
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Manifest, Permissions } from '../models/manifest.model';
|
||||
import { OpenUIOptions } from '../models/open-ui-options.model';
|
||||
import openUIApi from './openUI.api';
|
||||
import z from 'zod';
|
||||
|
@ -55,7 +56,7 @@ export function setSelection(selectionId: string) {
|
|||
triggerEvent('selectionchange', selectionId);
|
||||
}
|
||||
|
||||
export function createApi() {
|
||||
export function createApi(manifest: Manifest) {
|
||||
const closePlugin = () => {
|
||||
if (modal) {
|
||||
modal.remove();
|
||||
|
@ -65,6 +66,12 @@ export function createApi() {
|
|||
modal = null;
|
||||
};
|
||||
|
||||
const checkPermission = (permission: Permissions) => {
|
||||
if (!manifest.permissions.includes(permission)) {
|
||||
throw new Error(`Permission ${permission} is not granted`);
|
||||
}
|
||||
};
|
||||
|
||||
const penpot: Penpot = {
|
||||
ui: {
|
||||
open: (name: string, url: string, options: OpenUIOptions) => {
|
||||
|
@ -103,6 +110,14 @@ export function createApi() {
|
|||
z.enum(validEvents).parse(type);
|
||||
z.function().parse(callback);
|
||||
|
||||
if (type === 'pagechange') {
|
||||
checkPermission('page:read');
|
||||
}
|
||||
|
||||
if (type === 'filechange') {
|
||||
checkPermission('file:read');
|
||||
}
|
||||
|
||||
const listeners = eventListeners.get(type) || [];
|
||||
|
||||
listeners.push(callback as Callback<unknown>);
|
||||
|
@ -123,12 +138,18 @@ export function createApi() {
|
|||
);
|
||||
},
|
||||
getFileState: () => {
|
||||
checkPermission('file:read');
|
||||
|
||||
return fileState;
|
||||
},
|
||||
getPageState: () => {
|
||||
checkPermission('page:read');
|
||||
|
||||
return pageState;
|
||||
},
|
||||
getSelection: () => {
|
||||
checkPermission('selection:read');
|
||||
|
||||
return selection;
|
||||
},
|
||||
} as const;
|
||||
|
|
|
@ -6,7 +6,7 @@ let isLockedDown = false;
|
|||
let lastApi: ReturnType<typeof createApi> | undefined;
|
||||
|
||||
export const ɵloadPlugin = async function (config: PluginConfig) {
|
||||
const { code } = await parseManifest(config);
|
||||
const { code, manifest } = await parseManifest(config);
|
||||
|
||||
try {
|
||||
if (!isLockedDown) {
|
||||
|
@ -18,7 +18,7 @@ export const ɵloadPlugin = async function (config: PluginConfig) {
|
|||
lastApi.closePlugin();
|
||||
}
|
||||
|
||||
lastApi = createApi();
|
||||
lastApi = createApi(manifest);
|
||||
|
||||
const c = new Compartment({
|
||||
penpot: harden(lastApi),
|
||||
|
|
|
@ -2,3 +2,4 @@ import z from 'zod';
|
|||
import { manifestSchema } from './manifest.schema';
|
||||
|
||||
export type Manifest = z.infer<typeof manifestSchema>;
|
||||
export type Permissions = Manifest['permissions'][number];
|
||||
|
|
|
@ -3,4 +3,13 @@ import { z } from 'zod';
|
|||
export const manifestSchema = z.object({
|
||||
name: z.string(),
|
||||
code: z.string().url(),
|
||||
permissions: z.array(
|
||||
z.enum([
|
||||
'page:read',
|
||||
'page:write',
|
||||
'file:read',
|
||||
'file:write',
|
||||
'selection:read',
|
||||
])
|
||||
),
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue