public async Task Default
 (
     string permissionName,
     [OverrideTypeReader(typeof(HumanizerEnumTypeReader <PermissionTarget>))]
     PermissionTarget revokedTarget = PermissionTarget.Self
 )
 => await Default(this.Context.User, permissionName, revokedTarget);
Beispiel #2
0
            public async Task <RuntimeResult> Default
            (
                IRole discordRole,
                string permissionName,
                [OverrideTypeReader(typeof(HumanizerEnumTypeReader <PermissionTarget>))]
                PermissionTarget revokedTarget = PermissionTarget.Self
            )
            {
                var getPermissionResult = _permissionRegistry.GetPermission(permissionName);

                if (!getPermissionResult.IsSuccess)
                {
                    return(getPermissionResult.ToRuntimeResult());
                }

                var permission             = getPermissionResult.Entity;
                var revokePermissionResult = await _permissions.RevokePermissionAsync
                                             (
                    discordRole,
                    permission,
                    revokedTarget
                                             );

                if (!revokePermissionResult.IsSuccess)
                {
                    return(revokePermissionResult.ToRuntimeResult());
                }

                return(RuntimeCommandResult.FromSuccess
                       (
                           $"{permission.FriendlyName} revoked from {MentionUtils.MentionRole(discordRole.Id)}."
                       ));
            }
Beispiel #3
0
            public async Task <RuntimeResult> Default
            (
                IUser discordUser,
                string permissionName,
                [OverrideTypeReader(typeof(HumanizerEnumTypeReader <PermissionTarget>))]
                PermissionTarget grantedTarget = PermissionTarget.Self
            )
            {
                var getPermissionResult = _permissionRegistry.GetPermission(permissionName);

                if (!getPermissionResult.IsSuccess)
                {
                    return(getPermissionResult.ToRuntimeResult());
                }

                var permission            = getPermissionResult.Entity;
                var grantPermissionResult = await _permissions.GrantPermissionAsync
                                            (
                    this.Context.Guild,
                    discordUser,
                    permission,
                    grantedTarget
                                            );

                if (!grantPermissionResult.IsSuccess)
                {
                    return(grantPermissionResult.ToRuntimeResult());
                }

                return(RuntimeCommandResult.FromSuccess
                       (
                           $"{permission.FriendlyName} granted to {discordUser.Mention}."
                       ));
            }
Beispiel #4
0
        public async Task <ModifyEntityResult> RevokePermissionAsync
        (
            [NotNull] IRole discordRole,
            [NotNull] IPermission revokedPermission,
            PermissionTarget target
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var revokeSelfResult = await RevokePermissionAsync
                                       (
                    discordRole,
                    revokedPermission,
                    PermissionTarget.Self
                                       );

                var revokeOtherResult = await RevokePermissionAsync
                                        (
                    discordRole,
                    revokedPermission,
                    PermissionTarget.Other
                                        );

                if (revokeSelfResult.IsSuccess || revokeOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(revokeSelfResult));
            }

            var getPermissionResult = await GetOrCreateRolePermissionAsync
                                      (
                discordRole,
                revokedPermission,
                target
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (!permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The role is already prohibited from doing that."));
            }

            permission.IsGranted = false;

            await _database.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess());
        }
Beispiel #5
0
        public async Task <ModifyEntityResult> GrantPermissionAsync
        (
            [NotNull] IRole discordRole,
            [NotNull] IPermission grantedPermission,
            PermissionTarget target
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var grantSelfResult = await GrantPermissionAsync
                                      (
                    discordRole,
                    grantedPermission,
                    PermissionTarget.Self
                                      );

                var grantOtherResult = await GrantPermissionAsync
                                       (
                    discordRole,
                    grantedPermission,
                    PermissionTarget.Other
                                       );

                if (grantSelfResult.IsSuccess || grantOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(grantSelfResult));
            }

            var getPermissionResult = await GetOrCreateRolePermissionAsync
                                      (
                discordRole,
                grantedPermission,
                target
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user already has permission to do that."));
            }

            permission.IsGranted = true;

            await _database.SaveChangesAsync();

            return(ModifyEntityResult.FromSuccess());
        }
