Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PrivilegeConfig#canMemberRun #2774

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@
package net.dv8tion.jda.api.interactions.commands;

import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.SelfUser;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper;
import org.jetbrains.annotations.Unmodifiable;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -144,4 +148,28 @@ public Map<String, List<IntegrationPrivilege>> getAsMap()
{
return privileges;
}

/**
* Determines whether the {@link Command} can be run by the {@link Member} in the {@link GuildChannel}.
*
* <p>This will always return {@code true} for guild {@link Member#isOwner() Owners} and {@link Permission#ADMINISTRATOR Administrators}.
*
* <p>Implements <a href="https://discord.com/assets/6da3bd6082744a5eca59bb032c890092.svg" target="_blank">Discord's flow chart for command permissions logic</a>.
*
* @param channel
* The channel in which the command would run in
* @param member
* The member which would run the command
* @param command
* The command which should be tested for
*
* @return {@code true} if the command can be run by the specified member, in the guild channel, {@code false} otherwise.
*/
public boolean canMemberRun(@Nonnull GuildChannel channel, @Nonnull Member member, @Nonnull Command command)
{
Checks.notNull(channel, "Channel");
Checks.notNull(member, "Member");
Checks.notNull(command, "Command");
return PrivilegeHelper.canMemberRun(this, channel, member, command);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.internal.utils.interactions.commands;

import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.PrivilegeConfig;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;

import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.findPrivilege;
import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.matchingChannel;

public class AppLevelChannelPermissionChecks
{
public static boolean canMemberRun(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege appChannelPermissions = findPrivilege(config.getApplicationPrivileges(), matchingChannel(channel));
if (appChannelPermissions != null)
{
if (appChannelPermissions.isEnabled())
return CommandLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
return false;
}
else
return isAllowedInAllChannels(config, channel, member, command);
}

public static boolean isAllowedInAllChannels(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege appChannelPermissions = findPrivilege(config.getApplicationPrivileges(), IntegrationPrivilege::targetsAllChannels);
if (appChannelPermissions != null)
{
if (appChannelPermissions.isEnabled())
return CommandLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
return false;
}
else
return CommandLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.internal.utils.interactions.commands;

import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.PrivilegeConfig;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.*;

public class AppLevelUserOrRolePermissionChecks
{
public static boolean canMemberRun(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final List<IntegrationPrivilege> applicationPrivileges = config.getApplicationPrivileges();
final IntegrationPrivilege appUserPermissions = findPrivilege(applicationPrivileges, matchingMember(member));
if (appUserPermissions != null)
{
if (appUserPermissions.isEnabled())
return DefaultMemberPermissionsChecks.canMemberRun(channel, member, command);
return false;
}
else
{
return hasAtLeastOneConfiguredRole(config, channel, member, command);
}
}

public static boolean hasAtLeastOneConfiguredRole(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
// If there's a role override, then at least one needs to be enabled
// If there's no role override, check @everyone
final List<IntegrationPrivilege> commandRolePermissionList = member.getRoles().stream()
.flatMap(r -> findAllPrivileges(config.getApplicationPrivileges(), matchingRole(r)))
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (commandRolePermissionList.isEmpty())
return isEveryoneAllowed(config, channel, member, command);

for (IntegrationPrivilege integrationPrivilege : commandRolePermissionList)
{
if (integrationPrivilege.isEnabled())
return DefaultMemberPermissionsChecks.canMemberRun(channel, member, command);
}
return false;
}

public static boolean isEveryoneAllowed(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege commandEveryonePermissions = findPrivilege(config.getApplicationPrivileges(), matchingRole(channel.getGuild().getPublicRole()));
if (commandEveryonePermissions != null)
{
if (commandEveryonePermissions.isEnabled())
return DefaultMemberPermissionsChecks.canMemberRun(channel, member, command);
return false;
}
return DefaultMemberPermissionsChecks.canMemberRun(channel, member, command);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.internal.utils.interactions.commands;

import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.PrivilegeConfig;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;

import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.findPrivilege;
import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.matchingChannel;

public class CommandLevelChannelPermissionChecks
{
public static boolean canMemberRun(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege commandChannelPermissions = findPrivilege(config.getCommandPrivileges(command), matchingChannel(channel));
if (commandChannelPermissions != null)
{
if (commandChannelPermissions.isDisabled())
return false;
return CommandLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
}
else
return isAllowedInAllChannels(config, channel, member, command);
}

public static boolean isAllowedInAllChannels(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege commandAllChannelsPermissions = findPrivilege(config.getCommandPrivileges(command), IntegrationPrivilege::targetsAllChannels);

if (commandAllChannelsPermissions != null)
{
if (commandAllChannelsPermissions.isEnabled())
return CommandLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
return false;
}
else
return AppLevelChannelPermissionChecks.canMemberRun(config, channel, member, command);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.internal.utils.interactions.commands;

import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.PrivilegeConfig;
import net.dv8tion.jda.api.interactions.commands.privileges.IntegrationPrivilege;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static net.dv8tion.jda.internal.utils.interactions.commands.PrivilegeHelper.*;

public class CommandLevelUserOrRolePermissionChecks
{
public static boolean canMemberRun(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege commandUserPermissions = findPrivilege(config.getCommandPrivileges(command), matchingMember(member));
if (commandUserPermissions != null)
return commandUserPermissions.isEnabled();
else
return hasAtLeastOneConfiguredRole(config, channel, member, command);
}

public static boolean hasAtLeastOneConfiguredRole(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
// If there's a role override, then at least one needs to be enabled
// If there's no role override, check @everyone
final List<IntegrationPrivilege> commandRolePermissionList = member.getRoles().stream()
.flatMap(r -> findAllPrivileges(config.getCommandPrivileges(command), matchingRole(r)))
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (commandRolePermissionList.isEmpty())
return isEveryoneAllowed(config, channel, member, command);

for (IntegrationPrivilege integrationPrivilege : commandRolePermissionList)
{
if (integrationPrivilege.isEnabled())
return true;
}
return false;
}

public static boolean isEveryoneAllowed(PrivilegeConfig config, GuildChannel channel, Member member, Command command)
{
final IntegrationPrivilege commandEveryonePermissions = findPrivilege(config.getCommandPrivileges(command), matchingRole(channel.getGuild().getPublicRole()));
if (commandEveryonePermissions != null)
return commandEveryonePermissions.isEnabled();
return AppLevelUserOrRolePermissionChecks.canMemberRun(config, channel, member, command);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.dv8tion.jda.internal.utils.interactions.commands;

import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.internal.utils.PermissionUtil;

public class DefaultMemberPermissionsChecks
{
public static boolean canMemberRun(GuildChannel channel, Member member, Command command)
{
final Long rawPermissions = command.getDefaultPermissions().getPermissionsRaw();
// No permissions requires
if (rawPermissions == null)
return true;
// Admins only, already checked in [[PrivilegeHelper#canMemberRun]]
if (rawPermissions == 0)
return false;
return ((PermissionUtil.getEffectivePermission(channel, member) & rawPermissions) == rawPermissions);
}
}
Loading