0
Fork 0
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:
Juanfran 2024-03-04 10:49:53 +01:00
parent 9d2eafc1be
commit 3d45bb88f6
6 changed files with 42 additions and 5 deletions

View file

@ -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"
]
}

View file

@ -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"]
}
```

View file

@ -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;

View file

@ -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),

View file

@ -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];

View file

@ -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',
])
),
});