* #132 added UserTermsOfService model

* #132 added UserTermsOfService model

* #132 added logic to save user TOS data in a new table

* #132 Added logic to save and delete user TOS. Updated user TOS action logic

* #132 updated store mocks

* #132 added tests

* #132 removed cache from UserTermsOfService SQL store

* #132 fixed styling and license check

* #132 added message translations in en.json

* #132 fixed save user TOS logic to work second time as well

* #132 removed User.AcceptedTermsOfService colum and migrated accepted TOS data into new table

* #132 fixed formatting

* #132 fixed formatting

* #146 added field 'mandatory' to terms of service

* #146 updated tests

* #146 added getLatestTermsOfService API

* #146 Added tests

* #146 fixed styling

* #146 removed code for managing mandatory/optional TOS

* #146 Added TOS re-acceptance period config

* #146 fixed styling

* #146 removed some code left for debugging

* #146 added TOS re-acceptance period in config

* #146 fixed a json name from service_terms to terms_of_service

* #146 Minor refactoring and added TOS re-acceptance period to diagnistics

* Fixed style

* Updated upgraded script to keep app backward compatible
Этот коммит содержится в:
Harshil Sharma
2018-11-09 02:18:14 +05:30
коммит произвёл Jesse Hallam
родитель c52e808e34
Коммит 0c5f60f89b
31 изменённых файлов: 653 добавлений и 144 удалений

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

