Skip to content

Commit

Permalink
AAP-38623: Internal RH user check. (#1494)
Browse files Browse the repository at this point in the history
  • Loading branch information
romartin authored Jan 15, 2025
1 parent d9248bf commit e3828b7
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 38 deletions.
8 changes: 4 additions & 4 deletions ansible_ai_connect/ai/api/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3985,7 +3985,7 @@ def setUp(self):
super().setUp()
(org, _) = Organization.objects.get_or_create(id=123, telemetry_opt_out=False)
self.user.organization = org
self.user.rh_employee = True
self.user.rh_internal = True

@staticmethod
def mocked_requests_post(*args, **kwargs):
Expand Down Expand Up @@ -4323,7 +4323,7 @@ def test_chat_rate_limit(self):
)
(org, _) = Organization.objects.get_or_create(id=123, telemetry_opt_out=False)
self.user2.organization = org
self.user2.rh_employee = True
self.user2.rh_internal = True
# Call chart API five times using self.user2
for i in range(5):
self.assert_test(TestChatView.VALID_PAYLOAD, user=self.user2)
Expand All @@ -4333,7 +4333,7 @@ def test_chat_rate_limit(self):
if self.user2:
self.user2.delete()

def test_not_rh_employee_user(self):
def test_not_rh_internal_user(self):
try:
username = "u" + "".join(random.choices(string.digits, k=5))
self.user2 = get_user_model().objects.create_user(
Expand All @@ -4342,7 +4342,7 @@ def test_not_rh_employee_user(self):
self.user2.organization = Organization.objects.get_or_create(
id=123, telemetry_opt_out=False
)[0]
self.user2.rh_employee = False
self.user2.rh_internal = False
self.assert_test(TestChatView.VALID_PAYLOAD, expected_status_code=403, user=self.user2)
finally:
if self.user2:
Expand Down
4 changes: 2 additions & 2 deletions ansible_ai_connect/ai/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
)
from ansible_ai_connect.users.models import User

from ...main.permissions import IsRHEmployee, IsTestUser
from ...main.permissions import IsRHInternalUser, IsTestUser
from ...users.throttling import EndpointRateThrottle
from ..feature_flags import FeatureFlags
from .data.data_model import ContentMatchPayloadData, ContentMatchResponseDto
Expand Down Expand Up @@ -950,7 +950,7 @@ class ChatEndpointThrottle(EndpointRateThrottle):
permission_classes = [
permissions.IsAuthenticated,
IsAuthenticatedOrTokenHasScope,
IsRHEmployee | IsTestUser,
IsRHInternalUser | IsTestUser,
]
required_scopes = ["read", "write"]
schema1_event = schema1.ChatBotOperationalEvent
Expand Down
8 changes: 4 additions & 4 deletions ansible_ai_connect/main/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@
from rest_framework.permissions import BasePermission


class IsRHEmployee(BasePermission):
class IsRHInternalUser(BasePermission):
"""
Allow access only to users who are Red Hat employees
Allow access only to users who are Red Hat internal users.
"""

code = "permission_denied__user_not_rh_employee"
code = "permission_denied__user_not_rh_internal"
message = "The User is not a Red Hat employee."

def has_permission(self, request, view):
user = request.user
return user.is_authenticated and user.rh_employee
return user.is_authenticated and user.rh_internal


class IsTestUser(BasePermission):
Expand Down
14 changes: 7 additions & 7 deletions ansible_ai_connect/main/tests/test_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
from django.test import RequestFactory, TestCase
from django.urls import resolve, reverse

from ansible_ai_connect.main.permissions import IsRHEmployee, IsTestUser
from ansible_ai_connect.main.permissions import IsRHInternalUser, IsTestUser


class TestIsRHEmployee(TestCase):
class TestIsRHInternalUser(TestCase):
def setUp(self):
super().setUp()

self.permission = IsRHEmployee()
self.permission = IsRHInternalUser()

payload = {
"query": "Hello",
Expand All @@ -35,13 +35,13 @@ def setUp(self):
username="non-rh-user",
password="non-rh-password",
email="[email protected]",
rh_employee=False,
rh_internal=False,
)
self.rh_user = get_user_model().objects.create_user(
username="rh-user",
password="rh-password",
email="[email protected]",
rh_employee=True,
rh_internal=True,
)

def tearDown(self):
Expand Down Expand Up @@ -82,15 +82,15 @@ def setUp(self):
username="non-rh-user",
password="non-rh-password",
email="[email protected]",
rh_employee=False,
rh_internal=False,
)
self.test_group = Group(name="test")
self.test_group.save()
self.non_rh_test_user = get_user_model().objects.create_user(
username="non-rh-test-user",
password="non-rh-test-password",
email="[email protected]",
rh_employee=False,
rh_internal=False,
)
self.non_rh_test_user.groups.add(self.test_group)

Expand Down
6 changes: 3 additions & 3 deletions ansible_ai_connect/main/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,21 +255,21 @@ def setUp(self):
username="non-rh-user",
password="non-rh-password",
email="[email protected]",
rh_employee=False,
rh_internal=False,
)
self.rh_user = get_user_model().objects.create_user(
username="rh-user",
password="rh-password",
email="[email protected]",
rh_employee=True,
rh_internal=True,
)
self.test_group = Group(name="test")
self.test_group.save()
self.non_rh_test_user = get_user_model().objects.create_user(
username="non-rh-test-user",
password="non-rh-test-password",
email="[email protected]",
rh_employee=False,
rh_internal=False,
)
self.non_rh_test_user.groups.add(self.test_group)

