feat: app-to-app integration framework + OnlyOffice handlers
Generic integration system for connecting deployed apps via toggle UI. First handlers: OnlyOffice→FileBrowser (config.yaml patch) and OnlyOffice→Nextcloud (occ CLI). Lifecycle hooks auto-suspend on stop and re-apply on start. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
package integrations
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OnlyOfficeNextcloudHandler enables/disables OnlyOffice document editing in Nextcloud via occ.
|
||||
type OnlyOfficeNextcloudHandler struct{}
|
||||
|
||||
func (h *OnlyOfficeNextcloudHandler) Apply(ac *ApplyContext) error {
|
||||
jwtSecret := ac.ProviderEnv["JWT_SECRET"]
|
||||
if jwtSecret == "" {
|
||||
return fmt.Errorf("OnlyOffice JWT_SECRET nincs beállítva")
|
||||
}
|
||||
|
||||
subdomain := ac.ProviderEnv["SUBDOMAIN"]
|
||||
if subdomain == "" && ac.ProviderMeta != nil {
|
||||
subdomain = ac.ProviderMeta.Subdomain
|
||||
}
|
||||
if subdomain == "" {
|
||||
return fmt.Errorf("OnlyOffice aldomain nem ismert")
|
||||
}
|
||||
|
||||
publicURL := fmt.Sprintf("https://%s.%s", subdomain, ac.Domain)
|
||||
internalURL := "http://onlyoffice:80"
|
||||
|
||||
// Install and configure OnlyOffice app in Nextcloud
|
||||
commands := []struct {
|
||||
args []string
|
||||
tolerate string // substring in output to tolerate as success
|
||||
}{
|
||||
{
|
||||
args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "app:install", "onlyoffice"},
|
||||
tolerate: "already installed",
|
||||
},
|
||||
{
|
||||
args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "app:enable", "onlyoffice"},
|
||||
},
|
||||
{
|
||||
args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "config:app:set", "onlyoffice", "DocumentServerUrl", "--value=" + publicURL},
|
||||
},
|
||||
{
|
||||
args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "config:app:set", "onlyoffice", "DocumentServerInternalUrl", "--value=" + internalURL},
|
||||
},
|
||||
{
|
||||
args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "config:app:set", "onlyoffice", "jwt_secret", "--value=" + jwtSecret},
|
||||
},
|
||||
}
|
||||
|
||||
for _, cmd := range commands {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
c := exec.CommandContext(ctx, cmd.args[0], cmd.args[1:]...)
|
||||
out, err := c.CombinedOutput()
|
||||
cancel()
|
||||
if err != nil {
|
||||
if cmd.tolerate != "" && strings.Contains(string(out), cmd.tolerate) {
|
||||
ac.Logger.Printf("[DEBUG] Nextcloud occ: tolerated — %s", strings.TrimSpace(string(out)))
|
||||
continue
|
||||
}
|
||||
return fmt.Errorf("occ parancs sikertelen (%s): %v (kimenet: %s)", cmd.args[len(cmd.args)-1], err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
ac.Logger.Printf("[DEBUG] Nextcloud occ %s: ok", strings.Join(cmd.args[7:], " "))
|
||||
}
|
||||
|
||||
ac.Logger.Printf("[INFO] OnlyOffice integration applied to Nextcloud")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *OnlyOfficeNextcloudHandler) Revoke(ac *ApplyContext) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer cancel()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "app:disable", "onlyoffice")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
outStr := string(out)
|
||||
// Tolerate container not running or app not enabled
|
||||
if strings.Contains(err.Error(), "No such container") ||
|
||||
strings.Contains(outStr, "not enabled") ||
|
||||
strings.Contains(outStr, "not installed") {
|
||||
ac.Logger.Printf("[DEBUG] Nextcloud occ app:disable skipped — %s", strings.TrimSpace(outStr))
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("occ app:disable sikertelen: %v (kimenet: %s)", err, strings.TrimSpace(outStr))
|
||||
}
|
||||
|
||||
ac.Logger.Printf("[INFO] OnlyOffice integration revoked from Nextcloud")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user