<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/views/admin/layout/_site.rhtml</filename>
    </added>
    <added>
      <filename>app/views/admin/user/_site.rhtml</filename>
    </added>
    <added>
      <filename>db/migrate/004_create_default_site.rb</filename>
    </added>
    <added>
      <filename>db/migrate/005_add_site_id_to_users.rb</filename>
    </added>
    <added>
      <filename>db/migrate/006_add_site_id_to_layouts.rb</filename>
    </added>
    <added>
      <filename>lib/multi_site/layout_extensions.rb</filename>
    </added>
    <added>
      <filename>lib/multi_site/snippet_controller_extensions.rb</filename>
    </added>
    <added>
      <filename>lib/multi_site/user_extensions.rb</filename>
    </added>
    <added>
      <filename>test/functional/snippet_controller_extensions_test.rb</filename>
    </added>
    <added>
      <filename>test/unit/layout_extensions_test.rb</filename>
    </added>
    <added>
      <filename>test/unit/user_extensions_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,10 +1,11 @@
 = Multi Site
 
 Created by Sean Cribbs, November 2007. Inspired by the original virtual_domain
-behavior.
+behavior. Extended by Nick Plante, March 2008. 
 
 Multi Site allows you to host multiple websites on a single Radiant
-installation.
+installation. It also allows you to assign users to specific sites, scoping
+all their administrative activity to that one domain.
 
 Each site has its own independent sitemap/page-tree and these attributes:
 
@@ -16,10 +17,23 @@ Each site has its own independent sitemap/page-tree and these attributes:
   homepage_id: The numerical database ID of the root page (usually
                you can just leave this alone).
 
+Any existing pages that you have will be scoped to the 'Default' site, which
+is the site that will be seen for requests that don't match a particular
+base_domain.
+
+In addition to scoping users to sites, layouts can also be scoped to a
+particular site. Use the selection box on the edit layout page to assign a
+layout to a site. If no site is chosen, the layout will be available for
+selection from any site. Note that snippets are not limited in this way,
+but that access to snippets has been DISABLED for &quot;regular&quot; users (those
+users who are not developers or admins).
+
+If you don't like it, feel free to make suggestions or change it :).
+
 Included images are slightly modified from FamFamFam Silk Icons by Mark James:
 http://www.famfamfam.com/lab/icons/silk/
 
-*** THIS EXTENSION REQUIRES THE 'SHARDS' EXTENSION TO BE INSTALLED ***
+*** THIS EXTENSION REQUIRES RADIANT 0.6.7 OR LATER ***
 
 == Installation
 
@@ -39,4 +53,4 @@ http://www.famfamfam.com/lab/icons/silk/
 == Acknowledgments
 
 Thanks to Digital Pulp, Inc. for funding the initial development of this
-extension as part of the Redken.com project.
\ No newline at end of file
+extension as part of the Redken.com project. </diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,10 @@
 class Site &lt; ActiveRecord::Base
+  has_many :users
+  has_many :layouts
+
   acts_as_list
   order_by &quot;position ASC&quot;
+
   class &lt;&lt; self
     def find_for_host(hostname = '')
       default, normal = find(:all).partition {|s| s.domain.blank? }
@@ -29,11 +33,11 @@ class Site &lt; ActiveRecord::Base
   
   def create_homepage
     if self.homepage_id.blank?
-        self.homepage = self.build_homepage(:title =&gt; &quot;#{self.name} Homepage&quot;, 
-                           :slug =&gt; &quot;#{self.name.slugify}&quot;, :breadcrumb =&gt; &quot;Home&quot;, 
-                           :status =&gt; Status[:draft])
-        self.homepage.parts &lt;&lt; PagePart.new(:name =&gt; &quot;body&quot;, :content =&gt; &quot;&quot;)
-        save
+      self.homepage = self.build_homepage(:title =&gt; &quot;#{self.name} Homepage&quot;, 
+                       :slug =&gt; &quot;#{self.name.slugify}&quot;, :breadcrumb =&gt; &quot;Home&quot;, 
+                       :status =&gt; Status[:draft])
+      self.homepage.parts &lt;&lt; PagePart.new(:name =&gt; &quot;body&quot;, :content =&gt; &quot;&quot;)
+      save
     end
   end
 end</diff>
      <filename>app/models/site.rb</filename>
    </modified>
    <modified>
      <diff>@@ -14,12 +14,13 @@
     margin-right: 10px;
   }
 &lt;% end %&gt;
