diff --git a/app/components/Login.jsx b/app/components/Login.jsx
new file mode 100644
index 0000000..53a22bf
--- /dev/null
+++ b/app/components/Login.jsx
@@ -0,0 +1,24 @@
+import React from 'react'
+
+export const Login = ({ login }) => (
+
+)
+
+import {login} from 'APP/app/reducers/auth'
+import {connect} from 'react-redux'
+
+export default connect (
+ state => ({}),
+ dispatch => ({
+ login(username, password) {
+ return dispatch(login(username, password))
+ }
+ }),
+) (Login)
\ No newline at end of file
diff --git a/app/components/Login.test.jsx b/app/components/Login.test.jsx
new file mode 100644
index 0000000..3ff0d11
--- /dev/null
+++ b/app/components/Login.test.jsx
@@ -0,0 +1,27 @@
+import React from 'react'
+import chai, {expect} from 'chai'
+chai.use(require('chai-enzyme'))
+import {shallow} from 'enzyme'
+
+import {Login} from './Login'
+
+describe('', () => {
+ let root
+ beforeEach('render the root', () =>
+ root = shallow()
+ )
+
+ it('shows a login form', () => {
+ expect(root.find('input[name="username"]')).to.have.length(1)
+ expect(root.find('input[name="password"]')).to.have.length(1)
+ })
+
+ it('shows a password field', () => {
+ expect(root.find('input[type="password"]')).to.have.length(1)
+ })
+
+ it('has a login button', () => {
+ const submit = root.find('input[type="submit"]')
+ expect(submit).to.have.length(1)
+ })
+})
\ No newline at end of file
diff --git a/app/main.jsx b/app/main.jsx
index e2b6cd0..287112b 100644
--- a/app/main.jsx
+++ b/app/main.jsx
@@ -1,14 +1,19 @@
'use strict'
import React from 'react'
+import {Router, Route, IndexRedirect, browserHistory} from 'react-router'
import {render} from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import Root from './components/Root'
+import Login from './components/Login'
render (
-
+
+
+
+
,
document.getElementById('main')
)
\ No newline at end of file
diff --git a/app/reducers/auth.jsx b/app/reducers/auth.jsx
new file mode 100644
index 0000000..b809c3f
--- /dev/null
+++ b/app/reducers/auth.jsx
@@ -0,0 +1,35 @@
+const reducer = (state=null, action) => {
+ switch(action.type) {
+ case AUTHENTICATED:
+ return action.user
+ }
+ return state
+}
+
+const AUTHENTICATED = 'AUTHENTICATED'
+export const authenticated = user => ({
+ type: AUTHENTICATED, user
+})
+
+import axios from 'axios'
+
+export const login = (username, password) =>
+ dispatch => {
+ const body = {username, password}
+ console.log('req body=', body)
+ return axios.post('/api/auth/local/login', body)
+ .then(() => dispatch(whoami()))
+ }
+
+export const whoami = () =>
+ dispatch =>
+ axios.get('/api/auth/whoami')
+ .then(response => {
+ const user = response.data
+ if (!Object.keys(user).length) {
+ return dispatch(authenticated(null))
+ }
+ dispatch(authenticated(user))
+ })
+
+export default reducer
\ No newline at end of file
diff --git a/app/reducers/index.jsx b/app/reducers/index.jsx
index 1eedf84..a81df20 100644
--- a/app/reducers/index.jsx
+++ b/app/reducers/index.jsx
@@ -1,11 +1,7 @@
import { combineReducers } from 'redux'
-const initialState = {}
-
-const rootReducer = function(state = initialState, action) {
- switch(action.type) {
- default: return state
- }
-};
+const rootReducer = combineReducers({
+ auth: require('./auth').default,
+})
export default rootReducer
diff --git a/app/store.jsx b/app/store.jsx
index 80efadd..0fc8ac2 100644
--- a/app/store.jsx
+++ b/app/store.jsx
@@ -3,4 +3,11 @@ import rootReducer from './reducers'
import createLogger from 'redux-logger'
import thunkMiddleware from 'redux-thunk'
-export default createStore(rootReducer, applyMiddleware(createLogger(), thunkMiddleware))
+import {whoami} from './reducers/auth'
+
+const store = createStore(rootReducer, applyMiddleware(createLogger(), thunkMiddleware))
+
+export default store
+
+// Set the auth info at start
+store.dispatch(whoami())
diff --git a/package.json b/package.json
index eb4d35b..3d3f04d 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
},
"homepage": "https://github.com/queerviolet/bones#readme",
"dependencies": {
+ "axios": "^0.15.2",
"babel-preset-stage-2": "^6.18.0",
"bcrypt": "^0.8.7",
"body-parser": "^1.15.2",
@@ -47,6 +48,7 @@
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-redux": "^4.4.5",
+ "react-router": "^3.0.0",
"redux": "^3.6.0",
"redux-logger": "^2.7.0",
"redux-thunk": "^2.1.0",
diff --git a/server/start.js b/server/start.js
index f305f39..5a14bdf 100644
--- a/server/start.js
+++ b/server/start.js
@@ -14,10 +14,10 @@ const pkg = require('APP')
const app = express()
-if (!pkg.isProduction) {
- // Logging middleware (dev & testing only)
+if (!pkg.isProduction && !pkg.isTesting) {
+ // Logging middleware (dev only)
app.use(require('volleyball'))
-}
+}
module.exports = app
// We'll store the whole session in a cookie