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

Feature/16 storage util #18

Merged
merged 4 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/afs/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = ["*"]


# Application definition
Expand All @@ -44,6 +44,7 @@
"akvo.core_forms",
"akvo.core_node",
"akvo.core_data",
"akvo.utils",
]

MIDDLEWARE = [
Expand Down
33 changes: 33 additions & 0 deletions backend/akvo/utils/storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import os
from pathlib import Path
import shutil


class Storage:
def __init__(self, storage_path: str):
self.storage_path = storage_path

def upload(self, file: str, folder: str = None, filename: str = None):
storage_location = self.storage_path
if folder:
Path(f"{storage_location}/{folder}").mkdir(parents=True, exist_ok=True)
storage_location = f"{storage_location}/{folder}"
if not filename:
filename = file.split("/")[-1]
location = f"{storage_location}/{filename}"
shutil.copy2(file, location)
return location

def delete(self, url: str):
os.remove(f"{self.storage_path}/{url}")
return url

def check(self, url: str):
path = Path(f"{self.storage_path}/{url}")
return path.is_file()

def download(self, url: str):
if not self.check(url):
return None
with open(f"{self.storage_path}/{url}", "rb") as f:
return f.read()
Empty file.
49 changes: 49 additions & 0 deletions backend/akvo/utils/tests/test_storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import os
from django.test import TestCase
from storage import Storage


class StorageTestCase(TestCase):
def setUp(self):
# create a file
self.path = "/tmp"
self.file = "./test.txt"
with open(self.file, "w") as f:
f.write("test")
self.storage = Storage(storage_path=self.path)

def tearDown(self):
# delete the file
os.remove(self.file)

def test_upload(self):
self.storage.upload(file=self.file)
self.assertTrue(os.path.exists(f"{self.path}/{self.file}"))

# test upload with folder
self.storage.upload(file=self.file, folder="testing")
self.assertTrue(os.path.exists(f"{self.path}/testing/{self.file}"))
# test upload with filename
self.storage.upload(file=self.file, filename="test2.txt")
self.assertTrue(os.path.exists(f"{self.path}/test2.txt"))

def test_delete(self):
self.storage.upload(file=self.file)
self.storage.delete(url="test.txt")
self.assertFalse(os.path.exists(f"{self.path}/{self.file}"))

def test_check(self):
self.storage.upload(file=self.file)
self.assertTrue(self.storage.check(url="test.txt"))

def test_download(self):
self.storage.upload(file=self.file, folder="testing")
self.assertTrue(os.path.exists(f"{self.path}/testing/{self.file}"))
filename = self.file.split("/")[-1]
file = self.storage.download(url="testing/test.txt")
with open(f"{self.path}/testing/{filename}", "rb") as f:
self.assertEqual(f.read(), file)

# Failed Download
file = self.storage.download(url="testing/test2.txt")
self.assertFalse(file)
4 changes: 4 additions & 0 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ services:
- 8888:8888
frontend:
network_mode: service:mainnetwork
volumes:
- ${STORAGE_PATH}/images:/app/public/images:delegated
backend:
environment:
- WEBDOMAIN=https://afs.akvotest.org
network_mode: service:mainnetwork
volumes:
- ${STORAGE_PATH}:/app/storage:delegated
pgadmin:
image: dpage/pgadmin4:5.7
environment:
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ services:
- DB_HOST=db
- DEBUG=True
- DJANGO_SECRET=local-secret
- STORAGE_PATH
depends_on:
- db
frontend:
Expand Down
6 changes: 6 additions & 0 deletions frontend/nginx/conf.d/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ server {
proxy_pass http://localhost:8000;
}

location /images/ {
rewrite ^/images/(.*)$ /storage/images/$1 last;
expires 7d;
add_header Cache-Control "max-age=604800, public";
}

location / {
try_files $uri $uri/ /index.html;
}
Expand Down