From 85f2de11688a003306b6b910b38053f001363bd7 Mon Sep 17 00:00:00 2001 From: Manuel Thalmann Date: Thu, 16 May 2024 01:43:40 +0200 Subject: [PATCH] Add support for Proton --- lib/modules/rclone.nix | 107 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/lib/modules/rclone.nix b/lib/modules/rclone.nix index cdb7d59..2bb38a8 100644 --- a/lib/modules/rclone.nix +++ b/lib/modules/rclone.nix @@ -8,22 +8,26 @@ let nextcloudVendor = "nextcloud"; mkIfNotNull = value: name: lib.mkIf (value != null) { ${name} = value; }; + mkFileOption = { description }: lib.mkOption { + type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str); + description = "The path to a file containing ${description}"; + default = null; + }; + mkUsernameOption = { service }: lib.mkOption { type = lib.types.nullOr lib.types.str; description = "The user name for logging in to ${service}."; default = null; }; - mkPasswordOption = { service }: lib.mkOption { + mkPasswordOption = { service, itemKind ? "password" }: lib.mkOption { type = lib.types.nullOr lib.types.str; - description = "The password obscured using the `rclone obscure` command for logging in to ${service}."; + description = "The ${itemKind} obscured using the `rclone obscure` command for logging in to ${service}."; default = null; }; - mkPasswordFileOption = { service }: lib.mkOption { - type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str); - description = "The path to a file containing the password obscured using the `rclone obscure` command for logging in to ${service}."; - default = null; + mkPasswordFileOption = { service, itemKind ? "password" }: mkFileOption { + description = "the ${itemKind} obscured using the `rclone obscure` command for logging in to ${service}."; }; mkServerUsernameOption = { service }: mkUsernameOption { service = "the ${service} server."; }; @@ -179,6 +183,90 @@ let }; }); + mkProtonProvider = { displayName }: ( + { config, ... }: { + imports = [ + mkProvider + ]; + + options = { + username = mkUsernameOption { service = displayName; }; + obscuredPassword = mkPasswordOption { service = displayName; }; + obscuredPasswordFile = mkPasswordFileOption { service = displayName; }; + + webAuthnToken = lib.mkOption { + type = lib.types.strMatching "[0-9]{6}"; + description = "The 2 Factor Authentication code for logging in to ${displayName}."; + }; + + webAuthnTokenFile = mkFileOption { + description = "the 2 Factor Authentication code for logging in to ${displayName}."; + }; + + clientID = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "The client key."; + default = null; + }; + + accessToken = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "The access token."; + default = null; + }; + + refreshToken = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "The refresh token."; + default = null; + }; + + saltedKeyPass = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "The salted key pass."; + default = null; + }; + + enableCaching = lib.mkOption { + type = lib.types.nullOr lib.types.bool; + description = "Whether to enable ${displayName}'s integrated caching."; + default = null; + }; + + mailboxPassword = mkPasswordOption { service = displayName; itemKind = "mailbox password"; }; + mailboxPasswordFile = mkPasswordFileOption { service = displayName; itemKind = "mailbox password"; }; + clientIDFile = mkFileOption { description = "the client key."; }; + accessTokenFile = mkFileOption { description = "the access token."; }; + refreshTokenFile = mkFileOption { description = "the refresh token."; }; + saltedKeyPassFile = mkFileOption { description = "the salted key pass."; }; + }; + + config = { + config = lib.mkMerge [ + { type = "protondrive"; } + (mkIfNotNull config.username "username") + (mkIfNotNull config.obscuredPassword "password") + (mkIfNotNull config.webAuthnToken "2fa") + (mkIfNotNull config.mailboxPassword "mailbox_password") + (mkIfNotNull config.clientID "client_uid") + (mkIfNotNull config.accessToken "client_access_token") + (mkIfNotNull config.refreshToken "client_refresh_token") + (mkIfNotNull config.saltedKeyPass "client_salted_key_pass") + (mkIfNotNull config.enableCaching "enable_caching") + ]; + + secrets = lib.mkMerge [ + (mkIfNotNull config.obscuredPasswordFile "RCLONE_PROTONDRIVE_PASSWORD") + (mkIfNotNull config.webAuthnTokenFile "RCLONE_PROTONDRIVE_2FA") + (mkIfNotNull config.mailboxPasswordFile "RCLONE_PROTONDRIVE_MAILBOX_PASSWORD") + (mkIfNotNull config.clientIDFile "RCLONE_PROTONDRIVE_CLIENT_UID") + (mkIfNotNull config.accessTokenFile "RCLONE_PROTONDRIVE_CLIENT_ACCESS_TOKEN") + (mkIfNotNull config.refreshTokenFile "RCLONE_PROTONDRIVE_CLIENT_REFRESH_TOKEN") + (mkIfNotNull config.saltedKeyPassFile "RCLONE_PROTONDRIVE_CLIENT_SALTED_KEY_PASS") + ]; + }; + }); + syncProviders = { ${manualVendor} = { displayName = "Custom"; @@ -198,6 +286,11 @@ let displayName = owncloudName; module = mkOwncloudProvider { }; }; + + proton = rec { + displayName = "Proton"; + module = mkProtonProvider { inherit displayName; }; + }; }; in { options = { @@ -277,7 +370,7 @@ in { (lib.generators.toINI { } { name = sync.config; }); script = pkgs.writeShellScriptBin serviceName '' ${sync.secretsScript} - bash -c echo hello world + cat ${configFile} ''; in (lib.getExe script);