44import glob
55import json
66import os
7+ import platform
78import shutil
89from pathlib import Path
910from typing import (
@@ -112,92 +113,6 @@ def _set_attributes_after_config_load(self) -> None:
112113
113114 self ._make_project_metadata_if_does_not_exist ()
114115
115- def _try_set_rclone_password (self ): # TODO: BETTER NAME!
116- """"""
117- input_ = input (
118- f"Your SSH key will be stored in the rclone config at:\n " ## TODO: FIX T HIS IS NOT SSH
119- f"{ rclone .get_full_config_filepath (self .cfg )} .\n \n "
120- f"Would you like to set a password using Windows credential manager? "
121- f"Press 'y' to set password or leave blank to skip."
122- )
123-
124- set_password = input_ == "y"
125-
126- if set_password :
127- try :
128- self .set_rclone_password ()
129- except BaseException as e :
130- print (e )
131- # THIS PATH IS WRONG
132- config_path = rclone .get_full_config_filepath (self .cfg )
133-
134- raise RuntimeError (
135- f"Password set up failed. The config at { config_path } contains the private ssh key without a password.\n "
136- f"Use set_rclone_password()` to attempt to set the password again (see stacktrace above). "
137- )
138-
139- print ("Password set successfully" )
140-
141- def set_rclone_password (self ):
142- """"""
143- # TODO: CHECK CONNECTION METHOD
144- connection_method = self .cfg ["connection_method" ]
145-
146- if self .cfg .rclone_has_password [connection_method ]:
147- raise RuntimeError (
148- "This config file already has a password set. First, use `remove_rclone_password` to remove it."
149- )
150-
151- rclone_config_path = rclone .get_full_config_filepath (
152- self .cfg
153- ) # change name to rclone config because this is getting confusing!
154-
155- if not rclone_config_path .exists ():
156- raise RuntimeError (
157- f"Rclone config file for: { connection_method } was not found. "
158- f"Make sure you set up the connection first with `setup_{ connection_method } _connection()`"
159- )
160-
161- password_filepath = rclone_password .get_password_filepath (self .cfg )
162-
163- if password_filepath .exists ():
164- password_filepath .unlink ()
165-
166- rclone_password .save_credentials_password (
167- password_filepath ,
168- )
169-
170- rclone_password .set_rclone_password (
171- password_filepath , rclone .get_full_config_filepath (self .cfg )
172- )
173-
174- self .cfg .rclone_has_password [connection_method ] = (
175- True # HANDLE THIS PROPERLY
176- )
177- self .cfg .save_rclone_password_state ()
178- print (self .cfg .rclone_has_password [connection_method ])
179-
180- def remove_rclone_password (self ):
181- """"""
182- # TODO: CHECK CONNECTION METHOD
183- connection_method = self .cfg ["connection_method" ]
184-
185- if not self .cfg .rclone_has_password [self .cfg ["connection_method" ]]:
186- raise RuntimeError (
187- f"The config for the current connection method: { self .cfg ['connection_method' ]} does not have a password. Cannot remove."
188- )
189- config_filepath = rclone_password .get_password_filepath (self .cfg )
190- rclone_password .remove_rclone_password (
191- config_filepath , rclone .get_full_config_filepath (self .cfg )
192- )
193-
194- self .cfg .rclone_has_password [connection_method ] = (
195- False # HANDLE THIS PROPERLY
196- )
197- self .cfg .save_rclone_password_state ()
198-
199- print ("SAY SOMETHING LIKE PASSWORD REMOVED" )
200-
201116 # -------------------------------------------------------------------------
202117 # Public Folder Makers
203118 # -------------------------------------------------------------------------
@@ -870,6 +785,14 @@ def _transfer_specific_file_or_folder(
870785 # TODO: MAKE MORE NOTES ON HOW THE GDRIVE WORKER IS THE BEST MODEL
871786 # IT MUST BE DONE WILL NOT WORK WITHOUT
872787
788+ # TODO: this is going to be a massive pain because old config files will not work
789+ # will need to re-set up all connections
790+ # this can just be a breaking change, but will have to handle error nicely
791+ # We could just move it from the config file, then show a warning
792+
793+ # TODO: need the cancel button on tui in case we close the google window
794+ # THEN we can hide it while we make the connection to check
795+
873796 @requires_ssh_configs
874797 @check_is_not_local_project
875798 def setup_ssh_connection (self ) -> None :
@@ -900,10 +823,13 @@ def setup_ssh_connection(self) -> None:
900823
901824 self ._setup_rclone_central_ssh_config (private_key_str , log = True )
902825
903- if not self .cfg .rclone_has_password [self .cfg ["connection_method" ]]:
904- self ._try_set_rclone_password ()
826+ utils .log_and_message (
827+ f"Your SSH key will be stored in the rclone config at:\n "
828+ f"{ self .cfg .get_rclone_config_filepath ()} .\n \n "
829+ )
905830
906- print ("Checking write permissions on the `central_path`..." ) # TODO
831+ if not self .cfg .connection_method_rclone_config_has_password ():
832+ self ._try_set_rclone_password ()
907833
908834 rclone .check_successful_connection_and_raise_error_on_fail (
909835 self .cfg
@@ -919,14 +845,6 @@ def setup_ssh_connection(self) -> None:
919845 # Google Drive
920846 # -------------------------------------------------------------------------
921847
922- # TODO: this is going to be a massive pain because old config files will not work
923- # will need to re-set up all connections
924- # this can just be a breaking change, but will have to handle error nicely
925- # We could just move it from the config file, then show a warning
926-
927- # TODO: need the cancel button on tui in case we close the google window
928- # THEN we can hide it while we make the connection to check
929-
930848 @check_configs_set
931849 def setup_gdrive_connection (self ) -> None :
932850 """Set up a connection to Google Drive using the provided credentials.
@@ -973,12 +891,9 @@ def setup_gdrive_connection(self) -> None:
973891 self .cfg , process , log = True
974892 )
975893
976- # If re-running connection when password already set, we don't want to
977- # try and set a new password
978- if not self .cfg .rclone_has_password [self .cfg ["connection_method" ]]:
894+ if not self .cfg .connection_method_rclone_config_has_password ():
979895 self ._try_set_rclone_password ()
980896
981- print ("Now trying to connect or something" ) # TODO
982897 rclone .check_successful_connection_and_raise_error_on_fail (self .cfg )
983898
984899 utils .log_and_message ("Google Drive Connection Successful." )
@@ -1009,21 +924,96 @@ def setup_aws_connection(self) -> None:
1009924
1010925 self ._setup_rclone_aws_config (aws_secret_access_key , log = True )
1011926
1012- # If re-running connection when password already set, we don't want to
1013- # try and set a new password
1014- if not self .cfg .rclone_has_password [
1015- self .cfg ["connection_method" ]
1016- ]: # TODO: do this for ssh too!
927+ if not self .cfg .connection_method_rclone_config_has_password ():
1017928 self ._try_set_rclone_password ()
1018929
1019- print ("Say something like checking connection..." ) # TODO
1020930 rclone .check_successful_connection_and_raise_error_on_fail (self .cfg )
1021931 aws .raise_if_bucket_absent (self .cfg )
1022932
1023933 utils .log_and_message ("AWS Connection Successful." )
1024934
1025935 ds_logger .close_log_filehandler ()
1026936
937+ # -------------------------------------------------------------------------
938+ # Rclone config password
939+ # -------------------------------------------------------------------------
940+
941+ def _try_set_rclone_password (self ):
942+ """"""
943+ pass_type = {
944+ "Windows" : "Windows credential manager" ,
945+ "Linux" : "the `pass` program" ,
946+ "Darwin" : "macOS inbuild `security`."
947+ }
948+
949+ input_ = utils .get_user_input (
950+ f"Would you like to set a password using { pass_type [platform .system ()]} .\n "
951+ f"Press 'y' to set password or leave blank to skip."
952+ )
953+
954+ set_password = input_ == "y"
955+
956+ if set_password :
957+ try :
958+ self .set_rclone_password ()
959+ except Exception as e :
960+
961+ config_path = self .cfg .get_rclone_config_filepath ()
962+
963+ utils .log_and_raise_error (
964+ f"Password set up failed. The config at { config_path } contains the private ssh key without a password.\n "
965+ f"Use set_rclone_password()` to attempt to set the password again (see full error message above). " ,
966+ RuntimeError ,
967+ from_error = e
968+ )
969+
970+ utils .log_and_message ("Password set successfully" )
971+
972+ def set_rclone_password (self ):
973+ """"""
974+ if self .cfg .connection_method_rclone_config_has_password ():
975+ raise RuntimeError (
976+ "This config file already has a password set. "
977+ "First, use `remove_rclone_password` to remove it."
978+ )
979+
980+ connection_method = self .cfg ["connection_method" ]
981+
982+ rclone_config_path = self .cfg .get_rclone_config_filepath ()
983+
984+ if not rclone_config_path .exists ():
985+ raise RuntimeError (
986+ f"Rclone config file for: { connection_method } was not found. "
987+ f"Make sure you set up the connection first with `setup_{ connection_method } _connection()`"
988+ )
989+ rclone_password .run_rclone_config_encrypt (
990+ self .cfg
991+ )
992+
993+ self .cfg .rclone_has_password [connection_method ] = True
994+
995+ self .cfg .save_rclone_password_state ()
996+
997+ def remove_rclone_password (self ):
998+ """"""
999+ if not self .cfg .connection_method_rclone_config_has_password ():
1000+ raise RuntimeError (
1001+ f"The config for the current connection method: { self .cfg ['connection_method' ]} does not have a password. Cannot remove."
1002+ )
1003+ config_filepath = rclone_password .get_password_filepath (self .cfg )
1004+
1005+ rclone_password .remove_rclone_password (
1006+ config_filepath , self .cfg .get_rclone_config_filepath ()
1007+ )
1008+
1009+ self .cfg .rclone_has_password [self .cfg ["connection_method" ]] = False
1010+
1011+ self .cfg .save_rclone_password_state ()
1012+
1013+ utils .log_and_message (
1014+ f"Password removed from rclone config file: { } "
1015+ )
1016+
10271017 # -------------------------------------------------------------------------
10281018 # Configs
10291019 # -------------------------------------------------------------------------
@@ -1042,7 +1032,7 @@ def make_config_file(
10421032 ) -> None :
10431033 """Initialize the configurations for datashuttle on the local machine.
10441034
1045- Once initialised , these settings will be used each
1035+ Once initialized , these settings will be used each
10461036 time the datashuttle is opened.
10471037
10481038 These settings are stored in a config file on the
0 commit comments