feat: auto download admin (#1005

* feat: auto download admin

Signed-off-by: Innei <tukon479@gmail.com>

* fix: update

Signed-off-by: Innei <tukon479@gmail.com>

* fix: update

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
2023-03-08 11:40:42 +08:00
committed by GitHub
parent 050030dfdb
commit f57b23e515
4 changed files with 89 additions and 5 deletions

View File

@@ -5,6 +5,7 @@ import { isNull } from 'lodash'
import { lookup } from 'mime-types'
import PKG from 'package.json'
import { extname, join } from 'path'
import { Observable } from 'rxjs'
import {
Controller,
@@ -24,6 +25,7 @@ import { CacheService } from '~/processors/redis/cache.service'
import { getRedisKey } from '~/utils/redis.util'
import { dashboard } from '../../../package.json'
import { UpdateService } from '../update/update.service'
import { PageProxyDebugDto } from './pageproxy.dto'
import { PageProxyService } from './pageproxy.service'
@@ -33,6 +35,7 @@ export class PageProxyController {
constructor(
private readonly cacheService: CacheService,
private readonly service: PageProxyService,
private readonly updateService: UpdateService,
) {}
@Get('/qaqdmin')
@@ -150,21 +153,97 @@ export class PageProxyController {
return reply.type('text/html').send(entry)
}
private fetchObserver$: Observable<string> | null
private fetchLogs: string[] | null
private fetchErrorMsg: string | null
@Get('/proxy/qaqdmin')
@HTTPDecorators.Bypass
async getLocalBundledAdmin(@Res() reply: FastifyReply) {
async getLocalBundledAdmin(@Query() query: any, @Res() reply: FastifyReply) {
if ((await this.service.checkCanAccessAdminProxy()) === false) {
return reply.type('application/json').status(403).send({
message: 'admin proxy not enabled',
})
}
if (this.fetchObserver$ && query.log) {
if (this.fetchLogs === null) {
return reply.code(204)
}
const log = this.fetchLogs.pop() || '...'
reply.code(200).type('text/html').send(`${log}`)
return
}
if (query.log) {
if (this.fetchErrorMsg) {
reply.code(403).type('text/html').send(this.fetchErrorMsg)
this.fetchErrorMsg = null
} else {
reply.code(200).type('text/html').send('...')
}
return
}
const entryPath = path.join(LOCAL_ADMIN_ASSET_PATH, 'index.html')
const isAssetPathIsExist = existsSync(entryPath)
if (!isAssetPathIsExist) {
this.fetchLogs = []
reply.code(404).type('text/html')
.send(`<p>Local Admin Assets is not found. Navigator to page proxy in 3 second. </p><script>setTimeout(() => {
location.href = '/qaqdmin'
}, 3000);</script>`)
.send(`<script src="https://cdn.jsdelivr.net/npm/ansi_up@4.0.3/ansi_up.js"></script>
<p>Local Admin Assets is not found. Downloading start... </p>
<p>If finished download but page not reload or logs are not output for a period of time, please reload page manually. </p>
<pre id="block"></pre>
<script>
var txt = '';
var lastLine = ''
var ansi_up = new AnsiUp();
var cdiv = document.getElementById("block");
var timer = setInterval(function() {
fetch('?log=1')
.catch(() => {
clearInterval(timer)
})
.then(res => {
if(res.status === 204) {
clearInterval(timer)
window.location.reload()
return
}
return res
})
.then(res => res.text()).then(text => {
if(!text) window.location.reload()
if(lastLine === text) return
txt += text + '\\n'
lastLine = text
var html = ansi_up.ansi_to_html(txt);
cdiv.innerHTML = html;
})
}, 1000)
</script>`)
this.fetchObserver$ = this.updateService.downloadAdminAsset(
await this.updateService.getLatestAdminVersion().catch((err) => {
this.fetchErrorMsg = err.message
throw err
}),
)
const cleanup = () => {
this.fetchObserver$ = null
this.fetchLogs = null
}
this.fetchObserver$.subscribe({
next: (value) => {
this.fetchLogs?.push(value)
},
error: cleanup,
complete: cleanup,
})
return
}
try {

View File

@@ -1,10 +1,12 @@
import { Module } from '@nestjs/common'
import { UpdateModule } from '../update/update.module'
import { PageProxyController } from './pageproxy.controller'
import { PageProxyService } from './pageproxy.service'
@Module({
controllers: [PageProxyController],
providers: [PageProxyService],
imports: [UpdateModule],
})
export class PageProxyModule {}

View File

@@ -6,5 +6,6 @@ import { UpdateService } from './update.service'
@Module({
controllers: [UpdateController],
providers: [UpdateService],
exports: [UpdateService],
})
export class UpdateModule {}

View File

@@ -31,6 +31,8 @@ export class UpdateService {
})
if (!json) {
subscriber.next(chalk.red('Fetching error, json is empty. \n'))
subscriber.complete()
return
}
@@ -130,7 +132,7 @@ export class UpdateService {
return res.data.tag_name.replace(/^v/, '')
}
runShellCommandPipeOutput(
private runShellCommandPipeOutput(
command: string,
args: any[],
subscriber: Subscriber<string>,