Beispiel #6
0
        /// <summary>
        /// Gets an existing user permission, or creates a default one if it does not exist.
        /// </summary>
        /// <param name="discordGuild">The guild the user is in.</param>
        /// <param name="discordUser">The user.</param>
        /// <param name="permission">The permission.</param>
        /// <param name="target">The target.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A retrieval result which may or may not have finished.</returns>
        private async Task <RetrieveEntityResult <UserPermission> > GetOrCreateUserPermissionAsync
        (
            IGuild discordGuild,
            IUser discordUser,
            IPermission permission,
            PermissionTarget target,
            CancellationToken ct = default
        )
        {
            if (target == PermissionTarget.All)
            {
                throw new ArgumentException("Invalid permission target.", nameof(target));
            }

            var userPermissions = await _database.UserPermissions.ServersideQueryAsync
                                  (
                q => q.Where
                (
                    p =>
                    p.ServerID == (long)discordGuild.Id &&
                    p.UserID == (long)discordUser.Id &&
                    p.Permission == permission.UniqueIdentifier &&
                    p.Target == target
                ),
                ct
                                  );

            var userPermission = userPermissions.SingleOrDefault();

            if (!(userPermission is null))
            {
                return(userPermission);
            }

            var newPermission = _database.CreateProxy <UserPermission>
                                (
                (long)discordGuild.Id,
                (long)discordUser.Id,
                permission.UniqueIdentifier,
                target
                                );

            _database.UserPermissions.Update(newPermission);
            newPermission.IsGranted = permission.IsGrantedByDefaultTo(target);

            await _database.SaveChangesAsync(ct);

            return(newPermission);
        }
