Files
zeekay 8feb24ea1f One name for this fork, and it is ours
The server module named github.com/hanzoai/team/server/v8 — a path that
resolves to the retired workspace's repository, not this one — while
server/public still published github.com/mattermost/mattermost/server/public.
Both are github.com/hanzoteam/server/... now, which is where this code
actually lives.

That second half is what made the binary unbootable. Upstream's public path
stayed claimed by upstream, mattermost-plugin-ai imported it, and the build
linked public/model twice; public/plugin's gob.Register then ran twice under
one name and panicked at init, before main. Reverting the rename traded the
brand for a working binary. Rebranding the plugin alongside it needs no such
trade: the agents fork is github.com/hanzoteam/agents/v2 against our public
module, so no module named mattermost/mattermost is in the graph at all.

Measured: `go list -deps ./cmd/mattermost` names exactly one public/model, and
it is ours.
2026-08-28 23:35:36 -07:00

190 lines
6.0 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package properties
import (
"testing"
"github.com/hanzoteam/server/server/public/model"
"github.com/hanzoteam/server/server/public/shared/mlog"
"github.com/hanzoteam/server/server/public/shared/request"
"github.com/hanzoteam/server/server/v8/channels/store"
"github.com/stretchr/testify/require"
)
type TestHelper struct {
service *PropertyService
dbStore store.Store
Context *request.Context
CPAGroupID string
}
func Setup(tb testing.TB) *TestHelper {
if testing.Short() {
tb.SkipNow()
}
dbStore := mainHelper.GetStore()
dbStore.DropAllTables()
dbStore.MarkSystemRanUnitTests()
mainHelper.PreloadMigrations()
return setupTestHelper(dbStore, tb)
}
func setupTestHelper(s store.Store, tb testing.TB) *TestHelper {
logger := mlog.CreateConsoleTestLogger(tb)
service, err := New(ServiceConfig{
PropertyGroupStore: s.PropertyGroup(),
PropertyFieldStore: s.PropertyField(),
PropertyValueStore: s.PropertyValue(),
CallerIDExtractor: func(rctx request.CTX) string {
if rctx == nil {
return ""
}
callerID, _ := model.CallerIDFromContext(rctx.Context())
return callerID
},
RequestOptionsExtractor: func(rctx request.CTX) model.PropertyRequestOptions {
if rctx == nil {
return model.PropertyRequestOptions{}
}
return model.PropertyRequestOptionsFromContext(rctx.Context())
},
})
require.NoError(tb, err)
tb.Cleanup(func() {
s.Close()
})
return &TestHelper{
service: service,
dbStore: s,
Context: request.EmptyContext(logger),
}
}
// RequestContextWithCallerID adds the caller ID to a request.CTX for access control purposes.
func RequestContextWithCallerID(rctx request.CTX, callerID string) request.CTX {
ctx := model.WithCallerID(rctx.Context(), callerID)
return rctx.WithContext(ctx)
}
// RequestContextWithCallerIDAndOptions adds the caller ID and per-call
// declarations to a request.CTX for access control purposes.
func RequestContextWithCallerIDAndOptions(rctx request.CTX, callerID string, options model.PropertyRequestOptions) request.CTX {
ctx := model.WithCallerID(rctx.Context(), callerID)
ctx = model.WithPropertyRequestOptions(ctx, options)
return rctx.WithContext(ctx)
}
// setPluginCheckerForTests sets the plugin checker on the AccessControlHook for testing.
func (ps *PropertyService) setPluginCheckerForTests(pluginChecker PluginChecker) {
for _, hook := range ps.hooks {
if ach, ok := hook.(*AccessControlHook); ok {
ach.setPluginCheckerForTests(pluginChecker)
}
}
}
func (h *AccessControlHook) setPluginCheckerForTests(pluginChecker PluginChecker) {
h.pluginChecker = pluginChecker
}
func (th *TestHelper) RegisterCPAPropertyGroup(tb testing.TB) *TestHelper {
// Register the CPA group so requiresAccessControl can always look it up
group, groupErr := th.service.RegisterPropertyGroup(&model.PropertyGroup{Name: model.AccessControlPropertyGroupName, Version: model.PropertyGroupVersionV2})
require.NoError(tb, groupErr)
th.CPAGroupID = group.ID
// Create and register the access control hook now that the group ID is known
hook := NewAccessControlHook(th.service, nil, group.ID)
th.service.AddHook(hook)
return th
}
// RegisterPropertyGroup registers a new property group with the given version and a unique name.
func (th *TestHelper) RegisterPropertyGroup(tb testing.TB, version int) *model.PropertyGroup {
tb.Helper()
group, err := th.service.RegisterPropertyGroup(&model.PropertyGroup{
Name: model.NewId(),
Version: version,
})
require.NoError(tb, err)
return group
}
// CreateTeam creates a team for testing hierarchy
func (th *TestHelper) CreateTeam(tb testing.TB) *model.Team {
team := &model.Team{
DisplayName: "Test Team " + model.NewId(),
Name: "team" + model.NewId(),
Type: model.TeamOpen,
}
team, err := th.dbStore.Team().Save(team)
require.NoError(tb, err)
return team
}
// CreateChannel creates a channel in the given team
func (th *TestHelper) CreateChannel(tb testing.TB, teamID string) *model.Channel {
channel := &model.Channel{
TeamId: teamID,
DisplayName: "Test Channel " + model.NewId(),
Name: "channel" + model.NewId(),
Type: model.ChannelTypeOpen,
}
channel, err := th.dbStore.Channel().Save(th.Context, channel, 10000)
require.NoError(tb, err)
return channel
}
// CreateDMChannel creates a DM channel (no team association)
func (th *TestHelper) CreateDMChannel(tb testing.TB) *model.Channel {
// Create two users for the DM
user1 := th.CreateUser(tb)
user2 := th.CreateUser(tb)
channel, err := th.dbStore.Channel().CreateDirectChannel(th.Context, user1, user2)
require.NoError(tb, err)
return channel
}
// CreateUser creates a user for testing
func (th *TestHelper) CreateUser(tb testing.TB) *model.User {
id := model.NewId()
user := &model.User{
Email: "success+" + id + "@simulator.amazonses.com",
Username: "un_" + id,
Nickname: "nn_" + id,
Password: model.NewTestPassword(),
EmailVerified: true,
}
user, err := th.dbStore.User().Save(th.Context, user)
require.NoError(tb, err)
return user
}
// CreatePropertyField creates a property field using the service (with access control routing)
func (th *TestHelper) CreatePropertyField(tb testing.TB, rctx request.CTX, field *model.PropertyField) *model.PropertyField {
result, err := th.service.CreatePropertyField(rctx, field)
require.NoError(tb, err)
return result
}
// CreatePropertyFieldDirect creates a property field directly via store (bypasses conflict check and access control)
func (th *TestHelper) CreatePropertyFieldDirect(tb testing.TB, field *model.PropertyField) *model.PropertyField {
result, err := th.dbStore.PropertyField().Create(field)
require.NoError(tb, err)
return result
}
// CreatePropertyValue creates a property value using the service (with access control routing)
func (th *TestHelper) CreatePropertyValue(tb testing.TB, rctx request.CTX, value *model.PropertyValue) *model.PropertyValue {
result, err := th.service.CreatePropertyValue(rctx, value)
require.NoError(tb, err)
return result
}