mirror of
https://github.com/penpot/penpot-plugins.git
synced 2025-01-08 07:50:44 -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",
|
"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
|
```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"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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',
|
||||||
|
])
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue