From 4befef5bf4468d5af3db7ac95d130ed7cff1d413 Mon Sep 17 00:00:00 2001 From: Edin Dazdarevic Date: Mon, 2 Mar 2015 07:49:36 +0100 Subject: [PATCH] login progress --- front-api/controllers/user.rb | 28 ++++- front-ui/app/actions/userActions.js | 33 ++++- front-ui/app/components/account/login.js | 128 ++++++++++++++++---- front-ui/app/components/account/register.js | 26 ++-- front-ui/app/constants/userConstants.js | 5 +- front-ui/app/models/login.js | 23 ++++ front-ui/app/stores/userStore.js | 36 +++--- front-ui/app/utils/validation.js | 17 +++ 8 files changed, 233 insertions(+), 63 deletions(-) create mode 100644 front-ui/app/models/login.js create mode 100644 front-ui/app/utils/validation.js diff --git a/front-api/controllers/user.rb b/front-api/controllers/user.rb index f2a0338..82058c5 100644 --- a/front-api/controllers/user.rb +++ b/front-api/controllers/user.rb @@ -1,7 +1,27 @@ -get '/user/auth' do - # TODO: do something that makes sense here - res = User.find_by(id: 1).try(:authenticate, 'spassword') # => false - res.to_json + +post '/user/login' do + request.body.rewind + login_details = JSON.parse(request.body.read) + + email = login_details['email'] + password = login_details['password'] + + res = User.find_by(email: email).try(:authenticate, password) # => false + if res + #TODO : encrypt this cookie + response.set_cookie('ribica_auth', :path=> '/', :httponly => true, :value=>res.id, :expires=>Time.now+100.year) + res.to_json(except: 'password_digest') + else + status 401 + {:error => "email ili lozinka neispravni!"}.to_json + end +end + +get '/user' do + auth = cookies['ribica_auth'] + if not auth.nil? + return User.find_by(id: auth).to_json(except: 'password_digest') + end end post '/user' do diff --git a/front-ui/app/actions/userActions.js b/front-ui/app/actions/userActions.js index 646cb92..1df9eb1 100644 --- a/front-ui/app/actions/userActions.js +++ b/front-ui/app/actions/userActions.js @@ -12,12 +12,9 @@ var UserActions = { user.save(null, { success: function() { - alert('saved!'); UserActions.registrationSuccess(); }, error: function(model, response, options) { - alert('error'); - console.log('error:', response); UserActions.registrationFailure(response); } }); @@ -32,8 +29,36 @@ var UserActions = { actionType: UserConstants.REGISTRATION_FAILURE, error: error }); - } + }, + userLogin: function(loginDetails) { + AppDispatcher.handleAction({ + actionType: UserConstants.USER_LOGIN, + loginDetails: loginDetails + }); + loginDetails.save(null, { + success: function(){ + alert('ok') + UserActions.loginSuccess(); + }, + + error: function(model, response, options){ + alert('error!'); + UserActions.loginFailure(response); + } + }); + }, + loginSuccess: function() { + AppDispatcher.handleAction({ + actionType: UserConstants.LOGIN_SUCCESS + }); + }, + loginFailure: function(error) { + AppDispatcher.handleAction({ + actionType: UserConstants.LOGIN_FAILURE, + error: error + }); + } }; module.exports = UserActions; diff --git a/front-ui/app/components/account/login.js b/front-ui/app/components/account/login.js index 1beccd5..75e6af5 100644 --- a/front-ui/app/components/account/login.js +++ b/front-ui/app/components/account/login.js @@ -1,41 +1,117 @@ var React = require("react"); var NavigationActions = require('../../actions/navigationActions'); +var UserActions = require('../../actions/userActions'); var Router = require('react-router'); var Link = Router.Link; -var Login = React.createClass({ - +var RibicaValidationMixin = require('../../components/shared/mixins/ribicaValidationMixin'); +var ValidationUtils = require('../../utils/validation.js'); +var LoginModel = require('../../models/login'); +var UserStore = require('../../stores/userStore'); +var Login = React.createClass({ + mixins: [RibicaValidationMixin], + componentDidMount:function() { + UserStore.addChangeListener(this.onUserStoreChange); + }, + componentWillUnmount: function() { + UserStore.removeChangeListener(this.onUserStoreChange); + }, + onUserStoreChange: function() { + var loginState = UserStore.getLoginState(); + + if (loginState.loggedIn) { + NavigationActions.goToHome(); + } else { + + this.setState({login: loginState}); + } + }, + getInitialState: function() { + return { + email: '', + password: '', + errors: {}, + login: UserStore.getLoginState() + }; + }, + validations: { + email:function(value) { + + if(!ValidationUtils.isValidEmail(value)) { + return ['Neispravna email adresa.']; + } + return []; + }, + password: function(value) { + if(!ValidationUtils.isValidRequired(value)) { + return ["Šifra je obavezna."]; + } + return []; + } + }, + renderErrorMessage: function(message){ + return (
{message}
) + }, + doLogin: function(e) { + + if(this.validate()) { + var loginInfo = new LoginModel({ + email: this.state.email, + password: this.state.password + }); + + UserActions.userLogin(loginInfo); + + } + + e.preventDefault(); + }, + renderLoginFailure: function() { + + var loginState = this.state.login; + if(!loginState.loggedIn) { + return (
{loginState.error}
) + } + + return (
) + }, render : function() { return (
-
- - Prijava -
-
+
+ + Prijava + {this.renderLoginFailure()} +
+
- - -
-
- - -
- - -
+ + - -
-
- + {this.getValidationMessages('email').map(this.renderErrorMessage)} +
+
+ + -Niste registrovani? Kliknite ovdje da se registrujete! - + {this.getValidationMessages('password').map(this.renderErrorMessage)} +
+ + +
-
-
); + +
+ + + Niste registrovani? Kliknite ovdje da se registrujete! + + + +
+ ); } -}) +}); + module.exports = Login; diff --git a/front-ui/app/components/account/register.js b/front-ui/app/components/account/register.js index 1b866a6..f321df5 100644 --- a/front-ui/app/components/account/register.js +++ b/front-ui/app/components/account/register.js @@ -3,7 +3,8 @@ var React = require("react/addons"), RibicaValidationMixin = require('../../components/shared/mixins/ribicaValidationMixin'), UserStore = require('../../stores/userStore'), NavigationActions = require('../../actions/navigationActions'), - UserActions = require('../../actions/userActions'); + UserActions = require('../../actions/userActions'), + ValidationUtils = require('../../utils/validation'); @@ -18,7 +19,7 @@ var Register = React.createClass({ password: '', passwordConfirmation: '', errors: {}, - registrationState: UserStore.getRegistrationState() + registration: UserStore.getRegistrationState() }; }, myBabyChange: function() { @@ -96,12 +97,12 @@ var Register = React.createClass({ }, validations: { firstName: function(value) { - if (!value || value === '') { + if (!ValidationUtils.isValidRequired(value)) { return ["Ime je obavezno."]; } }, password: function(value, callback) { - if(value === undefined || value === "") { + if(!ValidationUtils.isValidRequired(value)) { return ["Šifra je obavezna."]; } @@ -119,16 +120,14 @@ var Register = React.createClass({ } }, lastName : function(value) { - if (!value || value === '') { + if (!ValidationUtils.isValidRequired(value)) { return ["Prezime je obavezno."]; } }, - _emailRe: /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, _emailTimeoutId: null, email: function(value, callback) { - var validEmail = this._emailRe.test(value); - if (validEmail) { + if (ValidationUtils.isValidEmail(value)) { //clearTimeout(this._emailTimeoutId); //this._emailTimeoutId = setTimeout(function(){ @@ -162,11 +161,10 @@ var Register = React.createClass({ }, onUserStoreChange: function() { this.setState({ - registrationState: UserStore.getRegistrationState() + registration: UserStore.getRegistrationState() }); }, register: function(e) { - // TODO: move this to the UserRegistrationStore if(this.validate()) { var user = new UserRegistration({ first_name: this.state.firstName, @@ -186,24 +184,24 @@ var Register = React.createClass({ e.preventDefault(); }, renderRegistrationState: function() { - var rs = this.state.registrationState; + var rs = this.state.registration; if (!rs.performed) { return (
) } else if(rs.performed && !rs.success){ return (
- Desila se pogreska pri registraciji. Detalji greske su: + Desila se pogreška pri registraciji. Detalji greške su: {rs.error.responseJSON}
) } else if (rs.performed && rs.success) { return (
- Uspjesno ste se registrovali na Ribicu. Kliknite ovdje za nastavak. + Uspješno ste se registrovali na Ribicu. Kliknite ovdje za nastavak.
) } }, render : function() { var cx = React.addons.classSet; - var regSuccess = this.state.registrationState.performed && this.state.registrationState.success; + var regSuccess = this.state.registration.performed && this.state.registration.success; var classes = cx({ 'hide': regSuccess }); diff --git a/front-ui/app/constants/userConstants.js b/front-ui/app/constants/userConstants.js index 56f9c8a..eacd671 100644 --- a/front-ui/app/constants/userConstants.js +++ b/front-ui/app/constants/userConstants.js @@ -4,5 +4,8 @@ var keyMirror = require('react/lib/keyMirror'); module.exports = keyMirror({ REGISTER_USER : null, REGISTRATION_SUCCESS: null, - REGISTRATION_FAILURE: null + REGISTRATION_FAILURE: null, + USER_LOGIN: null, + LOGIN_SUCCESS: null, + LOGIN_FAILURE: null }); diff --git a/front-ui/app/models/login.js b/front-ui/app/models/login.js new file mode 100644 index 0000000..b92cf7c --- /dev/null +++ b/front-ui/app/models/login.js @@ -0,0 +1,23 @@ +var Backbone = require('backbone'); +var Globals = require('../globals'); + +var Login = Backbone.Model.extend({ + initialize: function() { + $.ajaxPrefilter( + function(options, originalOptions, jqXHR) { + options.xhrFields = { + withCredentials: true + } + } + ); + }, + + url : Globals.ApiUrl + '/user/login', + defaults : { + email: '', + password: '' + } +}); + + +module.exports = Login; diff --git a/front-ui/app/stores/userStore.js b/front-ui/app/stores/userStore.js index 18d9acd..db2cbbb 100644 --- a/front-ui/app/stores/userStore.js +++ b/front-ui/app/stores/userStore.js @@ -3,9 +3,8 @@ var EventEmitter = require('events').EventEmitter; var UserConstants = require('../constants/userConstants'); var _ = require('underscore'); - - var _registrationState = {}; +var _loginState = {}; var handleRegistrationSuccess = function() { _registrationState = { @@ -22,6 +21,18 @@ var handleRegistrationFailure = function(error) { }; }; +var handleLoginSuccess = function() { + _loginState = { + loggedIn: true + }; +}; + +var handleLoginFailure = function(error) { + _loginState = { + loggedIn: false, + error: error + }; +}; // Extend SectionStore with EventEmitter to add eventing capabilities var UserStore = _.extend({}, EventEmitter.prototype, { @@ -29,6 +40,9 @@ var UserStore = _.extend({}, EventEmitter.prototype, { //return _categoryDetails; return _registrationState; }, + getLoginState: function() { + return _loginState; + }, // Emit Change event emitChange: function() { console.log("Emmiting Section change!"); @@ -54,18 +68,6 @@ AppDispatcher.register(function(payload) { switch(action.actionType) { - // Respond to SELECT_ITEM action - //case SectionConstants.LOAD_SECTIONS: - //loadSections(); - //break; - - //case SectionConstants.SET_SECTION_HOVER: - //setHovered(action.section.get('id')); - //break; - - //case SectionConstants.UNSET_SECTION_HOVER: - //setHovered(''); - //break; case UserConstants.REGISTRATION_SUCCESS: handleRegistrationSuccess(); @@ -73,6 +75,12 @@ AppDispatcher.register(function(payload) { case UserConstants.REGISTRATION_FAILURE: handleRegistrationFailure(action.error); break; + case UserConstants.LOGIN_SUCCESS: + handleLoginSuccess(); + break; + case UserConstants.LOGIN_FAILURE: + handleLoginFailure(action.error); + break; default: return true; diff --git a/front-ui/app/utils/validation.js b/front-ui/app/utils/validation.js new file mode 100644 index 0000000..a73536f --- /dev/null +++ b/front-ui/app/utils/validation.js @@ -0,0 +1,17 @@ +var Validations = { +_emailRe: /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, +isValidEmail: function(value) { + return this._emailRe.test(value); + +}, + isValidRequired: function(value) { + if(value === undefined || value === "") { + return false; + } + return true; + + } + +}; + +module.exports = Validations;