Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
110
backend/internal/pluginstore/home_sync.go
Normal file
110
backend/internal/pluginstore/home_sync.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
package pluginstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const PluginSyncSchemaVersion = 1
|
||||
|
||||
type PluginSyncRequest struct {
|
||||
SchemaVersion int `json:"schema_version"`
|
||||
GOOS string `json:"goos"`
|
||||
GOARCH string `json:"goarch"`
|
||||
InstalledVersions map[string]string `json:"installed_versions,omitempty"`
|
||||
}
|
||||
|
||||
func (r *PluginSyncRequest) Clear() {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
clear(r.InstalledVersions)
|
||||
r.InstalledVersions = nil
|
||||
}
|
||||
|
||||
type PluginSyncItem struct {
|
||||
Manifest Manifest `json:"manifest"`
|
||||
Auth []ResolvedAuthConfig `json:"auth,omitempty"`
|
||||
}
|
||||
|
||||
func (i *PluginSyncItem) Clear() {
|
||||
if i == nil {
|
||||
return
|
||||
}
|
||||
ClearResolvedAuthConfigs(i.Auth)
|
||||
i.Auth = nil
|
||||
i.Manifest = Manifest{}
|
||||
}
|
||||
|
||||
type PluginSyncResponse struct {
|
||||
SchemaVersion int `json:"schema_version"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
Items []PluginSyncItem `json:"items"`
|
||||
}
|
||||
|
||||
func (r *PluginSyncResponse) Validate(now time.Time) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("plugin sync response is nil")
|
||||
}
|
||||
if r.SchemaVersion != PluginSyncSchemaVersion {
|
||||
return fmt.Errorf("unsupported plugin sync schema_version %d", r.SchemaVersion)
|
||||
}
|
||||
if r.ExpiresAt.IsZero() {
|
||||
return fmt.Errorf("plugin sync response missing expires_at")
|
||||
}
|
||||
if !now.Before(r.ExpiresAt) {
|
||||
return fmt.Errorf("plugin sync response expired")
|
||||
}
|
||||
seen := make(map[string]struct{}, len(r.Items))
|
||||
for index := range r.Items {
|
||||
item := &r.Items[index]
|
||||
if errManifest := item.Manifest.Validate(); errManifest != nil {
|
||||
return fmt.Errorf("plugin sync item %d: %w", index, errManifest)
|
||||
}
|
||||
if errURLs := validatePluginSyncManifestURLs(item.Manifest); errURLs != nil {
|
||||
return fmt.Errorf("plugin sync item %d: %w", index, errURLs)
|
||||
}
|
||||
id := strings.TrimSpace(item.Manifest.ID)
|
||||
if _, exists := seen[id]; exists {
|
||||
return fmt.Errorf("plugin sync response contains duplicate plugin %q", id)
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
for authIndex := range item.Auth {
|
||||
if errAuth := ValidateResolvedAuthConfig(item.Auth[authIndex]); errAuth != nil {
|
||||
return fmt.Errorf("plugin sync item %d auth %d: %w", index, authIndex, errAuth)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validatePluginSyncManifestURLs(manifest Manifest) error {
|
||||
if manifest.InstallType() != InstallTypeDirect {
|
||||
return nil
|
||||
}
|
||||
plan := NormalizeInstallPlan(manifest.Install)
|
||||
if len(plan.Artifacts) == 0 {
|
||||
return fmt.Errorf("direct plugin sync manifest requires pinned artifacts")
|
||||
}
|
||||
for index, artifact := range plan.Artifacts {
|
||||
parsed, errParse := url.Parse(strings.TrimSpace(artifact.URL))
|
||||
if errParse != nil || !strings.EqualFold(parsed.Scheme, "https") {
|
||||
return fmt.Errorf("direct plugin sync artifact %d must use https", index)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *PluginSyncResponse) Clear() {
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
for index := range r.Items {
|
||||
r.Items[index].Clear()
|
||||
}
|
||||
r.Items = nil
|
||||
r.ExpiresAt = time.Time{}
|
||||
r.SchemaVersion = 0
|
||||
}
|
||||
Loading…
Reference in a new issue