Commit 2423dd97 authored by nano's avatar nano

fixed permission error and implemented delete functions

parent 2155cb0a
Pipeline #78 passed with stage
in 58 seconds
......@@ -27,8 +27,8 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
SECRET_KEY = ''
SERVER_NAME = ''
FIEX_DATA_FOLDER = '/etc/fiex/data'
FIEX_DATA_FOLDER_FILE_PERM_DEFAULT = 755
FIEX_DATA_FOLDER_DIR_PERM_DEFAULT = 644
FIEX_DATA_FOLDER_FILE_PERM_DEFAULT = 0o644
FIEX_DATA_FOLDER_DIR_PERM_DEFAULT = 0o755
FIEX_VALIDATOR_REGEX_PATH = r"^([\w\s\d\.\/\\\-_]+)$"
FIEX_VALIDATOR_REGEX_TEXT = r"^([\w\s\d\.\/\\\-_]+)$"
FIEX_VALIDATOR_REGEX_TOKEN = r"^([\w\s\d]+)$"
......
......@@ -53,6 +53,6 @@ class OperationNotPermittedException(FiexException):
class IllegalCharactersException(FiexException):
"""
Raised if a parameters contains illegal characters
Raised if a parameter contains illegal characters
"""
pass
# Generated by Django 2.1.3 on 2018-12-09 13:59
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
import fiexapp.validators
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('fiexapp', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='FiexFile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('path', models.CharField(max_length=500, unique=True, validators=[fiexapp.validators.validate_path])),
('comment', models.CharField(max_length=500, null=True, validators=[fiexapp.validators.validate_text])),
('expiration_date', models.DateField(null=True, verbose_name='Date when file should be deleted')),
('exchange', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='fiexapp.Exchange')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.RemoveField(
model_name='file',
name='belongs_to_exchange',
),
migrations.RemoveField(
model_name='file',
name='created_by_user',
),
migrations.DeleteModel(
name='File',
),
]
......@@ -59,12 +59,17 @@ class Exchange(models.Model):
description = models.CharField('description', max_length=300, validators=[validate_text])
creation_date = models.DateTimeField('date created')
def clean(self):
def setup(self):
"""
Should be called, after the exchange has been created, to set it up
:return: None
"""
try:
self._create_data_store_root_dir()
except FileExistsError:
except FileExistsError as _e:
pass
super(Exchange, self).clean()
self.create_initial_permissions()
"""
Permissions
......@@ -151,7 +156,7 @@ class Exchange(models.Model):
dest_path = Path(settings.FIEX_DATA_FOLDER, self.token)
return str(dest_path.absolute())
def _path_from_exchange_data_dir_root(self, path_str: str):
def path_from_exchange_data_dir_root(self, path_str: str):
"""
this function should always be called when dealing with paths to prevent directory traversal.
It assures that the path is relative to the root dir of the exchange data dir
......@@ -178,7 +183,7 @@ class Exchange(models.Model):
:raises FileExistsError if the directory already exists
"""
assert isinstance(path, str)
destination_path = Path(self._path_from_exchange_data_dir_root(path))
destination_path = Path(self.path_from_exchange_data_dir_root(path))
if destination_path.exists():
raise FileExistsError('dir at ' + destination_path + ' already exists')
else:
......@@ -192,7 +197,7 @@ class Exchange(models.Model):
:param not_empty_ok: delete even if the directory is not empty
:return: None
"""
dir_to_delete = Path(self._path_from_exchange_data_dir_root(path))
dir_to_delete = Path(self.path_from_exchange_data_dir_root(path))
if not dir_to_delete.exists() or not dir_to_delete.is_dir():
raise FileNotFoundError('the given path doesn\'t point to a dir or doesn\'t exist')
......@@ -204,7 +209,8 @@ class Exchange(models.Model):
if entity.is_dir():
self.delete_dir(entity_path_str, not_empty_ok=True)
elif entity.is_file():
file = File.objects.select_related().filter(belongs_to_exchange=self).filter(path=entity_path_str)[
file = \
FiexFile.objects.select_related().filter(exchange=self).filter(path=entity_path_str)[
0]
file.delete()
else:
......@@ -265,32 +271,31 @@ class PermissionGranted(models.Model):
time_granted = models.DateTimeField(null=True)
class File(models.Model):
class FiexFile(models.Model):
path = models.CharField(max_length=500, unique=True, validators=[validate_path])
comment = models.CharField(max_length=500, null=True, validators=[validate_text])
expiration_date = models.DateField(verbose_name="Date when file should be deleted", null=True)
created_by_user = models.ForeignKey(User, on_delete=models.CASCADE)
belongs_to_exchange = models.ForeignKey(Exchange, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
exchange = models.ForeignKey(Exchange, on_delete=models.CASCADE)
def absolute_path(self):
return self.belongs_to_exchange._path_from_exchange_data_dir_root(self.path)
return self.exchange.path_from_exchange_data_dir_root(self.path)
def write_content_from_mem(self, content: bytes, path: str, override: bool) -> None:
def write_content_from_mem(self, content: bytes, override: bool) -> None:
"""
creates a new file with the given content and safes it into the specified path.
The method does not create any not existing dirs
:param content: the content to write
:param path: the path of the file, relative from the exchange root
:param override: must be true if an existing file should be overriden
:return: None
"""
try:
dest_path = self.path_from_exchange_data_dir_root(path)
dest_path = Path(self.exchange.path_from_exchange_data_dir_root(self.path))
if override:
if not dest_path.exists():
raise FileNotFoundError('no file at ' + path + ' but override is set to true')
raise FileNotFoundError('no file at ' + self.path + ' but override is set to true')
with dest_path.open('wb') as dest_file:
if not dest_file.writable():
......@@ -298,7 +303,7 @@ class File(models.Model):
dest_file.write(content)
else:
if dest_path.exists():
raise FileExistsError('path ' + path + ' already exists in ' + str(self))
raise FileExistsError('path ' + self.path + ' already exists in ' + str(self))
with dest_path.open('wb') as dest_file:
if not dest_file.writable():
......@@ -335,4 +340,4 @@ class File(models.Model):
except FileNotFoundError:
pass
super(File, self).delete(using, keep_parents)
super(FiexFile, self).delete(using, keep_parents)
......@@ -25,8 +25,8 @@ from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
from fiexapp.exceptions import OperationNotPermittedException
from fiexapp.models import Exchange, gen_random_token, hash_password, Permission, File
from fiexapp.exceptions import OperationNotPermittedException, DirectoryNotEmptyException
from fiexapp.models import Exchange, gen_random_token, hash_password, Permission, FiexFile
FILTER_FUZZING = [ \
""""';alert(String.fromCharCode(88,83,83))//';""", \
......@@ -65,6 +65,7 @@ class ExchangeTestCase(TestCase):
self.test_exchange1 = Exchange.objects.create(description="permtest", creation_date=timezone.now(),
created_by=self.test_user1)
self.test_exchange1.save()
self.test_exchange1.setup()
self.test_exchange1.create_initial_permissions()
def test_object_creation(self):
......@@ -117,21 +118,36 @@ class ExchangeTestCase(TestCase):
self.assertTrue(os.path.commonprefix([settings.FIEX_DATA_FOLDER, exchange_data_dir_path]))
def test_path_from_exchange_data_dir_root(self):
self.assertEqual(self.test_exchange1._path_from_exchange_data_dir_root('test' + os.sep + 'a'),
self.assertEqual(self.test_exchange1.path_from_exchange_data_dir_root('test' + os.sep + 'a'),
os.path.join(self.test_exchange1._data_store_dir_path(), 'test' + os.sep + 'a'))
with self.assertRaises(OperationNotPermittedException):
self.test_exchange1._path_from_exchange_data_dir_root('/test' + os.sep + 'a')
self.test_exchange1.path_from_exchange_data_dir_root('/test' + os.sep + 'a')
with self.assertRaises(OperationNotPermittedException):
self.test_exchange1._path_from_exchange_data_dir_root('test' + os.sep + '..' + os.sep + '..' + os.sep + 'a')
self.test_exchange1.path_from_exchange_data_dir_root('test' + os.sep + '..' + os.sep + '..' + os.sep + 'a')
def test_folder_creation(self):
self.test_exchange1.mkdir('test_folder_creation')
def test_folder_destruction(self):
self.test_exchange1.mkdir('test_folder_creation')
self.test_exchange1.delete_dir('test_folder_creation', False)
# delete empty dir
self.test_exchange1.mkdir('test_folder_destruction1')
self.test_exchange1.delete_dir('test_folder_destruction1', False)
# delete not empty dir
self.test_exchange1.mkdir('test_folder_destruction2')
new_file_path = 'test_folder_destruction2' + os.sep + 'new_file.txt'
new_file = FiexFile(path=new_file_path, comment='test directory delete', user=self.test_user1,
exchange=self.test_exchange1)
new_file.save()
new_file.write_content_from_mem("test".encode(), False)
with self.assertRaises(DirectoryNotEmptyException):
self.test_exchange1.delete_dir('test_folder_destruction2', False)
self.test_exchange1.delete_dir('test_folder_destruction2', True)
self.assertTrue(FiexFile.objects.select_related().filter(exchange=self.test_exchange1).filter(
path=new_file_path).count() == 0)
class PermissionTestCase(TestCase):
def setUp(self):
......@@ -146,9 +162,10 @@ class ExchangeTestCase(TestCase):
self.test_exchange1 = Exchange.objects.create(description="permtest", creation_date=timezone.now(),
created_by=self.test_user1)
self.test_exchange1.save()
self.test_file1 = File.objects.create(path=('test' + os.sep + 'test.txt'),
created_by_user=self.test_user1,
belongs_to_exchange=self.test_exchange1)
self.test_exchange1.setup()
self.test_file1 = FiexFile.objects.create(path=('test' + os.sep + 'test.txt'),
created_by_user=self.test_user1,
belongs_to_exchange=self.test_exchange1)
self.test_file1.save()
def test_object_destruction(self):
......
import re
from django.conf import settings
from django.core.exceptions import ValidationError
......@@ -50,7 +51,7 @@ def validate_token(value):
validates a given path value a regex specified in django settings
:param value: the value to validate
:return: bool
:returns True if the validation has been successfull
:returns True if the validation has been successful
:raise ValidationError
:raises if the validation fails
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment