diff --git a/.drone.yml b/.drone.yml index 24142c8..0977dfc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -16,4 +16,10 @@ steps: - bandit -ll -r selfprivacy_api - name: formatting commands: - - black --check . \ No newline at end of file + - black --check . +- name: sonarqube + commands: + - sonar-scanner -Dsonar.projectKey=selfprivacy-api -Dsonar.sources=. -Dsonar.host.url=https://sonarqube.inex.dev -Dsonar.login=$TOKEN -Dsonar.branch.name=$DRONE_BRANCH + environment: + TOKEN: + from_secret: inex-sonarqube diff --git a/selfprivacy_api/resources/users.py b/selfprivacy_api/resources/users.py index 057a5e3..e7e3ccf 100644 --- a/selfprivacy_api/resources/users.py +++ b/selfprivacy_api/resources/users.py @@ -71,7 +71,6 @@ class Users(Resource): parser.add_argument("username", type=str, required=True) parser.add_argument("password", type=str, required=True) args = parser.parse_args() - hashing_command = ["mkpasswd", "-m", "sha-512", args["password"]] password_hash_process_descriptor = subprocess.Popen( hashing_command, @@ -82,7 +81,6 @@ class Users(Resource): hashed_password = password_hash_process_descriptor.communicate()[0] hashed_password = hashed_password.decode("ascii") hashed_password = hashed_password.rstrip() - # Check is username passes regex if not re.match(r"^[a-z_][a-z0-9_]+$", args["username"]): return {"error": "username must be alphanumeric"}, 400 diff --git a/selfprivacy_api/restic_controller/__init__.py b/selfprivacy_api/restic_controller/__init__.py index be533ac..24158b0 100644 --- a/selfprivacy_api/restic_controller/__init__.py +++ b/selfprivacy_api/restic_controller/__init__.py @@ -40,7 +40,6 @@ class ResticController: _initialized = False def __new__(cls): - print("new is called!") if not cls._instance: with cls._lock: cls._instance = super(ResticController, cls).__new__(cls) @@ -58,7 +57,6 @@ class ResticController: self.snapshot_list = [] self.error_message = None self._initialized = True - print("init is called!") self.load_configuration() self.write_rclone_config() self.load_snapshots() @@ -112,7 +110,6 @@ class ResticController: or self.state == ResticStates.RESTORING ): return - print("preparing to read snapshots") with subprocess.Popen( backup_listing_command, shell=False, diff --git a/tests/services/test_services.py b/tests/services/test_services.py index 859da5a..b059f90 100644 --- a/tests/services/test_services.py +++ b/tests/services/test_services.py @@ -4,8 +4,8 @@ import pytest def read_json(file_path): - with open(file_path, "r", encoding="utf-8") as f: - return json.load(f) + with open(file_path, "r", encoding="utf-8") as file: + return json.load(file) def call_args_asserts(mocked_object): diff --git a/tests/test_system.py b/tests/test_system.py index e7cfb0b..18be12c 100644 --- a/tests/test_system.py +++ b/tests/test_system.py @@ -5,12 +5,51 @@ import pytest from selfprivacy_api.utils import get_domain +def read_json(file_path): + with open(file_path, "r", encoding="utf-8") as file: + return json.load(file) + + @pytest.fixture def domain_file(mocker, datadir): mocker.patch("selfprivacy_api.utils.DOMAIN_FILE", datadir / "domain") return datadir +@pytest.fixture +def turned_on(mocker, datadir): + mocker.patch("selfprivacy_api.utils.USERDATA_FILE", new=datadir / "turned_on.json") + assert read_json(datadir / "turned_on.json")["autoUpgrade"]["enable"] == True + assert read_json(datadir / "turned_on.json")["autoUpgrade"]["allowReboot"] == True + assert read_json(datadir / "turned_on.json")["timezone"] == "Europe/Moscow" + return datadir + + +@pytest.fixture +def turned_off(mocker, datadir): + mocker.patch("selfprivacy_api.utils.USERDATA_FILE", new=datadir / "turned_off.json") + assert read_json(datadir / "turned_off.json")["autoUpgrade"]["enable"] == False + assert read_json(datadir / "turned_off.json")["autoUpgrade"]["allowReboot"] == False + assert read_json(datadir / "turned_off.json")["timezone"] == "Europe/Moscow" + return datadir + + +@pytest.fixture +def undefined_config(mocker, datadir): + mocker.patch("selfprivacy_api.utils.USERDATA_FILE", new=datadir / "undefined.json") + assert "autoUpgrade" not in read_json(datadir / "undefined.json") + assert "timezone" not in read_json(datadir / "undefined.json") + return datadir + + +@pytest.fixture +def no_values(mocker, datadir): + mocker.patch("selfprivacy_api.utils.USERDATA_FILE", new=datadir / "no_values.json") + assert "enable" not in read_json(datadir / "no_values.json")["autoUpgrade"] + assert "allowReboot" not in read_json(datadir / "no_values.json")["autoUpgrade"] + return datadir + + def test_wrong_auth(wrong_auth_client): response = wrong_auth_client.get("/system/pythonVersion") assert response.status_code == 401 @@ -18,3 +57,62 @@ def test_wrong_auth(wrong_auth_client): def test_get_domain(authorized_client, domain_file): assert get_domain() == "test-domain.tld" + + +## Timezones + + +def test_get_timezone_unauthorized(client, turned_on): + response = client.get("/system/configuration/timezone") + assert response.status_code == 401 + + +def test_get_timezone(authorized_client, turned_on): + response = authorized_client.get("/system/configuration/timezone") + assert response.status_code == 200 + assert response.get_json() == "Europe/Moscow" + + +def test_get_timezone_on_undefined(authorized_client, undefined_config): + response = authorized_client.get("/system/configuration/timezone") + assert response.status_code == 200 + assert response.get_json() == "Europe/Uzhgorod" + + +def test_put_timezone_unauthorized(client, turned_on): + response = client.put( + "/system/configuration/timezone", json={"timezone": "Europe/Moscow"} + ) + assert response.status_code == 401 + + +def test_put_timezone(authorized_client, turned_on): + response = authorized_client.put( + "/system/configuration/timezone", json={"timezone": "Europe/Helsinki"} + ) + assert response.status_code == 200 + assert read_json(turned_on / "turned_on.json")["timezone"] == "Europe/Helsinki" + + +def test_put_timezone_on_undefined(authorized_client, undefined_config): + response = authorized_client.put( + "/system/configuration/timezone", json={"timezone": "Europe/Helsinki"} + ) + assert response.status_code == 200 + assert ( + read_json(undefined_config / "undefined.json")["timezone"] == "Europe/Helsinki" + ) + + +def test_put_timezone_without_timezone(authorized_client, turned_on): + response = authorized_client.put("/system/configuration/timezone", json={}) + assert response.status_code == 400 + assert read_json(turned_on / "turned_on.json")["timezone"] == "Europe/Moscow" + + +def test_put_invalid_timezone(authorized_client, turned_on): + response = authorized_client.put( + "/system/configuration/timezone", json={"timezone": "Invalid/Timezone"} + ) + assert response.status_code == 400 + assert read_json(turned_on / "turned_on.json")["timezone"] == "Europe/Moscow" diff --git a/tests/test_system/no_values.json b/tests/test_system/no_values.json new file mode 100644 index 0000000..59e5e71 --- /dev/null +++ b/tests/test_system/no_values.json @@ -0,0 +1,50 @@ +{ + "backblaze": { + "accountId": "ID", + "accountKey": "KEY", + "bucket": "selfprivacy" + }, + "api": { + "token": "TEST_TOKEN", + "enableSwagger": false + }, + "bitwarden": { + "enable": true + }, + "cloudflare": { + "apiKey": "TOKEN" + }, + "databasePassword": "PASSWORD", + "domain": "test.tld", + "hashedMasterPassword": "HASHED_PASSWORD", + "hostname": "test-instance", + "nextcloud": { + "adminPassword": "ADMIN", + "databasePassword": "ADMIN", + "enable": true + }, + "resticPassword": "PASS", + "ssh": { + "enable": true, + "passwordAuthentication": true, + "rootKeys": [ + "ssh-ed25519 KEY test@pc" + ] + }, + "username": "tester", + "gitea": { + "enable": false + }, + "ocserv": { + "enable": true + }, + "pleroma": { + "enable": true + }, + "autoUpgrade": { + }, + "timezone": "Europe/Moscow", + "sshKeys": [ + "ssh-rsa KEY test@pc" + ] +} \ No newline at end of file