Skip to content

Commit

Permalink
feat: add a thin proxy API btw LMS and v1
Browse files Browse the repository at this point in the history
- Add apps.py and entry points for the app to be detected by LMS
- create a thin proxy API, this api will act as a middleware.
  edx-platdorm will call this api instead of forum v1 and this
  thin proxy api will call forum v1 APIs.
- implement get, post, put, delete mathods
- add sample curl requests
  • Loading branch information
Muhammad Faraz Maqsood committed Jul 31, 2024
1 parent b0a5907 commit e266c42
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 5 deletions.
2 changes: 2 additions & 0 deletions forum.egg-info/entry_points.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[lms.djangoapp]
forum = forum.apps:ForumConfig
20 changes: 19 additions & 1 deletion forum/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,29 @@
"""

from django.apps import AppConfig
from edx_django_utils.plugins import PluginURLs, PluginSettings
from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType


class ForumConfig(AppConfig):
"""
Configuration for the forum Django application.
"""

name = 'forum'
name = "forum"

plugin_app = {
PluginURLs.CONFIG: {
ProjectType.LMS: {
PluginURLs.NAMESPACE: "forum",
PluginURLs.REGEX: r"^forum",
PluginURLs.RELATIVE_PATH: "urls",
}
},
PluginSettings.CONFIG: {
ProjectType.LMS: {
SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: "settings.common"},
SettingsType.PRODUCTION: {PluginSettings.RELATIVE_PATH: "settings.production"},
}
},
}
Empty file added forum/settings/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions forum/settings/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""
Common settings for forum app.
"""


def plugin_settings(settings):
"""
Common settings for forum app
Set these variables in the Tutor Config or lms.yml for local testing
"""
settings.FORUM_PORT = "4567"
10 changes: 10 additions & 0 deletions forum/settings/production.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""
Production settings for forum app.
"""


def plugin_settings(settings):
"""
Production settings for forum app
"""
settings.FORUM_PORT = settings.ENV_TOKENS.get("FORUM_PORT", settings.FORUM_PORT)
9 changes: 5 additions & 4 deletions forum/urls.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""
URLs for forum.
"""
from django.urls import re_path # pylint: disable=unused-import
from django.views.generic import TemplateView # pylint: disable=unused-import

from django.urls import path # pylint: disable=unused-import
from forum.views import ForumProxyAPIView


