Skip to content

Commit a671af6

Browse files
authored
Update CLI to store access and refresh tokens (#169)
* Update direnv config to create .env if it doesn't exist * Install python version using pyenv if not present * Add keyring dependency * Add utils for storing & retrieving access and refresh tokens for SSO use
1 parent db5356a commit a671af6

File tree

5 files changed

+68
-10
lines changed

5 files changed

+68
-10
lines changed

.envrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ set -e
55
# development dependencies. Based on:
66
# https://hynek.me/til/python-project-local-venvs/
77
export VIRTUAL_ENV=.venv
8+
9+
pyenv install --skip-existing 3.8.16
810
layout pyenv 3.8.16
911
. .venv/bin/activate
1012
python -m pip install -q -r requirements.txt
1113

1214
# Load environment variables from the .env file (for pytest, mainly)
15+
if [ ! -f .env ]; then
16+
cp .env.example .env
17+
fi
1318
dotenv
1419

1520
# Install pre-commit hooks

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ Both configuration files use the simple INI format, such as:
145145
api_key=1234567890abcdef1234567890abcdef
146146
```
147147

148+
Additionally, the CLI will store SSO access and refresh tokens in the system keyring
149+
using the [`keyring`](https://github.com/jaraco/keyring) library.
150+
151+
148152
### Non-Credentials (config.ini)
149153

150154
See the [default config](https://raw.githubusercontent.com/cloudsmith-io/cloudsmith-cli/master/cloudsmith_cli/data/config.ini) in GitHub:

cloudsmith_cli/cli/commands/login.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""CLI/Commands - Get an API token."""
22

33
import collections
4+
import getpass
45
import stat
56

67
import click
8+
import keyring
79

810
from ...core.api.user import get_user_token
911
from ...core.utils import get_help_website
@@ -101,6 +103,30 @@ def create_config_files(ctx, opts, api_key):
101103
return create, has_errors
102104

103105

106+
def get_username():
107+
return getpass.getuser()
108+
109+
110+
def store_access_token(access_token):
111+
username = get_username()
112+
keyring.set_password("cloudsmith_cli-access_token", username, access_token)
113+
114+
115+
def get_access_token():
116+
username = get_username()
117+
return keyring.get_password("cloudsmith_cli-access_token", username)
118+
119+
120+
def store_refresh_token(refresh_token):
121+
username = get_username()
122+
keyring.set_password("cloudsmith_cli-refresh_token", username, refresh_token)
123+
124+
125+
def get_refresh_token():
126+
username = get_username()
127+
return keyring.get_password("cloudsmith_cli-refresh_token", username)
128+
129+
104130
@main.command(aliases=["token"])
105131
@click.option(
106132
"-l",

requirements.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# All production dependencies should be declared in setup.py `install_requires`.
33
bumpversion
44
httpretty
5+
keyring
56
pip-tools
67
pre-commit
78
pylint

requirements.txt

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,21 @@
66
#
77
astroid==2.15.6
88
# via pylint
9+
backports-tarfile==1.2.0
10+
# via jaraco-context
911
build==0.10.0
1012
# via pip-tools
1113
bump2version==1.0.1
1214
# via bumpversion
1315
bumpversion==0.6.0
1416
# via -r requirements.in
15-
certifi==2023.7.22
17+
certifi==2024.8.30
1618
# via
1719
# cloudsmith-api
1820
# requests
1921
cfgv==3.3.1
2022
# via pre-commit
21-
charset-normalizer==3.2.0
23+
charset-normalizer==3.3.2
2224
# via requests
2325
click==8.1.6
2426
# via
@@ -28,13 +30,13 @@ click==8.1.6
2830
# pip-tools
2931
click-configfile==0.2.3
3032
# via cloudsmith-cli (setup.py)
31-
click-didyoumean==0.3.0
33+
click-didyoumean==0.3.1
3234
# via cloudsmith-cli (setup.py)
3335
click-spinner==0.1.10
3436
# via cloudsmith-cli (setup.py)
35-
cloudsmith-api==2.0.12
37+
cloudsmith-api==2.0.13
3638
# via cloudsmith-cli (setup.py)
37-
configparser==6.0.0
39+
configparser==7.1.0
3840
# via click-configfile
3941
coverage[toml]==7.2.7
4042
# via
@@ -52,16 +54,32 @@ httpretty==1.1.4
5254
# via -r requirements.in
5355
identify==2.5.26
5456
# via pre-commit
55-
idna==3.4
57+
idna==3.8
5658
# via requests
59+
importlib-metadata==8.5.0
60+
# via keyring
61+
importlib-resources==6.4.5
62+
# via keyring
5763
iniconfig==2.0.0
5864
# via pytest
5965
isort==5.12.0
6066
# via pylint
67+
jaraco-classes==3.4.0
68+
# via keyring
69+
jaraco-context==6.0.1
70+
# via keyring
71+
jaraco-functools==4.0.2
72+
# via keyring
73+
keyring==25.3.0
74+
# via -r requirements.in
6175
lazy-object-proxy==1.9.0
6276
# via astroid
6377
mccabe==0.7.0
6478
# via pylint
79+
more-itertools==10.5.0
80+
# via
81+
# jaraco-classes
82+
# jaraco-functools
6583
nodeenv==1.8.0
6684
# via pre-commit
6785
packaging==23.1
@@ -86,17 +104,17 @@ pytest==7.4.0
86104
# via pytest-cov
87105
pytest-cov==4.1.0
88106
# via -r requirements.in
89-
python-dateutil==2.8.2
107+
python-dateutil==2.9.0.post0
90108
# via cloudsmith-api
91109
pyyaml==6.0.1
92110
# via pre-commit
93-
requests==2.31.0
111+
requests==2.32.3
94112
# via
95113
# cloudsmith-cli (setup.py)
96114
# requests-toolbelt
97115
requests-toolbelt==1.0.0
98116
# via cloudsmith-cli (setup.py)
99-
semver==3.0.1
117+
semver==3.0.2
100118
# via cloudsmith-cli (setup.py)
101119
six==1.16.0
102120
# via
@@ -117,7 +135,7 @@ typing-extensions==4.7.1
117135
# via
118136
# astroid
119137
# pylint
120-
urllib3==1.26.16
138+
urllib3==1.26.20
121139
# via
122140
# cloudsmith-api
123141
# cloudsmith-cli (setup.py)
@@ -128,6 +146,10 @@ wheel==0.41.1
128146
# via pip-tools
129147
wrapt==1.15.0
130148
# via astroid
149+
zipp==3.20.2
150+
# via
151+
# importlib-metadata
152+
# importlib-resources
131153

132154
# The following packages are considered to be unsafe in a requirements file:
133155
# pip

0 commit comments

Comments
 (0)