clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

expose visible connections as a public method

Dami committed 591f262
connections returns the configured app connections the viewer may see,
merged with their templates: public ones to everyone, member ones to
members, moderators and the owner, owner ones to the owner. Connections
whose feature is off are left out.
commit
591f26270893b3a17c7fb23aa569adc46323946e
parent
5df27560c504297b6e3122447c82686e28298194
author
Dami <dami.etoile@gmail.com>
2 files changed, +97 -1
Ainternal/daemon/connections_public_test.go42+++++++++++++++++++++++
Minternal/daemon/management.go56+++++++++++++++++++++++++++++-
A internal/daemon/connections_public_test.go +42 -0
M internal/daemon/management.go +55 -1
@@ -110,7 +110,7 @@ func managementAdapterMethod(method string) bool {
110110 // are intentionally separate from the NIP-86 management methods so a public111111 // page cannot accidentally gain access to privileged search or export APIs.112112 func PublicMethods() []string {113- return []string{"queryevents", "eventdetail", "feed", "listview", "claiminvite"}113+ return []string{"queryevents", "eventdetail", "feed", "listview", "claiminvite", "connections"}114114 }115115 116116 func publicManagementMethod(method string) bool {
@@ -151,6 +151,9 @@ func roleName(role string) string {
151151 }152152 153153 func (t *Tenant) executePublicManagement(ctx context.Context, actor, method string, params []json.RawMessage) (any, bool, error) {154+ if method == "connections" {155+ return t.visibleConnections(ctx, actor)156+ }154157 if method == "claiminvite" {155158 if strings.TrimSpace(actor) == "" {156159 return nil, true, errors.New("auth-required: claiminvite")
@@ -487,6 +490,57 @@ func featureEnabled(p policy.Policy, name string) bool {
487490 }488491 }489492 493+// visibleConnections lists configured connections the viewer may see, each494+// merged with its template so pages can render titles, links and QR codes.495+// Visibility "public" shows to everyone, "members" or "auth" to members,496+// moderators and the owner, and "owner" to the owner alone. Connections497+// whose feature is off are left out.498+func (t *Tenant) visibleConnections(ctx context.Context, actor string) (any, bool, error) {499+ rows, _, err := t.connections(ctx)500+ if err != nil {501+ return nil, true, err502+ }503+ role := ""504+ if strings.TrimSpace(actor) != "" {505+ if role, err = t.community.Role(ctx, actor); err != nil {506+ return nil, true, err507+ }508+ }509+ catalog := map[string]templates.Connection{}510+ for _, c := range templates.Connections() {511+ catalog[c.Name] = c512+ }513+ p := t.Policy()514+ result := make([]map[string]any, 0)515+ for _, row := range rows.([]map[string]any) {516+ name, _ := row["template"].(string)517+ if name == "" {518+ name, _ = row["name"].(string)519+ }520+ c, ok := catalog[name]521+ if !ok || (c.Feature != "" && !featureEnabled(p, c.Feature)) {522+ continue523+ }524+ visibility, _ := row["visibility"].(string)525+ if visibility == "" {526+ visibility = c.Visibility527+ }528+ switch visibility {529+ case "public":530+ case "members", "member", "auth":531+ if role != "member" && role != "moderator" && role != "owner" {532+ continue533+ }534+ default:535+ if role != "owner" {536+ continue537+ }538+ }539+ result = append(result, map[string]any{"template": c.Name, "title": c.Title, "about": c.About, "app": c.App, "where": c.Where, "icon": c.Icon, "feature": c.Feature, "visibility": visibility, "qr": c.QR, "inputs": c.Inputs, "links": c.Links})540+ }541+ return result, true, nil542+}543+490544 func (t *Tenant) connections(ctx context.Context) (any, bool, error) {491545 rows, err := t.store.DB().QueryContext(ctx, `SELECT value FROM config_connections ORDER BY position`)492546 if err != nil {