[WIP] Feat: create/get user public/private key

This commit is contained in:
Levi Yan
2024-10-23 18:37:27 +08:00
parent 1e856694af
commit 4b3868ced2
3 changed files with 153 additions and 2 deletions

View File

@@ -85,6 +85,25 @@ export default class DSHome {
panel.webview.postMessage({command: 'setUsername', data: {ok: false}});
break;
}
case 'getUserPublicKey':
var userPublicKey = '';
if (this.user.existUserPrivateKey()) {
userPublicKey = this.user.getUserPublicKey();
panel.webview.postMessage({command: 'getUserPublicKey', data: {userPublicKey: userPublicKey}})
break;
} else {
panel.webview.postMessage({command: 'getUserPublicKey', data: {userPublicKey: userPublicKey}})
break;
}
case 'createUserPublicKey':
this.user.createUserSSHKey();
if (this.user.existUserPublicKey()) {
panel.webview.postMessage({command: 'createUserPublicKey', data: {ok: true}})
break;
} else {
panel.webview.postMessage({command: 'createUserPublicKey', data: {ok: false}})
break;
}
case 'getDefaultPublicKey':
var defaultPublicKey;
if (utils.existDefaultPublicKey()) {

View File

@@ -1,6 +1,10 @@
import * as vscode from 'vscode';
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs';
const {
generateKeyPairSync,
} = require('node:crypto')
export default class User {
private context:vscode.ExtensionContext;
@@ -15,6 +19,23 @@ export default class User {
this.userToken = this.context.globalState.get(this.userTokenKey);
}
private isLogged() {
var existUsername = false;
var existUserToken = false;
if(this.username != undefined && this.username != '') {
existUsername = true;
}
if(this.userToken != undefined && this.userToken != '') {
existUserToken = true;
}
if (existUsername && existUserToken) {
return true;
} else {
return false;
}
}
public getUsernameFromLocal(): string|undefined {
return this.username;
}
@@ -33,4 +54,73 @@ export default class User {
this.userToken = userToken
}
public getUserPrivateKeyPath() : string{
if (!this.isLogged) {
return '';
}
return path.join(os.homedir(), '.ssh', `id_rsa_${this.username}`)
}
public getUserPublicKeyPath() :string{
if (!this.isLogged) {
return '';
}
return path.join(os.homedir(), '.ssh', `id_rsa_${this.username}.pub`)
}
public existUserPublicKey() :boolean{
const userPublicKeyPath = this.getUserPublicKeyPath();
return fs.existsSync(userPublicKeyPath)
}
public existUserPrivateKey() :boolean{
const userPrivateKeyPath = this.getUserPrivateKeyPath();
return fs.existsSync(userPrivateKeyPath)
}
public getUserPublicKey(): string {
const userPublicKeyPath = this.getUserPublicKeyPath();
const userPublicKey = fs.readFileSync(userPublicKeyPath, 'utf-8');
// remove `\r` `\n`
const trimmedDefaultPublicKey = userPublicKey.replace(/[\r\n]/g, "");
return trimmedDefaultPublicKey;
}
public getUserPrivateKey(): string {
const userPrivateKey = this.getUserPrivateKeyPath();
return fs.readFileSync(userPrivateKey, 'utf-8');
}
public createUserSSHKey() {
if (this.existUserPublicKey() && this.existUserPrivateKey()) {
// if both public and private key exists, stop
return;
}
const {
publicKey,
privateKey,
} = generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs8',
format: 'pem',
cipher: 'aes-256-cbc',
passphrase: 'devstar'
},
});
try {
fs.writeFileSync(this.getUserPublicKeyPath(), publicKey);
fs.writeFileSync(this.getUserPrivateKeyPath(), privateKey);
} catch(error) {
console.error("Failed to write public/private key into the default ssh public/key file: ", error);
}
}
}

View File

@@ -314,7 +314,7 @@ header("Allow: GET, POST, OPTIONS, PUT, DELETE");
document.getElementById('loginModal').style.display = 'none';
}
function login() {
async function login() {
var username = document.getElementById('username').value;
var password = document.getElementById('password').value;
const url = DEVSTAR_HOME + `/api/v1/users/${username}/tokens`;
@@ -343,7 +343,7 @@ header("Allow: GET, POST, OPTIONS, PUT, DELETE");
}
return response.json();
})
.then(data => {
.then(async data => {
// store token in global variable and vscode global state
USERTOKEN = data.sha1;
USERNAME = username;
@@ -351,6 +351,21 @@ header("Allow: GET, POST, OPTIONS, PUT, DELETE");
setUsernameToVSCode(username);
loadPageModules()
// if user public key exist, meaning that public key has been uploaded
await getUserPublicKeyFromVSCode()
.then(async userPublicKey => {
if (userPublicKey == '') {
await createUserPublicKeyByVSCode()
await getUserPublicKeyFromVSCode()
.then(async userPublicKey => {
// upload new created public key
})
}
})
closeLoginModal()
})
.catch(error => {
@@ -418,6 +433,33 @@ header("Allow: GET, POST, OPTIONS, PUT, DELETE");
})
}
async function getUserPublicKeyFromVSCode() {
return new Promise(async (resolve, reject) => {
await communicateVSCodeByWebview('getUserPublicKey', {})
.then(data => {
const publicKey = data.userPublicKey;
resolve(publicKey)
})
.catch(error => {
reject(error)
})
})
}
async function createUserPublicKeyByVSCode() {
await communicateVSCodeByWebview('createUserPublicKey', {})
.then(res => {
if (res.ok) {
console.log('User public key has been created')
} else {
console.error('Failed to create user public key')
}
})
.catch(error => {
console.error('Failed to request to create user public key: ', erro)
})
}
// ===================================== Repo ===========================
function loadRepositories() {
// clear old data