├── .codeclimate.yml ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── package.json ├── src └── index.js ├── test └── null_spec.js └── webpack.config.js /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | languages: 2 | JavaScript: true 3 | # exclude_paths: 4 | # - lib/* -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | 2 | ### Specific to project ########## 3 | 4 | # Results of builds 5 | lib 6 | dist 7 | 8 | ### Standard .gitignore ########## 9 | 10 | ## Dependency directory 11 | 12 | # Deployed apps should consider commenting this line out: 13 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 14 | node_modules/ 15 | bower_components/ 16 | jspm_packages/ 17 | 18 | ## Node 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | # Optional npm cache directory 25 | .npm 26 | # Optional REPL history 27 | .node_repl_history 28 | 29 | ## Apple 30 | 31 | 32 | ## Git 33 | .git/ 34 | 35 | ## Temporary storage 36 | temp/ 37 | tmp/ 38 | unused/ 39 | 40 | ## Logs 41 | logs/ 42 | *.log 43 | npm-debug.log* 44 | 45 | ## Runtime data 46 | pids 47 | *.pid 48 | *.seed 49 | 50 | ## WebStorm editor 51 | .idea/ 52 | # IntelliJ 53 | /out/ 54 | 55 | ## Build 56 | 57 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 58 | .grunt 59 | 60 | ## Testing coverage 61 | 62 | # Directory for instrumented libs generated by jscoverage/JSCover 63 | lib-cov 64 | # Coverage directory used by tools like istanbul 65 | coverage 66 | # nyc test coverage 67 | .nyc_output 68 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "airbnb", 3 | "parser": "babel-eslint", 4 | "env": { 5 | "browser": true, 6 | "es6": true, 7 | "node": true, 8 | "mocha": true, 9 | }, 10 | "plugins": [ 11 | "jsdoc", 12 | ], 13 | "rules": { // override airbnb rules, add other rules 14 | "func-names": 0, 15 | "import/no-extraneous-dependencies": 0, 16 | "import/no-named-as-default": 0, 17 | "import/no-unresolved": ["error", { "ignore": ["^redux-form-material-ui"] }], // why complaints? 18 | "linebreak-style": 0, 19 | "max-statements": ["warn", 100], 20 | "no-use-before-define": ["off", { 21 | "functions": false, "classes": false 22 | }], 23 | "react/jsx-filename-extension": 0, 24 | "react/jsx-first-prop-new-line": 0, 25 | "jsdoc/check-param-names": 2, 26 | "jsdoc/check-tag-names": 2, 27 | "jsdoc/check-types": 2, // {type} starting with upper case letter is always OK 28 | "jsdoc/newline-after-description": [2, "always"], 29 | "jsdoc/require-description-complete-sentence": 0, // 2 prevents code in comments 30 | "jsdoc/require-hyphen-before-param-description": 2, 31 | "jsdoc/require-param": 2, 32 | "jsdoc/require-param-description": 2, 33 | "jsdoc/require-param-type": 2, 34 | "jsdoc/require-returns-description": 2, 35 | "jsdoc/require-returns-type": 2, 36 | }, 37 | "settings": { 38 | "jsdoc": { 39 | "tagNamePreference": { 40 | "param": "param", 41 | "returns": "returns", 42 | } 43 | } 44 | }, 45 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ### Specific to project ########## 3 | 4 | # build 5 | lib/ 6 | # checklists 7 | docs-secure/ 8 | # Authentication information 9 | *.secure.js 10 | 11 | ### Standard .gitignore ########## 12 | 13 | ## Dependency directory 14 | 15 | # Deployed apps should consider commenting this line out: 16 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 17 | node_modules/ 18 | bower_components/ 19 | jspm_packages/ 20 | 21 | ## Node 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | # Compiled binary addons (http://nodejs.org/api/addons.html) 26 | build/Release 27 | # Optional npm cache directory 28 | .npm 29 | # Optional REPL history 30 | .node_repl_history 31 | 32 | ## Apple 33 | 34 | 35 | ## Git 36 | .git/ 37 | 38 | ## Temporary storage 39 | temp/ 40 | tmp/ 41 | unused/ 42 | 43 | ## Logs 44 | logs/ 45 | *.log 46 | npm-debug.log* 47 | 48 | ## Runtime data 49 | pids 50 | *.pid 51 | *.seed 52 | 53 | ## WebStorm editor 54 | .idea/ 55 | # IntelliJ 56 | /out/ 57 | 58 | ## VSCode 59 | .vscode/ 60 | 61 | ## Build 62 | 63 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 64 | .grunt 65 | 66 | ## Testing coverage 67 | 68 | # Directory for instrumented libs generated by jscoverage/JSCover 69 | lib-cov 70 | # Coverage directory used by tools like istanbul 71 | coverage 72 | # nyc test coverage 73 | .nyc_output 74 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # npm will use .gitignore if .npmignore does not exist. we don't want this. 2 | # npm modules 3 | node_modules/ 4 | # ES6 source 5 | src/ 6 | # example 7 | example/ 8 | # coverage report 9 | coverage/ 10 | # checklists and standard files 11 | docs-secure/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - stable 5 | 6 | install: 7 | - npm install 8 | 9 | script: 10 | - npm run cover 11 | 12 | # Send coverage data to Coveralls 13 | after_script: "cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js" -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Notable changes to feathers-reduxify-authentication 2 | 3 | ## 0.1.1 4 | - Released package as it works with feathers-starter-react-redux-login-roles. 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to feathers-reduxify-authentication 2 | 3 | We would love for you to contribute code and help make Feathersjs even more productive than it is 4 | today! Here are some guidelines we would like you to follow: 5 | 6 | - [Question or Problem?](#question) 7 | - [Submission Guidelines](#submit) 8 | - [Coding Rules](#rules) 9 | 10 | ## Got a Question or Problem? 11 | 12 | If you have questions about how to *use* Feathersjs, you are likely to get effective help from 13 | the community here on [Slack](https://feathersjs.slack.com/messages/general/). 14 | 15 | ## Pull Requests (PR) 16 | 17 | ### Submitting a Pull Request 18 | Before you submit your Pull Request (PR) consider the following guidelines: 19 | 20 | * Search [GitHub](https://github.com/eddyystop/feathers-reduxify-authentication) for an open or closed PR 21 | that relates to your submission. You don't want to duplicate effort. 22 | * Make your changes in a new git branch: 23 | 24 | ```shell 25 | git checkout -b my-fix-branch master 26 | ``` 27 | 28 | * Create your patch, **including appropriate test cases**. 29 | * Follow our [Coding Rules](#rules). 30 | * Run the full test suite with `npm test` and ensure that all tests pass. 31 | * Commit your changes using a descriptive commit message. 32 | 33 | ```shell 34 | git commit -a 35 | ``` 36 | Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. 37 | 38 | * Push your branch to GitHub: 39 | 40 | ```shell 41 | git push origin my-fix-branch 42 | ``` 43 | 44 | * In GitHub, send a pull request. 45 | * If a change is suggested then: 46 | * Make the required updates. 47 | * Re-run the test suite to ensure tests are still passing. 48 | * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): 49 | 50 | ```shell 51 | git rebase master -i 52 | git push -f 53 | ``` 54 | 55 | That's it! Thank you for your contribution! 56 | 57 | ### After your pull request is merged 58 | 59 | After your pull request is merged, you can safely delete your branch and pull the changes 60 | from the main (upstream) repository: 61 | 62 | * Delete the remote branch on GitHub: 63 | 64 | ```shell 65 | git push origin --delete my-fix-branch 66 | ``` 67 | 68 | * Check out the master branch: 69 | 70 | ```shell 71 | git checkout master -f 72 | ``` 73 | 74 | * Delete the local branch: 75 | 76 | ```shell 77 | git branch -D my-fix-branch 78 | ``` 79 | 80 | * Update your master with the latest upstream version: 81 | 82 | ```shell 83 | git pull --ff upstream master 84 | ``` 85 | 86 | ## Code 87 | 88 | The most important need is that all code changes and contributions have unit tests. 89 | 90 | * Place unit tests in `/test`. They should require their code from `/lib`. 91 | * Unit tests should not require a build step. Feel free to use the latest Nodejs syntax. 92 | * The repo is set up to use Mocha and Chai. 93 | You can use any assertion style but most tests are presently using the assert style. 94 | * `npm test` will build, lint and test. 95 | This command needs to complete successfully before you submit a PR. 96 | * `npm run test:build` will build and test. 97 | * `npm run test:only` will just run the tests. 98 | 99 | The build: 100 | 101 | * Add your code to `/src`. The build step expands it into `/lib`. 102 | * Babel is set up to use plugin babel-preset-es2015. Add others if your really have to. 103 | 104 | Linting and docs: 105 | 106 | * The lint step uses ESLint with the AirBnB rule set. 107 | ESLint is the most popular JavaScript linting tool right now, 108 | and AirBnB’s style guide is the most widely-used style guide. 109 | * `npm run eslint` runs the linting. 110 | * Feel free to add JSDoc blocks for your new hooks as that helps us write documentation. 111 | * The code should immediately follow any JSDoc blocks. 112 | * JSDoc blocks are linted. 113 | Follow them by a blank line if you have linting issues, as that stops the block from being linted. 114 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Eddyystop 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # feathers-reduxify-authentication 2 | Wrap feathers-client.authentication so it works transparently with Redux, as well as authentication, authorization packages for React-Router. 3 | 4 | [![Build Status](https://travis-ci.org/eddyystop/feathers-reduxify-authentication.svg?branch=master)](https://travis-ci.org/eddyystop/feathers-reduxify-authentication) 5 | 6 | - Work with standard `feathers-client.authentication` on the client. 7 | - Dispatch feathers authentication and logout to Redux. 8 | - Integrate with `react-router` and `react-router-redux`. 9 | - Use popular Redux, React-Router authentication and authorization packages for React routing. 10 | 11 | ## Code Examples 12 | 13 | - [What we want to be able to do](#todo) 14 | - [Making feathers-client.authentication work with Redux](#reduxifying) 15 | - [Working example](#workingexample) 16 | 17 | ### What we want to be able to do 18 | 19 | This is typical code for React routing and permissions. 20 | 21 | ```javascript 22 | import { UserAuthWrapper } from 'redux-auth-wrapper'; 23 | 24 | // Define permissions 25 | const UserIsAuthenticated = UserAuthWrapper({ 26 | authSelector: (state) => state.auth.user, // BEING ABLE TO DO THIS IS ONE REASON TO USE THIS REPO 27 | predicate: user => user && user.isVerified, 28 | ... 29 | }); 30 | const UserIsAdmin = UserAuthWrapper({ 31 | authSelector: (state) => state.auth.user, // BEING ABLE TO DO THIS IS ONE REASON TO USE THIS REPO 32 | predicate: user => user && user.isVerified && user.roles && user.roles.indexOf('admin') !== -1, 33 | ... 34 | }); 35 | 36 | // React routing 37 | 38 | 39 | 40 | 43 | 46 | 47 | 48 | 49 | ``` 50 | 51 | `require('feathers-client').authentication` cannot be used as-is in this scenario 52 | or other scenarios involving Redux-based projects. 53 | 54 | `feathers-reduxify-authentication` wraps feathers-client.authentication 55 | so it behaves transparently as 100% compatible Redux code. 56 | 57 | ### Making feathers-client.authentication work with Redux 58 | 59 | You wrap `require('feathers-client').authentication`, insert the wrapper's reducer 60 | into Redux's `combineReducers`, and use the wrapper's action creators with Redux's `dispatch`. 61 | 62 | Voila, 100% Redux compatible with the current user retained in Redux's `store`. 63 | 64 | ```javascript 65 | import feathers from 'feathers-client'; 66 | import feathersReduxifyAuthentication from 'feathers-reduxify-authentication'; 67 | 68 | // Configure feathers-client 69 | const app = feathers(). ... .configure(feathers.authentication({ ... }); 70 | 71 | // Reduxify feathers-client.authentication 72 | feathersAuthentication = reduxifyAuthentication(app, 73 | { isUserAuthorized: (user) => user.isVerified } // WE INSIST USER IS 'verified' TO AUTHENTICATE 74 | ); 75 | 76 | // Add to Redux reducer 77 | const rootReducer = combineReducers({ ..., auth: feathersAuthentication.reducer, ...}); 78 | 79 | // Dispatch actions as needed. Params are the same as for feathers.authentication(). 80 | dispatch(feathersAuthentication.authenticate({ type: 'local', email, password })).then().catch(); 81 | dispatch(feathersAuthentication.logout()); 82 | ``` 83 | 84 | ### Working Example 85 | 86 | This package is used in 87 | [feathers-starter-react-redux-login-roles](https://github.com/eddyystop/feathers-starter-react-redux-login-roles) 88 | which implements full featured local authentication with user roles, email verification, 89 | forgotten passwords, etc. 90 | 91 | You can review how that project uses `feathers-reduxify-authentication`: 92 | - `client/feathers/index.js` configures feathers and reduxifies feathers-client.authentication. 93 | - `client/reducers/index.js` adds our authentication to Redux's reducers. 94 | Our current user will be stored at `state.auth.user`. 95 | - `client/index.js` sets up React routing and permissions. 96 | - `client/screens/Users/UserSignIn/FormContainer.js` 97 | both authenticates users and logs them out. 98 | 99 | ## Motivation 100 | 101 | - Feathers is a great real-time client-server framework. 102 | - Redux is a great state container for the front-end. 103 | - React is a great declarative UI. 104 | - React-Router is a complete routing library for React by React. 105 | - There are several packages 106 | which handle authentication and authorization for React-Router and Redux. 107 | 108 | This repo let's everyone work together easily. 109 | 110 | ## Installation 111 | 112 | Install [Nodejs](https://nodejs.org/en/). 113 | 114 | Run `npm install --save-dev feathers-reduxify-authentication` in your project folder. 115 | 116 | You can then: 117 | 118 | ```javascript 119 | // ES6 120 | import feathersReduxifyAuthentication from 'feathers-reduxify-authentication'; 121 | // ES5 122 | const feathersReduxifyAuthentication = require('feathers-reduxify-authentication'); 123 | ``` 124 | 125 | `/src` on GitHub contains the ES6 source. 126 | 127 | ## API Reference 128 | 129 | Each module is fully documented. 130 | 131 | Also see [Working example](#workingexample) above. 132 | 133 | ## Build 134 | 135 | `npm test` to transpile the ES6 code in `/src` to ES5 in `/lib`. 136 | 137 | ## Contributing 138 | 139 | [Contribute to this repo.](./CONTRIBUTING.md) 140 | 141 | [Guide to ideomatic contributing.](https://github.com/jonschlinkert/idiomatic-contributing) 142 | 143 | ## Change Log 144 | 145 | [List of notable changes.](./CHANGELOG.md) 146 | 147 | ## License 148 | 149 | MIT. See LICENSE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feathers-reduxify-authentication", 3 | "version": "1.0.0", 4 | "description": "Wrap feathers-client.authentication so it works with Redux, as well as authentication, authorization packages for React-Router.", 5 | "files": [ 6 | "index.js", 7 | "test" 8 | ], 9 | "main": "lib/", 10 | "directories": { 11 | "lib": "lib" 12 | }, 13 | "scripts": { 14 | "copy": "rm -rf lib/ && mkdir lib && cp -r src/ lib/", 15 | "babel": "babel src/ --out-dir lib --presets babel-preset-es2015,babel-preset-stage-0", 16 | "babel:watch": "babel src/ --watch --out-dir lib --presets babel-preset-es2015,babel-preset-stage-0", 17 | "mocha": "mocha test/ --reporter spec --compilers js:babel-core/register", 18 | "mocha:only": "mocha test/ --reporter spec", 19 | "eslint": "eslint src/. test/. --ext .js,.jsx .", 20 | "build": "npm run copy && npm run babel", 21 | "test": "npm run build && npm run eslint && npm run mocha", 22 | "test:build": "npm run build && npm run mocha", 23 | "test:only": "npm run eslint && npm run mocha:only", 24 | "cover": "node_modules/istanbul/lib/cli.js cover node_modules/mocha/bin/_mocha -- --reporter spec test/*", 25 | "watch": "npm run copy && npm run babel:watch", 26 | "git:push": "npm run build && git push origin && git push origin --tags", 27 | "npm:patch": "npm version patch && npm publish", 28 | "npm:minor": "npm version minor && npm publish", 29 | "npm:major": "npm version major && npm publish", 30 | "npm:updates": "npm-check-updates" 31 | }, 32 | "repository": { 33 | "type": "git", 34 | "url": "git+https://github.com/eddyystop/feathers-reduxify-authentication.git" 35 | }, 36 | "keywords": [ 37 | "feathers", 38 | "feathersjs", 39 | "authentication", 40 | "react-router", 41 | "redux" 42 | ], 43 | "author": "John Szwaronek ", 44 | "license": "MIT", 45 | "bugs": { 46 | "url": "https://github.com/eddyystop/feathers-reduxify-authentication/issues" 47 | }, 48 | "homepage": "https://github.com/eddyystop/feathers-reduxify-authentication#readme", 49 | "dependencies": { 50 | "debug": "^2.2.0", 51 | "object.assign": "^4.0.4" 52 | }, 53 | "devDependencies": { 54 | "babel-cli": "^6.14.0", 55 | "babel-core": "^6.14.0", 56 | "babel-eslint": "^6.1.2", 57 | "babel-loader": "^6.2.5", 58 | "babel-plugin-add-module-exports": "^0.2.1", 59 | "babel-plugin-transform-es2015-destructuring": "^6.9.0", 60 | "babel-plugin-transform-object-rest-spread": "^6.8.0", 61 | "babel-plugin-transform-runtime": "^6.15.0", 62 | "babel-preset-es2015": "^6.14.0", 63 | "babel-preset-stage-0": "^6.5.0", 64 | "chai": "^3.5.0", 65 | "coveralls": "^2.11.12", 66 | "eslint": "^3.5.0", 67 | "eslint-config-airbnb": "^10.0.0", 68 | "eslint-plugin-import": "^1.15.0", 69 | "eslint-plugin-jsdoc": "^2.3.1", 70 | "eslint-plugin-jsx-a11y": "^2.2.2", 71 | "eslint-plugin-react": "^6.2.1", 72 | "istanbul": "^0.4.5", 73 | "mocha": "^3.0.2", 74 | "redux-actions": "0.12.0" 75 | }, 76 | "engines": { 77 | "node": ">=5.0.0", 78 | "npm": ">=3.8.0" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 2 | import { createAction, handleActions } from 'redux-actions'; 3 | import makeDebug from 'debug'; 4 | 5 | // handles situation where a logout is dispatched while an authentication is in progress 6 | 7 | export default (app, options = {}) => { 8 | const debug = makeDebug('reducer:authentication'); 9 | debug('instantiate'); 10 | 11 | const defaults = { 12 | isError: 'isError', 13 | isLoading: 'isLoading', // s/b compatible with feathers-reduxify-service::getServicesStatus 14 | isSignedIn: 'isSignedIn', 15 | user: 'user', 16 | token: 'token', 17 | PENDING: 'PENDING', 18 | FULFILLED: 'FULFILLED', 19 | REJECTED: 'REJECTED', 20 | isUserAuthorized: (/* user */) => true, 21 | assign: { 22 | verifyExpires: undefined, 23 | verifyToken: undefined, 24 | resetExpires: undefined, 25 | resetToken: undefined, 26 | }, 27 | }; 28 | const opts = Object.assign({}, defaults, options); 29 | 30 | const reducer = { 31 | [`SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.PENDING}`]: (state, action) => { 32 | debug(`redux:SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.PENDING}`, action); 33 | return ({ 34 | ...state, 35 | [opts.isError]: null, 36 | [opts.isLoading]: true, 37 | [opts.isSignedIn]: false, 38 | [opts.user]: null, 39 | [opts.token]: null, 40 | ignorePendingAuth: false, 41 | }); 42 | }, 43 | 44 | [`SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.FULFILLED}`]: (state, action) => { 45 | debug(`redux:SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.FULFILLED}`, action); 46 | const user = action.payload.data; 47 | 48 | if (state.ignorePendingAuth) { 49 | // A logout was dispatched between the authentication being started and completed 50 | app.logout(); 51 | 52 | return { 53 | ...state, 54 | [opts.isError]: null, 55 | [opts.isLoading]: false, 56 | [opts.isSignedIn]: false, 57 | [opts.data]: null, 58 | [opts.token]: null, 59 | ignorePendingAuth: false, 60 | }; 61 | } 62 | 63 | if (!opts.isUserAuthorized(user)) { 64 | // feathers authenticated the user but the app is rejecting 65 | app.logout(); 66 | 67 | return { 68 | ...state, 69 | [opts.isError]: new Error('User is not verified.'), 70 | [opts.isLoading]: false, 71 | [opts.isSignedIn]: false, 72 | [opts.data]: null, 73 | [opts.token]: null, 74 | ignorePendingAuth: false, 75 | }; 76 | } 77 | 78 | return { 79 | ...state, 80 | [opts.isError]: null, 81 | [opts.isLoading]: false, 82 | [opts.isSignedIn]: true, 83 | [opts.user]: Object.assign({}, user, opts.assign), 84 | [opts.token]: action.payload[opts.token], 85 | ignorePendingAuth: false, 86 | }; 87 | }, 88 | 89 | [`SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.REJECTED}`]: (state, action) => { 90 | debug(`redux:SERVICES_AUTHENTICATION_AUTHENTICATE_${opts.REJECTED}`, action); 91 | return { 92 | ...state, 93 | // action.payload = { name: "NotFound", message: "No record found for id 'G6HJ45'", 94 | // code:404, className: "not-found" } 95 | [opts.isError]: action.payload, 96 | [opts.isLoading]: false, 97 | [opts.isSignedIn]: false, 98 | [opts.data]: null, 99 | [opts.token]: null, 100 | ignorePendingAuth: false, 101 | }; 102 | }, 103 | 104 | SERVICES_AUTHENTICATION_LOGOUT: (state, action) => { 105 | debug('redux:SERVICES_AUTHENTICATION_LOGOUT', action); 106 | app.logout(); 107 | 108 | return ({ 109 | ...state, 110 | [opts.isError]: null, 111 | [opts.isLoading]: null, 112 | [opts.isSignedIn]: false, 113 | [opts.user]: null, 114 | [opts.token]: null, 115 | // Ignore the result if an authentication has been started 116 | ignorePendingAuth: state.isLoading, 117 | }); 118 | }, 119 | 120 | SERVICES_AUTHENTICATION_USER: (state, action) => { 121 | debug('redux:SERVICES_AUTHENTICATION_USER', action); 122 | 123 | let user = state[opts.user]; 124 | if (user) { 125 | user = { ...user, ...action.payload }; 126 | } 127 | 128 | return ({ 129 | ...state, 130 | [opts.isError]: null, 131 | [opts.isLoading]: null, 132 | [opts.isSignedIn]: false, 133 | [opts.user]: user, 134 | // A logout may be dispatched between the authentication being started and completed 135 | ignorePendingAuth: false, 136 | }); 137 | }, 138 | }; 139 | 140 | // ACTION TYPES 141 | 142 | const AUTHENTICATE = 'SERVICES_AUTHENTICATION_AUTHENTICATE'; 143 | const LOGOUT = 'SERVICES_AUTHENTICATION_LOGOUT'; 144 | const USER = 'SERVICES_AUTHENTICATION_USER'; 145 | 146 | return { 147 | // ACTION CREATORS 148 | // Note: action.payload in reducer will have the value of .data below 149 | authenticate: createAction( 150 | AUTHENTICATE, (p) => ({ promise: app.authenticate(p), data: undefined }) 151 | ), 152 | logout: createAction(LOGOUT), 153 | user: createAction(USER), 154 | 155 | // REDUCER 156 | reducer: handleActions( 157 | reducer, 158 | { 159 | [opts.isError]: null, 160 | [opts.isLoading]: false, 161 | [opts.isSignedIn]: false, 162 | [opts.user]: null, 163 | ignorePendingAuth: false, 164 | } 165 | ), 166 | }; 167 | }; 168 | -------------------------------------------------------------------------------- /test/null_spec.js: -------------------------------------------------------------------------------- 1 | 2 | /* eslint no-shadow: 0, no-var: 0 */ 3 | 4 | describe('feathers-reduxify-authentication', () => { 5 | it('no tests yet', () => {}); 6 | }); 7 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | const webpack = require('webpack'); // eslint-disable-line import/no-unresolved 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | context: path.join(__dirname, './client'), 7 | entry: './index.js', 8 | output: { 9 | path: path.join(__dirname, './public/dist'), 10 | filename: 'bundle.js', 11 | }, 12 | module: { 13 | loaders: [ 14 | { 15 | test: /\.(js|jsx)$/, 16 | exclude: /node_modules/, 17 | loaders: [ 18 | 'babel-loader', 19 | ], 20 | }, 21 | ], 22 | }, 23 | resolve: { 24 | extensions: ['', '.js', '.jsx'], 25 | }, 26 | plugins: [ 27 | new webpack.DefinePlugin({ 28 | 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development') }, 29 | }), 30 | ], 31 | }; 32 | --------------------------------------------------------------------------------