[MM-31674] app/product_notices: implement notices for ext. dependencies (#16871)
* app/product_notices: implement notices for ext. dependencies * remove a log line Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
31a80a5351
Коммит
013c495a97
@@ -32,6 +32,8 @@ var noticesCache = utils.RequestCache{}
|
||||
var cachedPostCount int64
|
||||
var cachedUserCount int64
|
||||
|
||||
var cachedDBMSVersion string
|
||||
|
||||
// previously fetched notices
|
||||
var cachedNotices model.ProductNotices
|
||||
var rcStripRegexp = regexp.MustCompile(`(.*?)(-rc\d+)(.*?)`)
|
||||
@@ -52,7 +54,8 @@ func cleanupVersion(originalVersion string) string {
|
||||
|
||||
func noticeMatchesConditions(config *model.Config, preferences store.PreferenceStore, userID string,
|
||||
client model.NoticeClientType, clientVersion string, postCount int64, userCount int64, isSystemAdmin bool,
|
||||
isTeamAdmin bool, isCloud bool, sku string, notice *model.ProductNotice) (bool, error) {
|
||||
isTeamAdmin bool, isCloud bool, sku, dbName, dbVer string,
|
||||
notice *model.ProductNotice) (bool, error) {
|
||||
cnd := notice.Conditions
|
||||
|
||||
// check client type
|
||||
@@ -144,6 +147,27 @@ func noticeMatchesConditions(config *model.Config, preferences store.PreferenceS
|
||||
}
|
||||
}
|
||||
|
||||
if cnd.DeprecatingDependency != nil {
|
||||
extDepVersion, err := semver.NewVersion(cnd.DeprecatingDependency.MinimumVersion)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "Cannot parse external dependency version %s", cnd.DeprecatingDependency.MinimumVersion)
|
||||
}
|
||||
|
||||
switch cnd.DeprecatingDependency.Name {
|
||||
case model.DATABASE_DRIVER_MYSQL, model.DATABASE_DRIVER_POSTGRES:
|
||||
if dbName != cnd.DeprecatingDependency.Name {
|
||||
return false, nil
|
||||
}
|
||||
serverDBMSVersion, err := semver.NewVersion(dbVer)
|
||||
if err != nil {
|
||||
return false, errors.Wrapf(err, "Cannot parse DBMS version %s", dbVer)
|
||||
}
|
||||
return extDepVersion.GreaterThan(serverDBMSVersion), nil
|
||||
default:
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// check if our server config matches the notice
|
||||
for k, v := range cnd.ServerConfig {
|
||||
if !validateConfigEntry(config, k, v) {
|
||||
@@ -225,6 +249,7 @@ func (a *App) GetProductNotices(userID, teamID string, client model.NoticeClient
|
||||
|
||||
sku := a.Srv().ClientLicense()["SkuShortName"]
|
||||
isCloud := a.Srv().License() != nil && *a.Srv().License().Features.Cloud
|
||||
dbName := *a.Srv().Config().SqlSettings.DriverName
|
||||
|
||||
filteredNotices := make([]model.NoticeMessage, 0)
|
||||
|
||||
@@ -262,6 +287,8 @@ func (a *App) GetProductNotices(userID, teamID string, client model.NoticeClient
|
||||
isTeamAdmin,
|
||||
isCloud,
|
||||
sku,
|
||||
dbName,
|
||||
cachedDBMSVersion,
|
||||
&cachedNotices[noticeIndex])
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("GetProductNotices", "api.system.update_notices.validating_failed", nil, err.Error(), http.StatusBadRequest)
|
||||
@@ -316,6 +343,13 @@ func (a *App) UpdateProductNotices() *model.AppError {
|
||||
mlog.Warn("Failed to fetch user count", mlog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
cachedDBMSVersion, err = a.Srv().Store.GetDbVersion(false)
|
||||
if err != nil {
|
||||
mlog.Warn("Failed to get DBMS version", mlog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
cachedDBMSVersion = strings.Split(cachedDBMSVersion, " ")[0] // get rid of trailing strings attached to the version
|
||||
|
||||
data, err := utils.GetUrlWithCache(url, ¬icesCache, skip)
|
||||
if err != nil {
|
||||
return model.NewAppError("UpdateProductNotices", "api.system.update_notices.fetch_failed", nil, err.Error(), http.StatusBadRequest)
|
||||
|
||||
@@ -60,6 +60,8 @@ func TestNoticeValidation(t *testing.T) {
|
||||
systemAdmin bool
|
||||
serverVersion string
|
||||
notice *model.ProductNotice
|
||||
dbmsName string
|
||||
dbmsVer string
|
||||
}
|
||||
messages := map[string]model.NoticeMessageInternal{
|
||||
"en": {
|
||||
@@ -538,6 +540,76 @@ func TestNoticeValidation(t *testing.T) {
|
||||
wantErr: false,
|
||||
wantOk: true,
|
||||
},
|
||||
{
|
||||
name: "notice with depreacting an external dependency",
|
||||
args: args{
|
||||
dbmsName: "mysql",
|
||||
dbmsVer: "5.6",
|
||||
notice: &model.ProductNotice{
|
||||
Conditions: model.Conditions{
|
||||
DeprecatingDependency: &model.ExternalDependency{
|
||||
Name: "mysql",
|
||||
MinimumVersion: "5.7",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
wantOk: true,
|
||||
},
|
||||
{
|
||||
name: "notice with depreacting an external dependency, on a future version",
|
||||
args: args{
|
||||
dbmsName: "mysql",
|
||||
dbmsVer: "5.6",
|
||||
serverVersion: "5.32",
|
||||
notice: &model.ProductNotice{
|
||||
Conditions: model.Conditions{
|
||||
ServerVersion: []string{">=v5.33"},
|
||||
DeprecatingDependency: &model.ExternalDependency{
|
||||
Name: "mysql",
|
||||
MinimumVersion: "5.7",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "notice on a deprecating dependency, server is all good",
|
||||
args: args{
|
||||
dbmsName: "postgres",
|
||||
dbmsVer: "10",
|
||||
notice: &model.ProductNotice{
|
||||
Conditions: model.Conditions{
|
||||
DeprecatingDependency: &model.ExternalDependency{
|
||||
Name: "postgres",
|
||||
MinimumVersion: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
wantOk: false,
|
||||
},
|
||||
{
|
||||
name: "notice on a deprecating dependency, server has different dbms",
|
||||
args: args{
|
||||
dbmsName: "mysql",
|
||||
dbmsVer: "5.7",
|
||||
notice: &model.ProductNotice{
|
||||
Conditions: model.Conditions{
|
||||
DeprecatingDependency: &model.ExternalDependency{
|
||||
Name: "postgres",
|
||||
MinimumVersion: "10",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
wantOk: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -561,6 +633,8 @@ func TestNoticeValidation(t *testing.T) {
|
||||
tt.args.teamAdmin,
|
||||
tt.args.cloud,
|
||||
tt.args.sku,
|
||||
tt.args.dbmsName,
|
||||
tt.args.dbmsVer,
|
||||
tt.args.notice,
|
||||
); (err != nil) != tt.wantErr {
|
||||
t.Errorf("noticeMatchesConditions() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
@@ -40,18 +40,19 @@ func (n *ProductNotice) TeamAdminOnly() bool {
|
||||
}
|
||||
|
||||
type Conditions struct {
|
||||
Audience *NoticeAudience `json:"audience,omitempty"`
|
||||
ClientType *NoticeClientType `json:"clientType,omitempty"` // Only show the notice on specific clients. Defaults to 'all'
|
||||
DesktopVersion []string `json:"desktopVersion,omitempty"` // What desktop client versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
DisplayDate *string `json:"displayDate,omitempty"` // When to display the notice.; Examples:; "2020-03-01T00:00:00Z" - show on specified date; ">= 2020-03-01T00:00:00Z" - show after specified date; "< 2020-03-01T00:00:00Z" - show before the specified date; "> 2020-03-01T00:00:00Z <= 2020-04-01T00:00:00Z" - show only between the specified dates
|
||||
InstanceType *NoticeInstanceType `json:"instanceType,omitempty"`
|
||||
MobileVersion []string `json:"mobileVersion,omitempty"` // What mobile client versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
NumberOfPosts *int64 `json:"numberOfPosts,omitempty"` // Only show the notice when server has more than specified number of posts
|
||||
NumberOfUsers *int64 `json:"numberOfUsers,omitempty"` // Only show the notice when server has more than specified number of users
|
||||
ServerConfig map[string]interface{} `json:"serverConfig,omitempty"` // Map of mattermost server config paths and their values. Notice will be displayed only if; the values match the target server config; Example: serverConfig: { "PluginSettings.Enable": true, "GuestAccountsSettings.Enable":; false }
|
||||
ServerVersion []string `json:"serverVersion,omitempty"` // What server versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
Sku *NoticeSKU `json:"sku,omitempty"`
|
||||
UserConfig map[string]interface{} `json:"userConfig,omitempty"` // Map of user's settings and their values. Notice will be displayed only if the values; match the viewing users' config; Example: userConfig: { "new_sidebar.disabled": true }
|
||||
Audience *NoticeAudience `json:"audience,omitempty"`
|
||||
ClientType *NoticeClientType `json:"clientType,omitempty"` // Only show the notice on specific clients. Defaults to 'all'
|
||||
DesktopVersion []string `json:"desktopVersion,omitempty"` // What desktop client versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
DisplayDate *string `json:"displayDate,omitempty"` // When to display the notice.; Examples:; "2020-03-01T00:00:00Z" - show on specified date; ">= 2020-03-01T00:00:00Z" - show after specified date; "< 2020-03-01T00:00:00Z" - show before the specified date; "> 2020-03-01T00:00:00Z <= 2020-04-01T00:00:00Z" - show only between the specified dates
|
||||
InstanceType *NoticeInstanceType `json:"instanceType,omitempty"`
|
||||
MobileVersion []string `json:"mobileVersion,omitempty"` // What mobile client versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
NumberOfPosts *int64 `json:"numberOfPosts,omitempty"` // Only show the notice when server has more than specified number of posts
|
||||
NumberOfUsers *int64 `json:"numberOfUsers,omitempty"` // Only show the notice when server has more than specified number of users
|
||||
ServerConfig map[string]interface{} `json:"serverConfig,omitempty"` // Map of mattermost server config paths and their values. Notice will be displayed only if; the values match the target server config; Example: serverConfig: { "PluginSettings.Enable": true, "GuestAccountsSettings.Enable":; false }
|
||||
ServerVersion []string `json:"serverVersion,omitempty"` // What server versions does this notice apply to.; Format: semver ranges (https://devhints.io/semver); Example: [">=1.2.3 < ~2.4.x"]; Example: ["<v5.19", "v5.20-v5.22"]
|
||||
Sku *NoticeSKU `json:"sku,omitempty"`
|
||||
UserConfig map[string]interface{} `json:"userConfig,omitempty"` // Map of user's settings and their values. Notice will be displayed only if the values; match the viewing users' config; Example: userConfig: { "new_sidebar.disabled": true }
|
||||
DeprecatingDependency *ExternalDependency `json:"deprecating_dependency,omitempty"` // External dependency which is going to be deprecated
|
||||
}
|
||||
|
||||
type NoticeMessageInternal struct {
|
||||
@@ -212,3 +213,8 @@ type ProductNoticeViewState struct {
|
||||
Viewed int32
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type ExternalDependency struct {
|
||||
Name string `json:"name"`
|
||||
MinimumVersion string `json:"minimum_version"`
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user