Skip to content

wbyoung/admit-one-ember

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Admit One Ember

Release Version Build status Code Climate Coverage Status

Admit One adapter for Ember.

Usage

The following code shows example routes, models, and controllers to get you started using Admit One with Ember:

window.App = Ember.Application.create();
Ember.AdmitOne.setup();

App.Router.map(function() {
  this.route('signup');
  this.route('login');
  this.route('logout');
  this.route('profile');
});

App.ApplicationAdapter = DS.RESTAdapter.extend({
  namespace: 'api'
});

// authenticate any route
App.ProfileRoute = Ember.Route.extend(Ember.AdmitOne.AuthenticatedRouteMixin, {
});

App.User = DS.Model.extend({
  username: DS.attr('string'),
  password: DS.attr('string')
});

App.LoginRoute = Ember.Route.extend({
  beforeModel: function() {
    this._super();
    if (this.get('session').get('isAuthenticated')) {
      this.transitionTo('profile');
    }
  }
});

App.LoginController = Ember.Controller.extend({
  actions: {
    authenticate: function() {
      var self = this;
      var session = this.get('session');
      var credentials = this.getProperties('username', 'password');
      this.set('error', undefined);
      this.set('password', undefined);
      session.authenticate(credentials).then(function() {
        var attemptedTransition = self.get('attemptedTransition');
        if (attemptedTransition) {
          attemptedTransition.retry();
          self.set('attemptedTransition', null);
        } else {
          self.transitionToRoute('profile');
        }
      })
      .catch(function(error) {
        self.set('error', error);
      });
    }
  }
});

App.LogoutRoute = Ember.Route.extend({
  beforeModel: function() {
    this._super();
    var self = this;
    var session = this.get('session');
    return session.invalidate().finally(function() {
      self.transitionTo('index');
    });
  }
});

App.SignupRoute = Ember.Route.extend({
  model: function() {
    return this.store.createRecord('user');
  }
});

App.SignupController = Ember.ObjectController.extend({
  actions: {
    signup: function() {
      var session = this.get('session');
      var self = this;

      this.set('error', undefined);
      this.get('model').save() // create the user
      .then(function() {
        session.login({ username: self.get('model.username') });
        self.transitionToRoute('profile');
      })
      .catch(function(error) {
        if (error.responseJSON) { error = error.responseJSON; }
        if (error.error) { error = error.error; }
        self.set('error', error);
      });
    }
  }
});

In any template you can show login/logout links:

{{#if session.isAuthenticated }}
  {{#link-to 'profile'}}{{ session.username }}{{/link-to}}
  {{#link-to 'logout'}}Logout{{/link-to}}
{{else}}
  {{#link-to 'login'}}Login{{/link-to}}
{{/if}}

The login template:

<form {{action 'authenticate' on='submit'}}>
  {{input type="username" required="true" autofocus="true" placeholder="Username" value=username}}
  {{input type="password" required="true" autofocus="true" placeholder="Password" value=password}}
  <button type="submit">Log in</button>
  {{#if error}}<div>Error: {{error}}.</div>{{/if}}
</form>

The signup template:

<form {{action 'signup' on='submit'}}>
  {{input type="username" required="true" autofocus="true" placeholder="Username" value=username}}
  {{input type="password" required="true" autofocus="true" placeholder="Password" value=password}}
  <button type="submit">Sign up</button>
  {{#if error}}<div>Error: {{error}}.</div>{{/if}}
</form>

API

Ember.AdmitOne.setup([options])

options.api

Type: String|Object

If you provide a string, it will be used as the value for options.api.endpoint rather than specifying the resources used in the API. An object can be used, though, and each option is explained below.

options.api.endpoint

Type: String
Default: '/api'

Changing this value will affect the values of options.api.authenticate and options.api.invalidate as well.

options.api.authenticate

Type: String
Default: '/api/sessions'

The resource to use for authentication. A POST request will be made here to authenticate the user.

options.api.invalidate

Type: String
Default: '/api/sessions/current'

The resource to use for authentication. A DELETE request will be made here to invalidate the user's session.

options.containers

Type: Object
Default: undefined

Containers to use to initialize TinyAuth. See testing example below.


This adapter currently has the following restrictions on customization:

  • Authentication will always be a POST request.
  • Authentication will always send a session object. You may pass whatever object you'd like to session.authenticate, but if, for instance, you are sending an object with email and password, the request will come through with an object { session: { email: '', password: '' } }.
  • Invalidation will always be a DELETE request.

Pull requests to address these issues are welcome. :)

Usage in Tests

Set up your main application.js file like so:

window.App = Ember.Application.create();

App.AdmitOneContainers = {}; // overridable by tests
Ember.AdmitOne.setup({ containers: App.AdmitOneContainers });

Then, in a test helper file that is included before your test files, but after application.js, you can include the following:

// use ephemeral store for authentication data
Ember.Application.initializer({
  name: 'authentication-test',
  initialize: function(container, application) {
    var Ephemeral = Ember.AdmitOne.Storage.Base.extend({
      data: null,
      persist: function(data) { this.set('data', data); },
      restore: function() { return this.get('data'); },
      clear: function() { this.set('data'); }
    });
    application.register('auth-session-storage:ephemeral', Ephemeral);
    application.register('auth-session-storage:test', Ephemeral);
    App.AdmitOneContainers.storage = 'auth-session-storage:test';
  }
});

Faking Login

Add a test helper:

Ember.Test.registerHelper('applicationContainer', function(app) {
  return app.__container__;
});

Then in your tests, you can access the session and set the content to create an authenticated:

var container = applicationContainer();
var session = container.lookup('auth-session:main');
session.set('content', {
  username: 'fake-username',
  token: 'fake-token'
});

License

This project is distributed under the MIT license.

About

Admit One for Ember

Resources

License

Stars

Watchers

Forks

Packages

No packages published