Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated #2749

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
15 changes: 8 additions & 7 deletions onadata/apps/api/viewsets/xform_list_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@

from django_filters import rest_framework as django_filter_filters
from rest_framework import permissions, viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.authentication import (
TokenAuthentication,
BaseAuthentication,
BasicAuthentication,
)
from rest_framework.decorators import action
from rest_framework.response import Response

Expand Down Expand Up @@ -43,6 +47,7 @@
)
from onadata.libs.utils.common_tags import GROUP_DELIMETER_TAG, REPEAT_INDEX_TAGS
from onadata.libs.utils.export_builder import ExportBuilder
from rest_framework import renderers

BaseViewset = get_baseviewset_class()

Expand All @@ -57,11 +62,7 @@ class XFormListViewSet(ETagsMixin, BaseViewset, viewsets.ReadOnlyModelViewSet):
OpenRosa Form List API - https://docs.getodk.org/openrosa-form-list/
"""

authentication_classes = (
DigestAuthentication,
EnketoTokenAuthentication,
TokenAuthentication,
)
authentication_classes = [BasicAuthentication, TokenAuthentication]
content_negotiation_class = MediaFileContentNegotiation
filterset_class = filters.FormIDFilter
filter_backends = (
Expand All @@ -74,7 +75,7 @@ class XFormListViewSet(ETagsMixin, BaseViewset, viewsets.ReadOnlyModelViewSet):
).only(
"id_string", "title", "version", "uuid", "description", "user__username", "hash"
)
permission_classes = (permissions.AllowAny,)
permission_classes = [permissions.AllowAny]
renderer_classes = (XFormListRenderer,)
serializer_class = XFormListSerializer
template_name = "api/xformsList.xml"
Expand Down
Empty file.
3 changes: 3 additions & 0 deletions onadata/apps/interview/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
6 changes: 6 additions & 0 deletions onadata/apps/interview/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class InterviewConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "onadata.apps.interview"
Empty file.
3 changes: 3 additions & 0 deletions onadata/apps/interview/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.
3 changes: 3 additions & 0 deletions onadata/apps/interview/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
11 changes: 11 additions & 0 deletions onadata/apps/interview/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.urls import path
from . import views


urlpatterns = [
path(
"form/<int:pk>/",
views.FetchOnadataFormView.as_view(),
name="form_id",
),
]
68 changes: 68 additions & 0 deletions onadata/apps/interview/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import requests
from requests.auth import HTTPBasicAuth
from django.http import JsonResponse
from rest_framework.generics import ListAPIView
from onadata.apps.logger.models import XForm
import xmltodict
from django.shortcuts import get_object_or_404
from rest_framework import status
import os
from rest_framework.authentication import TokenAuthentication, BasicAuthentication
from rest_framework.response import Response
from django.shortcuts import render
import json


# Go to http://localhost:8000/api/v1/form/<form_id>/
class FetchOnadataFormView(ListAPIView):
lookup_field = "pk"
authentication_classes = [BasicAuthentication, TokenAuthentication]

def get(self, request, *args, **kwargs):
try:
# Define authentication of admin user credentials
username = "kenlao" # Replace with environmental variables in production, I used this for simplicity
password = "admin123"

# Define the endpoint URL
pk = kwargs.get("pk")
model = get_object_or_404(XForm, id=pk)
if model:
endpoint = f"http://localhost:8000/api/v1/formlist/{pk}"

# Send a GET request to the endpoint with basic authentication
response = requests.get(
endpoint, auth=HTTPBasicAuth(username, password)
)

# Check for HTTP errors
response.raise_for_status()

# Access the XML response as text
xml_data = response.text

# Parse the XML into a Python dictionary using xmltodict
data_dict = xmltodict.parse(xml_data)
h_head = data_dict.get("h:html", {}).get("h:head", {})

# Return the parsed h_head as JSON response
# return JsonResponse(h_head, safe=False)
return render(
request, "display_data.html", {"data": json.dumps(h_head)}
)

except requests.exceptions.HTTPError as http_err:
return Response(
{"error": f"HTTP error occurred: {str(http_err)}"},
status=status.HTTP_400_BAD_REQUEST,
)
except requests.exceptions.RequestException as req_err:
return Response(
{"error": f"Request error: {str(req_err)}"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
except Exception as e:
return Response(
{"error": f"An unexpected error occurred: {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
)
2 changes: 1 addition & 1 deletion onadata/apps/logger/models/xform_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class XFormVersion(models.Model):
json = models.TextField()

def __str__(self):
return f"{self.xform.title}-{self.version}"
return f"{self.xform.title}-{self.version}-{self.xform.form_id}"

class Meta:
unique_together = ["xform", "version"]
8 changes: 8 additions & 0 deletions onadata/apps/main/static/js/display_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Get the raw JSON data passed from Django
let rawJsonData = document.getElementById('json-data').textContent;

// Parse the JSON string into a JavaScript object
let jsonData = JSON.parse(rawJsonData);

// Display the JSON data in a formatted way
document.getElementById('json-data').textContent = JSON.stringify(jsonData, null, 2);
10 changes: 10 additions & 0 deletions onadata/apps/main/templates/display_data.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!-- templates/display_data.html -->
{% load i18n %}
{% load static %}

<body>
<h1>Fetched JSON Data</h1>
<pre id="json-data">{{data | safe }}</pre>
<script type="text/javascript" src="{{STATIC_URL}}js/display_data.js"></script>

</body>
3 changes: 2 additions & 1 deletion onadata/apps/main/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# enable the admin:
from django.contrib import admin
from django.contrib.staticfiles import views as staticfiles_views
from django.urls import include, re_path
from django.urls import include, re_path, path
from django.views.generic import RedirectView

from onadata.apps import sms_support
Expand All @@ -39,6 +39,7 @@
admin.autodiscover()

urlpatterns = [
re_path("^api/v1/", include("onadata.apps.interview.urls")),
# change Language
re_path(r"^i18n/", include(i18n)),
re_path("^api/v1/", include(api_v1_router.urls)),
Expand Down
5 changes: 4 additions & 1 deletion onadata/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,12 +206,14 @@
"oauth2_provider",
"rest_framework",
"rest_framework.authtoken",
"rest_framework_simplejwt",
"taggit",
"onadata.apps.logger",
"onadata.apps.viewer",
"onadata.apps.main",
"onadata.apps.restservice",
"onadata.apps.api",
"onadata.apps.interview",
"guardian",
"onadata.apps.sms_support",
"onadata.libs",
Expand Down Expand Up @@ -292,12 +294,13 @@
"rest_framework.permissions.AllowAny",
],
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.TokenAuthentication",
"rest_framework_simplejwt.authentication.JWTAuthentication",
"onadata.libs.authentication.DigestAuthentication",
"onadata.libs.authentication.TempTokenAuthentication",
"onadata.libs.authentication.EnketoTokenAuthentication",
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
"DEFAULT_RENDERER_CLASSES": (
"rest_framework.renderers.JSONRenderer",
Expand Down
1 change: 1 addition & 0 deletions onadata/settings/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# settings.py)
from onadata.settings.staging_example import * # noqa pylint: disable=W0401,W0614

# DEBUG = True

ALLOWED_HOSTS = ["*"]

Expand Down
2 changes: 1 addition & 1 deletion onadata/settings/travis_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

PASSWORD_HASHERS = ("django.contrib.auth.hashers.MD5PasswordHasher",)

DEBUG = False
DEBUG = True
TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG
MIDDLEWARE = (
"django.middleware.common.CommonMiddleware",
Expand Down
1 change: 1 addition & 0 deletions requirements/docs.pip
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ tomli==2.0.1
# via sphinx
urllib3==2.2.2
# via requests
djangorestframework-simplejwt