refactor(everything): everything was refactored
This commit is contained in:
Родитель
b3defa6655
Коммит
f73a0101da
|
@ -1,3 +1,2 @@
|
|||
node_modules
|
||||
public/out.json
|
||||
*.log
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# fxa-telemetry-dashboard
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
npm install
|
||||
npm start
|
||||
```
|
|
@ -0,0 +1,23 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var path = require('path');
|
||||
var config = require('../lib/config');
|
||||
|
||||
var dashboards = require('../lib/dashboards')();
|
||||
|
||||
var app = require('../lib/express')();
|
||||
var routesAuth = require('../lib/routes/auth');
|
||||
app.use('/auth', routesAuth);
|
||||
app.use('/static_secure/out.json', function(req, res, next){
|
||||
if(req.session && req.session.email){
|
||||
return res.sendFile(path.resolve(__dirname + '/../static_secure/out.json'));
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
|
||||
var port = config.get('port');
|
||||
app.listen(port);
|
||||
console.log('Started on port:', port);
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"google_oauth_client_id": "501118371406-njrjt9r48obid0nng4mdr83afvspgl6n.apps.googleusercontent.com",
|
||||
"session_secret": "secret"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"google_oauth_client_id": "501118371406-3nuvgor9inia5mqmmm24ff1pmjss2j84.apps.googleusercontent.com",
|
||||
}
|
106
index.js
106
index.js
|
@ -1,106 +0,0 @@
|
|||
var Xray = require('x-ray');
|
||||
var JWTool = require('fxa-jwtool');
|
||||
var async = require('async');
|
||||
var _ = require('lodash');
|
||||
var fs = require('fs');
|
||||
|
||||
var dashboards = require('./dashboards');
|
||||
|
||||
var x = Xray();
|
||||
|
||||
var findOutput = function (book, cb) {
|
||||
var error;
|
||||
try {
|
||||
x(book.url, '.output_png img@src')(function(err, contents) {
|
||||
error = err;
|
||||
cb(null, contents);
|
||||
})
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
console.log(error, 'for', book.url);
|
||||
cb(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async.map(dashboards, findOutput, function(err, results){
|
||||
var finalResults = results.filter(Boolean);
|
||||
var output = {}
|
||||
var output = _.extend({}, finalResults);
|
||||
if (! err && results) {
|
||||
fs.writeFile('static_secure/out.json', JSON.stringify(output))
|
||||
}
|
||||
});
|
||||
|
||||
var express = require('express')
|
||||
var serveStatic = require('serve-static')
|
||||
var bodyParser = require('body-parser')
|
||||
var session = require('express-session')
|
||||
|
||||
var app = express()
|
||||
app.use(session({ secret: 'todosecret', cookie: { maxAge: 60000 }}))
|
||||
|
||||
app.use(bodyParser.urlencoded());
|
||||
app.use(bodyParser.json());
|
||||
|
||||
app.use(serveStatic('static/', {'index': ['index.html']}))
|
||||
app.use('/static_secure/out.json', function(req, res, next){
|
||||
if(req.session && req.session.email){
|
||||
return res.sendFile(__dirname + '/static_secure/out.json');
|
||||
} else {
|
||||
res.sendStatus(403);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
var jwtool = new JWTool(['https://www.googleapis.com/oauth2/v3/certs'])
|
||||
|
||||
app.post('/api/auth', function (req, res) {
|
||||
if (! req.body.idtoken) {
|
||||
return res.send(401)
|
||||
}
|
||||
// Verify the idtoken's (JWT) signature with the key set from the configured JKU.
|
||||
// (Google's jwt include a `kid` but no `jku`)
|
||||
jwtool.verify(req.body.idtoken, { jku: 'https://www.googleapis.com/oauth2/v3/certs' })
|
||||
.then(
|
||||
function (data) {
|
||||
// ensure the token meets all of our criteria
|
||||
if (
|
||||
data.aud === '501118371406-3nuvgor9inia5mqmmm24ff1pmjss2j84.apps.googleusercontent.com'
|
||||
&& data.exp > (Date.now() / 1000)
|
||||
&& data.hd === 'mozilla.com'
|
||||
) {
|
||||
// set a cookie for authenticating against our other endpoints
|
||||
req.session.email = data.email
|
||||
res.send(data)
|
||||
}
|
||||
else {
|
||||
// this user is not authorized
|
||||
res.sendStatus(401)
|
||||
}
|
||||
},
|
||||
function (err) {
|
||||
// the token was not valid
|
||||
res.send(500, err)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
app.get('/config', function (req, res) {
|
||||
res.type('application/javascript')
|
||||
res.send('var client_id = "501118371406-3nuvgor9inia5mqmmm24ff1pmjss2j84.apps.googleusercontent.com"')
|
||||
});
|
||||
|
||||
app.post('/api/logout', function(req, res) {
|
||||
if (req.session) {
|
||||
req.session.email = null;
|
||||
}
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
app.listen(10157)
|
||||
console.log('Started on port 10157!')
|
|
@ -0,0 +1,61 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var convict = require('convict');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var conf = module.exports = convict({
|
||||
google_oauth_client_id: {
|
||||
default: '501118371406-3nuvgor9inia5mqmmm24ff1pmjss2j84.apps.googleusercontent.com',
|
||||
doc: 'Google OAuth Client ID',
|
||||
format: String,
|
||||
},
|
||||
session_secret: {
|
||||
default: '',
|
||||
doc: 'Session Secret',
|
||||
format: String,
|
||||
},
|
||||
env: {
|
||||
default: 'production',
|
||||
doc: 'What environment are we running in? Note: all hosted environments are \'production\'.',
|
||||
env: 'NODE_ENV',
|
||||
format: [
|
||||
'production',
|
||||
'development'
|
||||
]
|
||||
},
|
||||
port: {
|
||||
default: 10157,
|
||||
doc: 'Server Port',
|
||||
env: 'PORT',
|
||||
format: 'port',
|
||||
},
|
||||
});
|
||||
|
||||
var DEV_CONFIG_PATH = path.join(__dirname, '..', 'config', 'local.json');
|
||||
var files;
|
||||
|
||||
// handle configuration files. you can specify a CSV list of configuration
|
||||
// files to process, which will be overlayed in order, in the CONFIG_FILES
|
||||
// environment variable
|
||||
if (process.env.CONFIG_FILES && process.env.CONFIG_FILES.trim() !== '') {
|
||||
files = process.env.CONFIG_FILES.split(',');
|
||||
} else if (fs.existsSync(DEV_CONFIG_PATH)) {
|
||||
files = [ DEV_CONFIG_PATH ];
|
||||
}
|
||||
|
||||
if (files) {
|
||||
conf.loadFile(files);
|
||||
}
|
||||
|
||||
if (! process.env.NODE_ENV) {
|
||||
process.env.NODE_ENV = conf.get('env');
|
||||
}
|
||||
|
||||
var options = {
|
||||
strict: true
|
||||
};
|
||||
|
||||
conf.validate(options);
|
|
@ -0,0 +1,44 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var _ = require('lodash');
|
||||
var async = require('async');
|
||||
var fs = require('fs');
|
||||
var Xray = require('x-ray');
|
||||
|
||||
var dashboards = require('../dashboards');
|
||||
|
||||
var findOutput = function (book, cb) {
|
||||
var x = Xray();
|
||||
var error;
|
||||
try {
|
||||
x(book.url, '.output_png img@src')(function(err, contents) {
|
||||
error = err;
|
||||
cb(null, contents);
|
||||
})
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
console.log(error, 'for', book.url);
|
||||
cb(null);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function generateDashboardOutput() {
|
||||
console.log('Fetching dashboard data...');
|
||||
|
||||
async.map(dashboards, findOutput, function(err, results){
|
||||
var finalResults = results.filter(Boolean);
|
||||
var output = {};
|
||||
var output = _.extend({}, finalResults);
|
||||
if (! err && results) {
|
||||
console.log('Writing dashboard data...');
|
||||
fs.writeFile('static_secure/out.json', JSON.stringify(output))
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
var express = require('express');
|
||||
var serveStatic = require('serve-static');
|
||||
var bodyParser = require('body-parser');
|
||||
var session = require('express-session');
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
module.exports = function configureExpress() {
|
||||
var app = express();
|
||||
|
||||
if (! config.get('session_secret')) {
|
||||
throw new Error('Set a session secret in configuration');
|
||||
}
|
||||
|
||||
app.use(session({
|
||||
secret: config.get('session_secret'),
|
||||
cookie: {
|
||||
maxAge: 60000,
|
||||
},
|
||||
saveUninitialized: true,
|
||||
resave: false,
|
||||
}));
|
||||
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
|
||||
app.use(bodyParser.json());
|
||||
|
||||
app.use(serveStatic('static/', {'index': ['index.html']}))
|
||||
|
||||
return app;
|
||||
};
|
|
@ -0,0 +1,53 @@
|
|||
var express = require('express');
|
||||
var JWTool = require('fxa-jwtool');
|
||||
|
||||
var GOOGLE_API_JKU = 'https://www.googleapis.com/oauth2/v3/certs';
|
||||
|
||||
var config = require('../config');
|
||||
var router = express.Router();
|
||||
var jwtool = new JWTool([GOOGLE_API_JKU])
|
||||
|
||||
router.post('/login', function (req, res) {
|
||||
if (!req.body.idtoken) {
|
||||
return res.send(401)
|
||||
}
|
||||
// Verify the idtoken's (JWT) signature with the key set from the configured JKU.
|
||||
// (Google's jwt include a `kid` but no `jku`)
|
||||
jwtool.verify(req.body.idtoken, {jku: GOOGLE_API_JKU})
|
||||
.then(
|
||||
function (data) {
|
||||
// ensure the token meets all of our criteria
|
||||
if (
|
||||
data.aud === config.get('google_oauth_client_id')
|
||||
&& data.exp > (Date.now() / 1000)
|
||||
&& data.hd === 'mozilla.com'
|
||||
) {
|
||||
// set a cookie for authenticating against our other endpoints
|
||||
req.session.email = data.email
|
||||
res.send(data)
|
||||
}
|
||||
else {
|
||||
// this user is not authorized
|
||||
res.sendStatus(401)
|
||||
}
|
||||
},
|
||||
function (err) {
|
||||
// the token was not valid
|
||||
res.send(500, err)
|
||||
}
|
||||
)
|
||||
});
|
||||
|
||||
router.get('/config', function (req, res) {
|
||||
res.type('application/javascript');
|
||||
res.send('var client_id = "'+ config.get('google_oauth_client_id') + '";');
|
||||
});
|
||||
|
||||
router.post('/logout', function (req, res) {
|
||||
if (req.session) {
|
||||
req.session.email = null;
|
||||
}
|
||||
res.sendStatus(200);
|
||||
});
|
||||
|
||||
module.exports = router;
|
22
package.json
22
package.json
|
@ -1,22 +1,30 @@
|
|||
{
|
||||
"name": "fxa-telemetry-dashboard",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"description": "FxA Metrics Dashboard",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"start": "nodemon -e js bin/server.js",
|
||||
"start-production": "CONFIG_FILES=config/production.json node bin/server.js"
|
||||
},
|
||||
"author": "",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mozilla/fxa-telemetry-dashboard"
|
||||
},
|
||||
"author": "Mozilla (https://mozilla.org/)",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"async": "1.5.0",
|
||||
"body-parser": "^1.14.2",
|
||||
"body-parser": "1.14.2",
|
||||
"convict": "1.0.2",
|
||||
"express": "4.13.3",
|
||||
"express-session": "^1.13.0",
|
||||
"fxa-jwtool": "^0.7.2",
|
||||
"express-session": "1.13.0",
|
||||
"fxa-jwtool": "0.7.2",
|
||||
"lodash": "3.10.1",
|
||||
"serve-static": "1.10.0",
|
||||
"x-ray": "2.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "1.8.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
body {
|
||||
border-left: 22px solid orange;
|
||||
padding-bottom: 1000px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
h1 {
|
||||
|
@ -25,7 +23,7 @@ button {
|
|||
margin: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
#placeholder img {
|
||||
max-width: 400px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
|
@ -33,24 +31,6 @@ img {
|
|||
background: white;
|
||||
}
|
||||
|
||||
img {
|
||||
-webkit-transition: all 1s ease;
|
||||
-moz-transition: all 1s ease;
|
||||
-o-transition: all 1s ease;
|
||||
-ms-transition: all 1s ease;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
|
||||
img:hover {
|
||||
-webkit-transform:scale(2.25);
|
||||
-moz-transform:scale(2.25);
|
||||
-ms-transform:scale(2.25);
|
||||
-o-transform:scale(2.25);
|
||||
transform:scale(2.25);
|
||||
-webkit-transform-origin : left top;
|
||||
-moz-transform-origin : left top;
|
||||
-o-transform-origin : left top;
|
||||
-ms-transform-origin : left top;
|
||||
transform-origin : left top;
|
||||
border: 2px solid orange;
|
||||
}
|
||||
.lg-outer * {
|
||||
text-align: left;
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
<meta name="description" content="">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.3/normalize.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.2.14/css/lightgallery.min.css">
|
||||
|
||||
<link rel="stylesheet" href="index.css">
|
||||
</head>
|
||||
<body>
|
||||
|
@ -17,8 +19,9 @@
|
|||
<div id="placeholder"><img id="spinner" style="display: none" src="spinner.gif"/></div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightgallery/1.2.14/js/lightgallery-all.min.js"></script>
|
||||
<script src="https://apis.google.com/js/platform.js"></script>
|
||||
<script src="/config"></script>
|
||||
<script src="/auth/config"></script>
|
||||
<script src="index.js"></script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
;window.loggedInEmail = null
|
||||
|
||||
var PLACEHOLDER = $('#placeholder');
|
||||
|
||||
function logout() {
|
||||
$.post('/api/logout');
|
||||
$('#placeholder').html('');
|
||||
$.post('/auth/logout');
|
||||
PLACEHOLDER.html('');
|
||||
}
|
||||
|
||||
function updateUI(data) {
|
||||
|
@ -18,7 +20,10 @@ function updateUI(data) {
|
|||
items.push('<a target="_blank" href="' + val + '"><img src="' + val + '" id="dash"' + key + '"/></a>');
|
||||
});
|
||||
|
||||
$('#placeholder').html(items)
|
||||
PLACEHOLDER.html(items)
|
||||
PLACEHOLDER.lightGallery({
|
||||
thumbnail:true
|
||||
});
|
||||
|
||||
});
|
||||
} else {
|
||||
|
@ -35,11 +40,10 @@ function signInChanged(signedIn) {
|
|||
|
||||
function userChanged(user) {
|
||||
var id_token = user.getAuthResponse().id_token
|
||||
console.log('user changed: ' + id_token)
|
||||
if (id_token) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/api/auth', // this creates a cookie used to authenicate other api requests
|
||||
url: '/auth/login', // this creates a cookie used to authenicate other api requests
|
||||
data: 'idtoken=' + id_token,
|
||||
contentType: 'application/x-www-form-urlencoded',
|
||||
dataType: 'json',
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
*
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче