From bffcccf99de8a8f3c68cff9e39d2847f0996b67b Mon Sep 17 00:00:00 2001 From: Harshil Sharma Date: Wed, 10 Oct 2018 00:55:47 +0000 Subject: Refactored to rename "service terms" to "terms of service" (#9581) * #124 renamed identififers from service terms to terms of service * #124 renamed identififers from service terms to terms of service * 124 renamed ServiceTerms model to TermsOfService * 124 Renamed EnableCustomServiceTerms feature flag to EnableCustomTermsOfService * 124 Renamed EnableCustomServiceTerms feature flag to EnableCustomTermsOfService * #124 fixed formatting * #124 fixed formatting * #132 renamed table ServiceTerms to TermsOfService * #124 renamed some missed files from 'service_terms' to 'terms_of_service' * #124 removed fixed TODOs * drop migrate of ServiceTerms table, since backporting * s/ServiceTerms/TermsOfService/ in tests * s/AcceptedServiceTermsId/AcceptedTermsOfServiceId/ Change the model attribute, even though the column name will eventually be removed. * s/accepted_service_terms_id/accepted_terms_of_service_id/ to match redux * s/serviceTerms/termsOfService * rename column too, and add max size constraint * s/EnableCustomServiceTerms/EnableCustomTermsOfService --- api4/api.go | 6 +- api4/service_terms.go | 64 --------- api4/service_terms_test.go | 53 -------- api4/terms_of_service.go | 64 +++++++++ api4/terms_of_service_test.go | 53 ++++++++ api4/user.go | 12 +- api4/user_test.go | 12 +- app/config.go | 8 +- app/diagnostics.go | 2 +- app/service_terms.go | 45 ------- app/terms_of_service.go | 45 +++++++ app/user.go | 6 +- app/user_test.go | 14 +- i18n/en.json | 22 ++-- model/client4.go | 22 ++-- model/config.go | 18 +-- model/service_terms.go | 70 ---------- model/service_terms_test.go | 62 --------- model/terms_of_service.go | 70 ++++++++++ model/terms_of_service_test.go | 62 +++++++++ model/user.go | 54 ++++---- store/layered_store.go | 4 +- store/sqlstore/service_terms_store.go | 143 --------------------- store/sqlstore/service_terms_store_test.go | 10 -- store/sqlstore/store.go | 2 +- store/sqlstore/supplier.go | 10 +- store/sqlstore/terms_of_service_store.go | 143 +++++++++++++++++++++ store/sqlstore/terms_of_service_store_test.go | 10 ++ store/sqlstore/upgrade.go | 2 +- store/sqlstore/user_store.go | 1 + store/store.go | 6 +- store/storetest/mocks/LayeredStoreDatabaseLayer.go | 32 ++--- store/storetest/mocks/ServiceTermsStore.go | 62 --------- store/storetest/mocks/SqlStore.go | 32 ++--- store/storetest/mocks/Store.go | 32 ++--- store/storetest/mocks/TermsOfServiceStore.go | 62 +++++++++ store/storetest/service_terms_store.go | 82 ------------ store/storetest/store.go | 4 +- store/storetest/terms_of_service_store.go | 82 ++++++++++++ utils/config.go | 12 +- 40 files changed, 748 insertions(+), 747 deletions(-) delete mode 100644 api4/service_terms.go delete mode 100644 api4/service_terms_test.go create mode 100644 api4/terms_of_service.go create mode 100644 api4/terms_of_service_test.go delete mode 100644 app/service_terms.go create mode 100644 app/terms_of_service.go delete mode 100644 model/service_terms.go delete mode 100644 model/service_terms_test.go create mode 100644 model/terms_of_service.go create mode 100644 model/terms_of_service_test.go delete mode 100644 store/sqlstore/service_terms_store.go delete mode 100644 store/sqlstore/service_terms_store_test.go create mode 100644 store/sqlstore/terms_of_service_store.go create mode 100644 store/sqlstore/terms_of_service_store_test.go delete mode 100644 store/storetest/mocks/ServiceTermsStore.go create mode 100644 store/storetest/mocks/TermsOfServiceStore.go delete mode 100644 store/storetest/service_terms_store.go create mode 100644 store/storetest/terms_of_service_store.go diff --git a/api4/api.go b/api4/api.go index ed3dda054..b324959e9 100644 --- a/api4/api.go +++ b/api4/api.go @@ -108,7 +108,7 @@ type Routes struct { Webrtc *mux.Router // 'api/v4/webrtc' - ServiceTerms *mux.Router // 'api/v4/service_terms + TermsOfService *mux.Router // 'api/v4/terms_of_service } type API struct { @@ -205,7 +205,7 @@ func Init(a *app.App, root *mux.Router) *API { api.BaseRoutes.Image = api.BaseRoutes.ApiRoot.PathPrefix("/image").Subrouter() - api.BaseRoutes.ServiceTerms = api.BaseRoutes.ApiRoot.PathPrefix("/terms_of_service").Subrouter() + api.BaseRoutes.TermsOfService = api.BaseRoutes.ApiRoot.PathPrefix("/terms_of_service").Subrouter() api.InitUser() api.InitTeam() @@ -235,7 +235,7 @@ func Init(a *app.App, root *mux.Router) *API { api.InitRole() api.InitScheme() api.InitImage() - api.InitServiceTerms() + api.InitTermsOfService() root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) diff --git a/api4/service_terms.go b/api4/service_terms.go deleted file mode 100644 index ff953102d..000000000 --- a/api4/service_terms.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package api4 - -import ( - "github.com/mattermost/mattermost-server/app" - "github.com/mattermost/mattermost-server/model" - "net/http" -) - -func (api *API) InitServiceTerms() { - api.BaseRoutes.ServiceTerms.Handle("", api.ApiSessionRequired(getServiceTerms)).Methods("GET") - api.BaseRoutes.ServiceTerms.Handle("", api.ApiSessionRequired(createServiceTerms)).Methods("POST") -} - -func getServiceTerms(c *Context, w http.ResponseWriter, r *http.Request) { - serviceTerms, err := c.App.GetLatestServiceTerms() - if err != nil { - c.Err = err - return - } - - w.Write([]byte(serviceTerms.ToJson())) -} - -func createServiceTerms(c *Context, w http.ResponseWriter, r *http.Request) { - if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { - c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) - return - } - - if license := c.App.License(); license == nil || !*license.Features.CustomTermsOfService { - c.Err = model.NewAppError("createServiceTerms", "api.create_service_terms.custom_service_terms_disabled.app_error", nil, "", http.StatusBadRequest) - return - } - - props := model.MapFromJson(r.Body) - text := props["text"] - userId := c.Session.UserId - - if text == "" { - c.Err = model.NewAppError("Config.IsValid", "api.create_service_terms.empty_text.app_error", nil, "", http.StatusBadRequest) - return - } - - oldServiceTerms, err := c.App.GetLatestServiceTerms() - if err != nil && err.Id != app.ERROR_SERVICE_TERMS_NO_ROWS_FOUND { - c.Err = err - return - } - - if oldServiceTerms == nil || oldServiceTerms.Text != text { - serviceTerms, err := c.App.CreateServiceTerms(text, userId) - if err != nil { - c.Err = err - return - } - - w.Write([]byte(serviceTerms.ToJson())) - } else { - w.Write([]byte(oldServiceTerms.ToJson())) - } -} diff --git a/api4/service_terms_test.go b/api4/service_terms_test.go deleted file mode 100644 index 607c104a6..000000000 --- a/api4/service_terms_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package api4 - -import ( - "github.com/mattermost/mattermost-server/model" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestGetServiceTerms(t *testing.T) { - th := Setup().InitBasic() - defer th.TearDown() - Client := th.Client - - _, err := th.App.CreateServiceTerms("abc", th.BasicUser.Id) - if err != nil { - t.Fatal(err) - } - - serviceTerms, resp := Client.GetServiceTerms("") - CheckNoError(t, resp) - - assert.NotNil(t, serviceTerms) - assert.Equal(t, "abc", serviceTerms.Text) - assert.NotEmpty(t, serviceTerms.Id) - assert.NotEmpty(t, serviceTerms.CreateAt) -} - -func TestCreateServiceTerms(t *testing.T) { - th := Setup().InitBasic() - defer th.TearDown() - Client := th.Client - - _, resp := Client.CreateServiceTerms("service terms new", th.BasicUser.Id) - CheckErrorMessage(t, resp, "api.context.permissions.app_error") -} - -func TestCreateServiceTermsAdminUser(t *testing.T) { - th := Setup().InitSystemAdmin() - defer th.TearDown() - Client := th.SystemAdminClient - - serviceTerms, resp := Client.CreateServiceTerms("service terms new", th.SystemAdminUser.Id) - CheckErrorMessage(t, resp, "api.create_service_terms.custom_service_terms_disabled.app_error") - - th.App.SetLicense(model.NewTestLicense("EnableCustomServiceTerms")) - - serviceTerms, resp = Client.CreateServiceTerms("service terms new_2", th.SystemAdminUser.Id) - CheckNoError(t, resp) - assert.NotEmpty(t, serviceTerms.Id) - assert.NotEmpty(t, serviceTerms.CreateAt) - assert.Equal(t, "service terms new_2", serviceTerms.Text) - assert.Equal(t, th.SystemAdminUser.Id, serviceTerms.UserId) -} diff --git a/api4/terms_of_service.go b/api4/terms_of_service.go new file mode 100644 index 000000000..de3f7499b --- /dev/null +++ b/api4/terms_of_service.go @@ -0,0 +1,64 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package api4 + +import ( + "github.com/mattermost/mattermost-server/app" + "github.com/mattermost/mattermost-server/model" + "net/http" +) + +func (api *API) InitTermsOfService() { + api.BaseRoutes.TermsOfService.Handle("", api.ApiSessionRequired(getTermsOfService)).Methods("GET") + api.BaseRoutes.TermsOfService.Handle("", api.ApiSessionRequired(createTermsOfService)).Methods("POST") +} + +func getTermsOfService(c *Context, w http.ResponseWriter, r *http.Request) { + termsOfService, err := c.App.GetLatestTermsOfService() + if err != nil { + c.Err = err + return + } + + w.Write([]byte(termsOfService.ToJson())) +} + +func createTermsOfService(c *Context, w http.ResponseWriter, r *http.Request) { + if !c.App.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) { + c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM) + return + } + + if license := c.App.License(); license == nil || !*license.Features.CustomTermsOfService { + c.Err = model.NewAppError("createTermsOfService", "api.create_terms_of_service.custom_terms_of_service_disabled.app_error", nil, "", http.StatusBadRequest) + return + } + + props := model.MapFromJson(r.Body) + text := props["text"] + userId := c.Session.UserId + + if text == "" { + c.Err = model.NewAppError("Config.IsValid", "api.create_terms_of_service.empty_text.app_error", nil, "", http.StatusBadRequest) + return + } + + oldTermsOfService, err := c.App.GetLatestTermsOfService() + if err != nil && err.Id != app.ERROR_TERMS_OF_SERVICE_NO_ROWS_FOUND { + c.Err = err + return + } + + if oldTermsOfService == nil || oldTermsOfService.Text != text { + termsOfService, err := c.App.CreateTermsOfService(text, userId) + if err != nil { + c.Err = err + return + } + + w.Write([]byte(termsOfService.ToJson())) + } else { + w.Write([]byte(oldTermsOfService.ToJson())) + } +} diff --git a/api4/terms_of_service_test.go b/api4/terms_of_service_test.go new file mode 100644 index 000000000..c1709df2b --- /dev/null +++ b/api4/terms_of_service_test.go @@ -0,0 +1,53 @@ +package api4 + +import ( + "github.com/mattermost/mattermost-server/model" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestGetTermsOfService(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + Client := th.Client + + _, err := th.App.CreateTermsOfService("abc", th.BasicUser.Id) + if err != nil { + t.Fatal(err) + } + + termsOfService, resp := Client.GetTermsOfService("") + CheckNoError(t, resp) + + assert.NotNil(t, termsOfService) + assert.Equal(t, "abc", termsOfService.Text) + assert.NotEmpty(t, termsOfService.Id) + assert.NotEmpty(t, termsOfService.CreateAt) +} + +func TestCreateTermsOfService(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + Client := th.Client + + _, resp := Client.CreateTermsOfService("terms of service new", th.BasicUser.Id) + CheckErrorMessage(t, resp, "api.context.permissions.app_error") +} + +func TestCreateTermsOfServiceAdminUser(t *testing.T) { + th := Setup().InitSystemAdmin() + defer th.TearDown() + Client := th.SystemAdminClient + + termsOfService, resp := Client.CreateTermsOfService("terms of service new", th.SystemAdminUser.Id) + CheckErrorMessage(t, resp, "api.create_terms_of_service.custom_terms_of_service_disabled.app_error") + + th.App.SetLicense(model.NewTestLicense("EnableCustomTermsOfService")) + + termsOfService, resp = Client.CreateTermsOfService("terms of service new_2", th.SystemAdminUser.Id) + CheckNoError(t, resp) + assert.NotEmpty(t, termsOfService.Id) + assert.NotEmpty(t, termsOfService.CreateAt) + assert.Equal(t, "terms of service new_2", termsOfService.Text) + assert.Equal(t, th.SystemAdminUser.Id, termsOfService.UserId) +} diff --git a/api4/user.go b/api4/user.go index 404457285..c97e90e89 100644 --- a/api4/user.go +++ b/api4/user.go @@ -41,7 +41,7 @@ func (api *API) InitUser() { api.BaseRoutes.Users.Handle("/password/reset/send", api.ApiHandler(sendPasswordReset)).Methods("POST") api.BaseRoutes.Users.Handle("/email/verify", api.ApiHandler(verifyUserEmail)).Methods("POST") api.BaseRoutes.Users.Handle("/email/verify/send", api.ApiHandler(sendVerificationEmail)).Methods("POST") - api.BaseRoutes.User.Handle("/terms_of_service", api.ApiSessionRequired(registerServiceTermsAction)).Methods("POST") + api.BaseRoutes.User.Handle("/terms_of_service", api.ApiSessionRequired(registerTermsOfServiceAction)).Methods("POST") api.BaseRoutes.User.Handle("/auth", api.ApiSessionRequiredTrustRequester(updateUserAuth)).Methods("PUT") @@ -1615,23 +1615,23 @@ func enableUserAccessToken(c *Context, w http.ResponseWriter, r *http.Request) { ReturnStatusOK(w) } -func registerServiceTermsAction(c *Context, w http.ResponseWriter, r *http.Request) { +func registerTermsOfServiceAction(c *Context, w http.ResponseWriter, r *http.Request) { props := model.StringInterfaceFromJson(r.Body) userId := c.Session.UserId - serviceTermsId := props["serviceTermsId"].(string) + termsOfServiceId := props["termsOfServiceId"].(string) accepted := props["accepted"].(bool) - if _, err := c.App.GetServiceTerms(serviceTermsId); err != nil { + if _, err := c.App.GetTermsOfService(termsOfServiceId); err != nil { c.Err = err return } - if err := c.App.RecordUserServiceTermsAction(userId, serviceTermsId, accepted); err != nil { + if err := c.App.RecordUserTermsOfServiceAction(userId, termsOfServiceId, accepted); err != nil { c.Err = err return } - c.LogAudit("ServiceTermsId=" + serviceTermsId + ", accepted=" + strconv.FormatBool(accepted)) + c.LogAudit("TermsOfServiceId=" + termsOfServiceId + ", accepted=" + strconv.FormatBool(accepted)) ReturnStatusOK(w) } diff --git a/api4/user_test.go b/api4/user_test.go index 405102373..b99011aeb 100644 --- a/api4/user_test.go +++ b/api4/user_test.go @@ -3069,20 +3069,20 @@ func TestGetUsersByStatus(t *testing.T) { }) } -func TestRegisterServiceTermsAction(t *testing.T) { +func TestRegisterTermsOfServiceAction(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() Client := th.Client - success, resp := Client.RegisterServiceTermsAction(th.BasicUser.Id, "st_1", true) - CheckErrorMessage(t, resp, "store.sql_service_terms_store.get.no_rows.app_error") + success, resp := Client.RegisteTermsOfServiceAction(th.BasicUser.Id, "st_1", true) + CheckErrorMessage(t, resp, "store.sql_terms_of_service_store.get.no_rows.app_error") - serviceTerms, err := th.App.CreateServiceTerms("service terms", th.BasicUser.Id) + termsOfService, err := th.App.CreateTermsOfService("terms of service", th.BasicUser.Id) if err != nil { t.Fatal(err) } - success, resp = Client.RegisterServiceTermsAction(th.BasicUser.Id, serviceTerms.Id, true) + success, resp = Client.RegisteTermsOfServiceAction(th.BasicUser.Id, termsOfService.Id, true) CheckNoError(t, resp) assert.True(t, *success) @@ -3091,5 +3091,5 @@ func TestRegisterServiceTermsAction(t *testing.T) { t.Fatal(err) } - assert.Equal(t, user.AcceptedServiceTermsId, serviceTerms.Id) + assert.Equal(t, user.AcceptedTermsOfServiceId, termsOfService.Id) } diff --git a/app/config.go b/app/config.go index cb74bd1b3..34f4dc751 100644 --- a/app/config.go +++ b/app/config.go @@ -24,7 +24,7 @@ import ( ) const ( - ERROR_SERVICE_TERMS_NO_ROWS_FOUND = "store.sql_service_terms_store.get.no_rows.app_error" + ERROR_TERMS_OF_SERVICE_NO_ROWS_FOUND = "store.sql_terms_of_service_store.get.no_rows.app_error" ) func (a *App) Config() *model.Config { @@ -246,12 +246,12 @@ func (a *App) AsymmetricSigningKey() *ecdsa.PrivateKey { func (a *App) regenerateClientConfig() { a.clientConfig = utils.GenerateClientConfig(a.Config(), a.DiagnosticId(), a.License()) - if a.clientConfig["EnableCustomServiceTerms"] == "true" { - serviceTerms, err := a.GetLatestServiceTerms() + if a.clientConfig["EnableCustomTermsOfService"] == "true" { + termsOfService, err := a.GetLatestTermsOfService() if err != nil { mlog.Err(err) } else { - a.clientConfig["CustomServiceTermsId"] = serviceTerms.Id + a.clientConfig["CustomTermsOfServiceId"] = termsOfService.Id } } diff --git a/app/diagnostics.go b/app/diagnostics.go index e8b3ebe4a..9f4d0d200 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -417,7 +417,7 @@ func (a *App) trackConfig() { "isdefault_help_link": isDefault(*cfg.SupportSettings.HelpLink, model.SUPPORT_SETTINGS_DEFAULT_HELP_LINK), "isdefault_report_a_problem_link": isDefault(*cfg.SupportSettings.ReportAProblemLink, model.SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK), "isdefault_support_email": isDefault(*cfg.SupportSettings.SupportEmail, model.SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL), - "custom_service_terms_enabled": *cfg.SupportSettings.CustomServiceTermsEnabled, + "custom_terms_of_service_enabled": *cfg.SupportSettings.CustomTermsOfServiceEnabled, }) a.SendDiagnostic(TRACK_CONFIG_LDAP, map[string]interface{}{ diff --git a/app/service_terms.go b/app/service_terms.go deleted file mode 100644 index 85808ddd4..000000000 --- a/app/service_terms.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package app - -import ( - "github.com/mattermost/mattermost-server/model" -) - -func (a *App) CreateServiceTerms(text, userId string) (*model.ServiceTerms, *model.AppError) { - serviceTerms := &model.ServiceTerms{ - Text: text, - UserId: userId, - } - - if _, err := a.GetUser(userId); err != nil { - return nil, err - } - - result := <-a.Srv.Store.ServiceTerms().Save(serviceTerms) - if result.Err != nil { - return nil, result.Err - } - - serviceTerms = result.Data.(*model.ServiceTerms) - return serviceTerms, nil -} - -func (a *App) GetLatestServiceTerms() (*model.ServiceTerms, *model.AppError) { - if result := <-a.Srv.Store.ServiceTerms().GetLatest(true); result.Err != nil { - return nil, result.Err - } else { - serviceTerms := result.Data.(*model.ServiceTerms) - return serviceTerms, nil - } -} - -func (a *App) GetServiceTerms(id string) (*model.ServiceTerms, *model.AppError) { - if result := <-a.Srv.Store.ServiceTerms().Get(id, true); result.Err != nil { - return nil, result.Err - } else { - serviceTerms := result.Data.(*model.ServiceTerms) - return serviceTerms, nil - } -} diff --git a/app/terms_of_service.go b/app/terms_of_service.go new file mode 100644 index 000000000..9850b3450 --- /dev/null +++ b/app/terms_of_service.go @@ -0,0 +1,45 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package app + +import ( + "github.com/mattermost/mattermost-server/model" +) + +func (a *App) CreateTermsOfService(text, userId string) (*model.TermsOfService, *model.AppError) { + termsOfService := &model.TermsOfService{ + Text: text, + UserId: userId, + } + + if _, err := a.GetUser(userId); err != nil { + return nil, err + } + + result := <-a.Srv.Store.TermsOfService().Save(termsOfService) + if result.Err != nil { + return nil, result.Err + } + + termsOfService = result.Data.(*model.TermsOfService) + return termsOfService, nil +} + +func (a *App) GetLatestTermsOfService() (*model.TermsOfService, *model.AppError) { + if result := <-a.Srv.Store.TermsOfService().GetLatest(true); result.Err != nil { + return nil, result.Err + } else { + termsOfService := result.Data.(*model.TermsOfService) + return termsOfService, nil + } +} + +func (a *App) GetTermsOfService(id string) (*model.TermsOfService, *model.AppError) { + if result := <-a.Srv.Store.TermsOfService().Get(id, true); result.Err != nil { + return nil, result.Err + } else { + termsOfService := result.Data.(*model.TermsOfService) + return termsOfService, nil + } +} diff --git a/app/user.go b/app/user.go index 1faf2b895..e565fea76 100644 --- a/app/user.go +++ b/app/user.go @@ -1652,16 +1652,16 @@ func (a *App) UpdateOAuthUserAttrs(userData io.Reader, user *model.User, provide return nil } -func (a *App) RecordUserServiceTermsAction(userId, serviceTermsId string, accepted bool) *model.AppError { +func (a *App) RecordUserTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) *model.AppError { user, err := a.GetUser(userId) if err != nil { return err } if accepted { - user.AcceptedServiceTermsId = serviceTermsId + user.AcceptedTermsOfServiceId = termsOfServiceId } else { - user.AcceptedServiceTermsId = "" + user.AcceptedTermsOfServiceId = "" } _, err = a.UpdateUser(user, false) if err != nil { diff --git a/app/user_test.go b/app/user_test.go index 465d2a994..7cd369749 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -545,7 +545,7 @@ func TestPermanentDeleteUser(t *testing.T) { } } -func TestRecordUserServiceTermsAction(t *testing.T) { +func TestRecordUserTermsOfServiceAction(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -563,24 +563,24 @@ func TestRecordUserServiceTermsAction(t *testing.T) { defer th.App.PermanentDeleteUser(user) - serviceTerms, err := th.App.CreateServiceTerms("text", user.Id) + termsOfService, err := th.App.CreateTermsOfService("text", user.Id) if err != nil { - t.Fatalf("failed to create service terms: %v", err) + t.Fatalf("failed to create terms of service: %v", err) } - err = th.App.RecordUserServiceTermsAction(user.Id, serviceTerms.Id, true) + err = th.App.RecordUserTermsOfServiceAction(user.Id, termsOfService.Id, true) if err != nil { t.Fatalf("failed to record user action: %v", err) } nuser, err := th.App.GetUser(user.Id) - assert.Equal(t, serviceTerms.Id, nuser.AcceptedServiceTermsId) + assert.Equal(t, termsOfService.Id, nuser.AcceptedTermsOfServiceId) - err = th.App.RecordUserServiceTermsAction(user.Id, serviceTerms.Id, false) + err = th.App.RecordUserTermsOfServiceAction(user.Id, termsOfService.Id, false) if err != nil { t.Fatalf("failed to record user action: %v", err) } nuser, err = th.App.GetUser(user.Id) - assert.Empty(t, nuser.AcceptedServiceTermsId) + assert.Empty(t, nuser.AcceptedTermsOfServiceId) } diff --git a/i18n/en.json b/i18n/en.json index 7d8bd4122..6bcfc603f 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -2371,7 +2371,7 @@ "translation": "Bad verify email token type." }, { - "id": "api.user.register_service_terms_action.bad_value.app_error", + "id": "api.user.register_terms_of_service_action.bad_value.app_error", "translation": "Bad accepted value" }, { @@ -2435,11 +2435,11 @@ "translation": "Invalid {{.Name}} parameter" }, { - "id": "api.create_service_terms.empty_text.app_error", + "id": "api.create_terms_of_service.empty_text.app_error", "translation": "Please enter text for your Custom Terms of Service." }, { - "id": "api.create_service_terms.custom_service_terms_disabled.app_error", + "id": "api.create_terms_of_service.custom_terms_of_service_disabled.app_error", "translation": "Custom terms of service feature is disabled" }, { @@ -4811,19 +4811,19 @@ "translation": "Unable to connect to the WebSocket server." }, { - "id": "model.service_terms.is_valid.id.app_error", + "id": "model.terms_of_service.is_valid.id.app_error", "translation": "Invalid term of service id." }, { - "id": "model.service_terms.is_valid.create_at.app_error", + "id": "model.terms_of_service.is_valid.create_at.app_error", "translation": "Missing required term of service property: create_at." }, { - "id": "model.service_terms.is_valid.user_id.app_error", + "id": "model.terms_of_service.is_valid.user_id.app_error", "translation": "Missing required terms of service property: user_id." }, { - "id": "model.service_terms.is_valid.text.app_error", + "id": "model.terms_of_service.is_valid.text.app_error", "translation": "Custom terms of service text is too long. Maximum {{.MaxLength}} characters allowed." }, { @@ -6459,19 +6459,19 @@ "translation": "Unable to update the webhook" }, { - "id": "store.sql_service_terms_store.save.existing.app_error", + "id": "store.sql_terms_of_service_store.save.existing.app_error", "translation": "Must not call save for existing terms of service." }, { - "id": "store.sql_service_terms.save.app_error", + "id": "store.sql_terms_of_service.save.app_error", "translation": "Unable to save terms of service." }, { - "id": "store.sql_service_terms_store.get.app_error", + "id": "store.sql_terms_of_service_store.get.app_error", "translation": "Unable to fetch terms of service." }, { - "id": "store.sql_service_terms_store.get.no_rows.app_error", + "id": "store.sql_terms_of_service_store.get.no_rows.app_error", "translation": "No terms of service found." }, { diff --git a/model/client4.go b/model/client4.go index 964218a68..903687ece 100644 --- a/model/client4.go +++ b/model/client4.go @@ -401,11 +401,11 @@ func (c *Client4) GetRedirectLocationRoute() string { return fmt.Sprintf("/redirect_location") } -func (c *Client4) GetRegisterServiceTermsRoute(userId string) string { +func (c *Client4) GetRegisterTermsOfServiceRoute(userId string) string { return c.GetUserRoute(userId) + "/terms_of_service" } -func (c *Client4) GetServiceTermsRoute() string { +func (c *Client4) GetTermsOfServiceRoute() string { return "/terms_of_service" } @@ -3828,9 +3828,9 @@ func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) } } -func (c *Client4) RegisterServiceTermsAction(userId, serviceTermsId string, accepted bool) (*bool, *Response) { - url := c.GetRegisterServiceTermsRoute(userId) - data := map[string]interface{}{"serviceTermsId": serviceTermsId, "accepted": accepted} +func (c *Client4) RegisteTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*bool, *Response) { + url := c.GetRegisterTermsOfServiceRoute(userId) + data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted} if r, err := c.DoApiPost(url, StringInterfaceToJson(data)); err != nil { return nil, BuildErrorResponse(r, err) @@ -3840,25 +3840,25 @@ func (c *Client4) RegisterServiceTermsAction(userId, serviceTermsId string, acce } } -func (c *Client4) GetServiceTerms(etag string) (*ServiceTerms, *Response) { - url := c.GetServiceTermsRoute() +func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response) { + url := c.GetTermsOfServiceRoute() if r, err := c.DoApiGet(url, etag); err != nil { return nil, BuildErrorResponse(r, err) } else { defer closeBody(r) - return ServiceTermsFromJson(r.Body), BuildResponse(r) + return TermsOfServiceFromJson(r.Body), BuildResponse(r) } } -func (c *Client4) CreateServiceTerms(text, userId string) (*ServiceTerms, *Response) { - url := c.GetServiceTermsRoute() +func (c *Client4) CreateTermsOfService(text, userId string) (*TermsOfService, *Response) { + url := c.GetTermsOfServiceRoute() data := map[string]string{"text": text} if r, err := c.DoApiPost(url, MapToJson(data)); err != nil { return nil, BuildErrorResponse(r, err) } else { defer closeBody(r) - return ServiceTermsFromJson(r.Body), BuildResponse(r) + return TermsOfServiceFromJson(r.Body), BuildResponse(r) } } diff --git a/model/config.go b/model/config.go index 5e6a676ae..d59b8d6db 100644 --- a/model/config.go +++ b/model/config.go @@ -996,13 +996,13 @@ type PrivacySettings struct { } type SupportSettings struct { - TermsOfServiceLink *string - PrivacyPolicyLink *string - AboutLink *string - HelpLink *string - ReportAProblemLink *string - SupportEmail *string - CustomServiceTermsEnabled *bool + TermsOfServiceLink *string + PrivacyPolicyLink *string + AboutLink *string + HelpLink *string + ReportAProblemLink *string + SupportEmail *string + CustomTermsOfServiceEnabled *bool } func (s *SupportSettings) SetDefaults() { @@ -1050,8 +1050,8 @@ func (s *SupportSettings) SetDefaults() { s.SupportEmail = NewString(SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL) } - if s.CustomServiceTermsEnabled == nil { - s.CustomServiceTermsEnabled = NewBool(false) + if s.CustomTermsOfServiceEnabled == nil { + s.CustomTermsOfServiceEnabled = NewBool(false) } } diff --git a/model/service_terms.go b/model/service_terms.go deleted file mode 100644 index 84ee0d395..000000000 --- a/model/service_terms.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package model - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "unicode/utf8" -) - -// we only ever need the latest version of service terms -const SERVICE_TERMS_CACHE_SIZE = 1 - -type ServiceTerms struct { - Id string `json:"id"` - CreateAt int64 `json:"create_at"` - UserId string `json:"user_id"` - Text string `json:"text"` -} - -func (t *ServiceTerms) IsValid() *AppError { - if len(t.Id) != 26 { - return InvalidServiceTermsError("id", "") - } - - if t.CreateAt == 0 { - return InvalidServiceTermsError("create_at", t.Id) - } - - if len(t.UserId) != 26 { - return InvalidServiceTermsError("user_id", t.Id) - } - - if utf8.RuneCountInString(t.Text) > POST_MESSAGE_MAX_RUNES_V2 { - return InvalidServiceTermsError("text", t.Id) - } - - return nil -} - -func (t *ServiceTerms) ToJson() string { - b, _ := json.Marshal(t) - return string(b) -} - -func ServiceTermsFromJson(data io.Reader) *ServiceTerms { - var serviceTerms *ServiceTerms - json.NewDecoder(data).Decode(&serviceTerms) - return serviceTerms -} - -func InvalidServiceTermsError(fieldName string, serviceTermsId string) *AppError { - id := fmt.Sprintf("model.service_terms.is_valid.%s.app_error", fieldName) - details := "" - if serviceTermsId != "" { - details = "service_terms_id=" + serviceTermsId - } - return NewAppError("ServiceTerms.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest) -} - -func (t *ServiceTerms) PreSave() { - if t.Id == "" { - t.Id = NewId() - } - - t.CreateAt = GetMillis() -} diff --git a/model/service_terms_test.go b/model/service_terms_test.go deleted file mode 100644 index 89b8ff9b5..000000000 --- a/model/service_terms_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package model - -import ( - "github.com/stretchr/testify/assert" - "strings" - "testing" -) - -func TestServiceTermsIsValid(t *testing.T) { - s := ServiceTerms{} - - if err := s.IsValid(); err == nil { - t.Fatal("should be invalid") - } - - s.Id = NewId() - if err := s.IsValid(); err == nil { - t.Fatal("should be invalid") - } - - s.CreateAt = GetMillis() - if err := s.IsValid(); err == nil { - t.Fatal("should be invalid") - } - - s.UserId = NewId() - if err := s.IsValid(); err != nil { - t.Fatal("should be invalid") - } - - s.Text = strings.Repeat("0", POST_MESSAGE_MAX_RUNES_V2+1) - if err := s.IsValid(); err == nil { - t.Fatal("should be invalid") - } - - s.Text = strings.Repeat("0", POST_MESSAGE_MAX_RUNES_V2) - if err := s.IsValid(); err != nil { - t.Fatal(err) - } - - s.Text = "test" - if err := s.IsValid(); err != nil { - t.Fatal(err) - } -} - -func TestServiceTermsJson(t *testing.T) { - o := ServiceTerms{ - Id: NewId(), - Text: NewId(), - CreateAt: GetMillis(), - UserId: NewId(), - } - j := o.ToJson() - ro := ServiceTermsFromJson(strings.NewReader(j)) - - assert.NotNil(t, ro) - assert.Equal(t, o, *ro) -} diff --git a/model/terms_of_service.go b/model/terms_of_service.go new file mode 100644 index 000000000..c99a78568 --- /dev/null +++ b/model/terms_of_service.go @@ -0,0 +1,70 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "unicode/utf8" +) + +// we only ever need the latest version of terms of service +const TERMS_OF_SERVICE_CACHE_SIZE = 1 + +type TermsOfService struct { + Id string `json:"id"` + CreateAt int64 `json:"create_at"` + UserId string `json:"user_id"` + Text string `json:"text"` +} + +func (t *TermsOfService) IsValid() *AppError { + if len(t.Id) != 26 { + return InvalidTermsOfServiceError("id", "") + } + + if t.CreateAt == 0 { + return InvalidTermsOfServiceError("create_at", t.Id) + } + + if len(t.UserId) != 26 { + return InvalidTermsOfServiceError("user_id", t.Id) + } + + if utf8.RuneCountInString(t.Text) > POST_MESSAGE_MAX_RUNES_V2 { + return InvalidTermsOfServiceError("text", t.Id) + } + + return nil +} + +func (t *TermsOfService) ToJson() string { + b, _ := json.Marshal(t) + return string(b) +} + +func TermsOfServiceFromJson(data io.Reader) *TermsOfService { + var termsOfService *TermsOfService + json.NewDecoder(data).Decode(&termsOfService) + return termsOfService +} + +func InvalidTermsOfServiceError(fieldName string, termsOfServiceId string) *AppError { + id := fmt.Sprintf("model.terms_of_service.is_valid.%s.app_error", fieldName) + details := "" + if termsOfServiceId != "" { + details = "terms_of_service_id=" + termsOfServiceId + } + return NewAppError("TermsOfServiceStore.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest) +} + +func (t *TermsOfService) PreSave() { + if t.Id == "" { + t.Id = NewId() + } + + t.CreateAt = GetMillis() +} diff --git a/model/terms_of_service_test.go b/model/terms_of_service_test.go new file mode 100644 index 000000000..134172a61 --- /dev/null +++ b/model/terms_of_service_test.go @@ -0,0 +1,62 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package model + +import ( + "github.com/stretchr/testify/assert" + "strings" + "testing" +) + +func TestTermsOfServiceIsValid(t *testing.T) { + s := TermsOfService{} + + if err := s.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + s.Id = NewId() + if err := s.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + s.CreateAt = GetMillis() + if err := s.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + s.UserId = NewId() + if err := s.IsValid(); err != nil { + t.Fatal("should be invalid") + } + + s.Text = strings.Repeat("0", POST_MESSAGE_MAX_RUNES_V2+1) + if err := s.IsValid(); err == nil { + t.Fatal("should be invalid") + } + + s.Text = strings.Repeat("0", POST_MESSAGE_MAX_RUNES_V2) + if err := s.IsValid(); err != nil { + t.Fatal(err) + } + + s.Text = "test" + if err := s.IsValid(); err != nil { + t.Fatal(err) + } +} + +func TestTermsOfServiceJson(t *testing.T) { + o := TermsOfService{ + Id: NewId(), + Text: NewId(), + CreateAt: GetMillis(), + UserId: NewId(), + } + j := o.ToJson() + ro := TermsOfServiceFromJson(strings.NewReader(j)) + + assert.NotNil(t, ro) + assert.Equal(t, o, *ro) +} diff --git a/model/user.go b/model/user.go index d94a28b2d..781bcae66 100644 --- a/model/user.go +++ b/model/user.go @@ -48,33 +48,33 @@ const ( ) type User struct { - Id string `json:"id"` - CreateAt int64 `json:"create_at,omitempty"` - UpdateAt int64 `json:"update_at,omitempty"` - DeleteAt int64 `json:"delete_at"` - Username string `json:"username"` - Password string `json:"password,omitempty"` - AuthData *string `json:"auth_data,omitempty"` - AuthService string `json:"auth_service"` - Email string `json:"email"` - EmailVerified bool `json:"email_verified,omitempty"` - Nickname string `json:"nickname"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - Position string `json:"position"` - Roles string `json:"roles"` - AllowMarketing bool `json:"allow_marketing,omitempty"` - Props StringMap `json:"props,omitempty"` - NotifyProps StringMap `json:"notify_props,omitempty"` - LastPasswordUpdate int64 `json:"last_password_update,omitempty"` - LastPictureUpdate int64 `json:"last_picture_update,omitempty"` - FailedAttempts int `json:"failed_attempts,omitempty"` - Locale string `json:"locale"` - Timezone StringMap `json:"timezone"` - MfaActive bool `json:"mfa_active,omitempty"` - MfaSecret string `json:"mfa_secret,omitempty"` - LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"` - AcceptedServiceTermsId string `json:"accepted_service_terms_id,omitempty"` + Id string `json:"id"` + CreateAt int64 `json:"create_at,omitempty"` + UpdateAt int64 `json:"update_at,omitempty"` + DeleteAt int64 `json:"delete_at"` + Username string `json:"username"` + Password string `json:"password,omitempty"` + AuthData *string `json:"auth_data,omitempty"` + AuthService string `json:"auth_service"` + Email string `json:"email"` + EmailVerified bool `json:"email_verified,omitempty"` + Nickname string `json:"nickname"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + Position string `json:"position"` + Roles string `json:"roles"` + AllowMarketing bool `json:"allow_marketing,omitempty"` + Props StringMap `json:"props,omitempty"` + NotifyProps StringMap `json:"notify_props,omitempty"` + LastPasswordUpdate int64 `json:"last_password_update,omitempty"` + LastPictureUpdate int64 `json:"last_picture_update,omitempty"` + FailedAttempts int `json:"failed_attempts,omitempty"` + Locale string `json:"locale"` + Timezone StringMap `json:"timezone"` + MfaActive bool `json:"mfa_active,omitempty"` + MfaSecret string `json:"mfa_secret,omitempty"` + LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"` + AcceptedTermsOfServiceId string `json:"accepted_terms_of_service_id,omitempty"` // TODO remove this field when new TOS user action table is created } type UserPatch struct { diff --git a/store/layered_store.go b/store/layered_store.go index f5f1f9b54..da2880fa5 100644 --- a/store/layered_store.go +++ b/store/layered_store.go @@ -169,8 +169,8 @@ func (s *LayeredStore) Role() RoleStore { return s.RoleStore } -func (s *LayeredStore) ServiceTerms() ServiceTermsStore { - return s.DatabaseLayer.ServiceTerms() +func (s *LayeredStore) TermsOfService() TermsOfServiceStore { + return s.DatabaseLayer.TermsOfService() } func (s *LayeredStore) Scheme() SchemeStore { diff --git a/store/sqlstore/service_terms_store.go b/store/sqlstore/service_terms_store.go deleted file mode 100644 index 43a1189f6..000000000 --- a/store/sqlstore/service_terms_store.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package sqlstore - -import ( - "database/sql" - "github.com/mattermost/mattermost-server/einterfaces" - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" - "github.com/mattermost/mattermost-server/utils" - "net/http" -) - -type SqlServiceTermsStore struct { - SqlStore - metrics einterfaces.MetricsInterface -} - -var serviceTermsCache = utils.NewLru(model.SERVICE_TERMS_CACHE_SIZE) - -const serviceTermsCacheName = "ServiceTerms" - -func NewSqlTermStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.ServiceTermsStore { - s := SqlServiceTermsStore{sqlStore, metrics} - - for _, db := range sqlStore.GetAllConns() { - table := db.AddTableWithName(model.ServiceTerms{}, "ServiceTerms").SetKeys(false, "Id") - table.ColMap("Id").SetMaxSize(26) - table.ColMap("UserId").SetMaxSize(26) - table.ColMap("Text").SetMaxSize(model.POST_MESSAGE_MAX_BYTES_V2) - } - - return s -} - -func (s SqlServiceTermsStore) CreateIndexesIfNotExists() { -} - -func (s SqlServiceTermsStore) Save(serviceTerms *model.ServiceTerms) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - if len(serviceTerms.Id) > 0 { - result.Err = model.NewAppError( - "SqlServiceTermsStore.Save", - "store.sql_service_terms_store.save.existing.app_error", - nil, - "id="+serviceTerms.Id, http.StatusBadRequest, - ) - return - } - - serviceTerms.PreSave() - - if result.Err = serviceTerms.IsValid(); result.Err != nil { - return - } - - if err := s.GetMaster().Insert(serviceTerms); err != nil { - result.Err = model.NewAppError( - "SqlServiceTermsStore.Save", - "store.sql_service_terms.save.app_error", - nil, - "service_term_id="+serviceTerms.Id+",err="+err.Error(), - http.StatusInternalServerError, - ) - } - - result.Data = serviceTerms - - serviceTermsCache.AddWithDefaultExpires(serviceTerms.Id, serviceTerms) - }) -} - -func (s SqlServiceTermsStore) GetLatest(allowFromCache bool) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - if allowFromCache { - if serviceTermsCache.Len() == 0 { - if s.metrics != nil { - s.metrics.IncrementMemCacheMissCounter(serviceTermsCacheName) - } - } else { - if cacheItem, ok := serviceTermsCache.Get(serviceTermsCache.Keys()[0]); ok { - if s.metrics != nil { - s.metrics.IncrementMemCacheHitCounter(serviceTermsCacheName) - } - - result.Data = cacheItem.(*model.ServiceTerms) - return - } else if s.metrics != nil { - s.metrics.IncrementMemCacheMissCounter(serviceTermsCacheName) - } - } - } - - var serviceTerms *model.ServiceTerms - - err := s.GetReplica().SelectOne(&serviceTerms, "SELECT * FROM ServiceTerms ORDER BY CreateAt DESC LIMIT 1") - if err != nil { - if err == sql.ErrNoRows { - result.Err = model.NewAppError("SqlServiceTermsStore.GetLatest", "store.sql_service_terms_store.get.no_rows.app_error", nil, "err="+err.Error(), http.StatusNotFound) - } else { - result.Err = model.NewAppError("SqlServiceTermsStore.GetLatest", "store.sql_service_terms_store.get.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) - } - } else { - result.Data = serviceTerms - - if allowFromCache { - serviceTermsCache.AddWithDefaultExpires(serviceTerms.Id, serviceTerms) - } - } - }) -} - -func (s SqlServiceTermsStore) Get(id string, allowFromCache bool) store.StoreChannel { - return store.Do(func(result *store.StoreResult) { - if allowFromCache { - if serviceTermsCache.Len() == 0 { - if s.metrics != nil { - s.metrics.IncrementMemCacheMissCounter(serviceTermsCacheName) - } - } else { - if cacheItem, ok := serviceTermsCache.Get(id); ok { - if s.metrics != nil { - s.metrics.IncrementMemCacheHitCounter(serviceTermsCacheName) - } - - result.Data = cacheItem.(*model.ServiceTerms) - return - } else if s.metrics != nil { - s.metrics.IncrementMemCacheMissCounter(serviceTermsCacheName) - } - } - } - - if obj, err := s.GetReplica().Get(model.ServiceTerms{}, id); err != nil { - result.Err = model.NewAppError("SqlServiceTermsStore.Get", "store.sql_service_terms_store.get.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) - } else if obj == nil { - result.Err = model.NewAppError("SqlServiceTermsStore.GetLatest", "store.sql_service_terms_store.get.no_rows.app_error", nil, "", http.StatusNotFound) - } else { - result.Data = obj.(*model.ServiceTerms) - } - }) -} diff --git a/store/sqlstore/service_terms_store_test.go b/store/sqlstore/service_terms_store_test.go deleted file mode 100644 index 030d0d7ae..000000000 --- a/store/sqlstore/service_terms_store_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package sqlstore - -import ( - "github.com/mattermost/mattermost-server/store/storetest" - "testing" -) - -func TestServiceTermsStore(t *testing.T) { - StoreTest(t, storetest.TestServiceTermsStore) -} diff --git a/store/sqlstore/store.go b/store/sqlstore/store.go index b6f0fa84e..0408c5feb 100644 --- a/store/sqlstore/store.go +++ b/store/sqlstore/store.go @@ -93,5 +93,5 @@ type SqlStore interface { UserAccessToken() store.UserAccessTokenStore Role() store.RoleStore Scheme() store.SchemeStore - ServiceTerms() store.ServiceTermsStore + TermsOfService() store.TermsOfServiceStore } diff --git a/store/sqlstore/supplier.go b/store/sqlstore/supplier.go index 62c1102ca..2fc299dc9 100644 --- a/store/sqlstore/supplier.go +++ b/store/sqlstore/supplier.go @@ -92,7 +92,7 @@ type SqlSupplierOldStores struct { channelMemberHistory store.ChannelMemberHistoryStore role store.RoleStore scheme store.SchemeStore - serviceTerms store.ServiceTermsStore + TermsOfService store.TermsOfServiceStore } type SqlSupplier struct { @@ -146,7 +146,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter supplier.oldStores.userAccessToken = NewSqlUserAccessTokenStore(supplier) supplier.oldStores.channelMemberHistory = NewSqlChannelMemberHistoryStore(supplier) supplier.oldStores.plugin = NewSqlPluginStore(supplier) - supplier.oldStores.serviceTerms = NewSqlTermStore(supplier, metrics) + supplier.oldStores.TermsOfService = NewSqlTermsOfServiceStore(supplier, metrics) initSqlSupplierReactions(supplier) initSqlSupplierRoles(supplier) @@ -182,7 +182,7 @@ func NewSqlSupplier(settings model.SqlSettings, metrics einterfaces.MetricsInter supplier.oldStores.job.(*SqlJobStore).CreateIndexesIfNotExists() supplier.oldStores.userAccessToken.(*SqlUserAccessTokenStore).CreateIndexesIfNotExists() supplier.oldStores.plugin.(*SqlPluginStore).CreateIndexesIfNotExists() - supplier.oldStores.serviceTerms.(SqlServiceTermsStore).CreateIndexesIfNotExists() + supplier.oldStores.TermsOfService.(SqlTermsOfServiceStore).CreateIndexesIfNotExists() supplier.oldStores.preference.(*SqlPreferenceStore).DeleteUnusedFeatures() @@ -964,8 +964,8 @@ func (ss *SqlSupplier) Role() store.RoleStore { return ss.oldStores.role } -func (ss *SqlSupplier) ServiceTerms() store.ServiceTermsStore { - return ss.oldStores.serviceTerms +func (ss *SqlSupplier) TermsOfService() store.TermsOfServiceStore { + return ss.oldStores.TermsOfService } func (ss *SqlSupplier) Scheme() store.SchemeStore { diff --git a/store/sqlstore/terms_of_service_store.go b/store/sqlstore/terms_of_service_store.go new file mode 100644 index 000000000..dc9ce5b5c --- /dev/null +++ b/store/sqlstore/terms_of_service_store.go @@ -0,0 +1,143 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package sqlstore + +import ( + "database/sql" + "github.com/mattermost/mattermost-server/einterfaces" + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" + "github.com/mattermost/mattermost-server/utils" + "net/http" +) + +type SqlTermsOfServiceStore struct { + SqlStore + metrics einterfaces.MetricsInterface +} + +var termsOfServiceCache = utils.NewLru(model.TERMS_OF_SERVICE_CACHE_SIZE) + +const termsOfServiceCacheName = "TermsOfServiceStore" + +func NewSqlTermsOfServiceStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) store.TermsOfServiceStore { + s := SqlTermsOfServiceStore{sqlStore, metrics} + + for _, db := range sqlStore.GetAllConns() { + table := db.AddTableWithName(model.TermsOfService{}, "TermsOfService").SetKeys(false, "Id") + table.ColMap("Id").SetMaxSize(26) + table.ColMap("UserId").SetMaxSize(26) + table.ColMap("Text").SetMaxSize(model.POST_MESSAGE_MAX_BYTES_V2) + } + + return s +} + +func (s SqlTermsOfServiceStore) CreateIndexesIfNotExists() { +} + +func (s SqlTermsOfServiceStore) Save(termsOfService *model.TermsOfService) store.StoreChannel { + return store.Do(func(result *store.StoreResult) { + if len(termsOfService.Id) > 0 { + result.Err = model.NewAppError( + "SqlTermsOfServiceStore.Save", + "store.sql_terms_of_service_store.save.existing.app_error", + nil, + "id="+termsOfService.Id, http.StatusBadRequest, + ) + return + } + + termsOfService.PreSave() + + if result.Err = termsOfService.IsValid(); result.Err != nil { + return + } + + if err := s.GetMaster().Insert(termsOfService); err != nil { + result.Err = model.NewAppError( + "SqlTermsOfServiceStore.Save", + "store.sql_terms_of_service.save.app_error", + nil, + "terms_of_service_id="+termsOfService.Id+",err="+err.Error(), + http.StatusInternalServerError, + ) + } + + result.Data = termsOfService + + termsOfServiceCache.AddWithDefaultExpires(termsOfService.Id, termsOfService) + }) +} + +func (s SqlTermsOfServiceStore) GetLatest(allowFromCache bool) store.StoreChannel { + return store.Do(func(result *store.StoreResult) { + if allowFromCache { + if termsOfServiceCache.Len() == 0 { + if s.metrics != nil { + s.metrics.IncrementMemCacheMissCounter(termsOfServiceCacheName) + } + } else { + if cacheItem, ok := termsOfServiceCache.Get(termsOfServiceCache.Keys()[0]); ok { + if s.metrics != nil { + s.metrics.IncrementMemCacheHitCounter(termsOfServiceCacheName) + } + + result.Data = cacheItem.(*model.TermsOfService) + return + } else if s.metrics != nil { + s.metrics.IncrementMemCacheMissCounter(termsOfServiceCacheName) + } + } + } + + var termsOfService *model.TermsOfService + + err := s.GetReplica().SelectOne(&termsOfService, "SELECT * FROM TermsOfService ORDER BY CreateAt DESC LIMIT 1") + if err != nil { + if err == sql.ErrNoRows { + result.Err = model.NewAppError("SqlTermsOfServiceStore.GetLatest", "store.sql_terms_of_service_store.get.no_rows.app_error", nil, "err="+err.Error(), http.StatusNotFound) + } else { + result.Err = model.NewAppError("SqlTermsOfServiceStore.GetLatest", "store.sql_terms_of_service_store.get.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) + } + } else { + result.Data = termsOfService + + if allowFromCache { + termsOfServiceCache.AddWithDefaultExpires(termsOfService.Id, termsOfService) + } + } + }) +} + +func (s SqlTermsOfServiceStore) Get(id string, allowFromCache bool) store.StoreChannel { + return store.Do(func(result *store.StoreResult) { + if allowFromCache { + if termsOfServiceCache.Len() == 0 { + if s.metrics != nil { + s.metrics.IncrementMemCacheMissCounter(termsOfServiceCacheName) + } + } else { + if cacheItem, ok := termsOfServiceCache.Get(id); ok { + if s.metrics != nil { + s.metrics.IncrementMemCacheHitCounter(termsOfServiceCacheName) + } + + result.Data = cacheItem.(*model.TermsOfService) + return + } else if s.metrics != nil { + s.metrics.IncrementMemCacheMissCounter(termsOfServiceCacheName) + } + } + } + + if obj, err := s.GetReplica().Get(model.TermsOfService{}, id); err != nil { + result.Err = model.NewAppError("SqlTermsOfServiceStore.Get", "store.sql_terms_of_service_store.get.app_error", nil, "err="+err.Error(), http.StatusInternalServerError) + } else if obj == nil { + result.Err = model.NewAppError("SqlTermsOfServiceStore.GetLatest", "store.sql_terms_of_service_store.get.no_rows.app_error", nil, "", http.StatusNotFound) + } else { + result.Data = obj.(*model.TermsOfService) + } + }) +} diff --git a/store/sqlstore/terms_of_service_store_test.go b/store/sqlstore/terms_of_service_store_test.go new file mode 100644 index 000000000..c41fe7210 --- /dev/null +++ b/store/sqlstore/terms_of_service_store_test.go @@ -0,0 +1,10 @@ +package sqlstore + +import ( + "github.com/mattermost/mattermost-server/store/storetest" + "testing" +) + +func TestTermsOfServiceStore(t *testing.T) { + StoreTest(t, storetest.TestTermsOfServiceStore) +} diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go index 31815e41e..42d34f525 100644 --- a/store/sqlstore/upgrade.go +++ b/store/sqlstore/upgrade.go @@ -502,7 +502,7 @@ func UpgradeDatabaseToVersion54(sqlStore SqlStore) { time.Sleep(time.Second) os.Exit(EXIT_GENERIC_FAILURE) } - sqlStore.CreateColumnIfNotExists("Users", "AcceptedServiceTermsId", "varchar(64)", "varchar(64)", "") + sqlStore.CreateColumnIfNotExists("Users", "AcceptedTermsOfServiceId", "varchar(64)", "varchar(64)", "") saveSchemaVersion(sqlStore, VERSION_5_4_0) } } diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 1b9752064..f0839c3b7 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -82,6 +82,7 @@ func NewSqlUserStore(sqlStore SqlStore, metrics einterfaces.MetricsInterface) st table.ColMap("MfaSecret").SetMaxSize(128) table.ColMap("Position").SetMaxSize(128) table.ColMap("Timezone").SetMaxSize(256) + table.ColMap("AcceptedTermsOfServiceId").SetMaxSize(64) } return us diff --git a/store/store.go b/store/store.go index 8a2051527..29028130e 100644 --- a/store/store.go +++ b/store/store.go @@ -65,7 +65,7 @@ type Store interface { UserAccessToken() UserAccessTokenStore ChannelMemberHistory() ChannelMemberHistoryStore Plugin() PluginStore - ServiceTerms() ServiceTermsStore + TermsOfService() TermsOfServiceStore MarkSystemRanUnitTests() Close() LockToMaster() @@ -523,8 +523,8 @@ type SchemeStore interface { PermanentDeleteAll() StoreChannel } -type ServiceTermsStore interface { - Save(serviceTerms *model.ServiceTerms) StoreChannel +type TermsOfServiceStore interface { + Save(termsOfService *model.TermsOfService) StoreChannel GetLatest(allowFromCache bool) StoreChannel Get(id string, allowFromCache bool) StoreChannel } diff --git a/store/storetest/mocks/LayeredStoreDatabaseLayer.go b/store/storetest/mocks/LayeredStoreDatabaseLayer.go index 7f653fc2f..3b06bbdf5 100644 --- a/store/storetest/mocks/LayeredStoreDatabaseLayer.go +++ b/store/storetest/mocks/LayeredStoreDatabaseLayer.go @@ -729,22 +729,6 @@ func (_m *LayeredStoreDatabaseLayer) SchemeSave(ctx context.Context, scheme *mod return r0 } -// ServiceTerms provides a mock function with given fields: -func (_m *LayeredStoreDatabaseLayer) ServiceTerms() store.ServiceTermsStore { - ret := _m.Called() - - var r0 store.ServiceTermsStore - if rf, ok := ret.Get(0).(func() store.ServiceTermsStore); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.ServiceTermsStore) - } - } - - return r0 -} - // Session provides a mock function with given fields: func (_m *LayeredStoreDatabaseLayer) Session() store.SessionStore { ret := _m.Called() @@ -814,6 +798,22 @@ func (_m *LayeredStoreDatabaseLayer) Team() store.TeamStore { return r0 } +// TermsOfService provides a mock function with given fields: +func (_m *LayeredStoreDatabaseLayer) TermsOfService() store.TermsOfServiceStore { + ret := _m.Called() + + var r0 store.TermsOfServiceStore + if rf, ok := ret.Get(0).(func() store.TermsOfServiceStore); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.TermsOfServiceStore) + } + } + + return r0 +} + // Token provides a mock function with given fields: func (_m *LayeredStoreDatabaseLayer) Token() store.TokenStore { ret := _m.Called() diff --git a/store/storetest/mocks/ServiceTermsStore.go b/store/storetest/mocks/ServiceTermsStore.go deleted file mode 100644 index 9115e6093..000000000 --- a/store/storetest/mocks/ServiceTermsStore.go +++ /dev/null @@ -1,62 +0,0 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. - -// Regenerate this file using `make store-mocks`. - -package mocks - -import mock "github.com/stretchr/testify/mock" -import model "github.com/mattermost/mattermost-server/model" -import store "github.com/mattermost/mattermost-server/store" - -// ServiceTermsStore is an autogenerated mock type for the ServiceTermsStore type -type ServiceTermsStore struct { - mock.Mock -} - -// Get provides a mock function with given fields: id, allowFromCache -func (_m *ServiceTermsStore) Get(id string, allowFromCache bool) store.StoreChannel { - ret := _m.Called(id, allowFromCache) - - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(string, bool) store.StoreChannel); ok { - r0 = rf(id, allowFromCache) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) - } - } - - return r0 -} - -// GetLatest provides a mock function with given fields: allowFromCache -func (_m *ServiceTermsStore) GetLatest(allowFromCache bool) store.StoreChannel { - ret := _m.Called(allowFromCache) - - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(bool) store.StoreChannel); ok { - r0 = rf(allowFromCache) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) - } - } - - return r0 -} - -// Save provides a mock function with given fields: serviceTerms -func (_m *ServiceTermsStore) Save(serviceTerms *model.ServiceTerms) store.StoreChannel { - ret := _m.Called(serviceTerms) - - var r0 store.StoreChannel - if rf, ok := ret.Get(0).(func(*model.ServiceTerms) store.StoreChannel); ok { - r0 = rf(serviceTerms) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.StoreChannel) - } - } - - return r0 -} diff --git a/store/storetest/mocks/SqlStore.go b/store/storetest/mocks/SqlStore.go index c2852f3a1..278ca1a61 100644 --- a/store/storetest/mocks/SqlStore.go +++ b/store/storetest/mocks/SqlStore.go @@ -603,22 +603,6 @@ func (_m *SqlStore) Scheme() store.SchemeStore { return r0 } -// ServiceTerms provides a mock function with given fields: -func (_m *SqlStore) ServiceTerms() store.ServiceTermsStore { - ret := _m.Called() - - var r0 store.ServiceTermsStore - if rf, ok := ret.Get(0).(func() store.ServiceTermsStore); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.ServiceTermsStore) - } - } - - return r0 -} - // Session provides a mock function with given fields: func (_m *SqlStore) Session() store.SessionStore { ret := _m.Called() @@ -683,6 +667,22 @@ func (_m *SqlStore) Team() store.TeamStore { return r0 } +// TermsOfService provides a mock function with given fields: +func (_m *SqlStore) TermsOfService() store.TermsOfServiceStore { + ret := _m.Called() + + var r0 store.TermsOfServiceStore + if rf, ok := ret.Get(0).(func() store.TermsOfServiceStore); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.TermsOfServiceStore) + } + } + + return r0 +} + // Token provides a mock function with given fields: func (_m *SqlStore) Token() store.TokenStore { ret := _m.Called() diff --git a/store/storetest/mocks/Store.go b/store/storetest/mocks/Store.go index 8f15650e8..b55df2097 100644 --- a/store/storetest/mocks/Store.go +++ b/store/storetest/mocks/Store.go @@ -320,22 +320,6 @@ func (_m *Store) Scheme() store.SchemeStore { return r0 } -// ServiceTerms provides a mock function with given fields: -func (_m *Store) ServiceTerms() store.ServiceTermsStore { - ret := _m.Called() - - var r0 store.ServiceTermsStore - if rf, ok := ret.Get(0).(func() store.ServiceTermsStore); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(store.ServiceTermsStore) - } - } - - return r0 -} - // Session provides a mock function with given fields: func (_m *Store) Session() store.SessionStore { ret := _m.Called() @@ -400,6 +384,22 @@ func (_m *Store) Team() store.TeamStore { return r0 } +// TermsOfService provides a mock function with given fields: +func (_m *Store) TermsOfService() store.TermsOfServiceStore { + ret := _m.Called() + + var r0 store.TermsOfServiceStore + if rf, ok := ret.Get(0).(func() store.TermsOfServiceStore); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.TermsOfServiceStore) + } + } + + return r0 +} + // Token provides a mock function with given fields: func (_m *Store) Token() store.TokenStore { ret := _m.Called() diff --git a/store/storetest/mocks/TermsOfServiceStore.go b/store/storetest/mocks/TermsOfServiceStore.go new file mode 100644 index 000000000..54dcee1fc --- /dev/null +++ b/store/storetest/mocks/TermsOfServiceStore.go @@ -0,0 +1,62 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +// Regenerate this file using `make store-mocks`. + +package mocks + +import mock "github.com/stretchr/testify/mock" +import model "github.com/mattermost/mattermost-server/model" +import store "github.com/mattermost/mattermost-server/store" + +// TermsOfServiceStore is an autogenerated mock type for the TermsOfServiceStore type +type TermsOfServiceStore struct { + mock.Mock +} + +// Get provides a mock function with given fields: id, allowFromCache +func (_m *TermsOfServiceStore) Get(id string, allowFromCache bool) store.StoreChannel { + ret := _m.Called(id, allowFromCache) + + var r0 store.StoreChannel + if rf, ok := ret.Get(0).(func(string, bool) store.StoreChannel); ok { + r0 = rf(id, allowFromCache) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.StoreChannel) + } + } + + return r0 +} + +// GetLatest provides a mock function with given fields: allowFromCache +func (_m *TermsOfServiceStore) GetLatest(allowFromCache bool) store.StoreChannel { + ret := _m.Called(allowFromCache) + + var r0 store.StoreChannel + if rf, ok := ret.Get(0).(func(bool) store.StoreChannel); ok { + r0 = rf(allowFromCache) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.StoreChannel) + } + } + + return r0 +} + +// Save provides a mock function with given fields: termsOfService +func (_m *TermsOfServiceStore) Save(termsOfService *model.TermsOfService) store.StoreChannel { + ret := _m.Called(termsOfService) + + var r0 store.StoreChannel + if rf, ok := ret.Get(0).(func(*model.TermsOfService) store.StoreChannel); ok { + r0 = rf(termsOfService) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(store.StoreChannel) + } + } + + return r0 +} diff --git a/store/storetest/service_terms_store.go b/store/storetest/service_terms_store.go deleted file mode 100644 index fcb209934..000000000 --- a/store/storetest/service_terms_store.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -package storetest - -import ( - "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store" - "github.com/stretchr/testify/assert" - "testing" -) - -func TestServiceTermsStore(t *testing.T, ss store.Store) { - t.Run("TestSaveServiceTerms", func(t *testing.T) { testSaveServiceTerms(t, ss) }) - t.Run("TestGetLatestServiceTerms", func(t *testing.T) { testGetLatestServiceTerms(t, ss) }) - t.Run("TestGetServiceTerms", func(t *testing.T) { testGetServiceTerms(t, ss) }) -} - -func testSaveServiceTerms(t *testing.T, ss store.Store) { - u1 := model.User{} - u1.Username = model.NewId() - u1.Email = MakeEmail() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(&u1)) - - serviceTerms := &model.ServiceTerms{Text: "service terms", UserId: u1.Id} - r1 := <-ss.ServiceTerms().Save(serviceTerms) - - if r1.Err != nil { - t.Fatal(r1.Err) - } - - savedServiceTerms := r1.Data.(*model.ServiceTerms) - if len(savedServiceTerms.Id) != 26 { - t.Fatal("Id should have been populated") - } - - if savedServiceTerms.CreateAt == 0 { - t.Fatal("Create at should have been populated") - } -} - -func testGetLatestServiceTerms(t *testing.T, ss store.Store) { - u1 := model.User{} - u1.Username = model.NewId() - u1.Email = MakeEmail() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(&u1)) - - serviceTerms := &model.ServiceTerms{Text: "service terms", UserId: u1.Id} - store.Must(ss.ServiceTerms().Save(serviceTerms)) - - r1 := <-ss.ServiceTerms().GetLatest(true) - if r1.Err != nil { - t.Fatal(r1.Err) - } - - fetchedServiceTerms := r1.Data.(*model.ServiceTerms) - assert.Equal(t, serviceTerms.Text, fetchedServiceTerms.Text) - assert.Equal(t, serviceTerms.UserId, fetchedServiceTerms.UserId) -} - -func testGetServiceTerms(t *testing.T, ss store.Store) { - u1 := model.User{} - u1.Username = model.NewId() - u1.Email = MakeEmail() - u1.Nickname = model.NewId() - store.Must(ss.User().Save(&u1)) - - serviceTerms := &model.ServiceTerms{Text: "service terms", UserId: u1.Id} - store.Must(ss.ServiceTerms().Save(serviceTerms)) - - r1 := <-ss.ServiceTerms().Get("an_invalid_id", true) - assert.NotNil(t, r1.Err) - assert.Nil(t, r1.Data) - - r1 = <-ss.ServiceTerms().Get(serviceTerms.Id, true) - assert.Nil(t, r1.Err) - - receivedServiceTerms := r1.Data.(*model.ServiceTerms) - assert.Equal(t, "service terms", receivedServiceTerms.Text) -} diff --git a/store/storetest/store.go b/store/storetest/store.go index e7086a3a5..d6ef4fcd0 100644 --- a/store/storetest/store.go +++ b/store/storetest/store.go @@ -45,7 +45,7 @@ type Store struct { ChannelMemberHistoryStore mocks.ChannelMemberHistoryStore RoleStore mocks.RoleStore SchemeStore mocks.SchemeStore - ServiceTermsStore mocks.ServiceTermsStore + TermsOfServiceStore mocks.TermsOfServiceStore } func (s *Store) Team() store.TeamStore { return &s.TeamStore } @@ -73,7 +73,7 @@ func (s *Store) UserAccessToken() store.UserAccessTokenStore { return &s.UserA func (s *Store) Plugin() store.PluginStore { return &s.PluginStore } func (s *Store) Role() store.RoleStore { return &s.RoleStore } func (s *Store) Scheme() store.SchemeStore { return &s.SchemeStore } -func (s *Store) ServiceTerms() store.ServiceTermsStore { return &s.ServiceTermsStore } +func (s *Store) TermsOfService() store.TermsOfServiceStore { return &s.TermsOfServiceStore } func (s *Store) ChannelMemberHistory() store.ChannelMemberHistoryStore { return &s.ChannelMemberHistoryStore } diff --git a/store/storetest/terms_of_service_store.go b/store/storetest/terms_of_service_store.go new file mode 100644 index 000000000..90af5c1ee --- /dev/null +++ b/store/storetest/terms_of_service_store.go @@ -0,0 +1,82 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package storetest + +import ( + "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/store" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestTermsOfServiceStore(t *testing.T, ss store.Store) { + t.Run("TestSaveTermsOfService", func(t *testing.T) { testSaveTermsOfService(t, ss) }) + t.Run("TestGetLatestTermsOfService", func(t *testing.T) { testGetLatestTermsOfService(t, ss) }) + t.Run("TestGetTermsOfService", func(t *testing.T) { testGetTermsOfService(t, ss) }) +} + +func testSaveTermsOfService(t *testing.T, ss store.Store) { + u1 := model.User{} + u1.Username = model.NewId() + u1.Email = MakeEmail() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(&u1)) + + termsOfService := &model.TermsOfService{Text: "terms of service", UserId: u1.Id} + r1 := <-ss.TermsOfService().Save(termsOfService) + + if r1.Err != nil { + t.Fatal(r1.Err) + } + + savedTermsOfService := r1.Data.(*model.TermsOfService) + if len(savedTermsOfService.Id) != 26 { + t.Fatal("Id should have been populated") + } + + if savedTermsOfService.CreateAt == 0 { + t.Fatal("Create at should have been populated") + } +} + +func testGetLatestTermsOfService(t *testing.T, ss store.Store) { + u1 := model.User{} + u1.Username = model.NewId() + u1.Email = MakeEmail() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(&u1)) + + termsOfService := &model.TermsOfService{Text: "terms of service", UserId: u1.Id} + store.Must(ss.TermsOfService().Save(termsOfService)) + + r1 := <-ss.TermsOfService().GetLatest(true) + if r1.Err != nil { + t.Fatal(r1.Err) + } + + fetchedTermsOfService := r1.Data.(*model.TermsOfService) + assert.Equal(t, termsOfService.Text, fetchedTermsOfService.Text) + assert.Equal(t, termsOfService.UserId, fetchedTermsOfService.UserId) +} + +func testGetTermsOfService(t *testing.T, ss store.Store) { + u1 := model.User{} + u1.Username = model.NewId() + u1.Email = MakeEmail() + u1.Nickname = model.NewId() + store.Must(ss.User().Save(&u1)) + + termsOfService := &model.TermsOfService{Text: "terms of service", UserId: u1.Id} + store.Must(ss.TermsOfService().Save(termsOfService)) + + r1 := <-ss.TermsOfService().Get("an_invalid_id", true) + assert.NotNil(t, r1.Err) + assert.Nil(t, r1.Data) + + r1 = <-ss.TermsOfService().Get(termsOfService.Id, true) + assert.Nil(t, r1.Err) + + receivedTermsOfService := r1.Data.(*model.TermsOfService) + assert.Equal(t, "terms of service", receivedTermsOfService.Text) +} diff --git a/utils/config.go b/utils/config.go index 408598558..a779eef65 100644 --- a/utils/config.go +++ b/utils/config.go @@ -40,9 +40,9 @@ var ( "../../..", } - serviceTermsEnabledAndEmpty = model.NewAppError( + termsOfServiceEnabledAndEmpty = model.NewAppError( "Config.IsValid", - "model.config.is_valid.support.custom_service_terms_text.app_error", + "model.config.is_valid.support.custom_terms_of_service_text.app_error", nil, "", http.StatusBadRequest, @@ -482,10 +482,10 @@ func LoadConfig(fileName string) (*model.Config, string, map[string]interface{}, config.SetDefaults() - // Don't treat it as an error right now if custom service terms are enabled but text is empty. - // This is because service terms text will be fetched from database at a later state, but + // Don't treat it as an error right now if custom terms of service are enabled but text is empty. + // This is because terms of service text will be fetched from database at a later state, but // the flag indicating it is enabled is fetched from config file right away. - if err := config.IsValid(); err != nil && err.Id != serviceTermsEnabledAndEmpty.Id { + if err := config.IsValid(); err != nil && err.Id != termsOfServiceEnabledAndEmpty.Id { return nil, "", nil, err } @@ -703,7 +703,7 @@ func GenerateClientConfig(c *model.Config, diagnosticId string, license *model.L } if *license.Features.CustomTermsOfService { - props["EnableCustomServiceTerms"] = strconv.FormatBool(*c.SupportSettings.CustomServiceTermsEnabled) + props["EnableCustomTermsOfService"] = strconv.FormatBool(*c.SupportSettings.CustomTermsOfServiceEnabled) } } -- cgit v1.2.3-1-g7c22