@@ -39,6 +39,14 @@ def url_safe_escape(instring:str) -> str:
39
39
return urllib .parse .quote (instring , safe = '~-._' )
40
40
41
41
42
+ def dump_overwrite (token :dict , output_filename :str , input_dict :dict ):
43
+ # overwrite fields in previous token (represented by input_dict)
44
+ # that also have values from new token
45
+ input_dict .update (token )
46
+ with open (output_filename ,'w' ) as output_file :
47
+ json .dump (input_dict , output_file , indent = 4 )
48
+
49
+
42
50
def gmail_redirect_uri (local_port :int ) -> str :
43
51
return 'http://127.0.0.1:%d%s' % (local_port , GOOGLE_OAUTH2_RESULT_PATH )
44
52
@@ -63,7 +71,7 @@ def gmail_get_token_from_code(client_id:str, client_secret:str, authorization_co
63
71
return json .loads (response )
64
72
65
73
66
- def gmail_get_RequestHandler (client_id :str , client_secret :str , output_file : IO [ str ] ) -> type :
74
+ def gmail_get_RequestHandler (client_id :str , client_secret :str , output_filename : str , input_dict : dict ) -> type :
67
75
class GMailRequestHandler (http .server .BaseHTTPRequestHandler ):
68
76
def log_request (self , code :Union [int ,str ]= '-' , size :Union [int ,str ]= '-' ) -> None :
69
77
# Silence request logging.
@@ -90,8 +98,7 @@ def gmail_get_RequestHandler(client_id:str, client_secret:str, output_file:IO[st
90
98
code ,
91
99
self .server .server_address [1 ],
92
100
)
93
- json .dump (token , output_file )
94
- output_file .close ()
101
+ dump_overwrite (token , output_filename , input_dict )
95
102
sys .exit (0 )
96
103
97
104
def ExtractCodeFromResponse (self ) -> Optional [str ]:
@@ -104,15 +111,16 @@ def gmail_get_RequestHandler(client_id:str, client_secret:str, output_file:IO[st
104
111
if len (qs ['code' ]) != 1 :
105
112
return None
106
113
return qs ['code' ][0 ]
107
-
114
+
108
115
return GMailRequestHandler
109
116
110
117
111
- def get_token_gmail (client_id :str , client_secret :str , scope :str , output_file : IO [ str ] ) -> None :
118
+ def get_token_gmail (client_id :str , client_secret :str , scope :str , output_filename : str , input_dict : dict ) -> None :
112
119
request_handler_class = gmail_get_RequestHandler (
113
120
client_id ,
114
121
client_secret ,
115
- output_file ,
122
+ output_filename ,
123
+ input_dict ,
116
124
)
117
125
server = http .server .HTTPServer (('' , 0 ), request_handler_class )
118
126
_ , port = server .server_address
@@ -199,13 +207,13 @@ def outlook_get_initial_tokens_by_device_flow(client_id:str, tenant:str) -> Dict
199
207
}
200
208
201
209
202
- def get_token_outlook (client_id :str , client_secret :str , tenant :str , use_device_flow :bool , output_file : IO [ str ] ) -> None :
210
+ def get_token_outlook (client_id :str , client_secret :str , tenant :str , use_device_flow :bool , output_filename : str , input_dict : dict ) -> None :
203
211
if use_device_flow :
204
212
tokens = outlook_get_initial_tokens_by_device_flow (client_id , tenant )
205
213
else :
206
214
code = outlook_get_authorization_code (client_id , tenant )
207
215
tokens = outlook_get_initial_tokens (client_id , client_secret , tenant , code )
208
- json . dump (tokens , output_file , indent = 4 )
216
+ dump_overwrite (tokens , output_filename , input_dict )
209
217
210
218
##########
211
219
@@ -219,6 +227,13 @@ def argparse_get_parser() -> argparse.ArgumentParser:
219
227
220
228
221
229
def subcommand_get_token (args :argparse .Namespace ) -> None :
230
+ input_dict = {}
231
+ if args .overwrite_existing_token :
232
+ if not os .path .isfile (args .output_file ):
233
+ raise Exception ("Cannot overwrite nonexistent token file {}" .format (args .output_file ))
234
+ else :
235
+ with open (args .output_file ,'r' ) as input_file :
236
+ input_dict = json .load (input_file )
222
237
if args .service == 'outlook' :
223
238
if not args .tenant :
224
239
parser .error ("'outlook' service requires 'tenant' argument." )
@@ -230,6 +245,7 @@ def subcommand_get_token(args:argparse.Namespace) -> None:
230
245
args .tenant ,
231
246
args .use_device_flow ,
232
247
args .output_file ,
248
+ input_dict ,
233
249
)
234
250
elif args .service == 'gmail' :
235
251
if not args .client_secret :
@@ -243,6 +259,7 @@ def subcommand_get_token(args:argparse.Namespace) -> None:
243
259
args .client_secret ,
244
260
args .scope ,
245
261
args .output_file ,
262
+ input_dict ,
246
263
)
247
264
248
265
@@ -275,7 +292,13 @@ sp_get_token.add_argument(
275
292
help = "use simplified device flow for Outlook/Azure" ,
276
293
)
277
294
sp_get_token .add_argument (
278
- 'output_file' , nargs = '?' , type = argparse .FileType ('w' ), default = '-' ,
295
+ '--overwrite-existing-token' ,
296
+ default = False ,
297
+ action = 'store_true' ,
298
+ help = 'overwrite existing token file (preserves extra fields)' ,
299
+ )
300
+ sp_get_token .add_argument (
301
+ 'output_file' , nargs = '?' , type = str , default = '-' ,
279
302
help = "output file, '-' for stdout" ,
280
303
)
281
304
0 commit comments