mirror of
https://github.com/clinicjs/node-clinic.git
synced 2026-01-18 16:22:03 +00:00
* clinic ask (#66) The `ask` command is used to upload on the private area, e.g.: ``` clinic ask --upload-url=http://localhost:3000 11213.clinic-bubbleprof ``` This will: - Start the authentication on upload server to obtain a JWT token - Upload the data to the protected API `/protected/data` on upload server On the server side, the API can extract the user email from the JWT token to correctly identify the "private" folder for the user * Authenticate for public uploads and support private uploads without `ask`ing (#102) `clinic upload xyz.clinic-doctor` now also requires authentication. A new `clinic upload --private` flag uploads to your private area. `clinic ask` does `clinic upload --private` and then calls a currently-noop function that can be implemented once we have a `/ask` endpoint on the server. * Store auth tokens in ~/.node-clinic-rc (#108) Stores the JWT in ~/.node-clinic-rc after logging in. ~/.node-clinic-rc is a JSON file with upload URLs as keys, JWTs as values. Use `clinic login` to login manually. Optionally specify an `--upload-url`. Use `clinic logout` to logout manually. Optionally specify an `--upload-url`. Add `--all` to log out of all Clinic Upload servers, this deletes the ~/.node-clinic-rc file. Use `clinic user` to show a list of current sessions. Optionally specify an `--upload-url` to only show that session. You can use the `CLINIC_CREDENTIALS` environment variable to point to a different file. I added this for tests, maybe it's also useful in programmatic environments and warrants docs? `clinic upload` and `clinic ask` automatically do what `clinic login` does at the start. * Feature/ask auth flag (#114) * [666] - Add ask param flag to login URL when authenticating using ask command * [666] - Factor user terms acceptance into CLI login when validating JWT payload against upload type * Implement ask with placeholder message (#115) Means we'll have to reply first to figure out what someone needs help with but it's better than not getting a message at all * 3.0.0-beta.0@next * Fix/private public auth redirect (#116) * Re #99 - Pass flag for private uploads to login URL so app can differentiate intent * Re #97 - Open new tab on upload callback and create flag to prevent this behaviour if desired * Re #97 - Update browser open flag to use recommended minimist syntax * Revert "Disable clinic upload in old CLI. (#117)" This reverts commit 75f80771b4741a4927788a2d492566d04416e1b7. * Update tool versions. * remove weird test? unsure what this was for
140 lines
3.6 KiB
JavaScript
140 lines
3.6 KiB
JavaScript
'use strict'
|
|
|
|
const http = require('http')
|
|
const test = require('tap').test
|
|
const websocket = require('websocket-stream')
|
|
const proxyquire = require('proxyquire')
|
|
let server, cliToken
|
|
let simulateTimeout = false
|
|
let simulateNoToken = false
|
|
|
|
test('Before all', function (t) {
|
|
server = http.createServer(() => {})
|
|
|
|
websocket.createServer({ server }, conn => {
|
|
conn.on('data', token => {
|
|
cliToken = token.toString('utf8')
|
|
if (simulateTimeout) {
|
|
conn.write('timeout\n')
|
|
} else if (simulateNoToken) {
|
|
conn.write('\n')
|
|
} else {
|
|
conn.write('jwtToken\n')
|
|
}
|
|
conn.end()
|
|
})
|
|
})
|
|
|
|
server.listen(0, function () {
|
|
t.plan(1)
|
|
t.ok(server)
|
|
})
|
|
})
|
|
|
|
test('authenticate', async function (t) {
|
|
let openedUrl = ''
|
|
const opnStub = url => {
|
|
openedUrl = url
|
|
}
|
|
|
|
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
|
|
|
|
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`)
|
|
t.plan(2)
|
|
t.strictEqual(openedUrl.split('/auth/token/')[1].replace('/', ''), cliToken)
|
|
t.strictEqual(jwtToken, 'jwtToken')
|
|
})
|
|
|
|
test('authenticate for private upload', async function (t) {
|
|
let openedUrl = ''
|
|
const opnStub = url => {
|
|
openedUrl = url
|
|
}
|
|
|
|
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
|
|
|
|
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`, {
|
|
private: true
|
|
})
|
|
const [token, askQuery] = openedUrl.split('/auth/token/')[1].split('?')
|
|
t.plan(3)
|
|
t.strictEqual(token.replace('/', ''), cliToken)
|
|
t.strictEqual(askQuery, 'private=1')
|
|
t.strictEqual(jwtToken, 'jwtToken')
|
|
})
|
|
|
|
test('authenticate using ask', async function (t) {
|
|
let openedUrl = ''
|
|
const opnStub = url => {
|
|
openedUrl = url
|
|
}
|
|
|
|
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
|
|
|
|
const jwtToken = await authenticate(`http://127.0.0.1:${server.address().port}`, {
|
|
ask: true
|
|
})
|
|
const [token, askQuery] = openedUrl.split('/auth/token/')[1].split('?')
|
|
t.plan(3)
|
|
t.strictEqual(token.replace('/', ''), cliToken)
|
|
t.strictEqual(askQuery, 'ask=1&private=1')
|
|
t.strictEqual(jwtToken, 'jwtToken')
|
|
})
|
|
|
|
test('authenticate timeout', async function (t) {
|
|
const opnStub = url => url
|
|
|
|
const authenticate = proxyquire('../lib/authenticate', { 'opn': opnStub }) // mocking the browser opening
|
|
|
|
simulateTimeout = true
|
|
|
|
try {
|
|
await authenticate(`http://127.0.0.1:${server.address().port}`)
|
|
simulateTimeout = false
|
|
t.fail('it should reject')
|
|
} catch (err) {
|
|
t.plan(2)
|
|
t.ok(err)
|
|
t.ok(err.message.includes('Authentication timed out'))
|
|
simulateTimeout = false
|
|
}
|
|
})
|
|
|
|
test('authenticate no auth token', async function (t) {
|
|
const authenticate = proxyquire('../lib/authenticate', { 'opn': url => url }) // mocking the browser opening
|
|
|
|
simulateNoToken = true
|
|
try {
|
|
await authenticate(`http://127.0.0.1:${server.address().port}`)
|
|
simulateNoToken = false
|
|
t.fail('it should reject')
|
|
} catch (err) {
|
|
t.plan(2)
|
|
t.ok(err)
|
|
t.ok(err.message.includes('Authentication failed. No token obtained'))
|
|
simulateNoToken = false
|
|
}
|
|
})
|
|
|
|
test('authenticate failure', async function (t) {
|
|
const authenticate = proxyquire(
|
|
'../lib/authenticate',
|
|
{
|
|
'opn': url => url,
|
|
'split2': () => ({ on: () => [] })
|
|
})
|
|
|
|
try {
|
|
await authenticate(`http://127.0.0.1:${server.address().port}`)
|
|
t.fail('it should reject')
|
|
} catch (err) {
|
|
t.plan(1)
|
|
t.ok(err)
|
|
}
|
|
})
|
|
|
|
test('After all', function (t) {
|
|
t.plan(0)
|
|
server.close()
|
|
})
|