Skip to content

Commit

Permalink
Transcribe the API endpoints from Webapp2 to Django (#143)
Browse files Browse the repository at this point in the history
* API for check NGO URL

* API for getting all NGOs

* WIP API webhooks

* Move some URLs back to TODO
  • Loading branch information
danniel authored Jan 24, 2024
1 parent 8609ed9 commit a9db710
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 19 deletions.
1 change: 1 addition & 0 deletions backend/donations/models/__init__
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .main import *
27 changes: 27 additions & 0 deletions backend/donations/models/jobs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from .main import Ngo
from users.models import User


class Job(models.Model):
"""Keep track for download jobs"""

ngo = models.ForeignKey(Ngo, verbose_name=_("NGO"), on_delete=models.CASCADE, db_index=True)
owner = models.ForeignKey(User, verbose_name=_("owner"), on_delete=models.CASCADE, db_index=True)
status = models.CharField(
verbose_name=_("status"),
blank=False,
null=False,
default="new",
choices=("new", "error", "done"),
max_length=5,
db_index=True,
)
url = models.URLField(verbose_name=_("URL"), blank=True, null=False, default="", max_length=255)
date_created = models.DateTimeField(verbose_name=_("date created"), db_index=True, auto_now_add=timezone.now)

def __str__(self):
return f"{self.owner} {self.ngo} {self.status}"
File renamed without changes.
4 changes: 2 additions & 2 deletions backend/donations/views/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from django.conf import settings
from django.core.exceptions import PermissionDenied, BadRequest
from django.core.mail import send_mail
from django.urls import reverse
from django.http import Http404
from django.shortcuts import redirect, render
from django.template.loader import render_to_string
from django.http import Http404
from django.urls import reverse
from django.utils import timezone

from users.models import User
Expand Down
107 changes: 94 additions & 13 deletions backend/donations/views/api.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,53 @@
from django.views.decorators.csrf import csrf_exempt
import json

import logging
from django.urls import reverse_lazy
from django.contrib.auth.decorators import login_required
from django.conf import settings
from django.core.exceptions import PermissionDenied, BadRequest
from django.http import HttpResponse
from django.http import JsonResponse
from django.urls import reverse
from django.utils.decorators import method_decorator

from ..models import Ngo
from ..models.jobs import Job
from .base import BaseHandler, AccountHandler


logger = logging.getLogger(__name__)


class CheckNgoUrl(AccountHandler):
def get(self, request, *args, **kwargs):
raise NotImplementedError("CheckNgoUrl not implemented yet")
def get(self, request, ngo_url, *args, **kwargs):
# if we don't receive an ngo url or it's not a logged in user or not and admin
if not ngo_url or not request.user and not request.user.is_staff:
raise PermissionDenied()

if not Ngo.objects.filter(slug=ngo_url).count():
return HttpResponse()
else:
raise BadRequest()


class NgosApi(BaseHandler):
template_name = "all-ngos.html"
def get(self, request, *args, **kwargs):
# get all the visible ngos
ngos = Ngo.objects.filter(is_active=True).all()

response = []
for ngo in ngos:
response.append(
{
"name": ngo.name,
"url": reverse("twopercent", kwargs={"ngo_url": ngo.slug}),
"logo": ngo.logo if ngo.logo else settings.DEFAULT_NGO_LOGO,
"active_region": ngo.active_region,
"description": ngo.description,
}
)

return JsonResponse(response, safe=False)


class GetNgoForm(BaseHandler):
Expand All @@ -23,17 +60,61 @@ def get(self, request, *args, **kwargs):
raise NotImplementedError("GetNgoForms not implemented yet")


@method_decorator(csrf_exempt, name="dispatch")
@method_decorator(login_required(login_url=reverse_lazy("login")), name="dispatch")
class GetUploadUrl(AccountHandler):
def get(self, request, *args, **kwargs):
raise NotImplementedError("GetUploadUrl not implemented yet")

def post(self, request, *args, **kwargs):
# logo_file = request.FILES.get("files")
# print(logo_file)
raise NotImplementedError("GetUploadUrl not implemented yet")
files = request.FILES
if len(files) != 1:
raise BadRequest()

ngo = request.user.ngo
if not ngo:
raise BadRequest()
# # TODO: should we create the NGO here?
# ngo = Ngo.objects.create()
# ngo.save()
# request.user.ngo = ngo
# request.user.save()

ngo.logo = files[0]
ngo.save()

self.return_json({"file_urls": [ngo.logo.url]})


class Webhook(BaseHandler):
def get(self, request, *args, **kwargs):
raise NotImplementedError("Webhook not implemented yet")
def post(self, request, *args, **kwargs):
body = json.decode(request.body)

data = body.get("data", {})
job_id = body.get("jobId")
error = body.get("error")
url = body.get("url")

if not job_id:
logger.error("Did not receive jobId argument")
raise BadRequest()

# mark the job as done
try:
job = Job.objects.get(id=job_id)
except Job.DoesNotExist:
logger.error("Received an webhook. Could not find job with id {}".format(data.get("jobId")))
raise BadRequest()

if job.status == "done":
logger.warning("Job with id {} is already done. Duplicate webhook".format(job.id))

if url:
job.url = url
job.status = "done"
elif error:
job.status = "error"

job.save()

# TODO:
# send email
# self.send_dynamic_email(
# template_id="d-312ab0a4221944e3ac728ae08c504a7c", email=job.owner.email, data={"link": url}
# )
9 changes: 5 additions & 4 deletions backend/redirectioneaza/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,17 @@
path("contul-meu", MyAccountHandler.as_view(), name="contul-meu"),
path("asociatia", NgoDetailsHandler.as_view(), name="asociatia"),
path("date-cont", MyAccountDetailsHandler.as_view(), name="date-contul-meu"),
# APIs
path("api/ngo/check-url/<ngo_url>", CheckNgoUrl.as_view(), name="api-ngo-check-url"),
path("api/ngos", NgosApi.as_view(), name="api-ngos"),
#
#
# TODO: all the URLs until END_OF_TODO need to be implemented
#
path("api/ngo/check-url/<ngo_url>", CheckNgoUrl.as_view(), name="api-ngo-check-url"),
path("api/ngo/upload-url", GetUploadUrl.as_view(), name="api-ngo-upload-url"),
path("webhook", Webhook.as_view(), name="webhook"),
path("api/ngo/upload-url", GetUploadUrl.as_view(), name="api-ngo-upload-url"), # TODO
path("api/ngo/form/<ngo_url>", GetNgoForm.as_view(), name="api-ngo-form-url"),
path("api/ngo/forms/download", GetNgoForms.as_view(), name="api-ngo-forms"),
path("api/ngos", NgosApi.as_view(), name="api-ngos"),
path("webhook", Webhook.as_view(), name="webhook"),
# Cron routes
path("cron/stats", Stats.as_view()),
path("cron/ngos/remove-form", NgoRemoveForms.as_view(), name="ngo-remove-form"),
Expand Down

0 comments on commit a9db710

Please sign in to comment.