Files
devstar_plugin/src/user.ts

141 lines
4.4 KiB
TypeScript
Raw Normal View History

import * as vscode from 'vscode';
import * as path from 'path';
import * as os from 'os';
import * as fs from 'fs';
const {
generateKeyPairSync,
2024-10-28 14:58:10 +08:00
createHash
} = require('node:crypto');
const sshpk = require('sshpk');
export default class User {
private context: vscode.ExtensionContext;
private username: string | undefined;
private userToken: string | undefined;
private usernameKey: string = 'devstarUsername'
private userTokenKey: string = 'devstarUserToken'
private devstarHostname: string;
constructor(context: vscode.ExtensionContext) {
this.context = context;
this.username = this.context.globalState.get(this.usernameKey);
this.userToken = this.context.globalState.get(this.userTokenKey);
// 提取devstar domain的主域名用于本地ssh key的命名
let devstarDomainFromConfig: string|undefined;
let devstarDomainURL: string;
devstarDomainFromConfig = vscode.workspace.getConfiguration('devstar').get('devstarDomain')
// 如果没有配置devstar domain则默认domain为https://devstar.cn
devstarDomainURL = (devstarDomainFromConfig === undefined || devstarDomainFromConfig === "") ? 'https://devstar.cn' : devstarDomainFromConfig;
let parsedUrl = new URL(devstarDomainURL);
this.devstarHostname = parsedUrl.hostname.replace(/\./g, '_'); //提取hostname并用下划线替换.
}
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;
}
public getUserTokenFromLocal(): string | undefined {
return this.userToken;
}
public setUsernameToLocal(username: string) {
this.context.globalState.update(this.usernameKey, username);
this.username = username;
}
public setUserTokenToLocal(userToken: string) {
this.context.globalState.update(this.userTokenKey, userToken)
this.userToken = userToken
}
public getUserPrivateKeyPath(): string {
if (!this.isLogged) {
return '';
}
return path.join(os.homedir(), '.ssh', `id_rsa_${this.username}_${this.devstarHostname}`)
}
public getUserPublicKeyPath(): string {
if (!this.isLogged) {
return '';
}
return path.join(os.homedir(), '.ssh', `id_rsa_${this.username}_${this.devstarHostname}.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 async createUserSSHKey() {
if (this.existUserPublicKey() && this.existUserPrivateKey()) {
// if both public and private key exists, stop
return;
}
const {
publicKey,
privateKey,
} = await generateKeyPairSync('rsa', {
modulusLength: 4096,
publicKeyEncoding: {
type: 'pkcs1',
format: 'pem',
},
privateKeyEncoding: {
type: 'pkcs1',
format: 'pem',
},
});
const publicKeyFingerprint = sshpk.parseKey(publicKey, 'pem').toString('ssh');
const publicKeyStr = publicKeyFingerprint; // public key is public key fingerprint
const privateKeyStr = privateKey;
try {
await fs.writeFileSync(this.getUserPublicKeyPath(), publicKeyStr);
await fs.writeFileSync(this.getUserPrivateKeyPath(), privateKeyStr);
// limit the permission of private key to prevent that the private key not works
await fs.chmodSync(this.getUserPrivateKeyPath(), 0o600)
} catch (error) {
console.error("Failed to write public/private key into the default ssh public/key file: ", error);
}
}
}