Skip to content
This repository was archived by the owner on Jan 19, 2026. It is now read-only.

Commit 31994e8

Browse files
Merge pull request #33 from storyblok/feat/int-713
feat(int-713): Adding option to log in the CLI with token (Enabling the possibility to login with SSO)
2 parents 168fb09 + a200952 commit 31994e8

3 files changed

Lines changed: 128 additions & 58 deletions

File tree

README.md

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
[![npm](https://img.shields.io/npm/v/storyblok.svg)](https://www.npmjs.com/package/storyblok)
77
[![npm](https://img.shields.io/npm/dt/storyblok.svg)](ttps://img.shields.io/npm/dt/storyblok.svg)
8-
[![GitHub issues](https://img.shields.io/github/issues/storyblok/storyblok.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok/issues?q=is%3Aopen+is%3Aissue)
9-
[![GitHub closed issues](https://img.shields.io/github/issues-closed/storyblok/storyblok.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok/issues?q=is%3Aissue+is%3Aclosed)
8+
[![GitHub issues](https://img.shields.io/github/issues/storyblok/storyblok-cli.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok/issues?q=is%3Aopen+is%3Aissue)
9+
[![GitHub closed issues](https://img.shields.io/github/issues-closed/storyblok/storyblok-cli.svg?style=flat-square&v=1)](https://github.com/storyblok/storyblok-cli/issues?q=is%3Aissue+is%3Aclosed)
1010

1111
## BREAKING CHANGE
1212

@@ -22,6 +22,43 @@ $ npm i storyblok -g
2222

2323
## Commands
2424

25+
26+
### login
27+
28+
Login to the Storyblok cli
29+
30+
```sh
31+
$ storyblok login
32+
```
33+
#### Login options
34+
35+
##### Options for Login with email and password
36+
* `email`: your user's email address
37+
* `password`: your user's password
38+
39+
##### Options for Login with token (Recomended to SSO user's but works with all user accounts)
40+
* `token`: your access token
41+
42+
**For Both login options you nedd to pass the region**
43+
44+
* `region`: your user's region (default: `eu`). You can use `us`, `cn` or `eu`. This region will be used for the other cli's commands.
45+
46+
### logout
47+
48+
Logout from the Storyblok cli
49+
50+
```sh
51+
$ storyblok logout
52+
```
53+
### user
54+
55+
Get the currently logged in user
56+
57+
```sh
58+
$ storyblok user
59+
```
60+
61+
2562
### select
2663

2764
Usage to kickstart a boilerplate, fieldtype or theme
@@ -188,35 +225,6 @@ Create a space in Storyblok and select the boilerplate to use
188225
$ storyblok quickstart
189226
```
190227

191-
### logout
192-
193-
Logout from the Storyblok cli
194-
195-
```sh
196-
$ storyblok logout
197-
```
198-
199-
### login
200-
201-
Login to the Storyblok cli
202-
203-
```sh
204-
$ storyblok login
205-
```
206-
#### Options
207-
208-
* `email`: your user's email address
209-
* `password`: your user's password
210-
* `region`: your user's region (default: `eu`). You can use `us`, `cn` or `eu`. This region will be used for the other cli's commands.
211-
212-
### user
213-
214-
Get the currently logged in user
215-
216-
```sh
217-
$ storyblok user
218-
```
219-
220228
### generate-migration
221229

222230
Create a migration file (with the name `change_<COMPONENT>_<FIELD>.js`) inside the `migrations` folder. Check **Migrations** section to more details

src/utils/api.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ module.exports = {
3535
return path
3636
},
3737

38-
async login (email, password, region) {
38+
async login (content) {
39+
const { email, password, region } = content
3940
try {
4041
const response = await axios.post(`${this.apiSwitcher(region)}users/login`, {
4142
email: email,
@@ -68,10 +69,10 @@ module.exports = {
6869
otp_attempt: code
6970
})
7071

71-
return this.persistCredentials(email, newResponse.data || {}, region)
72+
return this.persistCredentials(email, newResponse.data.access_token || {}, region)
7273
}
7374

74-
return this.persistCredentials(email, data, region)
75+
return this.persistCredentials(email, data.access_token, region)
7576
} catch (e) {
7677
return Promise.reject(e)
7778
}
@@ -92,27 +93,37 @@ module.exports = {
9293
}
9394
},
9495

95-
persistCredentials (email, data, region = 'eu') {
96-
const token = this.extractToken(data)
96+
persistCredentials (email, token = null, region = 'eu') {
9797
if (token) {
9898
this.oauthToken = token
9999
creds.set(email, token, region)
100100

101-
return Promise.resolve(data)
101+
return Promise.resolve(token)
102102
}
103103
return Promise.reject(new Error('The code could not be authenticated.'))
104104
},
105105

106106
async processLogin () {
107107
try {
108-
const questions = getQuestions('login')
109-
const { email, password, region } = await inquirer.prompt(questions)
108+
let content = {}
109+
await inquirer
110+
.prompt(getQuestions('login-strategy'))
111+
.then(async ({ strategy }) => {
112+
content = await inquirer.prompt(getQuestions(strategy))
113+
})
114+
.catch((error) => {
115+
console.log(error)
116+
})
110117

111-
const data = await this.login(email, password, region)
118+
if (!content.token) {
119+
await this.login(content)
120+
} else {
121+
await this.loginWithToken(content)
122+
}
112123

113124
console.log(chalk.green('✓') + ' Log in successfully! Token has been added to .netrc file.')
114125

115-
return Promise.resolve(data)
126+
return Promise.resolve(content)
116127
} catch (e) {
117128
if (e.response && e.response.data && e.response.data.error) {
118129
console.error(chalk.red('X') + ' An error ocurred when login the user: ' + e.response.data.error)
@@ -125,8 +136,20 @@ module.exports = {
125136
}
126137
},
127138

128-
extractToken (data) {
129-
return data.access_token
139+
async loginWithToken (content) {
140+
const { token, region } = content
141+
try {
142+
const { data } = await axios.get(`${this.apiSwitcher(region)}users/me`, {
143+
headers: {
144+
Authorization: token
145+
}
146+
})
147+
148+
this.persistCredentials(data.user.email, token, region)
149+
return data.user
150+
} catch (e) {
151+
return Promise.reject(e)
152+
}
130153
},
131154

132155
logout (unauthorized) {

src/utils/get-questions.js

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
const getOptions = (subCommand, argv = {}, api = {}) => {
22
let email = ''
3+
const moreOptions = [
4+
'delete-templates',
5+
'pull-components',
6+
'push-components',
7+
'scaffold'
8+
]
9+
const regionInput = {
10+
type: 'input',
11+
name: 'region',
12+
message: 'Enter your user\'s region (us, eu or cn):',
13+
validate: function (value) {
14+
const flagList = ['us', 'cn', 'eu']
15+
if (flagList.indexOf(value) > -1) {
16+
return true
17+
}
18+
19+
return 'Please enter a valid region: us, eu or cn'
20+
}
21+
}
322

423
if (subCommand === 'select') {
524
return [
@@ -103,7 +122,29 @@ const getOptions = (subCommand, argv = {}, api = {}) => {
103122
]
104123
}
105124

106-
if (subCommand === 'login') {
125+
if (subCommand === 'login-strategy') {
126+
return [
127+
{
128+
type: 'list',
129+
name: 'strategy',
130+
message: 'Select the login strategy: ',
131+
choices: [
132+
{
133+
name: 'With email and password (Common users with storyblok account)',
134+
value: 'login-with-email',
135+
short: 'Email'
136+
},
137+
{
138+
name: 'With Token (Most recommended for SSO users)',
139+
value: 'login-with-token',
140+
short: 'Token'
141+
}
142+
]
143+
}
144+
]
145+
}
146+
147+
if (subCommand === 'login-with-email') {
107148
return [
108149
{
109150
type: 'input',
@@ -129,29 +170,27 @@ const getOptions = (subCommand, argv = {}, api = {}) => {
129170
return 'Please enter a valid password:'
130171
}
131172
},
173+
regionInput
174+
]
175+
}
176+
177+
if (subCommand === 'login-with-token') {
178+
return [
132179
{
133180
type: 'input',
134-
name: 'region',
135-
message: 'Enter your user\'s region (us, eu or cn):',
181+
name: 'token',
182+
message: 'Enter your token:',
136183
validate: function (value) {
137-
const flagList = ['us', 'cn', 'eu']
138-
if (flagList.indexOf(value) > -1) {
184+
if (value.length > 0) {
139185
return true
140186
}
141-
142-
return 'Please enter a valid region: us, eu or cn'
187+
return 'Please enter a valid token:'
143188
}
144-
}
189+
},
190+
regionInput
145191
]
146192
}
147193

148-
const moreOptions = [
149-
'delete-templates',
150-
'pull-components',
151-
'push-components',
152-
'scaffold'
153-
]
154-
155194
if (moreOptions.indexOf(subCommand) > -1) {
156195
const loginQuestions = [
157196
{

0 commit comments

Comments
 (0)