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}, }, { // StorageUrl: tells OO Document Server where to reach Nextcloud internally for file callbacks args: []string{"docker", "exec", "-u", "www-data", "nextcloud", "php", "occ", "config:app:set", "onlyoffice", "StorageUrl", "--value=http://nextcloud"}, }, } 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 }