-&lt;div id=&quot;sites&quot;&gt;
-  &lt;% Site.find(:all).each do |site| %&gt;
-    &lt;% name = (@site == site) ? &quot;&lt;strong&gt;#{site.name}&lt;/strong&gt;&quot; : site.name -%&gt;
-    &lt;%= link_to name, page_index_path(:root =&gt; site.homepage) %&gt;
-  &lt;% end %&gt;
-&lt;/div&gt;
+&lt;% if developer? &amp;&amp; Site.count &gt; 1 %&gt;
+  &lt;div id=&quot;sites&quot;&gt;
+    &lt;strong&gt;Site:&lt;/strong&gt; 
+    &lt;%= select_tag('site-selector', options_from_collection_for_select(Site.find(:all), :homepage_id, :name, @site.nil? ? nil : @site.homepage_id), 
+      :onchange =&gt; &quot;document.location = '#{page_index_path}?root=' + this.options[this.selectedIndex].value&quot;) %&gt;
+  &lt;/div&gt;
+&lt;% end %&gt;
 
 &lt;% if Radiant::Config['multi_site.scoped?'] %&gt;
   &lt;% content_for :page_scripts do %&gt;</diff>
      <filename>app/views/admin/page/_site_subnav.rhtml</filename>
    </modified>
    <modified>
      <diff>@@ -1,53 +1,113 @@
 module MultiSite::PageControllerExtensions
   def self.included(base)
     base.class_eval {
+      before_filter :set_site, :only =&gt; [:remove, :new, :edit]
+      around_filter :scope_layouts_to_site, :only =&gt; [:new, :edit]
+
       alias_method_chain :index, :root
-      alias_method_chain :clear_model_cache, :site
-      alias_method_chain :continue_url, :site
-      %w{remove}.each do |m|
-        alias_method_chain m.to_sym, :back
+      %w{edit new remove continue_url clear_model_cache}.each do |m|
+        alias_method_chain m.to_sym, :site
       end
     }
   end
   
   def index_with_root
-    if params[:root] # If a root page is specified
-      @homepage = Page.find(params[:root])
-      @site = @homepage.root.site
-    elsif @site = Site.find(:first, :order =&gt; &quot;position ASC&quot;) # If there is a site defined
-      if @site.homepage
+    cookies.delete('expanded_rows')
+    if user_developer? # or admin
+      if params[:root] # If a root page is specified (should this ever be required for non-developers?)
+        @homepage = Page.find(params[:root])
+        @site = @homepage.root.site
+      elsif (@site = Site.find(:first, :order =&gt; &quot;position ASC&quot;)) &amp;&amp; @site.homepage # If there is a site defined
         @homepage = @site.homepage
       else
         index_without_root
       end
-    else # Just do the default
-      index_without_root
+    elsif (@site = current_user.site) &amp;&amp; @site.homepage
+      @homepage = @site.homepage
+    else
+      access_denied
     end
   end
-    
-  def remove_with_back
-    @page = Page.find(params[:id])
-    if request.post?
-      announce_pages_removed(@page.children.count + 1)
-      @page.destroy
-      return_url = session[:came_from]
-      session[:came_from] = nil
-      if return_url &amp;&amp; return_url != page_index_url(:root =&gt; @page)
-        redirect_to return_url
+
+  def remove_with_site
+    if user_authorized?
+      if request.post?
+        announce_pages_removed(@page.children.count + 1)
+        @page.destroy
+        return_url = session[:came_from]
+        session[:came_from] = nil
+        if return_url &amp;&amp; return_url != page_index_url(:root =&gt; @page)
+          redirect_to return_url
+        else
+          redirect_to page_index_url(:page =&gt; @page.parent)
+        end
       else
-        redirect_to page_index_url(:page =&gt; @page.parent)
+        session[:came_from] = request.env[&quot;HTTP_REFERER&quot;]
       end
     else
-      session[:came_from] = request.env[&quot;HTTP_REFERER&quot;]
+      access_denied
     end
   end
