Search Apps Documentation Source Content File Folder Download Copy Actions Download

public_ban.gno

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