Beispiel #7
0
        private async Task <RetrieveEntityResult <UserPermission> > GetOrCreateUserPermissionAsync
        (
            [NotNull] IGuild discordGuild,
            [NotNull] IUser discordUser,
            [NotNull] IPermission permission,
            PermissionTarget target
        )
        {
            if (target == PermissionTarget.All)
            {
                throw new ArgumentException("Invalid permission target.", nameof(target));
            }

            var existingPermission = await _database.UserPermissions.FirstOrDefaultAsync
                                     (
                p =>
                p.ServerID == (long)discordGuild.Id &&
                p.UserID == (long)discordUser.Id &&
                p.Permission == permission.UniqueIdentifier &&
                p.Target == target
                                     );

            if (!(existingPermission is null))
            {
                return(RetrieveEntityResult <UserPermission> .FromSuccess(existingPermission));
            }

            var newPermission = new UserPermission
                                (
                (long)discordGuild.Id,
                (long)discordUser.Id,
                permission.UniqueIdentifier,
                target
                                )
            {
                IsGranted = permission.IsGrantedByDefaultTo(target)
            };

            _database.UserPermissions.Update(newPermission);

            await _database.SaveChangesAsync();

            // Requery the database
            return(await GetOrCreateUserPermissionAsync(discordGuild, discordUser, permission, target));
        }
    /// <summary>
    /// Gets an existing role permission, or creates a default one if it does not exist.
    /// </summary>
    /// <param name="discordRole">The role.</param>
    /// <param name="permission">The permission.</param>
    /// <param name="target">The target.</param>
    /// <param name="ct">The cancellation token in use.</param>
    /// <returns>A retrieval result which may or may not have finished.</returns>
    private async Task <Result <RolePermission> > GetOrCreateRolePermissionAsync
    (
        Snowflake discordRole,
        IPermission permission,
        PermissionTarget target,
        CancellationToken ct = default
    )
    {
        if (target == PermissionTarget.All)
        {
            throw new ArgumentException("Invalid permission target.", nameof(target));
        }

        var rolePermissions = await _database.RolePermissions.ServersideQueryAsync
                              (
            q => q
            .Where(p => p.RoleID == discordRole)
            .Where(p => p.Permission == permission.UniqueIdentifier)
            .Where(p => p.Target == target),
            ct
                              );

        var rolePermission = rolePermissions.SingleOrDefault();

        if (rolePermission is not null)
        {
            return(rolePermission);
        }

        var newPermission = _database.CreateProxy <RolePermission>
                            (
            discordRole,
            permission.UniqueIdentifier,
            target
                            );

        _database.RolePermissions.Update(newPermission);
        newPermission.IsGranted = permission.IsGrantedByDefaultTo(target);

        await _database.SaveChangesAsync(ct);

        return(newPermission);
    }
            public async Task Default
            (
                [NotNull] IUser discordUser,
                string permissionName,
                [OverrideTypeReader(typeof(HumanizerEnumTypeReader <PermissionTarget>))]
                PermissionTarget revokedTarget = PermissionTarget.Self
            )
            {
                var getPermissionResult = _permissionRegistry.GetPermission(permissionName);

                if (!getPermissionResult.IsSuccess)
                {
                    await _feedback.SendErrorAsync(this.Context, getPermissionResult.ErrorReason);

                    return;
                }

                var permission             = getPermissionResult.Entity;
                var revokePermissionResult = await _permissions.RevokePermissionAsync
                                             (
                    this.Context.Guild,
                    discordUser,
                    permission,
                    revokedTarget
                                             );

                if (!revokePermissionResult.IsSuccess)
                {
                    await _feedback.SendErrorAsync(this.Context, revokePermissionResult.ErrorReason);

                    return;
                }

                await _feedback.SendConfirmationAsync
                (
                    this.Context,
                    $"{permission.FriendlyName} revoked from {discordUser.Mention}."
                );
            }
            public async Task Default
            (
                [NotNull] IRole discordRole,
                [NotNull] string permissionName,
                [OverrideTypeReader(typeof(HumanizerEnumTypeReader <PermissionTarget>))]
                PermissionTarget grantedTarget = PermissionTarget.Self
            )
            {
                var getPermissionResult = _permissionRegistry.GetPermission(permissionName);

                if (!getPermissionResult.IsSuccess)
                {
                    await _feedback.SendErrorAsync(this.Context, getPermissionResult.ErrorReason);

                    return;
                }

                var permission            = getPermissionResult.Entity;
                var grantPermissionResult = await _permissions.GrantPermissionAsync
                                            (
                    discordRole,
                    permission,
                    grantedTarget
                                            );

                if (!grantPermissionResult.IsSuccess)
                {
                    await _feedback.SendErrorAsync(this.Context, grantPermissionResult.ErrorReason);

                    return;
                }

                await _feedback.SendConfirmationAsync
                (
                    this.Context,
                    $"{permission.FriendlyName} granted to {MentionUtils.MentionRole(discordRole.Id)}."
                );
            }
        /// <summary>
        /// Gets an existing role permission, or creates a default one if it does not exist.
        /// </summary>
        /// <param name="discordRole">The role.</param>
        /// <param name="permission">The permission.</param>
        /// <param name="target">The target.</param>
        /// <returns>A retrieval result which may or may not have finished.</returns>
        private async Task <RetrieveEntityResult <RolePermission> > GetOrCreateRolePermissionAsync
        (
            IRole discordRole,
            IPermission permission,
            PermissionTarget target
        )
        {
            if (target == PermissionTarget.All)
            {
                throw new ArgumentException("Invalid permission target.", nameof(target));
            }

            var existingPermission = await _database.RolePermissions.AsQueryable().FirstOrDefaultAsync
                                     (
                p =>
                p.RoleID == (long)discordRole.Id &&
                p.Permission == permission.UniqueIdentifier &&
                p.Target == target
                                     );

            if (!(existingPermission is null))
            {
                return(RetrieveEntityResult <RolePermission> .FromSuccess(existingPermission));
            }

            var newPermission = new RolePermission((long)discordRole.Id, permission.UniqueIdentifier, target)
            {
                IsGranted = permission.IsGrantedByDefaultTo(target)
            };

            _database.RolePermissions.Update(newPermission);

            await _database.SaveChangesAsync();

            // Requery the database
            return(await GetOrCreateRolePermissionAsync(discordRole, permission, target));
        }
