Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add frontend render plugin system support#36099

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Draft
lunny wants to merge8 commits intogo-gitea:main
base:main
Choose a base branch
Loading
fromlunny:lunny/frontend_render_plugin
Draft
Show file tree
Hide file tree
Changes from1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Add permissions for render plugin
  • Loading branch information
@lunny
lunny committedDec 6, 2025
commit63fc35ea2295655105c9d1eadaf780eb5fc1ecef
5 changes: 5 additions & 0 deletionscontrib/render-plugins/example-wasm/README.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,6 +16,11 @@ then renders the result inside the file viewer.
- `build.sh` — helper script that builds `plugin.wasm` and produces a zip
archive ready for upload

As with other plugins, declare any Gitea endpoints or external hosts the WASM
module needs to call inside the `permissions` array in `manifest.json`. Without
an explicit entry, the plugin may only download the file that is currently being
rendered.

## Build & Install

1. Build the WASM binary and zip archive:
Expand Down
3 changes: 2 additions & 1 deletioncontrib/render-plugins/example-wasm/manifest.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,5 +7,6 @@
"entry": "render.js",
"filePatterns": [
"*.wasmnote"
]
],
"permissions": []
}
5 changes: 5 additions & 0 deletionscontrib/render-plugins/example/README.md
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,11 @@ as a quick way to validate the dynamic plugin system locally.
- `render.js` — an ES module that exports a `render(container, fileUrl)`
function; it downloads the source file and renders it in a styled `<pre>`

By default plugins may only fetch the file that is currently being rendered.
If your plugin needs to contact Gitea APIs or any external services, list their
domains under the `permissions` array in `manifest.json`. Requests to hosts that
are not declared there will be blocked by the runtime.

## Build & Install

