feat: add CalDAV settings UI and team management pages (Phase 3P)

Backend: PUT /api/tenants/{id}/settings endpoint for updating tenant
settings (JSONB merge). Frontend: /einstellungen page with CalDAV
config (URL, credentials, calendar path, sync toggle, interval),
manual sync button, live sync status display. /einstellungen/team
page with member list, invite-by-email, role management.
This commit is contained in:
m
2026-03-25 14:26:05 +01:00
parent b49992b9c0
commit fe97fed56d
8 changed files with 733 additions and 0 deletions

View File

@@ -3,6 +3,7 @@ package services
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"github.com/google/uuid"
@@ -173,6 +174,21 @@ func (s *TenantService) InviteByEmail(ctx context.Context, tenantID uuid.UUID, e
return &ut, nil
}
// UpdateSettings merges new settings into the tenant's existing settings JSONB.
func (s *TenantService) UpdateSettings(ctx context.Context, tenantID uuid.UUID, settings json.RawMessage) (*models.Tenant, error) {
var tenant models.Tenant
err := s.db.QueryRowxContext(ctx,
`UPDATE tenants SET settings = COALESCE(settings, '{}'::jsonb) || $1::jsonb, updated_at = NOW()
WHERE id = $2
RETURNING id, name, slug, settings, created_at, updated_at`,
settings, tenantID,
).StructScan(&tenant)
if err != nil {
return nil, fmt.Errorf("update settings: %w", err)
}
return &tenant, nil
}
// RemoveMember removes a user from a tenant. Cannot remove the last owner.
func (s *TenantService) RemoveMember(ctx context.Context, tenantID, userID uuid.UUID) error {
// Check if the user being removed is an owner