11from __future__ import print_function
22
3+ import os
4+ import stat
35from getpass import getpass
46
57import keyring
68
79from code42cli .profile .config import get_config_accessor , ConfigAccessor
10+ from code42cli .util import does_user_agree , open_file , get_user_project_path , print_error
811
912_ROOT_SERVICE_NAME = u"code42cli"
1013
1114
1215def get_stored_password (profile_name ):
1316 """Gets your currently stored password for the given profile name."""
1417 profile = _get_profile (profile_name )
15- service_name = _get_service_name (profile .name )
16- username = _get_username (profile )
17- password = keyring .get_password (service_name , username )
18- return password
18+ return _get_stored_password (profile )
1919
2020
2121def get_password_from_prompt ():
@@ -26,20 +26,94 @@ def get_password_from_prompt():
2626def set_password (profile_name , new_password ):
2727 """Sets your password for the given profile name."""
2828 profile = _get_profile (profile_name )
29- service_name = _get_service_name (profile .name )
29+ service_name = _get_keyring_service_name (profile .name )
3030 username = _get_username (profile )
31- keyring . set_password ( service_name , username , new_password )
32- print (u"'Code42 Password' updated." )
31+ if _store_password ( profile , service_name , username , new_password ):
32+ print (u"'Code42 Password' updated." )
3333
3434
3535def _get_profile (profile_name ):
3636 accessor = get_config_accessor ()
3737 return accessor .get_profile (profile_name )
3838
3939
40- def _get_service_name (profile_name ):
40+ def _get_stored_password (profile ):
41+ password = _get_password_from_keyring (profile ) or _get_password_from_file (profile )
42+ return password
43+
44+
45+ def _get_keyring_service_name (profile_name ):
4146 return u"{}::{}" .format (_ROOT_SERVICE_NAME , profile_name )
4247
4348
49+ def _get_password_from_keyring (profile ):
50+ try :
51+ service_name = _get_keyring_service_name (profile .name )
52+ username = _get_username (profile )
53+ return keyring .get_password (service_name , username )
54+ except :
55+ return None
56+
57+
58+ def _get_password_from_file (profile ):
59+ path = _get_password_file_path (profile )
60+
61+ def read_password (file ):
62+ try :
63+ return file .readline ().strip ()
64+ except Exception :
65+ return None
66+
67+ try :
68+ return open_file (path , u"r" , lambda file : read_password (file ))
69+ except Exception :
70+ return None
71+
72+
73+ def _store_password (profile , service_name , username , new_password ):
74+ return _store_password_using_keyring (
75+ service_name , username , new_password
76+ ) or _store_password_using_file (profile , new_password )
77+
78+
79+ def _store_password_using_keyring (service_name , username , new_password ):
80+ try :
81+ keyring .set_password (service_name , username , new_password )
82+ was_successful = keyring .get_password (service_name , username ) is not None
83+ return was_successful
84+ except :
85+ return False
86+
87+
88+ def _store_password_using_file (profile , new_password ):
89+ save_to_file = _prompt_for_alternative_store ()
90+ if save_to_file :
91+ path = _get_password_file_path (profile )
92+
93+ def write_password (file ):
94+ try :
95+ file .truncate (0 )
96+ line = u"{0}\n " .format (new_password )
97+ file .write (line )
98+ os .chmod (path , stat .S_IRUSR | stat .S_IWUSR )
99+ return True
100+ except Exception as ex :
101+ print_error (str (ex ))
102+ return False
103+
104+ return open_file (path , u"w+" , lambda file : write_password (file ))
105+ return False
106+
107+
108+ def _get_password_file_path (profile ):
109+ project_path = get_user_project_path ()
110+ return u"{0}.{1}" .format (project_path , profile .name .lower ())
111+
112+
44113def _get_username (profile ):
45114 return profile [ConfigAccessor .USERNAME_KEY ]
115+
116+
117+ def _prompt_for_alternative_store ():
118+ prompt = u"keyring is unavailable. Would you like to store in secure flat file? (y/n): "
119+ return does_user_agree (prompt )
0 commit comments