2017-03-19 17:04:38 +00:00
|
|
|
import Nuxt from "nuxt"
|
|
|
|
import logger from "morgan"
|
2020-04-10 11:29:40 +00:00
|
|
|
import fs from 'fs'
|
2017-03-19 17:04:38 +00:00
|
|
|
import Express from "express"
|
|
|
|
import gitBackend from "git-http-backend"
|
2020-04-15 02:19:34 +00:00
|
|
|
import cloudcmd from "cloudcmd"
|
|
|
|
import io from 'socket.io'
|
2017-03-19 17:04:38 +00:00
|
|
|
const spawn = require("child_process").spawn
|
|
|
|
|
|
|
|
const app = new Express()
|
|
|
|
|
|
|
|
app.use(logger("dev"))
|
|
|
|
const server = require("http").createServer(app)
|
|
|
|
const host = process.env.HOST || "127.0.0.1"
|
|
|
|
const port = process.env.PORT || "8000"
|
|
|
|
|
|
|
|
app.set("port", port)
|
|
|
|
|
|
|
|
app.get("/publicId", (req, res) => {
|
2020-04-21 11:23:40 +00:00
|
|
|
// For those reusing getPublicId, keep in mind that the session ID from the
|
|
|
|
// headers isn't used to generate the address for a grain, only the grain's
|
|
|
|
// internal ID. Once you've generated it once, that's it.
|
|
|
|
//
|
|
|
|
// See https://github.com/sandstorm-io/sandstorm/blob/1a1f5650472904e137393af077a3d90f094cd888/shell/imports/server/hack-session.js#L334-L365
|
|
|
|
// for more information.
|
2017-03-19 17:04:38 +00:00
|
|
|
const sessionId = req.headers["x-sandstorm-session-id"]
|
2020-04-10 11:29:40 +00:00
|
|
|
let allData = ""
|
2020-04-21 11:23:40 +00:00
|
|
|
// TODO: needed until https://github.com/sandstorm-io/sandstorm/pull/3292 is merged
|
|
|
|
//
|
|
|
|
// If this app is running in demo mode, its data will be thrown away in an hour,
|
|
|
|
// and the public ID assigned to the grain will also go away, so it's still OK
|
|
|
|
// to keep this file around, even in a demo scenario.
|
|
|
|
const file = `/var/publicid`
|
2020-04-10 11:29:40 +00:00
|
|
|
|
|
|
|
const handleResult = () => {
|
|
|
|
const lines = allData.split("\n")
|
2017-03-19 17:04:38 +00:00
|
|
|
const publicId = lines[0]
|
|
|
|
const hostname = lines[1]
|
|
|
|
const domain = publicId+"."+hostname
|
|
|
|
const url = lines[2]
|
|
|
|
const isDemo = lines[3] == "true"
|
|
|
|
res.json({publicId, hostname, domain, url, isDemo})
|
2020-04-10 11:29:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
allData = fs.readFileSync(file, 'utf8').toString()
|
|
|
|
} catch (e) {
|
2020-04-21 11:23:40 +00:00
|
|
|
// file probably doesn't exist
|
2020-04-10 11:29:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const lines = allData.split("\n")
|
|
|
|
if (lines.length >= 4) {
|
|
|
|
handleResult()
|
|
|
|
} else {
|
|
|
|
const gpId = spawn('getPublicId', [sessionId])
|
|
|
|
allData = ""
|
|
|
|
|
|
|
|
gpId.stdout.on('data', (data) => {
|
|
|
|
fs.appendFileSync(file, data)
|
|
|
|
allData += data
|
|
|
|
})
|
|
|
|
|
|
|
|
gpId.on('error', (err) => {
|
|
|
|
return res.send(err)
|
|
|
|
})
|
|
|
|
|
|
|
|
gpId.on('close', (code) => {
|
|
|
|
if (code !== 0) {
|
|
|
|
return res.send(code)
|
|
|
|
}
|
|
|
|
|
|
|
|
handleResult()
|
|
|
|
})
|
|
|
|
}
|
2017-03-19 17:04:38 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
app.use("/git", (req, res) => {
|
|
|
|
req.pipe(gitBackend(req.url, (err, service) => {
|
|
|
|
if(err)
|
|
|
|
return res.end(err+"\n")
|
|
|
|
res.setHeader("content-type", service.type)
|
|
|
|
console.log("cmd", service.cmd)
|
|
|
|
const ps = spawn(service.cmd, service.args.concat("/var/git"))
|
|
|
|
ps.stdout.pipe(service.createStream()).pipe(ps.stdin)
|
|
|
|
})).pipe(res)
|
|
|
|
})
|
|
|
|
|
2020-04-15 02:19:34 +00:00
|
|
|
const runCommand = (cmd, ...args) => {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const spawnCmd = spawn(cmd, args)
|
2017-03-19 17:04:38 +00:00
|
|
|
|
2020-04-15 02:19:34 +00:00
|
|
|
spawnCmd.stdout.on('data', (data) => {
|
|
|
|
console.log(data.toString())
|
|
|
|
})
|
|
|
|
|
|
|
|
spawnCmd.on('error', (err) => {
|
|
|
|
res.send(err)
|
|
|
|
|
|
|
|
reject(err)
|
|
|
|
})
|
|
|
|
|
|
|
|
spawnCmd.on('close', (code) => {
|
|
|
|
if (code === 0) {
|
|
|
|
resolve(true)
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
reject(new Error(code))
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
app.get('/dirty', async (req, res) => {
|
|
|
|
const currentDir = process.cwd()
|
|
|
|
|
|
|
|
process.chdir('/var/git')
|
|
|
|
|
|
|
|
const spawnCmd = spawn('git', ['diff', '--exit-code'])
|
|
|
|
|
|
|
|
spawnCmd.on('close', (code) => {
|
|
|
|
res.json({ dirty: code !== 0 })
|
|
|
|
})
|
|
|
|
|
|
|
|
process.chdir(currentDir)
|
|
|
|
})
|
|
|
|
|
|
|
|
app.use('/commit', async (req, res) => {
|
|
|
|
const currentDir = process.cwd()
|
|
|
|
|
|
|
|
try {
|
|
|
|
process.chdir('/var/git')
|
|
|
|
await runCommand('git', 'add', '.')
|
|
|
|
await runCommand('git', 'commit', '-m', 'From admin')
|
|
|
|
process.chdir(currentDir)
|
|
|
|
await runCommand('/opt/app/post-receive')
|
|
|
|
|
|
|
|
res.json({ok: true})
|
|
|
|
} catch (e) {
|
|
|
|
res.send({error: e.msg})
|
|
|
|
} finally {
|
|
|
|
process.chdir(currentDir)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
app.use('/reset-local', async (req, res) => {
|
|
|
|
const currentDir = process.cwd()
|
|
|
|
|
|
|
|
try {
|
|
|
|
process.chdir('/var/git')
|
|
|
|
await runCommand('git', 'reset', '--hard')
|
|
|
|
process.chdir(currentDir)
|
|
|
|
|
|
|
|
res.json({ok: true})
|
|
|
|
} catch (e) {
|
|
|
|
res.send({error: e.msg})
|
|
|
|
} finally {
|
|
|
|
process.chdir(currentDir)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
const { createConfigManager, configPath } = cloudcmd
|
|
|
|
|
|
|
|
const socket = io.listen(server, { path: "/admin/socket.io"})
|
|
|
|
|
|
|
|
const cloudConfig = {
|
|
|
|
name: "Hugo admin",
|
|
|
|
root: "/var/git",
|
|
|
|
open: false,
|
|
|
|
prefix: "/admin",
|
|
|
|
console: false,
|
|
|
|
terminal: false,
|
|
|
|
oneFilePanel: true,
|
|
|
|
configDialog: false,
|
|
|
|
configAuth: false,
|
|
|
|
keysPanel: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
const filePicker = {
|
|
|
|
data: { FilePicker: { key: 'key' } }
|
|
|
|
}
|
|
|
|
|
|
|
|
const cloudModules = { filePicker }
|
|
|
|
|
|
|
|
const configManager = createConfigManager({ configPath })
|
|
|
|
|
|
|
|
app.use("/admin", cloudcmd({
|
|
|
|
socket,
|
|
|
|
config: cloudConfig
|
|
|
|
}))
|
2017-03-19 17:04:38 +00:00
|
|
|
|
|
|
|
// Import and Set Nuxt.js options
|
|
|
|
let config = require("./nuxt.config.js")
|
|
|
|
config.dev = !(process.env.NODE_ENV === "production")
|
|
|
|
|
|
|
|
// Init Nuxt.js
|
|
|
|
const nuxt = new Nuxt(config)
|
|
|
|
app.use(nuxt.render)
|
|
|
|
|
|
|
|
// Build only in dev mode
|
|
|
|
if (config.dev) {
|
|
|
|
nuxt.build()
|
|
|
|
.catch((error) => {
|
|
|
|
console.error(error) // eslint-disable-line no-console
|
|
|
|
process.exit(1)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
server.listen(port, host, () => console.log(`Server listening on ${host}:${port}`))
|