Skip to content

Commit

Permalink
implement Discord Admin permissions
Browse files Browse the repository at this point in the history
  • Loading branch information
dragonejt committed Dec 4, 2023
1 parent 4a58004 commit f085ad9
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 35 deletions.
42 changes: 33 additions & 9 deletions clients/discord.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
import requests


class DiscordClient():

url = "https://discord.com/api/v10"

def __init__(self, access_token):
user = requests.get(f"{self.url}/users/@me", headers={
self.access_token = access_token
response = requests.get(f"{self.url}/users/@me", headers={
"Accept": "application/json",
"Authorization": f"Bearer {access_token}"
}).json()
user.raise_for_status()

self.user_id = user["id"]
})
response.raise_for_status()
self.user = response.json()

def is_server_admin(self, guild_id):
response = requests.get(
f"{self.url}/guilds/{guild_id}/members/{self.user_id}").json()
# Check if user is owner
response = requests.get(f"{self.url}/guilds/{guild_id}", headers={
"Accept": "application/json",
"Authorization": f"Bearer {self.access_token}"
})
response.raise_for_status()
guild = response.json()
if guild["owner_id"] == self.user["id"]:
return True

# Check if user is admin
response = requests.get(f"{self.url}/guilds/{guild_id}/members/{self.user['id']}", headers={
"Accept": "application/json",
"Authorization": f"Bearer {self.access_token}"
})
response.raise_for_status()
member = response.json()
roles = member["roles"]

print(response["permissions"])
def is_admin(role):
response = requests.get(f"{self.url}/guilds/{guild_id}/roles/{role}", headers={
"Accept": "application/json",
"Authorization": f"Bearer {self.access_token}"
})
response.raise_for_status()
role = response.json()
return role["permissions"] & 0x8 == 0x8

return True
return any(map(is_admin, roles))
22 changes: 2 additions & 20 deletions community/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from django.db import models
from django.contrib.auth import get_user_model
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.serializers import ModelSerializer
from rest_framework.permissions import BasePermission
from clients.discord import DiscordClient


# Create your models here.

Expand All @@ -18,7 +15,7 @@ class Meta:
verbose_name_plural = "Communities"

def __str__(self) -> str:
return f"{self.platform.username}/{self.community_id} ({self.id})"
return f"{self.platform.get_username()}/{self.community_id} ({self.id})"

# For Discord Servers Only
discord_log_channel = models.CharField(
Expand All @@ -31,18 +28,3 @@ class CommunitySerializer(ModelSerializer):
class Meta:
model = Community
fields = "__all__"

class DiscordAdmin(BasePermission):

def has_permission(self, request: Request, view: APIView):
return True

def has_object_permission(self, request: Request, view: APIView, obj: models.Model) -> bool:
platform, access_token = request.META["Authorization"].split(" ")

if (platform != "Discord"): return False
if (type(obj) == Community):
return DiscordClient(access_token).is_server_admin(obj.community_id)


return False
37 changes: 37 additions & 0 deletions community/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django.db import models
from rest_framework.permissions import BasePermission
from rest_framework.views import APIView
from rest_framework.request import Request
from community.models import Community
from dominator.models import MessageDominator, MemberDominator
from clients.discord import DiscordClient


class DiscordAdmin(BasePermission):

def has_permission(self, request: Request, view: APIView):
if request.method == "GET" or request.method == "PUT":
return True
return False

def has_object_permission(self, request: Request, view: APIView, obj: models.Model) -> bool:
try:
platform, access_token = request.headers["Authorization"].split(
' ')

if platform != "Discord":
return False
discord = DiscordClient(access_token)
if isinstance(obj, Community):
if obj.platform.get_username() != "discord":
return False
return discord.is_server_admin(obj.community_id)
if isinstance(obj, (MessageDominator, MemberDominator)):
if obj.community.platform.get_username() != "discord":
return False
return discord.is_server_admin(obj.community.community_id)

return False

except Exception:
return False
6 changes: 4 additions & 2 deletions community/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from community.models import Community, CommunitySerializer, DiscordAdmin
from rest_framework.decorators import permission_classes
from community.models import Community, CommunitySerializer
from community.permissions import DiscordAdmin
from psychopass.models import CommunityPsychoPass
from dominator.models import MessageDominator, MemberDominator

Expand All @@ -20,7 +22,7 @@ def get(self, request: Request) -> Response:
self.check_object_permissions(request, community)

return Response(CommunitySerializer(community).data, status=status.HTTP_200_OK)

def post(self, request: Request) -> Response:
community = Community.objects.create(
platform=request.user, community_id=request.data.get("communityID"))
Expand Down
4 changes: 2 additions & 2 deletions dominator/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Meta:
verbose_name_plural = "Message Dominators"

def __str__(self) -> str:
return f"{self.community.platform.username}/{self.community.community_id} ({self.id})"
return f"{self.community.platform.get_username()}/{self.community.community_id} ({self.id})"

toxicity_action = models.IntegerField(
choices=Actions.choices, default=Actions.NOTIFY)
Expand Down Expand Up @@ -60,7 +60,7 @@ class Meta:
verbose_name_plural = "Member Dominators"

def __str__(self) -> str:
return f"{self.community.platform.username}/{self.community.community_id} ({self.id})"
return f"{self.community.platform.get_username()}/{self.community.community_id} ({self.id})"

crime_coefficient_100_action = models.IntegerField(
choices=Actions.choices, default=Actions.NOTIFY)
Expand Down
4 changes: 2 additions & 2 deletions psychopass/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Meta:
verbose_name_plural = "Psycho-Passes"

def __str__(self) -> str:
return f"{self.platform.username}/{self.user_id} ({self.id})"
return f"{self.platform.get_username()}/{self.user_id} ({self.id})"

def ingest_message(self, scores: dict) -> None:
self.toxicity = self.update_score(
Expand Down Expand Up @@ -87,7 +87,7 @@ class Meta:
verbose_name_plural = "Community Psycho-Passes"

def __str__(self) -> str:
return f"{self.community.platform.username}/{self.community.community_id} ({self.id})"
return f"{self.community.platform.get_username()}/{self.community.community_id} ({self.id})"

def area_stress_level(self) -> dict:
return {
Expand Down

0 comments on commit f085ad9

Please sign in to comment.