mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-06-10 11:00:22 +00:00
backups: Use new utility for handling file uploads
- Use dedicated directory for uploads - Uploaded backup archives are owned by root and read-only (0o600) Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net> [sunil: Fix checking the relativeness of file path before removing] [sunil: Create backups upload path recursively] Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
770ec09557
commit
56a055639d
@ -4,9 +4,8 @@ Decorators for the backup views.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import os
|
||||
|
||||
from . import SESSION_PATH_VARIABLE
|
||||
from . import privileged, SESSION_PATH_VARIABLE
|
||||
|
||||
|
||||
def delete_tmp_backup_file(function):
|
||||
@ -15,12 +14,12 @@ def delete_tmp_backup_file(function):
|
||||
XXX: Implement a better way to delete uploaded files.
|
||||
|
||||
"""
|
||||
|
||||
@functools.wraps(function)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
path = request.session.get(SESSION_PATH_VARIABLE, None)
|
||||
if path:
|
||||
if os.path.isfile(path):
|
||||
os.remove(path)
|
||||
privileged.remove_uploaded_archive(path)
|
||||
del request.session[SESSION_PATH_VARIABLE]
|
||||
return function(request, *args, **kwargs)
|
||||
|
||||
|
||||
@ -8,11 +8,13 @@ import re
|
||||
import subprocess
|
||||
import tarfile
|
||||
|
||||
from plinth import action_utils
|
||||
from plinth.actions import privileged, secret_str
|
||||
from plinth.utils import Version
|
||||
|
||||
TIMEOUT = 30
|
||||
BACKUPS_DATA_PATH = pathlib.Path('/var/lib/plinth/backups-data/')
|
||||
BACKUPS_UPLOAD_PATH = pathlib.Path('/var/lib/freedombox/backups-upload/')
|
||||
MANIFESTS_FOLDER = '/var/lib/plinth/backups-manifests/'
|
||||
|
||||
|
||||
@ -143,6 +145,24 @@ def list_repo(path: str,
|
||||
return json.loads(process.stdout.decode())
|
||||
|
||||
|
||||
@privileged
|
||||
def add_uploaded_archive(file_name: str, temporary_file_path: str):
|
||||
"""Store an archive uploaded by the user."""
|
||||
BACKUPS_UPLOAD_PATH.mkdir(parents=True, exist_ok=True)
|
||||
action_utils.move_uploaded_file(temporary_file_path, BACKUPS_UPLOAD_PATH,
|
||||
file_name, allow_overwrite=True,
|
||||
permissions=0o600)
|
||||
|
||||
|
||||
@privileged
|
||||
def remove_uploaded_archive(file_path: str):
|
||||
"""Delete the archive uploaded by the user."""
|
||||
resolved_file_path = pathlib.Path(file_path).resolve()
|
||||
if (resolved_file_path.is_relative_to(BACKUPS_UPLOAD_PATH)
|
||||
and resolved_file_path.is_file()):
|
||||
resolved_file_path.unlink()
|
||||
|
||||
|
||||
def _get_borg_version():
|
||||
"""Return the version of borgbackup."""
|
||||
process = _run(['borg', '--version'], stdout=subprocess.PIPE)
|
||||
|
||||
@ -5,7 +5,6 @@ Views for the backups app.
|
||||
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
from urllib.parse import unquote
|
||||
|
||||
@ -190,11 +189,13 @@ class UploadArchiveView(SuccessMessageMixin, FormView):
|
||||
return context
|
||||
|
||||
def form_valid(self, form):
|
||||
"""store uploaded file."""
|
||||
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
|
||||
self.request.session[SESSION_PATH_VARIABLE] = tmp_file.name
|
||||
for chunk in self.request.FILES['backups-file'].chunks():
|
||||
tmp_file.write(chunk)
|
||||
"""Store uploaded file."""
|
||||
uploaded_file = self.request.FILES['backups-file']
|
||||
# Hold on to Django's uploaded file. It will be used by other views.
|
||||
privileged.add_uploaded_archive(uploaded_file.name,
|
||||
uploaded_file.temporary_file_path())
|
||||
self.request.session[SESSION_PATH_VARIABLE] = str(
|
||||
privileged.BACKUPS_UPLOAD_PATH / uploaded_file.name)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user