Permalink
Browse files

Efficiently persist access control role map to database

  • Loading branch information...
1 parent 7bb4e5a commit 0f8efe4d68dc924fb74cf7b9e5e9af52a4f25b43 @mbklein mbklein committed Feb 11, 2013
Showing with 81 additions and 8 deletions.
  1. +42 −0 app/models/role_map.rb
  2. +8 −0 db/migrate/20130211152936_role_map.rb
  3. +6 −1 db/schema.rb
  4. +1 −7 lib/role_controls.rb
  5. +24 −0 spec/models/role_map_spec.rb
View
@@ -0,0 +1,42 @@
+class RoleMap < ActiveRecord::Base
+ belongs_to :role, class_name: "RoleMap", foreign_key: "parent_id"
+ has_many :entries, class_name: "RoleMap", foreign_key: "parent_id"
+ attr_accessible :entry, :role
+
+ def self.reset!
+ self.replace_with! YAML.load(File.read(File.join(Rails.root, "config/role_map_#{Rails.env}.yml")))
+ end
+
+ def self.roles
+ self.find_all_by_parent_id(nil)
+ end
+
+ def self.load
+ Rails.cache.fetch('RoleMapHash') do
+ roles.inject({}) do |map, role|
+ map[role.entry] = role.entries.collect &:entry
+ map
+ end
+ end
+ end
+
+ def self.replace_with! map
+ roles.each { |r| r.destroy unless map.keys.include?(r.entry) }
+ map.each_pair do |role, entries|
+ r = self.find_or_create_by_entry_and_parent_id(role, nil)
+ existing = r.entries.collect &:entry
+ add = entries - existing
+ delete = existing - entries
+ delete.each { |e| r.entries.find_by_entry(e).destroy }
+ add.each { |e| r.entries.create :entry => e }
+ end
+ Rails.cache.delete('RoleMapHash')
+ end
+end
+
+module Hydra::RoleMapperBehavior::ClassMethods
+ def map
+ RoleMap.reset! if RoleMap.count == 0
+ RoleMap.load
+ end
+end
@@ -0,0 +1,8 @@
+class RoleMap < ActiveRecord::Migration
+ def change
+ create_table :role_maps do |t|
+ t.string :entry
+ t.integer :parent_id
+ end
+ end
+end
View
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20130108163856) do
+ActiveRecord::Schema.define(:version => 20130211152936) do
create_table "bookmarks", :force => true do |t|
t.integer "user_id", :null => false
@@ -55,6 +55,11 @@
t.string "name", :limit => 50
end
+ create_table "role_maps", :force => true do |t|
+ t.string "entry"
+ t.integer "parent_id"
+ end
+
create_table "searches", :force => true do |t|
t.text "query_params"
t.integer "user_id"
View
@@ -69,13 +69,7 @@ def add_user_role(user, role)
end
def save_changes
- doc = ""
- RoleMapper.map.each_pair do |k, v|
- usrarr = v.join("\r\n - ")
- doc += "#{k}:\r\n - #{usrarr}\r\n"
- end
-
- File.open(File.join(Rails.root, "config/role_map_#{Rails.env}.yml"), "w") {|f| f.write(doc) }
+ RoleMap.replace_with! RoleMapper.map
end
end
end
@@ -0,0 +1,24 @@
+require 'spec_helper'
+
+describe RoleMap do
+ describe "role map persistor" do
+ before :each do
+ RoleMap.reset!
+ end
+
+ after :each do
+ RoleMap.all.each &:destroy
+ end
+
+ it "should properly initialize the map" do
+ RoleMapper.map.should == YAML.load(File.read(File.join(Rails.root, "config/role_map_#{Rails.env}.yml")))
+ end
+
+ it "should properly persist a hash" do
+ new_hash = { 'archivist' => ['alice.archivist@example.edu'], 'registered' => ['bob.user@example.edu','charlie.user@example.edu'] }
+ RoleMap.replace_with!(new_hash)
+ RoleMapper.map.should == new_hash
+ RoleMap.load.should == new_hash
+ end
+ end
+end

2 comments on commit 0f8efe4

Liking where this is going! Eventually roles will be created in an admin dashboard page?

Owner

mbklein replied Feb 11, 2013

Yeah. And if the RoleMapper discovers that the RoleMap table it empty, it will initialize it from the role_map_#{Rails.env}.yml file.

Please sign in to comment.