Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
chee committed Dec 22, 2018
0 parents commit 0d3a80e
Show file tree
Hide file tree
Showing 16 changed files with 2,809 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .editorconfig
@@ -0,0 +1,13 @@
# http://editorconfig.org
root = true

[*]
indent_style = tab
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
3 changes: 3 additions & 0 deletions .gitignore
@@ -0,0 +1,3 @@
/.vscode/
/node_modules/
/test/
693 changes: 693 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions README.md
@@ -0,0 +1,7 @@
# Create snoot - the snoot maintenance module

This is the module used on the [snoot.club](https://snoot.club) server for creating new snoots.

It's specific to the setup of that server and would need changes in order to be useful to anyone else, but the code is here should anyone ever want to look at it or reuse any of the code.

It would be nice to make the non-specific parts of it work without running in that environment, so one could have a local snoot setup, but that's not the focus right now.
161 changes: 161 additions & 0 deletions commands/create-snoot.js
@@ -0,0 +1,161 @@
#!/usr/bin/env -S sudo node
let inquirer = require("inquirer")
let fetch = require("make-fetch-happen").defaults({
cacheManager: "./.snootclub/fetch-cache"
})
let {log, warn, shout} = require("../library/loggo.js")
let unix = require("../library/unix.js")
let snoots = require("../library/snoots.js")
let shell = require("../library/shell.js")

process.on("unhandledRejection", error => {
console.log(error)
process.exit(122)
})

process.on("uncaughtException", error => {
console.log(error)
process.exit(222)
})

function getKeysFromGithub (githubUsername) {
log("gonna get them an authorized_keys file from github")

return fetch(`https://github.com/${githubUsername}.keys`)
.then(response => response.text())
}

module.exports = async function createSnoot () {
let hasPrivilege = unix.checkYourPrivilege()

if (!hasPrivilege) {
shout("oh no: not root")
log("this program needs to be run as root, because it does different things as different snoots")
process.exit(22)
// log("this program needs elevated privileges, so i'll ask you for your password for sudo sometimes")
}

let {
snoot
} = await inquirer.prompt([
{
type: "input",
name: "snoot",
message: "oh, a new snoot? 💕 \nwhat's their name?",
default: "abe",
validate: snoots.validateName
},
{
type: "list",
choices: ["yes", "yes"],
name: "isAGoodBoy",
message: "a good boy? 💖💛",
when: ({snoot}) => snoot == "abe"
}
])

let snootAlreadyExists = await snoots.checkExists(snoot)

let {shouldContinue = true} = await inquirer.prompt({
type: "confirm",
name: "shouldContinue",
message: "🎺 whümf and wetch? this snoot already exists, should we continue?",
when: () => snootAlreadyExists,
default: true
})

if (!shouldContinue) {
shout("cancelling for there already existed such a snoot")
process.exit(2)
}

// let existingKeys = snootAlreadyExists && (
// (await snoots.getConfig(snoot)).authorizedKeys
// )

let {
githubUsername
} = await inquirer.prompt([
// {
// type: "confirm",
// name: useExistingKeys,
// message: "do you want to use the existing authorized_keys file they had?",
// when: () => existingKeys
// },
// {
// type: "confirm",
// name: getGithubKeys,
// message: "do you want to get keys from github?"
// },
{
type: "input",
name: "githubUsername",
message: "what is their github username? 🐙😻",
default: "chee",
// when: ({getGithubKeys}) => getGithubKeys
}
])

let githubKeys = githubUsername
? await getKeysFromGithub(githubUsername)
: ""

let {
authorizedKeys
} = await inquirer.prompt({
type: "editor",
name: "authorizedKeys",
message: "edit their authorized_keys ✏️🔑",
default: githubKeys
// .concat(useExistingKeys ? existingKeys : "")
})

if (await unix.checkUserExists(snoot)) {
warn(`there's already a user called "${snoot}"!! i hope that's ok! ♥`)
} else {
log("ok! creating them a unix user 👤 account on the computer 🖥 ⌨️ 🖱")
await snoots
.createUnixAccount(snoot)
.catch(error => {
shout("couldnt create user!")
shout(error.toString())
warn("creating them a directory 📂 📁 in /snoots as a backup 🦴")
return unix.mkdir(snoots.chrootResolver(snoot).path)
})
}

log("adding their authorized_keys ➕🔑 file so they can log in (:")
await snoots.createChrootSshConfiguration(snoot, {authorizedKeys})

log("generating their base application files! 📠 🎰")
let {
sshPort,
webPort
} = await snoots.getPorts(snoot)

if (!snootAlreadyExists) {
await snoots.createBaseApplication(snoot, {
authorizedKeys,
sshPort,
webPort
})

log("updating next snoot port 🌸")
await snoots.setNextPort(webPort + 1)
}

log("binding snoots 👀")
await snoots.bind(snoot)

log("booting snoot container 👢")
await snoots.bootContainer(snoot)

log("restarting nginx 🔂")
await shell.run("nginx -s reload")
}

let beingRunDirectly = process.argv[1].endsWith("create-snoot.js")

if (beingRunDirectly) {
module.exports()
}
1 change: 1 addition & 0 deletions commands/enter-snoot.js
@@ -0,0 +1 @@
module.exports = console.log
1 change: 1 addition & 0 deletions commands/get.js
@@ -0,0 +1 @@
module.exports = console.log
34 changes: 34 additions & 0 deletions index.js
@@ -0,0 +1,34 @@
#!/usr/bin/env -S sudo node
let yargs = require("yargs")
let createSnoot = require("./commands/create-snoot.js")
let enterSnoot = require("./commands/enter-snoot.js")
let stopSnoot = require("./commands/stop-snoot.js")
let get = require("./commands/get.js")

let positionalSnoot = yargs =>
yargs.positional("snoot", {
describe: "the name of the snoot you'd like to enter"
})

let arguments = yargs
.command(["create", "new"], "create a new snoot", () => {}, createSnoot)
.command(
"enter <snoot>",
"enter a snoot's container",
positionalSnoot,
enterSnoot
)
.command("get <snoot> <key>", "get snoot data", yargs => {
positionalSnoot(yargs)
.positional("key", {
describe: "the key for the data you'd like to see"
})
}, get)
.command(
"stop <snoot>",
"stop a snoot's container",
positionalSnoot,
stopSnoot
)
.demandCommand()
.argv
23 changes: 23 additions & 0 deletions library/create-path-resolver.js
@@ -0,0 +1,23 @@
let path = require("path")

module.exports = function createPathResolver (directory) {
function resolver (...files) {
let filepath = path.resolve(directory, ...files)
if (files.length) {
return createPathResolver(filepath)
}
return filepath
}

resolver.toString = function () {
return path.resolve(directory)
}

Object.defineProperty(resolver, "path", {
get () {
return this.toString()
}
})

return resolver
}
16 changes: 16 additions & 0 deletions library/loggo.js
@@ -0,0 +1,16 @@
let chalk = require("chalk")

exports.log = message => (
console.log(chalk.cyan.bold(message)),
message
)

exports.warn = message => (
console.warn(chalk.yellow(message)),
message
)

exports.shout = message => (
console.error(chalk.red.bold(message)),
message
)
41 changes: 41 additions & 0 deletions library/shell.js
@@ -0,0 +1,41 @@
let sudoSpawn = require("sudo")
let spawn = require("child_process").spawn

exports.run = function run (command, options = {}) {
let {
sudoPrompt = "could i get your password for sudo pls?",
sudo = false,
cwd,
env
} = options

let spawnOptions = {
cwd,
env
}

let sudoSpawnOptions = {
cachePassword: true,
prompt: sudoPrompt,
spawnOptions
}

let [name, ...args] = typeof command == "string"
? command.split(/\s+/)
: command

let child = sudo
? sudoSpawn([name, ...args], sudoSpawnOptions)
: spawn(name, args, spawnOptions)

let promise = new Promise(resolve => {
child.on("close", code => resolve(code))
})

promise.stdout = child.stdout
promise.stderr = child.stderr
promise.stdin = child.stdin
promise.stdio = child.stdio

return promise
}

0 comments on commit 0d3a80e

Please sign in to comment.