urlpatterns = [
# TODO: Fill in URL patterns and views here.
# re_path(r'', TemplateView.as_view(template_name="forum/base.html")),
path("/forum_proxy<path:suffix>/", ForumProxyAPIView.as_view(), name="forum_proxy"),
]
141 changes: 141 additions & 0 deletions forum/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""Forum Views"""

import logging
import requests

from django.conf import settings
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny

from common.djangoapps.util.json_request import JsonResponse

logger = logging.getLogger(__name__)


class ForumProxyAPIView(APIView):
"""
An Proxy API View to Redirect All API requests to forum/cs_comments_service urls
"""

permission_classes = (AllowAny,)
COMMENTS_SERVICE_URL = f"http://forum:{settings.FORUM_PORT}"

def post(self, request, suffix):
"""
Catches post requests and sends it to forum/cs_comments_service post urls
"""
request_headers = {
"X-Edx-Api-Key": request.headers.get("X-Edx-Api-Key"),
"Accept-Language": request.headers.get("Accept-Language"),
}
request_data = request.data
url = self.COMMENTS_SERVICE_URL + suffix

"""
Will be removed once start migrating the endpoints
sample curl request to /:commentable_id/threads POST:
curl --location 'http://local.edly.io:8000/forum/forum_proxy/api/v1/course123/threads/' \
--header 'X-Csrftoken: kjGJPW6nPDGpHd23bBtlPhlQYooctsDDuH9SycovPI7vdWODBAstmbT1HaGWgX7Z' \
--header 'X-Edx-Api-Key: forumapikey' \
--header 'Accept-Language: en' \
--header 'Content-Type: application/json' \
--header 'Cookie: csrftoken=kyDjTqsiafBgGTWKA99iH4IlTWsUXFEw; edx-user-info="{\"version\": 1\054 \"username\": \"faraz\"\054 \"email\": \"[email protected]\"\054 \"header_urls\": {\"logout\": \"http://local.edly.io:8000/logout\"\054 \"account_settings\": \"http://local.edly.io:8000/account/settings\"\054 \"learner_profile\": \"http://local.edly.io:8000/u/faraz\"\054 \"resume_block\": \"http://local.edly.io:8000/courses/course-v1:Arbisoft+SE002+2024_S2/jump_to/block-v1:Arbisoft+SE002+2024_S2+type@problem+block@a654102da8774b2fbc9bba69e17ae048\"}\054 \"user_image_urls\": {\"full\": \"http://local.edly.io:8000/static/images/profiles/default_500.png\"\054 \"large\": \"http://local.edly.io:8000/static/images/profiles/default_120.png\"\054 \"medium\": \"http://local.edly.io:8000/static/images/profiles/default_50.png\"\054 \"small\": \"http://local.edly.io:8000/static/images/profiles/default_30.png\"}}"; edxloggedin=true; lms_sessionid=1|x89atra67zu0k89rp3jo7ay6itx49bo5|L7fBSktC09GH|IjAzZGQ4MDIwMjNkMGQxNmUwNGQ0NDM3NjhlYjQ1Y2UwNjUxMzkwY2Q2MTY0YzNmZTZlNWMzNTM3MjhiMDQ3YWMi:1sZ6B9:wqkfFTnH2DmApEx5XRehMNEdhvFiXLoZ6NEgc1GHXNI' \
--data '{
"body": "<p>test post request 1</p>",
"anonymous": false,
"anonymous_to_peers": false,
"course_id": "course-v1:Arbisoft+SE002+2024_S2",
"commentable_id": "course",
"thread_type": "discussion",
"title": "Test"
}'
Uncomment below lines of code if want to test above curl request, when called from edx-platform suffix should have required params
"""
# user_id = request.user.id
# url = url + (f"&user_id={user_id}" if "?" in url else f"?user_id={user_id}")

logger.info(f"Post Request to cs_comments_service url: {url}")
response = requests.post(url, data=request_data, headers=request_headers)
return JsonResponse(response.json(), status=response.status_code)

def get(self, request, suffix):
"""
Catches get requests and sends it to forum/cs_comments_service get urls
"""
request_headers = {
"X-Edx-Api-Key": request.headers.get("X-Edx-Api-Key"),
"Accept-Language": request.headers.get("Accept-Language"),
}
request_data = request.data
url = self.COMMENTS_SERVICE_URL + suffix

"""
Will be removed once start migrating the endpoints
sample curl request to /:commentable_id/threads GET:
curl --location --request GET 'http://local.edly.io:8000/forum/forum_proxy/api/v1/course123/threads/' \
--header 'X-Edx-Api-Key: forumapikey' \
--header 'Accept-Language: en' \
--header 'Content-Type: application/json' \
--data '{
"course_id": "course-v1:Arbisoft+SE002+2024_S2",
"commentable_id": "course123"
}'
Uncomment below lines of code if want to test above curl request, when called from edx-platform suffix should have required params
"""
# course_id = request_data.get("course_id")
# url = url + (f"&course_id={course_id}" if "?" in url else f"?course_id={course_id}")

logger.info(f"Get Request to cs_comments_service url: {url}")
response = requests.get(url, data=request_data, headers=request_headers)
return JsonResponse(response.json(), status=response.status_code)

def delete(self, request, suffix):
"""
Catches delete requests and sends it to forum/cs_comments_service delete urls
"""
request_headers = {
"X-Edx-Api-Key": request.headers.get("X-Edx-Api-Key"),
"Accept-Language": request.headers.get("Accept-Language"),
}
request_data = request.data
url = self.COMMENTS_SERVICE_URL + suffix

"""
Will be removed once start migrating the endpoints
sample curl request to /:commentable_id/threads DELETE:
curl --location --request DELETE 'http://local.edly.io:8000/forum/forum_proxy/api/v1/course123/threads/' \
--header 'X-Edx-Api-Key: forumapikey' \
--header 'Accept-Language: en' \
--data ''
"""

logger.info(f"Get Request to cs_comments_service url: {url}")
response = requests.delete(url, data=request_data, headers=request_headers)
return JsonResponse(response.json(), status=response.status_code)

def put(self, request, suffix):
"""
Catches post requests and sends it to forum/cs_comments_service post urls
"""
request_headers = {
"X-Edx-Api-Key": request.headers.get("X-Edx-Api-Key"),
"Accept-Language": request.headers.get("Accept-Language"),
}
request_data = request.data
url = self.COMMENTS_SERVICE_URL + suffix

"""
Will be removed once start migrating the endpoints
sample curl request to /threads/:thread_id PUT:
curl --location --request PUT 'http://local.edly.io:8000/forum/forum_proxy/api/v1/threads/66a9d1cca99edf001d4c5f77/' \
--header 'X-Edx-Api-Key: forumapikey' \
--header 'Accept-Language: en' \
--header 'Content-Type: application/json' \
--data '{
"body": "<p>test post request 11</p>"
}'
"""

logger.info(f"Put Request to cs_comments_service url: {url}")
response = requests.put(url, data=request_data, headers=request_headers)
return JsonResponse({}, status=response.status_code)
5 changes: 5 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,9 @@ def is_requirement(line):
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
],
entry_points={
'lms.djangoapp': [
'forum = forum.apps:ForumConfig',
],
},
)

0 comments on commit e266c42

Please sign in to comment.