Beispiel #12
0
        public async Task <DetermineConditionResult> HasPermissionAsync
        (
            [NotNull] IGuild discordServer,
            [NotNull] IGuildUser discordUser,
            IPermission requiredPermission,
            PermissionTarget target
        )
        {
            // The server owner always has all permissions by default
            if (discordServer.OwnerId == discordUser.Id)
            {
                return(DetermineConditionResult.FromSuccess());
            }

            // Special handling for the All target
            if (target == PermissionTarget.All)
            {
                var hasSelf = await HasPermissionAsync
                              (
                    discordServer,
                    discordUser,
                    requiredPermission,
                    PermissionTarget.Self
                              );

                var hasOther = await HasPermissionAsync
                               (
                    discordServer,
                    discordUser,
                    requiredPermission,
                    PermissionTarget.Other
                               );

                if (hasSelf.IsSuccess && hasOther.IsSuccess)
                {
                    return(DetermineConditionResult.FromSuccess());
                }

                return(DetermineConditionResult.FromError("Permission denied."));
            }

            var hasPermission = false;

            // Check if the user is part of any roles which this permission applies to
            var rolePermission = await GetApplicableRolePermissions(discordUser)
                                 .FirstOrDefaultAsync
                                 (
                p =>
                p.Permission == requiredPermission.UniqueIdentifier &&
                p.Target == target
                                 );

            if (!(rolePermission is null))
            {
                hasPermission = rolePermission.IsGranted;
            }

            // Check if the user has the permission applied to themselves
            var userPermission = await GetApplicableUserPermissions(discordServer, discordUser)
                                 .FirstOrDefaultAsync
                                 (
                p =>
                p.Permission == requiredPermission.UniqueIdentifier &&
                p.Target == target
                                 );

            if (!(userPermission is null))
            {
                hasPermission = userPermission.IsGranted;
            }

            if (rolePermission is null && userPermission is null)
            {
                // Use the permission's default value
                hasPermission = requiredPermission.IsGrantedByDefaultTo(target);
            }

            if (hasPermission)
            {
                return(DetermineConditionResult.FromSuccess());
            }

            return(DetermineConditionResult.FromError("Permission denied."));
        }
Beispiel #13
0
        /// <summary>
        /// Grants the specified user the given permission.
        /// </summary>
        /// <param name="discordServer">The Discord server the permission was granted on.</param>
        /// <param name="discordUser">The Discord user.</param>
        /// <param name="grantedPermission">The granted permission.</param>
        /// <param name="target">The granted target.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> GrantPermissionAsync
        (
            IGuild discordServer,
            IUser discordUser,
            IPermission grantedPermission,
            PermissionTarget target,
            CancellationToken ct = default
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var grantSelfResult = await GrantPermissionAsync
                                      (
                    discordServer,
                    discordUser,
                    grantedPermission,
                    PermissionTarget.Self,
                    ct
                                      );

                var grantOtherResult = await GrantPermissionAsync
                                       (
                    discordServer,
                    discordUser,
                    grantedPermission,
                    PermissionTarget.Other,
                    ct
                                       );

                if (grantSelfResult.IsSuccess || grantOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the error from the self grant.
                return(ModifyEntityResult.FromError(grantSelfResult));
            }

            var getPermissionResult = await GetOrCreateUserPermissionAsync
                                      (
                discordServer,
                discordUser,
                grantedPermission,
                target,
                ct
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user already has permission to do that."));
            }

            permission.IsGranted = true;
            await _database.SaveChangesAsync(ct);

            return(ModifyEntityResult.FromSuccess());
        }
