Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/buyer approve request #53

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
7dc23f1
config `moduleDirectories` to avoid `../../../..`
hotay Jun 18, 2016
e1edbd3
add partial `transactionTransferSequence` feature
hotay Jun 18, 2016
06199e3
setup eslint
hotay Jun 20, 2016
9c45fe1
remove reselect
hotay Jun 20, 2016
6ea2871
fix typo
hotay Jun 20, 2016
c13e56e
setup eslint
hotay Jun 20, 2016
0772054
Merge branch 'chore/setup-eslint' of github.com:hotay/mxfactorial int…
hotay Jun 20, 2016
355acb3
fix typo
hotay Jun 20, 2016
a3e53de
Merge branch 'master' into chore/setup-eslint
hotay Jun 20, 2016
1544fc8
fix eslint errors
hotay Jun 20, 2016
b7e852b
add missing eslint packages
hotay Jun 20, 2016
0b5df8f
setup frontend test coverage and remove old test
hotay Jun 21, 2016
9d9404e
cover test for `reducers` `selectors` `actions` and `Transaction comp…
hotay Jun 21, 2016
96340cd
refactor old components and add test
hotay Jun 22, 2016
5c98f79
add render key for transaction item
hotay Jun 22, 2016
acb7f89
Merge pull request #2 from hotay/chore/setup-frontend-test
Jun 22, 2016
0f97a38
Merge remote-tracking branch 'upstream/master'
hotay Jun 22, 2016
324424f
Merge branch 'master' into chore/setup-eslint
hotay Jun 22, 2016
f39c963
remove unused `Link` from `HomePage`
hotay Jun 22, 2016
2b06b52
Merge pull request #1 from hotay/chore/setup-eslint
Jun 22, 2016
c9b08a1
Merge remote-tracking branch 'upstream/master'
hotay Jun 24, 2016
4f63cec
add `.editorconfig`
hotay Jun 24, 2016
c9e456b
Post Transaction to /transact api
hotay Jun 24, 2016
9e3d8a3
handle post to /transact failed
hotay Jun 24, 2016
935086d
fix post transaction test and generateAsyncTypes test
hotay Jun 24, 2016
9f82555
Merge pull request #3 from hotay/feature/post-transact-form
Jun 24, 2016
172e2cd
upgrade axios post user create form as xxx-form-url-endcode content-type
hotay Jun 24, 2016
c5a0f79
Merge pull request #4 from hotay/feature/post-transact-form
Jun 24, 2016
484caa1
fix field `name` and `cr_account` not include in transaction_item, fi…
hotay Jun 25, 2016
d194d40
Merge pull request #5 from hotay/feature/post-transact-form
Jun 25, 2016
40d106c
add validate password
hotay Jun 25, 2016
7b305a9
remove books directories
hotay Jun 25, 2016
3a5d19b
remove jQuery cdn, add headers to post action
hotay Jun 25, 2016
6c33ecb
remove console.log
hotay Jun 25, 2016
2be5c18
Merge pull request #6 from hotay/feature/post-transact-form
Jun 26, 2016
3cef28c
Merge branch 'master' of github.com:systemaccounting/mxfactorial
hotay Jun 26, 2016
f8f4dca
Merge remote-tracking branch 'upstream/master'
hotay Jun 29, 2016
db20090
create firebase rest client
hotay Jun 30, 2016
fa39e36
Merge branch 'master' of github.com:systemaccounting/mxfactorial into…
hotay Jun 30, 2016
9743c94
fix fields not save
hotay Jul 1, 2016
a64406d
minor ui tweak on transaction screen
hotay Jul 1, 2016
abcbf8b
change state_name to state and street to street_name
hotay Jul 1, 2016
a2b4040
Merge pull request #7 from hotay/feature/interact-with-firebase
Jul 1, 2016
725dfdc
update cr_account should change transaction_item cr_account
hotay Jul 1, 2016
dcd1e05
Merge branch 'master' of github.com:hotay/mxfactorial
hotay Jul 2, 2016
3e576f8
Merge remote-tracking branch 'upstream/master'
hotay Jul 2, 2016
15987a6
add account setting page, password edit form, email edit form
hotay Jul 3, 2016
1271098
add Account Profile page
hotay Jul 3, 2016
af84911
integrate back-end api with account setting
hotay Jul 3, 2016
8a6ffd8
add backbutton profile should save in array
hotay Jul 5, 2016
ddaba4a
Merge branch 'feature/account-setting-page'
hotay Jul 6, 2016
5a40ca5
Merge branch 'master' of github.com:systemaccounting/mxfactorial
hotay Jul 8, 2016
8d9c626
add buyer approve request feature
hotay Jul 12, 2016
5c5d71f
basic implement firebase - socket io
hotay Jul 19, 2016
7d274bd
add notify socket endpoint flow
hotay Jul 21, 2016
db6aa20
observe transaction to emit notification
hotay Jul 23, 2016
a1932c2
add black list transaction which is already emit an notification
hotay Jul 23, 2016
2d42548
change notification payload to object
hotay Jul 23, 2016
cef9ab7
change constant endpoint to production
hotay Jul 23, 2016
67e5c51
add tests for related files
hotay Jul 24, 2016
336200c
swap db_author and cr_author before request transaction
hotay Jul 24, 2016
d9e6ac3
correct notification for transaction request and transaction transact
hotay Jul 24, 2016
85e44da
enable flag button even there is no notification
hotay Jul 25, 2016
03bd39e
consistent api and sort notification
hotay Jul 25, 2016
3a9d73d
consistent money display, check diff before post form, omit unnecessa…
hotay Jul 26, 2016
d0108c8
fix eslint errors unused import
hotay Jul 26, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/auth-hooks.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getAccount, logout } from 'actions/authActions';
import notifyHub from 'socket/notify';

/* istanbul ignore next */
export const requireAuth = (store) => (nextState, replace, done) => {
Expand All @@ -11,6 +12,11 @@ export const requireAuth = (store) => (nextState, replace, done) => {
pathname: '/login',
state: { nextPathname: nextState.location.pathname }
});
} else {
const socket = notifyHub.getInstance();
if (socket.disconnected) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connected and disconnected props are not part of the public API of socket.io and have changed in the past, it's up to you whether you still want to use them but I'd suggest keeping track of the state outside of the socket object and changing it in the event handlers.

socket.connect();
}
}

done();
Expand All @@ -30,6 +36,10 @@ export const requireAuth = (store) => (nextState, replace, done) => {
/* istanbul ignore next */
export const handleLogout = (store) => (nextState, replace) => {
store.dispatch(logout());
const socket = notifyHub.getInstance();
if (socket.connected) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the note above

socket.disconnect();
}
replace({
pathname: '/login'
});
Expand Down
6 changes: 4 additions & 2 deletions app/constants/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import merge from 'lodash/merge';

export const BASE_URL = 'https://mxfactorial.appspot.com/systemaccounting';
// export const BASE_URL = 'http://localhost:8080/systemaccounting'
// export const BASE_URL = 'https://mxfactorial.appspot.com/systemaccounting';
// export const SOCKET_URL = 'https://mxfactorial.appspot.com/';
export const BASE_URL = 'http://192.168.66.131:8081/systemaccounting';
export const SOCKET_URL = 'http://192.168.66.131:8081/';

export const GET_EMPTY_TRANSACTION = (key, info)=>(merge({
key,
Expand Down
45 changes: 45 additions & 0 deletions app/socket/notify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint no-console: 0 */
import { SOCKET_URL } from 'constants/index';
import io from 'socket.io-client';

const link = `${SOCKET_URL}notify`;

const notifyHub = (function () {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is client-side where they'll only have on socket on the /notify namespace, do you really need to wrap it in a function here? You're transpiling ES6 modules so you could simply keep the socket reference in the module without being exported. It would lead to cleaner code without the wrapped function.

Alternatively you could consider a class to wrap the socket.

let socket;

function init() {
socket = io(link);

socket.on('connect', function () {
console.log('connected', socket);
});

socket.on('child_added', function (data) {
console.log(data);
});

socket.on('connection_refused', function (err) {
console.log(err);
});

socket.on('disconnect', function () {
});

return socket;
}

return {
getInstance: function () {

if ( !socket ) {
socket = init();
}

return socket;
}

};

})();

export default notifyHub;
9 changes: 9 additions & 0 deletions firebase-db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var firebase = require('firebase');
var config = require('config.js');

firebase.initializeApp({
databaseURL: config.get('FIREBASE_URL'),
serviceAccount: config.get('FIREBASE_KEY_PATH')
});

module.exports = firebase.database();
8 changes: 6 additions & 2 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ var passport = require('passport');
var cors = require('cors');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;

var socketServer = require('socket-server');

var app = express();

var http = require('http').Server(app);

socketServer(http);

app.disable('etag');
app.set('trust proxy', true);
app.use(function (req, res, next) {
Expand Down Expand Up @@ -58,7 +62,7 @@ passport.use(new JwtStrategy(opts, function (jwt_payload, done) {

if (module === require.main) {
// Start the server
var server = app.listen(config.get('PORT'), function () {
var server = http.listen(config.get('PORT'), function () {
var port = server.address().port;
console.log('App listening on port %s', port);
});
Expand Down
25 changes: 25 additions & 0 deletions notification/hub.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
var authorize = require('socket-server/cookie-authorize');
var db = require('firebase-db');
var ref = db.ref('notification');

var socketMap = {};

var subscribe = function (socket) {
authorize(socket).then(function (username) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could break this out using the socketio-jwt middleware as discussed on gitter

socketMap[username] = socket;
}).catch(function (err) {
socket.emit('connection_refused', err);
});
};

ref.on('child_added', function (snapshot, prevChildKey) {
var notification = snapshot.val();
var socket = notification.to && socketMap[notification.to];
if (socket) {
socket.emit('child_added', notification);
}
});

module.exports = {
subscribe: subscribe
};
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"axios": "^0.12.0",
"body-parser": "^1.15.0",
"classnames": "^2.2.5",
"cookie": "^0.3.1",
"cors": "^2.7.1",
"crypto-js": "^3.1.6",
"es6-promise": "^3.2.1",
Expand Down Expand Up @@ -58,8 +59,8 @@
"redux-logger": "^2.6.1",
"redux-promise": "^0.5.3",
"reselect": "^2.5.3",
"socket.io": "^1.4.5",
"socket.io-client": "^1.4.5",
"socket.io": "^1.4.8",
"socket.io-client": "^1.4.8",
"superagent": "^1.8.3",
"url-search-params": "^0.5.0",
"validator": "^5.4.0"
Expand Down
26 changes: 26 additions & 0 deletions socket-server/cookie-authorize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var cookie = require('cookie');
var jwt = require('jsonwebtoken');

var config = require('config.js');

module.exports = function authorize(socket) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above, if you use socketio-jwt or some other alternative you can put the auth stuff in socker-server/index.js without making it messy. It will also give you easier management of failures.

return new Promise(function (resolve, reject) {
var cookies = cookie.parse(socket.request.headers.cookie);
if (cookies.token) {
jwt.verify(cookies.token.replace('JWT ', ''), config.get('API_SECRET'), function (err, decoded) {
if (!err) {
var username = decoded && decoded.username;
if (username) {
resolve(username);
} else {
reject('Invalid token');
}
} else {
reject(err);
}
});
} else {
reject('No token provided');
}
});
};
13 changes: 13 additions & 0 deletions socket-server/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
var notificationHub = require('notification/hub');

module.exports = function (httpServer) {
var io = require('socket.io')(httpServer);

io.of('/notify').on('connection', function (socket) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I normally keep a reference to the namespace when creating one as the namespace object has plenty of useful methods (especially server-side) when managing multiple clients.

const nsp = io.of('/notify');
nsp.on('connection', function (socket) {

notificationHub.subscribe(socket);

socket.on('disconnect', function () {

});
});
};