You will need to perform a migration for this patch.
The projects table now has a column, called "approved", that
specifies whether the project has been approved or not. If not
approved then no products can be created and the project is only
visible to the owner and a user with project admin rights.
If a regular user requests a project be created, the project
record is created and marked as not approved. An email is sent to
the admin user with a link back to the new project.
If a user with project create rights creates a project, it's
automatically approved.
Signed-off-by: Darryl L. Pierce <mcpierce(a)gmail.com>
---
app/controllers/projects_controller.rb | 40 +++++++++++--------------
app/views/projects/_edit.html.erb | 12 +------
app/views/projects/index.html.erb | 7 +++-
app/views/projects/show.html.erb | 1 +
db/migrate/026_users_request_new_projects.rb | 33 +++++++++++++++++++++
test/functional/projects_controller_test.rb | 34 +++++++++++++---------
6 files changed, 79 insertions(+), 48 deletions(-)
create mode 100644 db/migrate/026_users_request_new_projects.rb
diff --git a/app/controllers/projects_controller.rb
b/app/controllers/projects_controller.rb
index 50329cb..f8aa305 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -45,7 +45,7 @@ class ProjectsController < ApplicationController
# GET /projects/new
def new
- if @user.can_create_projects?
+ if @user
@title = "New Project"
@project = Project.new(:owner_id => @user.id)
@source = params[:source] if params[:source]
@@ -69,27 +69,19 @@ class ProjectsController < ApplicationController
# POST /projects
def create
respond_to do |format|
- if @user.can_create_projects?
- @project = Project.new(params[:project])
-
- begin
- Project.transaction do
- if @project.save
- flash[:message] = "Project '#{(a)project.name}' created!"
- format.html { redirect_to params[:source] ? params[:source] :
project_url(@project) }
- else
- @title = "New Project"
- @project.valid?
- format.html { render :action => "new" }
- end
- end
- rescue Exception => error
- flash[:error] = "ERROR: #{error.message}"
- format.html { redirect_to params[:source] ? params[:source] : error_url }
+ @project = Project.new(params[:project])
+ # if the project is being created by an admin, then mark it approved
+ @project.approved = @user.can_create_projects?
+
+ Project.transaction do
+ if @project.save
+ flash[:message] = "Project '#{(a)project.name}' created!"
+ format.html { redirect_to params[:source] ? params[:source] :
project_url(@project) }
+ else
+ @title = "New Project"
+ @project.valid?
+ format.html { render :action => "new" }
end
- else
- flash[:error] = "You are not authorized to create projects."
- format.html { redirect_to params[:source] ? params[:source] : error_url }
end
end
end
@@ -145,6 +137,10 @@ class ProjectsController < ApplicationController
end
def setup_for_edit
- @users = User.find(:all, :order => 'display_name ASC')
+ if @user.can_create_projects?
+ @users = User.find(:all, :order => 'display_name ASC')
+ else
+ @users = [@user]
+ end
end
end
diff --git a/app/views/projects/_edit.html.erb b/app/views/projects/_edit.html.erb
index 153493f..72bd335 100644
--- a/app/views/projects/_edit.html.erb
+++ b/app/views/projects/_edit.html.erb
@@ -33,16 +33,8 @@
<tr>
<td class="label-required">Owner</td>
<td class="value">
- <% if @user.privileges.admin_projects %>
- <%= collection_select :project, :owner_id, @users, :id,
- :display_name, {:include_blank => true} %>
- <% else %>
- <% if @project.owner %>
- <%= h @project.owner.display_name %>
- <% else %>
- UNOWNED
- <% end %>
- <% end %>
+ <%= collection_select :project, :owner_id, @users, :id,
+ :display_name, {:include_blank => false} %>
<%= error_message_on(:project, :owner) %>
</td>
</tr>
diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb
index 824c010..d6b5447 100644
--- a/app/views/projects/index.html.erb
+++ b/app/views/projects/index.html.erb
@@ -8,7 +8,7 @@
<tr>
<td class="toolbar" colspan="2">
<%= link_to(image_tag("icons/new.png", :title => "Create a
new project..."),
- new_project_path) if @user && @user.can_create_projects? %>
+ new_project_path) if @user %>
</td>
</tr>
</tbody>
@@ -48,7 +48,10 @@
<tr class="<%= row_class %>">
<td class="row_id"><%= "#{project.id}"
%></td>
- <td><%= project.name %></td>
+ <td>
+ <%= project.name %>
+ <%= project.approved ? "" : " (Pending)" %>
+ </td>
<td><%= get_first_sentence project.description %></td>
<td><%= link_to project.owner.display_name, user_path(project.owner)
%></td>
<td><%= show_date(project.created_at) %></td>
diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb
index 504bf11..8d93f4c 100644
--- a/app/views/projects/show.html.erb
+++ b/app/views/projects/show.html.erb
@@ -13,6 +13,7 @@
<tbody>
<tr>
<td class="toolbar" colspan="2">
+ <%= link_to(image_tag("icons/add.png", :title => "Request a new
project..."), new_project_path) if @user %>
<%= link_to(image_tag("icons/back.png", :title =>
"Back..."),
projects_path) %>
<%= link_to(image_tag("icons/edit.png", :title => "Edit this
project..."),
diff --git a/db/migrate/026_users_request_new_projects.rb
b/db/migrate/026_users_request_new_projects.rb
new file mode 100644
index 0000000..e989101
--- /dev/null
+++ b/db/migrate/026_users_request_new_projects.rb
@@ -0,0 +1,33 @@
+# 026_users_request_new_projects.rb
+# Copyright (C) 2009, Darryl L. Pierce <mcpierce(a)gmail.com>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <
http://www.gnu.org/licenses/>.
+#
+
+class UsersRequestNewProjects < ActiveRecord::Migration
+ def self.up
+ Project.transaction do
+ add_column :projects, :approved, :boolean, :null => false, :default => false
+
+ Project.find(:all).each do |project|
+ project.approved = true
+ project.save
+ end
+ end
+ end
+
+ def self.down
+ remove_column :projects, :approved
+ end
+end
diff --git a/test/functional/projects_controller_test.rb
b/test/functional/projects_controller_test.rb
index 9a3fae0..f46ef34 100644
--- a/test/functional/projects_controller_test.rb
+++ b/test/functional/projects_controller_test.rb
@@ -35,6 +35,7 @@ class ProjectsControllerTest < ActionController::TestCase
@admin = users(:admin)
raise "Nonadmin and admin cannot be the same user!" if @nonadmin.id ==
@admin.id
+ raise "Admin must have project admin rights!" unless
@admin.can_create_projects?
end
# Ensures that showing the project index works as expected.
@@ -81,13 +82,15 @@ class ProjectsControllerTest < ActionController::TestCase
assert_redirected_to :controller => :home, :action => :login
end
- # Ensures that a user without project admin privileges cannot create a
- # project.
+ # Ensures that a user without project admin privileges can
+ # create a project but that it is not approved.
#
- def test_new_as_unauthorized_user
+ def test_new_as_nonadmin
get :new, {}, {:user_id => @nonadmin.id}
- assert_redirected_to error_url
+ assert_response :success
+ assert_equal 1, assigns['users'].size,
+ "The only owner a non-admin can assign is himself!"
end
# Ensures that starting off a new project works as expected.
@@ -96,11 +99,6 @@ class ProjectsControllerTest < ActionController::TestCase
get :new, {}, {:user_id => @admin.id}
assert_response :success
- assert assigns['project'], "Did not create a new project."
- assert_equal @admin.id, assigns['project'].owner_id,
- "Did not assign the default owner."
- assert assigns['users'], "Did not load the list of users."
- assert !assigns['source'], "Should not have stored a URL."
end
# Ensures that the url is held.
@@ -182,12 +180,17 @@ class ProjectsControllerTest < ActionController::TestCase
assert_redirected_to login_url
end
- # Ensures that a non-admin cannot create a project.
+ # Ensures that a non-admin can create an unapproved project.
#
def test_create_as_nonadmin
- post :create, {}, {:user_id => @nonadmin.id}
+ post :create,
+ {:project => {:name => 'test', :owner_id => @admin.id}},
+ {:user_id => @nonadmin.id}
- assert_redirected_to error_url
+ result = Project.find_by_name('test')
+ assert_redirected_to project_url(result)
+ assert result, "Project was not created!"
+ assert !result.approved, "Project should not have been approved!"
end
# Ensures that an invalid project returns the user to the edit page.
@@ -207,14 +210,17 @@ class ProjectsControllerTest < ActionController::TestCase
{:project => {:name => 'test', :owner_id => @admin.id}},
{:user_id => @admin.id}
- assert_redirected_to project_path(assigns['project'])
+ result = Project.find_by_name('test')
+ assert_redirected_to project_url(result)
+ assert result, "Project was not created!"
+ assert result.approved, "Project should have been approved!"
end
# Ensures the user is returned to the origin page if a url was provided.
#
def test_create_with_url
post :create,
- {:project => {:name => 'test', :owner_id => @admin.id},
+ {:project => {:name => 'test', :owner_id => @admin.id},
:source => "/farkle"},
{:user_id => @admin.id}
--
1.6.0.2