kata-cli
Version:
Kata AI Command Line Tools
474 lines (408 loc) • 17.9 kB
text/typescript
import { Component, JsonObject } from "merapi";
import { IHelper } from "interfaces/main";
const inquirer = require("inquirer");
const Table = require("cli-table");
const colors = require("colors");
export default class User extends Component {
constructor(private helper: IHelper, private api: any) {
super();
}
public async login(options: JsonObject) {
try {
let currToken = this.helper.getCurrentToken().token;
if (options.token) {
if (!currToken) {
currToken = options.token as string;
}
this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currToken}`;
let result = await this.helper.toPromise(this.api.authApi, this.api.authApi.tokensTokenIdGet, options.token);
const tokenObj = result.data;
if (tokenObj.type === "user") {
this.setToken({ name: "user", type: tokenObj.type }, options.token as string);
} else if (tokenObj.type === "team") {
result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, tokenObj.teamId);
const team = result.data;
this.setToken({ name: team.username, type: tokenObj.type }, options.token as string);
} else {
throw new Error("Invalid token");
}
} else {
let user = (options.user ? options.user : "") as string;
let pass = (options.password ? options.password : "") as string;
const answer = await inquirer.prompt([
{
type: "input",
name: "user",
message: "username: ",
when() {
return !user;
},
validate(user: string) {
if (!user) {
return "Username cannot be empty";
}
return true;
}
},
{
type: "password",
name: "password",
message: "password: ",
mask: "*",
when() {
return !pass;
},
validate(password: string) {
if (!password) {
return "Password cannot be empty";
}
return true;
}
}
]);
user = answer.user || user;
pass = answer.password || pass;
const result = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: user, password: pass });
if (!result.data.isLoggedIn && !result.data.id) {
console.log(`username or password is incorrect`);
} else {
const token = result.data.id;
this.helper.setProp("first_login", { type: "user", username: user, id: result.data.userId });
this.setToken({ name: user, type: "user", namespace: "platform" }, token);
console.log(`Logged in as ${user}`);
}
}
} catch (e) {
console.log(this.helper.wrapError(e));
}
}
public async logout() {
const answer = await this.helper.inquirerPrompt([
{
type: "confirm",
name: "confirmation",
message: "Do you want to log out ?",
default: false
}
]);
if (!answer.confirmation) {
return;
}
try {
const result = await this.helper.delete();
if (result) {
console.log("Logged out");
} else {
console.log("Please log in first");
}
this.helper.clearCommandSession();
} catch (e) {
console.log(this.helper.wrapError(e));
}
}
public async switch(type: string, name?: string) {
try {
const firstLogin = this.helper.getProp("first_login") as JsonObject;
const currentType = this.helper.getProp("current_user_type");
const currentLogin = this.helper.getProp("current_login");
const username = name ? name : currentLogin;
if (currentType === type && username === currentLogin) {
throw new Error(`Unable to switch : already on ${currentLogin} ${type}`);
}
if (type === "team") {
const { response } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, firstLogin.id);
if (!response) {
throw new Error("Unable to switch team");
}
const teams = response && response.body ? response.body.teams.filter((team: any) => team.username === name) : [];
if (teams.length > 0) {
const result = await this.helper.toPromise(this.api.authApi, this.api.authApi.tokensPost, { type: "team", teamId: teams[0].teamId });
const token = result.data.id;
this.setToken({ name, type: "team" }, token);
this.helper.setProp("current_login", name);
this.helper.setProp("current_user_type", "team");
console.log(`Switched to team: ${name}`);
} else {
console.log("Unable to switch to Team : Invalid team");
}
} else {
this.helper.setProp("current_login", firstLogin.username);
this.helper.setProp("current_user_type", "user");
console.log(`Switched to user ${firstLogin.username}`);
}
} catch (e) {
console.log(this.helper.wrapError(e));
}
}
public async changePassword() {
try {
const passObj = await this.getNewPasswordData();
if (passObj.newPass !== passObj.rePass) {
throw new Error("Invalid retype password");
}
const currentUser = this.helper.getProp("current_login") as string;
const { data } = await this.helper.toPromise(this.api.authApi, this.api.authApi.loginPost, { username: currentUser, password: passObj.oldPass });
if (data) {
const result = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdPut, currentUser, { password: passObj.newPass });
console.log("Password changed");
} else {
console.log("Invalid password");
}
} catch (error) {
console.log(this.helper.wrapError(error));
}
}
public whoami(options: JsonObject) {
const currentLogin = this.helper.getProp("current_login") as string;
const currentType = this.helper.getProp("current_user_type") as string;
console.log(`Current login: ${currentLogin}, login type: ${currentType}`);
}
public async createTeam(name: string) {
try {
const currentLogin = this.helper.getProp("current_login") as string;
const currentUserType = this.helper.getProp("current_user_type") as string;
if (currentUserType !== "user") {
throw new Error("Must be on user to do this operation");
}
const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsPost, { username: name, password: "", roleId: "teamAdmin" });
if (response && response.body.id) {
console.log(`Team ${name} created !`);
} else {
console.log(`Team ${name} exist !`);
}
} catch (error) {
console.log(this.helper.wrapError(error));
}
}
public async createUser(username: string, options?: JsonObject) {
const password = await this.helper.inquirerPrompt([
{
type: "password",
name: "answer",
message: "password: ",
mask: "*",
default: null
}]);
const confirmPassword = await this.helper.inquirerPrompt([
{
type: "password",
name: "answer",
message: "retype password: ",
mask: "*",
default: null
}
]);
try {
if (password.answer !== confirmPassword.answer) {
throw new Error("Invalid retype password");
}
let role: string;
if (options.admin) {
role = "admin";
} else if (options.internal) {
role = "internalUser";
} else {
role = "user";
}
const { data } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdGet, username);
if (data.id) {
throw new Error(`Username ${username} exist !`);
}
const newUser = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersPost, { username, password: password.answer, roleId: role });
console.log(`New user ${newUser.data.username} created !`);
} catch (error) {
console.log(this.helper.wrapError(error));
}
}
public async impersonate(userName: string) {
// TODO : dibuat seperti login, pake inquirer.
try {
const currentLogin: string = this.helper.getProp("current_login").toString();
if (currentLogin !== "admin") {
throw new Error(`Your login status is not superadmin. You are not authorized to impersonate a user`);
}
// set header bearer token
const currentToken: string = this.helper.getCurrentToken().token.toString();
this.api.authApi.apiClient.defaultHeaders.Authorization = `Bearer ${currentToken}`;
// get user id from username
const limit: number = 1;
const { response } = await this.helper.toPromise(
this.api.userApi, this.api.userApi.usersSearchGet, userName, limit
);
const users = response.body;
const name: string = users.map( (user: any) => user.username )[0].toString();
const id: string = users.map( (user: any) => user.userId )[0].toString();
if ( userName !== name ) {
throw new Error(`Sorry, username is not exist.`);
}
// impersonate function
const result = await this.helper.toPromise(
this.api.authApi, this.api.authApi.impersonatePost,
{
userId: id,
namespace: "platform"
}
);
// set value on .katajson
const impersonateToken: string = result.data.id.toString();
const type: string = result.data.type.toString();
this.setToken({ name, type }, impersonateToken);
console.log(`Succesfully impersonate as ${colors.green(name)}`);
} catch (error) {
console.log(this.helper.wrapError(error));
}
}
// unimpersonate command
public async unimpersonate() {
try {
const userName: string = this.helper.getProp("current_login").toString();
this.helper.deleteKeyToken(userName);
const currentLogin: string = this.helper.getProp("current_login").toString();
console.log(`Succesfully unimpersonate user. Now your current login is ${colors.green(currentLogin)}`);
} catch (error) {
console.log(this.helper.wrapError(error));
}
}
private setToken(userInfo: JsonObject, token: string) {
this.helper.setProp("current_login", userInfo.name);
this.helper.setProp("current_user_type", userInfo.type);
this.helper.setProp("namespace", userInfo.namespace);
const tokenProp = (this.helper.getProp("token") || {}) as JsonObject;
tokenProp[userInfo.name as string] = token;
this.helper.setProp("token", tokenProp);
}
private async getNewPasswordData(): Promise<JsonObject> {
let oldPass : string;
let newPass : string;
let rePass : string;
const answer = await inquirer.prompt([
{
type: "password",
name: "oldPass",
message: "current password: ",
mask: "*",
when() {
return !oldPass;
},
validate(user : string) {
if (!user) {
return "Password cannot be empty";
}
return true;
}
},
{
type: "password",
name: "newPass",
message: "new password: ",
mask: "*",
when() {
return !newPass;
},
validate(password: string) {
if (!password) {
return "Password cannot be empty";
}
return true;
}
},
{
type: "password",
name: "rePass",
message: "retype new password: ",
mask: "*",
when() {
return !rePass;
},
validate(password: string, answer: JsonObject) {
if (!password) {
return "Password cannot be empty";
}
if (password !== answer.newPass) {
return "Invalid retype password";
}
return true;
}
},
]);
return answer;
}
public async forgot(username: string) {
try {
const current_login = this.helper.getProp("current_login")
if (!current_login) {
const { response } = await this.helper.toPromise(this.api.authApi, this.api.authApi.forgotPost, { username });
if (response && response.body && response.body.message) {
console.log("Please check your email to reset your password.")
}
} else {
console.log(`Please log out first`)
}
} catch (e) {
console.error(this.helper.wrapError(e));
}
}
public async listTeam() {
try {
const current_login = this.helper.getProp("current_login")
if (current_login) {
const { response } = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login);
const table = new Table({
head: ["Team Name", "Projects", "Members", "Bots"],
colWidths: [50, 15, 15, 15]
});
response.body.forEach((team: JsonObject) => {
table.push([team.username, team.projects, team.members, team.bots]);
});
console.log(table.toString());
} else {
console.log("Please log in first");
}
} catch (e) {
console.error(this.helper.wrapError(e));
}
}
public async listTeamUser(teamName?: string) {
try {
const current_login = this.helper.getProp("current_login")
if (current_login) {
const dataTeams = await this.helper.toPromise(this.api.userApi, this.api.userApi.usersUserIdTeamsGet, current_login);
const teams: object[] = dataTeams.response.body;
const choices = teams.map((team: any) => ({
name: team.username,
value: team.teamId
}));
let teamId = null
if (teamName) {
const sameName = choices.find((choice: any) => choice.name === teamName);
if (sameName) {
teamId = sameName.value
}
} else {
const choice = await inquirer.prompt([
{
type: "list",
name: "teamId",
message: "Team:",
choices: choices
}
]);
teamId = choice.teamId
}
const { response } = await this.helper.toPromise(this.api.teamApi, this.api.teamApi.teamsTeamIdUsersGet, teamId);
const table = new Table({
head: ["Username", "Role"],
colWidths: [50, 25]
});
response.body.forEach((user: JsonObject) => {
table.push([user.username, user.roleName]);
});
console.log(table.toString());
} else {
console.log("Please log in first");
}
} catch (e) {
console.error(this.helper.wrapError(e));
}
}
}