38936

Ember SimpleAuth authenticate access to protected resources

Question:

I have an app where users can edit organisations in various 'pages'.

App.Router.map(function() { this.resource('organisation', {path: '/:orgname'}, function () { this.route('foo'); this.route('bar'); }); });

I want users to be able to view any organisation but the various pages should become editable if the user has admin rights over the organisation.

Organisations are editable based on some tricky logic handled by the server. The user model has an organisations attribute to reflect these admin rights. This is mirrored in the organisation object. On the server its a many-to-many table plus some other logic.

App.User = DS.Model.extend({ primaryKey: 'username', fullname: DS.attr('string'), username: DS.attr('string'), organisations: DS.hasMany('organisation', {async: true}) }); App.Organisation = DS.Model.extend({ primaryKey: 'orgname', orgname: DS.attr('string'), fullname: DS.attr('string', {defaultValue: 'Unnamed Organisation'}), description: DS.attr('string'), users: DS.hasMany('user', {async: true}), });

I am using Ember SimpleAuth to authenticate via a login page and to authorise requests to my API. I use a custom session to load in data for the authenticated user.

var CustomSession = SimpleAuth.Session.extend({ user: function() { var username = this.get('username'); if (!Ember.isEmpty(username)) { return this.container.lookup('store:main').find('user', username); } }.property('username') });

I have a controller like this which makes attributes editable in my template.

App.OrganisationController = Ember.Controller.extend({ actions: { ToggleEditFullname: function() { this.set('editingFullname', !this.get('editingFullname')); }, save: function() { this.set('editingFullname', false); return true; } } });

So in my template I do something like this...

{{#if editingFullname}} {{view Ember.TextField valueBinding="model.fullname" placeholder="Full name"}} <a href="#"><i {{action 'ToggleEditFullname'}} class="fa fa-times" title="cancel"></i></a> {{else}} {{#if model.fullname}} {{model.fullname}} {{else}} No name provided... {{/if}} {{#if session.isAuthenticated}} <a href="#"><i {{action 'ToggleEditFullname'}} class="fa fa-pencil" title="edit name"></i></a> {{/if}} {{/if}}

The key being the {{#if session.isAuthenticated}} statement. This ensures that users only get access to the restricted features if they are logged in.

All pretty normal so far (I think).

However, I want to be able to ask my session whether the current user is authorised to access the organisation in question. So I'd like to change the {{#if session.isAuthenticated}} to {{#if session.isAuthorised}} and have it check the current model/route against my data.

How can I best do this? Is there a better alternative? How do I protect resources individually?

P.S. Apologies for my English spelling of 'authorized'.

Answer1:

You'd want to compute from each organization so that it will be accurate on a per-model basis. So change

{{#if session.isAuthenticated}}

to

{{#if model.userCanAdminister}}

Then you can compute that straight off the model definition (this is probably not suitable for your async case, but could be workable) as seen here: <a href="http://emberjs.com/guides/models/defining-models/#toc_defining-attributes" rel="nofollow">http://emberjs.com/guides/models/defining-models/#toc_defining-attributes</a>

Or you can do it from the itemController (how I would do it for async). The logic for that should be pretty simple. Check if the current user is contained in the organization's user collection. Return a boolean from the computed property. Have that property bound to session.isAuthenticated and then users.@each.content or whatever might change in the organization in real-time.

Hope that helps!

Recommend

  • JAX-WS RI: Best way to implement a Method Interceptor
  • HTML select, correct option selected in DOM, but wrong item shown in firefox
  • In an Ember view, what's the best way to run code after the rerendering of an internal child vi
  • Ember.js Acceptance Testing not waiting for asynchronous data operations
  • Office365 authentication without login redirection
  • Emulate User Activity
  • Use query params of parent route to refresh the model in subroute
  • update record in database using jdatabase
  • Generating random numbers directly inside a .htaccess file
  • ASP.NET windows authentication should always ask for credentials
  • File extension of zlib zipped html page?
  • Authentication failed with Azure Active Directory in Windows Phone
  • Android device acting as an accessory
  • Switch to popup in python using selenium
  • How to pass a value from ASP.NET MVC controller to ASP.NET webforms control inside MVC View?
  • ASP.NET MVC 2 Preview 2 - display directory list rather than home/index
  • Jquery popup on mouse over of calendar control
  • Firefox Extension - Monitor refresh and change of tab
  • ADO and msqli connections very slow
  • How can the INSERT … ON CONFLICT (id) DO UPDATE… syntax be used with a sequence ID?
  • CakePHP 2.0.4 - findBy magic methods with conditions
  • QLPreviewController hide print button in ios6
  • How to attach a node.js readable stream to a Sendgrid email?
  • Django rest serializer Breaks when data exists
  • Highlight one bar in a series in highcharts?
  • Recording logins for password protected directories
  • DomPDF {PAGE_NUM} not on first page
  • Is there any way to access browser form field suggestions from JavaScript?
  • Uncaught Error: Could not find module `ember-load-initializers`
  • script to move all files from one location to another location
  • javascript inside java/jsp code
  • htaccess rewriting URLs with multiple forward slashes
  • Hazelcast - OperationTimeoutException
  • Display Images one by one with next and previous functionality
  • How to make Safari send if-modified-since header?
  • Web-crawler for facebook in python
  • RestKit - RKRequestDelegate does not exist
  • A cron job substitute?
  • Revoking OAuth Access Token Results in 404 Not Found
  • Getting error when using KSoap library to consume .NET web services