From 4e973c8bf9d59f5f66f21462cf4ab6596eaa84dd Mon Sep 17 00:00:00 2001 From: Nilesh Pant <58652823+NileshPant1999@users.noreply.github.com> Date: Mon, 30 Oct 2023 16:02:04 +0530 Subject: [PATCH] Add user serializer, org and profile api (#56) --- apps/fyle/helpers.py | 43 +++++++++++++++++++++++++++++++++++++++ apps/users/helpers.py | 41 +++++++++++++++++++++++++++++++++++++ apps/users/serializers.py | 9 ++++++++ apps/users/urls.py | 23 +++++++++++++++++++++ apps/users/views.py | 41 +++++++++++++++++++++++++++++++++++++ sage_desktop_api/urls.py | 6 +++--- 6 files changed, 160 insertions(+), 3 deletions(-) create mode 100644 apps/users/helpers.py diff --git a/apps/fyle/helpers.py b/apps/fyle/helpers.py index a65641d7..c52e8fb3 100644 --- a/apps/fyle/helpers.py +++ b/apps/fyle/helpers.py @@ -32,6 +32,40 @@ def post_request(url, body, refresh_token=None): raise Exception(response.text) +def get_request(url, params, refresh_token): + """ + Create a HTTP get request. + """ + access_token = get_access_token(refresh_token) + api_headers = { + 'content-type': 'application/json', + 'Authorization': 'Bearer {0}'.format(access_token) + } + api_params = {} + + for k in params: + # ignore all unused params + if not params[k] is None: + p = params[k] + + # convert boolean to lowercase string + if isinstance(p, bool): + p = str(p).lower() + + api_params[k] = p + + response = requests.get( + url, + headers=api_headers, + params=api_params + ) + + if response.status_code == 200: + return json.loads(response.text) + else: + raise Exception(response.text) + + def get_access_token(refresh_token: str) -> str: """ Get access token from fyle @@ -79,3 +113,12 @@ def get_expense_fields(workspace_id: int): }) return response + + +def get_fyle_orgs(refresh_token: str, cluster_domain: str): + """ + Get fyle orgs of a user + """ + api_url = '{0}/api/orgs/'.format(cluster_domain) + + return get_request(api_url, {}, refresh_token) diff --git a/apps/users/helpers.py b/apps/users/helpers.py new file mode 100644 index 00000000..c7fc15b5 --- /dev/null +++ b/apps/users/helpers.py @@ -0,0 +1,41 @@ +from typing import Tuple + +from fyle_rest_auth.models import AuthToken +from fyle_integrations_platform_connector import PlatformConnector + +from apps.workspaces.models import FyleCredential +from apps.fyle.helpers import get_cluster_domain + + +def get_cluster_domain_and_refresh_token(user) -> Tuple[str, str]: + """ + Get cluster domain and refresh token from User + """ + fyle_credentials = FyleCredential.objects.filter(workspace__user=user).first() + + if fyle_credentials: + refresh_token = fyle_credentials.refresh_token + cluster_domain = fyle_credentials.cluster_domain + else: + refresh_token = AuthToken.objects.get(user__user_id=user).refresh_token + cluster_domain = get_cluster_domain(refresh_token) + + return cluster_domain, refresh_token + + +def get_user_profile(request): + """ + Get user profile + """ + refresh_token = AuthToken.objects.get(user__user_id=request.user).refresh_token + cluster_domain, _ = get_cluster_domain_and_refresh_token(request.user) + + fyle_credentials = FyleCredential( + cluster_domain=cluster_domain, + refresh_token=refresh_token + ) + + platform = PlatformConnector(fyle_credentials) + employee_profile = platform.connection.v1beta.spender.my_profile.get() + + return employee_profile diff --git a/apps/users/serializers.py b/apps/users/serializers.py index e69de29b..ecdb606c 100644 --- a/apps/users/serializers.py +++ b/apps/users/serializers.py @@ -0,0 +1,9 @@ +from rest_framework import serializers + +from .models import User + + +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = '__all__' diff --git a/apps/users/urls.py b/apps/users/urls.py index e69de29b..d0960bfe 100644 --- a/apps/users/urls.py +++ b/apps/users/urls.py @@ -0,0 +1,23 @@ +"""fyle_intacct_api URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.urls import path + +from .views import UserProfileView, FyleOrgsView + +urlpatterns = [ + path('profile/', UserProfileView.as_view()), + path('orgs/', FyleOrgsView.as_view()) +] diff --git a/apps/users/views.py b/apps/users/views.py index e69de29b..636db51f 100644 --- a/apps/users/views.py +++ b/apps/users/views.py @@ -0,0 +1,41 @@ +from rest_framework import generics, status +from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response + +from apps.fyle.helpers import get_fyle_orgs +from apps.users.helpers import get_cluster_domain_and_refresh_token, get_user_profile + + +class UserProfileView(generics.RetrieveAPIView): + + permission_classes = [IsAuthenticated] + + def get(self, request, *args, **kwargs): + """ + Get User Details + """ + employee_profile = get_user_profile(request) + return Response( + data=employee_profile, + status=status.HTTP_200_OK + ) + + +class FyleOrgsView(generics.ListCreateAPIView): + """ + FyleOrgs view + """ + + permission_classes = [IsAuthenticated] + + def get(self, request, *args, **kwargs): + """ + Get cluster domain from Fyle + """ + cluster_domain, refresh_token = get_cluster_domain_and_refresh_token(request.user) + fyle_orgs = get_fyle_orgs(refresh_token, cluster_domain) + + return Response( + data=fyle_orgs, + status=status.HTTP_200_OK + ) diff --git a/sage_desktop_api/urls.py b/sage_desktop_api/urls.py index f86d7ec6..bbeea124 100644 --- a/sage_desktop_api/urls.py +++ b/sage_desktop_api/urls.py @@ -13,11 +13,11 @@ 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ -from django.contrib import admin from django.urls import path, include urlpatterns = [ - path('admin/', admin.site.urls), - path('api/workspaces/', include('apps.workspaces.urls')) + path('api/auth/', include('fyle_rest_auth.urls')), + path('api/workspaces/', include('apps.workspaces.urls')), + path('api/user/', include('apps.users.urls')) ]