func (k Keeper) UnbanUserInSubspace(ctx sdk.Context, subspaceID, user, admin string) error {
	err := k.checkSubspaceAdmin(ctx, subspaceID, admin)
	if err != nil {
		return err
	}
	if !k.IsBanned(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "the user is not blocked inside the subspace")
	}
	store := ctx.KVStore(k.storeKey)
	store.Delete(types.SubspaceBannedUserKey(subspaceID, user))
	return nil
}
UnbanUserInSubspace unbans the given user inside the subspace with the given ID.
It returns error if the user is not banned inside the subspace or the subspace does not exist.
package keeper
import (
	"github.com/cosmos/cosmos-sdk/codec"
	sdk "github.com/cosmos/cosmos-sdk/types"
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
	"github.com/tendermint/tendermint/libs/log"
	"github.com/desmos-labs/desmos/v2/x/staging/subspaces/types"
)
type Keeper struct {
	storeKey sdk.StoreKey
	cdc      codec.BinaryCodec
}
func NewKeeper(storeKey sdk.StoreKey, cdc codec.BinaryCodec) Keeper {
	return Keeper{
		storeKey: storeKey,
		cdc:      cdc,
	}
}
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
	return ctx.Logger().With("module", "x/"+types.ModuleName)
}
func (k Keeper) SaveSubspace(ctx sdk.Context, subspace types.Subspace, user string) error {
	err := subspace.Validate()
	if err != nil {
		return err
	}
	storedSubspace, found := k.GetSubspace(ctx, subspace.ID)
	if found && storedSubspace.Owner != user {
		return sdkerrors.Wrapf(types.ErrInvalidSubspaceOwner, user)
	}
	store := ctx.KVStore(k.storeKey)
	key := types.SubspaceStoreKey(subspace.ID)
	store.Set(key, k.cdc.MustMarshal(&subspace))
	k.Logger(ctx).Info("saved subspace", "id", subspace.ID, "owner", subspace.Owner)
	return nil
}
func (k Keeper) DoesSubspaceExist(ctx sdk.Context, subspaceID string) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.SubspaceStoreKey(subspaceID))
}
func (k Keeper) GetSubspace(ctx sdk.Context, subspaceID string) (subspace types.Subspace, found bool) {
	if !k.DoesSubspaceExist(ctx, subspaceID) {
		return types.Subspace{}, false
	}
	store := ctx.KVStore(k.storeKey)
	k.cdc.MustUnmarshal(store.Get(types.SubspaceStoreKey(subspaceID)), &subspace)
	return subspace, true
}
func (k Keeper) IsAdmin(ctx sdk.Context, subspaceID string, user string) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.SubspaceAdminKey(subspaceID, user))
}
func (k Keeper) AddAdminToSubspace(ctx sdk.Context, subspaceID, user, owner string) error {
	err := k.checkSubspaceOwner(ctx, subspaceID, owner)
	if err != nil {
		return err
	}
	if k.IsAdmin(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "the user with address %s is already an admin", user)
	}
	store := ctx.KVStore(k.storeKey)
	store.Set(types.SubspaceAdminKey(subspaceID, user), []byte(user))
	k.Logger(ctx).Info("added admin", "subspace-id", subspaceID, "admin", user)
	return nil
}
func (k Keeper) RemoveAdminFromSubspace(ctx sdk.Context, subspaceID, user, owner string) error {
	err := k.checkSubspaceOwner(ctx, subspaceID, owner)
	if err != nil {
		return err
	}
	if !k.IsAdmin(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(types.ErrInvalidSubspaceAdmin, user)
	}
	store := ctx.KVStore(k.storeKey)
	store.Delete(types.SubspaceAdminKey(subspaceID, user))
	k.Logger(ctx).Info("removed admin", "subspace-id", subspaceID, "admin", user)
	return nil
}
func (k Keeper) IsRegistered(ctx sdk.Context, subspaceID, user string) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.SubspaceRegisteredUserKey(subspaceID, user))
}
func (k Keeper) RegisterUserInSubspace(ctx sdk.Context, subspaceID, user, admin string) error {
	err := k.checkSubspaceAdmin(ctx, subspaceID, admin)
	if err != nil {
		return err
	}
	if k.IsRegistered(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "user already registered")
	}
	store := ctx.KVStore(k.storeKey)
	store.Set(types.SubspaceRegisteredUserKey(subspaceID, user), []byte(user))
	return nil
}
func (k Keeper) UnregisterUserFromSubspace(ctx sdk.Context, subspaceID, user, admin string) error {
	err := k.checkSubspaceAdmin(ctx, subspaceID, admin)
	if err != nil {
		return err
	}
	if !k.IsRegistered(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest,
			"the user with address : %s is not registered inside the subspace: %s", user, subspaceID)
	}
	store := ctx.KVStore(k.storeKey)
	store.Delete(types.SubspaceRegisteredUserKey(subspaceID, user))
	return nil
}
func (k Keeper) IsBanned(ctx sdk.Context, subspaceID, user string) bool {
	store := ctx.KVStore(k.storeKey)
	return store.Has(types.SubspaceBannedUserKey(subspaceID, user))
}
func (k Keeper) BanUserInSubspace(ctx sdk.Context, subspaceID, user, admin string) error {
	err := k.checkSubspaceAdmin(ctx, subspaceID, admin)
	if err != nil {
		return err
	}
	if k.IsBanned(ctx, subspaceID, user) {
		return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "user already banned")
	}
	store := ctx.KVStore(k.storeKey)
	store.Set(types.SubspaceBannedUserKey(subspaceID, user), []byte(user))
	return nil
}