unit tests for profile comment visibility
This commit is contained in:
parent
eeb932bd4b
commit
5bfc5e3e40
|
@ -66,8 +66,8 @@ type User struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserPrivacy struct {
|
type UserPrivacy struct {
|
||||||
ShowComments int // 0 = default, 1 = public, 2 = registered, 3 = friends, 4 = mods / self
|
ShowComments int // 0 = default, 1 = public, 2 = registered, 3 = friends, 4 = self, 5 = disabled / unused
|
||||||
AllowMessage int // 0 = default, 1 = registered, 2 = friends, 3 = mods / self
|
AllowMessage int // 0 = default, 1 = registered, 2 = friends, 3 = mods, 4 = disabled / unused
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) WebSockets() *WsJSONUser {
|
func (u *User) WebSockets() *WsJSONUser {
|
||||||
|
@ -569,7 +569,6 @@ var ErrProfileCommentsOutOfBounds = errors.New("profile_comments must be an inte
|
||||||
var ErrEnableEmbedsOutOfBounds = errors.New("enable_embeds must be -1, 0 or 1")
|
var ErrEnableEmbedsOutOfBounds = errors.New("enable_embeds must be -1, 0 or 1")
|
||||||
|
|
||||||
/*func (u *User) UpdatePrivacyS(sProfileComments, sEnableEmbeds string) error {
|
/*func (u *User) UpdatePrivacyS(sProfileComments, sEnableEmbeds string) error {
|
||||||
|
|
||||||
return u.UpdatePrivacy(profileComments, enableEmbeds)
|
return u.UpdatePrivacy(profileComments, enableEmbeds)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
@ -723,6 +722,43 @@ func (u *User) InitPerms() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Write tests
|
||||||
|
// TODO: Implement and use this
|
||||||
|
// TODO: Implement friends
|
||||||
|
func PrivacyAllowMessage(pu, u *User) (canMsg bool) {
|
||||||
|
switch pu.Privacy.AllowMessage {
|
||||||
|
case 4: // Unused
|
||||||
|
canMsg = false
|
||||||
|
case 3: // mods
|
||||||
|
canMsg = u.IsSuperMod
|
||||||
|
//case 2: // friends
|
||||||
|
case 1: // registered
|
||||||
|
canMsg = true
|
||||||
|
default: // 0
|
||||||
|
canMsg = true
|
||||||
|
}
|
||||||
|
return canMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement friend system
|
||||||
|
func PrivacyCommentsShow(pu, u *User) (showComments bool) {
|
||||||
|
switch pu.Privacy.ShowComments {
|
||||||
|
case 5: // Unused
|
||||||
|
showComments = false
|
||||||
|
case 4: // Self
|
||||||
|
showComments = u.ID == pu.ID
|
||||||
|
case 3: // friends
|
||||||
|
showComments = u.ID == pu.ID
|
||||||
|
case 2: // registered
|
||||||
|
showComments = u.Loggedin
|
||||||
|
case 1: // public
|
||||||
|
showComments = true
|
||||||
|
default: // 0
|
||||||
|
showComments = true
|
||||||
|
}
|
||||||
|
return showComments
|
||||||
|
}
|
||||||
|
|
||||||
var guestAvatar GuestAvatar
|
var guestAvatar GuestAvatar
|
||||||
|
|
||||||
type GuestAvatar struct {
|
type GuestAvatar struct {
|
||||||
|
|
104
misc_test.go
104
misc_test.go
|
@ -2012,7 +2012,7 @@ func TestUtils(t *testing.T) {
|
||||||
eemail := ""
|
eemail := ""
|
||||||
cemail = c.CanonEmail(email)
|
cemail = c.CanonEmail(email)
|
||||||
expect(t, cemail == eemail, fmt.Sprintf("%s should be %s", cemail, eemail))
|
expect(t, cemail == eemail, fmt.Sprintf("%s should be %s", cemail, eemail))
|
||||||
|
|
||||||
email = "ddd"
|
email = "ddd"
|
||||||
eemail = "ddd"
|
eemail = "ddd"
|
||||||
cemail = c.CanonEmail(email)
|
cemail = c.CanonEmail(email)
|
||||||
|
@ -2197,6 +2197,108 @@ func passwordTest(t *testing.T, realPassword, hashedPassword string) {
|
||||||
expect(t, err != nil, "The two shouldn't match!")
|
expect(t, err != nil, "The two shouldn't match!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserPrivacy(t *testing.T) {
|
||||||
|
pu, u := c.BlankUser(), &c.GuestUser
|
||||||
|
pu.ID = 1
|
||||||
|
|
||||||
|
var msg string
|
||||||
|
test := func(expects bool, level int) {
|
||||||
|
pu.Privacy.ShowComments = level
|
||||||
|
val := c.PrivacyCommentsShow(pu, u)
|
||||||
|
var bit string
|
||||||
|
if !expects {
|
||||||
|
bit = " not"
|
||||||
|
val = !val
|
||||||
|
}
|
||||||
|
expect(t, val, fmt.Sprintf("%s should%s be able to see comments on level %d", msg, bit, level))
|
||||||
|
}
|
||||||
|
// 0 = default, 1 = public, 2 = registered, 3 = friends, 4 = self, 5 = disabled
|
||||||
|
|
||||||
|
msg = "guest users"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(false, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
|
||||||
|
u = c.BlankUser()
|
||||||
|
msg = "blank users"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(false, 2)
|
||||||
|
//test(false,3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
|
||||||
|
u.Loggedin = true
|
||||||
|
msg = "registered users"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
|
||||||
|
u.IsBanned = true
|
||||||
|
msg = "banned users"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
u.IsBanned = false
|
||||||
|
|
||||||
|
u.IsMod = true
|
||||||
|
msg = "mods"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
u.IsMod = false
|
||||||
|
|
||||||
|
u.IsSuperMod = true
|
||||||
|
msg = "super mods"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
u.IsSuperMod = false
|
||||||
|
|
||||||
|
u.IsAdmin = true
|
||||||
|
msg = "admins"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
u.IsAdmin = false
|
||||||
|
|
||||||
|
u.IsSuperAdmin = true
|
||||||
|
msg = "super admins"
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(false, 3)
|
||||||
|
test(false, 4)
|
||||||
|
test(false, 5)
|
||||||
|
u.IsSuperAdmin = false
|
||||||
|
|
||||||
|
u.ID = 1
|
||||||
|
test(true, 0)
|
||||||
|
test(true, 1)
|
||||||
|
test(true, 2)
|
||||||
|
test(true, 3)
|
||||||
|
test(true, 4)
|
||||||
|
test(false, 5)
|
||||||
|
}
|
||||||
|
|
||||||
type METri struct {
|
type METri struct {
|
||||||
Name string // Optional, this is here for tests involving invisible characters so we know what's going in
|
Name string // Optional, this is here for tests involving invisible characters so we know what's going in
|
||||||
Msg string
|
Msg string
|
||||||
|
|
|
@ -113,46 +113,14 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Head
|
||||||
|
|
||||||
canMessage := (!blockedInv && user.Perms.UseConvos) || (!blockedInv && puser.IsSuperMod && user.Perms.UseConvosOnlyWithMod) || user.IsSuperMod
|
canMessage := (!blockedInv && user.Perms.UseConvos) || (!blockedInv && puser.IsSuperMod && user.Perms.UseConvosOnlyWithMod) || user.IsSuperMod
|
||||||
canComment := !blockedInv && user.Perms.CreateProfileReply
|
canComment := !blockedInv && user.Perms.CreateProfileReply
|
||||||
showComments := profileCommentsShow(puser, user)
|
showComments := c.PrivacyCommentsShow(puser, user)
|
||||||
if !showComments {
|
if !showComments {
|
||||||
canComment = false
|
canComment = false
|
||||||
}
|
}
|
||||||
if !profileAllowMessage(puser, user) {
|
if !c.PrivacyAllowMessage(puser, user) {
|
||||||
canMessage = false
|
canMessage = false
|
||||||
}
|
}
|
||||||
|
|
||||||
ppage := c.ProfilePage{h, reList, *puser, currentScore, nextScore, blocked, canMessage, canComment, showComments}
|
ppage := c.ProfilePage{h, reList, *puser, currentScore, nextScore, blocked, canMessage, canComment, showComments}
|
||||||
return renderTemplate("profile", w, r, h, ppage)
|
return renderTemplate("profile", w, r, h, ppage)
|
||||||
}
|
}
|
||||||
|
|
||||||
func profileAllowMessage(pu, u *c.User) (canMsg bool) {
|
|
||||||
switch pu.Privacy.AllowMessage {
|
|
||||||
case 4: // Unused
|
|
||||||
canMsg = false
|
|
||||||
case 3: // mods / self
|
|
||||||
canMsg = u.IsSuperMod
|
|
||||||
//case 2: // friends
|
|
||||||
case 1: // registered
|
|
||||||
canMsg = true
|
|
||||||
default: // 0
|
|
||||||
canMsg = true
|
|
||||||
}
|
|
||||||
return canMsg
|
|
||||||
}
|
|
||||||
|
|
||||||
func profileCommentsShow(pu, u *c.User) (showComments bool) {
|
|
||||||
switch pu.Privacy.ShowComments {
|
|
||||||
case 5: // Unused
|
|
||||||
showComments = false
|
|
||||||
case 4: // Self
|
|
||||||
showComments = u.ID == pu.ID
|
|
||||||
//case 3: // friends
|
|
||||||
case 2: // registered
|
|
||||||
showComments = u.Loggedin
|
|
||||||
case 1: // public
|
|
||||||
showComments = true
|
|
||||||
default: // 0
|
|
||||||
showComments = true
|
|
||||||
}
|
|
||||||
return showComments
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,51 +6,51 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
c "github.com/Azareal/Gosora/common"
|
c "github.com/Azareal/Gosora/common"
|
||||||
"github.com/Azareal/Gosora/common/counters"
|
co "github.com/Azareal/Gosora/common/counters"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProfileReplyCreateSubmit(w http.ResponseWriter, r *http.Request, user *c.User) c.RouteError {
|
func ProfileReplyCreateSubmit(w http.ResponseWriter, r *http.Request, u *c.User) c.RouteError {
|
||||||
if !user.Perms.CreateProfileReply {
|
if !u.Perms.CreateProfileReply {
|
||||||
return c.NoPermissions(w, r, user)
|
return c.NoPermissions(w, r, u)
|
||||||
}
|
}
|
||||||
uid, err := strconv.Atoi(r.PostFormValue("uid"))
|
uid, err := strconv.Atoi(r.PostFormValue("uid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalError("Invalid UID", w, r, user)
|
return c.LocalError("Invalid UID", w, r, u)
|
||||||
}
|
}
|
||||||
profileOwner, err := c.Users.Get(uid)
|
profileOwner, err := c.Users.Get(uid)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.LocalError("The profile you're trying to post on doesn't exist.", w, r, user)
|
return c.LocalError("The profile you're trying to post on doesn't exist.", w, r, u)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
blocked, err := c.UserBlocks.IsBlockedBy(profileOwner.ID, user.ID)
|
blocked, err := c.UserBlocks.IsBlockedBy(profileOwner.ID, u.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
// Supermods can bypass blocks so they can tell people off when they do something stupid or have to convey important information
|
// Supermods can bypass blocks so they can tell people off when they do something stupid or have to convey important information
|
||||||
if (blocked || !profileCommentsShow(profileOwner, user)) && !user.IsSuperMod {
|
if (blocked || !c.PrivacyCommentsShow(profileOwner, u)) && !u.IsSuperMod {
|
||||||
return c.LocalError("You don't have permission to send messages to one of these users.", w, r, user)
|
return c.LocalError("You don't have permission to send messages to one of these users.", w, r, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
content := c.PreparseMessage(r.PostFormValue("content"))
|
content := c.PreparseMessage(r.PostFormValue("content"))
|
||||||
if len(content) == 0 {
|
if len(content) == 0 {
|
||||||
return c.LocalError("You can't make a blank post", w, r, user)
|
return c.LocalError("You can't make a blank post", w, r, u)
|
||||||
}
|
}
|
||||||
// TODO: Fully parse the post and store it in the parsed column
|
// TODO: Fully parse the post and store it in the parsed column
|
||||||
prid, err := c.Prstore.Create(profileOwner.ID, content, user.ID, user.GetIP())
|
prid, err := c.Prstore.Create(profileOwner.ID, content, u.ID, u.GetIP())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ! Be careful about leaking per-route permission state with user ptr
|
// ! Be careful about leaking per-route permission state with user ptr
|
||||||
alert := c.Alert{ActorID: user.ID, TargetUserID: profileOwner.ID, Event: "reply", ElementType: "user", ElementID: profileOwner.ID, Actor: user, Extra: strconv.Itoa(prid)}
|
alert := c.Alert{ActorID: u.ID, TargetUserID: profileOwner.ID, Event: "reply", ElementType: "user", ElementID: profileOwner.ID, Actor: u, Extra: strconv.Itoa(prid)}
|
||||||
err = c.AddActivityAndNotifyTarget(alert)
|
err = c.AddActivityAndNotifyTarget(alert)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
counters.PostCounter.Bump()
|
co.PostCounter.Bump()
|
||||||
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
http.Redirect(w, r, "/user/"+strconv.Itoa(uid), http.StatusSeeOther)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ func ProfileReplyEditSubmit(w http.ResponseWriter, r *http.Request, u *c.User, s
|
||||||
return c.InternalError(err, w, r)
|
return c.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
// Supermods can bypass blocks so they can tell people off when they do something stupid or have to convey important information
|
// Supermods can bypass blocks so they can tell people off when they do something stupid or have to convey important information
|
||||||
if (blocked || !profileCommentsShow(profileOwner, u)) && !u.IsSuperMod {
|
if (blocked || !c.PrivacyCommentsShow(profileOwner, u)) && !u.IsSuperMod {
|
||||||
return c.NoPermissionsJSQ(w, r, u, js)
|
return c.NoPermissionsJSQ(w, r, u, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +108,6 @@ func ProfileReplyDeleteSubmit(w http.ResponseWriter, r *http.Request, u *c.User,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, u, js)
|
return c.LocalErrorJSQ("The provided Reply ID is not a valid number.", w, r, u, js)
|
||||||
}
|
}
|
||||||
|
|
||||||
reply, err := c.Prstore.Get(rid)
|
reply, err := c.Prstore.Get(rid)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return c.PreErrorJSQ("The target reply doesn't exist.", w, r, js)
|
return c.PreErrorJSQ("The target reply doesn't exist.", w, r, js)
|
||||||
|
|
Loading…
Reference in New Issue