-  
+
   def clear_model_cache_with_site
     Page.current_site ||= @site || @page.root.site
     clear_model_cache_without_site
   end
-  
-  def continue_url_with_site(options={})
-    options[:redirect_to] || (params[:continue] ? page_edit_url(:id =&gt; model.id) : page_index_url(:root =&gt; model.root.id))
+
+  def new_with_site
+    if user_authorized?
+      if request.get?
+        @page = Page.new_with_defaults(config)
+      else
+        @page = Page.new
+      end
+
+      @page.slug = params[:slug]
+      @page.breadcrumb = params[:breadcrumb]
+      @page.parent = Page.find_by_id(params[:parent_id])
+      render :action =&gt; :edit if handle_new_or_edit_post
+    else
+      access_denied
+    end
+  end
+
+  def edit_with_site
+    if user_authorized?
+      @old_page_url = @page.url
+      handle_new_or_edit_post
+    else
+      access_denied
+    end 
   end
-end
\ No newline at end of file
+
+  protected
+
+    def continue_url_with_site(options = {})
+      options[:redirect_to] || (params[:continue] ? model_edit_url(:id =&gt; model.id) : model_index_url(:root =&gt; model.root.id))
+    end
+
+    def access_denied
+      flash[:error] = 'Access denied.'
+      redirect_to login_url
+    end
+
+    def user_developer?
+      current_user and (current_user.developer? or current_user.admin?)
+    end
+
+    def user_authorized?
+      user_developer? || (!current_user.nil? &amp;&amp; current_user.owner?(@site))
+    end
+
+    def set_site
+      id = params[:id] || params[:root] || params[:parent_id]
+      @page = Page.find(id)
+      @site = @page.root.site
+    end
+
+    def scope_layouts_to_site
+      Layout.scoped_to_site(@site.id) do
+        yield
+      end
+    end
+end</diff>
      <filename>lib/multi_site/page_controller_extensions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,7 @@ module MultiSite::ResponseCacheExtensions
   
   def self.included(base)
     base.alias_method_chain :page_cache_path, :site
+    base.alias_method_chain :clear, :site
   end
   
   def page_cache_path_with_site(path)
@@ -11,4 +12,11 @@ module MultiSite::ResponseCacheExtensions
     cache_path = File.expand_path(File.join(root_dir, path), root_dir)
     cache_path if cache_path.index(root_dir) == 0
   end
