mirror of
https://github.com/moparisthebest/mail
synced 2024-12-21 14:58:49 -05:00
[WO-592] implement webmail using socket.io
* Relax CSP to allow iframe assets to load * Integrate socket.io proxy * go to /# when controllers not initiated * Add offline caching using AppCache manifest
This commit is contained in:
parent
e29f083c60
commit
487bb31d45
17
Gruntfile.js
17
Gruntfile.js
@ -213,6 +213,20 @@ module.exports = function(grunt) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
manifest: {
|
||||||
|
generate: {
|
||||||
|
options: {
|
||||||
|
basePath: 'dist/',
|
||||||
|
timestamp: true,
|
||||||
|
hash: true,
|
||||||
|
cache: ['socket.io/socket.io.js'],
|
||||||
|
master: ['index.html']
|
||||||
|
},
|
||||||
|
src: ['**/*.*'],
|
||||||
|
dest: 'dist/appcache.manifest'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
nodewebkit: {
|
nodewebkit: {
|
||||||
options: {
|
options: {
|
||||||
version: '0.9.2', // node-webkit version
|
version: '0.9.2', // node-webkit version
|
||||||
@ -238,12 +252,13 @@ module.exports = function(grunt) {
|
|||||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||||
grunt.loadNpmTasks('grunt-node-webkit-builder');
|
grunt.loadNpmTasks('grunt-node-webkit-builder');
|
||||||
|
grunt.loadNpmTasks('grunt-manifest');
|
||||||
|
|
||||||
// Build tasks
|
// Build tasks
|
||||||
grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
|
grunt.registerTask('dist-npm', ['copy:npm', 'copy:npmDev', 'copy:cryptoLib']);
|
||||||
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
|
grunt.registerTask('dist-css', ['sass', 'autoprefixer', 'csso']);
|
||||||
grunt.registerTask('dist-copy', ['copy']);
|
grunt.registerTask('dist-copy', ['copy']);
|
||||||
grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy']);
|
grunt.registerTask('dist', ['clean', 'dist-npm', 'dist-css', 'dist-copy', 'manifest']);
|
||||||
|
|
||||||
// Test/Dev tasks
|
// Test/Dev tasks
|
||||||
grunt.registerTask('dev', ['connect:dev']);
|
grunt.registerTask('dev', ['connect:dev']);
|
||||||
|
12
README.md
12
README.md
@ -50,11 +50,21 @@ Then visit [http://localhost:8580/dist/#/desktop?dev=true](http://localhost:8580
|
|||||||
|
|
||||||
grunt watch
|
grunt watch
|
||||||
|
|
||||||
## Releasing
|
## Releasing Chrome App
|
||||||
|
|
||||||
grunt release-test --release=0.0.0.x
|
grunt release-test --release=0.0.0.x
|
||||||
grunt release-stable --release=0.x.0
|
grunt release-stable --release=0.x.0
|
||||||
|
|
||||||
|
## Deploying Web App
|
||||||
|
|
||||||
|
First build and generate the `dist/` directory:
|
||||||
|
|
||||||
|
grunt
|
||||||
|
|
||||||
|
Then deploy that directoy by adding it to a local git branch. Push that branch to your node.js server and then start the server:
|
||||||
|
|
||||||
|
npm start
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright © 2014, Whiteout Networks GmbH. All rights reserved.
|
Copyright © 2014, Whiteout Networks GmbH. All rights reserved.
|
||||||
|
12
config/default.js
Normal file
12
config/default.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
server: {
|
||||||
|
port: process.env.PORT || 8889,
|
||||||
|
host: "0.0.0.0"
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
level: "silly",
|
||||||
|
http: ':remote-addr [:date] ":method :url HTTP/:http-version" :status :res[content-length] ":referrer"'
|
||||||
|
}
|
||||||
|
};
|
10
config/integration.js
Normal file
10
config/integration.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
server: {
|
||||||
|
port: 8889
|
||||||
|
},
|
||||||
|
log: {
|
||||||
|
level: "error"
|
||||||
|
}
|
||||||
|
};
|
28
package.json
28
package.json
@ -23,7 +23,6 @@
|
|||||||
"node": ">=0.10"
|
"node": ">=0.10"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"postinstall": "grunt",
|
|
||||||
"test": "grunt && grunt test",
|
"test": "grunt && grunt test",
|
||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
@ -39,26 +38,31 @@
|
|||||||
"ng-infinite-scroll": "~1.1.2",
|
"ng-infinite-scroll": "~1.1.2",
|
||||||
"pgpbuilder": "~0.4.0",
|
"pgpbuilder": "~0.4.0",
|
||||||
"pgpmailer": "~0.4.0",
|
"pgpmailer": "~0.4.0",
|
||||||
"requirejs": "~2.1.14"
|
"requirejs": "~2.1.14",
|
||||||
|
"config": "^1.0.2",
|
||||||
|
"morgan": "^1.2.3",
|
||||||
|
"npmlog": "^0.1.1",
|
||||||
|
"socket.io": "^1.0.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
|
"angularjs": "https://github.com/whiteout-io/angular.js/tarball/npm-version",
|
||||||
"browsercrow": "https://github.com/whiteout-io/browsercrow/tarball/master",
|
"browsercrow": "https://github.com/whiteout-io/browsercrow/tarball/master",
|
||||||
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
|
"browsersmtp": "https://github.com/whiteout-io/browsersmtp/tarball/master",
|
||||||
"grunt": "~0.4.1",
|
|
||||||
"mocha": "~1.13.0",
|
|
||||||
"chai": "~1.7.2",
|
"chai": "~1.7.2",
|
||||||
"sinon": "~1.7.3",
|
"grunt": "~0.4.1",
|
||||||
|
"grunt-contrib-clean": "~0.5.0",
|
||||||
|
"grunt-contrib-copy": "~0.4.1",
|
||||||
|
"grunt-manifest": "^0.4.0",
|
||||||
|
"grunt-autoprefixer": "~0.7.2",
|
||||||
|
"grunt-contrib-compress": "~0.5.2",
|
||||||
"grunt-contrib-connect": "~0.5.0",
|
"grunt-contrib-connect": "~0.5.0",
|
||||||
"grunt-contrib-jshint": "~0.6.4",
|
"grunt-contrib-jshint": "~0.6.4",
|
||||||
"grunt-mocha": "~0.4.1",
|
|
||||||
"grunt-contrib-clean": "~0.5.0",
|
|
||||||
"grunt-csso": "~0.6.1",
|
|
||||||
"grunt-contrib-sass": "~0.7.3",
|
"grunt-contrib-sass": "~0.7.3",
|
||||||
"grunt-autoprefixer": "~0.7.2",
|
|
||||||
"grunt-contrib-watch": "~0.5.3",
|
"grunt-contrib-watch": "~0.5.3",
|
||||||
"grunt-contrib-copy": "~0.4.1",
|
"grunt-csso": "~0.6.1",
|
||||||
"grunt-contrib-compress": "~0.5.2",
|
"grunt-mocha": "~0.4.1",
|
||||||
"grunt-node-webkit-builder": "~0.1.17"
|
"grunt-node-webkit-builder": "~0.1.17",
|
||||||
|
"mocha": "~1.13.0",
|
||||||
|
"sinon": "~1.7.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
146
server.js
146
server.js
@ -1,8 +1,70 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var express = require('express'),
|
process.chdir(__dirname);
|
||||||
compression = require('compression'),
|
|
||||||
app = express();
|
var cluster = require('cluster');
|
||||||
|
var config = require('config');
|
||||||
|
var log = require('npmlog');
|
||||||
|
|
||||||
|
log.level = config.log.level;
|
||||||
|
|
||||||
|
// Handle error conditions
|
||||||
|
process.on('SIGTERM', function() {
|
||||||
|
log.warn('exit', 'Exited on SIGTERM');
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('SIGINT', function() {
|
||||||
|
log.warn('exit', 'Exited on SIGINT');
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('uncaughtException', function(err) {
|
||||||
|
log.error('uncaughtException ', err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cluster.isMaster) {
|
||||||
|
// MASTER process
|
||||||
|
|
||||||
|
cluster.on('fork', function(worker) {
|
||||||
|
log.info('cluster', 'Forked worker #%s [pid:%s]', worker.id, worker.process.pid);
|
||||||
|
});
|
||||||
|
|
||||||
|
cluster.on('exit', function(worker) {
|
||||||
|
log.warn('cluster', 'Worker #%s [pid:%s] died', worker.id, worker.process.pid);
|
||||||
|
setTimeout(function() {
|
||||||
|
cluster.fork();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fork a single worker
|
||||||
|
cluster.fork();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WORKER process
|
||||||
|
|
||||||
|
var express = require('express');
|
||||||
|
var compression = require('compression');
|
||||||
|
var app = express();
|
||||||
|
var server = require('http').Server(app);
|
||||||
|
var io = require('socket.io')(server);
|
||||||
|
var net = require('net');
|
||||||
|
|
||||||
|
// Setup logger. Stream all http logs to general logger
|
||||||
|
app.use(require('morgan')(config.log.http, {
|
||||||
|
'stream': {
|
||||||
|
'write': function(line) {
|
||||||
|
if ((line = (line || '').trim())) {
|
||||||
|
log.http('express', line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Do not advertise Express
|
||||||
|
app.disable('x-powered-by');
|
||||||
|
|
||||||
//
|
//
|
||||||
// web server config
|
// web server config
|
||||||
@ -17,7 +79,8 @@ app.use(function(req, res, next) {
|
|||||||
// HSTS
|
// HSTS
|
||||||
res.set('Strict-Transport-Security', 'max-age=16070400; includeSubDomains');
|
res.set('Strict-Transport-Security', 'max-age=16070400; includeSubDomains');
|
||||||
// CSP
|
// CSP
|
||||||
res.set('Content-Security-Policy', "default-src 'self'; object-src 'none'; connect-src *; style-src 'self' 'unsafe-inline'; img-src 'self' data:");
|
var iframe = development ? "http://" + req.hostname + ":" + port : "https://" + req.hostname; // allow iframe to load assets
|
||||||
|
res.set('Content-Security-Policy', "default-src 'self' " + iframe + "; object-src 'none'; connect-src *; style-src 'self' 'unsafe-inline' " + iframe + "; img-src 'self' data:");
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -38,11 +101,84 @@ app.use(express.static(__dirname + '/dist', {
|
|||||||
maxAge: oneDay
|
maxAge: oneDay
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Socket.io proxy
|
||||||
|
//
|
||||||
|
|
||||||
|
io.on('connection', function(socket) {
|
||||||
|
|
||||||
|
log.info('io', 'New connection [%s]', socket.conn.id);
|
||||||
|
|
||||||
|
var idCounter = 0;
|
||||||
|
|
||||||
|
socket.on('open', function(data, fn) {
|
||||||
|
var socketId = ++idCounter;
|
||||||
|
var tcp;
|
||||||
|
|
||||||
|
log.verbose('io', 'Open request to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
|
||||||
|
|
||||||
|
tcp = net.connect(data.port, data.host, function() {
|
||||||
|
log.verbose('io', 'Opened tcp connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
|
||||||
|
|
||||||
|
tcp.on('data', function(chunk) {
|
||||||
|
log.silly('io', 'Received %s bytes from %s:%s [%s:%s]', chunk.length, data.host, data.port, socket.conn.id, socketId);
|
||||||
|
socket.emit('data-' + socketId, chunk);
|
||||||
|
});
|
||||||
|
|
||||||
|
tcp.on('error', function(err) {
|
||||||
|
log.verbose('io', 'Error for %s:%s [%s:%s]: %s', data.host, data.port, socket.conn.id, socketId, err.message);
|
||||||
|
socket.emit('error-' + socketId, err.message);
|
||||||
|
});
|
||||||
|
|
||||||
|
tcp.on('end', function() {
|
||||||
|
socket.emit('end-' + socketId);
|
||||||
|
});
|
||||||
|
|
||||||
|
tcp.on('close', function() {
|
||||||
|
log.verbose('io', 'Closed tcp connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
|
||||||
|
socket.emit('close-' + socketId);
|
||||||
|
|
||||||
|
socket.removeAllListeners('data-' + socketId);
|
||||||
|
socket.removeAllListeners('end-' + socketId);
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('data-' + socketId, function(chunk, fn) {
|
||||||
|
if (!chunk || !chunk.length) {
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.silly('io', 'Sending %s bytes to %s:%s [%s:%s]', chunk.length, data.host, data.port, socket.conn.id, socketId);
|
||||||
|
tcp.write(chunk, function() {
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('end-' + socketId, function() {
|
||||||
|
log.verbose('io', 'Received request to close connection to %s:%s [%s:%s]', data.host, data.port, socket.conn.id, socketId);
|
||||||
|
tcp.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (typeof fn === 'function') {
|
||||||
|
fn(socketId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('disconnect', function() {
|
||||||
|
log.info('io', 'Closed connection [%s]', socket.conn.id);
|
||||||
|
socket.removeAllListeners();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
// start server
|
// start server
|
||||||
//
|
//
|
||||||
|
|
||||||
app.listen(port);
|
server.listen(port);
|
||||||
if (development) {
|
if (development) {
|
||||||
console.log(' > starting in development mode');
|
console.log(' > starting in development mode');
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html ng-app="mail" ng-csp>
|
<html ng-app="mail" ng-csp manifest="appcache.manifest">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Whiteout Mail</title>
|
<title>Whiteout Mail</title>
|
||||||
@ -29,6 +29,7 @@
|
|||||||
<link rel="stylesheet" media="all" href="css/all.min.css" type="text/css">
|
<link rel="stylesheet" media="all" href="css/all.min.css" type="text/css">
|
||||||
|
|
||||||
<!-- The Scripts -->
|
<!-- The Scripts -->
|
||||||
|
<script src="socket.io/socket.io.js"></script>
|
||||||
<script src="lib/require.js"></script>
|
<script src="lib/require.js"></script>
|
||||||
<script src="require-config.js"></script>
|
<script src="require-config.js"></script>
|
||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
|
@ -3,7 +3,12 @@ define(function(require) {
|
|||||||
|
|
||||||
var appCtrl = require('js/app-controller');
|
var appCtrl = require('js/app-controller');
|
||||||
|
|
||||||
var AddAccountCtrl = function($scope, $location) {
|
var AddAccountCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appCtrl._auth && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$scope.connectToGoogle = function() {
|
$scope.connectToGoogle = function() {
|
||||||
// test for oauth support
|
// test for oauth support
|
||||||
if (appCtrl._auth._oauth.isSupported()) {
|
if (appCtrl._auth._oauth.isSupported()) {
|
||||||
|
@ -3,7 +3,12 @@ define(function(require) {
|
|||||||
|
|
||||||
var appController = require('js/app-controller');
|
var appController = require('js/app-controller');
|
||||||
|
|
||||||
var LoginExistingCtrl = function($scope, $location) {
|
var LoginExistingCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appController._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var emailDao = appController._emailDao;
|
var emailDao = appController._emailDao;
|
||||||
|
|
||||||
$scope.buttonEnabled = true;
|
$scope.buttonEnabled = true;
|
||||||
|
@ -3,7 +3,12 @@ define(function(require) {
|
|||||||
|
|
||||||
var appController = require('js/app-controller');
|
var appController = require('js/app-controller');
|
||||||
|
|
||||||
var LoginInitialCtrl = function($scope, $location) {
|
var LoginInitialCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appController._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var emailDao = appController._emailDao,
|
var emailDao = appController._emailDao,
|
||||||
states, termsMsg = 'You must accept the Terms of Service to continue.';
|
states, termsMsg = 'You must accept the Terms of Service to continue.';
|
||||||
|
|
||||||
|
@ -4,7 +4,12 @@ define(function(require) {
|
|||||||
var angular = require('angular'),
|
var angular = require('angular'),
|
||||||
appController = require('js/app-controller');
|
appController = require('js/app-controller');
|
||||||
|
|
||||||
var LoginExistingCtrl = function($scope, $location) {
|
var LoginExistingCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appController._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var emailDao = appController._emailDao,
|
var emailDao = appController._emailDao,
|
||||||
pgp = appController._pgp;
|
pgp = appController._pgp;
|
||||||
|
|
||||||
|
@ -3,7 +3,12 @@ define(function(require) {
|
|||||||
|
|
||||||
var appController = require('js/app-controller');
|
var appController = require('js/app-controller');
|
||||||
|
|
||||||
var LoginPrivateKeyDownloadCtrl = function($scope, $location) {
|
var LoginPrivateKeyDownloadCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appController._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var keychain = appController._keychain,
|
var keychain = appController._keychain,
|
||||||
emailDao = appController._emailDao,
|
emailDao = appController._emailDao,
|
||||||
userId = emailDao._account.emailAddress;
|
userId = emailDao._account.emailAddress;
|
||||||
|
@ -10,7 +10,12 @@ define(function(require) {
|
|||||||
ImapClient = require('imap-client'),
|
ImapClient = require('imap-client'),
|
||||||
SmtpClient = require('smtpclient');
|
SmtpClient = require('smtpclient');
|
||||||
|
|
||||||
var SetCredentialsCtrl = function($scope, $location) {
|
var SetCredentialsCtrl = function($scope, $location, $routeParams) {
|
||||||
|
if (!appCtrl._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var auth = appCtrl._auth;
|
var auth = appCtrl._auth;
|
||||||
|
|
||||||
var provider;
|
var provider;
|
||||||
|
@ -13,7 +13,12 @@ define(function(require) {
|
|||||||
// Controller
|
// Controller
|
||||||
//
|
//
|
||||||
|
|
||||||
var NavigationCtrl = function($scope, $routeParams) {
|
var NavigationCtrl = function($scope, $routeParams, $location) {
|
||||||
|
if (!appController._emailDao && !$routeParams.dev) {
|
||||||
|
$location.path('/'); // init app
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
emailDao = appController._emailDao;
|
emailDao = appController._emailDao;
|
||||||
outboxBo = appController._outboxBo;
|
outboxBo = appController._outboxBo;
|
||||||
|
|
||||||
|
@ -9,39 +9,44 @@ define(function(require) {
|
|||||||
appController = require('js/app-controller');
|
appController = require('js/app-controller');
|
||||||
|
|
||||||
describe('Add Account Controller unit test', function() {
|
describe('Add Account Controller unit test', function() {
|
||||||
var scope, location, ctrl, authStub;
|
var scope, location, ctrl, authStub, origAuth;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
// remember original module to restore later, then replace it
|
||||||
|
origAuth = appController._auth;
|
||||||
|
appController._auth = authStub = sinon.createStubInstance(Auth);
|
||||||
|
|
||||||
|
angular.module('addaccounttest', []);
|
||||||
|
mocks.module('addaccounttest');
|
||||||
|
mocks.inject(function($controller, $rootScope, $location) {
|
||||||
|
location = $location;
|
||||||
|
scope = $rootScope.$new();
|
||||||
|
scope.state = {};
|
||||||
|
|
||||||
|
sinon.stub(location, 'path').returns(location);
|
||||||
|
sinon.stub(location, 'search').returns(location);
|
||||||
|
sinon.stub(scope, '$apply', function() {});
|
||||||
|
|
||||||
|
ctrl = $controller(AddAccountCtrl, {
|
||||||
|
$location: location,
|
||||||
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
// restore the app controller module
|
||||||
|
appController._auth = origAuth;
|
||||||
|
|
||||||
|
location.path.restore();
|
||||||
|
location.search.restore();
|
||||||
|
scope.$apply.restore();
|
||||||
|
});
|
||||||
|
|
||||||
describe('connectToGoogle', function() {
|
describe('connectToGoogle', function() {
|
||||||
var origAuth;
|
|
||||||
beforeEach(function() {
|
|
||||||
// remember original module to restore later, then replace it
|
|
||||||
origAuth = appController._auth;
|
|
||||||
appController._auth = authStub = sinon.createStubInstance(Auth);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function() {
|
|
||||||
// restore the app controller module
|
|
||||||
appController._auth = origAuth;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
authStub._oauth = {
|
authStub._oauth = {
|
||||||
isSupported: function() {
|
isSupported: function() {
|
||||||
return true;
|
return true;
|
||||||
@ -57,30 +62,9 @@ define(function(require) {
|
|||||||
provider: 'gmail'
|
provider: 'gmail'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
expect(authStub.getOAuthToken.calledOnce).to.be.true;
|
expect(authStub.getOAuthToken.calledOnce).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not use oauth for gmail', function() {
|
it('should not use oauth for gmail', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
authStub._oauth = {
|
authStub._oauth = {
|
||||||
isSupported: function() {
|
isSupported: function() {
|
||||||
return false;
|
return false;
|
||||||
@ -94,30 +78,9 @@ define(function(require) {
|
|||||||
provider: 'gmail'
|
provider: 'gmail'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
expect(authStub.getOAuthToken.called).to.be.false;
|
expect(authStub.getOAuthToken.called).to.be.false;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not forward to login when oauth fails', function(done) {
|
it('should not forward to login when oauth fails', function(done) {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
authStub._oauth = {
|
authStub._oauth = {
|
||||||
isSupported: function() {
|
isSupported: function() {
|
||||||
return true;
|
return true;
|
||||||
@ -131,10 +94,6 @@ define(function(require) {
|
|||||||
expect(location.path.called).to.be.false;
|
expect(location.path.called).to.be.false;
|
||||||
expect(location.search.called).to.be.false;
|
expect(location.search.called).to.be.false;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,193 +103,67 @@ define(function(require) {
|
|||||||
|
|
||||||
describe('connectToYahoo', function() {
|
describe('connectToYahoo', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectToYahoo();
|
scope.connectToYahoo();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'yahoo'
|
provider: 'yahoo'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('connectToTonline', function() {
|
describe('connectToTonline', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectToTonline();
|
scope.connectToTonline();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'tonline'
|
provider: 'tonline'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('connectToOutlook', function() {
|
describe('connectToOutlook', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectToOutlook();
|
scope.connectToOutlook();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'outlook'
|
provider: 'outlook'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('connectToGmx', function() {
|
describe('connectToGmx', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectToGmx();
|
scope.connectToGmx();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'gmx'
|
provider: 'gmx'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('connectToWebde', function() {
|
describe('connectToWebde', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectToWebde();
|
scope.connectToWebde();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'webde'
|
provider: 'webde'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('connectOther', function() {
|
describe('connectOther', function() {
|
||||||
it('should forward to login', function() {
|
it('should forward to login', function() {
|
||||||
angular.module('addaccounttest', []);
|
|
||||||
mocks.module('addaccounttest');
|
|
||||||
mocks.inject(function($controller, $rootScope, $location) {
|
|
||||||
location = $location;
|
|
||||||
scope = $rootScope.$new();
|
|
||||||
scope.state = {};
|
|
||||||
|
|
||||||
sinon.stub(location, 'path').returns(location);
|
|
||||||
sinon.stub(location, 'search').returns(location);
|
|
||||||
sinon.stub(scope, '$apply', function() {});
|
|
||||||
|
|
||||||
ctrl = $controller(AddAccountCtrl, {
|
|
||||||
$location: location,
|
|
||||||
$scope: scope
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
scope.connectOther();
|
scope.connectOther();
|
||||||
|
|
||||||
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
expect(location.path.calledWith('/login-set-credentials')).to.be.true;
|
||||||
expect(location.search.calledWith({
|
expect(location.search.calledWith({
|
||||||
provider: 'custom'
|
provider: 'custom'
|
||||||
})).to.be.true;
|
})).to.be.true;
|
||||||
|
|
||||||
location.path.restore();
|
|
||||||
location.search.restore();
|
|
||||||
scope.$apply.restore();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -39,7 +39,8 @@ define(function(require) {
|
|||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
scope.state = {};
|
scope.state = {};
|
||||||
ctrl = $controller(LoginExistingCtrl, {
|
ctrl = $controller(LoginExistingCtrl, {
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -43,7 +43,8 @@ define(function(require) {
|
|||||||
ui: {}
|
ui: {}
|
||||||
};
|
};
|
||||||
ctrl = $controller(LoginInitialCtrl, {
|
ctrl = $controller(LoginInitialCtrl, {
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -41,7 +41,8 @@ define(function(require) {
|
|||||||
ui: {}
|
ui: {}
|
||||||
};
|
};
|
||||||
ctrl = $controller(LoginNewDeviceCtrl, {
|
ctrl = $controller(LoginNewDeviceCtrl, {
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -38,7 +38,8 @@ define(function(require) {
|
|||||||
scope.state = {};
|
scope.state = {};
|
||||||
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
|
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
|
||||||
$location: location,
|
$location: location,
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -251,7 +252,8 @@ define(function(require) {
|
|||||||
scope.state = {};
|
scope.state = {};
|
||||||
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
|
ctrl = $controller(LoginPrivateKeyDownloadCtrl, {
|
||||||
$location: location,
|
$location: location,
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ define(function(require) {
|
|||||||
|
|
||||||
scope.state = {};
|
scope.state = {};
|
||||||
setCredentialsCtrl = $controller(SetCredentialsCtrl, {
|
setCredentialsCtrl = $controller(SetCredentialsCtrl, {
|
||||||
$scope: scope
|
$scope: scope,
|
||||||
|
$routeParams: {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user