* Added premium SKU

* removed duplicate enterprise license check functions

* Added license check on API layer

* lint fix

* lint fix

* refactured signature:

* test: Add comprehensive tests for license tier check functions

* fixed test

* text update

* optimised license checks

* fixedf test

* Updated license valid function

* webapp license checks

* handling prekium SKU in webappp:

* added plugin api method and general refactoring

* Updated tests

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Harshil Sharma
2025-04-03 13:07:54 +05:30
коммит произвёл GitHub
родитель 21ca303b5e
Коммит a9f09cadc2
30 изменённых файлов: 409 добавлений и 163 удалений

Просмотреть файл

@@ -2453,7 +2453,7 @@ func convertGroupMessageToChannel(c *Context, w http.ResponseWriter, r *http.Req
}
func canEditChannelBanner(license *model.License, originalChannel *model.Channel) *model.AppError {
if license == nil || !license.IsE20OrEnterprise() {
if !model.MinimumPremiumLicense(license) {
return model.NewAppError("", "license_error.feature_unavailable", nil, "feature is not available for the current license", http.StatusForbidden)
}

Просмотреть файл

@@ -810,7 +810,7 @@ func TestPatchChannel(t *testing.T) {
t.Run("Should be able to configure channel banner on a channel", func(t *testing.T) {
client.Logout(context.Background())
th.LoginBasic()
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuPremium))
defer func() {
th.App.Srv().RemoveLicense()
}()
@@ -845,7 +845,7 @@ func TestPatchChannel(t *testing.T) {
t.Run("Cannot enable channel banner without configuring it", func(t *testing.T) {
client.Logout(context.Background())
th.LoginBasic()
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuPremium))
defer func() {
th.App.Srv().RemoveLicense()
}()
@@ -905,7 +905,7 @@ func TestPatchChannel(t *testing.T) {
t.Run("Cannot configure channel banner on a DM channel", func(t *testing.T) {
client.Logout(context.Background())
th.LoginBasic()
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuPremium))
defer func() {
th.App.Srv().RemoveLicense()
}()
@@ -932,7 +932,7 @@ func TestPatchChannel(t *testing.T) {
t.Run("Cannot configure channel banner on a GM channel", func(t *testing.T) {
client.Logout(context.Background())
th.LoginBasic()
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise))
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuPremium))
defer func() {
th.App.Srv().RemoveLicense()
}()
@@ -5728,7 +5728,7 @@ func TestCanEditChannelBanner(t *testing.T) {
})
t.Run("when channel type is direct message", func(t *testing.T) {
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise)
license := model.NewTestLicenseSKU(model.LicenseShortSkuPremium)
channel := &model.Channel{
Type: model.ChannelTypeDirect,
}
@@ -5741,7 +5741,7 @@ func TestCanEditChannelBanner(t *testing.T) {
})
t.Run("when channel type is group message", func(t *testing.T) {
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise)
license := model.NewTestLicenseSKU(model.LicenseShortSkuPremium)
channel := &model.Channel{
Type: model.ChannelTypeGroup,
}
@@ -5753,7 +5753,7 @@ func TestCanEditChannelBanner(t *testing.T) {
})
t.Run("when channel type is open and license is valid", func(t *testing.T) {
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise)
license := model.NewTestLicenseSKU(model.LicenseShortSkuPremium)
channel := &model.Channel{
Type: model.ChannelTypeOpen,
}
@@ -5763,7 +5763,7 @@ func TestCanEditChannelBanner(t *testing.T) {
})
t.Run("when channel type is private and license is valid", func(t *testing.T) {
license := model.NewTestLicenseSKU(model.LicenseShortSkuEnterprise)
license := model.NewTestLicenseSKU(model.LicenseShortSkuPremium)
channel := &model.Channel{
Type: model.ChannelTypePrivate,
}

Просмотреть файл

@@ -27,7 +27,7 @@ func (api *API) InitCustomProfileAttributes() {
}
func listCPAFields(c *Context, w http.ResponseWriter, r *http.Request) {
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.listCPAFields", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}
@@ -49,7 +49,7 @@ func createCPAField(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.createCPAField", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}
@@ -89,7 +89,7 @@ func patchCPAField(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.patchCPAField", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}
@@ -151,7 +151,7 @@ func deleteCPAField(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.deleteCPAField", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}
@@ -255,7 +255,7 @@ func sanitizePropertyValue(cpaField *model.CPAField, rawValue json.RawMessage) (
}
func patchCPAValues(c *Context, w http.ResponseWriter, r *http.Request) {
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.patchCPAValues", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}
@@ -327,7 +327,7 @@ func patchCPAValues(c *Context, w http.ResponseWriter, r *http.Request) {
}
func listCPAValues(c *Context, w http.ResponseWriter, r *http.Request) {
if c.App.Channels().License() == nil || !c.App.Channels().License().IsE20OrEnterprise() {
if !model.MinimumEnterpriseLicense(c.App.Channels().License()) {
c.Err = model.NewAppError("Api4.listCPAValues", "api.custom_profile_attributes.license_error", nil, "", http.StatusForbidden)
return
}

Просмотреть файл

@@ -1482,7 +1482,7 @@ func licensedAndConfiguredForGroupBySource(app *app.App, source model.GroupSourc
return model.NewAppError("", "api.ldap_groups.license_error", nil, "", http.StatusForbidden)
}
if source == model.GroupSourceCustom && lic.SkuShortName != model.LicenseShortSkuProfessional && lic.SkuShortName != model.LicenseShortSkuEnterprise {
if source == model.GroupSourceCustom && !model.MinimumProfessionalLicense(lic) {
return model.NewAppError("", "api.custom_groups.license_error", nil, "", http.StatusBadRequest)
}

Просмотреть файл

@@ -238,10 +238,6 @@ func requireLicense(c *Context) *model.AppError {
return nil
}
func minimumProfessionalLicense(c *Context) *model.AppError {
return model.MinimumProfessionalProvidedLicense(c.App.Srv().License())
}
func setHandlerOpts(handler *web.Handler, opts ...APIHandlerOption) {
if len(opts) == 0 {
return

Просмотреть файл

@@ -21,7 +21,9 @@ func (api *API) InitIPFiltering() {
}
func ensureIPFilteringInterface(c *Context, where string) (einterfaces.IPFilteringInterface, bool) {
if c.App.IPFiltering() == nil || !c.App.Config().FeatureFlags.CloudIPFiltering || c.App.License() == nil || !c.App.License().IsCloud() || c.App.License().SkuShortName != model.LicenseShortSkuEnterprise {
license := c.App.License()
ipFilteringFeatureFlag := c.App.Config().FeatureFlags.CloudIPFiltering
if c.App.IPFiltering() == nil || !ipFilteringFeatureFlag || license == nil || !license.IsCloud() || !model.MinimumEnterpriseLicense(license) {
c.Err = model.NewAppError(where, "api.context.ip_filtering.not_available.app_error", nil, "", http.StatusNotImplemented)
return nil, false
}

Просмотреть файл

@@ -63,7 +63,7 @@ func ensureOutgoingOAuthConnectionInterface(c *Context, where string) (einterfac
return nil, false
}
if c.App.OutgoingOAuthConnections() == nil || c.App.License() == nil || c.App.License().SkuShortName != model.LicenseShortSkuEnterprise {
if c.App.OutgoingOAuthConnections() == nil || !model.MinimumEnterpriseLicense(c.App.License()) {
c.Err = model.NewAppError(where, "api.license.upgrade_needed.app_error", nil, "", http.StatusNotImplemented)
return nil, false
}

Просмотреть файл

@@ -1083,11 +1083,11 @@ func unpinPost(c *Context, w http.ResponseWriter, _ *http.Request) {
func acknowledgePost(c *Context, w http.ResponseWriter, r *http.Request) {
// license check
permissionErr := minimumProfessionalLicense(c)
if permissionErr != nil {
c.Err = permissionErr
if !model.MinimumProfessionalLicense(c.App.Srv().License()) {
c.Err = model.NewAppError("", model.NoTranslation, nil, "feature is not available for the current license", http.StatusNotImplemented)
return
}
c.RequirePostId().RequireUserId()
if c.Err != nil {
return
@@ -1122,11 +1122,11 @@ func acknowledgePost(c *Context, w http.ResponseWriter, r *http.Request) {
func unacknowledgePost(c *Context, w http.ResponseWriter, r *http.Request) {
// license check
permissionErr := minimumProfessionalLicense(c)
if permissionErr != nil {
c.Err = permissionErr
if !model.MinimumProfessionalLicense(c.App.Srv().License()) {
c.Err = model.NewAppError("", "license_error.feature_unavailable", nil, "feature is not available for the current license", http.StatusNotImplemented)
return
}
c.RequirePostId().RequireUserId()
if c.Err != nil {
return

Просмотреть файл

@@ -1465,7 +1465,7 @@ func (a *App) allowChannelMentions(c request.CTX, post *model.Post, numProfiles
// allowGroupMentions returns whether or not the group mentions are allowed for the given post.
func (a *App) allowGroupMentions(c request.CTX, post *model.Post) bool {
if license := a.Srv().License(); license == nil || (license.SkuShortName != model.LicenseShortSkuProfessional && license.SkuShortName != model.LicenseShortSkuEnterprise) {
if !model.MinimumProfessionalLicense(a.Srv().License()) {
return false
}

Просмотреть файл

@@ -670,7 +670,6 @@ func (a *App) mergePrepackagedPlugins(remoteMarketplacePlugins map[string]*model
return model.NewAppError("mergePrepackagedPlugins", "app.plugin.config.app_error", nil, "", http.StatusInternalServerError)
}
isEnterpriseLicense := a.License() != nil && a.License().IsE20OrEnterprise()
for _, prepackaged := range pluginsEnvironment.PrepackagedPlugins() {
if prepackaged.Manifest == nil {
continue
@@ -687,7 +686,7 @@ func (a *App) mergePrepackagedPlugins(remoteMarketplacePlugins map[string]*model
// If not enterprise, check version.
// Playbooks is not listed in the marketplace, this only handles prepackaged.
if !isEnterpriseLicense {
if !model.MinimumEnterpriseLicense(a.License()) {
if prepackaged.Manifest.Id == model.PluginIdPlaybooks {
version, err := semver.Parse(prepackaged.Manifest.Version)
if err != nil {
@@ -1033,8 +1032,8 @@ func (ch *Channels) processPrepackagedPlugin(pluginPath *pluginSignaturePath) (*
if err != nil {
return nil, errors.Wrapf(err, "Unable to verify prepackaged playbooks version")
}
license := ch.License()
hasEnterpriseLicense := license != nil && license.IsE20OrEnterprise()
hasEnterpriseLicense := model.MinimumEnterpriseLicense(ch.License())
// Do not install playbooks >=v2 if we do not have an enterprise license
if version.GTE(SemVerV2) && !hasEnterpriseLicense {
@@ -1105,15 +1104,13 @@ func (ch *Channels) pluginIsTransitionallyPrepackaged(m *model.Manifest) bool {
// - the server is not enterprise licensed
// - the playbooks version is <v2
func (ch *Channels) playbooksIsTransitionallyPrepackaged(m *model.Manifest) bool {
license := ch.srv.License()
isNotEnterpriseLicensed := !(license != nil && license.IsE20OrEnterprise())
version, err := semver.Parse(m.Version)
if err != nil {
ch.srv.Log().Warn("unable to parse prepackaged playbooks version - not marking it as transitional.", mlog.String("version", m.Version), mlog.Err(err))
return false
}
return isNotEnterpriseLicensed && version.LT(SemVerV2)
return !model.MinimumEnterpriseLicense(ch.srv.License()) && version.LT(SemVerV2)
}
// shouldPersistTransitionallyPrepackagedPlugin determines if a transitionally prepackaged plugin

Просмотреть файл

@@ -55,16 +55,14 @@ func postPriorityCheck(
}
if ack := priority.RequestedAck; ack != nil && *ack {
licenseErr := model.MinimumProfessionalProvidedLicense(license)
if licenseErr != nil {
return licenseErr
if !model.MinimumProfessionalLicense(license) {
return model.NewAppError("", "license_error.feature_unavailable", nil, "feature is not available for the current license", http.StatusNotImplemented)
}
}
if notification := priority.PersistentNotifications; notification != nil && *notification {
licenseErr := model.MinimumProfessionalProvidedLicense(license)
if licenseErr != nil {
return licenseErr
if !model.MinimumProfessionalLicense(license) {
return model.NewAppError("", "license_error.feature_unavailable", nil, "feature is not available for the current license", http.StatusNotImplemented)
}
if !isPersistentNotificationsEnabled {
return priorityForbiddenErr

Просмотреть файл

@@ -199,7 +199,7 @@ func (a *App) GetUserCountForReport(filter *model.UserReportOptions) (*int64, *m
}
func (a *App) StartUsersBatchExport(rctx request.CTX, ro *model.UserReportOptions, startAt int64, endAt int64) *model.AppError {
if license := a.Srv().License(); license == nil || (license.SkuShortName != model.LicenseShortSkuProfessional && license.SkuShortName != model.LicenseShortSkuEnterprise) {
if !model.MinimumProfessionalLicense(a.Srv().License()) {
return model.NewAppError("StartUsersBatchExport", "app.report.start_users_batch_export.license_error", nil, "", http.StatusBadRequest)
}

Просмотреть файл

@@ -21,8 +21,7 @@ func (scheduler *Scheduler) NextScheduleTime(cfg *model.Config, _ time.Time, _ b
func MakeScheduler(jobServer *jobs.JobServer, licenseFunc func() *model.License) *Scheduler {
enabledFunc := func(_ *model.Config) bool {
l := licenseFunc()
return l != nil && (l.SkuShortName == model.LicenseShortSkuProfessional || l.SkuShortName == model.LicenseShortSkuEnterprise)
return model.MinimumProfessionalLicense(licenseFunc())
}
return &Scheduler{jobs.NewPeriodicScheduler(jobServer, model.JobTypePostPersistentNotifications, 0, enabledFunc)}
}

Просмотреть файл

@@ -226,7 +226,7 @@ func GenerateClientConfig(c *model.Config, telemetryID string, license *model.Li
props["ExperimentalRemoteClusterService"] = strconv.FormatBool(c.FeatureFlags.EnableRemoteClusterService && *c.ConnectedWorkspacesSettings.EnableRemoteClusterService)
}
if license.SkuShortName == model.LicenseShortSkuProfessional || license.SkuShortName == model.LicenseShortSkuEnterprise {
if model.MinimumProfessionalLicense(license) {
props["EnableCustomGroups"] = strconv.FormatBool(*c.ServiceSettings.EnableCustomGroups)
props["PostAcknowledgements"] = "true"
props["ScheduledPosts"] = strconv.FormatBool(*c.ServiceSettings.ScheduledPosts)

Просмотреть файл

@@ -99,6 +99,7 @@ type TrackSKU string
const (
TrackProfessionalSKU TrackSKU = "professional"
TrackEnterpriseSKU TrackSKU = "enterprise"
TrackPremiumSKU TrackSKU = "premium"
)
type TrackFeature string

Просмотреть файл

@@ -23,8 +23,19 @@ const (
LicenseShortSkuE20 = "E20"
LicenseShortSkuProfessional = "professional"
LicenseShortSkuEnterprise = "enterprise"
LicenseShortSkuPremium = "premium"
ProfessionalTier = 10
EnterpriseTier = 20
PremiumTier = 30
)
var LicenseToLicenseTier = map[string]int{
LicenseShortSkuProfessional: ProfessionalTier,
LicenseShortSkuEnterprise: EnterpriseTier,
LicenseShortSkuPremium: PremiumTier,
}
const (
LicenseUpForRenewalEmailSent = "LicenseUpForRenewalEmailSent"
)
@@ -356,8 +367,7 @@ func (l *License) IsSanctionedTrial() bool {
func (l *License) HasEnterpriseMarketplacePlugins() bool {
return *l.Features.EnterprisePlugins ||
l.SkuShortName == LicenseShortSkuE20 ||
l.SkuShortName == LicenseShortSkuProfessional ||
l.SkuShortName == LicenseShortSkuEnterprise
MinimumProfessionalLicense(l)
}
func (l *License) HasRemoteClusterService() bool {
@@ -371,8 +381,7 @@ func (l *License) HasRemoteClusterService() bool {
}
return (l.Features != nil && l.Features.RemoteClusterService != nil && *l.Features.RemoteClusterService) ||
l.SkuShortName == LicenseShortSkuProfessional ||
l.SkuShortName == LicenseShortSkuEnterprise
MinimumProfessionalLicense(l)
}
func (l *License) HasSharedChannels() bool {
@@ -381,13 +390,7 @@ func (l *License) HasSharedChannels() bool {
}
return (l.Features != nil && l.Features.SharedChannels != nil && *l.Features.SharedChannels) ||
l.SkuShortName == LicenseShortSkuProfessional ||
l.SkuShortName == LicenseShortSkuEnterprise
}
// IsE20OrEnterprise returns true when the license is for E20 or Enterprise.
func (l *License) IsE20OrEnterprise() bool {
return l.SkuShortName == LicenseShortSkuE20 || l.SkuShortName == LicenseShortSkuEnterprise
MinimumProfessionalLicense(l)
}
// NewTestLicense returns a license that expires in the future and has the given features.
@@ -459,9 +462,19 @@ func (lr *LicenseRecord) PreSave() {
lr.CreateAt = GetMillis()
}
func MinimumProfessionalProvidedLicense(license *License) *AppError {
if license == nil || (license.SkuShortName != LicenseShortSkuProfessional && license.SkuShortName != LicenseShortSkuEnterprise) {
return NewAppError("", NoTranslation, nil, "license is neither professional nor enterprise", http.StatusNotImplemented)
}
return nil
// MinimumProfessionalLicense returns true if the provided license is at least a professional license.
// Higher tier licenses also satisfy the condition.
func MinimumProfessionalLicense(license *License) bool {
return license != nil && LicenseToLicenseTier[license.SkuShortName] >= ProfessionalTier
}
// MinimumEnterpriseLicense returns true if the provided license is at least a enterprise license.
// Higher tier licenses also satisfy the condition.
func MinimumEnterpriseLicense(license *License) bool {
return license != nil && LicenseToLicenseTier[license.SkuShortName] >= EnterpriseTier
}
// MinimumPremiumLicense returns true if the provided license is at least a premium license.
func MinimumPremiumLicense(license *License) bool {
return license != nil && LicenseToLicenseTier[license.SkuShortName] >= PremiumTier
}

Просмотреть файл

@@ -485,3 +485,189 @@ func TestLicenseHasSharedChannels(t *testing.T) {
})
}
}
func TestMinimumProfessionalLicense(t *testing.T) {
testCases := []struct {
description string
license *License
expectedValue bool
}{
{
"nil license",
nil,
false,
},
{
"professional license",
&License{
SkuShortName: LicenseShortSkuProfessional,
},
true,
},
{
"enterprise license",
&License{
SkuShortName: LicenseShortSkuEnterprise,
},
true,
},
{
"premium license",
&License{
SkuShortName: LicenseShortSkuPremium,
},
true,
},
{
"E10 license",
&License{
SkuShortName: LicenseShortSkuE10,
},
false,
},
{
"E20 license",
&License{
SkuShortName: LicenseShortSkuE20,
},
false,
},
{
"unknown license",
&License{
SkuShortName: "unknown",
},
false,
},
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
assert.Equal(t, testCase.expectedValue, MinimumProfessionalLicense(testCase.license))
})
}
}
func TestMinimumEnterpriseLicense(t *testing.T) {
testCases := []struct {
description string
license *License
expectedValue bool
}{
{
"nil license",
nil,
false,
},
{
"professional license",
&License{
SkuShortName: LicenseShortSkuProfessional,
},
false,
},
{
"enterprise license",
&License{
SkuShortName: LicenseShortSkuEnterprise,
},
true,
},
{
"premium license",
&License{
SkuShortName: LicenseShortSkuPremium,
},
true,
},
{
"E10 license",
&License{
SkuShortName: LicenseShortSkuE10,
},
false,
},
{
"E20 license",
&License{
SkuShortName: LicenseShortSkuE20,
},
false,
},
{
"unknown license",
&License{
SkuShortName: "unknown",
},
false,
},
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
assert.Equal(t, testCase.expectedValue, MinimumEnterpriseLicense(testCase.license))
})
}
}
func TestMinimumPremiumLicense(t *testing.T) {
testCases := []struct {
description string
license *License
expectedValue bool
}{
{
"nil license",
nil,
false,
},
{
"professional license",
&License{
SkuShortName: LicenseShortSkuProfessional,
},
false,
},
{
"enterprise license",
&License{
SkuShortName: LicenseShortSkuEnterprise,
},
false,
},
{
"premium license",
&License{
SkuShortName: LicenseShortSkuPremium,
},
true,
},
{
"E10 license",
&License{
SkuShortName: LicenseShortSkuE10,
},
false,
},
{
"E20 license",
&License{
SkuShortName: LicenseShortSkuE20,
},
false,
},
{
"unknown license",
&License{
SkuShortName: "unknown",
},
false,
},
}
for _, testCase := range testCases {
t.Run(testCase.description, func(t *testing.T) {
assert.Equal(t, testCase.expectedValue, MinimumPremiumLicense(testCase.license))
})
}
}

Просмотреть файл

@@ -4,13 +4,6 @@ import (
"github.com/mattermost/mattermost/server/public/model"
)
const (
e10 = "E10"
e20 = "E20"
professional = "professional"
enterprise = "enterprise"
)
// IsEnterpriseLicensedOrDevelopment returns true when the server is licensed with any Mattermost
// Enterprise License, or has `EnableDeveloper` and `EnableTesting` configuration settings
// enabled signaling a non-production, developer mode.
@@ -30,7 +23,7 @@ func isValidSkuShortName(license *model.License) bool {
}
switch license.SkuShortName {
case e10, e20, professional, enterprise:
case model.LicenseShortSkuE10, model.LicenseShortSkuE20, model.LicenseShortSkuProfessional, model.LicenseShortSkuEnterprise, model.LicenseShortSkuPremium:
return true
default:
return false
@@ -41,9 +34,7 @@ func isValidSkuShortName(license *model.License) bool {
// Enterprise E10 License or a Mattermost Professional License, or has `EnableDeveloper` and
// `EnableTesting` configuration settings enabled, signaling a non-production, developer mode.
func IsE10LicensedOrDevelopment(config *model.Config, license *model.License) bool {
if license != nil &&
(license.SkuShortName == e10 || license.SkuShortName == professional ||
license.SkuShortName == e20 || license.SkuShortName == enterprise) {
if model.MinimumProfessionalLicense(license) {
return true
}
@@ -65,7 +56,7 @@ func IsE10LicensedOrDevelopment(config *model.Config, license *model.License) bo
// Enterprise E20 License or a Mattermost Enterprise License, or has `EnableDeveloper` and
// `EnableTesting` configuration settings enabled, signaling a non-production, developer mode.
func IsE20LicensedOrDevelopment(config *model.Config, license *model.License) bool {
if license != nil && (license.SkuShortName == e20 || license.SkuShortName == enterprise) {
if model.MinimumEnterpriseLicense(license) {
return true
}
@@ -83,6 +74,16 @@ func IsE20LicensedOrDevelopment(config *model.Config, license *model.License) bo
return IsConfiguredForDevelopment(config)
}
// IsPremiumLicensedOrDevelopment returns true when the server is licensed with a Mattermost
// Premium License, or has `EnableDeveloper` and `EnableTesting` configuration settings
func IsPremiumLicensedOrDevelopment(config *model.Config, license *model.License) bool {
if license != nil && license.SkuShortName == model.LicenseShortSkuPremium {
return true
}
return IsConfiguredForDevelopment(config)
}
// IsConfiguredForDevelopment returns true when the server has `EnableDeveloper` and `EnableTesting`
// configuration settings enabled, signaling a non-production, developer mode.
func IsConfiguredForDevelopment(config *model.Config) bool {

Просмотреть файл

@@ -133,19 +133,6 @@ func TestIsE20LicensedOrDevelopment(t *testing.T) {
Features: &model.Features{FutureFeatures: bToP(true)},
}))
})
t.Run("license with E20 SKU name, disabled future features", func(t *testing.T) {
assert.True(t, IsE20LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{FutureFeatures: bToP(false)},
}))
})
t.Run("license with E20 SKU name, enabled future features", func(t *testing.T) {
assert.True(t, IsE20LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{FutureFeatures: bToP(true)},
}))
})
t.Run("license with enterprise SKU name, disabled future features", func(t *testing.T) {
assert.True(t, IsE20LicensedOrDevelopment(nil, &model.License{
@@ -229,20 +216,6 @@ func TestIsE10LicensedOrDevelopment(t *testing.T) {
))
})
t.Run("license with E10 SKU name, disabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E10",
Features: &model.Features{LDAP: bToP(false)},
}))
})
t.Run("license with E10 SKU name, enabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E10",
Features: &model.Features{LDAP: bToP(true)},
}))
})
t.Run("license with professional SKU name, disabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
SkuShortName: "professional",
@@ -256,19 +229,6 @@ func TestIsE10LicensedOrDevelopment(t *testing.T) {
Features: &model.Features{LDAP: bToP(true)},
}))
})
t.Run("license with E20 SKU name, disabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{LDAP: bToP(false)},
}))
})
t.Run("license with E20 SKU name, enabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{LDAP: bToP(true)},
}))
})
t.Run("license with enterprise SKU name, disabled LDAP", func(t *testing.T) {
assert.True(t, IsE10LicensedOrDevelopment(nil, &model.License{
@@ -325,6 +285,88 @@ func TestIsValidSKUShortName(t *testing.T) {
})
}
func TestIsPremiumOrDevelopment(t *testing.T) {
t.Run("nil license features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{}))
})
t.Run("nil future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{Features: &model.Features{}}))
})
t.Run("disabled future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{Features: &model.Features{
FutureFeatures: bToP(false),
}}))
})
t.Run("should have no affect of future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{Features: &model.Features{
FutureFeatures: bToP(true),
}}))
})
t.Run("no license, no config", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, nil))
})
t.Run("no license, nil config", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(
&model.Config{ServiceSettings: model.ServiceSettings{EnableDeveloper: nil, EnableTesting: nil}},
nil,
))
})
t.Run("no license, only developer mode", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(
&model.Config{ServiceSettings: model.ServiceSettings{EnableDeveloper: bToP(true), EnableTesting: bToP(false)}},
nil,
))
})
t.Run("no license, only testing mode", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(
&model.Config{ServiceSettings: model.ServiceSettings{EnableDeveloper: bToP(false), EnableTesting: bToP(true)}},
nil,
))
})
t.Run("no license, developer and testing mode", func(t *testing.T) {
assert.True(t, IsPremiumLicensedOrDevelopment(
&model.Config{ServiceSettings: model.ServiceSettings{EnableDeveloper: bToP(true), EnableTesting: bToP(true)}},
nil,
))
})
t.Run("license with E10 SKU name, disabled future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{
SkuShortName: "E10",
Features: &model.Features{FutureFeatures: bToP(false)},
}))
})
t.Run("license with E10 SKU name, enabled future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{
SkuShortName: "E10",
Features: &model.Features{FutureFeatures: bToP(true)},
}))
})
t.Run("license with E20 SKU name, disabled future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{FutureFeatures: bToP(false)},
}))
})
t.Run("license with E20 SKU name, enabled future features", func(t *testing.T) {
assert.False(t, IsPremiumLicensedOrDevelopment(nil, &model.License{
SkuShortName: "E20",
Features: &model.Features{FutureFeatures: bToP(true)},
}))
})
}
func bToP(b bool) *bool {
return &b
}