Open digitalplaywright opened 10 years ago
I'm done with refactoring! removing last lodash usage is simply a matter of creating a minimal lodash custom build and putting it in there... time to move on ;)
I would suggest that you look at PermitsRuleLoader
https://github.com/kristianmandrup/permit-authorize/blob/master/permit-rules-loader.ls
(still WIP - please play around with it!)
Please expand on this: "Ember Object model to express permits similarly to middleware in authorize-mw" (see below)
"can view helper" - see Readme. I introduced a canUser
helper method as an example usage. Ability now supports arguments such as currentAbility.can('read', book)
;)
load_and_authorize_resource
, hmm, I think this needs integration into the Ember model loading/routing somewhere... I think there is a kind of Ember "middleware" to hooks already (as I recall?) try asking on the forums.
FYI - ES6
https://github.com/gkz/LiveScript/issues/438#issuecomment-40949413
https://github.com/gkz/LiveScript/blob/0c7d891860f0246d0f140e4fb252fbff9c1f7dc2/test/generators.ls
npm install -g gkz/Livescript#generators
Sweet :)
Lots of great changes, and using LiveScript ES6 modules together with a transpiler seems very promising.
As @marcoow suggested an example app integrating Ember Simple Auth and permit-authorize would probably go a long way in showing how this can be used, with the great bonus that we can learn how to work with this in Ember through practical usage.
I am creating an example blog using Ember. The example is using an Ember App Kit + Ember Simple Auth client (https://github.com/digitalplaywright/eak-simple-auth-blog-client) and a companion rails+devise+doorkeeper API server (https://github.com/digitalplaywright/eak-simple-auth-blog-server). I think we should consider introducing permit-authorize into the mix to enforce who can create/update/delete blog posts.
I am happy playing around with permit-authorize as part of this and give you feedback. Do you have time to give me a boost by showing how you recommend integrating it and submit a pull request? Just showing a working permit file and a single working can action is sufficient. I can take it from there.
Please expand on this: "Ember Object model to express permits similarly to middleware in authorize-mw" (see below)
The point I am making is that we should make sure similar syntax works for Ember as under the usage example with middleware in https://github.com/kristianmandrup/authorize-mw#usage. That might already be there, might not, I am yet to use this in an Ember app. Should quickly get to that though if you think it is ready.
FYI - ES6
gkz/LiveScript#438 (comment)
This together with the es6 transpiler sounds like a great path forward.
Hi there,
I remember reading this article early last year when I was considering using Ember. I shelved it for many of the same reasons...
http://avitevet.blogspot.fr/2013/01/shelving-emberjs-was-authorization-in.html
But perhaps Ember is finally getting mature enough?
He suggests the following approach, introducing a handlebars helper can
Ember.Handlebars.registerBoundHelper 'can', (object, options) ->
# hook into permit-authorize here?
We can browsify the node src code using browserify
and make it available via bower
I guess. Perhaps is there an even simpler way?
As I understand the "Ember way", the routing is basically a "state machine" and so you should be authorized to change state. So I think it makes sense to create an AuthorizedRoute
mixin.
Then declaratively define for which routes it should be mixed in. For a route such as post/:id/edit
it should then authorize if the user can 'edit', 'Post'
for starters.
If the route loads the model from the server, the server could also be set up to do authorization (perhaps reusing auth rules if defined in JSON - see PermitRulesLoader
). If without server authorization, you could still do a "post load authorize check" to see if the user has access to do the action on that particular model instance: can 'edit', post
. This could f.ex depend on whether the user is the owner/author of that post. Now I remember this is a planned feature I never got around to implementing in my library. Feel free to try. It would be in rule-applier.ls
I'm sure.
I would actually prefer to have a Node server as a middleman before my Rails server. The Node server should ideally act as my outer layer, handling authentication (via passport) and authorization, and perhaps streaming (via Firehose.io and Web Sockets) so I get Real Time sync. I don't think using devise makes any sense in 2014, then rather something like sorcery.
Another model would be to integrate this authorization as a thin layer of the Model layer of Ember. Not sure how this is feasible, but is my idea in my current project (using Racer.js Real Time engine or Firehose.io on top a Rails API). Then you would enrich the client side models and have a proxy layer on top which examines what you want to do to the object before allowing the action perhaps?
So instead of allowing post.name = 5
you would instead have an API like post.edit 'name', 5
and then the edit
method would apply authorization and subsequent validation (middleware style!?).
When the models are updated server side and you load them, I guess you could have the models pass through an auth filter, or just have a custom handlebars filter that performs authorization.
So many options... I think you should draw different ideas on paper and see what makes sense ;)
I'm playing with ES6, traceur and 'LiveScript* now. Pretty cool :) Webstorm 8 is awesome! Even has spy.js integration now for super sweet tracing/debugging... :)
How to package permit-authorize
With regards to packaging I think @marcoow did a great job with Ember Simple Auth, and provide both release downloads as distributed .tar.gz (https://github.com/simplabs/ember-simple-auth/releases) and releases through bower (https://github.com/simplabs/ember-simple-auth-component). The bower repository seems like a repository with pre-built distributions. How this is built is probably up to your personal preference, but what Ember Simple Auth does is super-simple. He basically creates different tasks in grunt, where one of them is building a distribution: https://github.com/simplabs/ember-simple-auth/blob/master/Gruntfile.js
Integation with Ember
I think implementing the can helper as you suggest here and as you did in ember-beercan is probably a great first step. I also agree with your other suggestions, but I think we should get something working before we get advanced. We can look into crystalizing whatever we get in the end into a component so that others can easily use it. :)
Using node as API Server
Ember is agnostic to what you run as an API server, and we currently have an example rails+devise+doorkeeper API server and an example python API server. The goal is to have example API servers in many server-side frameworks, and adding node to that would be great. Personally I think fronting rails with node server side is an unnecessary complication, and that it is probably better to use either node or rails.
With regards to devise vs sorcery I am all for simplifying the examples. If the required functionality can be provided by something simpler I am all for it. In the end we can also have multiple examples so that people that actually are married to devise for whatever reason can see how to use that, and the ones that have no ties can use the best tool for the job.
About ember
I was also holding out due to the problems you mention. At this point though I have decided to dig into it since it now seems to have a good user-story, and components like Ember Simple Auth is starting to pop up and mature so you as a user can capitalize on Ember being Ember. I hope we can build a cancan-like component using your permit-authorize.
As a tip I find Ember App Kit very pleasant to develop in, and Ember CLI ( http://iamstef.net/ember-cli/ ) will soon make it even better (people already use it, but I don't like to use alpha software unless I have to). If you decide to get back into Ember then the Dash and Alfred tools are great for browsing/searching documentation.
Definitely seems like using Pre-1.0 Ember.js definitely was fraught with frustrations as the blog you linked to mentions. After 1.0 was released last August things has been stable and they have kept the stability promise so the APIs have the same semantics in between each version. And since they have a 6 week release schedule they've already shown with 5 releases that they keep their word in this respect. :) However, all is not ponies and rainbows. Ember Data is great and it is getting close to 1.0 (see http://emberjs.com/blog/2014/03/18/the-road-to-ember-data-1-0.html), but it is not there yet. Its good, but not fully baked.
Edit: need to learn how to spell.
Btw, by following the ember community best practices of using ES6, Ember and jshint I have actually started liking client-side web development in pure javascript. And Ember App Kit live reload in the browser while developing is awesome!
An example of how much this has improved the code when assuming the previous and the Ember Object model is this base object https://github.com/simplabs/ember-simple-auth/blob/master/packages/ember-simple-auth/lib/ember-simple-auth/authenticators/base.js and how it is implementation in https://github.com/simplabs/ember-simple-auth/blob/master/packages/ember-simple-auth-oauth2/lib/ember-simple-auth-oauth2/authenticators/oauth2.js. I am very thankful for the effort the javascript ecosystem and Ember community has put into making javascript development more pleasant.
" I have actually started liking client-side web development in pure javascript."
Totally, me too. Doing the client side from the server side (HAML templates, jQuery, etc. linking back to controllers for full page reload response/request) always sucked big time!
I am moving this discussion back here so that we don't spam the Ember Simple Auth issue tracker. I started work on using permit-authorize directly, but have not had much time to spend on it yet and got some errors. If you have time please see if you can get it to work in Ember by forking https://github.com/digitalplaywright/eak-simple-auth-blog-client/tree/post-authorize-experiment.
I'll also start looking at refactoring this to Ember tomorrow. However, for now I am only interested in the subset of permit-authorize that is equivalent to cancan. This is reasonable since the server acts like the authorization oracle by returning an error when the action is unauthorized at any rate. There might also be different consumers of the same API with wildly different can-rules that calls the same server-API.
How much work do you think it is to fork permit-authorize to extract the cancan subset (e.g only rules)? For simplicity I don't want the permit functionality and loading rules from the server. Is it easy to refactor it to this subset or is it better to just rewrite?
I don't understand why you want to duplicate cancan directly. The trouble with CanCan is exactly that it doesn't really scale to well. It is ok for simple rules, such as: one editor, one admin and one guest. Permits is a nice flexible abstraction which let's you package rules for each kind of user role, subject, context etc. by matching on the access-request. This permit mechanism could even take advantage of some caching mechanism as well as other things planned down the road...
To get CanCan equivalence, it would be using static rules only (see below). Then only use the rules.default:
key or the rules:
key directly (as I recall).
You can use the following and remove dynamic rule application.
# rule application test
describe 'Rules application' ->
# auto applies static rules by default (in init) as part of construction!
describe 'static rules application' ->
# permit.ls
class Permit
init: ->
@apply-rules!
@
apply-rules: (access-request, force) ->
@rule-applier(access-request).apply-rules!
rule-applier: (access-request) ->
access-request = {} unless typeof! access-request is 'Object'
new @rule-applier-class @rule-repo, @rules, access-request, @debugging
The Allower performs dynamic rule application. You can remove that part to have only static rules like CanCan.
# allowe.ls
test: (allow-type) ->
for permit in @permits
@debug 'test permit', allow-type, permit
@debug 'with rules', permit.rules
permit.debug-on! if @debugging
# apply dynamic rules (REMOVE!?)
permit.apply-rules @access-request #, true
@debug 'permit rules'
return true if permit[allow-type] @access-request
false
That should get you close to CanCan functionality. Then you just define one single permit, with one rules function which is evaluated statically on Permit construction. Then go from there to further simplify if you like.
I think it is easier to just show you what I am thinking of after I've made it work. I made good progress today, and will let you know when you have something to present. :)
Great! Looking forward to see it ;)
@kristianmandrup I just pushed out a first alpha of the Ember Declarative Authorization at https://github.com/digitalplaywright/ember-declarative-authorization.
I have a lot of improvements on the whiteboard, especially with regards to declaratively protecting a route. For instance, I need to figure out a generic way to get the current user. Please let me know what you think and if you have any comments or thoughts.
Cool :) I was actually wondering what kind of progress you had made and was just about to contact you. I think it would be nice to load rules from a Json file, was my idea... But never finished it. Cheers!
Generic way to get the current user? Should be stored as the user session currentUser on a singleton session service that is available or injected in controllers and the routes I think?
I must say that it looks VERY impressive what you have come up with. A pretty full-featured, simple yet flexible and elegant solution! Well done :)
Thanks. :)
With regards to returning current user we would ideally have something as nice as the rails 'current_user' like method. There should ideally be:
I am not sure if the way of doing this is an injection, since an injection is rather invasive and does not provide a current_user method in the contexts above, but at any rate it injections are probably part of the underlying mechanism. What should the injection be? 'session:current-user'?
Maybe a simpler solution would be to let users optionally define a function that returns the current user on the rules object? That is unfortunately not a generic solution, and only solves the problem for Ember Declarative Authorization.
Angular is designed around dependency injected. You typically define singletons that are injected where you need them. I'm pretty sure that Ember has a similar mechanism.
Yes, I am actually using dependency injection in this components. It's the register and lookup calls on the container.— Sent from Mailbox
On Tue, May 6, 2014 at 10:28 AM, Kristian Mandrup notifications@github.com wrote:
Angular is designed around dependency injected. You typically define singletons that are injected where you need them. I'm pretty sure that Ember has a similar mechanism.
Reply to this email directly or view it on GitHub: https://github.com/kristianmandrup/permit-authorize/issues/1#issuecomment-42332773
Go for DI ;) it is the design pattern for loose coupled systems and Apis, less intrusive not more IMO.
So to make the currentUser
method available, the developer should be required to inject a service into the "scope" to add the currentUser
to that scope and make it available. To make it available in the template is just exposing another model to the view I imagine. For controllers and routes it should be injected I think.
http://dmathieu.com/articles/development/emberjs-dependency-injection/
I talked to some ember core members and went for a simple solution as documented here https://github.com/digitalplaywright/ember-declarative-authorization#declaratively-protecting-a-route.
When declaratively protecting a route the user can optionally define a method called 'actor' on the route. The actor method is expected to return the current actor.
For the #can-do and #cannot-do components I think no change is necessary. Components in Ember are supposed to be context agnostic so providing the actor through the actor=something parameter seems to be the ember way.
Hi there,
I have now switched to using Ember myself :) Has come a long way since 15 months ago before 1.0 when it was in a state of flux.
I just made a major update to the permit-authorize project! It is now much cleaner (+ no dependencies!). It is available for use with both Bower and Node. It should be much easier to use now :)
I will be looking into your solution shortly and see how it can be integrated. Cheers!
Hi so , if i want to integrate authorization on ember, we should use permit-authorize or ember-declarative-authorization??
As soon as you are done with the refactoring and removal of dependencies I would like to touch base with you on Ember bindings. Your experience with ember-beercan should be very useful in this context. This is a preliminary list of features:
load_and_authorize_resource from cancan is very handy. Is it possible to implement something similar if we assume an authentication mechanism and data model?