Application Architecture with User Permissions for Routes

1,326 views
Skip to first unread message

Ruben Vreeken

unread,
Sep 7, 2012, 1:36:09 PM9/7/12
to backbone-...@googlegroups.com
Hey all,

I've been working on my first backbone application that's significantly larger then say, an over-sized Todo app.
In my application, users can be members of a group and each group is allowed access to different functionality.

Of course access to data is handled by a server back-end, but on the client I mainly validate if a user has the rights to visit a particular route. If they don't have access to that route, they'll get some sort of access-denied warning.

Currently the way I manage this, is by using an Authentication Module (App.Auth), and a Router component (App.Router).
Modules register their routes with the App.Router, and their required permissions with the App.Auth module.

Once a route is triggered, the router triggers an event to validate a triggered route like so:

this.routeIsValidated = $.Deferred();
App.vent.trigger("validate:route", route, this.routeIsValidated);

The App.Auth responds to this event, and checks if any required permissions are registered for this route.
If any of the required permissions are not met, it rejects the deferred object, otherwise it resolves it.
The router reacts then either triggers a secondary event for the approved route or follows instructions returned by the rejection:

this.routeIsValidated.done(function() {
  App.vent.trigger("navigate:" + route, args);
});

this.routeIsValidated.fail(function(route, options) {
  if(route) {
    var options = _.isObject(options) ? options : { trigger: true };
    that.navigate(route, options);
  }
  else {
    throw new Error('Route was rejected, but no alternative route was supplied');
  }
});

Modules can then respond tot he navigate:* events to further execute whatever is behind the route's url. 

While this works, it's probably not ideal. This architecture requires me to load all modules, regardless if the user will ever use them at all.

My question would be, does anyone here know a better alternative, which i could apply to future projects? 
In particular, is there something that allows me to only load certain parts of the application once I know for sure if the user is even allowed to use them?

I'm thinking I might be able to achieve this partly with the use of RequireJS, but I'm not sure how. Currently, if I list all the dependencies of all my AMD modules, RequireJS is going to end up loading all my modules anyways, regardless if I'll execute them, right? 
Is there maybe a way to define dependencies after the user's permissions have been checked and load only those modules they're actually going to need? Or is there an entirely different solution to this scenario?

--
Ruben Vreeken

saniko

unread,
Oct 16, 2012, 7:43:06 AM10/16/12
to backbone-...@googlegroups.com
Hi Ruben,
As you have mentioned all security tasks like authorization and authentication should be managed by the server, though i would like
to implement something similar.
Did you mange to solve the AMD issue?

Thanks

Ruben Vreeken

unread,
Oct 16, 2012, 8:13:29 AM10/16/12
to backbone-...@googlegroups.com
Hey,

You are right, all actual security concerns and authentications are managed by the server. However, there can still be some authentication checks on the front-end.
Imagine working with multiple user groups, each enabling different functionality. Your front-end code generates your UI, so even if this front-end code does not secure your application, you can still choose to expose certain parts of the UI, depending on the user group.

I did not manage to solve the AMD issue yet, I can't seem to find anything on delayed loading of AMD modules.

--
Ruben Vreeken

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marion...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.
To view this discussion on the web visit https://groups.google.com/d/msg/backbone-marionette/-/J8VU8f1PLRwJ.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

Ruben Vreeken

unread,
Oct 23, 2012, 2:07:10 PM10/23/12
to backbone-...@googlegroups.com
Wow, so there is a built-in requireJS module for on-demand loading after all? I wish I had known about that, that's exactly what I need! :D thanx!

On Tue, Oct 23, 2012 at 7:54 PM, Jeremy Mcleod <isoch...@gmail.com> wrote:
Can you not use something like this:

