diff --git a/cmd/cgr-loader/cgr-loader.go b/cmd/cgr-loader/cgr-loader.go index 7cfb3c2d5..d403e7ddb 100755 --- a/cmd/cgr-loader/cgr-loader.go +++ b/cmd/cgr-loader/cgr-loader.go @@ -259,7 +259,7 @@ func getLoader(cfg *config.CGRConfig) (loader engine.LoadReader, err error) { return } if gprefix := utils.MetaGoogleAPI + utils.CONCATENATED_KEY_SEP; strings.HasPrefix(*dataPath, gprefix) { // Default load from csv files to dataDb - return engine.NewGoogleCSVStorage(cfg.LoaderCgrCfg().FieldSeparator, strings.TrimPrefix(*dataPath, gprefix), *cfgPath) + return engine.NewGoogleCSVStorage(cfg.LoaderCgrCfg().FieldSeparator, strings.TrimPrefix(*dataPath, gprefix)) } if !utils.IsURL(*dataPath) { loader = engine.NewFileCSVStorage(cfg.LoaderCgrCfg().FieldSeparator, *dataPath) diff --git a/config/config_defaults.go b/config/config_defaults.go index aa2db26e0..b5ce4550a 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -784,7 +784,8 @@ const CGRATES_CFG_JSON = ` "field_separator": ",", // separator used in case of csv files "caches_conns":["*localhost"], "scheduler_conns": ["*localhost"], - "gapi_credentials": ".gapi/credentials.json" // the path to the credentials for google API or the credentials.json file content + "gapi_credentials": ".gapi/credentials.json", // the path to the credentials for google API or the credentials.json file content + "gapi_token": ".gapi/token.json" // the path to the token for google API or the token.json file content }, diff --git a/config/config_json_test.go b/config/config_json_test.go index bb0c3ed09..f2c47945b 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -1690,6 +1690,7 @@ func TestDfDispatcherSJsonCfg(t *testing.T) { func TestDfLoaderCfg(t *testing.T) { cred := json.RawMessage(`".gapi/credentials.json"`) + tok := json.RawMessage(`".gapi/token.json"`) eCfg := &LoaderCfgJson{ Tpid: utils.StringPointer(""), Data_path: utils.StringPointer("./"), @@ -1698,6 +1699,7 @@ func TestDfLoaderCfg(t *testing.T) { Caches_conns: &[]string{utils.MetaLocalHost}, Scheduler_conns: &[]string{utils.MetaLocalHost}, Gapi_credentials: &cred, + Gapi_token: &tok, } if cfg, err := dfCgrJsonCfg.LoaderCfgJson(); err != nil { t.Error(err) diff --git a/config/config_test.go b/config/config_test.go index cb6bbf958..f44487273 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -1506,6 +1506,7 @@ func TestCgrLoaderCfgDefault(t *testing.T) { CachesConns: []string{utils.MetaLocalHost}, SchedulerConns: []string{utils.MetaLocalHost}, GapiCredentials: json.RawMessage(`".gapi/credentials.json"`), + GapiToken: json.RawMessage(`".gapi/credentials.json"`), } if !reflect.DeepEqual(cgrCfg.LoaderCgrCfg(), eLdrCfg) { t.Errorf("received: %+v, expecting: %+v", utils.ToJSON(cgrCfg.LoaderCgrCfg()), utils.ToJSON(eLdrCfg)) diff --git a/config/libconfig_json.go b/config/libconfig_json.go index 859297637..850aaef8c 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -506,6 +506,7 @@ type LoaderCfgJson struct { Caches_conns *[]string Scheduler_conns *[]string Gapi_credentials *json.RawMessage + Gapi_token *json.RawMessage } type MigratorCfgJson struct { diff --git a/config/loadercgrcfg.go b/config/loadercgrcfg.go index 3997b77b7..3846a3072 100644 --- a/config/loadercgrcfg.go +++ b/config/loadercgrcfg.go @@ -32,6 +32,7 @@ type LoaderCgrCfg struct { CachesConns []string SchedulerConns []string GapiCredentials json.RawMessage + GapiToken json.RawMessage } func (ld *LoaderCgrCfg) loadFromJsonCfg(jsnCfg *LoaderCfgJson) (err error) { @@ -76,5 +77,8 @@ func (ld *LoaderCgrCfg) loadFromJsonCfg(jsnCfg *LoaderCfgJson) (err error) { if jsnCfg.Gapi_credentials != nil { ld.GapiCredentials = *jsnCfg.Gapi_credentials } + if jsnCfg.Gapi_token != nil { + ld.GapiToken = *jsnCfg.Gapi_token + } return nil } diff --git a/engine/storage_csv.go b/engine/storage_csv.go index e116b1f04..c86fdb5b8 100644 --- a/engine/storage_csv.go +++ b/engine/storage_csv.go @@ -172,8 +172,8 @@ func NewStringCSVStorage(sep rune, } // NewGoogleCSVStorage creates a csv storege from google sheets -func NewGoogleCSVStorage(sep rune, spreadsheetID, cfgPath string) (*CSVStorage, error) { - sht, err := newSheet(cfgPath) +func NewGoogleCSVStorage(sep rune, spreadsheetID string) (*CSVStorage, error) { + sht, err := newSheet() if err != nil { return nil, err } @@ -717,20 +717,22 @@ func (c *csvString) Close() { // no need for close // Google // Retrieve a token, saves the token, then returns the generated client. -func getClient(config *oauth2.Config, configPath string) (*http.Client, error) { +func getClient(cfg *oauth2.Config, configPath string) (*http.Client, error) { // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. - tokFile := path.Join(configPath, utils.GoogleTokenFileName) - tok, err := tokenFromFile(tokFile) + tok := &oauth2.Token{} + raw, err := getCfgJSONData(config.CgrConfig().LoaderCgrCfg().GapiToken) if err != nil { - tok, err = getTokenFromWeb(config) + tok, err = getTokenFromWeb(cfg) if err != nil { return nil, err } - saveToken(tokFile, tok) + saveToken(string(config.CgrConfig().LoaderCgrCfg().GapiToken[1:len(config.CgrConfig().LoaderCgrCfg().GapiToken)-1]), tok) + } else if err = json.Unmarshal(raw, tok); err != nil { + return nil, err } - return config.Client(context.Background(), tok), nil + return cfg.Client(context.Background(), tok), nil } // Request a token from the web, then returns the retrieved token. @@ -752,18 +754,6 @@ func getTokenFromWeb(config *oauth2.Config) (*oauth2.Token, error) { return tok, err } -// Retrieves a token from a local file. -func tokenFromFile(file string) (*oauth2.Token, error) { - f, err := os.Open(file) - if err != nil { - return nil, err - } - defer f.Close() - tok := &oauth2.Token{} - err = json.NewDecoder(f).Decode(tok) - return tok, err -} - // Saves a token to a file path. func saveToken(path string, token *oauth2.Token) { fmt.Printf("Saving credential file to: %s\n", path) @@ -776,34 +766,27 @@ func saveToken(path string, token *oauth2.Token) { json.NewEncoder(f).Encode(token) } -func newSheet(cfgPath string) (sht *sheets.Service, err error) { //*google_api +func getCfgJSONData(raw json.RawMessage) (data []byte, err error) { + if len(raw) == 0 { + return + } + if raw[0] == '{' && raw[len(raw)-1] == '}' { + data = raw + return + } + dataPath := string(raw[1 : len(raw)-1]) + if !strings.HasSuffix(dataPath, utils.JSNSuffix) { + dataPath = path.Join(dataPath, utils.GoogleCredentialsFileName) + } + return ioutil.ReadFile(dataPath) +} + +func newSheet() (sht *sheets.Service, err error) { //*google_api var cred []byte var cfgPathDir string - raw := config.CgrConfig().LoaderCgrCfg().GapiCredentials - if len(raw) != 0 { - if raw[0] == '{' && raw[len(raw)-1] == '}' { - cred = raw - if utils.IsURL(cfgPath) { - cfgPath = "." - } - if strings.HasSuffix(cfgPath, utils.JSNSuffix) { - cfgPathDir = filepath.Dir(cfgPath) - } - cfgPathDir = path.Join(cfgPathDir, utils.GoogleConfigDirName) - if err = os.MkdirAll(cfgPathDir, 744); err != nil { - return - } - } else { - credPath := string(raw[1 : len(raw)-1]) - if !strings.HasSuffix(credPath, utils.JSNSuffix) { - credPath = path.Join(credPath, utils.GoogleCredentialsFileName) - } - if cred, err = ioutil.ReadFile(credPath); err != nil { - err = fmt.Errorf("Unable to read client secret file: %v", err) - return - } - cfgPathDir = filepath.Dir(credPath) - } + if cred, err = getCfgJSONData(config.CgrConfig().LoaderCgrCfg().GapiCredentials); err != nil { + err = fmt.Errorf("Unable to read client secret file: %v", err) + return } // If modifying these scopes, delete your previously saved token.json. config, err := google.ConfigFromJSON(cred, "https://www.googleapis.com/auth/spreadsheets.readonly")