55
66import types
77import time
8+ import json
9+ from pathlib import Path
10+ from .. import __TEMP_STORAGE__
811from .PwdAuth_cloner import PwdAuthCloner
912
1013
@@ -20,12 +23,13 @@ class PwdAuth:
2023
2124 """
2225
23- def __init__ (self , user , password ):
26+ def __init__ (self , user , password , mfa_code = None ):
2427 self .user = user
2528 self .password = password
2629 self ._token = None
2730 self .carol = None
2831 self .connector_id = None
32+ self .mfa_code = mfa_code
2933
3034 def _set_token (self , data ):
3135 self ._token = types .SimpleNamespace ()
@@ -34,6 +38,8 @@ def _set_token(self, data):
3438 self ._token .expiration = data ['timeIssuedInMillis' ] + (
3539 data ['expires_in' ] * 1000 )
3640
41+ self ._save_token (data )
42+
3743 def set_connector_id (self , connector_id ):
3844 self .connector_id = connector_id
3945
@@ -54,6 +60,27 @@ def login(self, carol):
5460 """
5561 self .carol = carol
5662
63+ self ._temp_file_name = f".pycarol_token_{ self .user } _{ self .carol .organization } _{ self .carol .domain } .json"
64+ self ._tmp_filepath = Path (__TEMP_STORAGE__ ) / self ._temp_file_name
65+
66+ if self ._tmp_filepath .exists ():
67+ with open (self ._tmp_filepath , "r" , encoding = "utf-8" ) as file :
68+ token_data = json .load (file )
69+ self ._set_token (token_data )
70+
71+ # Try access token
72+ resp = self .carol .call_api (f'v5/oauth2/token/{ token_data ["access_token" ]} ' , auth = False , errors = "ignore" )
73+ if resp .get ('access_token' ) and resp .get ('errorCode' ) is None :
74+ return
75+
76+ # Try refresh token
77+ try :
78+ self ._refresh_token ()
79+ return
80+ except Exception :
81+ pass
82+
83+ # New login
5784 data = {
5885 'username' : self .user ,
5986 'password' : self .password ,
@@ -62,13 +89,30 @@ def login(self, carol):
6289 'connectorId' : carol .connector_id ,
6390 'orgSubdomain' : carol .organization
6491 }
65- resp = self .carol .call_api ('v2/oauth2/token' , auth = False , data = data ,
92+
93+ resp = self .carol .call_api ('v5/oauth2/token' , auth = False , data = data ,
6694 content_type = 'application/x-www-form-urlencoded' )
6795
96+ if resp .get ('mfa_token' ):
97+ mfa_code = input ('Input your TOTVS Carol - MFA code: ' ) if self .mfa_code is None else self .mfa_code
98+
99+ data = {
100+ 'mfaCode' : mfa_code
101+ }
102+
103+ resp = self .carol .call_api ('v5/oauth2/token/mfa/authenticate' , auth = False , data = data ,
104+ extra_headers = {'Authorization' : resp ['mfa_token' ]},
105+ content_type = 'application/x-www-form-urlencoded' )
106+
68107 self ._set_token (resp )
69108 if self .carol .verbose :
70109 print ("Token: {}" .format (self ._token .access_token ))
71110
111+ def _save_token (self , data ):
112+ self ._tmp_filepath .parent .mkdir (parents = True , exist_ok = True )
113+ with open (self ._tmp_filepath , "w" , encoding = "utf-8" ) as file :
114+ json .dump (data , file )
115+
72116 def authenticate_request (self , headers ):
73117 headers ['Authorization' ] = self .get_access_token ()
74118
@@ -92,7 +136,7 @@ def get_access_token(self):
92136 return self ._token .access_token
93137
94138 def _refresh_token (self ):
95- resp = self .carol .call_api ('v2 /oauth2/token' , auth = False , data = {
139+ resp = self .carol .call_api ('v5 /oauth2/token' , auth = False , data = {
96140 'grant_type' : 'refresh_token' ,
97141 'refresh_token' : self ._token .refresh_token
98142 }, content_type = 'application/x-www-form-urlencoded' )
0 commit comments