1
votes

I am completely new to developing with the Sencha Touch 2 library. I followed this tutorial to help create a simple login script (http://miamicoder.com/2012/adding-a-login-screen-to-a-sencha-touch-application-part-2/). The one thing I am unsure about is how to check if the session token exists on the client side so that when they come back to the app the login screen doesn't show if they are authenticated.

app.js

Ext.application({
    name: 'RecruitTalkTouch',
    views: ['Login', 'MainMenu'],
    controllers: ['Login'],
    launch: function () {
      Ext.Viewport.add([
        { xtype: 'loginview' },
        { xtype: 'mainmenuview' }
      ]);
    }
});

Login.js Controller:

Ext.define('RecruitTalkTouch.controller.Login', {
  extend: 'Ext.app.Controller',
  config: {
    refs: {
      loginView: 'loginview',
      mainMenuView: 'mainmenuview'
    },
    control: {
      loginView: {
        signInCommand: 'onSignInCommand'
      },
      mainMenuView: {
        signOffCommand: 'onSignOffCommand'
      }
    }
  },
  onSignInCommand: function(view, username, password) {
    var me = this,
        loginView = me.getLoginView();

    if(username.length === 0 || password.length === 0) {
      loginView.showSignInFailedMessage('Please enter your username and password.');
      return;
    }

    loginView.setMasked({
      xtype: 'loadmask',
      message: 'Signing In...'
    });

    Ext.Ajax.request({
      url: 'http://localhost:3000/api/v1/sessions.json',
      method: 'POST',
      useDefaultXhrHeader: false,
      params: {
        login: username,
        password: password
      },
      success: function(resp) {
        var json = Ext.JSON.decode(resp.responseText);

        if(json.success === "true") {
          me.sessionToken = json.auth_token;
          me.signInSuccess();
        } else {
          me.signInFailure(json.message)
        }
      },
      failure: function(resp) {
        me.sessionToken = null;
        me.signInFailure('Login failed. Please try again');
      }
    });
  },
  signInSuccess: function() {
    console.log("Signed In");
    var loginView = this.getLoginView(),
        mainMenuView = this.getMainMenuView();

    loginView.setMasked(false);

    Ext.Viewport.animateActiveItem(mainMenuView, this.transition('slide', 'left'));
  },
  signInFailure: function(message) {
    var loginView = this.getLoginView();
    loginView.showSignInFailedMessage(message);
    loginView.setMasked(false);
  },
  transition: function(type, direction) {
    return { type: type, direction: direction };
  },
  onSignOffCommand: function() {
    var me = this;
    me.sessionToken = null;
    Ext.Viewport.animateActiveItem(this.getLoginView(), this.transition('slide', 'right'));
  }
});

Login.js View:

Ext.define('RecruitTalkTouch.view.Login', {
    extend: 'Ext.form.Panel',
    alias: "widget.loginview",
    requires: ['Ext.form.FieldSet', 'Ext.form.Password', 'Ext.Label', 'Ext.Button'],
    config: {
        title: 'Login',
        items: [
          {
            xtype: 'label',
            html: 'Login failed. Please enter the correct credentials.',
            itemId: 'signInFailed',
            hidden: true,
            hideAnimation: 'fadeOut',
            showAnimation: 'fadeIn'
          },
          {
            xtype: 'fieldset',
            title: 'Login',
            items: [
              {
                xtype: 'textfield',
                placeHolder: 'Username',
                itemId: 'userNameTextField',
                name: 'userNameTextField',
                required: true
              },
              {
                xtype: 'passwordfield',
                placeHolder: 'Password',
                itemId: 'passwordTextField',
                name: 'passwordTextField',
                required: true
              }
            ]
          },
          {
            xtype: 'button',
            itemId: 'logInButton',
            ui: 'action',
            padding: '10px',
            text: 'Log In'
          }
        ],
        listeners: [{
          delegate: '#logInButton',
          event: 'tap',
          fn: 'onLogInButtonTap'
        }]
    },
    onLogInButtonTap: function() {
      var me = this,
          usernameField = me.down('#userNameTextField'),
          passwordField = me.down('#passwordTextField'),
          label = me.down('#signInFailed'),
          username = usernameField.getValue(),
          password = passwordField.getValue();

      label.hide();

      var task = Ext.create('Ext.util.DelayedTask', function(){
        label.setHtml('');
        me.fireEvent('signInCommand', me, username, password);

        usernameField.setValue('');
        passwordField.setValue('');
      });

      task.delay(500);
    },
    showSignInFailedMessage: function(message) {
      var label = this.down('#signInFailed');
      label.setHtml(message);
      label.show();
    }
});
2

2 Answers

2
votes

You might find it easier to just add a check function on the server to check for a valid session. Even if the cookie is there, it doesn't mean they haven't logged out and the session cookie is sent back and forth with every request.

That said, if you want to access the cookies from the client, they are attached to the document as a single string value. You can access them at document.cookies. I would look at the documentation and source of the ExtJS cookies utility for some inspiration about how to go about finding your cookie in that string.

Ext.util.Cookies Documentation

Ext.util.Cookies Source

Essentially the process is to go through each letter in the cookie string, take a substring out to the length of the session key's name, see if it matches, then pull the data between the next equals sign and semicolon. Then you un-percent-encode the value and you're good to go.

Edit To ping the server, you just make an Ajax request somewhere along the application loading process before the first view is shown. The launch function is a pretty natural place I think:

Ext.application({
    name: 'App',

    requires: [],
    models: [],
    stores: [],
    views: [],
    controllers: [],

    ....

    launch: function () {
        //Check with the server
        Ext.Ajax.request({
            //Proxy Settings
            url: 'path/to/check/script.php',
            //Callbacks
            success: function (response, opts) {
                // process server response here
                response = Ext.JSON.decode(response.responseText);
                if(response && response.success === true) {
                    //Load the normal first view
                    Ext.Viewport.add(Ext.create('App.view.Main');
                } else {
                    //Load the login view
                    Ext.Viewport.add(Ext.create('App.view.LoginForm');
                }
            },
            failure: function (response, opts) {
                //Notify of network failure
            }
        });
    }
});

As far as what to do in the script on the server side, it is dependent on what language you are developing in and what you are authenticating against. If it's just a database of usernames and passwords then when the user first logs in, start a session, and store a session variable for their userID and password. In the check function, make sure they are still valid by first checking if a current session exists, and then re-authenticating against your database (in case you or someone else canceled their account while the session was still valid). Then just send back a json response that says whether or not they are logged in, and includes any relevant user information needed to make your app work.

0
votes

In Sencha Touch use:

var cookiestr = document.cookie.split('; ');
var cookieObjArr = new Array();

for (var i=0; i<cookiestr.length; ++i)
{
    if (i in cookiestr)
    {
        tmp = cookiestr[i].split('=');
        cookieObjArr.push({"key": tmp[0], "value": tmp[1]});
    }
}