-end
\ No newline at end of file
+
+  def clear_with_site(site = nil)
+    dirs = site.nil? ? Dir[&quot;#{directory}/*&quot;] : Dir[&quot;#{directory}/#{site.base_domain}&quot;]
+    dirs.each do |f|
+      FileUtils.rm_rf f
+    end
+  end
+end</diff>
      <filename>lib/multi_site/response_cache_extensions.rb</filename>
    </modified>
    <modified>
      <diff>@@ -22,13 +22,27 @@ class MultiSiteExtension &lt; Radiant::Extension
     require_dependency 'application'
     
     Page.send :include, MultiSite::PageExtensions
+    ResponseCache.send :include, MultiSite::ResponseCacheExtensions
+    User.send :include, MultiSite::UserExtensions
+    Layout.send :include, MultiSite::LayoutExtensions
+
     SiteController.send :include, MultiSite::SiteControllerExtensions
     Admin::PageController.send :include, MultiSite::PageControllerExtensions
-    ResponseCache.send :include, MultiSite::ResponseCacheExtensions
+    Admin::SnippetController.send :include, MultiSite::SnippetControllerExtensions
+
     Radiant::Config[&quot;dev.host&quot;] = 'preview'
+
     # Add site navigation
     admin.page.index.add :top, &quot;site_subnav&quot;
     admin.tabs.add &quot;Sites&quot;, &quot;/admin/sites&quot;, :visibility =&gt; [:admin]
+
+    # Make snippets visible only to admins and developers
+    admin.tabs.remove &quot;Snippets&quot;
+    admin.tabs.add &quot;Snippets&quot;, &quot;/admin/snippets&quot;, :before =&gt; &quot;Layouts&quot;, :visibility =&gt; [:admin, :developer]
+
+    # Add site admin scoping fields
+    admin.user.edit.add :form, &quot;site&quot;, :before =&gt; &quot;edit_table_footer&quot;
+    admin.layout.edit.add :form, &quot;site&quot;, :before =&gt; &quot;edit_timestamp&quot;
   end
   
   def deactivate</diff>
      <filename>multi_site_extension.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,47 +4,203 @@ require File.dirname(__FILE__) + '/../test_helper'
 Admin::PageController.class_eval { def rescue_action(e) raise e end }
 
 class PageControllerExtensionsTest &lt; Test::Unit::TestCase
+  include ActionController::UrlWriter
+  
   fixtures :sites, :pages
-  test_helper :page, :login
+  test_helper :pages, :login, :difference
+  
+  class TestResponse &lt; ActionController::TestResponse
+    def initialize(body = '', headers = {})
+      self.body = body
+      self.headers = headers
+    end
+  end
   
   def setup
     @controller = Admin::PageController.new
     @request    = ActionController::TestRequest.new
     @response   = ActionController::TestResponse.new
-    login_as(:existing)
+
+    default_url_options[:host] = 'test.host'
   end
   
   def test_should_set_root_to_given_page_id
+    login_as(:developer) # or admin
     get :index, :root =&gt; 5
     assert_response :success
     assert_not_nil assigns(:homepage)
     assert_equal 5, assigns(:homepage).id
     assert_equal sites(:one), assigns(:site)
   end
+
+  def test_should_deny_regular_user_access_to_other_sites
+    login_as(:existing)
+    get :index, :root =&gt; 5
+    assert_response :redirect
+    assert_redirected_to login_url
+  end
   
   def test_should_pick_first_site_if_no_root_given
+    login_as(:developer) # non-devel or admin users are bound to their own sites
     get :index
     assert_response :success
     assert_equal pages(:homepage), assigns(:homepage)
     assert_equal sites(:one), assigns(:site)
   end
-  
+
   def test_should_fallback_on_default_when_no_sites_defined
+    login_as(:developer) # or admin
     Site.delete_all
     get :index
     assert_response :success
     assert_equal pages(:homepage), assigns(:homepage)
   end
+
+  def test_should_deny_access_if_user_site_deleted
+    user = users(:existing)
+    user.site = sites(:one)
+    user.save
+
+    login_as(:existing)
+    Site.delete_all
+    get :index
+    assert_response :redirect
+    assert_redirected_to login_url
+  end
+  
+  def test_should_remove_page_if_site_owner
+    create_pages_for(sites(:two))
+    @user = users(:existing)
+    @user.site = sites(:two)
+    @user.save
+    
+    login_as(:existing)
+    assert_difference(Page, :count, -1) do
+      post :remove, :id =&gt; sites(:two).homepage.children[0].id
+      assert_response :redirect
+      assert sites(:two), assigns(:site)
+    end
+  end
+  
+  def test_should_deny_remove_page_if_user_is_not_owner
+    login_as(:existing)
+    assert_no_difference(Page, :count) do
+      post :remove, :id =&gt; pages(:childless)
+      assert_response :redirect
+      assert_redirected_to login_url
+    end
+  end
+  
+  def test_should_redirect_after_remove
+    create_pages_for(sites(:two))
+    login_as(:developer)
+    
+    assert_difference(Page, :count, -1) do
+      post :remove, :id =&gt; sites(:two).homepage.children[0].id
+      assert_response :redirect
+      assert sites(:two), assigns(:site)
+    end
+  end
+  
+  def test_should_create_user_site_page
+    @user = users(:existing)
+    @user.site = sites(:two)
+    @user.save
+    
+    create_pages_for(sites(:two))    
+
+    login_as(:existing)
+    assert_difference(Page, :count) do
+      post :new, :parent_id =&gt; sites(:two).homepage_id, :page =&gt; page_params(:title =&gt; 'xyz', :slug =&gt; 'xyz')
+      assert_response :redirect
+      assert_equal sites(:two), assigns(:site)
+    end
+  end
+  
+  def test_should_limit_create_to_user_site
+    login_as(:existing)
+    assert_no_difference(Page, :count) do
+      post :new, :parent_id =&gt; pages(:homepage), :page =&gt; page_params(:title =&gt; 'xyz', :slug =&gt; 'xyz')
+      assert_response :redirect
+      assert_redirected_to login_url
+    end
+  end
+  
+  def test_should_redirect_on_create # admin or developer
+    create_pages_for(sites(:two))
+    
+    login_as(:developer)
+    assert_difference(Page, :count) do
+      post :new, :parent_id =&gt; sites(:two).homepage_id, :page =&gt; page_params(:title =&gt; 'xyz', :slug =&gt; 'xyz')
+      assert_response :redirect
+      assert_equal sites(:two), assigns(:site)
+    end
+  end
+  
+  def test_should_edit_user_site_page
+    @user = users(:existing)
+    @user.site = sites(:one)
+    @user.save
+    
+    login_as(:existing)
+    post :edit, :id =&gt; pages(:homepage), :page =&gt; { :title =&gt; 'updated', :slug =&gt; 'updated' }
+    assert_response :redirect
+    assert_equal sites(:one), assigns(:site)
+    
+    assert_equal 'updated', sites(:one).homepage.title
+  end
+  
+  def test_should_limit_edit_to_user_site
+    login_as(:existing)
+    title = pages(:homepage).title
+    post :edit, :id =&gt; pages(:homepage), :page =&gt; { :title =&gt; 'updated', :slug =&gt; 'updated' }
+    assert_response :redirect
+    assert_redirected_to login_url
+    assert_equal title, pages(:homepage).reload.title
+  end
+  
+  def test_should_redirect_on_edit # admin or developer
+    login_as(:developer)    
+    post :edit, :id =&gt; pages(:homepage), :page =&gt; { :title =&gt; 'updated', :slug =&gt; 'updated' }
+    assert_response :redirect
+    assert_equal pages(:homepage).root.site, assigns(:site)
+    assert_equal 'updated', pages(:homepage).reload.title
+  end
   
   def test_should_set_site_when_clearing_cache
+    Page.send &quot;current_site=&quot;, nil 
     @controller.send :instance_variable_set, &quot;@page&quot;, pages(:homepage)
     @controller.send :clear_model_cache
     assert_equal sites(:one), Page.current_site
   end
-  
-  def test_should_redirect_to_same_site_after_edit
-    post :edit, :id =&gt; 2
-    assert_response :redirect
-    assert_redirected_to page_index_url(:root =&gt; 1)
+
+  def test_should_scope_layouts_to_site
+    @user = users(:existing)
+    @user.site = sites(:one)
+    @user.save
+
+    @layout = Layout.create(:name =&gt; &quot;Layout for site&quot;, :site =&gt; sites(:two))
+
+    login_as(:existing)
+    get :edit, :id =&gt; pages(:homepage)
+    assert_response :success
+    assert_select &quot;select#page_layout_id&quot; do
+      assert_select &quot;option&quot;, Layout.count(:conditions =&gt; &quot;site_id IS NULL or site_id = #{@user.site_id}&quot;) + 1 # +1 is inherit
+    end
   end
+
+  protected
+
+    def create_pages_for(site)
+      homepage = create_test_page(:title =&gt; &quot;new home page&quot;, :slug =&gt; &quot;new1&quot;)
+      childpage = create_test_page(:title =&gt; &quot;new child page&quot;, :slug =&gt; &quot;new2&quot;, :parent_id =&gt; homepage.id)
+      site.homepage = homepage
+      site.save
+    end
+    
+    def create_cached_pages_for(site)      
+      Page.current_site = site
+      @cache.cache_response('test', TestResponse.new('test'))
+      assert_equal 2, Dir[&quot;#{@cache_dir}/#{site.base_domain}/*&quot;].size
+    end
 end</diff>
      <filename>test/functional/page_controller_extensions_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,6 +6,7 @@ SitesController.class_eval { def rescue_action(e) raise e end }
 class SitesControllerTest &lt; Test::Unit::TestCase
   test_helper :login, :difference
   fixtures :sites
+
   def setup
     @controller = SitesController.new
     @request    = ActionController::TestRequest.new
@@ -45,8 +46,6 @@ class SitesControllerTest &lt; Test::Unit::TestCase
     assert_difference Site, :count do
       post :create, :site =&gt; {:name =&gt; &quot;New site&quot;, :domain =&gt; &quot;new-site&quot;, :position =&gt; nil, :base_domain =&gt; &quot;new-site.dp.com&quot;}
       assert_response :redirect
-      assert_equal &quot;New site&quot;, assigns(:site).name
-      assert_equal &quot;new-site&quot;, assigns(:site).domain
     end
   end
   </diff>
      <filename>test/functional/sites_controller_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,9 +2,22 @@ require File.dirname(__FILE__) + '/../test_helper'
 
 class ResponseCacheExtensionsTest &lt; Test::Unit::TestCase
   fixtures :sites
+
+  class TestResponse &lt; ActionController::TestResponse
+    def initialize(body = '', headers = {})
+      self.body = body
+      self.headers = headers
+    end
+  end
   
   def setup
-    @cache = ResponseCache.new
+    @cache_dir = File.expand_path(&quot;#{RAILS_ROOT}/test/cache&quot;)
+    Dir[&quot;#{@cache_dir}/*&quot;].each { |d| FileUtils.rm_rf d }
+
+    @cache = ResponseCache.new(
+      :directory =&gt; @cache_dir,
+      :perform_caching =&gt; true
+    )
   end
   
   def test_should_scope_cache_location_to_current_site
@@ -17,4 +30,32 @@ class ResponseCacheExtensionsTest &lt; Test::Unit::TestCase
     assert_equal File.join(base_path, '_site-root'), @cache.send(:page_cache_path, &quot;/&quot;)
     assert_equal File.join(base_path, 'blah'), @cache.send(:page_cache_path_without_site, '/mysite.domain.com/blah')
   end
-end
\ No newline at end of file
+
+  def test_should_clear_site_cache
+    Page.current_site = sites(:one)
+    @cache.cache_response(&quot;test1&quot;, response('content'))
+    @cache.cache_response(&quot;test2&quot;, response('content'))
+    assert_equal 1, Dir[&quot;#{@cache_dir}/*&quot;].size
+    assert_equal 4, Dir[&quot;#{@cache_dir}/#{sites(:one).base_domain}/*&quot;].size
+
+    @cache.clear_with_site(sites(:one))
+    assert_equal 0, Dir[&quot;#{@cache_dir}/#{sites(:one).base_domain}/*&quot;].size
+  end
+
+  def test_should_clear_all_site_caches
+    Page.current_site = sites(:one)
+    @cache.cache_response(&quot;test1&quot;, response('content'))
+    @cache.cache_response(&quot;test2&quot;, response('content'))
+    assert_equal 1, Dir[&quot;#{@cache_dir}/*&quot;].size
+    assert_equal 4, Dir[&quot;#{@cache_dir}/#{sites(:one).base_domain}/*&quot;].size
+
+    @cache.clear_with_site(nil)
+    assert_equal 0, Dir[&quot;#{@cache_dir}/*&quot;].size
+  end
+
+  private
+
+    def response(*args)
+      TestResponse.new(*args)
+    end
+end</diff>
      <filename>test/unit/response_cache_extensions_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b0563cf47525224bc1fb1e0a0a5dab8522d583bb</id>
    </parent>
  </parents>
  <author>
    <name>Nick Plante</name>
    <email>nap@zerosum.org</email>
  </author>
  <url>http://github.com/zapnap/radiant-multi-site-extension/commit/46a035d00126be51a49f431e4838f3968d156486</url>
  <id>46a035d00126be51a49f431e4838f3968d156486</id>
  <committed-date>2008-06-24T09:51:40-07:00</committed-date>
  <authored-date>2008-06-24T09:51:40-07:00</authored-date>
  <message>add scoped multi-site updates as described at http://blog.zerosum.org/2008/4/3/radiant-super-multi
 * scopes user level access to individual sites (admins and developers still have access to all sites)
 * regular users cannot see, edit, or access other user sites that they do not own
 * optionally scopes layouts to sites
 * snippets usable everywhere, but display and editing of snippets limited to admins/developers

updated for radiant 0.6.7</message>
  <tree>7581446b1ff380cfa8a3dc6df1c209838d65fd01</tree>
  <committer>
    <name>Nick Plante</name>
    <email>nap@zerosum.org</email>
  </committer>
</commit>
