From f1eb9ec78e01b3314e923b773dd5ac0dbade5f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCbleitner?= Date: Tue, 27 Aug 2019 20:58:37 +0200 Subject: [PATCH 1/2] cleaned up, no extensions --- src/backend/Extension.ts | 428 ------------------------------------ src/backend/UpdateManger.ts | 21 -- 2 files changed, 449 deletions(-) delete mode 100644 src/backend/Extension.ts diff --git a/src/backend/Extension.ts b/src/backend/Extension.ts deleted file mode 100644 index 2cee98c..0000000 --- a/src/backend/Extension.ts +++ /dev/null @@ -1,428 +0,0 @@ - -import * as Logger from 'log4js' -import * as path from "path"; -import { promises as fs } from "fs" -import * as git from "simple-git/promise" -import * as trash from "trash" - - -Logger.configure({ - appenders: - { - "admin/extension": { type: 'stdout' }, - //app: { type: 'file', filename: 'application.log' } - }, - categories: - { - default: { appenders: [ 'admin/extension' ], level: 'debug' } - } -}) -const exec = require('child-process-promise').exec; -const logger = Logger.getLogger("admin/updatemanager") - -type SharedStatus = { - name: string - installed?: boolean - outdated?: boolean -} - -abstract class Extension{ - constructor( - protected name: string - ){} - - /** - * the generic Status object - */ - protected async status():Promise{ - const installed = await this.isInstalled() - const outdated = await this.isOutdated() - return { name: this.name, installed: installed, outdated: outdated } - } - - /** - * true => extension was installed - * false => extension was not install - * undefined => signals error - */ - abstract async install():Promise - - /** - * reverts the install procedure - */ - abstract async uninstall():Promise - - /** - * true => an update was performed - * false => no update was performed - * undefined => signals error - */ - abstract async update(force?: boolean): Promise - - /** - * true => update would install a newer version - * false => nothing would be updated if update would be performed - * undefined => signals error - */ - abstract async isOutdated():Promise - - /** - * promises a boolean - * true => install would do nothing would it be called - * false => install would try to install the newest extension - * undefined => signals error - */ - abstract async isInstalled():Promise -} - -export type FSStatus = SharedStatus & { - path: string - empty?: boolean -} - -export abstract class FSExtension extends Extension{ - constructor( - name: string, - protected readonly path: string){ - super(name) - } - - public async status(): Promise{ - const shdStatus = await super.status() - const empty = await this.isEmpty() - return {...shdStatus, prefix: this.path, empty: empty} - } - - public async install():Promise{ - const installed = await this.isInstalled() - if (!installed) { - logger.info('Installing extension to', path.resolve(this.path, this.name)) - await fs.mkdir(path.resolve(this.path, this.name), {recursive: true}) - return true - } - logger.error('Extension already installed at', path.resolve(this.path, this.name)) - return false - } - - public async uninstall(): Promise{ - logger.info('Uninstalling extension from', path.resolve(this.path, this.name)) - return await trash(path.resolve(this.path, this.name)) - } - - public async update(force?: boolean): Promise{ - if (force) await this.uninstall() - return await this.install() - } - - public async isEmpty(): Promise{ - if (!this.isInstalled()) return true - try { - const files = await fs.readdir(path.resolve(this.path, this.name)) - return files.length === 0 - } catch (error) { - logger.error("fs read error", error) - return - } - } - - public async isInstalled(): Promise{ - try { - await fs.access(path.resolve(this.path, this.name)) - return true - } catch (error) { - return false - } - } -} - -type NPMStatus = FSStatus & { - latest?: string, - current?: string, - author?: string - license?: string, - description?: string -} - -export class NPMExtension extends FSExtension{ - private prefix: string - constructor( - pkgName: string, - prefix: string = './plugins', - private version: string, - ){ - super(pkgName, path.resolve(prefix, pkgName, "node_modules")) - this.prefix = (path.resolve(prefix, pkgName)) - } - - public async status(): Promise { - - const fsStatus = await super.status() - const latest = await this.getLatestVersion() - const author = await this.getAuthor() - const current = await this.getCurrentVersion() - const license = await this.getLicense() - const description = await this.getDescription() - - return { - ...fsStatus, - latest: latest, - author: author, - current: current, - license: license, - description: description - } - } - - public async install(): Promise { - super.install() - logger.info("npm install", this.name, 'to', path.resolve(this.prefix, this.name)) - const { error, stdout, stderr } = await exec('npm install --prefix '+ this.prefix + ' ' + this.name+"@"+this.version) - if (error) { - logger.error('npm install', this.name, "@", this.version, ' from prefix', this.prefix, 'stderr:', stderr) - return false - } else { - logger.info('npm install', this.name, "@", this.version, 'from prefix', this.prefix, 'stdout:', stdout) - return true - } - } - - public async uninstall(force?: boolean): Promise { - super.uninstall() - logger.info("npm uninstall", this.name, 'from', path.resolve(this.prefix, this.name)) - const { error, stdout, stderr } = await exec('npm uninstall --prefix '+ this.prefix + ' ' + this.name) - if (error) { - logger.error('npm uninstall', this.name, 'from prefix', this.prefix, 'stderr:', stderr) - } else { - logger.info('npm uninstall', this.name, 'from prefix', this.prefix, 'stdout:', stdout) - } - } - - public async update(force?: boolean): Promise { - super.update(force) - logger.info("npm update", path.resolve(this.prefix, this.name)) - const { error, stdout, stderr } = await exec('npm update --prefix '+ this.prefix + ' ' + this.name) - if (error) { - logger.error('npm update', this.name, 'from prefix', this.prefix, 'stderr:', stderr) - return false - } else { - logger.info('npm update', this.name, 'from prefix', this.prefix, 'stdout:', stdout) - return true - } - } - - public async isOutdated(): Promise { - try { - const { - error, - stdout, - stderr } = await exec('npm outdated --prefix ' + this.prefix + " --json" + ' ' + this.name) - if (error) throw new Error(stderr) - if (Object.keys(JSON.parse(stdout)).length > 0) return true - else return false - } catch (error) { - logger.error('npm outdated', this.name, 'from prefix', this.prefix, 'stderr:', error) - return - } - } - - private async getAuthor(): Promise{ - const { - error, - stdout, - stderr } = await exec('npm author ls --prefix ' + this.prefix + ' ' + this.name) - - if(error){ - logger.error(stderr) - return - } else { - logger.info(stdout) - return stdout - } - } - - private async getLatestVersion(): Promise{ - try{ - const { - error, - stdout, - stderr } = await exec('npm view --prefix ' + this.prefix + ' ' + this.name + " version") - - if(error){ - logger.error(stderr) - return - } else { - logger.info(stdout) - return stdout - } - }catch(error){ - logger.error(error) - return - } - } - - private async getCurrentVersion(): Promise{ - try{ - const { - error, - stdout, - stderr } = await exec('npm list --json --prefix ' + this.prefix + ' ' + this.name) - - if(error){ - logger.error(stderr) - return - } else { - logger.info(stdout) - return JSON.parse(stdout) - ['dependencies'] - ['frontblock'] - ['dependencies'] - [this.name] - ['version'] - } - }catch(error){ - logger.error(error) - return - } - } - - private async getDescription(): Promise{ - try{ - const { - error, - stdout, - stderr } = await exec('npm show --prefix ' + this.prefix + ' ' + this.name+" description") - - if(error){ - logger.error(stderr) - return - } else { - logger.info(stdout) - return stdout - } - }catch(error){ - logger.error(error) - return - } - } - - private async getLicense(): Promise{ - try{ - - const { - error, - stdout, - stderr } = await exec('npm show --prefix ' + this.prefix + ' ' + this.name+" license") - - if(error){ - logger.error(stderr) - return - } else { - logger.info(stdout) - return stdout - } - }catch(error){ - logger.error(error) - return - } - } -} - -export type GitStatus = FSStatus & { - branch?: string - remote?: string - latest?: string -} - -export class GitExtension extends FSExtension{ - protected repo: git.SimpleGit - constructor( - repoName:string, - localPrefix:string, - protected gitCloneURL: string, - protected credentials?: [string, string] - ){ - super(repoName, localPrefix) - } - - public async status(): Promise{ - const fsStatus = await super.status() - - return { - ...fsStatus, - branch: 'wat', - remote: this.gitCloneURL, - latest: 'kek' - } - } - - public async install(): Promise { - if (super.install()){ - if (this.credentials){ - - } else { - - } - } else { - - } - return false; - } - - - public async update(): Promise { - return true // do git pull remote origin && git checkout - } - - public async isOutdated(): Promise { - return true - } -} - -export type PluginStatus = GitStatus & { - hasFrontend: boolean, - hasBackend: boolean, - isFrontendLoaded: boolean, - isBackendLoaded: boolean -} - -export class PluginExtension extends GitExtension { - protected frontendLoaded: boolean - protected backendLoaded: boolean - - constructor( - pluginName: string, - gitCloneURL: string, - localPrefix: string = './plugins', - credentials?: [string, string], - protected hasBackend: boolean = true, - protected hasFrontend: boolean = true){ - super(pluginName,localPrefix,gitCloneURL,credentials) - } - - public async load(): Promise{ - if (this.hasFrontend) await this.loadFrontend() - if (this.hasBackend) await this.loadBackend() - } - - public async loadFrontend(): Promise{ - return //TODO - } - - public async loadBackend(): Promise{ - return //TODO - } - - public async unload(): Promise{ - if (this.hasFrontend) await this.unloadFrontend() - if (this.hasBackend) await this.unloadBackend() - } - - public async unloadFrontend(): Promise{ - return //TODO - } - - public async unloadBackend(): Promise{ - return //TODO - } - -} \ No newline at end of file diff --git a/src/backend/UpdateManger.ts b/src/backend/UpdateManger.ts index bd29748..67c7c86 100644 --- a/src/backend/UpdateManger.ts +++ b/src/backend/UpdateManger.ts @@ -4,7 +4,6 @@ import { GitUpdater, RepoFolderStatus } from "./GitUpdater"; import { FrontblockCherryPicker } from "git-cherrypicker"; import * as Logger from 'log4js' import { FrontblockAdmin } from "./FrontblockAdmin"; -import { NPMExtension } from "./Extension"; import { TableDefiniton } from "frontblock-generic/Admin"; var exec = require('child-process-promise').exec; @@ -79,26 +78,6 @@ export class UpdateManager extends Plugin{ async updatePlatformDependencies(){ logger.info("installing npm stuff") - -/* - const res = await exec('npm install --prefix ./plugins knex sqlite3') - logger.warn(res.stderr) - logger.info(res.stdout) -*/ - - /* - const extensions = [ - new NPMExtension("sqlite3", "./plugins", "4.1.0"), - new NPMExtension("frontblock", "./plugins", "latest") - - ] - */ - - const extensions:NPMExtension[] = [] - - await Promise.all(extensions.map(e => e.install())) - const status = await Promise.all(extensions.map(e => e.status())) - console.log(status) } async installPlugin(name: string, force:boolean = false):Promise{ From 3a9aae3f7bdb11019ed20a4749ca3a8fa05465f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=BCbleitner?= Date: Tue, 27 Aug 2019 21:06:44 +0200 Subject: [PATCH 2/2] renamed some stuff --- src/backend/FrontblockAdmin.ts | 179 --------------------------------- src/backend/Main.ts | 10 +- src/backend/UpdateManger.ts | 2 +- 3 files changed, 6 insertions(+), 185 deletions(-) delete mode 100644 src/backend/FrontblockAdmin.ts diff --git a/src/backend/FrontblockAdmin.ts b/src/backend/FrontblockAdmin.ts deleted file mode 100644 index 8a79d36..0000000 --- a/src/backend/FrontblockAdmin.ts +++ /dev/null @@ -1,179 +0,0 @@ -'use strict' - -import * as Logger from 'log4js' -import * as Knex from 'knex' -import { FrontblockApiClient, FrontblockApiConf } from 'frontblock'; -import { AdminBase } from 'frontblock-generic/Admin'; -import express = require('express'); -import http = require('http'); -import bsock = require('bsock'); -import { promises as fs } from "fs" -import * as path from "path" -import { UpdateManager } from './UpdateManger'; -import { FrontblockApi } from 'frontblock-generic/Api'; -import { Plugin } from 'frontblock-generic/Plugin'; -var exec = require('child-process-promise').exec; - -Logger.configure({ - appenders: - { - "admin": { type: 'stdout' }, - //app: { type: 'file', filename: 'application.log' } - }, - categories: - { - default: { appenders: [ 'admin' ], level: 'debug' } - } -}) -const logger = Logger.getLogger("admin") - - -export type AdminConf = { httpPort: number} - -/** - * FrontblockAdmin - * - * The customer-facing dynamic component of the customer backend - * Supports (un)loading plugins which will be communicated to its library component (See FrontblockLib.ts and the info() RPC) - * - * The list of available plugins is published via the frontblock API and downloaded via gitea-releases - */ -export class FrontblockAdmin extends AdminBase{ - - private express - private httpServer - private io = bsock.createServer() - private wsServer = http.createServer() - private updateManager:UpdateManager = new UpdateManager(this) - - constructor(runningPlugins: Plugin[] = []){ - super(runningPlugins) - this.initialize() - } - - getDefaultConfig(): { apiConf: FrontblockApiConf; } & AdminConf & { dbConf:Knex.Config; } { - return { - httpPort: 8080, - apiConf: { - apiHost: "api.testnet.frontblock.me", - apiKey: "", - apiPort: 10001, - tls: false - }, - dbConf: { - client: 'sqlite3', - connection: { - filename: "./data/ApiClient.sqlite" - }, - useNullAsDefault: true - } - } - } - - protected makeApiClient(conf: FrontblockApiConf): FrontblockApi { - // @ts-ignore - if(this.apiClient) this.apiClient.disconnect() - this.apiClient = new FrontblockApiClient(conf) - - // @ts-ignore - this.apiClient.connect() - return this.apiClient - } - - private async initialize(){ - this.addPlugin(this.updateManager) - await this.updateManager.updateAdmin() - await this.updateManager.updatePlatformDependencies() - await this.updateManager.updateDashboard() - await this.updateManager.updateFrontblockLib() - - this.startWebsocket() - this.startWebserver() - } - - private startWebserver(){ - if(this.httpServer != null || this.express != null){ - logger.warn("Webserver is already running") - return - } - - let port:number = this.getConfig().httpPort - this.express = express() - this.express.use('/', express.static('static')) - - /** - * get the compiled FrontendPlugins.js - */ - this.express.get('/plugins/:id'+".js", async (request, response) => { - const pth = path.resolve("plugins/"+request.params.id, "FrontendPlugin.js"); - const file = await fs.readFile(pth) - const frontend = file.toString() - - response.status(200) - response.set('Content-Type', 'application/javascript') - response.send(frontend) - }) - - /** - * serve the index.html from the static folder - */ - this.express.get("/", (request, response) => { - response.status(200) - response.sendFile('index.html'); - }) - - /** - * redirect all the other traffic to the single - * page app to the main entry point from where - * a webpacked and rolled up index.html is serverd - * and angular takes over routing - */ - this.express.get("*", (request, response) => { - response.status(301) - response.redirect('/') - }) - - this.httpServer = new http.Server(this.express) - this.httpServer.listen(port, () => { - logger.info('Admin panel listening for HTTP on *'+port) - }) - } - - private stopWebserver(){ - if(this.httpServer == null || this.express == null){ - logger.warn("Webserver is not running") - return - } - this.httpServer.close() - this.httpServer = null - this.express = null - logger.info("Webserver stopped") - } - - private startWebsocket(){ - try{ - this.io.attach(this.wsServer) - this.io.on('socket', (socket) => { - logger.info("New Websocket connection on port", socket.port) - - const handleError = (e: any) => { - logger.info("Websocket closing", String(e)) - socket.close() - } - - socket.on('error', handleError) - this.initApis(socket) - }) - logger.info('Admin websocket listening on *20000') - this.wsServer.listen(20000) - }catch(e){ - logger.error(String(e)) - } - } -} - -process.on( 'SIGINT', function() { - logger.info( "Gracefully shutting down from SIGINT (Ctrl-C)" ); - // some other closing procedures go here - process.exit( ); - }) \ No newline at end of file diff --git a/src/backend/Main.ts b/src/backend/Main.ts index 539c7fc..908f757 100644 --- a/src/backend/Main.ts +++ b/src/backend/Main.ts @@ -5,21 +5,21 @@ var exec = require('child-process-promise').exec; Logger.configure({ appenders: { - "admin": { type: 'stdout' }, + "main": { type: 'stdout' }, //app: { type: 'file', filename: 'application.log' } }, categories: { - default: { appenders: [ 'admin' ], level: 'debug' } + default: { appenders: [ 'main' ], level: 'debug' } } }) -const logger = Logger.getLogger("admin") +const logger = Logger.getLogger("main") logger.info("Checking npm dependencies...") exec("npm i --prefix ./plugins knex@0.19.2 sqlite3@4.1.0").then(process => { logger.debug(process.stdout) - const admin = require("./FrontblockAdmin").FrontblockAdmin - new admin() + const Admin = require("./Admin").FrontblockAdmin + new Admin() }) diff --git a/src/backend/UpdateManger.ts b/src/backend/UpdateManger.ts index 67c7c86..5b9d426 100644 --- a/src/backend/UpdateManger.ts +++ b/src/backend/UpdateManger.ts @@ -3,7 +3,7 @@ import { socketioRPC } from "frontblock-generic/RPC"; import { GitUpdater, RepoFolderStatus } from "./GitUpdater"; import { FrontblockCherryPicker } from "git-cherrypicker"; import * as Logger from 'log4js' -import { FrontblockAdmin } from "./FrontblockAdmin"; +import { FrontblockAdmin } from "./Admin"; import { TableDefiniton } from "frontblock-generic/Admin"; var exec = require('child-process-promise').exec;