Search Apps Documentation Source Content File Folder Download Copy Actions Download

public_ban.gno

2.81 Kb · 116 lines
  1package boards2
  2
  3import (
  4	"chain"
  5	"strings"
  6	"time"
  7
  8	"gno.land/p/gnoland/boards"
  9	"gno.land/p/nt/bptree/v0"
 10)
 11
 12// Constants for different banning periods.
 13const (
 14	BanDay  = uint(24)
 15	BanWeek = BanDay * 7
 16	BanYear = BanDay * 365
 17)
 18
 19// Ban bans a user from a board for a period of time.
 20// Only invited guest members and external users can be banned.
 21// Banning board owners, admins and moderators is not allowed.
 22func Ban(cur realm, boardID boards.ID, user address, hours uint, reason string) {
 23	assertAddressIsValid(user)
 24
 25	if hours == 0 {
 26		panic("ban period in hours is required")
 27	}
 28
 29	reason = strings.TrimSpace(reason)
 30	if reason == "" {
 31		panic("ban reason is required")
 32	}
 33
 34	board := mustGetBoard(boardID)
 35	caller := cur.Previous().Address()
 36	until := time.Now().Add(time.Minute * 60 * time.Duration(hours))
 37	args := boards.Args{boardID, user, until, reason}
 38	board.Permissions.WithPermission(caller, PermissionUserBan, args, func() {
 39		// When banning invited members make sure they are guests, otherwise
 40		// disallow banning. Only guest or external users can be banned.
 41		if board.Permissions.HasUser(user) && !board.Permissions.HasRole(user, RoleGuest) {
 42			panic("owner, admin and moderator banning is not allowed")
 43		}
 44
 45		banned, found := getBannedUsers(boardID)
 46		if !found {
 47			banned = bptree.NewBPTree32()
 48			gBannedUsers.Set(boardID.Key(), banned)
 49		}
 50
 51		banned.Set(user.String(), until)
 52
 53		chain.Emit(
 54			"UserBanned",
 55			"bannedBy", caller.String(),
 56			"boardID", board.ID.String(),
 57			"user", user.String(),
 58			"until", until.Format(time.RFC3339),
 59			"reason", reason,
 60		)
 61	})
 62}
 63
 64// Unban unbans a user from a board.
 65func Unban(cur realm, boardID boards.ID, user address, reason string) {
 66	assertAddressIsValid(user)
 67
 68	board := mustGetBoard(boardID)
 69	caller := cur.Previous().Address()
 70	args := boards.Args{boardID, user, reason}
 71	board.Permissions.WithPermission(caller, PermissionUserUnban, args, func() {
 72		banned, found := getBannedUsers(boardID)
 73		if !found || !banned.Has(user.String()) {
 74			panic("user is not banned")
 75		}
 76
 77		banned.Remove(user.String())
 78
 79		chain.Emit(
 80			"UserUnbanned",
 81			"bannedBy", caller.String(),
 82			"boardID", board.ID.String(),
 83			"user", user.String(),
 84			"reason", reason,
 85		)
 86	})
 87}
 88
 89// IsBanned checks if a user is banned from a board.
 90func IsBanned(boardID boards.ID, user address) bool {
 91	banned, found := getBannedUsers(boardID)
 92	return found && banned.Has(user.String())
 93}
 94
 95func assertAddressIsValid(addr address) {
 96	if !addr.IsValid() {
 97		panic("invalid address: " + addr.String())
 98	}
 99}
100
101func assertUserIsNotBanned(boardID boards.ID, user address) {
102	banned, found := getBannedUsers(boardID)
103	if !found {
104		return
105	}
106
107	v, found := banned.Get(user.String())
108	if !found {
109		return
110	}
111
112	until := v.(time.Time)
113	if time.Now().Before(until) {
114		panic(user.String() + " is banned until " + until.Format(dateFormat))
115	}
116}