1. Create a zip archive that contains both files:
Expand Down
3 changes: 2 additions & 1 deletioncontrib/render-plugins/example/manifest.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,5 +5,6 @@
"version": "1.0.0",
"description": "Simple sample plugin that renders .txt files with a custom color scheme.",
"entry": "render.js",
"filePatterns": ["*.txt"]
"filePatterns": ["*.txt"],
"permissions": []
}
1 change: 1 addition & 0 deletionsmodels/migrations/v1_26/v324.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,6 +18,7 @@ func AddRenderPluginTable(x *xorm.Engine) error {
Version string `xorm:"NOT NULL"`
Description string `xorm:"TEXT"`
Source string `xorm:"TEXT"`
Permissions []string `xorm:"JSON"`
Entry string `xorm:"NOT NULL"`
FilePatterns []string `xorm:"JSON"`
FormatVersion int `xorm:"NOT NULL DEFAULT 1"`
Expand Down
1 change: 1 addition & 0 deletionsmodels/render/plugin.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,6 +20,7 @@ type Plugin struct {
Source string `xorm:"TEXT"`
Entry string `xorm:"NOT NULL"`
FilePatterns []string `xorm:"JSON"`
Permissions []string `xorm:"JSON"`
FormatVersion int `xorm:"NOT NULL DEFAULT 1"`
Enabled bool `xorm:"NOT NULL DEFAULT false"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
Expand Down
27 changes: 27 additions & 0 deletionsmodules/renderplugin/manifest.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ type Manifest struct {
Description string `json:"description"`
Entry string `json:"entry"`
FilePatterns []string `json:"filePatterns"`
Permissions []string `json:"permissions"`
}

// Normalize validates mandatory fields and normalizes values.
Expand DownExpand Up@@ -71,9 +72,34 @@ func (m *Manifest) Normalize() error {
}
sort.Strings(cleanPatterns)
m.FilePatterns = cleanPatterns

cleanPerms := make([]string, 0, len(m.Permissions))
seenPerm := make(map[string]struct{}, len(m.Permissions))
for _, perm := range m.Permissions {
perm = strings.TrimSpace(strings.ToLower(perm))
if perm == "" {
continue
}
if !isValidPermissionHost(perm) {
return fmt.Errorf("manifest permission %q is invalid; only plain domains optionally including a port are allowed", perm)
}
if _, ok := seenPerm[perm]; ok {
continue
}
seenPerm[perm] = struct{}{}
cleanPerms = append(cleanPerms, perm)
}
sort.Strings(cleanPerms)
m.Permissions = cleanPerms
return nil
}

var permissionHostRegexp = regexp.MustCompile(`^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*(?::[0-9]{1,5})?$`)

func isValidPermissionHost(value string) bool {
return permissionHostRegexp.MatchString(value)
}

// LoadManifest reads and validates the manifest.json file located under dir.
func LoadManifest(dir string) (*Manifest, error) {
manifestPath := filepath.Join(dir, "manifest.json")
Expand DownExpand Up@@ -103,4 +129,5 @@ type Metadata struct {
AssetsBase string `json:"assetsBaseUrl"`
FilePatterns []string `json:"filePatterns"`
SchemaVersion int `json:"schemaVersion"`
Permissions []string `json:"permissions"`
}
17 changes: 17 additions & 0 deletionsmodules/renderplugin/manifest_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,7 @@ func TestManifestNormalizeDefaults(t *testing.T) {
assert.Equal(t, "example.plugin", manifest.ID)
assert.Equal(t, "render.js", manifest.Entry)
assert.Equal(t, []string{"*.TXT", "README.md"}, manifest.FilePatterns)
assert.Empty(t, manifest.Permissions)
}

func TestManifestNormalizeErrors(t *testing.T) {
Expand All@@ -50,6 +51,7 @@ func TestManifestNormalizeErrors(t *testing.T) {
{"missing name", func(m *Manifest) { m.Name = "" }, "name is required"},
{"missing version", func(m *Manifest) { m.Version = "" }, "version is required"},
{"no patterns", func(m *Manifest) { m.FilePatterns = nil }, "at least one file pattern"},
{"invalid permission", func(m *Manifest) { m.Permissions = []string{"http://bad"} }, "manifest permission"},
}

for _, tt := range tests {
Expand DownExpand Up@@ -82,3 +84,18 @@ func TestLoadManifest(t *testing.T) {
assert.Equal(t, "example", manifest.ID)
assert.Equal(t, []string{"*.md", "*.txt"}, manifest.FilePatterns)
}

func TestManifestNormalizePermissions(t *testing.T) {
manifest := Manifest{
SchemaVersion: SupportedManifestVersion,
ID: "perm",
Name: "perm",
Version: "1.0.0",
Entry: "render.js",
FilePatterns: []string{"*.md"},
Permissions: []string{" Example.com ", "api.example.com:8080", "example.com", ""},
}

require.NoError(t, manifest.Normalize())
assert.Equal(t, []string{"api.example.com:8080", "example.com"}, manifest.Permissions)
}
14 changes: 14 additions & 0 deletionsoptions/locale/locale_en-US.ini
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3030,6 +3030,20 @@ render_plugins.detail.none = Not provided
render_plugins.detail.file_patterns_empty = No file patterns declared.
render_plugins.detail.actions = Plugin actions
render_plugins.detail.upgrade = Upgrade plugin
render_plugins.detail.permissions = Permissions
render_plugins.confirm_install = Review permissions before installing "%s"
render_plugins.confirm_upgrade = Review permissions before upgrading "%s"
render_plugins.confirm.description = Gitea will only allow this plugin to contact the domains listed below (plus the file being rendered). Continue only if you trust these endpoints.
render_plugins.confirm.permissions = Requested domains
render_plugins.confirm.permission_hint = If the list is empty the plugin will only fetch the file currently being rendered.
render_plugins.confirm.permission_none = None
render_plugins.confirm.archive = Archive
render_plugins.confirm.actions.install = Install Plugin
render_plugins.confirm.actions.upgrade = Upgrade Plugin
render_plugins.confirm.actions.cancel = Cancel Upload
render_plugins.upload_token_invalid = Plugin upload session expired. Please upload the archive again.
render_plugins.upload_discarded = Plugin upload discarded.
render_plugins.identifier_mismatch = Uploaded plugin identifier "%s" does not match "%s".
hooks = Webhooks
integrations = Integrations
authentication = Authentication Sources
Expand Down
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp