0
Fork 0
mirror of https://github.com/penpot/penpot-plugins.git synced 2025-01-07 15:39:49 -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", "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 ```json
{ {
"name": "Example plugin", "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 { OpenUIOptions } from '../models/open-ui-options.model';
import openUIApi from './openUI.api'; import openUIApi from './openUI.api';
import z from 'zod'; import z from 'zod';
@ -55,7 +56,7 @@ export function setSelection(selectionId: string) {
triggerEvent('selectionchange', selectionId); triggerEvent('selectionchange', selectionId);
} }
export function createApi() { export function createApi(manifest: Manifest) {
const closePlugin = () => { const closePlugin = () => {
if (modal) { if (modal) {
modal.remove(); modal.remove();
@ -65,6 +66,12 @@ export function createApi() {
modal = null; modal = null;
}; };
const checkPermission = (permission: Permissions) => {
if (!manifest.permissions.includes(permission)) {
throw new Error(`Permission ${permission} is not granted`);
}
};
const penpot: Penpot = { const penpot: Penpot = {
ui: { ui: {
open: (name: string, url: string, options: OpenUIOptions) => { open: (name: string, url: string, options: OpenUIOptions) => {
@ -103,6 +110,14 @@ export function createApi() {
z.enum(validEvents).parse(type); z.enum(validEvents).parse(type);
z.function().parse(callback); z.function().parse(callback);
if (type === 'pagechange') {
checkPermission('page:read');
}
if (type === 'filechange') {
checkPermission('file:read');
}
const listeners = eventListeners.get(type) || []; const listeners = eventListeners.get(type) || [];
listeners.push(callback as Callback<unknown>); listeners.push(callback as Callback<unknown>);
@ -123,12 +138,18 @@ export function createApi() {
); );
}, },
getFileState: () => { getFileState: () => {
checkPermission('file:read');
return fileState; return fileState;
}, },
getPageState: () => { getPageState: () => {
checkPermission('page:read');
return pageState; return pageState;
}, },
getSelection: () => { getSelection: () => {
checkPermission('selection:read');
return selection; return selection;
}, },
} as const; } as const;

View file

@ -6,7 +6,7 @@ let isLockedDown = false;
let lastApi: ReturnType<typeof createApi> | undefined; let lastApi: ReturnType<typeof createApi> | undefined;
export const ɵloadPlugin = async function (config: PluginConfig) { export const ɵloadPlugin = async function (config: PluginConfig) {
const { code } = await parseManifest(config); const { code, manifest } = await parseManifest(config);
try { try {
if (!isLockedDown) { if (!isLockedDown) {
@ -18,7 +18,7 @@ export const ɵloadPlugin = async function (config: PluginConfig) {
lastApi.closePlugin(); lastApi.closePlugin();
} }
lastApi = createApi(); lastApi = createApi(manifest);
const c = new Compartment({ const c = new Compartment({
penpot: harden(lastApi), penpot: harden(lastApi),

View file

@ -2,3 +2,4 @@ import z from 'zod';
import { manifestSchema } from './manifest.schema'; import { manifestSchema } from './manifest.schema';
export type Manifest = z.infer<typeof manifestSchema>; 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({ export const manifestSchema = z.object({
name: z.string(), name: z.string(),
code: z.string().url(), code: z.string().url(),
permissions: z.array(
z.enum([
'page:read',
'page:write',
'file:read',
'file:write',
'selection:read',
])
),
}); });