mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-19 11:16:38 +00:00
Convert lib/auth/server to typescript
Change-type: patch
This commit is contained in:
parent
af86ac73e6
commit
93ba5832d8
@ -1,101 +0,0 @@
|
||||
###
|
||||
Copyright 2016 Balena
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
###
|
||||
|
||||
express = require('express')
|
||||
path = require('path')
|
||||
bodyParser = require('body-parser')
|
||||
Promise = require('bluebird')
|
||||
balena = require('balena-sdk').fromSharedOptions()
|
||||
utils = require('./utils')
|
||||
|
||||
createServer = ({ port, isDev } = {}) ->
|
||||
app = express()
|
||||
app.use bodyParser.urlencoded
|
||||
extended: true
|
||||
|
||||
app.set('view engine', 'ejs')
|
||||
app.set('views', path.join(__dirname, 'pages'))
|
||||
|
||||
if isDev
|
||||
app.use(express.static(path.join(__dirname, 'pages', 'static')))
|
||||
|
||||
server = app.listen(port)
|
||||
|
||||
return { app, server }
|
||||
|
||||
###*
|
||||
# @summary Await for token
|
||||
# @function
|
||||
# @protected
|
||||
#
|
||||
# @param {Object} options - options
|
||||
# @param {String} options.path - callback path
|
||||
# @param {Number} options.port - http port
|
||||
#
|
||||
# @example
|
||||
# server.awaitForToken
|
||||
# path: '/auth'
|
||||
# port: 9001
|
||||
# .then (token) ->
|
||||
# console.log(token)
|
||||
###
|
||||
exports.awaitForToken = (options) ->
|
||||
{ app, server } = createServer(port: options.port)
|
||||
|
||||
return new Promise (resolve, reject) ->
|
||||
closeServer = (errorMessage, successPayload) ->
|
||||
server.close ->
|
||||
if errorMessage
|
||||
reject(new Error(errorMessage))
|
||||
return
|
||||
|
||||
resolve(successPayload)
|
||||
|
||||
renderAndDone = ({ request, response, viewName, errorMessage, statusCode, token }) ->
|
||||
return getContext(viewName)
|
||||
.then (context) ->
|
||||
response.status(statusCode || 200).render(viewName, context)
|
||||
request.connection.destroy()
|
||||
closeServer(errorMessage, token)
|
||||
|
||||
app.post options.path, (request, response) ->
|
||||
token = request.body.token?.trim()
|
||||
|
||||
Promise.try ->
|
||||
if not token
|
||||
throw new Error('No token')
|
||||
return utils.loginIfTokenValid(token)
|
||||
.tap (loggedIn) ->
|
||||
if not loggedIn
|
||||
throw new Error('Invalid token')
|
||||
.then ->
|
||||
renderAndDone({ request, response, viewName: 'success', token })
|
||||
.catch (error) ->
|
||||
renderAndDone({
|
||||
request, response, viewName: 'error',
|
||||
statusCode: 401, errorMessage: error.message
|
||||
})
|
||||
|
||||
app.use (request, response) ->
|
||||
response.status(404).send('Not found')
|
||||
closeServer('Unknown path or verb')
|
||||
|
||||
exports.getContext = getContext = (viewName) ->
|
||||
if viewName is 'success'
|
||||
return Promise.props
|
||||
dashboardUrl: balena.settings.get('dashboardUrl')
|
||||
|
||||
return Promise.resolve({})
|
138
lib/auth/server.ts
Normal file
138
lib/auth/server.ts
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
Copyright 2016 Balena
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import * as balenaSdk from 'balena-sdk';
|
||||
import * as Promise from 'bluebird';
|
||||
import * as bodyParser from 'body-parser';
|
||||
import * as express from 'express';
|
||||
import * as path from 'path';
|
||||
import * as utils from './utils';
|
||||
|
||||
const balena = balenaSdk.fromSharedOptions();
|
||||
|
||||
const createServer = ({ port }: { port: number }) => {
|
||||
const app = express();
|
||||
app.use(
|
||||
bodyParser.urlencoded({
|
||||
extended: true,
|
||||
}),
|
||||
);
|
||||
|
||||
app.set('view engine', 'ejs');
|
||||
app.set('views', path.join(__dirname, 'pages'));
|
||||
|
||||
const server = app.listen(port);
|
||||
|
||||
return { app, server };
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Await for token
|
||||
* @function
|
||||
* @protected
|
||||
*
|
||||
* @param {Object} options - options
|
||||
* @param {String} options.path - callback path
|
||||
* @param {Number} options.port - http port
|
||||
*
|
||||
* @example
|
||||
* server.awaitForToken
|
||||
* path: '/auth'
|
||||
* port: 9001
|
||||
* .then (token) ->
|
||||
* console.log(token)
|
||||
*/
|
||||
export const awaitForToken = (options: {
|
||||
path: string;
|
||||
port: number;
|
||||
}): Promise<string> => {
|
||||
const { app, server } = createServer({ port: options.port });
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const closeServer = (
|
||||
errorMessage: string | undefined,
|
||||
successPayload?: string,
|
||||
) => {
|
||||
server.close(() => {
|
||||
if (errorMessage) {
|
||||
reject(new Error(errorMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(successPayload);
|
||||
});
|
||||
};
|
||||
|
||||
const renderAndDone = async ({
|
||||
request,
|
||||
response,
|
||||
viewName,
|
||||
errorMessage,
|
||||
statusCode = 200,
|
||||
token,
|
||||
}: {
|
||||
request: express.Request;
|
||||
response: express.Response;
|
||||
viewName: 'success' | 'error';
|
||||
errorMessage?: string;
|
||||
statusCode?: number;
|
||||
token?: string;
|
||||
}) => {
|
||||
const context = await getContext(viewName);
|
||||
response.status(statusCode).render(viewName, context);
|
||||
request.connection.destroy();
|
||||
closeServer(errorMessage, token);
|
||||
};
|
||||
|
||||
app.post(options.path, async (request, response) => {
|
||||
try {
|
||||
const token = request.body.token?.trim();
|
||||
|
||||
if (!token) {
|
||||
throw new Error('No token');
|
||||
}
|
||||
const loggedIn = await utils.loginIfTokenValid(token);
|
||||
if (!loggedIn) {
|
||||
throw new Error('Invalid token');
|
||||
}
|
||||
await renderAndDone({ request, response, viewName: 'success', token });
|
||||
} catch (error) {
|
||||
await renderAndDone({
|
||||
request,
|
||||
response,
|
||||
viewName: 'error',
|
||||
statusCode: 401,
|
||||
errorMessage: error.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.use((_request, response) => {
|
||||
response.status(404).send('Not found');
|
||||
closeServer('Unknown path or verb');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const getContext = (viewName: 'success' | 'error') => {
|
||||
if (viewName === 'success') {
|
||||
return Promise.props({
|
||||
dashboardUrl: balena.settings.get('dashboardUrl'),
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve({});
|
||||
};
|
62
npm-shrinkwrap.json
generated
62
npm-shrinkwrap.json
generated
@ -594,6 +594,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz",
|
||||
"integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw=="
|
||||
},
|
||||
"@types/body-parser": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz",
|
||||
"integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/connect": "*",
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/caseless": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||
@ -635,6 +645,15 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.0.tgz",
|
||||
"integrity": "sha512-htRqZr5qn8EzMelhX/Xmx142z218lLyGaeZ3YR8jlze4TATRU9huKKvuBmAJEW4LCC4pnY1N6JAm6p85fMHjhg=="
|
||||
},
|
||||
"@types/connect": {
|
||||
"version": "3.4.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
|
||||
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/depcheck": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/depcheck/-/depcheck-0.6.0.tgz",
|
||||
@ -676,6 +695,27 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
|
||||
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.2.tgz",
|
||||
"integrity": "sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/body-parser": "*",
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/serve-static": "*"
|
||||
}
|
||||
},
|
||||
"@types/express-serve-static-core": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.2.tgz",
|
||||
"integrity": "sha512-El9yMpctM6tORDAiBwZVLMcxoTMcqqRO9dVyYcn7ycLWbvR8klrDn8CAOwRfZujZtWD7yS/mshTdz43jMOejbg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"@types/range-parser": "*"
|
||||
}
|
||||
},
|
||||
"@types/form-data": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
|
||||
@ -754,6 +794,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/memoizee/-/memoizee-0.4.3.tgz",
|
||||
"integrity": "sha512-N6QT0c9ZbEKl33n1wyoTxZs4cpN+YXjs0Aqy5Qim8ipd9PBNIPqOh/p5Pixc4601tqr5GErsdxUbfqviDfubNw=="
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
|
||||
"integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/minimatch": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
|
||||
@ -846,6 +892,12 @@
|
||||
"integrity": "sha1-ExqJDe1kIbG1RfRRCkrqvG1GUnU=",
|
||||
"dev": true
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
||||
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/raven": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/raven/-/raven-2.5.1.tgz",
|
||||
@ -888,6 +940,16 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz",
|
||||
"integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ=="
|
||||
},
|
||||
"@types/serve-static": {
|
||||
"version": "1.13.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz",
|
||||
"integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/express-serve-static-core": "*",
|
||||
"@types/mime": "*"
|
||||
}
|
||||
},
|
||||
"@types/shell-escape": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/shell-escape/-/shell-escape-0.2.0.tgz",
|
||||
|
@ -98,12 +98,14 @@
|
||||
"@octokit/rest": "^16.38.1",
|
||||
"@types/archiver": "2.1.2",
|
||||
"@types/bluebird": "^3.5.29",
|
||||
"@types/body-parser": "^1.17.1",
|
||||
"@types/chai": "^4.2.7",
|
||||
"@types/chai-as-promised": "^7.1.1",
|
||||
"@types/chokidar": "^1.7.5",
|
||||
"@types/common-tags": "^1.8.0",
|
||||
"@types/dockerode": "2.5.6",
|
||||
"@types/ejs": "^3.0.0",
|
||||
"@types/express": "^4.17.2",
|
||||
"@types/fs-extra": "7.0.0",
|
||||
"@types/intercept-stdout": "^0.1.0",
|
||||
"@types/is-root": "1.0.0",
|
||||
|
@ -25,7 +25,9 @@ const options = {
|
||||
path: '/auth',
|
||||
};
|
||||
|
||||
const getPage = function(name: string): Promise<string> {
|
||||
const getPage = function(
|
||||
name: Parameters<typeof server.getContext>[0],
|
||||
): Promise<string> {
|
||||
const pagePath = path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
|
Loading…
Reference in New Issue
Block a user