Skip to content

Commit

Permalink
feat: config
Browse files Browse the repository at this point in the history
  • Loading branch information
simoneb committed Dec 29, 2020
1 parent 4dc0af6 commit 53eb929
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 74 deletions.
45 changes: 35 additions & 10 deletions ghenv.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ const { terminalWidth } = require('yargs')
const { hideBin } = require('yargs/helpers')

const log = require('./lib/log')
const { setup, setupLogging } = require('./lib/middleware')
const {
setup,
setupLogging,
setupConfig,
} = require('./lib/middleware')
const { view, read, write, list, explain } = require('./lib/commands')
const { NAME, pkg } = require('./lib/const')
const { tryLoadConfig } = require('./lib/util')

yargs(hideBin(process.argv))
.middleware([setupLogging, setup])
.middleware([setupLogging, setupConfig, setup])
.config(tryLoadConfig())
.option('repository', {
group: 'Options:',
group: 'Global Options:',
description:
'The name of the repository where to store the processed files. It can be a simple name, in which case the authenticated user account is assumed to be the owner, or in the form {owner}/{name}',
default: `.${NAME}`,
})
.option('pattern', {
group: 'Options:',
group: 'Global Options:',
description: 'The pattern to use to match files to include',
default: '**/.env',
})
.option('file-name', {
group: 'Options:',
group: 'Global Options:',
description:
'The name of the file to store in the repository. Defaults to the name of the package as specified in package.json',
default: pkg.name,
Expand Down Expand Up @@ -71,13 +75,13 @@ yargs(hideBin(process.argv))
)
.command(
'read',
'Reads the remote archive and writes to the local file system',
'Reads the remote archive and writes to the local file system, creating new files or overwriting existing ones',
() => {},
read
)
.command(
['list', 'ls'],
'Lists the files that will be processed',
'Lists the files that will be processed. Defaults to showing the local files',
yargs =>
yargs.option('remote', {
group: 'Command Options:',
Expand All @@ -91,8 +95,16 @@ yargs(hideBin(process.argv))
)
.command(
'view',
'View the contents of the remote archive',
() => {},
'View the contents of the files. Defaults to showing the local files',
yargs =>
yargs.option('remote', {
group: 'Command Options:',
alias: 'r',
boolean: true,
default: false,
description:
'When provided, shows the contents of the remote files instead of the local ones',
}),
view
)
.command(
Expand All @@ -101,7 +113,20 @@ yargs(hideBin(process.argv))
() => {},
explain
)
.command('debug', false, () => {}, console.log)
.command(
'debug',
false,
yargs =>
yargs.option('remote', {
group: 'Command Options:',
alias: 'r',
boolean: true,
default: false,
description:
'When provided, performs remote inizialization before outputting debug information',
}),
console.log
)
.demandCommand()
.strict()
.fail(function (msg, err, yargs) {
Expand Down
5 changes: 2 additions & 3 deletions lib/api/authentication.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ const fetch = require('node-fetch')
const open = require('open')

const log = require('../log')
const config = require('../config')
const { delay } = require('../util')
const { CLIENT_ID } = require('../const')
const { getUser } = require('./common')

async function tryUseStoredToken() {
async function tryUseStoredToken(config) {
const storedToken = config.token

if (!storedToken) {
Expand All @@ -31,7 +30,7 @@ async function tryUseStoredToken() {
}
}

async function login() {
async function login(config) {
log.debug('Authenticating')

const loginRes = await fetch(
Expand Down
92 changes: 76 additions & 16 deletions lib/commands.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict'

const fs = require('fs')

const unzipper = require('unzipper')
const glob = require('readdir-glob')

Expand All @@ -12,9 +14,19 @@ const {
decryptArchive,
} = require('./util')

async function write({ repo, token, pattern, fileName, message }) {
async function write({
repo,
token,
pattern,
fileName,
message,
config,
}) {
const archive = await createArchive(pattern)
const encryptedArchive = encryptArchive(archive)
const encryptedArchive = encryptArchive(
archive,
config.encryptionKey
)
const existingArchive = await tryGetFile(repo, fileName, token)

if (!existingArchive) {
Expand All @@ -37,8 +49,13 @@ async function write({ repo, token, pattern, fileName, message }) {
)
}

async function read({ repo, token, fileName }) {
const archive = await downloadArchive(repo, token, fileName)
async function read({ repo, token, fileName, config }) {
const archive = await downloadArchive(
repo,
token,
fileName,
config.encryptionKey
)
const zip = await unzipper.Open.buffer(archive)

log.info('Replacing local files')
Expand All @@ -49,9 +66,16 @@ async function read({ repo, token, fileName }) {
})
}

async function list({ repo, token, fileName, pattern, remote }) {
async function list({
repo,
token,
fileName,
pattern,
remote,
config,
}) {
const names = await (remote
? listRemote(repo, token, fileName)
? listRemote(repo, token, fileName, config)
: listLocal(pattern))

log(names.join('\n'))
Expand All @@ -69,27 +93,63 @@ function listLocal(pattern) {
})
}

async function listRemote(repo, token, fileName) {
const archive = await downloadArchive(repo, token, fileName)
async function listRemote(repo, token, fileName, config) {
const archive = await downloadArchive(
repo,
token,
fileName,
config.encryptionKey
)
const zip = await unzipper.Open.buffer(archive)

return zip.files.map(f => f.path)
}

async function view({ repo, token, fileName }) {
const archive = await downloadArchive(repo, token, fileName)
async function view({
repo,
token,
fileName,
config,
pattern,
remote,
}) {
return remote
? viewRemote(repo, token, fileName, config)
: viewLocal(pattern)
}

async function viewLocal(pattern) {
const files = await listLocal(pattern)

for (const file of files) {
viewHeader(file)
log(fs.readFileSync(file))
}
}

async function viewRemote(repo, token, fileName, config) {
const archive = await downloadArchive(
repo,
token,
fileName,
config.encryptionKey
)
const zip = await unzipper.Open.buffer(archive)

for (const file of zip.files) {
const l = 30 - file.path.length
const h = '-'.repeat(l / 2)

log`${h} {bold ${file.path}} ${h}`
viewHeader(file.path)
log(await file.buffer())
}
}

async function downloadArchive(repo, token, fileName) {
function viewHeader(filePath) {
const l = 30 - filePath.length
const h = '-'.repeat(l / 2)

log`${h} {bold ${filePath}} ${h}`
}

async function downloadArchive(repo, token, fileName, encryptionKey) {
log.verbose('Downloading archive')

const file = await tryGetFile(repo, fileName, token)
Expand All @@ -102,7 +162,7 @@ async function downloadArchive(repo, token, fileName) {

const encryptedArchive = Buffer.from(file.content, file.encoding)

return decryptArchive(encryptedArchive)
return decryptArchive(encryptedArchive, encryptionKey)
}

async function explain({ repo, pattern, fileName }) {
Expand Down
55 changes: 34 additions & 21 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
'use strict'

const Conf = require('conf')

const config = new Conf({
// data is stored on the local file system
// assuming this is secure enough for all practical purposes
encryptionKey: 'encryption key does not need to be secret',
})
const log = require('./log')

const ENCRYPTION_KEY = 'ENCRYPTION_KEY'
const TOKEN = 'TOKEN'

module.exports = {
get encryptionKey() {
return config.has(ENCRYPTION_KEY)
? Buffer.from(config.get(ENCRYPTION_KEY), 'hex')
: null
},
set encryptionKey(buffer) {
config.set(ENCRYPTION_KEY, buffer.toString('hex'))
},
get token() {
return config.get(TOKEN)
},
set token(value) {
config.set(TOKEN, value)
},
function createConfig(repository) {
log.verbose(`Initializing config for repository ${repository}`)

const userConfig = new Conf({
configName: 'user',
// data is stored on the local file system
// assuming this is secure enough for all practical purposes
encryptionKey: `user encryption key`,
})

const repositoryConfig = new Conf({
configName: repository,
encryptionKey: `repository ${repository} encryption key`,
})

return {
get encryptionKey() {
return repositoryConfig.has(ENCRYPTION_KEY)
? Buffer.from(repositoryConfig.get(ENCRYPTION_KEY), 'hex')
: null
},
set encryptionKey(buffer) {
repositoryConfig.set(ENCRYPTION_KEY, buffer.toString('hex'))
},
get token() {
return userConfig.get(TOKEN)
},
set token(value) {
userConfig.set(TOKEN, value)
},
}
}

module.exports = createConfig
12 changes: 10 additions & 2 deletions lib/middleware/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
'use strict'

const log = require('../log')
const createConfig = require('../config')
const { setup } = require('./setup')

function setupLogging(argv) {
log.setLevel(argv.verbose)
function setupLogging(yargs) {
log.setLevel(yargs.verbose)
}

function setupConfig({ repository }) {
return {
config: createConfig(repository),
}
}

module.exports = {
setup,
setupLogging,
setupConfig,
}
6 changes: 3 additions & 3 deletions lib/middleware/setup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ async function setup(yargs) {
return
}

const storedToken = await tryUseStoredToken()
const token = storedToken || (await login())
const storedToken = await tryUseStoredToken(yargs.config)
const token = storedToken || (await login(yargs.config))

const user = await getUser(token.access_token)

Expand All @@ -36,7 +36,7 @@ async function setup(yargs) {

await setupRepo(repo, token, yargs)

return { repo, token }
return { repo, token, user }
}

module.exports = { setup }
Loading

0 comments on commit 53eb929

Please sign in to comment.