From 64a18259c320dd9c03d78523d9ba3133ce4226b5 Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 00:51:28 -0500 Subject: [PATCH 1/9] feat(boards2): add core flagging logic --- examples/gno.land/r/demo/boards2/flag.gno | 47 +++++++++++++++++++ .../gno.land/r/demo/boards2/permission.gno | 2 + examples/gno.land/r/demo/boards2/post.gno | 32 +++++++++++-- examples/gno.land/r/demo/boards2/public.gno | 28 +++++++++++ 4 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 examples/gno.land/r/demo/boards2/flag.gno diff --git a/examples/gno.land/r/demo/boards2/flag.gno b/examples/gno.land/r/demo/boards2/flag.gno new file mode 100644 index 00000000000..46a9cdada2d --- /dev/null +++ b/examples/gno.land/r/demo/boards2/flag.gno @@ -0,0 +1,47 @@ +package boards2 + +import ( + "std" + "strconv" +) + +var flagThreshold = 3 + +type Flag struct { + User std.Address + Reason string +} + +func NewFlag(creator std.Address, reason string) Flag { + return Flag{ + User: creator, + Reason: reason, + } +} + +type Flaggable interface { + // AddFlag adds a new flag to an entry. + // + // Returns false if item was already flagged by user. + AddFlag(flag Flag) bool + + // FlagsCount returns number of times entry was flagged. + FlagsCount() int +} + +// flagItem adds a flag to a flaggable item (post, thread, etc). +// +// Returns whether flag count threshold is reached and item can be hidden. +// +// Panics if flag count threshold was already reached. +func flagItem(item Flaggable, flag Flag) bool { + if item.FlagsCount() >= flagThreshold { + panic("item flag count threshold exceeded: " + strconv.Itoa(flagThreshold)) + } + + if !item.AddFlag(flag) { + panic("item has been already flagged by a user") + } + + return item.FlagsCount() == flagThreshold +} diff --git a/examples/gno.land/r/demo/boards2/permission.gno b/examples/gno.land/r/demo/boards2/permission.gno index d287b4f8e8b..e465e346418 100644 --- a/examples/gno.land/r/demo/boards2/permission.gno +++ b/examples/gno.land/r/demo/boards2/permission.gno @@ -7,8 +7,10 @@ const ( PermissionThreadCreate = "thread:create" PermissionThreadEdit = "thread:edit" PermissionThreadDelete = "thread:delete" + PermissionThreadFlag = "thread:flag" PermissionThreadRepost = "thread:repost" PermissionReplyDelete = "reply:delete" + PermissionReplyFlag = "reply:flag" PermissionMemberInvite = "member:invite" PermissionMemberRemove = "member:remove" ) diff --git a/examples/gno.land/r/demo/boards2/post.gno b/examples/gno.land/r/demo/boards2/post.gno index 7364b985c84..27ca884c19f 100644 --- a/examples/gno.land/r/demo/boards2/post.gno +++ b/examples/gno.land/r/demo/boards2/post.gno @@ -30,12 +30,14 @@ type Post struct { creator std.Address title string // optional body string + isHidden bool replies avl.Tree // Post.id -> *Post repliesAll avl.Tree // Post.id -> *Post (all replies, for top-level posts) reposts avl.Tree // Board.id -> Post.id - threadID PostID // original Post.id - parentID PostID // parent Post.id (if reply or repost) - repostBoardID BoardID // original Board.id (if repost) + flags []Flag + threadID PostID // original Post.id + parentID PostID // parent Post.id (if reply or repost) + repostBoardID BoardID // original Board.id (if repost) createdAt time.Time updatedAt time.Time } @@ -97,6 +99,30 @@ func (post *Post) GetUpdatedAt() time.Time { return post.updatedAt } +func (post *Post) AddFlag(flag Flag) bool { + // TODO: sort flags for fast search in case of big thresholds + for _, v := range post.flags { + if v.User == flag.User { + return false + } + } + + post.flags = append(post.flags, flag) + return true +} + +func (post *Post) FlagsCount() int { + return len(post.flags) +} + +func (post *Post) SetVisibility(isVisible bool) { + post.isHidden = !isVisible +} + +func (post *Post) Hidden() bool { + return post.isHidden +} + func (post *Post) AddReply(creator std.Address, body string) *Post { board := post.board pid := board.incGetPostID() diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index 083f8daff65..e4a5fb70e8e 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -36,6 +36,21 @@ func CreateBoard(name string) BoardID { return id } +func FlagThread(bid BoardID, postID PostID, reason string) { + caller := std.GetOrigCaller() + assertHasPermission(caller, PermissionThreadFlag) + + board := mustGetBoard(bid) + t, ok := board.GetThread(postID) + if !ok { + panic("post doesn't exist") + } + + if flagItem(t, NewFlag(caller, reason)) { + t.SetVisibility(false) + } +} + func CreateThread(bid BoardID, title, body string) PostID { assertIsUserCall() @@ -72,6 +87,19 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { return reply.id } +func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { + caller := std.GetOrigCaller() + assertHasPermission(caller, PermissionThreadFlag) + + board := mustGetBoard(bid) + thread := mustGetThread(board, threadID) + reply := mustGetReply(thread, replyID) + + if flagItem(reply, NewFlag(caller, reason)) { + reply.SetVisibility(false) + } +} + func CreateRepost(bid BoardID, threadID PostID, title, body string, dstBoardID BoardID) PostID { assertIsUserCall() From 661edc26cdaaaa0715b2b36090161d0be5ad0d5b Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 15:13:56 -0500 Subject: [PATCH 2/9] fix: address @jeronimoalbi review --- examples/gno.land/r/demo/boards2/flag.gno | 6 +++--- examples/gno.land/r/demo/boards2/public.gno | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/flag.gno b/examples/gno.land/r/demo/boards2/flag.gno index 46a9cdada2d..aa4ef00b0cd 100644 --- a/examples/gno.land/r/demo/boards2/flag.gno +++ b/examples/gno.land/r/demo/boards2/flag.gno @@ -20,12 +20,12 @@ func NewFlag(creator std.Address, reason string) Flag { } type Flaggable interface { - // AddFlag adds a new flag to an entry. + // AddFlag adds a new flag to an item. // // Returns false if item was already flagged by user. AddFlag(flag Flag) bool - // FlagsCount returns number of times entry was flagged. + // FlagsCount returns number of times item was flagged. FlagsCount() int } @@ -40,7 +40,7 @@ func flagItem(item Flaggable, flag Flag) bool { } if !item.AddFlag(flag) { - panic("item has been already flagged by a user") + panic("item has been already flagged by a current user") } return item.FlagsCount() == flagThreshold diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index e4a5fb70e8e..f18734c24ab 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -38,6 +38,7 @@ func CreateBoard(name string) BoardID { func FlagThread(bid BoardID, postID PostID, reason string) { caller := std.GetOrigCaller() + // TODO: Replace by assertHasBoardPermission() when supported assertHasPermission(caller, PermissionThreadFlag) board := mustGetBoard(bid) @@ -89,6 +90,7 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { caller := std.GetOrigCaller() + // TODO: Replace by assertHasBoardPermission() when supported assertHasPermission(caller, PermissionThreadFlag) board := mustGetBoard(bid) From 22718596ec0862eee800d9eca7b19874ff32fb08 Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 15:15:50 -0500 Subject: [PATCH 3/9] fix: SetVisible --- examples/gno.land/r/demo/boards2/post.gno | 2 +- examples/gno.land/r/demo/boards2/public.gno | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/post.gno b/examples/gno.land/r/demo/boards2/post.gno index 27ca884c19f..012269e11d1 100644 --- a/examples/gno.land/r/demo/boards2/post.gno +++ b/examples/gno.land/r/demo/boards2/post.gno @@ -115,7 +115,7 @@ func (post *Post) FlagsCount() int { return len(post.flags) } -func (post *Post) SetVisibility(isVisible bool) { +func (post *Post) SetVisible(isVisible bool) { post.isHidden = !isVisible } diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index f18734c24ab..385ff4d524b 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -48,7 +48,7 @@ func FlagThread(bid BoardID, postID PostID, reason string) { } if flagItem(t, NewFlag(caller, reason)) { - t.SetVisibility(false) + t.SetVisible(false) } } @@ -98,7 +98,7 @@ func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { reply := mustGetReply(thread, replyID) if flagItem(reply, NewFlag(caller, reason)) { - reply.SetVisibility(false) + reply.SetVisible(false) } } From b5ed08d86b835ce978fe14e1649d12f3344b194d Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 16:52:46 -0500 Subject: [PATCH 4/9] feat: add tests and hide hidden posts --- examples/gno.land/r/demo/boards2/board.gno | 7 ++++++- examples/gno.land/r/demo/boards2/post.gno | 12 ++++++++++- .../gno.land/r/demo/boards2/post_test.gno | 21 +++++++++++++++++++ examples/gno.land/r/demo/boards2/render.gno | 8 +++++-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/board.gno b/examples/gno.land/r/demo/boards2/board.gno index 1920cd41225..8b667cb291e 100644 --- a/examples/gno.land/r/demo/boards2/board.gno +++ b/examples/gno.land/r/demo/boards2/board.gno @@ -100,8 +100,13 @@ func (board *Board) Render() string { s := "\\[" + newLink("post", board.GetPostFormURL()) + "]\n\n" if board.threads.Size() > 0 { board.threads.Iterate("", "", func(_ string, v interface{}) bool { + post := v.(*Post) + if post.isHidden { + return false + } + s += "----------------------------------------\n" - s += v.(*Post).RenderSummary() + "\n" + s += post.RenderSummary() + "\n" return false }) } diff --git a/examples/gno.land/r/demo/boards2/post.gno b/examples/gno.land/r/demo/boards2/post.gno index 012269e11d1..2df46a57e84 100644 --- a/examples/gno.land/r/demo/boards2/post.gno +++ b/examples/gno.land/r/demo/boards2/post.gno @@ -245,6 +245,11 @@ func (post *Post) RenderSummary() string { if !found { return "reposted post does not exist" } + + if thread.isHidden { + return "reposted post was hidden" + } + return "Repost: " + post.GetSummary() + "\n" + thread.RenderSummary() } @@ -293,8 +298,13 @@ func (post *Post) Render(indent string, levels int) string { if levels > 0 { if post.replies.Size() > 0 { post.replies.Iterate("", "", func(_ string, value interface{}) bool { + reply := value.(*Post) + if reply.isHidden { + return false + } + s += indent + "\n" - s += value.(*Post).Render(indent+"> ", levels-1) + s += reply.Render(indent+"> ", levels-1) return false }) } diff --git a/examples/gno.land/r/demo/boards2/post_test.gno b/examples/gno.land/r/demo/boards2/post_test.gno index 05888f9e297..bab7f3de93b 100644 --- a/examples/gno.land/r/demo/boards2/post_test.gno +++ b/examples/gno.land/r/demo/boards2/post_test.gno @@ -23,6 +23,27 @@ func TestPostUpdate(t *testing.T) { uassert.False(t, post.GetUpdatedAt().IsZero()) } +func TestPostAddFlag(t *testing.T) { + addr := testutils.TestAddress("creator") + post := createTestThread(t) + + flag := NewFlag(addr, "foobar") + uassert.True(t, post.AddFlag(flag)) + uassert.False(t, post.AddFlag(flag), "should reject flag from duplicate user") + uassert.Equal(t, post.FlagsCount(), 1) +} + +func TestPostSetVisible(t *testing.T) { + post := createTestThread(t) + uassert.False(t, post.Hidden(), "post should be visible by default") + + post.SetVisible(false) + uassert.True(t, post.Hidden(), "post should be hidden") + + post.SetVisible(true) + uassert.False(t, post.Hidden(), "post should be visible") +} + func TestPostAddRepostTo(t *testing.T) { cases := []struct { name, title, body string diff --git a/examples/gno.land/r/demo/boards2/render.gno b/examples/gno.land/r/demo/boards2/render.gno index 02e7fda9e81..a2074aae94c 100644 --- a/examples/gno.land/r/demo/boards2/render.gno +++ b/examples/gno.land/r/demo/boards2/render.gno @@ -59,7 +59,9 @@ func renderThread(res *mux.ResponseWriter, req *mux.Request) { board := v.(*Board) thread, found := board.GetThread(PostID(tID)) if !found { - res.Write("Thread does not exist with ID: " + req.GetVar("thread")) + res.Write("Thread does not exist with ID: " + rawID) + } else if thread.Hidden() { + res.Write("Thread with ID: " + rawID + " was hidden") } else { res.Write(thread.Render("", 5)) } @@ -96,7 +98,9 @@ func renderReply(res *mux.ResponseWriter, req *mux.Request) { reply, found := thread.GetReply(PostID(rID)) if !found { - res.Write("Reply does not exist with ID: " + req.GetVar("reply")) + res.Write("Reply does not exist with ID: " + rawID) + } else if reply.Hidden() { + res.Write("Reply with ID: " + rawID + " was hidden") } else { res.Write(reply.RenderInner()) } From d459fa8b321e58024db2889c9257da5271952563 Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 17:30:24 -0500 Subject: [PATCH 5/9] feat: add e2e tests --- examples/gno.land/r/demo/boards2/flag.gno | 2 +- examples/gno.land/r/demo/boards2/public.gno | 11 +++++++- .../r/demo/boards2/z_2_a_filetest.gno | 23 ++++++++++++++++ .../r/demo/boards2/z_2_b_filetest.gno | 26 +++++++++++++++++++ .../r/demo/boards2/z_2_c_filetest.gno | 26 +++++++++++++++++++ 5 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 examples/gno.land/r/demo/boards2/z_2_a_filetest.gno create mode 100644 examples/gno.land/r/demo/boards2/z_2_b_filetest.gno create mode 100644 examples/gno.land/r/demo/boards2/z_2_c_filetest.gno diff --git a/examples/gno.land/r/demo/boards2/flag.gno b/examples/gno.land/r/demo/boards2/flag.gno index aa4ef00b0cd..e5744211ddf 100644 --- a/examples/gno.land/r/demo/boards2/flag.gno +++ b/examples/gno.land/r/demo/boards2/flag.gno @@ -5,7 +5,7 @@ import ( "strconv" ) -var flagThreshold = 3 +const flagThreshold = 1 type Flag struct { User std.Address diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index 385ff4d524b..804bb4c12e6 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -73,9 +73,10 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { board := mustGetBoard(bid) thread := mustGetThread(board, threadID) + assertThreadVisible(thread) + // TODO: Assert thread is not locked // TODO: Assert that caller is a board member (when board type is invite only) - var reply *Post if replyID == threadID { // When the parent reply is the thread just add reply to thread @@ -83,6 +84,8 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { } else { // Try to get parent reply and add a new child reply post := mustGetReply(thread, replyID) + assertThreadVisible(thread) + reply = post.AddReply(caller, body) } return reply.id @@ -246,3 +249,9 @@ func assertReplyExists(thread *Post, replyID PostID) { panic("reply not found: " + replyID.String()) } } + +func assertThreadVisible(thread *Post) { + if thread.Hidden() { + panic("thread with ID: " + thread.GetPostID().String() + " was hidden") + } +} diff --git a/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno new file mode 100644 index 00000000000..626438d0c0a --- /dev/null +++ b/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno @@ -0,0 +1,23 @@ +package main + +import ( + "std" + + "gno.land/r/demo/boards2" +) + +const owner = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // @test1 + +func init() { + std.TestSetOrigCaller(owner) +} + +func main() { + bid := boards2.CreateBoard("test1") + pid := boards2.CreateThread(bid, "thread", "thread") + boards2.FlagThread(bid, pid, "reason") + rid := boards2.CreateReply(bid, pid, pid, "reply") +} + +// Error: +// thread with ID: 1 was hidden diff --git a/examples/gno.land/r/demo/boards2/z_2_b_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_b_filetest.gno new file mode 100644 index 00000000000..a4f4d403c8c --- /dev/null +++ b/examples/gno.land/r/demo/boards2/z_2_b_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "std" + + "gno.land/r/demo/boards2" +) + +const owner = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // @test1 + +func init() { + std.TestSetOrigCaller(owner) +} + +func main() { + // ensure that nested replies denied if root thread is hidden. + bid := boards2.CreateBoard("test1") + pid := boards2.CreateThread(bid, "thread", "thread") + rid := boards2.CreateReply(bid, pid, pid, "reply1") + + boards2.FlagThread(bid, pid, "reason") + _ = boards2.CreateReply(bid, pid, rid, "reply1.1") +} + +// Error: +// thread with ID: 1 was hidden diff --git a/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno new file mode 100644 index 00000000000..c5ef6a5e6ed --- /dev/null +++ b/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno @@ -0,0 +1,26 @@ +package main + +import ( + "std" + + "gno.land/r/demo/boards2" +) + +const owner = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // @test1 + +func init() { + std.TestSetOrigCaller(owner) +} + +func main() { + // ensure that nested replies denied if root thread is hidden. + bid := boards2.CreateBoard("test1") + pid := boards2.CreateThread(bid, "thread", "thread") + rid := boards2.CreateReply(bid, pid, pid, "reply1") + + boards2.FlagReply(bid, pid, rid, "reason") + _ = boards2.CreateReply(bid, pid, rid, "reply1.1") +} + +// Error: +// thread with ID: 2 was hidden From f48a46dcff428cdd5f814c50ba912227c6f5d0ea Mon Sep 17 00:00:00 2001 From: x1unix Date: Thu, 19 Dec 2024 17:36:22 -0500 Subject: [PATCH 6/9] feat: add flag threshold test --- .../r/demo/boards2/z_2_a_filetest.gno | 2 +- .../r/demo/boards2/z_2_d_filetest.gno | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 examples/gno.land/r/demo/boards2/z_2_d_filetest.gno diff --git a/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno index 626438d0c0a..d95759e4236 100644 --- a/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno +++ b/examples/gno.land/r/demo/boards2/z_2_a_filetest.gno @@ -16,7 +16,7 @@ func main() { bid := boards2.CreateBoard("test1") pid := boards2.CreateThread(bid, "thread", "thread") boards2.FlagThread(bid, pid, "reason") - rid := boards2.CreateReply(bid, pid, pid, "reply") + _ = boards2.CreateReply(bid, pid, pid, "reply") } // Error: diff --git a/examples/gno.land/r/demo/boards2/z_2_d_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_d_filetest.gno new file mode 100644 index 00000000000..dbd809c84cd --- /dev/null +++ b/examples/gno.land/r/demo/boards2/z_2_d_filetest.gno @@ -0,0 +1,25 @@ +package main + +import ( + "std" + + "gno.land/r/demo/boards2" +) + +const owner = std.Address("g1jg8mtutu9khhfwc4nxmuhcpftf0pajdhfvsqf5") // @test1 + +func init() { + std.TestSetOrigCaller(owner) +} + +func main() { + // Only single user per flag can't be tested atm, as flagThreshold = 1. + bid := boards2.CreateBoard("test1") + pid := boards2.CreateThread(bid, "thread", "thread") + + boards2.FlagThread(bid, pid, "reason1") + boards2.FlagThread(bid, pid, "reason2") +} + +// Error: +// item flag count threshold exceeded: 1 From 0bfe07916c3fd7246c0d256c21e812d150657d9f Mon Sep 17 00:00:00 2001 From: x1unix Date: Mon, 23 Dec 2024 12:59:50 -0500 Subject: [PATCH 7/9] feat: use per-board permissions --- examples/gno.land/r/demo/boards2/public.gno | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index 804bb4c12e6..d987cf8b4d0 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -38,10 +38,9 @@ func CreateBoard(name string) BoardID { func FlagThread(bid BoardID, postID PostID, reason string) { caller := std.GetOrigCaller() - // TODO: Replace by assertHasBoardPermission() when supported - assertHasPermission(caller, PermissionThreadFlag) - board := mustGetBoard(bid) + assertHasBoardOrGlobalPermission(board, caller, PermissionThreadFlag) + t, ok := board.GetThread(postID) if !ok { panic("post doesn't exist") @@ -93,10 +92,10 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { caller := std.GetOrigCaller() - // TODO: Replace by assertHasBoardPermission() when supported - assertHasPermission(caller, PermissionThreadFlag) board := mustGetBoard(bid) + assertHasBoardOrGlobalPermission(board, caller, PermissionThreadFlag) + thread := mustGetThread(board, threadID) reply := mustGetReply(thread, replyID) @@ -232,6 +231,14 @@ func assertHasBoardPermission(b *Board, user std.Address, p Permission) { } } +func assertHasBoardOrGlobalPermission(b *Board, user std.Address, p Permission) { + if b.perms.HasPermission(user, p) || gPerm.HasPermission(user, p) { + return + } + + panic("unauthorized") +} + func assertBoardExists(id BoardID) { if _, found := getBoard(id); !found { panic("board not found: " + id.String()) From 2506936fd48355b8bf3580f82cd445b8b9231403 Mon Sep 17 00:00:00 2001 From: x1unix Date: Mon, 23 Dec 2024 13:34:09 -0500 Subject: [PATCH 8/9] feat: dont use global perm --- examples/gno.land/r/demo/boards2/public.gno | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index d987cf8b4d0..afc69257430 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -39,7 +39,7 @@ func CreateBoard(name string) BoardID { func FlagThread(bid BoardID, postID PostID, reason string) { caller := std.GetOrigCaller() board := mustGetBoard(bid) - assertHasBoardOrGlobalPermission(board, caller, PermissionThreadFlag) + assertHasBoardPermission(board, caller, PermissionThreadFlag) t, ok := board.GetThread(postID) if !ok { @@ -94,7 +94,7 @@ func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { caller := std.GetOrigCaller() board := mustGetBoard(bid) - assertHasBoardOrGlobalPermission(board, caller, PermissionThreadFlag) + assertHasBoardPermission(board, caller, PermissionThreadFlag) thread := mustGetThread(board, threadID) reply := mustGetReply(thread, replyID) @@ -231,14 +231,6 @@ func assertHasBoardPermission(b *Board, user std.Address, p Permission) { } } -func assertHasBoardOrGlobalPermission(b *Board, user std.Address, p Permission) { - if b.perms.HasPermission(user, p) || gPerm.HasPermission(user, p) { - return - } - - panic("unauthorized") -} - func assertBoardExists(id BoardID) { if _, found := getBoard(id); !found { panic("board not found: " + id.String()) From a3e31889e412d51f3d695fced684a187501aa067 Mon Sep 17 00:00:00 2001 From: x1unix Date: Mon, 6 Jan 2025 13:54:13 -0500 Subject: [PATCH 9/9] chore: address jeronimoalbi complaints --- examples/gno.land/r/demo/boards2/post.gno | 3 ++- examples/gno.land/r/demo/boards2/post_test.gno | 6 +++--- examples/gno.land/r/demo/boards2/public.gno | 12 +++++++++--- examples/gno.land/r/demo/boards2/render.gno | 6 +++--- examples/gno.land/r/demo/boards2/z_2_c_filetest.gno | 2 +- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/examples/gno.land/r/demo/boards2/post.gno b/examples/gno.land/r/demo/boards2/post.gno index 2df46a57e84..5a79302af22 100644 --- a/examples/gno.land/r/demo/boards2/post.gno +++ b/examples/gno.land/r/demo/boards2/post.gno @@ -119,7 +119,7 @@ func (post *Post) SetVisible(isVisible bool) { post.isHidden = !isVisible } -func (post *Post) Hidden() bool { +func (post *Post) IsHidden() bool { return post.isHidden } @@ -300,6 +300,7 @@ func (post *Post) Render(indent string, levels int) string { post.replies.Iterate("", "", func(_ string, value interface{}) bool { reply := value.(*Post) if reply.isHidden { + // TODO: change this in case of pagination return false } diff --git a/examples/gno.land/r/demo/boards2/post_test.gno b/examples/gno.land/r/demo/boards2/post_test.gno index bab7f3de93b..232b4ea75cd 100644 --- a/examples/gno.land/r/demo/boards2/post_test.gno +++ b/examples/gno.land/r/demo/boards2/post_test.gno @@ -35,13 +35,13 @@ func TestPostAddFlag(t *testing.T) { func TestPostSetVisible(t *testing.T) { post := createTestThread(t) - uassert.False(t, post.Hidden(), "post should be visible by default") + uassert.False(t, post.IsHidden(), "post should be visible by default") post.SetVisible(false) - uassert.True(t, post.Hidden(), "post should be hidden") + uassert.True(t, post.IsHidden(), "post should be hidden") post.SetVisible(true) - uassert.False(t, post.Hidden(), "post should be visible") + uassert.False(t, post.IsHidden(), "post should be visible") } func TestPostAddRepostTo(t *testing.T) { diff --git a/examples/gno.land/r/demo/boards2/public.gno b/examples/gno.land/r/demo/boards2/public.gno index afc69257430..62015f9d690 100644 --- a/examples/gno.land/r/demo/boards2/public.gno +++ b/examples/gno.land/r/demo/boards2/public.gno @@ -83,7 +83,7 @@ func CreateReply(bid BoardID, threadID, replyID PostID, body string) PostID { } else { // Try to get parent reply and add a new child reply post := mustGetReply(thread, replyID) - assertThreadVisible(thread) + assertReplyVisible(post) reply = post.AddReply(caller, body) } @@ -99,7 +99,7 @@ func FlagReply(bid BoardID, threadID, replyID PostID, reason string) { thread := mustGetThread(board, threadID) reply := mustGetReply(thread, replyID) - if flagItem(reply, NewFlag(caller, reason)) { + if hide := flagItem(reply, NewFlag(caller, reason)); hide { reply.SetVisible(false) } } @@ -250,7 +250,13 @@ func assertReplyExists(thread *Post, replyID PostID) { } func assertThreadVisible(thread *Post) { - if thread.Hidden() { + if thread.IsHidden() { panic("thread with ID: " + thread.GetPostID().String() + " was hidden") } } + +func assertReplyVisible(thread *Post) { + if thread.IsHidden() { + panic("reply with ID: " + thread.GetPostID().String() + " was hidden") + } +} diff --git a/examples/gno.land/r/demo/boards2/render.gno b/examples/gno.land/r/demo/boards2/render.gno index a2074aae94c..ea575bc4fb1 100644 --- a/examples/gno.land/r/demo/boards2/render.gno +++ b/examples/gno.land/r/demo/boards2/render.gno @@ -60,8 +60,8 @@ func renderThread(res *mux.ResponseWriter, req *mux.Request) { thread, found := board.GetThread(PostID(tID)) if !found { res.Write("Thread does not exist with ID: " + rawID) - } else if thread.Hidden() { - res.Write("Thread with ID: " + rawID + " was hidden") + } else if thread.IsHidden() { + res.Write("Thread with ID: " + rawID + " has been flagged as inappropriate") } else { res.Write(thread.Render("", 5)) } @@ -99,7 +99,7 @@ func renderReply(res *mux.ResponseWriter, req *mux.Request) { reply, found := thread.GetReply(PostID(rID)) if !found { res.Write("Reply does not exist with ID: " + rawID) - } else if reply.Hidden() { + } else if reply.IsHidden() { res.Write("Reply with ID: " + rawID + " was hidden") } else { res.Write(reply.RenderInner()) diff --git a/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno b/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno index c5ef6a5e6ed..3a27b4497cd 100644 --- a/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno +++ b/examples/gno.land/r/demo/boards2/z_2_c_filetest.gno @@ -23,4 +23,4 @@ func main() { } // Error: -// thread with ID: 2 was hidden +// reply with ID: 2 was hidden