class Map include DataMapper::Resource property :id, Serial property :key_repository, String, :default => 'keys' has n, :roles has n, :users belongs_to :parent, :model => Map, :required => false after :create do self.users += self.parent.users if self.parent end after :key_repository= do |*args| unless File.exists?(self.expanded_key_repository_path) raise LoadError, "Could not load key repository - #{self.expanded_key_repository_path}" end end def self.draw(opts = {}) map = Map.create(opts) yield map if block_given? map.read! map end def read! self.roles.all.each do |role| role.update_user_access! end true end def key_repository(repo = nil) if repo self.key_repository = repo end @key_repository end def expanded_key_repository_path File.join(Fabric.options(:map_root), self.key_repository) # self.key_repository end def role(name, *hosts) role = self.roles.create(:name => name.to_s) hosts.each do |host| role.servers.create(:host => host) end role.save end def user(*names) names.each do |name| user = self.users.create(:name => name.to_s) self.load_keys_from_repository(user) end end # This method has become too long again... def grant(user_names, role_names, role_conditions = {}) users = self.users.all roles = self.roles.all users = users.all(:name => user_names) unless user_names == :all roles = roles.all(:name => role_names) unless role_names == :all if role_conditions.include?(:except) roles = roles.all(:name.not => role_conditions[:except]) end raise DataMapper::ObjectNotFoundError if users.empty? or roles.empty? roles.each do |role| role.users += users end end def namespace(&block) self.class.draw(:parent => self, &block) end protected def load_keys_from_repository(user) path = File.join(self.expanded_key_repository_path, "#{user.name}.pub") narrate "Looking for key for #{user.name} in #{path}" if File.exists?(path) user.keys.create(:public_key => File.read(path)) end end end