Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions readthedocs/oauth/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
"""Admin configuration for the OAuth app."""

from django import urls
from django.contrib import admin
from django.utils.html import format_html

from .models import GitHubAppInstallation
from .models import RemoteOrganization
Expand All @@ -25,6 +27,7 @@ class RemoteRepositoryAdmin(admin.ModelAdmin):
readonly_fields = (
"created",
"modified",
"remote_repository_relations",
)
raw_id_fields = ("organization", "github_app_installation")
list_select_related = ("organization",)
Expand All @@ -37,6 +40,8 @@ class RemoteRepositoryAdmin(admin.ModelAdmin):
"name",
"full_name",
"remote_id",
"projects__slug",
"projects__name",
)
list_display = (
"id",
Expand All @@ -48,6 +53,29 @@ class RemoteRepositoryAdmin(admin.ModelAdmin):
"get_vcs_display",
)

@admin.display(description="Remote repository relations")
def remote_repository_relations(self, obj):
"""Link to relation objects filtered to this remote repository."""
if not obj.pk:
return "-"

url = urls.reverse(
"admin:{}_{}_changelist".format(
RemoteRepositoryRelation._meta.app_label,
RemoteRepositoryRelation._meta.model_name,
),
)
relation_count = obj.remote_repository_relations.count()
relation_label = "relation" if relation_count == 1 else "relations"
return format_html(
'<a href="{}?{}={}">{} remote repository {}</a>',
url,
"remote_repository__id__exact",
obj.pk,
relation_count,
relation_label,
)


@admin.register(RemoteOrganization)
class RemoteOrganizationAdmin(admin.ModelAdmin):
Expand Down Expand Up @@ -100,6 +128,13 @@ class RemoteRepositoryRelationAdmin(admin.ModelAdmin):
"remote_repository__vcs_provider",
"admin",
)
search_fields = (
"remote_repository__name",
"remote_repository__full_name",
"remote_repository__remote_id",
"remote_repository__projects__slug",
"remote_repository__projects__name",
)

def vcs_provider(self, obj):
"""Get the display name for the VCS provider."""
Expand Down
116 changes: 116 additions & 0 deletions readthedocs/oauth/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import django_dynamic_fixture as fixture
from allauth.socialaccount.models import SocialAccount
from django import urls
from django.contrib.auth.models import User
from django.test import TestCase

from readthedocs.oauth.models import RemoteRepository
from readthedocs.oauth.models import RemoteRepositoryRelation
from readthedocs.projects.models import Project


class OAuthAdminTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.admin = fixture.get(User, is_staff=True, is_superuser=True)
cls.user = fixture.get(User, username="owner")
cls.account = fixture.get(
SocialAccount,
user=cls.user,
provider="github",
uid="owner-account",
)
cls.remote_repository = fixture.get(
RemoteRepository,
name="zephyrdocs",
full_name="organization/zephyrdocs",
remote_id="100",
html_url=None,
)
cls.other_remote_repository = fixture.get(
RemoteRepository,
name="telescope",
full_name="organization/telescope",
remote_id="101",
html_url=None,
)
cls.project = fixture.get(
Project,
slug="manualhub",
name="Manualhub",
remote_repository=cls.remote_repository,
main_language_project=None,
)
cls.other_project = fixture.get(
Project,
slug="telescopeapi",
name="Telescopeapi",
remote_repository=cls.other_remote_repository,
main_language_project=None,
)
cls.remote_repository_relation = fixture.get(
RemoteRepositoryRelation,
remote_repository=cls.remote_repository,
user=cls.user,
account=cls.account,
admin=True,
)
cls.other_user = fixture.get(User, username="other-owner")
cls.other_account = fixture.get(
SocialAccount,
user=cls.other_user,
provider="github",
uid="other-account",
)
cls.other_remote_repository_relation = fixture.get(
RemoteRepositoryRelation,
remote_repository=cls.other_remote_repository,
user=cls.other_user,
account=cls.other_account,
admin=False,
)

def setUp(self):
self.client.force_login(self.admin)

def test_remote_repository_admin_searches_by_project_slug(self):
response = self.client.get(
urls.reverse("admin:oauth_remoterepository_changelist"),
{"q": self.project.slug},
)

self.assertContains(response, self.remote_repository.full_name)
self.assertNotContains(response, self.other_remote_repository.full_name)

def test_remote_repository_change_view_links_to_filtered_relations(self):
response = self.client.get(
urls.reverse(
"admin:oauth_remoterepository_change",
args=[self.remote_repository.pk],
),
)

changelist_url = urls.reverse("admin:oauth_remoterepositoryrelation_changelist")
self.assertContains(
response,
f'{changelist_url}?remote_repository__id__exact={self.remote_repository.pk}',
)
self.assertContains(response, "1 remote repository relation")

def test_remote_repository_relation_admin_searches_by_project_name(self):
response = self.client.get(
urls.reverse("admin:oauth_remoterepositoryrelation_changelist"),
{"q": self.project.name},
)

self.assertContains(response, self.remote_repository.full_name)
self.assertNotContains(response, self.other_remote_repository.full_name)

def test_remote_repository_relation_admin_searches_by_remote_repository(self):
response = self.client.get(
urls.reverse("admin:oauth_remoterepositoryrelation_changelist"),
{"q": self.remote_repository.name},
)

self.assertContains(response, self.remote_repository.full_name)
self.assertNotContains(response, self.other_remote_repository.full_name)
Loading