-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathcredentials.py
More file actions
97 lines (83 loc) · 3.14 KB
/
credentials.py
File metadata and controls
97 lines (83 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Copyright (c) 2025, Salesforce, Inc.
# SPDX-License-Identifier: Apache-2
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
import configparser
from dataclasses import dataclass
import os
from loguru import logger
ENV_CREDENTIALS = {
"username": "SFDC_USERNAME",
"password": "SFDC_PASSWORD",
"client_id": "SFDC_CLIENT_ID",
"client_secret": "SFDC_CLIENT_SECRET",
"login_url": "SFDC_LOGIN_URL",
}
INI_FILE = os.path.expanduser("~/.datacustomcode/credentials.ini")
@dataclass
class Credentials:
username: str
password: str
client_id: str
client_secret: str
login_url: str
@classmethod
def from_ini(
cls,
profile: str = "default",
ini_file: str = INI_FILE,
) -> Credentials:
config = configparser.ConfigParser()
logger.debug(f"Reading {ini_file} for profile {profile}")
config.read(ini_file)
return cls(
username=config[profile]["username"],
password=config[profile]["password"],
client_id=config[profile]["client_id"],
client_secret=config[profile]["client_secret"],
login_url=config[profile]["login_url"],
)
@classmethod
def from_env(cls) -> Credentials:
try:
return cls(**{k: os.environ[v] for k, v in ENV_CREDENTIALS.items()})
except KeyError as exc:
raise ValueError(
f"All of {ENV_CREDENTIALS.values()} must be set in environment."
) from exc
@classmethod
def from_available(cls, profile: str = "default") -> Credentials:
if os.environ.get("SFDC_USERNAME"):
return cls.from_env()
if os.path.exists(INI_FILE):
return cls.from_ini(profile=profile)
raise ValueError(
"Credentials not found in env or ini file. "
"Run `datacustomcode configure` to create a credentials file."
)
def update_ini(self, profile: str = "default", ini_file: str = INI_FILE):
config = configparser.ConfigParser()
expanded_ini_file = os.path.expanduser(ini_file)
os.makedirs(os.path.dirname(expanded_ini_file), exist_ok=True)
if os.path.exists(expanded_ini_file):
config.read(expanded_ini_file)
if profile not in config:
config[profile] = {}
config[profile]["username"] = self.username
config[profile]["password"] = self.password
config[profile]["client_id"] = self.client_id
config[profile]["client_secret"] = self.client_secret
config[profile]["login_url"] = self.login_url
with open(expanded_ini_file, "w") as f:
config.write(f)