Skip to content

Commit

Permalink
feat(login): add --token option
Browse files Browse the repository at this point in the history
  • Loading branch information
robingenz committed May 2, 2024
1 parent 9f017be commit 2cdd649
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 37 deletions.
69 changes: 42 additions & 27 deletions src/commands/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,57 @@ import userConfig from '../utils/userConfig';
import { API_URL } from '../config';
import { passwordPrompt, prompt } from '../utils/prompt';
import { isRunningInCi } from '../utils/ci';
import usersService from '../services/users';

export default defineCommand({
meta: {
name: 'login',
description: 'Sign in to the Capawesome Cloud Console.',
},
args: {
token: {
type: 'string',
description: 'Token to use for authentication.',
},
},
run: async (ctx) => {
if (isRunningInCi()) {
consola.error(
'Sign in is not supported in CI environments. Please use the CAPAWESOME_TOKEN environment variable.',
let token = ctx.args.token;
if (token) {
userConfig.write({
token: token,
});
try {
await usersService.me();
} catch (error) {
userConfig.write({});
consola.error('Invalid token.');
return;
}
consola.success(`Successfully signed in.`);
} else {
const email = await prompt('Enter your email:', { type: 'text' });
const password = await passwordPrompt('Enter your password:');
consola.start('Logging in...');
let sessionId: string;
try {
const sessionResponse = await axios.post<{ id: string }>(`${API_URL}/sessions`, {
email: email,
password: password,
});
sessionId = sessionResponse.data.id;
} catch (error) {
consola.error('Invalid email or password.');
return;
}
const tokenResponse = await axios.post<{ token: string }>(
`${API_URL}/tokens`,
{ name: 'Capawesome CLI' },
{ headers: { Authorization: `Bearer ${sessionId}` } },
);
return;
}
const email = await prompt('Enter your email:', { type: 'text' });
const password = await passwordPrompt('Enter your password:');
consola.start('Logging in...');
let sessionId: string;
try {
const sessionResponse = await axios.post<{ id: string }>(`${API_URL}/sessions`, {
email: email,
password: password,
userConfig.write({
token: tokenResponse.data.token,
});
sessionId = sessionResponse.data.id;
} catch (error) {
consola.error('Invalid email or password.');
return;
consola.success(`Successfully signed in.`);
}
const tokenResponse = await axios.post<{ token: string }>(
`${API_URL}/tokens`,
{ name: 'Capawesome CLI' },
{ headers: { Authorization: `Bearer ${sessionId}` } },
);
userConfig.write({
username: email,
token: tokenResponse.data.token,
});
consola.success(`Successfully signed in.`);
},
});
5 changes: 1 addition & 4 deletions src/commands/logout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ export default defineCommand({
},
args: {},
run: async () => {
const config = userConfig.read();
delete config.username;
delete config.token;
userConfig.write(config);
userConfig.write({});
consola.success('Successfully signed out.');
},
});
14 changes: 10 additions & 4 deletions src/commands/whoami.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
import { defineCommand } from 'citty';
import consola from 'consola';
import userConfig from '../utils/userConfig';
import usersService from '../services/users';

export default defineCommand({
meta: {
name: 'whoami',
description: 'Show current user',
},
run: async () => {
const { username } = userConfig.read();
if (!username) {
consola.error('Not logged in');
const { token } = userConfig.read();
if (token) {
try {
const user = await usersService.me();
consola.info(`Logged in as ${user.email}.`);
} catch (error) {
consola.error('Token is invalid. Please sign in again.');
}
} else {
consola.info(`Logged in as ${username}`);
consola.error('Not logged in.');
}
},
});
31 changes: 31 additions & 0 deletions src/services/users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { UserDto } from '../types';
import httpClient, { HttpClient } from '../utils/http-client';
import authorizationService from './authorization-service';

export interface UsersService {
me(): Promise<UserDto>;
}

class UsersServiceImpl implements UsersService {
private readonly httpClient: HttpClient;

constructor(httpClient: HttpClient) {
this.httpClient = httpClient;
}

async me(): Promise<UserDto> {
const response = await this.httpClient.get<UserDto>('/users/me', {
headers: {
Authorization: `Bearer ${authorizationService.getCurrentAuthorizationToken()}`,
},
});
if (!response.success) {
throw response.error;
}
return response.data;
}
}

const usersService = new UsersServiceImpl(httpClient);

export default usersService;
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './app';
export * from './app-bundle';
export * from './app-device';
export * from './app-channel';
export * from './user';
4 changes: 4 additions & 0 deletions src/types/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface UserDto {
id: string;
email: string;
}
2 changes: 0 additions & 2 deletions src/utils/userConfig.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { readUser, writeUser } from 'rc9';

export interface IUserConfig {
username?: string;
token?: string;
}

export interface UserConfig {
read(): IUserConfig;

write(config: IUserConfig): void;
}

Expand Down

0 comments on commit 2cdd649

Please sign in to comment.