@@ -401,7 +401,7 @@ func (c *Client4) GetRedirectLocationRoute() string {
return fmt.Sprintf("/redirect_location")
}
func (c *Client4) GetRegisterTermsOfServiceRoute(userId string) string {
func (c *Client4) GetUserTermsOfServiceRoute(userId string) string {
return c.GetUserRoute(userId) + "/terms_of_service"
}
@@ -3849,7 +3849,7 @@ func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response)
}
func (c *Client4) RegisteTermsOfServiceAction(userId, termsOfServiceId string, accepted bool) (*bool, *Response) {
url := c.GetRegisterTermsOfServiceRoute(userId)
url := c.GetUserTermsOfServiceRoute(userId)
data := map[string]interface{}{"termsOfServiceId": termsOfServiceId, "accepted": accepted}
if r, err := c.DoApiPost(url, StringInterfaceToJson(data)); err != nil {
@@ -3871,11 +3871,22 @@ func (c *Client4) GetTermsOfService(etag string) (*TermsOfService, *Response) {
}
}
func (c *Client4) GetUserTermsOfService(userId, etag string) (*UserTermsOfService, *Response) {
url := c.GetUserTermsOfServiceRoute(userId)
if r, err := c.DoApiGet(url, etag); err != nil {
return nil, BuildErrorResponse(r, err)
} else {
defer closeBody(r)
return UserTermsOfServiceFromJson(r.Body), BuildResponse(r)
}
}
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 {
data := map[string]interface{}{"text": text}
if r, err := c.DoApiPost(url, StringInterfaceToJson(data)); err != nil {
return nil, BuildErrorResponse(r, err)
} else {
defer closeBody(r)

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

@@ -112,6 +112,7 @@ const (
SUPPORT_SETTINGS_DEFAULT_HELP_LINK = "https://about.mattermost.com/default-help/"
SUPPORT_SETTINGS_DEFAULT_REPORT_A_PROBLEM_LINK = "https://about.mattermost.com/default-report-a-problem/"
SUPPORT_SETTINGS_DEFAULT_SUPPORT_EMAIL = "feedback@mattermost.com"
SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD = 365
LDAP_SETTINGS_DEFAULT_FIRST_NAME_ATTRIBUTE = ""
LDAP_SETTINGS_DEFAULT_LAST_NAME_ATTRIBUTE = ""
@@ -1030,13 +1031,14 @@ type PrivacySettings struct {
}
type SupportSettings struct {
TermsOfServiceLink *string
PrivacyPolicyLink *string
AboutLink *string
HelpLink *string
ReportAProblemLink *string
SupportEmail *string
CustomTermsOfServiceEnabled *bool
TermsOfServiceLink *string
PrivacyPolicyLink *string
AboutLink *string
HelpLink *string
ReportAProblemLink *string
SupportEmail *string
CustomTermsOfServiceEnabled *bool
CustomTermsOfServiceReAcceptancePeriod *int
}
func (s *SupportSettings) SetDefaults() {
@@ -1087,6 +1089,10 @@ func (s *SupportSettings) SetDefaults() {
if s.CustomTermsOfServiceEnabled == nil {
s.CustomTermsOfServiceEnabled = NewBool(false)
}
if s.CustomTermsOfServiceReAcceptancePeriod == nil {
s.CustomTermsOfServiceReAcceptancePeriod = NewInt(SUPPORT_SETTINGS_DEFAULT_RE_ACCEPTANCE_PERIOD)
}
}
type AnnouncementSettings struct {

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

@@ -11,7 +11,6 @@ import (
"unicode/utf8"
)
// we only ever need the latest version of terms of service
const TERMS_OF_SERVICE_CACHE_SIZE = 1
type TermsOfService struct {
@@ -58,7 +57,7 @@ func InvalidTermsOfServiceError(fieldName string, termsOfServiceId string) *AppE
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)
return NewAppError("TermsOfService.IsValid", id, map[string]interface{}{"MaxLength": POST_MESSAGE_MAX_RUNES_V2}, details, http.StatusBadRequest)
}
func (t *TermsOfService) PreSave() {

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

@@ -50,33 +50,32 @@ 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"`
AcceptedTermsOfServiceId string `json:"accepted_terms_of_service_id,omitempty"` // TODO remove this field when new TOS user action table is created
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"`
}
type UserPatch struct {

46
model/user_terms_of_Service_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,46 @@
// 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 TestUserTermsOfServiceIsValid(t *testing.T) {
s := UserTermsOfService{}
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.TermsOfServiceId = 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 valid")
}
}
func TestUserTermsOfServiceJson(t *testing.T) {
o := UserTermsOfService{
UserId: NewId(),
TermsOfServiceId: NewId(),
CreateAt: GetMillis(),
}
j := o.ToJson()
ro := UserTermsOfServiceFromJson(strings.NewReader(j))
assert.NotNil(t, ro)
assert.Equal(t, o, *ro)
}

61
model/user_terms_of_service.go Обычный файл
Просмотреть файл

@@ -0,0 +1,61 @@
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type UserTermsOfService struct {
UserId string `json:"user_id"`
TermsOfServiceId string `json:"terms_of_service_id"`
CreateAt int64 `json:"create_at"`
}
func (ut *UserTermsOfService) IsValid() *AppError {
if len(ut.UserId) != 26 {
return InvalidUserTermsOfServiceError("user_id", ut.UserId)
}
if len(ut.TermsOfServiceId) != 26 {
return InvalidUserTermsOfServiceError("terms_of_service_id", ut.UserId)
}
if ut.CreateAt == 0 {
return InvalidUserTermsOfServiceError("create_at", ut.UserId)
}
return nil
}
func (ut *UserTermsOfService) ToJson() string {
b, _ := json.Marshal(ut)
return string(b)
}
func (ut *UserTermsOfService) PreSave() {
if ut.UserId == "" {
ut.UserId = NewId()
}
ut.CreateAt = GetMillis()
}
func UserTermsOfServiceFromJson(data io.Reader) *UserTermsOfService {
var userTermsOfService *UserTermsOfService
json.NewDecoder(data).Decode(&userTermsOfService)
return userTermsOfService
}
func InvalidUserTermsOfServiceError(fieldName string, userTermsOfServiceId string) *AppError {
id := fmt.Sprintf("model.user_terms_of_service.is_valid.%s.app_error", fieldName)
details := ""
if userTermsOfServiceId != "" {
details = "user_terms_of_service_user_id=" + userTermsOfServiceId
}
return NewAppError("UserTermsOfService.IsValid", id, nil, details, http.StatusBadRequest)
}