define("module.fetcher", [
   
'App.Auth',
   
'App.Router',
   
'require'     // this is a special built-in requireJS module that allows for on-demand loading
],
function(auth, router, require) {

   
var fetchedModule = null,
        hasRights
= false;
   
// some code that figures out if the user has rights to the requested route
   
if (hasRights) {
       
require('moduleName', function(module) {
            fetchedModule
= module;
       
}
   
}
   
return fetchedModule;

}

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marion...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.

Jeremy Mcleod

unread,
Oct 24, 2012, 12:02:49 PM10/24/12
to backbone-...@googlegroups.com
Sure thing... the only real issue is that the code I provided may not work, because the closure (the define method) will return immediately, but the value of fetchedModule might not have been resolved yet (also, require's first parameter should be an array, just like define()).  You should probably use a deferred object if you're going to attempt this kind of thing:

define("module.fetcher", [
    'jquery',

   
'App.Auth',
   
'App.Router',
   
'require'     // this is a special built-in requireJS module that allows for on-demand loading
],
function($, auth, router, require) {

   
var def = $.Deferred(),

        hasRights
= false;
   
// some code that figures out if the user has rights to the requested route
   
if (hasRights) {
       
require(["moduleName"], function(module) {

           
def.resolve(module);
       
}
   
}
   
return def;
}
To unsubscribe from this group, send email to backbone-marionette+unsub...@googlegroups.com.

Jeremy Mcleod

unread,
Oct 24, 2012, 12:04:56 PM10/24/12
to backbone-...@googlegroups.com
Whoops, also meant to link to requireJS docs regarding on-demand loading: http://requirejs.org/docs/api.html#multiversion

(plus I didn't close my define call in the sample code I provided, so watch out for that)

Ruben Vreeken

unread,
Oct 24, 2012, 12:20:57 PM10/24/12
to backbone-...@googlegroups.com
Thanks, I think I'll get this to work next time I need it. 

And wow.. 'multi-version support'... like that's ever gunna be the first phrase to pop up in a guy's mind when searching for on-demand module loading... :-/
Sure it makes sense for their example use-case, but a separate chapter explaining the basics of on-demand module loading would've been much, much easier.

ah well, at least the problem is solved now :)

To unsubscribe from this group, send email to backbone-marion...@googlegroups.com.

Jeremy

unread,
Oct 24, 2012, 6:06:35 PM10/24/12
to backbone-...@googlegroups.com
I know - honestly I think the documentation is requireJS's weakest link.  It's more like a series of use cases rather than a real API reference, and you have to kind of kludge together the big picture from a bunch of disparate examples.

That said, I have mad respect for James Burke... but not everyone is good at writing documentation.

I'm actually in the process of writing some Marionette documentation that's from a more holistic perspective than the existing per-module definition.  Marionette's docs assume you're very familiar with Backbone already, so they only enumerate the additional properties that Marionette provides, and there's not a lot of information about how to plug all the different bits together into a cohesive whole.  Right now it's only about half done, and I have to update it based on the new 1.0.0 beta releases, but hopefully in a week or so I'll have something publicly available.

In case you're curious, we're using these separate pieces together:

RequireJS 
    + Speck (loads DustJS templates)
Backbone.Relational
Backbone.Marionette (latest version)
Backbone.Marionette.Async
jQueryUI
jQueryMX (without $.Controller, $.View, and $.Model)
Amplify
DustJS-LinkedIn

The documentation won't get into the details of all these components, but I will be pushing a couple of new bits of code to github: I modified Speck to use view.serializeData() instead of this.model directly, and updated its HTML method to NOT automatically update the contents of view.$el upon compiling/rendering the template, and modified Backbone.Relational to work properly with requireJS.  I'll provide the links to those particular forks in the documentation once it goes up.

Derick Bailey

unread,
Oct 24, 2012, 6:25:18 PM10/24/12
to backbone-...@googlegroups.com

+1000 this sounds great! thank you! :)

Ruben Vreeken

unread,
Oct 25, 2012, 7:30:52 AM10/25/12
to backbone-...@googlegroups.com
Sounds very interesting, please do feel free to keep us updated!

Jeremy Mcleod

unread,
Dec 18, 2012, 10:42:37 AM12/18/12
to backbone-...@googlegroups.com
Well, obviously it's two months later and I still haven't gotten that documentation finished, but that's just because I've been slammed with actual implementation.  On the plus side, I have a FAR better understanding of backbone, Marionette, and several other crucial libraries now, so the quality of the documentation (once I actually finish it) should be much higher.  I'd post my WIP but being almost two months out of date there are several important changes that have been introduced since version 0.9.6, so I don't want to have any wrong or misleading information out there in the ether.  I'm still committed to finishing it though - I've grown to really appreciate not only the functionality but also the elegance of marionette (once I got past the pulling-my-hair-out stage, that is).
To unsubscribe from this group, send email to backbone-marionette+unsubscribe...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marionette+unsub...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.
To view this discussion on the web visit https://groups.google.com/d/msg/backbone-marionette/-/kFhez0DrTFgJ.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marionette+unsub...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marionette+unsub...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "Backbone.Marionette" group.
To post to this group, send email to backbone-...@googlegroups.com.
To unsubscribe from this group, send email to backbone-marionette+unsub...@googlegroups.com.
Visit this group at http://groups.google.com/group/backbone-marionette?hl=en.

Ruben Vreeken

unread,
Dec 18, 2012, 12:52:31 PM12/18/12
to backbone-...@googlegroups.com
Take your time bro, better late and great then quick and crappy ;)
Still lookin forward to the end-result though!
>>>>>>>>> backbone-marion...@googlegroups.com.
>>>>>>>>> Visit this group at
>>>>>>>>> http://groups.google.com/group/backbone-marionette?hl=en.
>>>>>>>>> To view this discussion on the web visit
>>>>>>>>> https://groups.google.com/d/msg/backbone-marionette/-/UClsKsSlb58J.
>>>>>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "Backbone.Marionette" group.
>>>>>> To post to this group, send email to backbone-...@googlegroups.com.
>>>>>> To unsubscribe from this group, send email to
>>>>>> backbone-marion...@googlegroups.com.
>>>>>> Visit this group at
>>>>>> http://groups.google.com/group/backbone-marionette?hl=en.
>>>>>> To view this discussion on the web visit
>>>>>> https://groups.google.com/d/msg/backbone-marionette/-/kFhez0DrTFgJ.
>>>>>>
>>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "Backbone.Marionette" group.
>>>>> To post to this group, send email to backbone-...@googlegroups.com.
>>>>> To unsubscribe from this group, send email to
>>>>> backbone-marion...@googlegroups.com.
>>>>> Visit this group at
>>>>> http://groups.google.com/group/backbone-marionette?hl=en.
>>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "Backbone.Marionette" group.
>>>> To post to this group, send email to backbone-...@googlegroups.com.
>>>> To unsubscribe from this group, send email to
>>>> backbone-marion...@googlegroups.com.
>>>> Visit this group at
>>>> http://groups.google.com/group/backbone-marionette?hl=en.
>>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>>
>>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google Groups
>>> "Backbone.Marionette" group.
>>> To post to this group, send email to backbone-...@googlegroups.com.
>>> To unsubscribe from this group, send email to
>>> backbone-marion...@googlegroups.com.
>>> Visit this group at
>>> http://groups.google.com/group/backbone-marionette?hl=en.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>>
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Backbone.Marionette" group.
> To post to this group, send email to backbone-...@googlegroups.com.
> To unsubscribe from this group, send email to
> backbone-marion...@googlegroups.com.
> Visit this group at
> http://groups.google.com/group/backbone-marionette?hl=en.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/backbone-marionette/-/bfsdPkym5I4J.
Reply all
Reply to author
Forward
0 new messages