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 def grant(user_opts, role_opts, opts = {}) users = load_by_attribute(:users, :name, user_opts) roles = load_by_attribute(:roles, :name, role_opts) 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 def load_association(klass, opts = {}) association = self.send(klass.to_sym).all(opts) raise DataMapper::ObjectNotFoundError if association.empty? association end def load_by_attribute(klass, attribute, opts = {}) if opts == :all load_association(klass) else load_association(klass, attribute.to_sym => opts) end end end