* Add cloud connection statuses on user page * Add fixes for oncall hobby docker-compose installation * Fix for links and for cloud user status at User settings * Delete cloud api token on cloud disconnect * Merge branch 'dev' into cloud_connection_statuses_on_user_page * Fix cloud statuses for users * Fix usagestats service * Fix phone verification message in users table * added request after syncing user * Add endpoint to create CloudHeartbeat and polish code * Fix imports * Check token and heartbeat setting in setup_hertbeat_integration * Add macthed_users_count in cloud users * Sync users on token change * Fix query param * Fix tests * Heartbit button logic, tab width fix, coount users fix * Solve problem of existent cloud heartbeat integration * Solve problem of existent cloud heartbeat integration 2 * Solve problem of existent cloud heartbeat integration 3 * fix build * build fix, styles for env variables description Co-authored-by: Ildar Iskhakov <ildar.iskhakov@grafana.com> Co-authored-by: Yulia Shanyrova <yulia.shanyrova@grafana.com>
107 lines
4.1 KiB
Python
107 lines
4.1 KiB
Python
from collections import OrderedDict
|
|
|
|
from rest_framework import mixins, status, viewsets
|
|
from rest_framework.decorators import action
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
|
|
from apps.api.permissions import ActionPermission, AnyRole, IsAdmin, IsOwnerOrAdmin
|
|
from apps.auth_token.auth import PluginAuthentication
|
|
from apps.oss_installation.models import CloudConnector, CloudUserIdentity
|
|
from apps.oss_installation.serializers import CloudUserSerializer
|
|
from apps.oss_installation.utils import cloud_user_identity_status
|
|
from apps.user_management.models import User
|
|
from common.api_helpers.mixins import PublicPrimaryKeyMixin
|
|
from common.api_helpers.paginators import HundredPageSizePaginator
|
|
from common.constants.role import Role
|
|
|
|
|
|
class CloudUsersView(HundredPageSizePaginator, APIView):
|
|
authentication_classes = (PluginAuthentication,)
|
|
permission_classes = (IsAuthenticated, IsAdmin)
|
|
|
|
def get(self, request):
|
|
organization = request.user.organization
|
|
|
|
queryset = User.objects.filter(organization=organization, role__in=[Role.ADMIN, Role.EDITOR])
|
|
|
|
if request.user.current_team is not None:
|
|
queryset = queryset.filter(teams=request.user.current_team).distinct()
|
|
emails = list(queryset.values_list("email", flat=True))
|
|
|
|
results = self.paginate_queryset(queryset, request, view=self)
|
|
|
|
cloud_identities = list(CloudUserIdentity.objects.filter(email__in=emails))
|
|
cloud_identities = {cloud_identity.email: cloud_identity for cloud_identity in cloud_identities}
|
|
|
|
response = []
|
|
|
|
connector = CloudConnector.objects.first()
|
|
|
|
for user in results:
|
|
cloud_identity = cloud_identities.get(user.email, None)
|
|
status, link = cloud_user_identity_status(connector, cloud_identity)
|
|
response.append(
|
|
{
|
|
"id": user.public_primary_key,
|
|
"email": user.email,
|
|
"username": user.username,
|
|
"cloud_data": {"status": status, "link": link},
|
|
}
|
|
)
|
|
|
|
return self.get_paginated_response_with_matched_users_count(response, len(cloud_identities))
|
|
|
|
def get_paginated_response_with_matched_users_count(self, data, matched_users_count):
|
|
return Response(
|
|
OrderedDict(
|
|
[
|
|
("count", self.page.paginator.count),
|
|
("matched_users_count", matched_users_count),
|
|
("next", self.get_next_link()),
|
|
("previous", self.get_previous_link()),
|
|
("results", data),
|
|
]
|
|
)
|
|
)
|
|
|
|
def post(self, request):
|
|
connector = CloudConnector.objects.first()
|
|
if connector is not None:
|
|
sync_status, err = connector.sync_users_with_cloud()
|
|
return Response(status=status.HTTP_200_OK, data={"status": sync_status, "error": err})
|
|
else:
|
|
return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": "Grafana Cloud is not connected"})
|
|
|
|
|
|
class CloudUserView(
|
|
PublicPrimaryKeyMixin,
|
|
mixins.RetrieveModelMixin,
|
|
viewsets.GenericViewSet,
|
|
):
|
|
authentication_classes = (PluginAuthentication,)
|
|
permission_classes = (IsAuthenticated, ActionPermission)
|
|
|
|
action_permissions = {
|
|
AnyRole: ("retrieve",),
|
|
IsAdmin: ("sync",),
|
|
}
|
|
action_object_permissions = {
|
|
IsOwnerOrAdmin: ("retrieve", "sync"),
|
|
}
|
|
serializer_class = CloudUserSerializer
|
|
|
|
def get_queryset(self):
|
|
queryset = User.objects.filter(organization=self.request.user.organization)
|
|
return queryset
|
|
|
|
@action(detail=True, methods=["post"])
|
|
def sync(self, request, pk):
|
|
user = self.get_object()
|
|
connector = CloudConnector.objects.first()
|
|
if connector is not None:
|
|
sync_status, err = connector.sync_user_with_cloud(user)
|
|
return Response(status=status.HTTP_200_OK, data={"status": sync_status, "error": err})
|
|
else:
|
|
return Response(status=status.HTTP_400_BAD_REQUEST, data={"detail": "Grafana Cloud is not connected"})
|