refactor(everything): everything was refactored
This commit is contained in:
Родитель
b3defa6655
Коммит
f73a0101da
|
@ -1,3 +1,2 @@
|
||||||
node_modules
|
node_modules
|
||||||
public/out.json
|
|
||||||
*.log
|
*.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",
|
"name": "fxa-telemetry-dashboard",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "FxA Metrics Dashboard",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node index.js",
|
"start": "nodemon -e js bin/server.js",
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"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",
|
"license": "MPL-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "1.5.0",
|
"async": "1.5.0",
|
||||||
"body-parser": "^1.14.2",
|
"body-parser": "1.14.2",
|
||||||
|
"convict": "1.0.2",
|
||||||
"express": "4.13.3",
|
"express": "4.13.3",
|
||||||
"express-session": "^1.13.0",
|
"express-session": "1.13.0",
|
||||||
"fxa-jwtool": "^0.7.2",
|
"fxa-jwtool": "0.7.2",
|
||||||
"lodash": "3.10.1",
|
"lodash": "3.10.1",
|
||||||
"serve-static": "1.10.0",
|
"serve-static": "1.10.0",
|
||||||
"x-ray": "2.0.2"
|
"x-ray": "2.0.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"nodemon": "1.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
body {
|
body {
|
||||||
border-left: 22px solid orange;
|
border-left: 22px solid orange;
|
||||||
padding-bottom: 1000px;
|
|
||||||
overflow: scroll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -25,7 +23,7 @@ button {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
#placeholder img {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
@ -33,24 +31,6 @@ img {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
.lg-outer * {
|
||||||
-webkit-transition: all 1s ease;
|
text-align: left;
|
||||||
-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;
|
|
||||||
}
|
|
|
@ -7,6 +7,8 @@
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<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/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">
|
<link rel="stylesheet" href="index.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -17,8 +19,9 @@
|
||||||
<div id="placeholder"><img id="spinner" style="display: none" src="spinner.gif"/></div>
|
<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://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="https://apis.google.com/js/platform.js"></script>
|
||||||
<script src="/config"></script>
|
<script src="/auth/config"></script>
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
;window.loggedInEmail = null
|
;window.loggedInEmail = null
|
||||||
|
|
||||||
|
var PLACEHOLDER = $('#placeholder');
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
$.post('/api/logout');
|
$.post('/auth/logout');
|
||||||
$('#placeholder').html('');
|
PLACEHOLDER.html('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUI(data) {
|
function updateUI(data) {
|
||||||
|
@ -18,7 +20,10 @@ function updateUI(data) {
|
||||||
items.push('<a target="_blank" href="' + val + '"><img src="' + val + '" id="dash"' + key + '"/></a>');
|
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 {
|
} else {
|
||||||
|
@ -35,11 +40,10 @@ function signInChanged(signedIn) {
|
||||||
|
|
||||||
function userChanged(user) {
|
function userChanged(user) {
|
||||||
var id_token = user.getAuthResponse().id_token
|
var id_token = user.getAuthResponse().id_token
|
||||||
console.log('user changed: ' + id_token)
|
|
||||||
if (id_token) {
|
if (id_token) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
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,
|
data: 'idtoken=' + id_token,
|
||||||
contentType: 'application/x-www-form-urlencoded',
|
contentType: 'application/x-www-form-urlencoded',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
*
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче