Skip to content

Commit 19872ee

Browse files
committed
Refactoring.
1 parent 5211ae5 commit 19872ee

File tree

6 files changed

+167
-155
lines changed

6 files changed

+167
-155
lines changed

datashuttle/configs/canonical_folders.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
if TYPE_CHECKING:
77
from datashuttle.utils.custom_types import TopLevelFolder
88

9+
import platform
10+
911
from datashuttle.configs import canonical_configs
1012
from datashuttle.utils.folder_class import Folder
1113

@@ -91,3 +93,13 @@ def get_project_datashuttle_path(project_name: str) -> Tuple[Path, Path]:
9193
temp_logs_path = base_path / "temp_logs"
9294

9395
return base_path, temp_logs_path
96+
97+
98+
def get_rclone_config_base_path():
99+
"""TODO PLACEHOLDER."""
100+
if platform.system() == "Windows":
101+
return (
102+
Path().home() / "AppData" / "Roaming" / "rclone"
103+
) # # "$HOME/.config/rclone/rclone.conf")
104+
else: # TODO HANDLE platform.system() == "Linux":
105+
return Path().home() / ".config" / "rclone"

datashuttle/configs/config_class.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ def __init__(
7070
self.rclone_has_password = {}
7171
self.setup_rclone_has_password()
7272

73+
def connection_method_rclone_config_has_password(self):
74+
return self.rclone_has_password[self["connection_method"]]
75+
7376
def setup_rclone_has_password(self):
7477
""""""
7578
if self.rclone_password_state_file_path.is_file():
@@ -281,6 +284,13 @@ def get_rclone_config_name(
281284

282285
return f"central_{self.project_name}_{connection_method}"
283286

287+
def get_rclone_config_filepath(self) -> Path:
288+
""""""
289+
return (
290+
canonical_folders.get_rclone_config_base_path()
291+
/ f"{self.get_rclone_config_name()}.conf"
292+
)
293+
284294
def make_rclone_transfer_options(
285295
self, overwrite_existing_files: OverwriteExistingFiles, dry_run: bool
286296
) -> Dict:

datashuttle/datashuttle_class.py

Lines changed: 98 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import glob
55
import json
66
import os
7+
import platform
78
import shutil
89
from pathlib import Path
910
from 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

Comments
 (0)