Skip to content

Commit

Permalink
File path fixes
Browse files Browse the repository at this point in the history
* Configure ZIP jobs

* Fix the export job creation

* Refactor media file paths

* Fix NGO logos
  • Loading branch information
danniel authored Jan 31, 2024
1 parent 20cb211 commit 2c90867
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 4.2.9 on 2024-01-31 12:37

from django.db import migrations, models
import donations.models.main
import functools


class Migration(migrations.Migration):

dependencies = [
("donations", "0005_alter_ngo_prefilled_form"),
]

operations = [
migrations.AlterField(
model_name="donor",
name="pdf_file",
field=models.FileField(
blank=True,
upload_to=functools.partial(
donations.models.main.year_ngo_donor_directory_path, *("donation-forms",), **{}
),
verbose_name="PDF file",
),
),
migrations.AlterField(
model_name="ngo",
name="prefilled_form",
field=models.FileField(
blank=True,
storage=donations.models.main.select_public_storage,
upload_to=functools.partial(donations.models.main.year_ngo_directory_path, *("ngo-forms",), **{}),
verbose_name="form with prefilled ngo data",
),
),
]
39 changes: 28 additions & 11 deletions backend/donations/models/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,39 @@ def select_public_storage():
return storages["public"]


def _id_code(prefix: str, id: int) -> str:
def hash_id_secret(prefix: str, id: int) -> str:
return hashlib.sha1(f"{prefix}-{id}-{settings.SECRET_KEY}".encode()).hexdigest()[:10]


def ngo_directory_path(subdir, instance, filename) -> str:
# file will be uploaded to MEDIA_ROOT/ngo-<id>-<hash>/<subdir>/<filename>
return "{0}/ngo-{1}-{2}/{3}".format(subdir, instance.pk, _id_code("ngo", instance.pk), filename)
def ngo_directory_path(subdir: str, instance: "Ngo", filename: str) -> str:
"""
The file will be uploaded to MEDIA_ROOT/<subdir>/ngo-<id>-<hash>/<filename>
"""
return "{0}/ngo-{1}-{2}/{3}".format(subdir, instance.pk, hash_id_secret("ngo", instance.pk), filename)


def year_ngo_donor_directory_path(subdir, instance, filename) -> str:
def year_ngo_directory_path(subdir: str, instance: "Ngo", filename: str) -> str:
"""
The file will be uploaded to MEDIA_ROOT/<subdir>/<year>/ngo-<id>-<hash>/<filename>
"""
timestamp = timezone.now()
return "{0}/{1}/ngo-{2}-{3}/{4}".format(
subdir, timestamp.date().year, instance.pk, hash_id_secret("ngo", instance.pk), filename
)


def year_ngo_donor_directory_path(subdir: str, instance: "Donor", filename: str) -> str:
"""
The file will be uploaded to MEDIA_ROOT/<subdir>/<year>/ngo-<ngo.id>-<ngo.hash>/<id>_<hash>_<filename>
"""
timestamp = timezone.now()
return "{0}/{1}/ngo-{2}-{3}/{4}_{5}_{6}".format(
subdir,
timestamp.date().year,
instance.ngo.pk if instance.ngo else 0,
_id_code("ngo", instance.ngo.pk if instance.ngo else 0),
hash_id_secret("ngo", instance.ngo.pk if instance.ngo else 0),
instance.pk,
_id_code("donor", instance.pk),
hash_id_secret("donor", instance.pk),
filename,
)

Expand Down Expand Up @@ -156,7 +171,7 @@ class Ngo(models.Model):
blank=True,
null=False,
storage=select_public_storage,
upload_to=partial(ngo_directory_path, "prefilled_forms"),
upload_to=partial(year_ngo_directory_path, "ngo-forms"),
)

date_created = models.DateTimeField(verbose_name=_("date created"), db_index=True, auto_now_add=timezone.now)
Expand All @@ -174,8 +189,10 @@ def __str__(self):
return f"{self.name}"

def get_full_form_url(self):
if self.form_url:
return "https://{}/{}".format(settings.APEX_DOMAIN, self.form_url)
if self.prefilled_form:
return self.prefilled_form.url
elif self.form_url:
return self.form_url
else:
return ""

Expand Down Expand Up @@ -249,7 +266,7 @@ class Donor(models.Model):
verbose_name=_("PDF file"),
blank=True,
null=False,
upload_to=partial(year_ngo_donor_directory_path, "forms"),
upload_to=partial(year_ngo_donor_directory_path, "donation-forms"),
)

date_created = models.DateTimeField(verbose_name=_("date created"), db_index=True, auto_now_add=timezone.now)
Expand Down
97 changes: 81 additions & 16 deletions backend/donations/views/api.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import json
import logging

from urllib.request import Request, urlopen
from datetime import datetime, date

