public_flag.gno
3.71 Kb ยท 140 lines
1package boards2
2
3import (
4 "chain"
5 "chain/runtime"
6 "strconv"
7
8 "gno.land/p/gnoland/boards"
9
10 "gno.land/r/gnoland/boards2/v1/permissions"
11)
12
13// SetFlaggingThreshold sets the number of flags required to hide a thread or comment.
14//
15// Threshold is only applicable within the board where it's setted.
16func SetFlaggingThreshold(_ realm, boardID boards.ID, threshold int) {
17 if threshold < 1 {
18 panic("invalid flagging threshold")
19 }
20
21 assertRealmIsNotLocked()
22
23 board := mustGetBoard(boardID)
24 assertBoardIsNotFrozen(board)
25
26 caller := runtime.PreviousRealm().Address()
27 args := boards.Args{board.ID, threshold}
28 board.Permissions.WithPermission(cross, caller, permissions.PermissionBoardFlaggingUpdate, args, func(realm) {
29 assertRealmIsNotLocked()
30
31 gFlaggingThresholds.Set(boardID.String(), threshold)
32
33 chain.Emit(
34 "FlaggingThresholdUpdated",
35 "caller", caller.String(),
36 "boardID", board.ID.String(),
37 "threshold", strconv.Itoa(threshold),
38 )
39 })
40}
41
42// GetFlaggingThreshold returns the number of flags required to hide a thread or comment within a board.
43func GetFlaggingThreshold(boardID boards.ID) int {
44 assertBoardExists(boardID)
45 return getFlaggingThreshold(boardID)
46}
47
48// FlagThread adds a new flag to a thread.
49//
50// Flagging requires special permissions and hides the thread when
51// the number of flags reaches a pre-defined flagging threshold.
52func FlagThread(_ realm, boardID, threadID boards.ID, reason string) {
53 caller := runtime.PreviousRealm().Address()
54 board := mustGetBoard(boardID)
55 isRealmOwner := gPerms.HasRole(caller, permissions.RoleOwner)
56 if !isRealmOwner {
57 assertRealmIsNotLocked()
58 assertBoardIsNotFrozen(board)
59 }
60
61 thread, found := board.Threads.Get(threadID)
62 if !found {
63 panic("thread not found")
64 }
65
66 assertThreadIsNotFrozen(thread)
67
68 flagThread := func() {
69 hide := flagItem(thread, caller, reason, getFlaggingThreshold(board.ID))
70 if hide || isRealmOwner {
71 // Realm owners can hide with a single flag
72 thread.Hidden = true
73 }
74
75 chain.Emit(
76 "ThreadFlagged",
77 "caller", caller.String(),
78 "boardID", board.ID.String(),
79 "threadID", thread.ID.String(),
80 "reason", reason,
81 )
82 }
83
84 // Realm owners should be able to flag without permissions even when board is frozen
85 if isRealmOwner {
86 flagThread()
87 return
88 }
89
90 args := boards.Args{caller, board.ID, thread.ID, reason}
91 board.Permissions.WithPermission(cross, caller, permissions.PermissionThreadFlag, args, func(realm) {
92 flagThread()
93 })
94}
95
96// FlagReply adds a new flag to a comment or reply.
97//
98// Flagging requires special permissions and hides the comment or reply
99// when the number of flags reaches a pre-defined flagging threshold.
100func FlagReply(_ realm, boardID, threadID, replyID boards.ID, reason string) {
101 caller := runtime.PreviousRealm().Address()
102 board := mustGetBoard(boardID)
103 isRealmOwner := gPerms.HasRole(caller, permissions.RoleOwner)
104 if !isRealmOwner {
105 assertRealmIsNotLocked()
106 assertBoardIsNotFrozen(board)
107 }
108
109 thread := mustGetThread(board, threadID)
110 assertThreadIsNotFrozen(thread)
111
112 reply := mustGetReply(thread, replyID)
113 flagReply := func() {
114 hide := flagItem(reply, caller, reason, getFlaggingThreshold(board.ID))
115 if hide || isRealmOwner {
116 // Realm owners can hide with a single flag
117 reply.Hidden = true
118 }
119
120 chain.Emit(
121 "ReplyFlagged",
122 "caller", caller.String(),
123 "boardID", board.ID.String(),
124 "threadID", thread.ID.String(),
125 "replyID", reply.ID.String(),
126 "reason", reason,
127 )
128 }
129
130 // Realm owners should be able to flag without permissions even when board is frozen
131 if isRealmOwner {
132 flagReply()
133 return
134 }
135
136 args := boards.Args{caller, board.ID, thread.ID, reply.ID, reason}
137 board.Permissions.WithPermission(cross, caller, permissions.PermissionReplyFlag, args, func(realm) {
138 flagReply()
139 })
140}