Skip to content

Commit

Permalink
implemented cli login, not fully done but almost
Browse files Browse the repository at this point in the history
  • Loading branch information
samifouad committed Sep 10, 2024
1 parent e900bdb commit 232283a
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 1 deletion.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { status } from './status/status'
export { check } from './check/check'
export { init } from './new/new'
export { add } from './add/add'
export { login } from './login/login'


export const sleep = (ms = 2000) => new Promise((resolve) => setTimeout(resolve, ms));
108 changes: 108 additions & 0 deletions core/login/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { sleep, serve, $ } from 'bun'
import { createSpinner } from 'nanospinner'
import data from '#/package.json' with { type: 'json' }
import { sysinfo } from '!/utils'
import base64url from 'base64url'

export async function login() {
let spinner = createSpinner(' task: initiate login flow for fromafri.ca').start();

const port = 55555;
let isAuthorized = false;

// Start the local server to handle the OAuth redirect
const server = serve({
port: port,
async fetch(req) {
const url = new URL(req.url);
const params = new URLSearchParams(url.search);

if (url.pathname === '/callback') {
const authCode = params.get('code');
if (authCode) {
spinner2.success({ text: `Received OAuth code: ${authCode}`})
isAuthorized = true;
// Send the response
const response = new Response("Login successful! You can close this window.");

// Allow some time for the response to be sent
setTimeout(() => {
server.stop(); // Stop the server
process.exit(0); // Exit
}, 100); // Adjust the delay as needed

return response;

} else {
// Send the response
const response = new Response("No OAuth code received.");

// Allow some time for the response to be sent
setTimeout(() => {
server.stop(); // Stop the server
process.exit(1); // Exit with failure code
}, 100); // Adjust the delay as needed

return response;
}


}

return new Response("Not Found", { status: 404 });
server.stop(); // Stop the server
process.exit(1); // Exit with failure code
},
});

let params = [
{ client: `${data.name}_v${data.version}`},
{ redirect_uri: `http://localhost:${port}/callback`},
{ response_type: 'code'},
]

const client_info = await sysinfo()

params.push(...client_info)

params = await base64url(JSON.stringify(params))

const authUrl = `http://localhost:3000/cli?a=${params}`;

spinner.success();

let browser_spinner = createSpinner(' task: launch browser').start();

// Attempt to open the browser
try {
if (process.platform === 'win32') {
await $`start ${authUrl}`.quiet();
browser_spinner.success();
} else if (process.platform === 'darwin') {
await $`open ${authUrl}`.quiet();
browser_spinner.success();
} else if (process.platform === 'linux') {
await $`xdg-open ${authUrl}`.quiet();
browser_spinner.success();
} else {
throw new Error('unsupported platform');
}
} catch (error) {
console.log('\nautomatic browser launch failed');
browser_spinner.error({ text: 'Browser launch failed' });
}

console.log(`\nyou can use this URL if your browser didn't open:\n\n${authUrl}`);
console.log('\n');

let spinner2 = createSpinner(' task: waiting for login...').start();

// Set a timeout for 15 seconds (15000 ms)
const timeout = setTimeout(() => {
if (!isAuthorized) {
server.stop(); // Stop the server on timeout
spinner2.error({ text: 'Login failed: timeout' });
process.exit(1); // Exit with failure code
}
}, 30000);
}
7 changes: 7 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,11 @@ program
console.log('get')
})

program
.command('login')
.description('authenticate with fromafri.ca')
.action(async () => {
await core.login()
})

program.parse()
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "gild-cli",
"version": "0.7.0",
"module": "index.ts",
"type": "module",
"scripts": {
Expand All @@ -13,6 +14,7 @@
},
"dependencies": {
"ansi-colors": "^4.1.3",
"base64url": "^3.0.1",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"inquirer": "^10.1.2",
Expand Down
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
// imports
"paths": {
"@/core": ["./core/index.ts"],
"@/*": ["./core/*"]
"@/*": ["./core/*"],
"!/utils": ["./utils/index.ts"],
"#/*": ["./*"]
},

// Bundler mode
Expand Down
1 change: 1 addition & 0 deletions utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { sysinfo } from './sysinfo/sysinfo'
27 changes: 27 additions & 0 deletions utils/sysinfo/sysinfo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os from 'node:os'

export async function sysinfo() {
const platform = os.platform();
const osVersion = os.release();
const architecture = os.arch();

const networkInterfaces = os.networkInterfaces();
let ipAddress = '';
for (const [key, interfaces] of Object.entries(networkInterfaces)) {
for (const iface of interfaces) {
if (iface.family === 'IPv4' && !iface.internal) {
ipAddress = iface.address;
break;
}
}
if (ipAddress) break;
}

// payload
return [
{machineType: platform},
{osVersion: osVersion},
{architecture: architecture},
{ipAddress: ipAddress},
]
}

0 comments on commit 232283a

Please sign in to comment.