from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied, BadRequest
from django.core.files import File
from django.http import HttpResponse, JsonResponse, Http404
from django.shortcuts import redirect
from django.urls import reverse
from django.urls import reverse_lazy
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.utils import timezone
from django.views.decorators.csrf import csrf_exempt

from ..models.main import Ngo
from ..models.jobs import Job
from ..models.main import Ngo, Donor, ngo_directory_path, hash_id_secret
from ..models.jobs import Job, JobStatusChoices
from ..pdf import create_pdf
from .base import BaseHandler, AccountHandler

Expand Down Expand Up @@ -93,30 +97,91 @@ def get(self, request, ngo_url, *args, **kwargs):


class GetNgoForms(AccountHandler):
def get(self, request, *args, **kwargs):
raise NotImplementedError("GetNgoForms not implemented yet")
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect(reverse("login"))

ngo = request.user.ngo
if not ngo:
return redirect(reverse("contul-meu"))

DONATION_LIMIT = date(timezone.now().year, 5, 25)

now = timezone.now()
start_of_year = datetime(now.year, 1, 1, 0, 0)

if now.date() > DONATION_LIMIT:
return redirect(reverse("contul-meu"))

# get all the forms that have been completed since the start of the year
# and they are also signed
donations = Donor.objects.filter(ngo=ngo, date_created__gte=start_of_year, has_signed=True).all()

# extract only the urls from the array of models
urls = [u.pdf_file.url if u.pdf_file else u.pdf_url for u in donations if u.has_signed]

# if no forms
if len(urls) == 0:
logging.warn("Could not find any signed forms for this ngo: {}".format(ngo.id))
return redirect(reverse("contul-meu"))

# create job
job = Job(
ngo=ngo,
owner=request.user,
)
job.save()

export_destination = ngo_directory_path(
"exports", ngo, "export_{}_{}.zip".format(job.id, hash_id_secret(timezone.now(), job.id))
)

# make request
params = {
"passphrase": settings.ZIP_SECRET,
"urls": urls,
"path": export_destination,
"webhook": {
"url": "https://{}{}".format(settings.APEX_DOMAIN, reverse("webhook")),
"data": {"jobId": job.id},
},
}

request = Request(url=settings.ZIP_ENDPOINT, data=params, headers={"Content-type": "application/json"})

try:
httpresp = urlopen(request)
response = json.decode(httpresp.read())
logging.info(response)
httpresp.close()
except Exception as e:
logging.exception(e)
# if job failed to start remotely
job.status = JobStatusChoices.ERROR
job.save()
finally:
return redirect(reverse("contul-meu"))


@method_decorator(login_required(login_url=reverse_lazy("login")), name="dispatch")
@method_decorator(csrf_exempt, name="dispatch")
class GetUploadUrl(AccountHandler):
def post(self, request, *args, **kwargs):
files = request.FILES
if len(files) != 1:
logo_file = request.FILES.get("files")
if not logo_file:
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 = Ngo.objects.create()
ngo.save()
request.user.ngo = ngo
request.user.save()

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

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


class Webhook(BaseHandler):
Expand Down
10 changes: 4 additions & 6 deletions backend/donations/views/ngo.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def post(self, request, ngo_url):
self.donor.pdf_file.delete()
self.donor.pdf_file = None

self.donor.pdf_file.save("declaratia_completata.pdf", File(new_pdf))
self.donor.pdf_file.save("declaratie_semnata.pdf", File(new_pdf))
new_pdf.close()

# # TODO: Send email
Expand Down Expand Up @@ -306,9 +306,6 @@ def get_post_value(arg, add_to_error_list=True):
# self.return_error(errors)
# return

filename = "filled_form.pdf"
pdf = create_pdf(donor_dict, ngo_data)

# create the donor and save it
donor = Donor(
first_name=donor_dict["first_name"],
Expand All @@ -324,11 +321,12 @@ def get_post_value(arg, add_to_error_list=True):
# make a request to get geo ip data for this user
# geoip = self.get_geoip_data(),
ngo=ngo,
filename=filename,
# TODO: 'filename' is unused
)
donor.save()

donor.pdf_file.save(filename, File(pdf))
pdf = create_pdf(donor_dict, ngo_data)
donor.pdf_file.save("declaratie_nesemnata.pdf", File(pdf))

# close the file after it has been uploaded
pdf.close()
Expand Down
7 changes: 4 additions & 3 deletions backend/redirectioneaza/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@
CORS_ALLOWED_ORIGINS=(list, []),
CORS_ALLOW_ALL_ORIGINS=(bool, False),
# zipping settings
ZIPPY_URL=(str, "zippy:8000"),
ZIP_ENDPOINT=(str, "zippy:8000"),
ZIP_SECRET=(str, ""),
# email settings
EMAIL_SEND_METHOD=(str, "async"),
EMAIL_BACKEND=(str, "django.core.mail.backends.console.EmailBackend"),
Expand Down Expand Up @@ -446,5 +447,5 @@

