Skip to content

Permissions in future library versions #1969

@akiraveliara

Description

@akiraveliara

Currently, DSharpPlus models permissions as bitfield enum with 64 bits. Discord documents permissions as unbounded-length integers, and as we are approaching the 64-bit limit (at the time of writing, we are at 50 permissions), we will need to change how we handle permissions.

Permissions will be refactored into a DiscordPermission enum containing all individual permissions, and a DiscordPermissions/DiscordPermissionSet struct storing all these permissions. Additionally, serialization will be changed to tolerate permissions being too long, so as to ensure Discord rolling over any future threshold will not render all previous builds of the library unusable.

Proposed API Surface

-[Flags]
-public enum DiscordPermissions;
+public enum DiscordPermission;
public struct DiscordPermissions
{
    public DiscordPermissions(DiscordPermission);
    public DiscordPermissions(params ReadOnlySpan<DiscordPermission>);
    public DiscordPermissions(BigInteger);
    public DiscordPermissions(scoped ReadOnlySpan<byte>);

    public static implicit operator DiscordPermissions(DiscordPermission);

    public bool HasFlag(DiscordPermission);
    public bool HasPermission(DiscordPermission); // factors in admin
    public bool HasAnyPermission(params ReadOnlySpan<DiscordPermission>);
    public bool HasAllPermissions(params ReadOnlySpan<DiscordPermission>);
    public DiscordPermissions Toggle(DiscordPermission); // toggles the value of the field on or off
    public DiscordPermissions Toggle(params ReadOnlySpan<DiscordPermission>); // toggles the value of the fields on or off
    
    public static bool operator ==(DiscordPermissions, DiscordPermissions);
    public static bool operator !=(DiscordPermissions, DiscordPermissions);
    
    public DiscordPermissions Add(DiscordPermission);
    public DiscordPermissions Add(params ReadOnlySpan<DiscordPermission>);
    public static DiscordPermissions operator +(DiscordPermissions, DiscordPermission);
    
    public DiscordPermissions Remove(DiscordPermission);
    public DiscordPermissions Remove(params ReadOnlySpan<DiscordPermission>);
    public static DiscordPermissions operator -(DiscordPermissions, DiscordPermission);
    public static DiscordPermissions operator -(DiscordPermissions, DiscordPermissions);
    
    public static DiscordPermissions operator &(DiscordPermissions, DiscordPermissions);
    public static DiscordPermissions operator &(DiscordPermissions, DiscordPermission);
    public static DiscordPermissions operator |(DiscordPermissions, DiscordPermissions);
    public static DiscordPermissions operator |(DiscordPermissions, DiscordPermission);
    public static DiscordPermissions operator ^(DiscordPermissions, DiscordPermissions);
    public static DiscordPermissions operator ^(DiscordPermissions, DiscordPermission);
    public static DiscordPermissions operator ~(DiscordPermissions);
}

Let us know on the issue or on Discord if this doesn't meet your expectation, and if you wish to discuss the details of the backing implementation, our discussion channel is found here.

Plan of Action

  • Relax v4 serialization to permit longer permissions. This does not imply changing the permission model in v4 or changing how many permissions v4 can represent.
  • Implement the new design in v5 and v6 (v6 can serve as experimenting ground and to explore using newer runtime/language features v5 cannot yet use)
  • Migrate all existing API surface interacting with permissions
    • This especially concerns DiscordChannel.PermissionsFor(DiscordMember) and DiscordMember.PermissionsIn(DiscordChannel), which work with overwrites. We might want to consider designing these entirely separately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions