diff --git a/modules/accounts/calendar.nix b/modules/accounts/calendar.nix index 961cd0b3a..bfbc3e124 100644 --- a/modules/accounts/calendar.nix +++ b/modules/accounts/calendar.nix @@ -58,15 +58,6 @@ let description = "User name for authentication."; }; - # userNameCommand = mkOption { - # type = types.nullOr (types.listOf types.str); - # default = null; - # example = [ "~/get-username.sh" ]; - # description = '' - # A command that prints the user name to standard output. - # ''; - # }; - passwordCommand = mkOption { type = types.nullOr (types.listOf types.str); default = null; diff --git a/modules/programs/vdirsyncer-accounts.nix b/modules/programs/vdirsyncer-accounts.nix index 4edd17429..7ab9521c1 100644 --- a/modules/programs/vdirsyncer-accounts.nix +++ b/modules/programs/vdirsyncer-accounts.nix @@ -10,6 +10,20 @@ in { options.vdirsyncer = { enable = mkEnableOption "synchronization using vdirsyncer"; + urlCommand = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + example = [ "~/get-url.sh" ]; + description = "A command that prints the URL of the storage."; + }; + + userNameCommand = mkOption { + type = types.nullOr (types.listOf types.str); + default = null; + example = [ "~/get-username.sh" ]; + description = "A command that prints the user name to standard output."; + }; + collections = mkOption { type = types.nullOr (types.listOf collection); default = null; diff --git a/modules/programs/vdirsyncer.nix b/modules/programs/vdirsyncer.nix index 32c003394..562d7b4be 100644 --- a/modules/programs/vdirsyncer.nix +++ b/modules/programs/vdirsyncer.nix @@ -32,27 +32,25 @@ let }); remoteStorage = a: - filterAttrs (_: v: v != null) ((getAttrs [ - "type" - "url" - "userName" - #"userNameCommand" - "passwordCommand" - ] a.remote) // (if a.vdirsyncer == null then - { } - else - getAttrs [ - "itemTypes" - "verify" - "verifyFingerprint" - "auth" - "authCert" - "userAgent" - "tokenFile" - "clientIdCommand" - "clientSecretCommand" - "timeRange" - ] a.vdirsyncer)); + filterAttrs (_: v: v != null) + ((getAttrs [ "type" "url" "userName" "passwordCommand" ] a.remote) + // (if a.vdirsyncer == null then + { } + else + getAttrs [ + "urlCommand" + "userNameCommand" + "itemTypes" + "verify" + "verifyFingerprint" + "auth" + "authCert" + "userAgent" + "tokenFile" + "clientIdCommand" + "clientSecretCommand" + "timeRange" + ] a.vdirsyncer)); pair = a: with a.vdirsyncer; @@ -77,6 +75,8 @@ let ''post_hook = "${v}"'' else if (n == "url") then ''url = "${v}"'' + else if (n == "urlCommand") then + "url.fetch = ${listString (map wrap ([ "command" ] ++ v))}" else if (n == "timeRange") then '' start_date = "${v.start}" end_date = "${v.end}"'' else if (n == "itemTypes") then @@ -196,6 +196,9 @@ in { config = mkIf cfg.enable { assertions = let + mutuallyExclusiveOptions = + [ [ "url" "urlCommand" ] [ "userName" "userNameCommand" ] ]; + requiredOptions = t: if (t == "caldav" || t == "carddav" || t == "http") then [ "url" ] @@ -213,6 +216,7 @@ in { allowedOptions = let remoteOptions = [ + "urlCommand" "userName" "userNameCommand" "password" @@ -264,7 +268,16 @@ in { Storage ${n} is of type ${v.type}, but required option ${a} is not set. ''; - }]) required)) (removeAttrs v [ "type" "_module" ]); + }]) required) ++ map (attrs: + let + defined = attrNames (filterAttrs (n: v: v != null) + (genAttrs attrs (a: v.${a} or null))); + in { + assertion = length defined <= 1; + message = "Storage ${n} has mutually exclusive options: ${ + concatStringsSep ", " defined + }"; + }) mutuallyExclusiveOptions) (removeAttrs v [ "type" "_module" ]); storageAssertions = flatten (mapAttrsToList assertStorage localStorages) ++ flatten (mapAttrsToList assertStorage remoteStorages);