Expand Down
4 changes: 2 additions & 2 deletions ansible_ai_connect/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
IsOrganisationLightspeedSubscriber,
)
from ansible_ai_connect.main.base_views import ProtectedTemplateView
from ansible_ai_connect.main.permissions import IsRHEmployee, IsTestUser
from ansible_ai_connect.main.permissions import IsRHInternalUser, IsTestUser
from ansible_ai_connect.main.settings.base import SOCIAL_AUTH_OIDC_KEY

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -116,7 +116,7 @@ class ChatbotView(ProtectedTemplateView):
template_name = "chatbot/index.html"

permission_classes = [
IsRHEmployee | IsTestUser,
IsRHInternalUser | IsTestUser,
]

def get(self, request):
Expand Down
22 changes: 22 additions & 0 deletions ansible_ai_connect/users/migrations/0014_user_rh_internal_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.2.11 on 2024-07-19 17:55

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("users", "0013_user_email_verified_user_family_name_user_given_name_and_more"),
]

operations = [
migrations.RemoveField(
model_name="user",
name="rh_employee",
),
migrations.AddField(
model_name="user",
name="rh_internal",
field=models.BooleanField(default=False),
),
]
2 changes: 1 addition & 1 deletion ansible_ai_connect/users/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class User(ExportModelOperationsMixin("user"), AbstractUser):
on_delete=models.CASCADE,
)
rh_user_is_org_admin = models.BooleanField(default=False)
rh_employee = models.BooleanField(default=False)
rh_internal = models.BooleanField(default=False)
external_username = models.CharField(default="", null=False)
name = models.CharField(default=None, null=True)
given_name = models.CharField(default=None, null=True)
Expand Down
13 changes: 11 additions & 2 deletions ansible_ai_connect/users/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,15 @@ def github_get_username(strategy, details, backend, user=None, *args, **kwargs):
return get_username(strategy, details, backend, user, *args, **kwargs)


def is_rh_email_domain(email) -> bool:
email_domain: str = email[email.find("@") + 1 :] if email else None
return email_domain.lower() == "redhat.com" if email_domain else False


def is_rh_internal_user(user) -> bool:
return is_rh_email_domain(user.email) and bool(user.email_verified)


def redhat_organization(backend, user, response, *args, **kwargs):
if backend.name != "oidc":
return
Expand All @@ -106,7 +115,7 @@ def redhat_organization(backend, user, response, *args, **kwargs):
user.email = payload.get("email")
user.email_verified = payload.get("email_verified")
user.rh_user_is_org_admin = "admin:org:all" in roles
user.rh_employee = "redhat:employees" in roles
user.rh_internal = is_rh_internal_user(user)

if settings.AUTHZ_BACKEND_TYPE == "dummy":
if settings.AUTHZ_DUMMY_RH_ORG_ADMINS == "*":
Expand All @@ -125,7 +134,7 @@ def redhat_organization(backend, user, response, *args, **kwargs):
return {
"external_username": user.external_username,
"organization_id": user.organization.id,
"rh_employee": user.rh_employee,
"rh_internal": user.rh_internal,
"rh_user_is_org_admin": user.rh_user_is_org_admin,
}

Expand Down
2 changes: 1 addition & 1 deletion ansible_ai_connect/users/templates/users/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ <h1 class="pf-c-title pf-m-lg">{{ project_name }}</h1>
{% if deployment_mode == 'saas' and user.is_authenticated and user.rh_user_is_org_admin %}
<a class="pf-l-level__item" href="/console"><span class="fas fa-solid fa-cog"></span> Admin Portal</a>
{% endif %}
{% if chatbot_enabled and deployment_mode == 'saas' and user.is_authenticated and rh_employee_or_test_user %}
{% if chatbot_enabled and deployment_mode == 'saas' and user.is_authenticated and rh_internal_user_or_test_user %}
<a class="pf-l-level__item" href="/chatbot"><span class="fas fa-solid fa-comments"></span> Chatbot</a>
{% endif %}
</div>
Expand Down
2 changes: 1 addition & 1 deletion ansible_ai_connect/users/templates/users/trial.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ <h1 class="pf-c-title pf-m-lg">{{ project_name }}</h1>
{% if deployment_mode == 'saas' and user.is_authenticated and user.rh_user_is_org_admin %}
<a class="pf-l-level__item" href="/console"><span class="fas fa-solid fa-cog"></span> Admin Portal</a>
{% endif %}
{% if chatbot_enabled and deployment_mode == 'saas' and user.is_authenticated and rh_employee_or_test_user %}
{% if chatbot_enabled and deployment_mode == 'saas' and user.is_authenticated and rh_internal_user_or_test_user %}
<a class="pf-l-level__item" href="/chatbot"><span class="fas fa-solid fa-comments"></span> Chatbot</a>
{% endif %}
</div>
Expand Down
Loading

0 comments on commit e3828b7

Please sign in to comment.