Files
archy/scripts/tests/test_filebrowser_credentials.py
T

62 lines
2.9 KiB
Python
Raw Normal View History

import importlib.util
from pathlib import Path
import json
import os
import tempfile
import unittest
spec = importlib.util.spec_from_file_location('filebrowser_credentials', Path(__file__).resolve().parents[1] / 'filebrowser-credentials.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
class CredentialTests(unittest.TestCase):
def test_record_validation_rejects_defaults_and_malformed_credentials(self):
valid = {'schema': 1, 'username': 'archy-' + 'a' * 32, 'password': 'b' * 64}
self.assertEqual(module.credentials(valid), valid)
for values in [{**valid, 'username': 'admin'}, {**valid, 'password': 'admin'}, {**valid, 'schema': 2}, {**valid, 'password': 'x' * 64}, None]:
with self.assertRaises(module.ProvisionError):
module.credentials(values)
def test_atomic_secret_is_private_and_refuses_symlinks(self):
with tempfile.TemporaryDirectory() as tmp:
path = Path(tmp) / 'credential.json'
module.atomic_json(path, {'value': 'test'})
self.assertEqual(path.stat().st_mode & 0o777, 0o600)
self.assertEqual(json.loads(path.read_text()), {'value': 'test'})
target = Path(tmp) / 'target'
target.write_text('preserved')
path.unlink()
path.symlink_to(target)
with self.assertRaises(module.ProvisionError):
module.atomic_json(path, {})
self.assertEqual(target.read_text(), 'preserved')
def test_database_selection_preserves_legacy_and_configured_locations(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
self.assertEqual(module.database_path(root), '/data/filebrowser.db')
(root / 'database.db').touch()
self.assertEqual(module.database_path(root), '/data/database.db')
(root / 'filebrowser.db').touch()
with self.assertRaises(module.ProvisionError):
module.database_path(root)
(root / '.filebrowser.json').write_text(json.dumps({'database': '/data/database.db'}))
self.assertEqual(module.database_path(root), '/data/database.db')
def test_database_paths_fail_closed_on_traversal_or_symlinks(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
for database in ['/data/../outside.db', '/outside.db', None, '/data/a.db\n--flag']:
(root / '.filebrowser.json').write_text(json.dumps({'database': database}))
with self.assertRaises(module.ProvisionError):
module.database_path(root)
(root / '.filebrowser.json').write_text(json.dumps({'database': '/data/filebrowser.db'}))
(root / 'filebrowser.db').symlink_to(root / 'elsewhere')
with self.assertRaises(module.ProvisionError):
module.database_path(root)
if __name__ == '__main__':
unittest.main()