Skip to content

Commit

Permalink
Merge pull request #89 from lumaxis/feature/api-tokens
Browse files Browse the repository at this point in the history
Add commands for API token management
  • Loading branch information
Chris Tavares authored Dec 13, 2016
2 parents 2cecb66 + d7f99a0 commit db13312
Show file tree
Hide file tree
Showing 87 changed files with 8,327 additions and 6,840 deletions.
4 changes: 2 additions & 2 deletions src/commands/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ export default class LoginCommand extends Command {
out.text(`Logged in as ${user.name}`);
}

private createAuthToken(): Promise<models.ApiTokensPostResponse> {
private createAuthToken(): Promise<models.ApiTokensCreateResponse> {
const endpoint = environments(this.environmentName).endpoint;
const client = createMobileCenterClient(this.userName, this.password, endpoint);
return clientCall<models.ApiTokensPostResponse>(cb => client.account.createApiToken({ description: "Created from mobile center cli"}, cb));
return clientCall<models.ApiTokensCreateResponse>(cb => client.account.createApiToken({ description: "Created from mobile center cli"}, cb));
}

private getUserInfo(token: string): Promise<models.UserProfileResponse> {
Expand Down
1 change: 1 addition & 0 deletions src/commands/tokens/category.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Commands to manage API tokens in Mobile Center
49 changes: 49 additions & 0 deletions src/commands/tokens/create.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// token create command

import { Command, CommandArgs, CommandResult, help, success, failure, ErrorCodes, shortName, longName, hasArg, required } from "../../util/commandline";
import { out } from "../../util/interaction";
import { reportToken } from "./lib/format-token";
import { MobileCenterClient, models, clientRequest } from "../../util/apis";

const debug = require("debug")("mobile-center-cli:commands:apps:create");
import { inspect } from "util";

@help("Create a new API token")
export default class TokenCreateCommand extends Command {
constructor(args: CommandArgs) {
super(args);
}

@help("Description of the API token")
@shortName("d")
@longName("description")
@hasArg
description: string;

async run(client: MobileCenterClient): Promise<CommandResult> {
const tokenAttributes: models.ApiTokensCreateRequest = {
description: this.description,
};

const createTokenResponse = await out.progress("Creating token ...",
clientRequest<models.ApiTokensCreateResponse>(cb => client.account.createApiToken(tokenAttributes, cb))
);

const statusCode = createTokenResponse.response.statusCode;
if (statusCode >= 400) {
switch (statusCode) {
case 400:
default:
return failure(ErrorCodes.Exception, "invalid request");
case 403:
return failure(ErrorCodes.InvalidParameter, "authorization to create an API token failed");
case 404:
return failure(ErrorCodes.NotLoggedIn, "user could not be found");
}
}

reportToken(createTokenResponse.result);

return success();
}
}
36 changes: 36 additions & 0 deletions src/commands/tokens/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// tokens delete command

import { Command, CommandArgs, CommandResult, help, success, failure, ErrorCodes, shortName, longName, hasArg, required } from "../../util/commandline";
import { out, prompt } from "../../util/interaction";
import { MobileCenterClient, models, clientRequest } from "../../util/apis";

const debug = require("debug")("mobile-center-cli:commands:apps:create");
import { inspect } from "util";

@help("Delete an API token")
export default class AppDeleteCommand extends Command {
constructor(args: CommandArgs) {
super(args);
}

@help("ID of the API token")
@required
@hasArg
id: string;

async run(client: MobileCenterClient): Promise<CommandResult> {
const confirmation = await prompt.confirm(`Do you really want to delete the token with ID "${this.id}"`);

if (confirmation) {
const deleteTokenResponse = await out.progress("Deleting app ...", clientRequest<null>(cb => client.account.deleteApiToken(this.id, cb)));

if (deleteTokenResponse.response.statusCode === 404) {
return failure(ErrorCodes.InvalidParameter, `the token with ID "${this.id}" could not be found`);
}
} else {
out.text(`Deletion of token with ID "${this.id}" canceled`);
}

return success();
}
}
21 changes: 21 additions & 0 deletions src/commands/tokens/lib/format-token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { out } from "../../../util/interaction";
import { models } from "../../../util/apis";

export function reportTokenInfo(token: models.ApiTokensGetResponse | models.ApiTokensCreateResponse): void {
out.report(
[
["ID", "id" ],
[ "Description", "description"],
[ "Created at", "createdAt"]
], token);
}

export function reportToken(token: models.ApiTokensGetResponse | models.ApiTokensCreateResponse): void {
out.report(
[
["ID", "id" ],
[ "API Token", "apiToken" ],
[ "Description", "description"],
[ "Created at", "createdAt"]
], token);
}
25 changes: 25 additions & 0 deletions src/commands/tokens/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Command, CommandArgs, CommandResult, help, success } from "../../util/commandline";
import { out } from "../../util/interaction";
import { reportTokenInfo } from "./lib/format-token";
import { MobileCenterClient, models, clientRequest } from "../../util/apis";

const debug = require("debug")("mobile-center-cli:commands:apps:list");
import { inspect } from "util";

@help("Get a list of API tokens")
export default class ApiTokenListCommand extends Command {
constructor(args: CommandArgs) {
super(args);
}

async run(client: MobileCenterClient): Promise<CommandResult> {
const apiTokensResponse = await out.progress("Getting API tokens ...",
clientRequest<models.ApiTokensGetResponse[]>(cb => client.account.getApiTokens(cb)));

out.table({ head: ['ID', 'Description', 'Created At'], style: { head: [] } },
apiTokensResponse.result.map(apiToken => [apiToken.id, apiToken.description, apiToken.createdAt])
);

return success();
}
}
2 changes: 1 addition & 1 deletion src/util/apis/generated/mobileCenterClient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ declare class MobileCenterClient {
credentials: ServiceClientCredentials;

// Operation groups
data: operations.Data;
account: operations.Account;
buildOperations: operations.BuildOperations;
crashOperations: operations.CrashOperations;
test: operations.Test;
data: operations.Data;
distribute: operations.Distribute;
analytics: operations.Analytics;
}
Expand Down
4 changes: 2 additions & 2 deletions src/util/apis/generated/mobileCenterClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,15 @@ function MobileCenterClient(credentials, baseUri, options) {
MobileCenterClient['super_'].call(this, credentials, options);
this.baseUri = baseUri;
if (!this.baseUri) {
this.baseUri = 'https://api.sonoma.hockeyapp.com/';
this.baseUri = 'https://api.mobile.azure.com/';
}
this.credentials = credentials;

this.data = new operations.Data(this);
this.account = new operations.Account(this);
this.buildOperations = new operations.BuildOperations(this);
this.crashOperations = new operations.CrashOperations(this);
this.test = new operations.Test(this);
this.data = new operations.Data(this);
this.distribute = new operations.Distribute(this);
this.analytics = new operations.Analytics(this);
this.models = models;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@
*
* @member {string} [gradleWrapperPath] Path to the Gradle wrapper script
*
* @member {string} gradleTasks The Gradle tasks to perform
* @member {string} module The Gradle module to build
*
* @member {string} [module] The Gradle module to build
* @member {string} variant The Android build variant to build
*
* @member {string} [variant] The Android build variant to build
* @member {boolean} [runTests] Whether to run unit tests during the build
* (default). Default value: true .
*
* @member {boolean} [runLint] Whether to run lint checks during the build
* (default). Default value: true .
*
*/
function AndroidBranchConfigurationProperties() {
Expand All @@ -45,25 +49,34 @@ AndroidBranchConfigurationProperties.prototype.mapper = function () {
name: 'String'
}
},
gradleTasks: {
module: {
required: true,
serializedName: 'gradleTasks',
serializedName: 'module',
type: {
name: 'String'
}
},
module: {
required: false,
serializedName: 'module',
variant: {
required: true,
serializedName: 'variant',
type: {
name: 'String'
}
},
variant: {
runTests: {
required: false,
serializedName: 'variant',
serializedName: 'runTests',
defaultValue: true,
type: {
name: 'String'
name: 'Boolean'
}
},
runLint: {
required: false,
serializedName: 'runLint',
defaultValue: true,
type: {
name: 'Boolean'
}
}
}
Expand Down
34 changes: 30 additions & 4 deletions src/util/apis/generated/models/androidModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@

'use strict';

var util = require('util');

/**
* @class
* Initializes a new instance of the AndroidModule class.
* @constructor
* @member {string} name Name of the Android module
*
* @member {string} [path] Path to the module
* @member {array} [productFlavors] The product flavors of the Android module
*
* @member {array} [buildVariants] The build variants of the Android module
* (matrix of product flavor + build type (debug|release))
*
*/
function AndroidModule() {
Expand All @@ -39,11 +44,32 @@ AndroidModule.prototype.mapper = function () {
name: 'String'
}
},
path: {
productFlavors: {
required: false,
serializedName: 'path',
serializedName: 'productFlavors',
type: {
name: 'String'
name: 'Sequence',
element: {
required: false,
serializedName: 'StringElementType',
type: {
name: 'String'
}
}
}
},
buildVariants: {
required: false,
serializedName: 'buildVariants',
type: {
name: 'Sequence',
element: {
required: false,
serializedName: 'StringElementType',
type: {
name: 'String'
}
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions src/util/apis/generated/models/androidProject.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ var util = require('util');
* @class
* Initializes a new instance of the AndroidProject class.
* @constructor
* @member {array} modules Gradle modules for the project
* @member {array} androidModules Android Gradle modules
*
* @member {string} [gradleWrapperPath]
* @member {string} [gradleWrapperPath] The path of the Gradle wrapper
*
*/
function AndroidProject() {
Expand All @@ -36,9 +36,9 @@ AndroidProject.prototype.mapper = function () {
name: 'Composite',
className: 'AndroidProject',
modelProperties: {
modules: {
androidModules: {
required: true,
serializedName: 'modules',
serializedName: 'androidModules',
type: {
name: 'Sequence',
element: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@

/**
* @class
* Initializes a new instance of the ApiTokensPostRequest class.
* Initializes a new instance of the ApiTokensCreateRequest class.
* @constructor
* @member {string} [description] The description of the token
*
*/
function ApiTokensPostRequest() {
function ApiTokensCreateRequest() {
}

/**
* Defines the metadata of ApiTokensPostRequest
* Defines the metadata of ApiTokensCreateRequest
*
* @returns {object} metadata of ApiTokensPostRequest
* @returns {object} metadata of ApiTokensCreateRequest
*
*/
ApiTokensPostRequest.prototype.mapper = function () {
ApiTokensCreateRequest.prototype.mapper = function () {
return {
required: false,
serializedName: 'ApiTokensPostRequest',
serializedName: 'ApiTokensCreateRequest',
type: {
name: 'Composite',
className: 'ApiTokensPostRequest',
className: 'ApiTokensCreateRequest',
modelProperties: {
description: {
required: false,
Expand All @@ -42,4 +42,4 @@ ApiTokensPostRequest.prototype.mapper = function () {
};
};

module.exports = ApiTokensPostRequest;
module.exports = ApiTokensCreateRequest;
Loading

0 comments on commit db13312

Please sign in to comment.