diff --git a/.gitignore b/.gitignore index 91dfed8..a461bb4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store -node_modules \ No newline at end of file +node_modules +test/build diff --git a/cancan_backbone.coffee b/cancan_backbone.coffee index 180a633..96f6f3c 100644 --- a/cancan_backbone.coffee +++ b/cancan_backbone.coffee @@ -14,10 +14,12 @@ create: ["new"] update: ["edit"] - initialize: -> + initialize: (attributes, options = {}) -> + @options = options + @options.rule ?= options.rule unless _.isEmpty(@get("rules")) - @set "rules", _.map(@get("rules"), (rule) -> - new Rule(rule) + @set "rules", _.map(@get("rules"), (rule) => + new Rule(rule, @options.rule) ) return @@ -32,19 +34,23 @@ set_can: (action, subject, conditions) -> @get("rules").push new Rule( - base_behavior: true - action: action - subject: subject - conditions: conditions + { + base_behavior: true + action: action + subject: subject + conditions: conditions + }, @options.rule ) return set_cannot: (action, subject, conditions) -> @get("rules").push new Rule( - base_behavior: false - action: action - subject: subject - conditions: conditions + { + base_behavior: false + action: action + subject: subject + conditions: conditions + }, @options.rule ) return @@ -80,14 +86,20 @@ # Rule # ----------------------------------------------------------------- root.Rule = Backbone.Model.extend( - initialize: -> + initialize: (attributes, options = {}) -> + (@options = options).backboneClass ?= 'backboneClass' # or pass a function. + @set "actions", _.flatten([@get("action")]) if not @get("actions") and @get("action") @set "subjects", _.flatten([@get("subject")]) if not @get("subjects") and @get("subject") @set "conditions", {} unless @get("conditions") return backbone_class: (sub = null) -> - sub?.backboneClass + if _.isString(@options.backboneClass) + sub?[@options.backboneClass] + else if _.isFunction(@options.backboneClass) + @options.backboneClass(sub) + is_relevant: (action, subject) -> @matches_action(action) and @matches_subject(subject) diff --git a/package.json b/package.json index ea2eb19..201c6e2 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,9 @@ "title": "cancan-backbone", "name": "cancan-backbone", "version": "0.0.1", - "author": "Rune Madsen", + "author": { + "name": "Rune Madsen" + }, "description": "A library with Javascript bindings for the Ruby access control library CanCan", "repository": { "type": "git", @@ -13,7 +15,8 @@ "gutil": "~1.1.0", "gulp-coffee": "~2.0.1", "gulp-connect": "~2.0.5", - "gulp-sourcemaps": "~0.4.0" + "gulp-sourcemaps": "~0.4.0", + "node-qunit-phantomjs": "~0.2.1" }, "dependencies": {}, "bugs": { @@ -33,5 +36,9 @@ "ruby", "javascript" ], - "license": "MIT" + "license": "MIT", + "readme": "CanCan for Backbone.js\n======================\n\nReal-world web applications often rely on a combination of server-side and client-side code. If you're building a Rails application, you're probably relying on an access control library like CanCan, and a JS framework like Backbone.js for client side rendering.\n\nThis library makes it possible to export your CanCan abilities from Ruby to JS, and do the same access checks on the client side. This is great for doing UI-specific functionality, but should of course be backed by an API with tight access control.\n\nThe JS code was adapted directly from the CanCan Ruby code, but without Ruby-specific functionality like blocks, etc.\n\n\nCoverage\n--------\n\nSee the tests for coverage. Most of the CanCan functionality has been implemented, although only the action, subject and conditions will be used in the JS library. Your ability blocks will not work.\n\nModel associations will work, if you return the data in the main model response. This means that this rule:\n\n```\nability.set_can(\"read\", Comment, { user: { id: 1 }});\n```\n\nWill only work if your API json response for that comment model looks like this:\n\n```\n{\n\t\"body\" : \"This is a comment\",\n\t\"user\" : {\n\t\t\"id\" : 1\n\t}\n}\n```\n\nOn the API side, this will probably be way too slow for larger sets of associations, but that's just how it is right now. If I had time, I would probably try to implement some type of lazy-loading of associations.\n\n\nSetup\n-----\n\nFirst drop the cancan-backbone.js file into your assets folder.\n\nThen in your Backbone models, add a backboneClass class property, make sure you define it in the object that is the second parameter to Backbone.Model.extend. The second object is for classProperties:\n\n```\nvar Comment = Backbone.Model.extend({}, {backboneClass:\"Comment\"});\n```\n\nIn your controller/helper, implement a method that exports you abilities to JSON. This looks something like this:\n\n```\ndef ability_to_array(a)\n a.instance_variable_get(\"@rules\").collect do |rule| \n rule.instance_eval do\n {\n :base_behavior => @base_behavior,\n :subjects => @subjects.map(&:to_s),\n :actions => @actions.map(&:to_s),\n :conditions => @conditions\n }\n end\n end\nend\n```\n\n... and can be used like this:\n\n```\n@js_abilities = ability_to_array(current_ability)\n```\n\nIn your view, you can now pass the abilities into js:\n\n```\nvar ability = new Ability({rules : <%= @js_abilities.to_json.html_safe %>});\n````\n\nUsage\n------------\n\nIf you already loaded your abilities into your model, you're all ready to check for access:\n\n```\nability.can(\"read\", Comment);\nability.can(\"read\", \"custom\");\nability.can(\"read\", new Comment());\n```\n\nIf you want to set abilities from JS, you need to use the set_ functions:\n\n```\nability.set_can(\"read\", Comment, {id:1});\nability.set_can(\"read\", \"somethingelse\");\n```\n\nIt's also possible to pass the name of your Backbone models as strings. It will still work:\n\n```\nability.set_can(\"index\", \"Comment\");\nability.can(\"index\", Comment) // => true\nability.can(\"index\", \"Comment\") // => true\n\nability.set_can(\"index\", Post);\nability.can(\"index\", Post) // => true\nability.can(\"index\", \"Post\") // => true\n```\n\nObviously, you need the backboneClass of your backbone models to correspond to your Rails models.\n\nContributors\n------------\n\n- @runemadsen\n- @bogn\n", + "readmeFilename": "README.md", + "_id": "cancan-backbone@0.0.1", + "_from": "cancan-backbone@" } diff --git a/test/ability.coffee b/test/ability.coffee index b7d7765..f110257 100644 --- a/test/ability.coffee +++ b/test/ability.coffee @@ -1,4 +1,11 @@ do (Backbone) -> + User = Backbone.Model.extend( + modelName: 'user' + className: -> + up = @modelName.split('') + up.shift().toUpperCase() + up.join('') + ) + Post = Backbone.Model.extend( defaults: title: "Hello!" @@ -47,6 +54,24 @@ do (Backbone) -> ok a.cannot("new", new Comment(post_id: 2)) return + test "should be able to pass options to rule", -> + a = new Ability({}, {rule: backboneClass: 'foo'}) + ok a.options.rule.backboneClass is 'foo' + return + + test "should lookup default backboneClass by attribute `backboneClass`", -> + r = new Rule() + ok r.backbone_class(Post) is 'Post' + return + + test "should be able lookup backboneClass by passing a function", -> + lfcs = (sub) -> + up = (new sub).modelName.split(''); + up.shift().toUpperCase() + up.join('') + r = new Rule({}, {backboneClass: lfcs}) + ok r.backbone_class(User) is 'User' + return + test "should work on backbone model", -> a = new Ability() a.set_can "read", Post diff --git a/test/build/ability.js b/test/build/ability.js deleted file mode 100644 index 8d6f249..0000000 --- a/test/build/ability.js +++ /dev/null @@ -1,277 +0,0 @@ -(function() { - (function(Backbone) { - var Comment, Post; - Post = Backbone.Model.extend({ - defaults: { - title: "Hello!", - body: "This is a blog post!" - } - }, { - backboneClass: "Post" - }); - Comment = Backbone.Model.extend({ - defaults: { - body: "This is a comment!" - } - }, { - backboneClass: "Comment" - }); - test("should work when passing in existing object with rules and subjects", function() { - var a, existing; - existing = { - rules: [ - { - base_behavior: true, - subjects: ["Post"], - actions: ["index", "show"], - conditions: { - id: 1 - } - }, { - base_behavior: true, - subjects: ["Comment"], - actions: ["index", "show", "new", "create"], - conditions: { - post_id: 1 - } - } - ] - }; - a = new Ability(existing); - ok(a.can("index", Post)); - ok(a.can("index", new Post({ - id: 1 - }))); - ok(a.cannot("index", new Post({ - id: 2 - }))); - ok(a.cannot("destroy", Post)); - ok(a.can("new", Comment)); - ok(a.can("new", new Comment({ - post_id: 1 - }))); - ok(a.cannot("new", new Comment({ - post_id: 2 - }))); - }); - test("should work on backbone model", function() { - var a; - a = new Ability(); - a.set_can("read", Post); - ok(a.can("read", Post)); - }); - test("should work on backbone model name as string", function() { - var a; - a = new Ability(); - a.set_can("read", Post); - ok(a.can("read", "Post")); - }); - test("should work on backbone model name as string the other way around", function() { - var a; - a = new Ability(); - a.set_can("read", "Post"); - ok(a.can("read", Post)); - }); - test("should be able to 'read' anything", function() { - var a; - a = new Ability(); - a.set_can("read", "all"); - ok(a.can("read", String)); - ok(a.can("read", 123)); - }); - test("should not have permission to do something it doesn't know about", function() { - var a; - a = new Ability(); - ok(a.cannot("foodfight", String)); - }); - test("should alias update or destroy actions to modify action", function() { - var a; - a = new Ability(); - a.alias_action(["update", "destroy"], "modify"); - a.set_can("modify", "all"); - ok(a.can("update", 123)); - ok(a.can("destroy", 123)); - }); - test("should allow deeply nested aliased actions", function() { - var a; - a = new Ability(); - a.alias_action(["increment"], "sort"); - a.alias_action(["sort"], "modify"); - a.set_can("modify", "all"); - ok(a.can("increment", 123)); - }); - test("should raise an Error if alias target is an exist action", function() { - var a; - a = new Ability(); - throws((function() { - a.alias_action(["show"], "show"); - }), "You can't specify target (show) as alias because it is real action name"); - }); - test("should automatically alias index and show into read calls", function() { - var a; - a = new Ability(); - a.set_can("read", "all"); - ok(a.can("index", 123)); - ok(a.can("show", 123)); - }); - test("should automatically alias new and edit into create and update respectively", function() { - var a; - a = new Ability(); - a.set_can("create", "all"); - a.set_can("update", "all"); - ok(a.can("new", 123)); - ok(a.can("edit", 123)); - }); - test("should offer cannot? method which is simply invert of can?", function() { - var a; - a = new Ability(); - ok(a.cannot("tie", String)); - }); - test("should be able to specify multiple actions and match any", function() { - var a; - a = new Ability(); - a.set_can(["read", "update"], "all"); - ok(a.can("read", 123)); - ok(a.can("update", 123)); - ok(a.cannot("count", 123)); - }); - test("should be able to specify multiple classes and match any instances", function() { - var a; - a = new Ability(); - a.set_can("update", [Post, Comment]); - ok(a.can("update", new Post())); - ok(a.can("update", new Comment())); - ok(a.cannot("update", new RegExp())); - }); - test("should be able to specify multiple classes and match any classes", function() { - var a; - a = new Ability(); - a.set_can("update", [Post, Comment]); - ok(a.can("update", Post)); - ok(a.can("update", Comment)); - ok(a.cannot("update", RegExp)); - }); - test("should support custom objects in the rule", function() { - var a; - a = new Ability(); - a.set_can("read", "stats"); - ok(a.can("read", "stats")); - ok(a.cannot("update", "stats")); - ok(a.cannot("read", "nonstats")); - }); - test("should support 'cannot' method to define what user cannot do", function() { - var a; - a = new Ability(); - a.set_can("read", "all"); - a.set_cannot("read", Post); - ok(a.can("read", "foo")); - ok(a.cannot("read", new Post())); - }); - test("should append aliased actions", function() { - var a; - a = new Ability(); - a.alias_action(["update"], "modify"); - a.alias_action(["destroy"], "modify"); - ok(_.isEqual(["update", "destroy"], a.get("aliased_actions")["modify"])); - }); - test("should clear aliased actions", function() { - var a; - a = new Ability(); - a.alias_action(["update"], "modify"); - a.clear_aliased_actions(); - equal(undefined, a.get("aliased_actions")["modify"]); - }); - test("should use conditions as third parameter and determine abilities from it", function() { - var a; - a = new Ability(); - a.set_can("read", Post, { - title: "Hello" - }); - ok(a.can("read", new Post({ - title: "Hello" - }))); - ok(a.cannot("read", new Post({ - title: "Goodbye" - }))); - ok(a.can("read", Post)); - }); - test("should allow an array of options in conditions hash", function() { - var a; - a = new Ability(); - a.set_can("read", Post, { - tags: ["awesome", "cool", "pretty"] - }); - ok(a.can("read", new Post({ - tags: ["awesome", "cool", "pretty"] - }))); - ok(a.cannot("read", new Post({ - tags: ["ugly", "bad"] - }))); - ok(a.can("read", Post)); - }); - test("should allow nested hashes in conditions hash", function() { - var a; - a = new Ability(); - a.set_can("read", Post, { - comment: { - user_id: 1 - } - }); - ok(a.can("read", new Post({ - comment: { - user_id: 1 - } - }))); - ok(a.cannot("read", new Post({ - comment: { - user_id: 2 - } - }))); - }); - test("should allow false values conditions hash", function() { - var a; - a = new Ability(); - a.set_can("read", Post, { - comment: { - is_protected: false - } - }); - ok(a.can("read", new Post({ - comment: { - is_protected: false - } - }))); - ok(a.cannot("read", new Post({ - comment: { - is_protected: true - } - }))); - }); - test("should not stop at cannot definition when comparing class", function() { - var a; - a = new Ability(); - a.set_can("read", Post); - a.set_cannot("read", Post, { - id: 1 - }); - ok(a.can("read", new Post({ - id: 2 - }))); - ok(a.cannot("read", new Post({ - id: 1 - }))); - ok(a.can("read", Post)); - }); - return test("should stop at cannot definition when no hash is present", function() { - var a; - a = new Ability(); - a.set_can("read", "all"); - a.set_cannot("read", Post); - ok(a.cannot("read", new Post())); - ok(a.cannot("read", Post)); - }); - })(Backbone); - -}).call(this); - -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJpbGl0eS5qcyIsInNvdXJjZXMiOlsiYWJpbGl0eS5jb2ZmZWUiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQSxFQUFHLENBQUEsU0FBQyxRQUFELEdBQUE7QUFDRCxRQUFBLGFBQUE7QUFBQSxJQUFBLElBQUEsR0FBTyxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQWYsQ0FDTDtBQUFBLE1BQUEsUUFBQSxFQUNFO0FBQUEsUUFBQSxLQUFBLEVBQU8sUUFBUDtBQUFBLFFBQ0EsSUFBQSxFQUFNLHNCQUROO09BREY7S0FESyxFQUtMO0FBQUEsTUFBQSxhQUFBLEVBQWUsTUFBZjtLQUxLLENBQVAsQ0FBQTtBQUFBLElBT0EsT0FBQSxHQUFVLFFBQVEsQ0FBQyxLQUFLLENBQUMsTUFBZixDQUNSO0FBQUEsTUFBQSxRQUFBLEVBQ0U7QUFBQSxRQUFBLElBQUEsRUFBTSxvQkFBTjtPQURGO0tBRFEsRUFJUjtBQUFBLE1BQUEsYUFBQSxFQUFlLFNBQWY7S0FKUSxDQVBWLENBQUE7QUFBQSxJQWFBLElBQUEsQ0FBSyxxRUFBTCxFQUE0RSxTQUFBLEdBQUE7QUFDMUUsVUFBQSxXQUFBO0FBQUEsTUFBQSxRQUFBLEdBQVc7QUFBQSxRQUFBLEtBQUEsRUFBTztVQUNoQjtBQUFBLFlBQ0UsYUFBQSxFQUFlLElBRGpCO0FBQUEsWUFFRSxRQUFBLEVBQVUsQ0FBQyxNQUFELENBRlo7QUFBQSxZQUdFLE9BQUEsRUFBUyxDQUNQLE9BRE8sRUFFUCxNQUZPLENBSFg7QUFBQSxZQU9FLFVBQUEsRUFDRTtBQUFBLGNBQUEsRUFBQSxFQUFJLENBQUo7YUFSSjtXQURnQixFQVdoQjtBQUFBLFlBQ0UsYUFBQSxFQUFlLElBRGpCO0FBQUEsWUFFRSxRQUFBLEVBQVUsQ0FBQyxTQUFELENBRlo7QUFBQSxZQUdFLE9BQUEsRUFBUyxDQUNQLE9BRE8sRUFFUCxNQUZPLEVBR1AsS0FITyxFQUlQLFFBSk8sQ0FIWDtBQUFBLFlBU0UsVUFBQSxFQUNFO0FBQUEsY0FBQSxPQUFBLEVBQVMs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QUFTLE1BQVQsRUFBcUIsSUFBQSxJQUFBLENBQUEsQ0FBckIsQ0FBSCxDQUhBLENBQUE7QUFBQSxNQUlBLEVBQUEsQ0FBRyxDQUFDLENBQUMsTUFBRixDQUFTLE1BQVQsRUFBaUIsSUFBakIsQ0FBSCxDQUpBLENBRCtEO0lBQUEsQ0FBakUsRUF0UUM7RUFBQSxDQUFBLENBQUgsQ0FBSSxRQUFKLENBQUEsQ0FBQTtBQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZG8gKEJhY2tib25lKSAtPlxuICBQb3N0ID0gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKFxuICAgIGRlZmF1bHRzOlxuICAgICAgdGl0bGU6IFwiSGVsbG8hXCJcbiAgICAgIGJvZHk6IFwiVGhpcyBpcyBhIGJsb2cgcG9zdCFcIlxuICAsXG4gICAgYmFja2JvbmVDbGFzczogXCJQb3N0XCJcbiAgKVxuICBDb21tZW50ID0gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKFxuICAgIGRlZmF1bHRzOlxuICAgICAgYm9keTogXCJUaGlzIGlzIGEgY29tbWVudCFcIlxuICAsXG4gICAgYmFja2JvbmVDbGFzczogXCJDb21tZW50XCJcbiAgKVxuICB0ZXN0IFwic2hvdWxkIHdvcmsgd2hlbiBwYXNzaW5nIGluIGV4aXN0aW5nIG9iamVjdCB3aXRoIHJ1bGVzIGFuZCBzdWJqZWN0c1wiLCAtPlxuICAgIGV4aXN0aW5nID0gcnVsZXM6IFtcbiAgICAgIHtcbiAgICAgICAgYmFzZV9iZWhhdmlvcjogdHJ1ZVxuICAgICAgICBzdWJqZWN0czogW1wiUG9zdFwiXVxuICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgXCJpbmRleFwiXG4gICAgICAgICAgXCJzaG93XCJcbiAgICAgICAgXVxuICAgICAgICBjb25kaXRpb25zOlxuICAgICAgICAgIGlkOiAxXG4gICAgICB9XG4gICAgICB7XG4gICAgICAgIGJhc2VfYmVoYXZpb3I6IHRydWVcbiAgICAgICAgc3ViamVjdHM6IFtcIkNvbW1lbnRcIl1cbiAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgIFwiaW5kZXhcIlxuICAgICAgICAgIFwic2hvd1wiXG4gICAgICAgICAgXCJuZXdcIlxuICAgICAgICAgIFwiY3JlYXRlXCJcbiAgICAgICAgXVxuICAgICAgICBjb25kaXRpb25zOlxuICAgICAgICAgIHBvc3RfaWQ6IDFcbiAgICAgIH1cbiAgICBdXG4gICAgYSA9IG5ldyBBYmlsaXR5KGV4aXN0aW5nKVxuICAgIG9rIGEuY2FuKFwiaW5kZXhcIiwgUG9zdClcbiAgICBvayBhLmNhbihcImluZGV4XCIsIG5ldyBQb3N0KGlkOiAxKSlcbiAgICBvayBhLmNhbm5vdChcImluZGV4XCIsIG5ldyBQb3N0KGlkOiAyKSlcbiAgICBvayBhLmNhbm5vdChcImRlc3Ryb3lcIiwgUG9zdClcbiAgICBvayBhLmNhbihcIm5ld1wiLCBDb21tZW50KVxuICAgIG9rIGEuY2FuKFwibmV3XCIsIG5ldyBDb21tZW50KHBvc3RfaWQ6IDEpKVxuICAgIG9rIGEuY2Fubm90KFwibmV3XCIsIG5ldyBDb21tZW50KHBvc3RfaWQ6IDIpKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgd29yayBvbiBiYWNrYm9uZSBtb2RlbFwiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBQb3N0XG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFBvc3QpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCB3b3JrIG9uIGJhY2tib25lIG1vZGVsIG5hbWUgYXMgc3RyaW5nXCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLnNldF9jYW4gXCJyZWFkXCIsIFBvc3RcbiAgICBvayBhLmNhbihcInJlYWRcIiwgXCJQb3N0XCIpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCB3b3JrIG9uIGJhY2tib25lIG1vZGVsIG5hbWUgYXMgc3RyaW5nIHRoZSBvdGhlciB3YXkgYXJvdW5kXCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLnNldF9jYW4gXCJyZWFkXCIsIFwiUG9zdFwiXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFBvc3QpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBiZSBhYmxlIHRvICdyZWFkJyBhbnl0aGluZ1wiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBcImFsbFwiXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFN0cmluZylcbiAgICBvayBhLmNhbihcInJlYWRcIiwgMTIzKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgbm90IGhhdmUgcGVybWlzc2lvbiB0byBkbyBzb21ldGhpbmcgaXQgZG9lc24ndCBrbm93IGFib3V0XCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBvayBhLmNhbm5vdChcImZvb2RmaWdodFwiLCBTdHJpbmcpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBhbGlhcyB1cGRhdGUgb3IgZGVzdHJveSBhY3Rpb25zIHRvIG1vZGlmeSBhY3Rpb25cIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuYWxpYXNfYWN0aW9uIFtcbiAgICAgIFwidXBkYXRlXCJcbiAgICAgIFwiZGVzdHJveVwiXG4gICAgXSwgXCJtb2RpZnlcIlxuICAgIGEuc2V0X2NhbiBcIm1vZGlmeVwiLCBcImFsbFwiXG4gICAgb2sgYS5jYW4oXCJ1cGRhdGVcIiwgMTIzKVxuICAgIG9rIGEuY2FuKFwiZGVzdHJveVwiLCAxMjMpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBhbGxvdyBkZWVwbHkgbmVzdGVkIGFsaWFzZWQgYWN0aW9uc1wiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5hbGlhc19hY3Rpb24gW1wiaW5jcmVtZW50XCJdLCBcInNvcnRcIlxuICAgIGEuYWxpYXNfYWN0aW9uIFtcInNvcnRcIl0sIFwibW9kaWZ5XCJcbiAgICBhLnNldF9jYW4gXCJtb2RpZnlcIiwgXCJhbGxcIlxuICAgIG9rIGEuY2FuKFwiaW5jcmVtZW50XCIsIDEyMylcbiAgICByZXR1cm5cblxuICB0ZXN0IFwic2hvdWxkIHJhaXNlIGFuIEVycm9yIGlmIGFsaWFzIHRhcmdldCBpcyBhbiBleGlzdCBhY3Rpb25cIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIHRocm93cyAoLT5cbiAgICAgIGEuYWxpYXNfYWN0aW9uIFtcInNob3dcIl0sIFwic2hvd1wiXG4gICAgICByZXR1cm5cbiAgICApLCBcIllvdSBjYW4ndCBzcGVjaWZ5IHRhcmdldCAoc2hvdykgYXMgYWxpYXMgYmVjYXVzZSBpdCBpcyByZWFsIGFjdGlvbiBuYW1lXCJcbiAgICByZXR1cm5cblxuICB0ZXN0IFwic2hvdWxkIGF1dG9tYXRpY2FsbHkgYWxpYXMgaW5kZXggYW5kIHNob3cgaW50byByZWFkIGNhbGxzXCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLnNldF9jYW4gXCJyZWFkXCIsIFwiYWxsXCJcbiAgICBvayBhLmNhbihcImluZGV4XCIsIDEyMylcbiAgICBvayBhLmNhbihcInNob3dcIiwgMTIzKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgYXV0b21hdGljYWxseSBhbGlhcyBuZXcgYW5kIGVkaXQgaW50byBjcmVhdGUgYW5kIHVwZGF0ZSByZXNwZWN0aXZlbHlcIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuc2V0X2NhbiBcImNyZWF0ZVwiLCBcImFsbFwiXG4gICAgYS5zZXRfY2FuIFwidXBkYXRlXCIsIFwiYWxsXCJcbiAgICBvayBhLmNhbihcIm5ld1wiLCAxMjMpXG4gICAgb2sgYS5jYW4oXCJlZGl0XCIsIDEyMylcbiAgICByZXR1cm5cblxuICB0ZXN0IFwic2hvdWxkIG9mZmVyIGNhbm5vdD8gbWV0aG9kIHdoaWNoIGlzIHNpbXBseSBpbnZlcnQgb2YgY2FuP1wiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgb2sgYS5jYW5ub3QoXCJ0aWVcIiwgU3RyaW5nKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgYmUgYWJsZSB0byBzcGVjaWZ5IG11bHRpcGxlIGFjdGlvbnMgYW5kIG1hdGNoIGFueVwiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFtcbiAgICAgIFwicmVhZFwiXG4gICAgICBcInVwZGF0ZVwiXG4gICAgXSwgXCJhbGxcIlxuICAgIG9rIGEuY2FuKFwicmVhZFwiLCAxMjMpXG4gICAgb2sgYS5jYW4oXCJ1cGRhdGVcIiwgMTIzKVxuICAgIG9rIGEuY2Fubm90KFwiY291bnRcIiwgMTIzKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgYmUgYWJsZSB0byBzcGVjaWZ5IG11bHRpcGxlIGNsYXNzZXMgYW5kIG1hdGNoIGFueSBpbnN0YW5jZXNcIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuc2V0X2NhbiBcInVwZGF0ZVwiLCBbXG4gICAgICBQb3N0XG4gICAgICBDb21tZW50XG4gICAgXVxuICAgIG9rIGEuY2FuKFwidXBkYXRlXCIsIG5ldyBQb3N0KCkpXG4gICAgb2sgYS5jYW4oXCJ1cGRhdGVcIiwgbmV3IENvbW1lbnQoKSlcbiAgICBvayBhLmNhbm5vdChcInVwZGF0ZVwiLCBuZXcgUmVnRXhwKCkpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBiZSBhYmxlIHRvIHNwZWNpZnkgbXVsdGlwbGUgY2xhc3NlcyBhbmQgbWF0Y2ggYW55IGNsYXNzZXNcIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuc2V0X2NhbiBcInVwZGF0ZVwiLCBbXG4gICAgICBQb3N0XG4gICAgICBDb21tZW50XG4gICAgXVxuICAgIG9rIGEuY2FuKFwidXBkYXRlXCIsIFBvc3QpXG4gICAgb2sgYS5jYW4oXCJ1cGRhdGVcIiwgQ29tbWVudClcbiAgICBvayBhLmNhbm5vdChcInVwZGF0ZVwiLCBSZWdFeHApXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBzdXBwb3J0IGN1c3RvbSBvYmplY3RzIGluIHRoZSBydWxlXCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLnNldF9jYW4gXCJyZWFkXCIsIFwic3RhdHNcIlxuICAgIG9rIGEuY2FuKFwicmVhZFwiLCBcInN0YXRzXCIpXG4gICAgb2sgYS5jYW5ub3QoXCJ1cGRhdGVcIiwgXCJzdGF0c1wiKVxuICAgIG9rIGEuY2Fubm90KFwicmVhZFwiLCBcIm5vbnN0YXRzXCIpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBzdXBwb3J0ICdjYW5ub3QnIG1ldGhvZCB0byBkZWZpbmUgd2hhdCB1c2VyIGNhbm5vdCBkb1wiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBcImFsbFwiXG4gICAgYS5zZXRfY2Fubm90IFwicmVhZFwiLCBQb3N0XG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFwiZm9vXCIpXG4gICAgb2sgYS5jYW5ub3QoXCJyZWFkXCIsIG5ldyBQb3N0KCkpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBhcHBlbmQgYWxpYXNlZCBhY3Rpb25zXCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLmFsaWFzX2FjdGlvbiBbXCJ1cGRhdGVcIl0sIFwibW9kaWZ5XCJcbiAgICBhLmFsaWFzX2FjdGlvbiBbXCJkZXN0cm95XCJdLCBcIm1vZGlmeVwiXG4gICAgb2sgXy5pc0VxdWFsKFtcbiAgICAgIFwidXBkYXRlXCJcbiAgICAgIFwiZGVzdHJveVwiXG4gICAgXSwgYS5nZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbXCJtb2RpZnlcIl0pXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBjbGVhciBhbGlhc2VkIGFjdGlvbnNcIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuYWxpYXNfYWN0aW9uIFtcInVwZGF0ZVwiXSwgXCJtb2RpZnlcIlxuICAgIGEuY2xlYXJfYWxpYXNlZF9hY3Rpb25zKClcbiAgICBlcXVhbCBgdW5kZWZpbmVkYCwgYS5nZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbXCJtb2RpZnlcIl1cbiAgICByZXR1cm5cblxuICB0ZXN0IFwic2hvdWxkIHVzZSBjb25kaXRpb25zIGFzIHRoaXJkIHBhcmFtZXRlciBhbmQgZGV0ZXJtaW5lIGFiaWxpdGllcyBmcm9tIGl0XCIsIC0+XG4gICAgYSA9IG5ldyBBYmlsaXR5KClcbiAgICBhLnNldF9jYW4gXCJyZWFkXCIsIFBvc3QsXG4gICAgICB0aXRsZTogXCJIZWxsb1wiXG5cbiAgICBvayBhLmNhbihcInJlYWRcIiwgbmV3IFBvc3QodGl0bGU6IFwiSGVsbG9cIikpXG4gICAgb2sgYS5jYW5ub3QoXCJyZWFkXCIsIG5ldyBQb3N0KHRpdGxlOiBcIkdvb2RieWVcIikpXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFBvc3QpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBhbGxvdyBhbiBhcnJheSBvZiBvcHRpb25zIGluIGNvbmRpdGlvbnMgaGFzaFwiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBQb3N0LFxuICAgICAgdGFnczogW1xuICAgICAgICBcImF3ZXNvbWVcIlxuICAgICAgICBcImNvb2xcIlxuICAgICAgICBcInByZXR0eVwiXG4gICAgICBdXG5cbiAgICBvayBhLmNhbihcInJlYWRcIiwgbmV3IFBvc3QodGFnczogW1xuICAgICAgXCJhd2Vzb21lXCJcbiAgICAgIFwiY29vbFwiXG4gICAgICBcInByZXR0eVwiXG4gICAgXSkpXG4gICAgb2sgYS5jYW5ub3QoXCJyZWFkXCIsIG5ldyBQb3N0KHRhZ3M6IFtcbiAgICAgIFwidWdseVwiXG4gICAgICBcImJhZFwiXG4gICAgXSkpXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIFBvc3QpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBhbGxvdyBuZXN0ZWQgaGFzaGVzIGluIGNvbmRpdGlvbnMgaGFzaFwiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBQb3N0LFxuICAgICAgY29tbWVudDpcbiAgICAgICAgdXNlcl9pZDogMVxuXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIG5ldyBQb3N0KGNvbW1lbnQ6XG4gICAgICB1c2VyX2lkOiAxXG4gICAgKSlcbiAgICBvayBhLmNhbm5vdChcInJlYWRcIiwgbmV3IFBvc3QoY29tbWVudDpcbiAgICAgIHVzZXJfaWQ6IDJcbiAgICApKVxuICAgIHJldHVyblxuXG4gIHRlc3QgXCJzaG91bGQgYWxsb3cgZmFsc2UgdmFsdWVzIGNvbmRpdGlvbnMgaGFzaFwiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBQb3N0LFxuICAgICAgY29tbWVudDpcbiAgICAgICAgaXNfcHJvdGVjdGVkOiBmYWxzZVxuXG4gICAgb2sgYS5jYW4oXCJyZWFkXCIsIG5ldyBQb3N0KGNvbW1lbnQ6XG4gICAgICBpc19wcm90ZWN0ZWQ6IGZhbHNlXG4gICAgKSlcbiAgICBvayBhLmNhbm5vdChcInJlYWRcIiwgbmV3IFBvc3QoY29tbWVudDpcbiAgICAgIGlzX3Byb3RlY3RlZDogdHJ1ZVxuICAgICkpXG4gICAgcmV0dXJuXG5cbiAgdGVzdCBcInNob3VsZCBub3Qgc3RvcCBhdCBjYW5ub3QgZGVmaW5pdGlvbiB3aGVuIGNvbXBhcmluZyBjbGFzc1wiLCAtPlxuICAgIGEgPSBuZXcgQWJpbGl0eSgpXG4gICAgYS5zZXRfY2FuIFwicmVhZFwiLCBQb3N0XG4gICAgYS5zZXRfY2Fubm90IFwicmVhZFwiLCBQb3N0LFxuICAgICAgaWQ6IDFcblxuICAgIG9rIGEuY2FuKFwicmVhZFwiLCBuZXcgUG9zdChpZDogMikpXG4gICAgb2sgYS5jYW5ub3QoXCJyZWFkXCIsIG5ldyBQb3N0KGlkOiAxKSlcbiAgICBvayBhLmNhbihcInJlYWRcIiwgUG9zdClcbiAgICByZXR1cm5cblxuICB0ZXN0IFwic2hvdWxkIHN0b3AgYXQgY2Fubm90IGRlZmluaXRpb24gd2hlbiBubyBoYXNoIGlzIHByZXNlbnRcIiwgLT5cbiAgICBhID0gbmV3IEFiaWxpdHkoKVxuICAgIGEuc2V0X2NhbiBcInJlYWRcIiwgXCJhbGxcIlxuICAgIGEuc2V0X2Nhbm5vdCBcInJlYWRcIiwgUG9zdFxuICAgIG9rIGEuY2Fubm90KFwicmVhZFwiLCBuZXcgUG9zdCgpKVxuICAgIG9rIGEuY2Fubm90KFwicmVhZFwiLCBQb3N0KVxuICAgIHJldHVyblxuIl0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/test/build/cancan_backbone.js b/test/build/cancan_backbone.js deleted file mode 100644 index 76bac84..0000000 --- a/test/build/cancan_backbone.js +++ /dev/null @@ -1,175 +0,0 @@ -(function() { - (function() { - var root; - root = this; - root.Ability = Backbone.Model.extend({ - defaults: function() { - return { - rules: [], - aliased_actions: { - read: ["index", "show"], - create: ["new"], - update: ["edit"] - } - }; - }, - initialize: function() { - if (!_.isEmpty(this.get("rules"))) { - this.set("rules", _.map(this.get("rules"), function(rule) { - return new Rule(rule); - })); - } - }, - can: function(action, subject) { - var match; - match = _.detect(this.relevant_rules(action, subject), function(rule) { - return rule.matches_conditions(action, subject); - }, this); - if (match) { - return match.get("base_behavior"); - } else { - return false; - } - }, - cannot: function(action, subject) { - return !this.can(action, subject); - }, - set_can: function(action, subject, conditions) { - this.get("rules").push(new Rule({ - base_behavior: true, - action: action, - subject: subject, - conditions: conditions - })); - }, - set_cannot: function(action, subject, conditions) { - this.get("rules").push(new Rule({ - base_behavior: false, - action: action, - subject: subject, - conditions: conditions - })); - }, - alias_action: function(from, target) { - this.validate_target(target); - if (!_.isArray(this.get("aliased_actions")[target])) { - this.get("aliased_actions")[target] = []; - } - this.get("aliased_actions")[target] = this.get("aliased_actions")[target].concat(from); - }, - validate_target: function(target) { - if (_.chain(this.get("aliased_actions")).values().flatten().include(target).value()) { - throw new Error("You can't specify target (" + target + ") as alias because it is real action name"); - } - }, - clear_aliased_actions: function() { - this.set("aliased_actions", {}); - }, - expand_actions: function(actions) { - return _.chain(actions).map(function(action) { - if (this.get("aliased_actions")[action]) { - return [action].concat(this.expand_actions(this.get("aliased_actions")[action])); - } else { - return action; - } - }, this).flatten().value(); - }, - relevant_rules: function(action, subject) { - var reversed_rules; - reversed_rules = this.get("rules").slice(0); - return _.select(reversed_rules.reverse(), (function(rule) { - rule.set("expanded_actions", this.expand_actions(rule.get("actions"))); - return rule.is_relevant(action, subject); - }), this); - } - }); - root.Rule = Backbone.Model.extend({ - initialize: function() { - if (!this.get("actions") && this.get("action")) { - this.set("actions", _.flatten([this.get("action")])); - } - if (!this.get("subjects") && this.get("subject")) { - this.set("subjects", _.flatten([this.get("subject")])); - } - if (!this.get("conditions")) { - this.set("conditions", {}); - } - }, - backbone_class: function(sub) { - if (sub == null) { - sub = null; - } - return sub != null ? sub.backboneClass : void 0; - }, - is_relevant: function(action, subject) { - return this.matches_action(action) && this.matches_subject(subject); - }, - matches_conditions: function(action, subject) { - if (_.isObject(this.get("conditions")) && !_.isEmpty(this.get("conditions")) && !this.subject_class(subject)) { - return this.matches_conditions_hash(subject); - } else { - if (_.isEmpty(this.get("conditions"))) { - return true; - } else { - return this.get("base_behavior"); - } - } - }, - subject_class: function(subject) { - if (this.backbone_class(subject)) { - return true; - } else { - return false; - } - }, - matches_action: function(action) { - return _.include(this.get("expanded_actions"), "manage") || _.include(this.get("expanded_actions"), action); - }, - matches_subject: function(subject) { - return _.include(this.get("subjects"), "all") || _.include(this.get("subjects"), subject) || this.matches_subject_class(subject); - }, - matches_subject_class: function(subject) { - return _.any(this.get("subjects"), (function(_this) { - return function(sub) { - var sub_class, subject_class; - sub_class = _this.backbone_class(sub) || _this.backbone_class(sub.constructor); - subject_class = _this.backbone_class(subject) || _this.backbone_class(subject.constructor); - return (sub_class && subject_class && sub_class === subject_class) || sub === subject_class || sub_class === subject; - }; - })(this)); - }, - matches_conditions_hash: function(subject, conditions) { - if (!conditions) { - conditions = this.get("conditions"); - } - if (_.isEmpty(conditions)) { - return true; - } else { - return _.all(conditions, (function(value, name) { - var attribute; - attribute = subject[name]; - if (_.isUndefined(attribute)) { - attribute = subject.get(name); - } - if (_.isObject(value) && !_.isArray(value)) { - if (_.isArray(attribute)) { - return _.any(attribute, (function(element) { - this.matches_conditions_hash(element, value); - }), this); - } else { - return attribute && this.matches_conditions_hash(attribute, value); - } - } else if (_.isArray(value)) { - return _.include(value, attribute) || _.isEqual(value, attribute); - } else { - return attribute === value; - } - }), this); - } - } - }); - }).call(this); - -}).call(this); - -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FuY2FuX2JhY2tib25lLmpzIiwic291cmNlcyI6WyJjYW5jYW5fYmFja2JvbmUuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FBQUEsRUFBQSxDQUFDLFNBQUEsR0FBQTtBQUNDLFFBQUEsSUFBQTtBQUFBLElBQUEsSUFBQSxHQUFPLElBQVAsQ0FBQTtBQUFBLElBSUEsSUFBSSxDQUFDLE9BQUwsR0FBZSxRQUFRLENBQUMsS0FBSyxDQUFDLE1BQWYsQ0FDYjtBQUFBLE1BQUEsUUFBQSxFQUFVLFNBQUEsR0FBQTtlQUNSO0FBQUEsVUFBQSxLQUFBLEVBQU8sRUFBUDtBQUFBLFVBQ0EsZUFBQSxFQUNFO0FBQUEsWUFBQSxJQUFBLEVBQU0sQ0FDSixPQURJLEVBRUosTUFGSSxDQUFOO0FBQUEsWUFJQSxNQUFBLEVBQVEsQ0FBQyxLQUFELENBSlI7QUFBQSxZQUtBLE1BQUEsRUFBUSxDQUFDLE1BQUQsQ0FMUjtXQUZGO1VBRFE7TUFBQSxDQUFWO0FBQUEsTUFVQSxVQUFBLEVBQVksU0FBQSxHQUFBO0FBQ1YsUUFBQSxJQUFBLENBQUEsQ0FBUSxDQUFDLE9BQUYsQ0FBVSxJQUFDLENBQUEsR0FBRCxDQUFLLE9BQUwsQ0FBVixDQUFQO0FBQ0UsVUFBQSxJQUFDLENBQUEsR0FBRCxDQUFLLE9BQUwsRUFBYyxDQUFDLENBQUMsR0FBRixDQUFNLElBQUMsQ0FBQSxHQUFELENBQUssT0FBTCxDQUFOLEVBQXFCLFNBQUMsSUFBRCxHQUFBO21CQUM3QixJQUFBLElBQUEsQ0FBSyxJQUFMLEVBRDZCO1VBQUEsQ0FBckIsQ0FBZCxDQUFBLENBREY7U0FEVTtNQUFBLENBVlo7QUFBQSxNQWlCQSxHQUFBLEVBQUssU0FBQyxNQUFELEVBQVMsT0FBVCxHQUFBO0FBQ0gsWUFBQSxLQUFBO0FBQUEsUUFBQSxLQUFBLEdBQVEsQ0FBQyxDQUFDLE1BQUYsQ0FBUyxJQUFDLENBQUEsY0FBRCxDQUFnQixNQUFoQixFQUF3QixPQUF4QixDQUFULEVBQTJDLFNBQUMsSUFB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RixDQUFVLFNBQVYsQ0FBSDt1QkFDRSxDQUFDLENBQUMsR0FBRixDQUFNLFNBQU4sRUFBaUIsQ0FBQyxTQUFDLE9BQUQsR0FBQTtBQUNoQixrQkFBQSxJQUFDLENBQUEsdUJBQUQsQ0FBeUIsT0FBekIsRUFBa0MsS0FBbEMsQ0FBQSxDQURnQjtnQkFBQSxDQUFELENBQWpCLEVBR0csSUFISCxFQURGO2VBQUEsTUFBQTt1QkFNRSxTQUFBLElBQWMsSUFBQyxDQUFBLHVCQUFELENBQXlCLFNBQXpCLEVBQW9DLEtBQXBDLEVBTmhCO2VBREY7YUFBQSxNQVFLLElBQUcsQ0FBQyxDQUFDLE9BQUYsQ0FBVSxLQUFWLENBQUg7cUJBQ0gsQ0FBQyxDQUFDLE9BQUYsQ0FBVSxLQUFWLEVBQWlCLFNBQWpCLENBQUEsSUFBK0IsQ0FBQyxDQUFDLE9BQUYsQ0FBVSxLQUFWLEVBQWlCLFNBQWpCLEVBRDVCO2FBQUEsTUFBQTtxQkFHSCxTQUFBLEtBQWEsTUFIVjthQVhZO1VBQUEsQ0FBRCxDQUFsQixFQWVHLElBZkgsRUFIRjtTQUZ1QjtNQUFBLENBbkN6QjtLQURVLENBaEZaLENBREQ7RUFBQSxDQUFELENBNElDLENBQUMsSUE1SUYsQ0E0SU8sSUE1SVAsQ0FBQSxDQUFBO0FBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIoLT5cbiAgcm9vdCA9IHRoaXNcblxuICAjIEFiaWxpdHlcbiAgIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgcm9vdC5BYmlsaXR5ID0gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKFxuICAgIGRlZmF1bHRzOiAtPlxuICAgICAgcnVsZXM6IFtdXG4gICAgICBhbGlhc2VkX2FjdGlvbnM6XG4gICAgICAgIHJlYWQ6IFtcbiAgICAgICAgICBcImluZGV4XCJcbiAgICAgICAgICBcInNob3dcIlxuICAgICAgICBdXG4gICAgICAgIGNyZWF0ZTogW1wibmV3XCJdXG4gICAgICAgIHVwZGF0ZTogW1wiZWRpdFwiXVxuXG4gICAgaW5pdGlhbGl6ZTogLT5cbiAgICAgIHVubGVzcyBfLmlzRW1wdHkoQGdldChcInJ1bGVzXCIpKVxuICAgICAgICBAc2V0IFwicnVsZXNcIiwgXy5tYXAoQGdldChcInJ1bGVzXCIpLCAocnVsZSkgLT5cbiAgICAgICAgICBuZXcgUnVsZShydWxlKVxuICAgICAgICApXG4gICAgICByZXR1cm5cblxuICAgIGNhbjogKGFjdGlvbiwgc3ViamVjdCkgLT5cbiAgICAgIG1hdGNoID0gXy5kZXRlY3QoQHJlbGV2YW50X3J1bGVzKGFjdGlvbiwgc3ViamVjdCksIChydWxlKSAtPlxuICAgICAgICBydWxlLm1hdGNoZXNfY29uZGl0aW9ucyBhY3Rpb24sIHN1YmplY3RcbiAgICAgICwgdGhpcylcbiAgICAgIChpZiBtYXRjaCB0aGVuIG1hdGNoLmdldChcImJhc2VfYmVoYXZpb3JcIikgZWxzZSBmYWxzZSlcblxuICAgIGNhbm5vdDogKGFjdGlvbiwgc3ViamVjdCkgLT5cbiAgICAgIG5vdCBAY2FuKGFjdGlvbiwgc3ViamVjdClcblxuICAgIHNldF9jYW46IChhY3Rpb24sIHN1YmplY3QsIGNvbmRpdGlvbnMpIC0+XG4gICAgICBAZ2V0KFwicnVsZXNcIikucHVzaCBuZXcgUnVsZShcbiAgICAgICAgYmFzZV9iZWhhdmlvcjogdHJ1ZVxuICAgICAgICBhY3Rpb246IGFjdGlvblxuICAgICAgICBzdWJqZWN0OiBzdWJqZWN0XG4gICAgICAgIGNvbmRpdGlvbnM6IGNvbmRpdGlvbnNcbiAgICAgIClcbiAgICAgIHJldHVyblxuXG4gICAgc2V0X2Nhbm5vdDogKGFjdGlvbiwgc3ViamVjdCwgY29uZGl0aW9ucykgLT5cbiAgICAgIEBnZXQoXCJydWxlc1wiKS5wdXNoIG5ldyBSdWxlKFxuICAgICAgICBiYXNlX2JlaGF2aW9yOiBmYWxzZVxuICAgICAgICBhY3Rpb246IGFjdGlvblxuICAgICAgICBzdWJqZWN0OiBzdWJqZWN0XG4gICAgICAgIGNvbmRpdGlvbnM6IGNvbmRpdGlvbnNcbiAgICAgIClcbiAgICAgIHJldHVyblxuXG4gICAgYWxpYXNfYWN0aW9uOiAoZnJvbSwgdGFyZ2V0KSAtPlxuICAgICAgQHZhbGlkYXRlX3RhcmdldCB0YXJnZXRcbiAgICAgIEBnZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbdGFyZ2V0XSA9IFtdICB1bmxlc3MgXy5pc0FycmF5KEBnZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbdGFyZ2V0XSlcbiAgICAgIEBnZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbdGFyZ2V0XSA9IEBnZXQoXCJhbGlhc2VkX2FjdGlvbnNcIilbdGFyZ2V0XS5jb25jYXQoZnJvbSlcbiAgICAgIHJldHVyblxuXG4gICAgdmFsaWRhdGVfdGFyZ2V0OiAodGFyZ2V0KSAtPlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiWW91IGNhbid0IHNwZWNpZnkgdGFyZ2V0IChcIiArIHRhcmdldCArIFwiKSBhcyBhbGlhcyBiZWNhdXNlIGl0IGlzIHJlYWwgYWN0aW9uIG5hbWVcIikgIGlmIF8uY2hhaW4oQGdldChcImFsaWFzZWRfYWN0aW9uc1wiKSkudmFsdWVzKCkuZmxhdHRlbigpLmluY2x1ZGUodGFyZ2V0KS52YWx1ZSgpXG4gICAgICByZXR1cm5cblxuICAgIGNsZWFyX2FsaWFzZWRfYWN0aW9uczogLT5cbiAgICAgIEBzZXQgXCJhbGlhc2VkX2FjdGlvbnNcIiwge31cbiAgICAgIHJldHVyblxuXG4gICAgZXhwYW5kX2FjdGlvbnM6IChhY3Rpb25zKSAtPlxuICAgICAgXy5jaGFpbihhY3Rpb25zKS5tYXAoKGFjdGlvbikgLT5cbiAgICAgICAgaWYgQGdldChcImFsaWFzZWRfYWN0aW9uc1wiKVthY3Rpb25dXG4gICAgICAgICAgW2FjdGlvbl0uY29uY2F0IEBleHBhbmRfYWN0aW9ucyhAZ2V0KFwiYWxpYXNlZF9hY3Rpb25zXCIpW2FjdGlvbl0pXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBhY3Rpb25cbiAgICAgICwgdGhpcykuZmxhdHRlbigpLnZhbHVlKClcblxuICAgIHJlbGV2YW50X3J1bGVzOiAoYWN0aW9uLCBzdWJqZWN0KSAtPlxuICAgICAgcmV2ZXJzZWRfcnVsZXMgPSBAZ2V0KFwicnVsZXNcIikuc2xpY2UoMClcbiAgICAgIF8uc2VsZWN0IHJldmVyc2VkX3J1bGVzLnJldmVyc2UoKSwgKChydWxlKSAtPlxuICAgICAgICBydWxlLnNldCBcImV4cGFuZGVkX2FjdGlvbnNcIiwgQGV4cGFuZF9hY3Rpb25zKHJ1bGUuZ2V0KFwiYWN0aW9uc1wiKSlcbiAgICAgICAgcnVsZS5pc19yZWxldmFudCBhY3Rpb24sIHN1YmplY3RcbiAgICAgICksIHRoaXNcbiAgKVxuICAjIFJ1bGVcbiAgIyAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgcm9vdC5SdWxlID0gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKFxuICAgIGluaXRpYWxpemU6IC0+XG4gICAgICBAc2V0IFwiYWN0aW9uc1wiLCBfLmZsYXR0ZW4oW0BnZXQoXCJhY3Rpb25cIildKSAgaWYgbm90IEBnZXQoXCJhY3Rpb25zXCIpIGFuZCBAZ2V0KFwiYWN0aW9uXCIpXG4gICAgICBAc2V0IFwic3ViamVjdHNcIiwgXy5mbGF0dGVuKFtAZ2V0KFwic3ViamVjdFwiKV0pICBpZiBub3QgQGdldChcInN1YmplY3RzXCIpIGFuZCBAZ2V0KFwic3ViamVjdFwiKVxuICAgICAgQHNldCBcImNvbmRpdGlvbnNcIiwge30gIHVubGVzcyBAZ2V0KFwiY29uZGl0aW9uc1wiKVxuICAgICAgcmV0dXJuXG5cbiAgICBiYWNrYm9uZV9jbGFzczogKHN1YiA9IG51bGwpIC0+XG4gICAgICBzdWI/LmJhY2tib25lQ2xhc3NcblxuICAgIGlzX3JlbGV2YW50OiAoYWN0aW9uLCBzdWJqZWN0KSAtPlxuICAgICAgQG1hdGNoZXNfYWN0aW9uKGFjdGlvbikgYW5kIEBtYXRjaGVzX3N1YmplY3Qoc3ViamVjdClcblxuICAgIG1hdGNoZXNfY29uZGl0aW9uczogKGFjdGlvbiwgc3ViamVjdCkgLT5cbiAgICAgIGlmIF8uaXNPYmplY3QoQGdldChcImNvbmRpdGlvbnNcIikpIGFuZCBub3QgXy5pc0VtcHR5KEBnZXQoXCJjb25kaXRpb25zXCIpKSBhbmQgbm90IEBzdWJqZWN0X2NsYXNzKHN1YmplY3QpXG4gICAgICAgIEBtYXRjaGVzX2NvbmRpdGlvbnNfaGFzaCBzdWJqZWN0XG4gICAgICBlbHNlXG4gICAgICAgIChpZiBfLmlzRW1wdHkoQGdldChcImNvbmRpdGlvbnNcIikpIHRoZW4gdHJ1ZSBlbHNlIEBnZXQoXCJiYXNlX2JlaGF2aW9yXCIpKVxuXG4gICAgc3ViamVjdF9jbGFzczogKHN1YmplY3QpIC0+XG4gICAgICAoaWYgQGJhY2tib25lX2NsYXNzKHN1YmplY3QpIHRoZW4gdHJ1ZSBlbHNlIGZhbHNlKVxuXG4gICAgbWF0Y2hlc19hY3Rpb246IChhY3Rpb24pIC0+XG4gICAgICBfLmluY2x1ZGUoQGdldChcImV4cGFuZGVkX2FjdGlvbnNcIiksIFwibWFuYWdlXCIpIG9yIF8uaW5jbHVkZShAZ2V0KFwiZXhwYW5kZWRfYWN0aW9uc1wiKSwgYWN0aW9uKVxuXG4gICAgbWF0Y2hlc19zdWJqZWN0OiAoc3ViamVjdCkgLT5cbiAgICAgIF8uaW5jbHVkZShAZ2V0KFwic3ViamVjdHNcIiksIFwiYWxsXCIpIG9yIF8uaW5jbHVkZShAZ2V0KFwic3ViamVjdHNcIiksIHN1YmplY3QpIG9yIEBtYXRjaGVzX3N1YmplY3RfY2xhc3Moc3ViamVjdClcblxuICAgIG1hdGNoZXNfc3ViamVjdF9jbGFzczogKHN1YmplY3QpIC0+XG4gICAgICAjIGlmIGJvdGggYXJlIGJhY2tib25lIG9iamVjdHMgKGVpdGhlciBjbGFzcyBvciBpbnN0YW5jZSkgaW1wbGVtZW50aW5nIGJhY2tib25lQ2xhc3NcbiAgICAgIF8uYW55IEBnZXQoXCJzdWJqZWN0c1wiKSwgKHN1YikgPT5cbiAgICAgICAgc3ViX2NsYXNzID0gQGJhY2tib25lX2NsYXNzKHN1Yikgb3IgQGJhY2tib25lX2NsYXNzKHN1Yi5jb25zdHJ1Y3RvcilcbiAgICAgICAgc3ViamVjdF9jbGFzcyA9IEBiYWNrYm9uZV9jbGFzcyhzdWJqZWN0KSBvciBAYmFja2JvbmVfY2xhc3Moc3ViamVjdC5jb25zdHJ1Y3RvcilcbiAgICAgICAgKHN1Yl9jbGFzcyBhbmQgc3ViamVjdF9jbGFzcyBhbmQgc3ViX2NsYXNzIGlzIHN1YmplY3RfY2xhc3MpIG9yIHN1YiBpcyBzdWJqZWN0X2NsYXNzIG9yIHN1Yl9jbGFzcyBpcyBzdWJqZWN0XG5cblxuICAgIG1hdGNoZXNfY29uZGl0aW9uc19oYXNoOiAoc3ViamVjdCwgY29uZGl0aW9ucykgLT5cbiAgICAgIGNvbmRpdGlvbnMgPSBAZ2V0KFwiY29uZGl0aW9uc1wiKSAgdW5sZXNzIGNvbmRpdGlvbnNcbiAgICAgIGlmIF8uaXNFbXB0eShjb25kaXRpb25zKVxuICAgICAgICB0cnVlXG4gICAgICBlbHNlXG4gICAgICAgIF8uYWxsIGNvbmRpdGlvbnMsICgodmFsdWUsIG5hbWUpIC0+XG4gICAgICAgICAgYXR0cmlidXRlID0gc3ViamVjdFtuYW1lXVxuICAgICAgICAgIGF0dHJpYnV0ZSA9IHN1YmplY3QuZ2V0KG5hbWUpICBpZiBfLmlzVW5kZWZpbmVkKGF0dHJpYnV0ZSlcbiAgICAgICAgICBpZiBfLmlzT2JqZWN0KHZhbHVlKSBhbmQgbm90IF8uaXNBcnJheSh2YWx1ZSlcbiAgICAgICAgICAgIGlmIF8uaXNBcnJheShhdHRyaWJ1dGUpXG4gICAgICAgICAgICAgIF8uYW55IGF0dHJpYnV0ZSwgKChlbGVtZW50KSAtPlxuICAgICAgICAgICAgICAgIEBtYXRjaGVzX2NvbmRpdGlvbnNfaGFzaCBlbGVtZW50LCB2YWx1ZVxuICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICApLCB0aGlzXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgIGF0dHJpYnV0ZSBhbmQgQG1hdGNoZXNfY29uZGl0aW9uc19oYXNoKGF0dHJpYnV0ZSwgdmFsdWUpXG4gICAgICAgICAgZWxzZSBpZiBfLmlzQXJyYXkodmFsdWUpXG4gICAgICAgICAgICBfLmluY2x1ZGUodmFsdWUsIGF0dHJpYnV0ZSkgb3IgXy5pc0VxdWFsKHZhbHVlLCBhdHRyaWJ1dGUpXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgYXR0cmlidXRlIGlzIHZhbHVlXG4gICAgICAgICksIHRoaXNcbiAgKVxuICByZXR1cm5cbikuY2FsbCB0aGlzIl0sInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file