CAPTCHA_ENABLED = True if CAPTCHA_PUBLIC_KEY else False


USER_FORMS = "documents"
ZIP_ENDPOINT = env.str("ZIP_ENDPOINT")
ZIP_SECRET = env.str("ZIP_SECRET")
2 changes: 1 addition & 1 deletion backend/static_extras/js/ngo/ngo-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ $(function () {
var uploadLogo = $("#upload-logo");
var displayLogo = $("#display-logo");

var aws_api_url = '/api/ngo/upload-url';
var aws_api_url = '/api/ngo/upload-url/';
var photoLogoClass = "fa-picture-o";
var loadingLogoClass = "fa-spinner fa-pulse";

Expand Down
2 changes: 1 addition & 1 deletion backend/templates/v1/all-ngos.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h1>Asociații pentru care poți redirecționa 3.5%</h1>
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="ong-panel panel panel-default">
<a href="{{ ngo.slug }}">
{% set logo = ngo.logo_url if ngo.logo_url else DEFAULT_NGO_LOGO %}
{% set logo = ngo.logo.url if ngo.logo else DEFAULT_NGO_LOGO %}
<div class="ong-logo">
<img src="{{ logo }}" class="img-responsive center-block" alt="{{ ngo.name }} logo" />
</div>
Expand Down
8 changes: 4 additions & 4 deletions backend/templates/v1/components/ngo-details-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
</div>
<div class="form-group">
<div class="col-xs-4 text-center">
<div id="upload-logo" class="{{ 'hidden' if ngo.logo_url }}">
<div id="upload-logo" class="{{ 'hidden' if ngo.logo }}">
<label for="ong-logo">
<i class="glyphicon glyphicon-picture upload-file-icon"></i>
<p>Logo-ul asociației</p>
</label>
<input type="file" id="ong-logo" class="hidden" accept="image/*" name="ong-logo" />
</div>
<div id="display-logo" class="text-center {{ 'hidden' if not ngo.logo_url }}">
<img id="ngo-logo" src="{{ ngo.logo_url if ngo }}" class="img-responsive center-block" />
<div id="display-logo" class="text-center {{ 'hidden' if not ngo.logo }}">
<img id="ngo-logo" src="{{ ngo.logo.url if ngo }}" class="img-responsive center-block" />
<span id="delete-ngo-logo" class="text-danger">Șterge</span>
<input type="hidden" id="ong-logo-url" name="ong-logo-url" value="{{ ngo.logo_url if ngo }}" />
<input type="hidden" id="ong-logo-url" name="ong-logo-url" value="{{ ngo.logo.url if ngo.logo }}" />
</div>
</div>
<div class="col-xs-8">
Expand Down
4 changes: 2 additions & 2 deletions backend/templates/v1/components/ngo-header.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<div class="col-xs-12 col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-6">
<div class="media ngo-details" itemscope itemtype ="http://schema.org/NGO" >
<div class="media-left">
{% if ngo.logo_url %}
<img class="media-object" itemprop="logo" src="{{ ngo.logo_url }}" />
{% if ngo.logo %}
<img class="media-object" itemprop="logo" src="{{ ngo.logo.url }}" />
{% endif %}
</div>
<div class="media-body">
Expand Down
2 changes: 1 addition & 1 deletion backend/templates/v1/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ <h4>
<div class="col-xs-6 col-sm-4 col-md-3">
<div class="ong-panel panel panel-default">
<a href="{{ ngo.slug }}">
{% set logo = ngo.logo_url if ngo.logo_url else DEFAULT_NGO_LOGO %}
{% set logo = ngo.logo.url if ngo.logo else DEFAULT_NGO_LOGO %}
<div class="ong-logo">
<img src="{{ logo }}" class="img-responsive center-block" alt="{{ ngo.name }} logo" />
</div>
Expand Down
6 changes: 3 additions & 3 deletions backend/templates/v1/twopercent.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
{% block additional_headers %}
<meta property="og:title" content="{{ ngo.name }}" />
<meta property="og:description" content="{{ ngo.description }}" />
{% if ngo.logo_url %}
<meta property="og:image" content="{{ ngo.logo_url }}" />
<meta property="og:image:secure_url" content="{{ ngo.logo_url }}" />
{% if ngo.logo %}
<meta property="og:image" content="{{ ngo.logo.url }}" />
<meta property="og:image:secure_url" content="{{ ngo.logo.url }}" />
{% endif %}

<meta property="og:type" content="website" />
Expand Down

0 comments on commit 2c90867

Please sign in to comment.