Implement admin file manager, lots of cleanups
This commit is contained in:
parent
bc5b2ccc5d
commit
48ad2e4fb7
12
.cloudcmd.menu.js
Normal file
12
.cloudcmd.menu.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
'G - Commit all changes and re-run Hugo': async({ CloudCmd }) => {
|
||||
const response = await fetch('/commit')
|
||||
const responseJSON = await response.json()
|
||||
|
||||
if (responseJSON.ok) {
|
||||
window.location.href = '/'
|
||||
} else {
|
||||
console.error(responseJSON.error)
|
||||
}
|
||||
}
|
||||
}
|
BIN
.sandstorm/app-graphics/admin_interface.png
Normal file
BIN
.sandstorm/app-graphics/admin_interface.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
BIN
.sandstorm/app-graphics/site_setup.png
Normal file
BIN
.sandstorm/app-graphics/site_setup.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 119 KiB |
@ -1,3 +1,8 @@
|
||||
# V0.69.0~2020-04-14
|
||||
|
||||
* Upgrade Hugo.
|
||||
* Replace Caddy with Cloud Commander for admin file management.
|
||||
|
||||
# V0.20-sandstorm2
|
||||
|
||||
* Upgrade Hugo.
|
||||
|
@ -22,4 +22,7 @@ fi
|
||||
cd /opt/app
|
||||
cp post-receive /var/git/.git/hooks
|
||||
|
||||
# cloudcmd wants this in your home directory
|
||||
ln -sf /opt/app/.cloudcmd.menu.js /var/.cloudcmd.menu.js
|
||||
|
||||
npm start
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
appVersion = 4, # Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "0.69.0-sandstorm"),
|
||||
appMarketingVersion = (defaultText = "0.69.0~2020-04-14"),
|
||||
# Human-readable representation of appVersion. Should match the way you
|
||||
# identify versions of your app in documentation and marketing.
|
||||
|
||||
@ -123,8 +123,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
# Screenshots to use for marketing purposes. Examples below.
|
||||
# Sizes are given in device-independent pixels, so if you took these
|
||||
# screenshots on a Retina-style high DPI screen, divide each dimension by two.
|
||||
(width = 1366, height = 672, png = embed "app-graphics/screenshot1.png"),
|
||||
(width = 1366, height = 672, png = embed "app-graphics/screenshot2.png"),
|
||||
(width = 758, height = 718, png = embed "app-graphics/site_setup.png"),
|
||||
(width = 761, height = 861, png = embed "app-graphics/admin_interface.png"),
|
||||
],
|
||||
changeLog = (defaultText = embed "changelog.md"),
|
||||
# Documents the history of changes in Github-flavored markdown format (with the same restrictions
|
||||
@ -143,7 +143,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
( sourcePath = "/", # Then search the system root directory.
|
||||
hidePaths = [ "home", "proc", "sys",
|
||||
"etc/hosts", "etc/host.conf",
|
||||
"etc/passwd", "etc/nsswitch.conf", "etc/resolv.conf" ]
|
||||
"etc/passwd", "etc/nsswitch.conf", "etc/resolv.conf",
|
||||
"opt/app/.git"]
|
||||
# You probably don't want the app pulling files from these places,
|
||||
# so we hide them. Note that /dev, /var, and /tmp are implicitly
|
||||
# hidden because Sandstorm itself provides them.
|
||||
@ -245,6 +246,7 @@ const myCommand :Spk.Manifest.Command = (
|
||||
(key = "SANDSTORM", value = "1"),
|
||||
(key = "HOME", value = "/var"),
|
||||
(key = "NODE_ENV", value = "production"),
|
||||
(key = "THREAD_IT_COUNT", value = "0"),
|
||||
# Export SANDSTORM=1 into the environment, so that apps running within Sandstorm
|
||||
# can detect if $SANDSTORM="1" at runtime, switching UI and/or backend to use
|
||||
# the app's Sandstorm-specific integration code.
|
||||
|
29
CHANGELOG.md
29
CHANGELOG.md
@ -1,27 +1,12 @@
|
||||
## V0 (2016-10-10)
|
||||
|
||||
* Initial release.
|
||||
|
||||
## 0.69.0 (2020-04-10)
|
||||
|
||||
The "I can't stand Hugo 0.20.something anymore" release.
|
||||
## 0.69.0 (2020-04-14)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* Upgrade Hugo to 0.69.0
|
||||
* Remove Caddy & admin interface for now
|
||||
* This never quite worked right for me and direct support for
|
||||
Hugo management was [dropped during Caddy 2 development](https://caddy.community/t/new-old-plugin-http-filebrowser/5103).
|
||||
Bringing back Caddy would require a bit more work than I'm able to put into
|
||||
it for this release.
|
||||
* Update NodeJS to 10 and `yarn upgrade` all transitive dependencies
|
||||
* Upgrade Hugo to 0.69.0.
|
||||
* Replace Caddy with [Cloud Commander](https://cloudcmd.io/) for
|
||||
web-based file management.
|
||||
* Update NodeJS to 10 and `yarn upgrade` all transitive dependencies.
|
||||
|
||||
### Workarounds
|
||||
## V0 (2016-10-10)
|
||||
|
||||
* For some reason the `getPublicId` script causes some part of Cap'n Proto to
|
||||
crash the grain when executed, specifically as the script is exiting.
|
||||
I've tried everything I know to have it not do that, but ended up with a
|
||||
terrible workaround: capture the stdout of the script to a file as it
|
||||
executes and memoize the output based on the session ID parameter.
|
||||
For my single-person Sandstorm server, this seems fine. I would love help
|
||||
figuring this out.
|
||||
* Initial release.
|
||||
|
@ -21,4 +21,22 @@
|
||||
td {
|
||||
padding: 0 10 0 10;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 0.5rem;
|
||||
border: solid #aaa 1px;
|
||||
background-color: #eee;
|
||||
color: #000;
|
||||
border-radius: 3px;
|
||||
margin: 0 1rem;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button.disabled {
|
||||
color: #555;
|
||||
background-color: #aaa;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
|
@ -12,10 +12,11 @@
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"express": "^4.15.2",
|
||||
"git-http-backend": "^1.0.1",
|
||||
"http-proxy": "^1.15.1",
|
||||
"isomorphic-fetch": "^2.2.1",
|
||||
"morgan": "^1.8.1",
|
||||
"nuxt": "^0.10.6"
|
||||
"nuxt": "^0.10.6",
|
||||
"cloudcmd": "^14.3.10",
|
||||
"socket.io": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^1.11.0"
|
||||
|
@ -57,12 +57,25 @@
|
||||
<render-template
|
||||
rpcId="gitPush"
|
||||
:template="'git remote add origin ' + this.gitUrl + '\ngit push -fu origin master'"/>
|
||||
<h2>Admin Interface</h2>
|
||||
<h2>Upgrade notes from the 0.20 Sandstorm release:</h2>
|
||||
<ul>
|
||||
<li>
|
||||
If you were using inline HTML in any Markdown files, enter the following into
|
||||
your <code>config.toml</code> file:
|
||||
<pre>
|
||||
[markup.goldmark.renderer]
|
||||
unsafe= true
|
||||
</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
...had to be removed temporarily because Caddy 1 isn't recommended anymore and
|
||||
<a target="_blank" rel="noopener" href="https://caddy.community/t/new-old-plugin-http-filebrowser/5103">Caddy 2 needs some work to get working well with Hugo</a>.
|
||||
<a target="_blank" rel="noopener" href="https://github.com/johnbintz/hugo-sandstorm">Want to help?</a>
|
||||
Be sure to <a href="https://gohugo.io/news/">read through the Hugo release notes</a>
|
||||
if you notice any other odd behavior after upgrading.
|
||||
</p>
|
||||
<h2>Admin Interface (<a href="https://cloudcmd.io/">Cloud Commander</a>)</h2>
|
||||
<a :class="{disabled: !dirty}" class="button" @click="commitLocal">Commit & publish local changes</a>
|
||||
<a :class="{disabled: !dirty}" class="button" @click="deleteLocal">Delete local changes (git reset --hard)</a>
|
||||
<iframe id="files" src="/admin" style="width: 100%; height: 800px; margin-top: 1rem"></iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -77,7 +90,8 @@
|
||||
domain: "",
|
||||
publicId: "",
|
||||
isLoading: true,
|
||||
loadError: null
|
||||
loadError: null,
|
||||
dirty: false
|
||||
}),
|
||||
computed: {
|
||||
gitHost: () => {
|
||||
@ -112,10 +126,38 @@
|
||||
} finally {
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
setInterval(this.checkDirty, 5000)
|
||||
},
|
||||
head: {
|
||||
title: "Home"
|
||||
},
|
||||
methods: {
|
||||
async commitLocal () {
|
||||
if (!this.dirty) return
|
||||
|
||||
if (confirm('Are you sure?')) {
|
||||
await fetch('/commit')
|
||||
}
|
||||
},
|
||||
async deleteLocal () {
|
||||
if (!this.dirty) return
|
||||
|
||||
if (confirm('Are you sure?')) {
|
||||
await fetch('/reset-local')
|
||||
|
||||
document.getElementById('files').contentWindow.location.reload(true)
|
||||
}
|
||||
},
|
||||
async checkDirty () {
|
||||
const response = await fetch('/dirty')
|
||||
const json = await response.json()
|
||||
|
||||
if (json.hasOwnProperty('dirty')) {
|
||||
this.dirty = json.dirty
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {RenderTemplate}
|
||||
}
|
||||
|
||||
|
111
server.js
111
server.js
@ -3,9 +3,8 @@ import logger from "morgan"
|
||||
import fs from 'fs'
|
||||
import Express from "express"
|
||||
import gitBackend from "git-http-backend"
|
||||
// TODO: once Caddy 2 or something similar is in place, reinstate the
|
||||
// admin proxy.
|
||||
//import httpProxy from "http-proxy"
|
||||
import cloudcmd from "cloudcmd"
|
||||
import io from 'socket.io'
|
||||
const spawn = require("child_process").spawn
|
||||
|
||||
const app = new Express()
|
||||
@ -78,12 +77,108 @@ app.use("/git", (req, res) => {
|
||||
})).pipe(res)
|
||||
})
|
||||
|
||||
//const proxy = httpProxy.createProxyServer({
|
||||
// target: "http://127.0.0.1:8001/admin/",
|
||||
// changeOrigin: true
|
||||
//})
|
||||
const runCommand = (cmd, ...args) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawnCmd = spawn(cmd, args)
|
||||
|
||||
// app.use("/admin/", (req, res) => proxy.web(req, res))
|
||||
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
|
||||
}))
|
||||
|
||||
// Import and Set Nuxt.js options
|
||||
let config = require("./nuxt.config.js")
|
||||
|
Loading…
Reference in New Issue
Block a user