public_ban.gno

2.81 Kb ยท 116 lines
  1package boards2
  2
  3import (
  4	"std"
  5	"strings"
  6	"time"
  7
  8	"gno.land/p/nt/avl"
  9)
 10
 11// Constants for different banning periods.
 12const (
 13	BanDay  = uint(24)
 14	BanWeek = BanDay * 7
 15	BanYear = BanDay * 365
 16)
 17
 18// Ban bans a user from a board for a period of time.
 19// Only invited guest members and external users can be banned.
 20// Banning board owners, admins and moderators is not allowed.
 21func Ban(_ realm, boardID BoardID, user std.Address, hours uint, reason string) {
 22	assertAddressIsValid(user)
 23
 24	if hours == 0 {
 25		panic("ban period in hours is required")
 26	}
 27
 28	reason = strings.TrimSpace(reason)
 29	if reason == "" {
 30		panic("ban reason is required")
 31	}
 32
 33	board := mustGetBoard(boardID)
 34	caller := std.PreviousRealm().Address()
 35	until := time.Now().Add(time.Minute * 60 * time.Duration(hours))
 36	args := Args{boardID, user, until, reason}
 37	board.perms.WithPermission(cross, caller, PermissionUserBan, args, func(realm, Args) {
 38		// When banning invited members make sure they are guests, otherwise
 39		// disallow banning. Only guest or external users can be banned.
 40		board := mustGetBoard(boardID)
 41		if board.perms.HasUser(user) && !board.perms.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 = avl.NewTree()
 48			gBannedUsers.Set(boardID.Key(), banned)
 49		}
 50
 51		banned.Set(user.String(), until)
 52
 53		std.Emit(
 54			"UserBanned",
 55			"bannedBy", caller.String(),
 56			"boardID", boardID.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(_ realm, boardID BoardID, user std.Address, reason string) {
 66	assertAddressIsValid(user)
 67
 68	board := mustGetBoard(boardID)
 69	caller := std.PreviousRealm().Address()
 70	args := Args{boardID, user, reason}
 71	board.perms.WithPermission(cross, caller, PermissionUserUnban, args, func(realm, Args) {
 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		std.Emit(
 80			"UserUnbanned",
 81			"bannedBy", caller.String(),
 82			"boardID", boardID.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 BoardID, user std.Address) bool {
 91	banned, found := getBannedUsers(boardID)
 92	return found && banned.Has(user.String())
 93}
 94
 95func assertAddressIsValid(addr std.Address) {
 96	if !addr.IsValid() {
 97		panic("invalid address: " + addr.String())
 98	}
 99}
100
101func assertUserIsNotBanned(boardID BoardID, user std.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}