Skip to content

Commit ae96d76

Browse files
authored
Merge pull request #15 from aitomatic/feat/refresh_key_flow
Add flow to refresh token automatically when it expired
2 parents ab364b9 + 00dbac2 commit ae96d76

3 files changed

Lines changed: 95 additions & 64 deletions

File tree

DEVELOPING.md

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,83 +5,83 @@
55
1. python3
66
2. pip
77
3. virtualenv
8-
```shell
9-
pip install virtualenv
10-
```
8+
```shell
9+
pip install virtualenv
10+
```
1111

1212
## Steps to setup dev environment
1313

1414
1. Create a python3 virtual environment
15-
```shell
16-
virtualenv .venv -p python3
17-
```
15+
```shell
16+
virtualenv .venv -p python3
17+
```
1818
2. Activate the virtual environment created in step 1
19-
```shell
20-
source .venv/bin/activate
21-
```
19+
```shell
20+
source .venv/bin/activate
21+
```
2222
3. Install `setuptools` to package code and `black` to format python code
23-
```shell
24-
pip install setuptools black
25-
```
23+
```shell
24+
pip install setuptools black
25+
```
2626
4. Install libraries in file requirements.txt
27-
```shell
28-
pip install -r requirements.txt
29-
```
27+
```shell
28+
pip install -r requirements.txt
29+
```
3030

3131
## Steps to test code in local
3232

3333
1. Run `black` command to format code
34-
```shell
35-
black -S .
36-
```
34+
```shell
35+
black -S .
36+
```
3737
2. Run command to test script
38-
```shell
39-
python src/aito.py
40-
```
38+
```shell
39+
python src/aito.py
40+
```
4141

4242
## Steps to install the CLI to virtual environment and test it
4343

4444
1. Run command to install CLI
45-
```shell
46-
pip install -e .
47-
```
45+
```shell
46+
pip install -e .
47+
```
4848
2. Verify the CLI
49-
```shell
50-
which aito
51-
```
49+
```shell
50+
which aito
51+
```
5252
3. Run `aito` command
53-
```shell
54-
aito
55-
```
53+
```shell
54+
aito
55+
```
5656

5757
## Steps to package and distribute CLI to TestPyPI
5858

5959
1. Install `build` to generate distribution packages and `twine` to distribute package to PyPI
60-
```shell
61-
pip install build twine
62-
```
60+
```shell
61+
pip install build twine
62+
```
6363
2. Run `build` command as the root folder, where file `pyproject.toml` is located
64-
```shell
65-
rm -rf dist
66-
python -m build
67-
```
68-
After that command, we will have `tar.gz` and `.whl` files in `dist` folder
64+
```shell
65+
rm -rf dist
66+
python -m build
67+
```
68+
After that command, we will have `tar.gz` and `.whl` files in `dist` folder
6969

7070
3. Register an account in TestPyPI and create an API token with `Entire account` scope
7171
4. Using twine to upload the distribution packages created in step 2 to TestPyPI
72-
```shell
73-
twine upload --repository testpypi --skip-existing dist/*
74-
```
75-
`--repository` used to choose upload to PyPI or TestPyPI, `--skip-existing` if we want to distribute further versions of the cli.
72+
```shell
73+
twine upload --repository testpypi --skip-existing dist/*
74+
```
75+
`--repository` used to choose upload to PyPI or TestPyPI, `--skip-existing` if we want to distribute further versions of the cli.
7676

77-
You will be prompted for a username and password. For the username, use __token__. For the password, use the token value, including the pypi- prefix.
77+
You will be prompted for a username and password. For the username, use __token__. For the password, use the token value, including the pypi- prefix.
7878
5. Using another virtual environment and install the `aitomatic-cli` using pip to verify that it works
79-
```shell
80-
deactivate
81-
virtualenv .venv-test -p python3
82-
source .venv-test/bin/activate
83-
pip install -i https://test.pypi.org/simple/ aitomatic
84-
```
79+
```shell
80+
deactivate
81+
virtualenv .venv-test -p python3
82+
source .venv-test/bin/activate
83+
pip install -i https://test.pypi.org/simple/ aitomatic
84+
```
8585

8686
## Steps to package and distribute CLI to PyPI
8787

@@ -92,13 +92,13 @@ Similar to steps to distribute to TestPyPI, except:
9292
## Temporary: If the deploy command failed due to change in service api. Update api base:
9393

9494
1. Clone https://github.com/aitomatic/ai-cloud
95-
2. Follow instruction and select dev stack
95+
2. Follow instruction in `infrastructure/DEVELOPING.md` and select `dev` stack
9696
3. Get the service host name
97-
```shell
98-
pulumi stack select dev
99-
pulumi stack output kodaServiceHostname
100-
```
97+
```shell
98+
pulumi stack select dev
99+
pulumi stack output kodaServiceHostname
100+
```
101101
4. Set AI_CLI_API_BASE env var to
102-
```shell
103-
export AI_CLI_API_BASE = "http://" + <hostname from step 3>
104-
```
102+
```shell
103+
export AI_CLI_API_BASE = "http://" + <hostname from step 3>
104+
```

src/login/main.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ def initiate_login_flow(obj):
107107
f'&scope={SCOPE}'
108108
f'&audience={AUDIENCE}'
109109
f'&state={login_seed}'
110+
f'&max_age=3600'
110111
)
111112

112113
click.launch(url)
@@ -145,7 +146,7 @@ def wait_for_login_callback(obj):
145146
'id': polling_data.get('id_token', ''),
146147
}
147148
)
148-
click.echo('Login successful')
149+
click.echo('Login successfully')
149150
exit(0)
150151
return
151152

@@ -169,11 +170,10 @@ def save_credential(obj, data):
169170
def authenticated(f):
170171
@click.pass_obj
171172
def wrapper(obj, *args, **kwargs):
172-
token = obj and obj.get('access_token')
173+
token = obj.get('access_token')
173174

174-
if token is None:
175+
if token is None or len(token) == 0:
175176
prompt_login()
176-
exit(1)
177177

178178
res = requests.get(
179179
url='https://{}/userinfo'.format(ORG),
@@ -182,13 +182,44 @@ def wrapper(obj, *args, **kwargs):
182182

183183
if res.status_code == 200:
184184
f(*args, **kwargs)
185+
elif res.status_code == 401:
186+
refresh_token()
187+
f(*args, **kwargs)
185188
else:
186-
click.echo(res.text)
187189
prompt_login()
188-
exit(1)
189190

190191
return update_wrapper(wrapper, f)
191192

192193

193194
def prompt_login():
194195
click.echo("You're not logged in. Please run `aito login` first.")
196+
exit(1)
197+
198+
199+
@click.pass_obj
200+
def refresh_token(obj):
201+
token = obj.get('refresh_token')
202+
203+
if token is None or len(token) == 0:
204+
prompt_login()
205+
206+
res = requests.post(
207+
url='https://{}/oauth/token'.format(ORG),
208+
data={
209+
'client_id': CLIENT_ID,
210+
'grant_type': 'refresh_token',
211+
'refresh_token': obj['refresh_token'],
212+
},
213+
headers={'content-type': 'application/x-www-form-urlencoded'},
214+
)
215+
if res.status_code == 200:
216+
data = res.json()
217+
save_credential(
218+
{
219+
'access_token': data['access_token'],
220+
'refresh_token': token,
221+
'id': data.get('id_token', ''),
222+
}
223+
)
224+
else:
225+
prompt_login()

version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.6.0
1+
0.6.1

0 commit comments

Comments
 (0)