diff --git a/LabApi/Features/Permissions/PermissionsManager.cs b/LabApi/Features/Permissions/PermissionsManager.cs index fd1d522..0036fe1 100644 --- a/LabApi/Features/Permissions/PermissionsManager.cs +++ b/LabApi/Features/Permissions/PermissionsManager.cs @@ -2,6 +2,7 @@ using LabApi.Features.Wrappers; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; namespace LabApi.Features.Permissions; @@ -31,13 +32,7 @@ public static void RegisterProvider() return; } - if (Activator.CreateInstance() is not IPermissionsProvider provider) - { - Logger.Error($"{LoggerPrefix} Failed to create an instance of the permission provider of type {typeof(T).FullName}."); - return; - } - - PermissionProviders.Add(typeof(T), provider); + PermissionProviders.Add(typeof(T), new T()); } /// @@ -62,13 +57,38 @@ public static void UnregisterProvider() /// The registered of the given type ; otherwise, null. public static IPermissionsProvider? GetProvider() where T : IPermissionsProvider, new() + => GetProvider(typeof(T)); + + /// + /// Retrieves the registered of the given type . + /// + /// The type of the permission provider to retrieve. + /// The registered of the given type ; otherwise, null. + public static bool TryGetProvider([NotNullWhen(true)] out T? provider) + where T : class, IPermissionsProvider, new() { - if (PermissionProviders.TryGetValue(typeof(T), out IPermissionsProvider provider)) + provider = GetProvider(typeof(T)) as T; + return provider != null; + } + + /// + /// Retrieves the registered of the given type . + /// + /// The type of the permission provider to retrieve. + /// The registered of the given type ; otherwise, null. + public static IPermissionsProvider? GetProvider(Type providerType) + { + if (providerType == null) + { + throw new ArgumentNullException(nameof(providerType)); + } + + if (PermissionProviders.TryGetValue(providerType, out IPermissionsProvider provider)) { return provider; } - Logger.Warn($"{LoggerPrefix} The permission provider of type {typeof(T).FullName} is not registered."); + Logger.Warn($"{LoggerPrefix} The permission provider of type {providerType.FullName} is not registered."); return null; } diff --git a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs index bfdac82..ddb6284 100644 --- a/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs +++ b/LabApi/Features/Permissions/Providers/DefaultPermissionsProvider.cs @@ -5,6 +5,7 @@ using Serialization; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -110,9 +111,36 @@ public void RemovePermissions(Player player, params string[] permissions) /// void IPermissionsProvider.ReloadPermissions() => ReloadPermissions(); - private PermissionGroup GetPlayerGroup(Player player) => _permissionsDictionary.GetValueOrDefault(player.PermissionsGroupName ?? "default") ?? PermissionGroup.Default; + /// + /// Gets the the player is a part of. + /// + /// The player whose to find. + /// The the player is a part of, otherwise . + public PermissionGroup GetPlayerGroup(Player player) => GetPermissionGroup(player.PermissionsGroupName ?? "default"); + + /// + /// Gets the from a 's registry name. + /// + /// A 's registry name to find the of. + /// The if one is defined, otherwise. + /// The should be a key in and not necessarily the as they can differ. + public PermissionGroup GetPermissionGroup(string groupName) => _permissionsDictionary.GetValueOrDefault(groupName) ?? PermissionGroup.Default; - private string[] GetPermissions(PermissionGroup group) + /// + /// Tries to get the from a 's registry name. + /// + /// A 's registry name to find the of. + /// The found when true, null otherwise. + /// Whether a with the registry name of was found. + /// The should be a key in and not necessarily the as they can differ. + public bool TryGetPermissionGroup(string groupName, [NotNullWhen(true)] out PermissionGroup? permissionGroup) => _permissionsDictionary.TryGetValue(groupName, out permissionGroup); + + /// + /// Gets the [] of permissions a grants. + /// + /// The , permissions of which will be returned. + /// A array of permission to this group grants. + public string[] GetPermissions(PermissionGroup group) { List permissions = ListPool.Shared.Rent(); @@ -132,6 +160,45 @@ private string[] GetPermissions(PermissionGroup group) return [.. permissions]; } + /// + /// Adds a new permission group or overrides an existing permission group. + /// + /// The registry name of a permission group. + /// The group to add. + /// Whether to override any existing group. + /// Whether the group was successfully added, always true if is true. + /// + /// The is used to get permissions of a player using . + /// The can also be obtained from a 's registry name. + /// WARNING: If used to remove a group which wasn't created at runtime it can cause a change to the file's contents. + /// WARNING: It marks all permission groups as Runtime, and as such when overriding a group it can cause it to be deleted if it was previously obtained from the file. + /// + public bool AddPermissionGroup(string groupName, PermissionGroup group, bool overrideExisting = false) + { + group.IsRuntime = true; + if (overrideExisting) + { + _permissionsDictionary[groupName] = group; + return true; + } + + return _permissionsDictionary.TryAdd(groupName, group); + } + + /// + /// Adds a new permission group or overrides an existing permission group. + /// + /// The registry name of a permission group. + /// The group which was removed or null. + /// Whether the group was found and removed successfully. + /// + /// The is used to get permissions of a player using . + /// The can also be obtained from a 's registry name. + /// WARNING: If used to remove a group which wasn't created at runtime it can cause a change to the file's contents. + /// + public bool RemovePermissionGroup(string groupName, [NotNullWhen(true)] out PermissionGroup? group) + => _permissionsDictionary.Remove(groupName, out group); + private bool HasPermission(PermissionGroup group, string permission) { if (group.IsRoot) @@ -208,5 +275,5 @@ private void ReloadPermissions() } } - private void SavePermissions() => File.WriteAllText(_permissions.FullName, YamlParser.Serializer.Serialize(_permissionsDictionary)); + private void SavePermissions() => File.WriteAllText(_permissions.FullName, YamlParser.Serializer.Serialize(_permissionsDictionary.Where(kvp => !kvp.Value.IsRuntime).ToDictionary(kvp => kvp.Key, kvp => kvp.Value))); } diff --git a/LabApi/Features/Permissions/Providers/PermissionGroup.cs b/LabApi/Features/Permissions/Providers/PermissionGroup.cs index 875e080..2f4ed06 100644 --- a/LabApi/Features/Permissions/Providers/PermissionGroup.cs +++ b/LabApi/Features/Permissions/Providers/PermissionGroup.cs @@ -64,6 +64,12 @@ public PermissionGroup(string[] inheritedGroups, string[] permissions) [YamlIgnore] public bool IsRoot { get; set; } = false; + /// + /// An internal bool indicating whether the permission was created at runtime and as such should not be saved. + /// + [YamlIgnore] + internal bool IsRuntime { get; set; } = false; + /// /// An internal dictionary that saves special permissions. (x.*). ///