Beispiel #14
0
        /// <summary>
        /// Revokes the given permission from the given Discord user. If the user does not have the permission, no
        /// changes are made.
        /// </summary>
        /// <param name="discordServer">The Discord server the permission was revoked on.</param>
        /// <param name="discordUser">The Discord user.</param>
        /// <param name="revokedPermission">The revoked permission.</param>
        /// <param name="target">The revoked target.</param>
        /// <param name="ct">The cancellation token in use.</param>
        /// <returns>A modification result which may or may not have succeeded.</returns>
        public async Task <ModifyEntityResult> RevokePermissionAsync
        (
            IGuild discordServer,
            IUser discordUser,
            IPermission revokedPermission,
            PermissionTarget target,
            CancellationToken ct = default
        )
        {
            // Special All target handling
            if (target == PermissionTarget.All)
            {
                var revokeSelfResult = await RevokePermissionAsync
                                       (
                    discordServer,
                    discordUser,
                    revokedPermission,
                    PermissionTarget.Self,
                    ct
                                       );

                var revokeOtherResult = await RevokePermissionAsync
                                        (
                    discordServer,
                    discordUser,
                    revokedPermission,
                    PermissionTarget.Other,
                    ct
                                        );

                if (revokeSelfResult.IsSuccess || revokeOtherResult.IsSuccess)
                {
                    return(ModifyEntityResult.FromSuccess());
                }

                // Both are false, so we'll just inherit the self result.
                return(ModifyEntityResult.FromError(revokeSelfResult));
            }

            var getPermissionResult = await GetOrCreateUserPermissionAsync
                                      (
                discordServer,
                discordUser,
                revokedPermission,
                target,
                ct
                                      );

            if (!getPermissionResult.IsSuccess)
            {
                return(ModifyEntityResult.FromError(getPermissionResult));
            }

            var permission = getPermissionResult.Entity;

            if (!permission.IsGranted)
            {
                return(ModifyEntityResult.FromError("The user is already prohibited from doing that."));
            }

            permission.IsGranted = false;
            await _database.SaveChangesAsync(ct);

            return(ModifyEntityResult.FromSuccess());
        }
    public async Task <Result> HasPermissionAsync
    (
        Snowflake discordServer,
        Snowflake discordUser,
        IPermission requiredPermission,
        PermissionTarget target,
        CancellationToken ct = default
    )
    {
        var getDiscordServer = await _guildAPI.GetGuildAsync(discordServer, ct : ct);

        if (!getDiscordServer.IsSuccess)
        {
            return(Result.FromError(getDiscordServer));
        }

        var guild = getDiscordServer.Entity;

        // The server owner always has all permissions by default
        if (guild.OwnerID == discordUser)
        {
            return(Result.FromSuccess());
        }

        // Special handling for the All target
        if (target == PermissionTarget.All)
        {
            var hasSelf = await HasPermissionAsync
                          (
                discordServer,
                discordUser,
                requiredPermission,
                PermissionTarget.Self,
                ct
                          );

            var hasOther = await HasPermissionAsync
                           (
                discordServer,
                discordUser,
                requiredPermission,
                PermissionTarget.Other,
                ct
                           );

            if (hasSelf.IsSuccess && hasOther.IsSuccess)
            {
                return(Result.FromSuccess());
            }

            return(new UserError("Permission denied."));
        }

        var hasPermission = false;

        var getGuildMember = await _guildAPI.GetGuildMemberAsync(discordServer, discordUser, ct);

        if (!getGuildMember.IsSuccess)
        {
            return(Result.FromError(getGuildMember));
        }

        var member = getGuildMember.Entity;

        // Check if the user is part of any roles which this permission applies to
        var rolePermissions = await GetApplicableRolePermissionsAsync(member.Roles, ct);

        var rolePermission = rolePermissions.FirstOrDefault
                             (
            p =>
            p.Permission == requiredPermission.UniqueIdentifier &&
            p.Target == target
                             );

        if (rolePermission is not null)
        {
            hasPermission = rolePermission.IsGranted;
        }

        // Check if the user has the permission applied to themselves
        var userPermission = await _database.UserPermissions.ServersideQueryAsync
                             (
            q => q
            .Where(p => p.ServerID == discordServer)
            .Where(p => p.UserID == discordUser)
            .Where(p => p.Permission == requiredPermission.UniqueIdentifier)
            .Where(p => p.Target == target)
            .SingleOrDefaultAsync(ct)
                             );

        if (userPermission is not null)
        {
            hasPermission = userPermission.IsGranted;
        }

        if (rolePermission is null && userPermission is null)
        {
            // Use the permission's default value
            hasPermission = requiredPermission.IsGrantedByDefaultTo(target);
        }

        return(hasPermission
            ? Result.FromSuccess()
            : new UserError("Permission denied."));
    }