Skip to content

Commit

Permalink
Merge pull request #2469 from bcgov/2160-internal-user-can-view-acces…
Browse files Browse the repository at this point in the history
…s-requests

2160 internal user can view access requests
  • Loading branch information
Sepehr-Sobhani authored Nov 21, 2024
2 parents 1e96823 + 5f1c36c commit 7f9684f
Show file tree
Hide file tree
Showing 28 changed files with 1,119 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@
"title": "Operator Administrators and Access Requests",
"icon": "Inbox",
"content": "View all operator administrators and administrator access requests here.",
"href": "/administration/tbd"
},
{
"title": "Operation Administrations",
"icon": "Layers",
"content": "View the administration of operations here.",
"href": "/administration/tbd"
"href": "/administration/operator-administrators-and-access-requests"
},
{
"title": "Contacts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@
"title": "Operator Administrators and Access Requests",
"icon": "Inbox",
"content": "View all operator administrators and administrator access requests here.",
"href": "/administration/tbd"
},
{
"title": "Operation Administrations",
"icon": "File",
"content": "View the administration of operations here.",
"href": "/administration/tbd"
"href": "/administration/operator-administrators-and-access-requests"
},
{
"title": "Contacts",
Expand Down
4 changes: 2 additions & 2 deletions bc_obps/common/fixtures/dashboard/bciers/internal.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
"href": "/administration/operations"
},
{
"title": "Operator Admins and Access Requests",
"href": "/administration/tbd"
"title": "Operator Administrators and Access Requests",
"href": "/administration/operator-administrators-and-access-requests"
},
{
"title": "Contacts",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ class TestEndpointPermissions(TestCase):
],
"authorized_irc_user": [
{"method": "get", "endpoint_name": "list_user_operators"},
{"method": "get", "endpoint_name": "list_user_operators_v2"},
{"method": "put", "endpoint_name": "update_operator_status", "kwargs": {"operator_id": mock_uuid}},
{
"method": "put",
Expand Down
26 changes: 24 additions & 2 deletions bc_obps/registration/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@

admin.site.register(AppRole)
admin.site.register(NaicsCode)
admin.site.register(User)
admin.site.register(Operator)
admin.site.register(UserOperator)
admin.site.register(ParentOperator)
admin.site.register(RegulatedProduct)
admin.site.register(Activity)
Expand Down Expand Up @@ -103,3 +101,27 @@ class DocumentAdmin(admin.ModelAdmin):
@staticmethod
def type_name(obj: Document) -> str:
return obj.type.name


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ('user_guid', 'first_name', 'last_name', 'email', 'position_title', 'role')
search_fields = ('user_guid', 'first_name', 'last_name')

@staticmethod
def role(obj: User) -> str:
return obj.app_role.role_name


@admin.register(UserOperator)
class UserOperatorAdmin(admin.ModelAdmin):
list_display = ('id', 'user_full_name', 'operator_legal_name', 'role', 'status')
ordering = ('-created_at',)

@staticmethod
def user_full_name(obj: UserOperator) -> str:
return obj.user.first_name + ' ' + obj.user.last_name

@staticmethod
def operator_legal_name(obj: UserOperator) -> str:
return obj.operator.legal_name
31 changes: 28 additions & 3 deletions bc_obps/registration/api/v2/user_operators.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,41 @@
from django.db.models import QuerySet
from ninja import Query
from common.permissions import authorize
from common.api.utils import get_current_user_guid
from django.http import HttpRequest
from registration.decorators import handle_http_errors
from registration.models import UserOperator
from registration.schema.generic import Message
from registration.api.router import router
from service.error_service.custom_codes_4xx import custom_codes_4xx
from typing import Literal, Tuple

from typing import Literal, Tuple, Optional, List
from registration.constants import USER_OPERATOR_TAGS_V2
from registration.schema.v2.operator import OperatorIn
from registration.schema.v2.user_operator import UserOperatorOperatorOut
from registration.schema.v2.user_operator import UserOperatorOperatorOut, UserOperatorListOut, UserOperatorFilterSchema
from service.user_operator_service_v2 import UserOperatorServiceV2
from ninja.pagination import paginate, PageNumberPagination

## GET
@router.get(
"/v2/user-operators",
response={200: List[UserOperatorListOut], custom_codes_4xx: Message},
tags=USER_OPERATOR_TAGS_V2,
description="""Retrieves a paginated list of user operators.
The endpoint allows authorized IRC roles to view user operators, sorted by various fields such as creation date,
user details, and operator legal name.""",
auth=authorize("authorized_irc_user"),
)
@handle_http_errors()
@paginate(PageNumberPagination)
def list_user_operators_v2(
request: HttpRequest,
filters: UserOperatorFilterSchema = Query(...),
sort_field: Optional[str] = "created_at",
sort_order: Optional[Literal["desc", "asc"]] = "desc",
paginate_result: bool = Query(True, description="Whether to paginate the results"),
) -> QuerySet[UserOperator]:
# NOTE: PageNumberPagination raises an error if we pass the response as a tuple (like 200, ...)
return UserOperatorServiceV2.list_user_operators_v2(get_current_user_guid(request), sort_field, sort_order, filters)


## POST
Expand Down
6 changes: 3 additions & 3 deletions bc_obps/registration/fixtures/mock/admin/user_operator.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000007",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"role": "admin",
"status": "Pending",
"verified_at": null,
"verified_by": null,
Expand Down Expand Up @@ -196,8 +196,8 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000014",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"status": "Pending",
"role": "admin",
"status": "Declined",
"verified_at": null,
"verified_by": null,
"user_friendly_id": 17
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000007",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"role": "admin",
"status": "Pending",
"verified_at": null,
"verified_by": null,
Expand Down Expand Up @@ -196,8 +196,8 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000014",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"status": "Pending",
"role": "admin",
"status": "Declined",
"verified_at": null,
"verified_by": null,
"user_friendly_id": 17
Expand Down
6 changes: 3 additions & 3 deletions bc_obps/registration/fixtures/mock/user_operator.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000007",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"role": "admin",
"status": "Pending",
"verified_at": null,
"verified_by": null,
Expand Down Expand Up @@ -196,8 +196,8 @@
"fields": {
"user": "00000000-0000-0000-0000-000000000014",
"operator": "5712ee05-5f3b-4822-825d-6fffddafda4c",
"role": "pending",
"status": "Pending",
"role": "admin",
"status": "Declined",
"verified_at": null,
"verified_by": null,
"user_friendly_id": 17
Expand Down
39 changes: 38 additions & 1 deletion bc_obps/registration/schema/v2/user_operator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
from ninja import Schema
from typing import Optional
from django.db.models import Q
from ninja import Schema, FilterSchema, Field, ModelSchema
from uuid import UUID
from registration.models import UserOperator


class UserOperatorOperatorOut(Schema):
operator_id: UUID
user_operator_id: UUID


class UserOperatorFilterSchema(FilterSchema):
user_friendly_id: Optional[str] = Field(None, json_schema_extra={'q': 'user_friendly_id__icontains'})
status: Optional[str] = None
user__first_name: Optional[str] = Field(None, json_schema_extra={'q': 'user__first_name__icontains'})
user__last_name: Optional[str] = Field(None, json_schema_extra={'q': 'user__last_name__icontains'})
user__email: Optional[str] = Field(None, json_schema_extra={'q': 'user__email__icontains'})
user__bceid_business_name: Optional[str] = Field(
None, json_schema_extra={'q': 'user__bceid_business_name__icontains'}
)
operator__legal_name: Optional[str] = Field(None, json_schema_extra={'q': 'operator__legal_name__icontains'})

@staticmethod
def filter_status(value: Optional[str]) -> Q:
# Override the default filter_status method to handle the special case of 'admin' and 'access'
# The value in the frontend is 'admin access' but the value in the database is 'approved'
if value:
if value.lower() in "admin access":
value = "approved"
return Q(status__icontains=value)
return Q()


class UserOperatorListOut(ModelSchema):
user__first_name: str = Field(..., alias="user.first_name")
user__last_name: str = Field(..., alias="user.last_name")
user__email: str = Field(..., alias="user.email")
user__bceid_business_name: str = Field(..., alias="user.bceid_business_name")
operator__legal_name: str = Field(..., alias="operator.legal_name")

class Meta:
model = UserOperator
fields = ['id', 'user_friendly_id', 'status']
Loading

0 comments on commit 7f9684f

Please sign in to comment.