[CLD-7567] Deprecate Self Serve: Second Pass (#26853)
* Deprecate Self Serve: First Pass * Fix ci * Fix more ci * Remmove outdated server tests * Fix a missed spot opening purchase modal in Self Hosted * Fix i18n * Clean up some more server code, fix webapp test * Fix alignment of button * Fix linter * Fix i18n server side * Deprecate in product true up * Add back translation * Remove client functions * Put back client functions * webapp deprecation * Deprecate Self Serve: Second Pass * Fix various pipeline issues * Fix linter * Fix pipelines * Fix handlers_test.go * Fix console.error around hostedCustomer in reducer * PICKY LINTER PLEASE * Fix webapp tests, various other fixes for the CI pipelines * Fix i18n * Updates to accomadate enterprise code removal * Fix mocks * More removal * Fix * Adjustments from PR * Fixes for QA Feedback * Update * Add migrations to remove true up review history * Fix migrations check --------- Co-authored-by: Mattermost Build <build@mattermost.com> Co-authored-by: maria.nunez <maria.nunez@mattermost.com>
Этот коммит содержится в:
@@ -747,7 +747,6 @@ type AppIface interface {
|
||||
GetOnboarding() (*model.System, *model.AppError)
|
||||
GetOpenGraphMetadata(requestURL string) ([]byte, error)
|
||||
GetOrCreateDirectChannel(c request.CTX, userID, otherUserID string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError)
|
||||
GetOrCreateTrueUpReviewStatus(rctx request.CTX) (*model.TrueUpReviewStatus, *model.AppError)
|
||||
GetOutgoingWebhook(hookID string) (*model.OutgoingWebhook, *model.AppError)
|
||||
GetOutgoingWebhooksForChannelPageByUser(channelID string, userID string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError)
|
||||
GetOutgoingWebhooksForTeamPage(teamID string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError)
|
||||
@@ -852,7 +851,6 @@ type AppIface interface {
|
||||
GetThreadMembershipsForUser(userID, teamID string) ([]*model.ThreadMembership, error)
|
||||
GetThreadsForUser(userID, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError)
|
||||
GetTokenById(token string) (*model.Token, *model.AppError)
|
||||
GetTrueUpProfile() (map[string]any, error)
|
||||
GetUploadSession(c request.CTX, uploadId string) (*model.UploadSession, *model.AppError)
|
||||
GetUploadSessionsForUser(userID string) ([]*model.UploadSession, *model.AppError)
|
||||
GetUser(userID string) (*model.User, *model.AppError)
|
||||
|
||||
@@ -156,13 +156,3 @@ func (s *Server) RemoveLicenseListener(id string) {
|
||||
func (s *Server) GetSanitizedClientLicense() map[string]string {
|
||||
return s.platform.GetSanitizedClientLicense()
|
||||
}
|
||||
|
||||
// GenerateRenewalToken returns a renewal token that expires after duration expiration
|
||||
func (s *Server) GenerateRenewalToken(expiration time.Duration) (string, *model.AppError) {
|
||||
return s.platform.GenerateRenewalToken(expiration)
|
||||
}
|
||||
|
||||
// GenerateLicenseRenewalLink returns a link that points to the CWS where clients can renew license
|
||||
func (s *Server) GenerateLicenseRenewalLink() (string, string, *model.AppError) {
|
||||
return s.platform.GenerateLicenseRenewalLink()
|
||||
}
|
||||
|
||||
@@ -73,24 +73,6 @@ func TestGetSanitizedClientLicense(t *testing.T) {
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestGenerateRenewalToken(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("renewal token generated correctly", func(t *testing.T) {
|
||||
setLicense(th, nil)
|
||||
token, appErr := th.App.Srv().GenerateRenewalToken(JWTDefaultTokenExpiration)
|
||||
require.Nil(t, appErr)
|
||||
require.NotEmpty(t, token)
|
||||
})
|
||||
|
||||
t.Run("return error if there is no active license", func(t *testing.T) {
|
||||
th.App.Srv().SetLicense(nil)
|
||||
_, appErr := th.App.Srv().GenerateRenewalToken(JWTDefaultTokenExpiration)
|
||||
require.NotNil(t, appErr)
|
||||
})
|
||||
}
|
||||
|
||||
func setLicense(th *TestHelper, customer *model.Customer) {
|
||||
l1 := &model.License{}
|
||||
l1.Features = &model.Features{}
|
||||
|
||||
@@ -8005,28 +8005,6 @@ func (a *OpenTracingAppLayer) GetOrCreateDirectChannel(c request.CTX, userID str
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetOrCreateTrueUpReviewStatus(rctx request.CTX) (*model.TrueUpReviewStatus, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetOrCreateTrueUpReviewStatus")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetOrCreateTrueUpReviewStatus(rctx)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetOutgoingWebhook(hookID string) (*model.OutgoingWebhook, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetOutgoingWebhook")
|
||||
@@ -10617,28 +10595,6 @@ func (a *OpenTracingAppLayer) GetTotalUsersStats(viewRestrictions *model.ViewUse
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetTrueUpProfile() (map[string]any, error) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetTrueUpProfile")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := a.app.GetTrueUpProfile()
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetUploadSession(c request.CTX, uploadId string) (*model.UploadSession, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetUploadSession")
|
||||
|
||||
@@ -343,54 +343,6 @@ func (ps *PlatformService) RequestTrialLicense(trialRequest *model.TrialLicenseR
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateRenewalToken returns a renewal token that expires after duration expiration
|
||||
func (ps *PlatformService) GenerateRenewalToken(expiration time.Duration) (string, *model.AppError) {
|
||||
license := ps.License()
|
||||
if license == nil {
|
||||
return "", model.NewAppError("GenerateRenewalToken", "app.license.generate_renewal_token.no_license", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
if license.IsCloud() {
|
||||
return "", model.NewAppError("GenerateRenewalToken", "app.license.generate_renewal_token.bad_license", nil, "", http.StatusBadRequest)
|
||||
}
|
||||
|
||||
activeUsers, err := ps.Store.User().Count(model.UserCountOptions{})
|
||||
if err != nil {
|
||||
return "", model.NewAppError("GenerateRenewalToken", "app.license.generate_renewal_token.app_error",
|
||||
nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
expirationTime := time.Now().UTC().Add(expiration)
|
||||
claims := &JWTClaims{
|
||||
LicenseID: license.Id,
|
||||
ActiveUsers: activeUsers,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString([]byte(license.Customer.Email))
|
||||
if err != nil {
|
||||
return "", model.NewAppError("GenerateRenewalToken", "app.license.generate_renewal_token.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
// GenerateLicenseRenewalLink returns a link that points to the CWS where clients can renew license
|
||||
func (ps *PlatformService) GenerateLicenseRenewalLink() (string, string, *model.AppError) {
|
||||
renewalToken, err := ps.GenerateRenewalToken(JWTDefaultTokenExpiration)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return fmt.Sprintf("%s?token=%s", ps.getLicenseRenewalURL(), renewalToken), renewalToken, nil
|
||||
}
|
||||
|
||||
func (ps *PlatformService) getLicenseRenewalURL() string {
|
||||
return fmt.Sprintf("%s/subscribe/renew", *ps.Config().CloudSettings.CWSURL)
|
||||
}
|
||||
|
||||
func (ps *PlatformService) getRequestTrialURL() string {
|
||||
return fmt.Sprintf("%s/api/v1/trials", *ps.Config().CloudSettings.CWSURL)
|
||||
}
|
||||
|
||||
@@ -73,24 +73,6 @@ func TestGetSanitizedClientLicense(t *testing.T) {
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestGenerateRenewalToken(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("renewal token generated correctly", func(t *testing.T) {
|
||||
setLicense(th, nil)
|
||||
token, appErr := th.Service.GenerateRenewalToken(JWTDefaultTokenExpiration)
|
||||
require.Nil(t, appErr)
|
||||
require.NotEmpty(t, token)
|
||||
})
|
||||
|
||||
t.Run("return error if there is no active license", func(t *testing.T) {
|
||||
th.Service.SetLicense(nil)
|
||||
_, appErr := th.Service.GenerateRenewalToken(JWTDefaultTokenExpiration)
|
||||
require.NotNil(t, appErr)
|
||||
})
|
||||
}
|
||||
|
||||
func setLicense(th *TestHelper, customer *model.Customer) {
|
||||
l1 := &model.License{}
|
||||
l1.Features = &model.Features{}
|
||||
|
||||
@@ -1296,16 +1296,6 @@ func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, lice
|
||||
|
||||
daysToExpiration := license.DaysToExpiration()
|
||||
|
||||
ctaLink, tokenToBeUsedForRenew, appErr := s.GenerateLicenseRenewalLink()
|
||||
if appErr != nil {
|
||||
return model.NewAppError("s.sendLicenseUpForRenewalEmail", "api.server.license_up_for_renewal.error_generating_link", nil, "", http.StatusInternalServerError).Wrap(appErr)
|
||||
}
|
||||
|
||||
status, err := s.Cloud.GetLicenseSelfServeStatus("", tokenToBeUsedForRenew)
|
||||
if err != nil {
|
||||
return model.NewAppError("s.sendLicenseUpForRenewalEmail", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
// we want to at least have one email sent out to an admin
|
||||
countNotOks := 0
|
||||
|
||||
@@ -1315,13 +1305,10 @@ func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, lice
|
||||
name = user.Username
|
||||
}
|
||||
T := i18n.GetUserTranslations(user.Locale)
|
||||
ctaTitle := T("api.templates.license_up_for_renewal_subtitle_two")
|
||||
ctaText := T("api.templates.license_up_for_renewal_renew_now")
|
||||
if !status.IsRenewable {
|
||||
ctaTitle = ""
|
||||
ctaText = T("api.templates.license_up_for_renewal_contact_sales")
|
||||
ctaLink = "https://mattermost.com/contact-sales/"
|
||||
}
|
||||
|
||||
ctaTitle := ""
|
||||
ctaText := T("api.templates.license_up_for_renewal_contact_sales")
|
||||
ctaLink := "https://mattermost.com/contact-sales/"
|
||||
|
||||
if err := s.EmailService.SendLicenseUpForRenewalEmail(user.Email, name, user.Locale, *s.platform.Config().ServiceSettings.SiteURL, ctaTitle, ctaLink, ctaText, daysToExpiration); err != nil {
|
||||
mlog.Error("Error sending license up for renewal email to", mlog.String("user_email", user.Email), mlog.Err(err))
|
||||
@@ -1383,18 +1370,6 @@ func (s *Server) doLicenseExpirationCheck() {
|
||||
return
|
||||
}
|
||||
|
||||
ctaLink, tokenToBeUsedForRenew, appErr := s.GenerateLicenseRenewalLink()
|
||||
if appErr != nil {
|
||||
mlog.Debug(model.NewAppError("s.sendLicenseUpForRenewalEmail", "api.server.license_up_for_renewal.error_generating_link", nil, "", http.StatusInternalServerError).Wrap(appErr).Error())
|
||||
return
|
||||
}
|
||||
|
||||
status, err := s.Cloud.GetLicenseSelfServeStatus("", tokenToBeUsedForRenew)
|
||||
if err != nil {
|
||||
mlog.Debug(model.NewAppError("s.sendLicenseUpForRenewalEmail", "api.cloud.request_error", nil, "", http.StatusInternalServerError).Wrap(err).Error())
|
||||
return
|
||||
}
|
||||
|
||||
//send email to admin(s)
|
||||
for _, user := range users {
|
||||
user := user
|
||||
@@ -1404,11 +1379,8 @@ func (s *Server) doLicenseExpirationCheck() {
|
||||
}
|
||||
|
||||
T := i18n.GetUserTranslations(user.Locale)
|
||||
ctaText := T("api.templates.remove_expired_license.body.renew_button")
|
||||
if !status.IsRenewable {
|
||||
ctaText = T("api.templates.license_up_for_renewal_contact_sales")
|
||||
ctaLink = "https://mattermost.com/contact-sales/"
|
||||
}
|
||||
ctaText := T("api.templates.license_up_for_renewal_contact_sales")
|
||||
ctaLink := "https://mattermost.com/contact-sales/"
|
||||
|
||||
mlog.Debug("Sending license expired email.", mlog.String("user_email", user.Email))
|
||||
s.Go(func() {
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/public/shared/request"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/store"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/utils"
|
||||
"github.com/mattermost/mattermost/server/v8/platform/services/telemetry"
|
||||
)
|
||||
|
||||
func pluginActivated(pluginStates map[string]*model.PluginState, pluginId string) bool {
|
||||
state, ok := pluginStates[pluginId]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return state.Enable
|
||||
}
|
||||
|
||||
func (a *App) getMarketplacePlugins() ([]string, error) {
|
||||
ts := a.Srv().telemetryService
|
||||
config := a.Srv().Config()
|
||||
|
||||
marketplacePlugins, err := ts.GetAllMarketplacePlugins(model.PluginSettingsDefaultMarketplaceURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
activePlugins := []string{}
|
||||
for _, p := range marketplacePlugins {
|
||||
id := p.Manifest.Id
|
||||
if pluginActivated(config.PluginSettings.PluginStates, id) {
|
||||
activePlugins = append(activePlugins, id)
|
||||
}
|
||||
}
|
||||
|
||||
return activePlugins, nil
|
||||
}
|
||||
|
||||
func (a *App) getTrueUpProfile() (*model.TrueUpReviewProfile, error) {
|
||||
license := a.Channels().License()
|
||||
if license == nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.license_required", nil, "Could not get the total active users count", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Customer Info & Usage Analytics
|
||||
|
||||
// active registered users
|
||||
activatedUsers, err := a.Srv().Store().User().Count(model.UserCountOptions{})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.user_count_fail", nil, "Could not get the total activated users count", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
// daily active users
|
||||
dau, err := a.Srv().Store().User().AnalyticsActiveCount(DayMilliseconds, model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.user_count_fail", nil, "Could not get the total daily active users count", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// monthly active users
|
||||
mau, err := a.Srv().Store().User().AnalyticsActiveCount(MonthMilliseconds, model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.user_count_fail", nil, "Could not get the total monthly active users count", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
// Webhook, calls, boards, and playbook counts
|
||||
incomingWebhookCount, err := a.Srv().Store().Webhook().AnalyticsIncomingCount("")
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.webhook_in_count_fail", nil, "Could not get the total incoming webhook count", http.StatusInternalServerError)
|
||||
}
|
||||
outgoingWebhookCount, err := a.Srv().Store().Webhook().AnalyticsOutgoingCount("")
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.webhook_out_count_fail", nil, "Could not get the total outgoing webhook count", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
// Plugin Data
|
||||
trueUpReviewPlugins := model.TrueUpReviewPlugins{
|
||||
PluginNames: []string{},
|
||||
}
|
||||
|
||||
if plugins, err := a.getMarketplacePlugins(); err == nil {
|
||||
trueUpReviewPlugins.PluginNames = plugins
|
||||
trueUpReviewPlugins.TotalPlugins = len(plugins)
|
||||
}
|
||||
|
||||
// Authentication Features
|
||||
config := a.Config()
|
||||
mfaUsed := config.ServiceSettings.EnforceMultifactorAuthentication
|
||||
ldapUsed := config.LdapSettings.Enable
|
||||
samlUsed := config.SamlSettings.Enable
|
||||
openIdUsed := config.OpenIdSettings.Enable
|
||||
guestAccessAllowed := config.GuestAccountsSettings.Enable
|
||||
|
||||
authFeatures := map[string]*bool{
|
||||
model.TrueUpReviewAuthFeaturesMfa: mfaUsed,
|
||||
model.TrueUpReviewAuthFeaturesADLdap: ldapUsed,
|
||||
model.TrueUpReviewAuthFeaturesSaml: samlUsed,
|
||||
model.TrueUpReviewAuthFeatureOpenId: openIdUsed,
|
||||
model.TrueUpReviewAuthFeatureGuestAccess: guestAccessAllowed,
|
||||
}
|
||||
|
||||
authFeatureList := []string{}
|
||||
for feature, used := range authFeatures {
|
||||
if used != nil && *used {
|
||||
authFeatureList = append(authFeatureList, feature)
|
||||
}
|
||||
}
|
||||
|
||||
reviewProfile := model.TrueUpReviewProfile{
|
||||
ServerId: a.TelemetryId(),
|
||||
ServerVersion: model.CurrentVersion,
|
||||
ServerInstallationType: os.Getenv(telemetry.EnvVarInstallType),
|
||||
LicenseId: license.Id,
|
||||
LicensedSeats: *license.Features.Users,
|
||||
LicensePlan: license.SkuName,
|
||||
CustomerName: license.Customer.Name,
|
||||
ActivatedUsers: activatedUsers,
|
||||
DailyActiveUsers: dau,
|
||||
MonthlyActiveUsers: mau,
|
||||
TotalIncomingWebhooks: incomingWebhookCount,
|
||||
TotalOutgoingWebhooks: outgoingWebhookCount,
|
||||
Plugins: trueUpReviewPlugins,
|
||||
AuthenticationFeatures: authFeatureList,
|
||||
}
|
||||
|
||||
return &reviewProfile, nil
|
||||
}
|
||||
|
||||
func (a *App) GetTrueUpProfile() (map[string]any, error) {
|
||||
profile, err := a.getTrueUpProfile()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
profileJson, err := json.Marshal(profile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
telemetryProperties := map[string]any{}
|
||||
|
||||
json.Unmarshal(profileJson, &telemetryProperties)
|
||||
delete(telemetryProperties, "plugins")
|
||||
plugins := profile.Plugins.ToMap()
|
||||
for key, pluginValue := range plugins {
|
||||
telemetryProperties[key] = pluginValue
|
||||
}
|
||||
|
||||
delete(telemetryProperties, "authentication_features")
|
||||
telemetryProperties["authentication_features"] = strings.Join(profile.AuthenticationFeatures, ",")
|
||||
|
||||
return telemetryProperties, nil
|
||||
}
|
||||
|
||||
func (a *App) GetOrCreateTrueUpReviewStatus(rctx request.CTX) (*model.TrueUpReviewStatus, *model.AppError) {
|
||||
nextDueDate := utils.GetNextTrueUpReviewDueDate(time.Now())
|
||||
status, err := a.Srv().Store().TrueUpReview().GetTrueUpReviewStatus(nextDueDate.UnixMilli())
|
||||
if err != nil {
|
||||
var nfErr *store.ErrNotFound
|
||||
switch {
|
||||
case errors.As(err, &nfErr):
|
||||
rctx.Logger().Warn("Could not find true up review status")
|
||||
default:
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.get_status_error", nil, "Could not get true up status records", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
status, err = a.Srv().Store().TrueUpReview().CreateTrueUpReviewStatusRecord(&model.TrueUpReviewStatus{DueDate: nextDueDate.UnixMilli(), Completed: false})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("requestTrueUpReview", "api.license.true_up_review.create_error", nil, "Could not create true up status record", http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
return status, nil
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost/server/public/model"
|
||||
"github.com/mattermost/mattermost/server/v8/channels/store/storetest/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGetTrueUpProfile(t *testing.T) {
|
||||
th := SetupWithStoreMock(t)
|
||||
defer th.TearDown()
|
||||
|
||||
mockStore := th.App.Srv().Store().(*mocks.Store)
|
||||
mockUserStore := mocks.UserStore{}
|
||||
//Activated userss set to 10
|
||||
mockUserStore.On("Count", mock.Anything).Return(int64(10), nil)
|
||||
//Mau set to 5
|
||||
mockUserStore.On("AnalyticsActiveCount", int64(MonthMilliseconds), model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false}).Return(int64(5), nil)
|
||||
//dau set to 2
|
||||
mockUserStore.On("AnalyticsActiveCount", int64(DayMilliseconds), model.UserCountOptions{IncludeBotAccounts: false, IncludeDeleted: false}).Return(int64(2), nil)
|
||||
mockStore.On("User").Return(&mockUserStore)
|
||||
|
||||
mockWebhookStore := mocks.WebhookStore{}
|
||||
mockWebhookStore.On("AnalyticsIncomingCount", mock.Anything).Return(int64(1), nil)
|
||||
mockWebhookStore.On("AnalyticsOutgoingCount", mock.Anything).Return(int64(1), nil)
|
||||
mockStore.On("Webhook").Return(&mockWebhookStore)
|
||||
|
||||
t.Run("missing license", func(t *testing.T) {
|
||||
_, err := th.App.GetTrueUpProfile()
|
||||
require.Error(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), "True up review requires a license"))
|
||||
})
|
||||
|
||||
t.Run("happy path - returns correct mau and activated users", func(t *testing.T) {
|
||||
th.App.Srv().SetLicense(model.NewTestLicenseSKU(model.LicenseShortSkuProfessional))
|
||||
|
||||
profile, err := th.App.GetTrueUpProfile()
|
||||
assert.NoError(t, err, "Unexpected error")
|
||||
|
||||
require.NotNil(t, profile)
|
||||
assert.Equal(t, float64(5), profile["monthly_active_users"])
|
||||
assert.Equal(t, float64(2), profile["daily_active_users"])
|
||||
assert.Equal(t, float64(10), profile["total_activated_users"])
|
||||
assert.Equal(t, float64(1), profile["incoming_webhooks_count"])
|
||||
assert.Equal(t, float64(1), profile["outgoing_webhooks_count"])
|
||||
})
|
||||
}
|
||||
Ссылка в новой задаче
Block a user