Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/minekube/gate/llms.txt

Use this file to discover all available pages before exploring further.

Command Permissions

Gate’s permission system allows you to control who can execute commands and access features.

Permission Interface

The permission.Subject interface is implemented by command sources:
type Subject interface {
    HasPermission(permission string) bool
}
Source: pkg/util/permission/permission.go

Basic Permission Checks

In Command Requirements

Add permission checks when registering commands:
cmdManager.Register(brigodier.Literal("admin").
    Requires(command.Requires(func(c *command.RequiresContext) bool {
        return c.Source.HasPermission("gate.admin")
    })).
    Executes(command.Command(func(c *command.Context) error {
        return c.Source.SendMessage(&component.Text{
            Content: "Admin command executed",
        })
    })),
)
Source: pkg/command/command.go:70-78

In Command Execution

Check permissions during command execution:
Executes(command.Command(func(c *command.Context) error {
    if !c.Source.HasPermission("myplugin.kick") {
        return c.Source.SendMessage(&component.Text{
            Content: "You don't have permission to use this command",
            S: component.Style{Color: color.Red},
        })
    }
    
    // Command logic
    return nil
}))

Permission Levels

Organize permissions hierarchically:
// Basic user permissions
"gate.command.server"        // Use /server
"gate.command.glist"         // Use /glist

// Moderator permissions
"gate.mod.kick"              // Kick players
"gate.mod.mute"              // Mute players

// Admin permissions
"gate.admin.reload"          // Reload config
"gate.admin.shutdown"        // Stop proxy
"gate.admin.*"               // All admin permissions

Built-in Command Permissions

Gate’s built-in commands use these permissions:
CommandPermissionConfigurable
/servergate.command.serverYes
/glistgate.command.glistYes
/sendgate.command.sendYes
Enable permission checks for built-in commands with:
requireBuiltinCommandPermissions: true
in config.yml

Permission Checks for Players

Check permissions on player objects:
player := proxy.Player("username")

if player.HasPermission("myplugin.vip") {
    // Give VIP benefits
}

Console vs Players

Different sources have different permission behavior:
Executes(command.Command(func(c *command.Context) error {
    // Console has all permissions by default
    if _, isPlayer := c.Source.(proxy.Player); !isPlayer {
        // Source is console
        // Console can execute any command
    } else {
        // Source is player - check permissions
        if !c.Source.HasPermission("admin.command") {
            return errors.New("insufficient permissions")
        }
    }
    
    return nil
}))

Implementing Permission Providers

Gate doesn’t include a permission management system by default. Implement your own:

Simple File-based Permissions

type PermissionManager struct {
    permissions map[string][]string // username -> permissions
}

func (pm *PermissionManager) HasPermission(username, permission string) bool {
    perms, ok := pm.permissions[username]
    if !ok {
        return false
    }
    
    for _, perm := range perms {
        if perm == permission || perm == "*" {
            return true
        }
        
        // Check wildcard permissions
        if strings.HasSuffix(perm, ".*") {
            prefix := strings.TrimSuffix(perm, ".*")
            if strings.HasPrefix(permission, prefix+".") {
                return true
            }
        }
    }
    
    return false
}

Integrating with Players

Wrap player objects to add permission checking:
type PlayerWithPermissions struct {
    proxy.Player
    permManager *PermissionManager
}

func (p *PlayerWithPermissions) HasPermission(permission string) bool {
    return p.permManager.HasPermission(p.Username(), permission)
}

External Permission Plugins

Integrate with permission plugins on backend servers:

LuckPerms Integration

Query LuckPerms via plugin messages:
// Send permission check request
req := map[string]interface{}{
    "id": "check-perm",
    "player": player.UUID(),
    "permission": "myplugin.admin",
}

data, _ := json.Marshal(req)
player.SendPluginMessage("luckperms:api", data)

// Listen for response
eventMgr.Subscribe(&proxy.PluginMessageEvent{}, 0, 
    func(e *proxy.PluginMessageEvent) {
        if e.Identifier == "luckperms:api" {
            var resp map[string]interface{}
            json.Unmarshal(e.Data, &resp)
            
            if resp["id"] == "check-perm" {
                hasPermission := resp["result"].(bool)
                // Use permission result
            }
        }
    },
)

Dynamic Permissions

Grant temporary permissions:
type TemporaryPermission struct {
    permission string
    expiresAt  time.Time
}

type PermissionManager struct {
    temporary map[string][]TemporaryPermission
}

func (pm *PermissionManager) GrantTemporary(username, permission string, duration time.Duration) {
    pm.temporary[username] = append(pm.temporary[username], TemporaryPermission{
        permission: permission,
        expiresAt:  time.Now().Add(duration),
    })
}

func (pm *PermissionManager) HasPermission(username, permission string) bool {
    // Check temporary permissions
    if temps, ok := pm.temporary[username]; ok {
        for _, temp := range temps {
            if time.Now().Before(temp.expiresAt) && temp.permission == permission {
                return true
            }
        }
    }
    
    // Check permanent permissions
    // ...
}

Best Practices

Use a consistent naming scheme:
  • plugin.category.action format
  • All lowercase with dots as separators
  • Specific to general: gate.admin.kick not kick.admin.gate
Examples:
  • myplugin.command.teleport
  • myplugin.admin.reload
  • myplugin.feature.fly
Support wildcard permissions for convenience:
  • myplugin.* - All plugin permissions
  • myplugin.admin.* - All admin permissions
  • * - All permissions (superadmin)
But be careful with wildcards in production!
Some permissions should be granted by default:
func (pm *PermissionManager) HasPermission(username, permission string) bool {
    // Default permissions for all players
    defaultPerms := []string{
        "gate.command.server",
        "gate.command.glist",
    }
    
    for _, perm := range defaultPerms {
        if perm == permission {
            return true
        }
    }
    
    // Check other permissions
    // ...
}
Always grant console full permissions:
if c.Source == proxy.ConsoleCommandSource {
    return true // Console has all permissions
}

Next Steps

Command Examples

See complete command with permissions

Event System

Learn about Gate’s event system