diff --git a/.gitignore b/.gitignore index 9d6ea2ca..ce0ead42 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /package-lock.json /tmp node_modules +.env \ No newline at end of file diff --git a/package.json b/package.json index af352397..658163d3 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "@oclif/config": "^1", "@oclif/plugin-help": "^2", "@types/node-fetch": "^2.5.0", + "cli-ux": "^5.3.1", + "dotenv": "^8.0.0", "node-fetch": "^2.6.0", "tslib": "^1" }, diff --git a/src/commands/login.ts b/src/commands/login.ts new file mode 100644 index 00000000..25b6db33 --- /dev/null +++ b/src/commands/login.ts @@ -0,0 +1,28 @@ +import { Command, flags } from "@oclif/command" +import cli from "cli-ux" +import Gravity from "../lib/gravity" + +export default class Login extends Command { + static description = + "Log into the Artsy API. This is a prerequisite for many other commands." + + static flags = { + help: flags.help({ char: "h" }), + } + + async run() { + require("dotenv").config() + + const email = await cli.prompt("Email", { type: "normal" }) + const password = await cli.prompt("Password", { type: "hide" }) + + this.log(`Authenticating against stagingapi.artsy.net for ${email}...`) + + const result = await new Gravity().getAccessToken({ + email, + password, + }) + + this.log(result.access_token) + } +} diff --git a/src/lib/gravity/index.ts b/src/lib/gravity/index.ts index b9737bc0..ed3a5acc 100644 --- a/src/lib/gravity/index.ts +++ b/src/lib/gravity/index.ts @@ -6,10 +6,30 @@ class Gravity { production: "api.artsy.net", } + async getAccessToken(credentials: Credentials) { + const gravityUrl = this.url("oauth2/access_token") + const body: AccessTokenRequest = { + client_id: process.env.CLIENT_ID!, + client_secret: process.env.CLIENT_SECRET!, + grant_type: "credentials", + ...credentials, + } + + const response = await fetch(gravityUrl, { + method: "post", + body: JSON.stringify(body), + headers: { "Content-Type": "application/json" }, + }) + + const json = await response.json() + + return json as AccessTokenResponse + } + async get(endpoint: string) { const token: string = process.env.TOKEN! // temp until our auth/token plumbing is hooked up - const gravityUrl: string = this.url(endpoint) + const gravityUrl: string = this.url(`api/v1/${endpoint}`) const headers = { "X-Access-Token": token } const response = await fetch(gravityUrl, { headers }) @@ -18,8 +38,24 @@ class Gravity { url(endpoint: string): string { const host = Gravity.HOSTS.staging - return `https://${host}/api/v1/${endpoint}` + return `https://${host}/${endpoint}` } } export default Gravity + +export interface Credentials { + email: string + password: string +} + +interface AccessTokenRequest extends Credentials { + grant_type: string + client_id: string + client_secret: string +} + +interface AccessTokenResponse { + access_token: string + expires_in: string +} diff --git a/yarn.lock b/yarn.lock index f5ef0519..e0b5cac4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -473,7 +473,7 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== -cli-ux@^5.2.1: +cli-ux@^5.2.1, cli-ux@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/cli-ux/-/cli-ux-5.3.1.tgz#3bed8b37c44b03a5d1b9d71d39a69a919a101835" integrity sha512-l2MXbitx0FjtHKSbHytuxfxWv6MdWBRh23ItRJjU17cjj0dqZxfAL863tzbR1FIs7jccPllPUvn3QWK6BQg3Pg== @@ -650,6 +650,11 @@ doctrine@0.7.2: esutils "^1.1.6" isarray "0.0.1" +dotenv@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.0.0.tgz#ed310c165b4e8a97bb745b0a9d99c31bda566440" + integrity sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg== + "emoji-regex@>=6.0.0 <=6.1.1": version "6.1.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e"