Skip to content
Merged
9 changes: 8 additions & 1 deletion src/commands/authorizations/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {hux} from '@heroku/heroku-cli-util'
import * as color from '@heroku/heroku-cli-util/color'
import {ux} from '@oclif/core/ux'

import {SDK_HEADER} from '../../lib/api.js'
import {display} from '../../lib/authorizations/authorizations.js'

export default class AuthorizationsCreate extends Command {
Expand All @@ -18,19 +19,25 @@ export default class AuthorizationsCreate extends Command {
json: flags.boolean({char: 'j', description: 'output in json format'}),
scope: flags.string({char: 's', completion: ScopeCompletion, description: 'set custom OAuth scopes'}),
short: flags.boolean({char: 'S', description: 'only output token'}),
team: flags.team({description: 'team to create OAuth authorization on'}),
}

async run() {
const {flags} = await this.parse(AuthorizationsCreate)

ux.action.start('Creating OAuth Authorization')

const {body: auth} = await this.heroku.post<Heroku.OAuthAuthorization>('/oauth/authorizations', {
const endpoint = flags.team
? `/teams/${encodeURIComponent(flags.team)}/oauth/authorizations`
: '/oauth/authorizations'

const {body: auth} = await this.heroku.post<Heroku.OAuthAuthorization>(endpoint, {
body: {
description: flags.description,
expires_in: flags['expires-in'],
scope: flags.scope ? flags.scope.split(',') : undefined,
},
...(flags.team ? {headers: {Accept: SDK_HEADER}} : {}),
})

ux.action.stop()
Expand Down
11 changes: 10 additions & 1 deletion src/commands/authorizations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ import * as Heroku from '@heroku-cli/schema'
import {color, hux} from '@heroku/heroku-cli-util'
import {ux} from '@oclif/core/ux'

import {SDK_HEADER} from '../../lib/api.js'

export default class AuthorizationsIndex extends Command {
static description = 'list OAuth authorizations'
static examples = [
color.command('heroku authorizations'),
]
static flags = {
json: flags.boolean({char: 'j', description: 'output in json format'}),
team: flags.team({description: 'team to list OAuth authorizations for'}),
}

async run() {
const {flags} = await this.parse(AuthorizationsIndex)

const {body: authorizations} = await this.heroku.get<Array<Heroku.OAuthAuthorization>>('/oauth/authorizations')
const endpoint = flags.team
? `/teams/${encodeURIComponent(flags.team)}/oauth/authorizations`
: '/oauth/authorizations'
const {body: authorizations} = await this.heroku.get<Array<Heroku.OAuthAuthorization>>(
endpoint,
flags.team ? {headers: {Accept: SDK_HEADER}} : {},
)

if (flags.json) {
hux.styledJSON(authorizations.sort((a, b) => a.description.localeCompare(b.description)))
Expand Down
15 changes: 15 additions & 0 deletions test/unit/commands/authorizations/create.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,19 @@ describe('authorizations:create', function () {
expect(json.scope).to.contain('global')
})
})

context('with team flag', function () {
it('creates the authorization for the team', async function () {
api
.matchHeader('accept', 'application/vnd.heroku+json; version=3.sdk')
.post('/teams/my-team/oauth/authorizations', {description: 'awesome'})
.reply(201, {access_token: {token: 'secrettoken'}, scope: ['global']})

const {stdout} = await runCommand(AuthorizationsCreate, ['--description', 'awesome', '--team', 'my-team'])

expect(stdout).to.contain('Client: <none>\n')
expect(stdout).to.contain('Scope: global\n')
expect(stdout).to.contain('Token: secrettoken\n')
})
})
})
41 changes: 41 additions & 0 deletions test/unit/commands/authorizations/index.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,45 @@ describe('authorizations', function () {
expect(stdout).to.equal('No OAuth authorizations.\n')
})
})

context('with team flag', function () {
it('lists the named team\'s authorizations alphabetically by description', async function () {
api
.matchHeader('accept', 'application/vnd.heroku+json; version=3.sdk')
.get('/teams/my-team/oauth/authorizations')
.reply(200, [exampleAuthorization1, exampleAuthorization2])

const {stdout} = await runCommand(Authorizations, ['--team', 'my-team'])

const actual = removeAllWhitespace(stdout)
const expected = removeAllWhitespace(`
awesome f6e8d969-129f-42d2-854b-c2eca9d5a42e app,user
b description aBcD1234-129f-42d2-854b-dEf123abc123 global`)
expect(actual).to.include(expected)
})

it('lists the named team\'s authorizations as json', async function () {
api
.matchHeader('accept', 'application/vnd.heroku+json; version=3.sdk')
.get('/teams/my-team/oauth/authorizations')
.reply(200, [exampleAuthorization1, exampleAuthorization2])

const {stdout} = await runCommand(Authorizations, ['--team', 'my-team', '--json'])

const authJSON = JSON.parse(stdout)
expect(authJSON[0]).to.eql(exampleAuthorization2)
expect(authJSON[1]).to.eql(exampleAuthorization1)
})

it('shows no authorizations message for a team with none', async function () {
api
.matchHeader('accept', 'application/vnd.heroku+json; version=3.sdk')
.get('/teams/my-team/oauth/authorizations')
.reply(200, [])

const {stdout} = await runCommand(Authorizations, ['--team', 'my-team'])

expect(stdout).to.equal('No OAuth authorizations.\n')
})
})
})
Loading