summary refs log tree commit diff
path: root/nixos/tests/radicale.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/tests/radicale.nix')
-rw-r--r--nixos/tests/radicale.nix209
1 files changed, 82 insertions, 127 deletions
diff --git a/nixos/tests/radicale.nix b/nixos/tests/radicale.nix
index 1d3679c82a2..5101628a682 100644
--- a/nixos/tests/radicale.nix
+++ b/nixos/tests/radicale.nix
@@ -1,140 +1,95 @@
+import ./make-test-python.nix ({ lib, pkgs, ... }:
+
 let
   user = "someuser";
   password = "some_password";
-  port = builtins.toString 5232;
+  port = "5232";
+  filesystem_folder = "/data/radicale";
+
+  cli = "${pkgs.calendar-cli}/bin/calendar-cli --caldav-user ${user} --caldav-pass ${password}";
+in {
+  name = "radicale3";
+  meta.maintainers = with lib.maintainers; [ dotlambda ];
 
-  common = { pkgs, ... }: {
+  machine = { pkgs, ... }: {
     services.radicale = {
       enable = true;
-      config = ''
-        [auth]
-        type = htpasswd
-        htpasswd_filename = /etc/radicale/htpasswd
-        htpasswd_encryption = bcrypt
-
-        [storage]
-        filesystem_folder = /tmp/collections
-      '';
+      settings = {
+        auth = {
+          type = "htpasswd";
+          htpasswd_filename = "/etc/radicale/users";
+          htpasswd_encryption = "bcrypt";
+        };
+        storage = {
+          inherit filesystem_folder;
+          hook = "git add -A && (git diff --cached --quiet || git commit -m 'Changes by '%(user)s)";
+        };
+        logging.level = "info";
+      };
+      rights = {
+        principal = {
+          user = ".+";
+          collection = "{user}";
+          permissions = "RW";
+        };
+        calendars = {
+          user = ".+";
+          collection = "{user}/[^/]+";
+          permissions = "rw";
+        };
+      };
     };
+    systemd.services.radicale.path = [ pkgs.git ];
+    environment.systemPackages = [ pkgs.git ];
+    systemd.tmpfiles.rules = [ "d ${filesystem_folder} 0750 radicale radicale -" ];
     # WARNING: DON'T DO THIS IN PRODUCTION!
     # This puts unhashed secrets directly into the Nix store for ease of testing.
-    environment.etc."radicale/htpasswd".source = pkgs.runCommand "htpasswd" {} ''
+    environment.etc."radicale/users".source = pkgs.runCommand "htpasswd" {} ''
       ${pkgs.apacheHttpd}/bin/htpasswd -bcB "$out" ${user} ${password}
     '';
   };
-
-in
-
-  import ./make-test-python.nix ({ lib, ... }@args: {
-    name = "radicale";
-    meta.maintainers = with lib.maintainers; [ aneeshusa infinisil ];
-
-    nodes = rec {
-      radicale = radicale1; # Make the test script read more nicely
-      radicale1 = lib.recursiveUpdate (common args) {
-        nixpkgs.overlays = [
-          (self: super: {
-            radicale1 = super.radicale1.overrideAttrs (oldAttrs: {
-              propagatedBuildInputs = with self.pythonPackages;
-                (oldAttrs.propagatedBuildInputs or []) ++ [ passlib ];
-            });
-          })
-        ];
-        system.stateVersion = "17.03";
-      };
-      radicale1_export = lib.recursiveUpdate radicale1 {
-        services.radicale.extraArgs = [
-          "--export-storage" "/tmp/collections-new"
-        ];
-        system.stateVersion = "17.03";
-      };
-      radicale2_verify = lib.recursiveUpdate radicale2 {
-        services.radicale.extraArgs = [ "--debug" "--verify-storage" ];
-        system.stateVersion = "17.09";
-      };
-      radicale2 = lib.recursiveUpdate (common args) {
-        system.stateVersion = "17.09";
-      };
-      radicale3 = lib.recursiveUpdate (common args) {
-        system.stateVersion = "20.09";
-      };
-    };
-
-    # This tests whether the web interface is accessible to an authenticated user
-    testScript = { nodes }: let
-      switchToConfig = nodeName: let
-        newSystem = nodes.${nodeName}.config.system.build.toplevel;
-      in "${newSystem}/bin/switch-to-configuration test";
-    in ''
-      with subtest("Check Radicale 1 functionality"):
-          radicale.succeed(
-              "${switchToConfig "radicale1"} >&2"
-          )
-          radicale.wait_for_unit("radicale.service")
-          radicale.wait_for_open_port(${port})
-          radicale.succeed(
-              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
-          )
-
-      with subtest("Export data in Radicale 2 format"):
-          radicale.succeed("systemctl stop radicale")
-          radicale.succeed("ls -al /tmp/collections")
-          radicale.fail("ls -al /tmp/collections-new")
-
-      with subtest("Radicale exits immediately after exporting storage"):
-          radicale.succeed(
-              "${switchToConfig "radicale1_export"} >&2"
-          )
-          radicale.wait_until_fails("systemctl status radicale")
-          radicale.succeed("ls -al /tmp/collections")
-          radicale.succeed("ls -al /tmp/collections-new")
-
-      with subtest("Verify data in Radicale 2 format"):
-          radicale.succeed("rm -r /tmp/collections/${user}")
-          radicale.succeed("mv /tmp/collections-new/collection-root /tmp/collections")
-          radicale.succeed(
-              "${switchToConfig "radicale2_verify"} >&2"
-          )
-          radicale.wait_until_fails("systemctl status radicale")
-
-          (retcode, logs) = radicale.execute("journalctl -u radicale -n 10")
-          assert (
-              retcode == 0 and "Verifying storage" in logs
-          ), "Radicale 2 didn't verify storage"
-          assert (
-              "failed" not in logs and "exception" not in logs
-          ), "storage verification failed"
-
-      with subtest("Check Radicale 2 functionality"):
-          radicale.succeed(
-              "${switchToConfig "radicale2"} >&2"
-          )
-          radicale.wait_for_unit("radicale.service")
-          radicale.wait_for_open_port(${port})
-
-          (retcode, output) = radicale.execute(
-              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
-          )
-          assert (
-              retcode == 0 and "VCALENDAR" in output
-          ), "Could not read calendar from Radicale 2"
-
-          radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
-
-      with subtest("Check Radicale 3 functionality"):
-          radicale.succeed(
-              "${switchToConfig "radicale3"} >&2"
-          )
-          radicale.wait_for_unit("radicale.service")
-          radicale.wait_for_open_port(${port})
-
-          (retcode, output) = radicale.execute(
-              "curl --fail http://${user}:${password}@localhost:${port}/someuser/calendar.ics/"
-          )
-          assert (
-              retcode == 0 and "VCALENDAR" in output
-          ), "Could not read calendar from Radicale 3"
-
-          radicale.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
-    '';
+  testScript = ''
+    machine.wait_for_unit("radicale.service")
+    machine.wait_for_open_port(${port})
+
+    machine.succeed("sudo -u radicale git -C ${filesystem_folder} init")
+    machine.succeed(
+        "sudo -u radicale git -C ${filesystem_folder} config --local user.email radicale@example.com"
+    )
+    machine.succeed(
+        "sudo -u radicale git -C ${filesystem_folder} config --local user.name radicale"
+    )
+
+    with subtest("Test calendar and event creation"):
+        machine.succeed(
+            "${cli} --caldav-url http://localhost:${port}/${user} calendar create cal"
+        )
+        machine.succeed("test -d ${filesystem_folder}/collection-root/${user}/cal")
+        machine.succeed('test -z "$(ls ${filesystem_folder}/collection-root/${user}/cal)"')
+        machine.succeed(
+            "${cli} --caldav-url http://localhost:${port}/${user}/cal calendar add 2021-04-23 testevent"
+        )
+        machine.succeed('test -n "$(ls ${filesystem_folder}/collection-root/${user}/cal)"')
+        (status, stdout) = machine.execute(
+            "sudo -u radicale git -C ${filesystem_folder} log --format=oneline | wc -l"
+        )
+        assert status == 0, "git log failed"
+        assert stdout == "3\n", "there should be exactly 3 commits"
+
+    with subtest("Test rights file"):
+        machine.fail(
+            "${cli} --caldav-url http://localhost:${port}/${user} calendar create sub/cal"
+        )
+        machine.fail(
+            "${cli} --caldav-url http://localhost:${port}/otheruser calendar create cal"
+        )
+
+    with subtest("Test web interface"):
+        machine.succeed("curl --fail http://${user}:${password}@localhost:${port}/.web/")
+
+    with subtest("Test security"):
+        output = machine.succeed("systemd-analyze security radicale.service")
+        machine.log(output)
+        assert output[-9:-1] == "SAFE :-}"
+  '';
 })