2020-06-22 02:44:17 +00:00
/// <reference types="@javatypes/tomcat" />
/// <reference types="@javatypes/spring-web" />
2020-06-02 10:12:37 +00:00
2020-06-20 08:40:34 +00:00
import { constants , database , plugin , web } from "@ccms/api"
2020-06-30 08:02:51 +00:00
import { inject , ContainerInstance , Container , JSClass , postConstruct } from "@ccms/container"
2020-06-17 08:11:47 +00:00
import { JSPlugin , interfaces , cmd } from "@ccms/plugin"
2020-06-02 10:12:37 +00:00
import { DataBase , DataBaseManager } from '@ccms/database'
2020-07-06 08:13:18 +00:00
import { Server , Context , RequestHandler , Controllers , Controller , Get , Post , Param , Body } from '@ccms/web'
2020-06-20 08:40:34 +00:00
2020-06-02 10:12:37 +00:00
import * as fs from '@ccms/common/dist/fs'
2020-06-17 08:11:47 +00:00
import * as reflect from '@ccms/common/dist/reflect'
2020-07-06 08:13:18 +00:00
@Controller ( )
class PluginController {
@inject ( plugin . PluginManager )
private pluginManager : plugin.PluginManager
@inject ( database . DataBaseManager )
private databaseManager : DataBaseManager
private mainDB : DataBase
@postConstruct ( )
initialize() {
this . mainDB = this . databaseManager . getMainDatabase ( )
}
@Get ( )
list ( @Param ( 'install' ) install : boolean ) {
if ( install ) {
return { status : 200 , data : [ . . . this . pluginManager . getPlugins ( ) . values ( ) ] . map ( ( plugin ) = > plugin . description ) , msg : '插件列表获取成功!' }
} else {
return { status : 200 , data : this.mainDB.query < Plugin > ( "SELECT name FROM plugins WHERE deleted = 0" ) }
}
}
@Post ( )
deploy ( @Body ( ) info : Plugin ) {
let plugin = this . mainDB . query < Plugin > ( "SELECT name FROM plugins WHERE name = ?" , info . name )
if ( plugin . length == 0 ) {
this . mainDB . update ( "INSERT INTO `plugins`(`name`, `source`) VALUES (?, ?)" , info . name , info . source )
return { status : 200 , msg : ` 插件 ${ info . name } 新增成功! ` }
} else {
this . mainDB . update ( "UPDATE `plugins` SET `source` = ? WHERE id = ?" , info . source , plugin [ 0 ] . id )
return { status : 200 , msg : ` 插件 ${ info . name } 更新成功! ` }
}
}
}
@JSPlugin ( { author : 'MiaoWoo' , servers : [ constants . ServerType . Spring ] , source : __filename } )
2020-06-02 10:12:37 +00:00
export class MiaoSpring extends interfaces . Plugin {
2020-06-17 08:11:47 +00:00
@inject ( ContainerInstance )
private container : Container
@inject ( plugin . PluginManager )
private pluginManager : plugin.PluginManager
2020-06-02 10:12:37 +00:00
@inject ( database . DataBaseManager )
private databaseManager : DataBaseManager
2020-06-20 08:40:34 +00:00
@inject ( web . Server )
private webServer : Server
2020-06-22 02:44:17 +00:00
@JSClass ( 'org.springframework.http.HttpStatus' )
private HttpStatus : org.springframework.http.HttpStatus
2020-06-20 08:40:34 +00:00
private ResponseEntity = org . springframework . http . ResponseEntity
2020-06-02 10:12:37 +00:00
private mainDatabase : DataBase
2020-06-20 08:40:34 +00:00
private mappings : Set < string >
2020-06-02 10:12:37 +00:00
@cmd ( )
2020-06-17 08:11:47 +00:00
mspring ( sender : any ) {
2020-06-02 10:12:37 +00:00
this . pluginManager . reload ( this )
this . logger . sender ( sender , "§a插件重载完成!" )
}
load() {
this . mainDatabase = this . databaseManager . getMainDatabase ( )
2020-06-20 08:40:34 +00:00
this . mappings = new Set ( )
2020-06-02 10:12:37 +00:00
}
2020-07-06 08:13:18 +00:00
@Controllers ( PluginController )
2020-06-02 10:12:37 +00:00
enable() {
this . registryDefault ( )
2020-06-17 08:11:47 +00:00
this . registryPages ( )
this . registryDatabase ( )
2020-06-02 10:12:37 +00:00
}
registryMapping ( path : string , handler : RequestHandler ) {
2020-06-20 08:40:34 +00:00
this . mappings . add ( path )
this . webServer . registryMapping ( path , handler )
2020-06-02 10:12:37 +00:00
}
registryDefault() {
2020-06-17 08:11:47 +00:00
const foundMap = [ "/node_modules/amis/sdk/sdk.js" , 'https://houtai.baidu.com/v2/jssdk' , "/node_modules/amis/sdk/sdk.css" , 'https://houtai.baidu.com/v2/csssdk' ]
2020-06-20 08:40:34 +00:00
this . webServer . registryInterceptor ( {
2020-06-17 08:11:47 +00:00
name : 'RedirectHandle' ,
preHandle : ( ctx : Context ) = > {
const index = foundMap . indexOf ( ctx . request . getRequestURI ( ) )
if ( index != - 1 ) {
2020-11-13 01:41:15 +00:00
return this . ResponseEntity . status ( org . springframework . http . HttpStatus . FOUND ) . header ( 'Location' , foundMap [ index + 1 ] ) . build ( )
2020-06-02 10:12:37 +00:00
}
2020-06-17 08:11:47 +00:00
}
} )
2020-06-20 08:40:34 +00:00
this . webServer . registryInterceptor ( {
2020-06-17 08:11:47 +00:00
name : 'StaticHandle' ,
preHandle : ( ctx : Context ) = > {
2020-06-30 08:02:51 +00:00
let type = ctx . headers [ 'Accept' ] || ''
2020-06-17 08:11:47 +00:00
if ( type == '*/*' || type . includes ( 'text/css' ) || type . includes ( 'text/html' ) ) {
let filePath = fs . concat ( root , 'wwwroot' , ( ctx . request . getRequestURI ( ) == '/' ? 'index.html' : ctx . request . getRequestURI ( ) ) )
let fileType = 'text/html;charset=utf-8'
if ( ! fs . exists ( filePath ) ) { filePath = filePath + '.html' }
if ( fs . exists ( filePath ) ) {
if ( filePath . endsWith ( '.js' ) ) { fileType = 'application/javascript' }
if ( filePath . endsWith ( '.css' ) ) { fileType = 'text/css' }
return this . ResponseEntity . ok ( ) . header ( 'Content-Type' , fileType ) . body ( base . read ( filePath ) )
2020-06-02 10:12:37 +00:00
}
}
}
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/eval' , ( ctx : Context ) = > {
2020-06-02 10:12:37 +00:00
try {
2020-06-17 08:11:47 +00:00
return { status : 200 , data : this.runCode ( ctx . body + '' ) , msg : '代码执行成功!' }
2020-06-02 10:12:37 +00:00
} catch ( error ) {
return { status : 500 , data : console.stack ( error , false ) , msg : '代码执行异常!' }
}
} )
2020-06-17 08:11:47 +00:00
}
private registryPages() {
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/page/list' , ( ) = > {
2020-06-17 08:11:47 +00:00
return { status : 0 , data : { rows : this.mainDatabase.query ( 'SELECT `id`, `type`, `name`, `content` FROM `pages` WHERE `deleted` = 0' ) } }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/page/get' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
let name = decodeURIComponent ( ` ${ ctx . params . name } ` )
let varable = undefined
if ( ! name ) { return { status : 400 , msg : '名称不能为空!' } }
if ( name . includes ( '|' ) ) {
const temp = ` ${ name } ` . split ( '|' )
name = temp [ 0 ]
varable = temp [ 1 ] . replace ( /'/ig , '"' )
}
let result = this . mainDatabase . query < any > ( 'SELECT content FROM `pages` WHERE name = ?' , name )
if ( ! result . length ) { return { status : 404 , msg : ` '页面配置 ${ name } 不存在! ` } }
let content = result [ 0 ] . content
if ( varable ) {
let varObj = JSON . parse ( varable )
for ( const key in varObj ) {
content = content . replace ( new RegExp ( ` {{ ${ key } }} ` , 'ig' ) , varObj [ key ] )
}
}
return { status : 0 , data : JSON.parse ( content ) }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/page/add' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
let body = ctx . body
if ( typeof body . content !== "string" ) { body . content = JSON . stringify ( body . content ) }
this . mainDatabase . update ( "INSERT INTO `pages`(`type`, `name`, `content`) VALUES (?, ?, ?)" , body . type || 1 , body . name , body . content )
return { status : 0 , msg : ` ${ body . name } 新增成功! ` }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/page/update' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
if ( ! ctx . params . id ) { return { status : 400 , msg : 'ID 不能为空!' } }
const body = ctx . body
if ( typeof body . content !== "string" ) { body . content = JSON . stringify ( body . content ) }
this . mainDatabase . update ( "UPDATE `pages` SET `name` = ?, `content` = ? WHERE id = ?" , body . name , body . content , ctx . params . id )
return { status : 0 , msg : ` ${ body . name } 更新成功! ` }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/page/delete' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
if ( ! ctx . params . name ) { return { status : 400 , msg : '页面 名称 不能为空!' } }
this . mainDatabase . update ( "UPDATE `pages` SET `name` = CONCAT(name, '_deleted'), deleted = 1 WHERE name = ?" , ctx . params . name )
return { status : 0 , msg : ` ${ ctx . params . name } 删除成功! ` }
} )
}
private configTable = "config"
private registryDatabase() {
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/config/list' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
return { status : 0 , data : this.mainDatabase.query ( 'SELECT id, name, label, url, driver, username, password FROM `' + this . configTable + '` WHERE deleted = 0 AND type = ?' , ctx . params . type || 0 ) }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/config/get' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
let name = ctx . params . name
if ( ! name ) { return { status : 400 , msg : '名称不能为空!' } }
let result = this . mainDatabase . query ( 'SELECT id, name, label, url, driver, username, password FROM `' + this . configTable + '` WHERE `name` = ?' , name )
if ( ! result . length ) { return { status : 404 , msg : ` 配置 ${ name } 不存在! ` } }
return { status : 0 , data : result [ 0 ] }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/config/add' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
let body = ctx . body
if ( ! body . name ) { return { status : 400 , msg : '名称不能为空!' } }
this . mainDatabase . update (
'INSERT INTO `' + this . configTable + '`(`type`, `name`, `label`, `url`, `driver`, `username`, `password`) VALUES (?, ?, ?, ?, ?, ?, ?)' ,
ctx . params . type || 0 , body . name , body . label || '' , body . url , body . driver || '' , body . username || '' , body . password || ''
)
return { status : 0 , msg : ` 配置 ${ body . name } 新增成功! ` }
} )
2020-06-30 08:02:51 +00:00
this . registryMapping ( '/api/config/update' , ( ctx : Context ) = > {
2020-06-17 08:11:47 +00:00
if ( ! ctx . params . id ) { return { status : 400 , msg : 'ID 不能为空!' } }
let body = ctx . body
this . mainDatabase . update (
'UPDATE `' + this . configTable + '` SET `name` = ?, `label` = ?, `url` = ?, `driver` = ?, `username` = ?, `password` = ? WHERE `id` = ?' ,
body . name , body . label || '' , body . url , body . driver || '' , body . username || '' , body . password || '' , ctx . params . id
)
return { status : 0 , msg : ` 配置 ${ body . name } 更新成功! ` }
} )
2020-06-02 10:12:37 +00:00
}
private runCode ( code : string ) {
2020-06-17 08:11:47 +00:00
let paramNames = [
'beanFactory' ,
'mainDatabase' ,
'reflect' ,
'container' ,
'pluginManager'
]
let params = [
2020-07-06 08:13:18 +00:00
base . getInstance ( ) . getAutowireCapableBeanFactory ( ) ,
2020-06-17 08:11:47 +00:00
this . mainDatabase ,
reflect ,
this . container ,
this . pluginManager
]
let tfunc = new Function (
. . . paramNames ,
` var api = require('@ccms/api');
return eval ( $ { JSON . stringify ( code ) } ) ; ` )
return tfunc . apply ( this , params )
2020-06-02 10:12:37 +00:00
}
disable() {
2020-06-20 08:40:34 +00:00
Object . keys ( this . mappings ) . forEach ( ( r ) = > this . webServer . unregistryMapping ( r ) )
2020-07-06 08:13:18 +00:00
this . webServer . unregistryInterceptor ( { name : 'RedirectHandle' } )
this . webServer . unregistryInterceptor ( { name : 'StaticHandle' } )
2020-06-02 10:12:37 +00:00
}
}
2020-06-30 08:02:51 +00:00
class Plugin {
id : number
name : string
source : string
}