package service import ( "context" "testing" "github.com/Tencent/WeKnora/internal/types" "github.com/Tencent/WeKnora/internal/types/interfaces" ) type stubEmbedChannelRepo struct { interfaces.EmbedChannelRepository ch *types.EmbedChannel } func (r *stubEmbedChannelRepo) GetByID(_ context.Context, id string) (*types.EmbedChannel, error) { if r.ch == nil || r.ch.ID != id { return nil, nil } cp := *r.ch return &cp, nil } func (r *stubEmbedChannelRepo) Update(_ context.Context, ch *types.EmbedChannel) error { cp := *ch r.ch = &cp return nil } func (r *stubEmbedChannelRepo) ListByTenant(_ context.Context, tenant uint64) ([]*types.EmbedChannel, error) { if r.ch != nil && r.ch.TenantID == tenant { return []*types.EmbedChannel{r.ch}, nil } return nil, nil } func embedManagementTestContext(user string, role types.TenantRole) context.Context { ctx := context.WithValue(context.Background(), types.TenantIDContextKey, uint64(42)) ctx = context.WithValue(ctx, types.UserIDContextKey, user) return context.WithValue(ctx, types.TenantRoleContextKey, role) } func TestEmbedChannelUpdateAgentID(t *testing.T) { repo := &stubEmbedChannelRepo{ ch: &types.EmbedChannel{ ID: "ch-1", TenantID: 42, AgentID: "agent-old", Name: "Support", }, } svc := &embedChannelService{ repo: repo, agentService: &stubAgentForEmbed{ agent: &types.CustomAgent{ID: "agent-new", TenantID: 42}, }, } enabled := true updated, err := svc.Update( embedManagementTestContext("admin", types.TenantRoleAdmin), 42, "ch-1", &types.EmbedChannel{AgentID: "agent-new"}, &enabled, nil, nil, nil, nil, nil, nil, ) if err != nil { t.Fatalf("Update() error = %v", err) } if updated.AgentID != "agent-new" { t.Fatalf("updated.AgentID = %q, want agent-new", updated.AgentID) } if repo.ch.AgentID != "agent-new" { t.Fatalf("persisted AgentID = %q, want agent-new", repo.ch.AgentID) } } func TestEmbedManagementRequiresAgentOwnership(t *testing.T) { repo := &stubEmbedChannelRepo{ch: &types.EmbedChannel{ID: "private-channel", TenantID: 42, AgentID: "private-agent", PublishToken: "private-token"}} svc := &embedChannelService{repo: repo, agentService: &stubAgentForEmbed{agent: &types.CustomAgent{ID: "private-agent", TenantID: 42, CreatedBy: "alice"}}} for _, tc := range []struct { name string user string role types.TenantRole allowed bool }{ {"owner", "alice", types.TenantRoleContributor, true}, {"other member", "bob", types.TenantRoleContributor, false}, {"viewer", "bob", types.TenantRoleViewer, false}, {"administrator", "admin", types.TenantRoleAdmin, true}, } { t.Run(tc.name, func(t *testing.T) { ctx := embedManagementTestContext(tc.user, tc.role) channel, err := svc.GetOwnedChannel(ctx, 42, "private-channel") if (err == nil && channel != nil) != tc.allowed { t.Fatalf("channel visibility does not match ownership: allowed=%v err=%v", tc.allowed, err) } channels, err := svc.ListByTenant(ctx, 42) if err != nil || (len(channels) == 1) != tc.allowed { t.Fatalf("channel list exposed a private publish token: count=%d err=%v", len(channels), err) } _, err = svc.ensureAgentOwned(ctx, 42, "private-agent") if (err == nil) != tc.allowed { t.Fatalf("channel creation authority did not match ownership: %v", err) } }) } }