Returned User TermsOfService Data in Certain GetUser APIs To Be Used on Webapp for Decicion Making (#10478)

* Used user TOS data embedded in user object itself

* #MI-372 Added user TOS data in getUserByUsername API and updated tests

* #MI-372 returned user TOS data only for admin or self

* #MI-372 fixed tests

* #MI-372 added user ID checks in a missing place
Этот коммит содержится в:
Harshil Sharma
2019-03-27 18:31:35 +05:30
коммит произвёл Hanzei
родитель f17de7929b
Коммит f84be43937
3 изменённых файлов: 185 добавлений и 28 удалений

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

@@ -119,6 +119,19 @@ func getUser(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if c.IsSystemAdmin() || c.App.Session.UserId == user.Id {
userTermsOfService, err := c.App.GetUserTermsOfService(user.Id)
if err != nil && err.StatusCode != http.StatusNotFound {
c.Err = err
return
}
if userTermsOfService != nil {
user.TermsOfServiceId = userTermsOfService.TermsOfServiceId
user.TermsOfServiceCreateAt = userTermsOfService.CreateAt
}
}
etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress) etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress)
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {
@@ -149,6 +162,19 @@ func getUserByUsername(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
if c.IsSystemAdmin() || c.App.Session.UserId == user.Id {
userTermsOfService, err := c.App.GetUserTermsOfService(user.Id)
if err != nil && err.StatusCode != http.StatusNotFound {
c.Err = err
return
}
if userTermsOfService != nil {
user.TermsOfServiceId = userTermsOfService.TermsOfServiceId
user.TermsOfServiceCreateAt = userTermsOfService.CreateAt
}
}
etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress) etag := user.Etag(*c.App.Config().PrivacySettings.ShowFullName, *c.App.Config().PrivacySettings.ShowEmailAddress)
if c.HandleEtag(etag, "Get User", w, r) { if c.HandleEtag(etag, "Get User", w, r) {

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

@@ -417,6 +417,105 @@ func TestGetUser(t *testing.T) {
} }
} }
func TestGetUserWithAcceptedTermsOfServiceForOtherUser(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
user := th.CreateUser()
tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
th.App.UpdateUser(user, false)
ruser, resp := th.Client.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
assert.Empty(t, ruser.TermsOfServiceId)
th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
ruser, resp = th.Client.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
// user TOS data cannot be fetched for other users by non-admin users
assert.Empty(t, ruser.TermsOfServiceId)
}
func TestGetUserWithAcceptedTermsOfService(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
user := th.BasicUser
tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
ruser, resp := th.Client.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
assert.Empty(t, ruser.TermsOfServiceId)
th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
ruser, resp = th.Client.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
// a user can view their own TOS details
assert.Equal(t, tos.Id, ruser.TermsOfServiceId)
}
func TestGetUserWithAcceptedTermsOfServiceWithAdminUser(t *testing.T) {
th := Setup().InitBasic()
th.LoginSystemAdmin()
defer th.TearDown()
user := th.BasicUser
tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
ruser, resp := th.SystemAdminClient.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
assert.Empty(t, ruser.TermsOfServiceId)
th.App.SaveUserTermsOfService(user.Id, tos.Id, true)
ruser, resp = th.SystemAdminClient.GetUser(user.Id, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
// admin can view anyone's TOS details
assert.Equal(t, tos.Id, ruser.TermsOfServiceId)
}
func TestGetBotUser(t *testing.T) { func TestGetBotUser(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
defer th.TearDown() defer th.TearDown()
@@ -501,6 +600,36 @@ func TestGetUserByUsername(t *testing.T) {
} }
} }
func TestGetUserByUsernameWithAcceptedTermsOfService(t *testing.T) {
th := Setup().InitBasic()
defer th.TearDown()
user := th.BasicUser
ruser, resp := th.Client.GetUserByUsername(user.Username, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
tos, _ := th.App.CreateTermsOfService("Dummy TOS", user.Id)
th.App.SaveUserTermsOfService(ruser.Id, tos.Id, true)
ruser, resp = th.Client.GetUserByUsername(user.Username, "")
CheckNoError(t, resp)
CheckUserSanitization(t, ruser)
if ruser.Email != user.Email {
t.Fatal("emails did not match")
}
if ruser.TermsOfServiceId != tos.Id {
t.Fatal("Terms of service ID didn't match")
}
}
func TestGetUserByEmail(t *testing.T) { func TestGetUserByEmail(t *testing.T) {
th := Setup().InitBasic() th := Setup().InitBasic()
defer th.TearDown() defer th.TearDown()

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

@@ -81,6 +81,8 @@ type User struct {
MfaSecret string `json:"mfa_secret,omitempty"` MfaSecret string `json:"mfa_secret,omitempty"`
LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"` LastActivityAt int64 `db:"-" json:"last_activity_at,omitempty"`
IsBot bool `db:"-" json:"is_bot,omitempty"` IsBot bool `db:"-" json:"is_bot,omitempty"`
TermsOfServiceId string `db:"-" json:"terms_of_service_id,omitempty"`
TermsOfServiceCreateAt int64 `db:"-" json:"terms_of_service_create_at,omitempty"`
} }
type UserPatch struct { type UserPatch struct {
@@ -372,7 +374,7 @@ func (u *UserAuth) ToJson() string {
// Generate a valid strong etag so the browser can cache the results // Generate a valid strong etag so the browser can cache the results
func (u *User) Etag(showFullName, showEmail bool) string { func (u *User) Etag(showFullName, showEmail bool) string {
return Etag(u.Id, u.UpdateAt, showFullName, showEmail) return Etag(u.Id, u.UpdateAt, u.TermsOfServiceId, u.TermsOfServiceCreateAt, showFullName, showEmail)
} }
// Remove any private data from the user object // Remove any private data from the user object