diff options
author | Johan Sørensen <johan@johansorensen.com> | 2009-06-16 14:38:53 +0200 |
---|---|---|
committer | Johan Sørensen <johan@johansorensen.com> | 2009-06-17 12:21:21 +0200 |
commit | d2c36407a76f6946f366916882726ce0fca496d2 (patch) | |
tree | 8ce1fadd46bbb9b9718c131f10e4f6e8a104849a | |
parent | 4793b6e94da496a732262f81e77e61746e8ee98c (diff) | |
download | gitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.zip gitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.tar.gz gitorious-mainline-outdated-d2c36407a76f6946f366916882726ce0fca496d2.tar.bz2 |
Added Web Hook model
-rw-r--r-- | app/controllers/application_controller.rb | 16 | ||||
-rw-r--r-- | app/controllers/hooks_controller.rb | 57 | ||||
-rw-r--r-- | app/controllers/repositories_controller.rb | 18 | ||||
-rw-r--r-- | app/helpers/hooks_helper.rb | 2 | ||||
-rw-r--r-- | app/models/hook.rb | 25 | ||||
-rw-r--r-- | app/models/repository.rb | 1 | ||||
-rw-r--r-- | app/views/hooks/index.html.erb | 53 | ||||
-rw-r--r-- | app/views/hooks/new.html.erb | 50 | ||||
-rw-r--r-- | config/locales/en.rb | 4 | ||||
-rw-r--r-- | config/routes.rb | 1 | ||||
-rw-r--r-- | db/migrate/20090616085408_create_web_hooks.rb | 17 | ||||
-rw-r--r-- | test/functional/hooks_controller_test.rb | 108 | ||||
-rw-r--r-- | test/unit/helpers/hooks_helper_test.rb | 4 | ||||
-rw-r--r-- | test/unit/hook_test.rb | 29 | ||||
-rw-r--r-- | test/unit/repository_test.rb | 2 |
15 files changed, 370 insertions, 17 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c67362d..f0e1b3f 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -158,6 +158,22 @@ class ApplicationController < ActionController::Base @repository = Repository.find_by_name_and_project_id!(params[:repository_id], @project.id) end + def require_owner_adminship + unless @owner.admin?(current_user) + respond_to do |format| + format.html { + flash[:error] = I18n.t "repositories_controller.adminship_error" + redirect_to(@owner) + } + format.xml { + render :text => I18n.t( "repositories_controller.adminship_error"), + :status => :forbidden + } + end + return + end + end + def check_repository_for_commits unless @repository.has_commits? flash[:notice] = I18n.t "application.no_commits_notice" diff --git a/app/controllers/hooks_controller.rb b/app/controllers/hooks_controller.rb new file mode 100644 index 0000000..132da5f --- /dev/null +++ b/app/controllers/hooks_controller.rb @@ -0,0 +1,57 @@ +# encoding: utf-8 +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ + +class HooksController < ApplicationController + before_filter :login_required + before_filter :find_repository + before_filter :require_owner_adminship + renders_in_global_context + + def index + @hooks = @repository.hooks + @root = @repository + end + + def new + @hook = @repository.hooks.new + @hook.user = current_user + @root = @repository + end + + def create + @hook = @repository.hooks.new(params[:hook]) + @hook.user = current_user + @root = @repository + if @hook.save + redirect_to repo_owner_path(@repository, :project_repository_hooks_path, + @repository.project, @repository) + else + render "new" + end + end + # + # def destroy + # + # end + + protected + def find_repository + find_repository_owner + @repository = @owner.repositories.find_by_name!(params[:repository_id]) + end +end diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index c79aa7c..945bd4c 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -23,7 +23,7 @@ class RepositoriesController < ApplicationController before_filter :login_required, :except => [:index, :show, :writable_by] before_filter :find_repository_owner - before_filter :require_adminship, :only => [:edit, :update, :new, :create, :edit, :update, :committers] + before_filter :require_owner_adminship, :only => [:edit, :update, :new, :create, :edit, :update, :committers] before_filter :require_user_has_ssh_keys, :only => [:clone, :create_clone] before_filter :only_projects_can_add_new_repositories, :only => [:new, :create] skip_before_filter :public_and_logged_in, :only => [:writable_by] @@ -202,22 +202,6 @@ class RepositoriesController < ApplicationController end private - def require_adminship - unless @owner.admin?(current_user) - respond_to do |format| - format.html { - flash[:error] = I18n.t "repositories_controller.adminship_error" - redirect_to(@owner) - } - format.xml { - render :text => I18n.t( "repositories_controller.adminship_error"), - :status => :forbidden - } - end - return - end - end - def only_projects_can_add_new_repositories if !@owner.is_a?(Project) respond_to do |format| diff --git a/app/helpers/hooks_helper.rb b/app/helpers/hooks_helper.rb new file mode 100644 index 0000000..14354af --- /dev/null +++ b/app/helpers/hooks_helper.rb @@ -0,0 +1,2 @@ +module HooksHelper +end diff --git a/app/models/hook.rb b/app/models/hook.rb new file mode 100644 index 0000000..5434cc6 --- /dev/null +++ b/app/models/hook.rb @@ -0,0 +1,25 @@ +# encoding: utf-8 +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ + +class Hook < ActiveRecord::Base + belongs_to :repository + belongs_to :user + + validates_presence_of :repository, :user, :url + +end diff --git a/app/models/repository.rb b/app/models/repository.rb index 1fbb263..ee01b8a 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -50,6 +50,7 @@ class Repository < ActiveRecord::Base :class_name => 'MergeRequest', :order => "id desc", :dependent => :destroy has_many :cloners, :dependent => :destroy has_many :events, :as => :target, :dependent => :destroy + has_many :hooks, :dependent => :destroy NAME_FORMAT = /[a-z0-9_\-]+/i.freeze validates_presence_of :user_id, :name, :owner_id, :project_id diff --git a/app/views/hooks/index.html.erb b/app/views/hooks/index.html.erb new file mode 100644 index 0000000..eabde40 --- /dev/null +++ b/app/views/hooks/index.html.erb @@ -0,0 +1,53 @@ +<% +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ +%> + +<% @page_title = t("views.hooks.repository_web_hooks") -%> +<%= breadcrumbs_from(@root) -%> + +<h1><%= t("views.hooks.repository_web_hooks") %></h1> + +<table class="listing"> + <thead> + <th>Created</th> + <th>URL</th> + <th>Last response</th> + <th></th> + </thead> + <% @hooks.each do |hook| -%> + <tr class="<%= cycle('even', 'odd') -%>"> + <td><%= hook.created_at.to_s(:short) -%></td> + <td><%=h hook.url -%></td> + <td><code><%=h hook.last_response -%></code></td> + <td> + <%= button_to t("views.common.delete"), repo_owner_path(@repository, + :project_repository_hook_path, @repository.project, @repository, hook), + :confirm => t("views.common.confirm"), :method => :delete, :class => "inline" -%> + </td> + </tr> + <% end -%> +</table> + +<% content_for :sidebar do -%> + <ul class="links"> + <li class="new_hook"> + <%= link_to t("views.hooks.add_hook"), repo_owner_path(@repository, + :new_project_repository_hook_path, @repository.project, @repository) -%></li> + </ul> +<% end -%> + diff --git a/app/views/hooks/new.html.erb b/app/views/hooks/new.html.erb new file mode 100644 index 0000000..58ef4bb --- /dev/null +++ b/app/views/hooks/new.html.erb @@ -0,0 +1,50 @@ +<% +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ +%> + +<% help_box do -%> +<p> + A <em>hook</em> is a callback URL Gitorious will post the contents of a push + to. The contents and format is described + <a href="http://gitorious.org/gitorious/pages/WebHooks">here</a> +</p> +<p> + In a nutshell, a JSON hash i POSTed to the url you give here whenever a set + of commits is pushed to this repository +</p> +<% end -%> + +<%= error_messages_for :hook -%> +<% form_for :hook, + :url => repo_owner_path(@repository, [@repository.project, @repository, @hook]) do |f| -%> + <p> + <%= f.label :url %>: <br /> + <%= f.text_field :url %> + </p> + <p><%= f.submit "Add commit callback URL" -%></p> +<% end -%> + +<% content_for(:sidebar) do -%> + <% content_for :sidebar do -%> + <ul class="links"> + <li class="repository"> + <%= link_to "Back to repository", repo_owner_path(@repository, + :project_repository_path, @repository.project, @repository) -%></li> + </ul> + <% end -%> +<% end -%>
\ No newline at end of file diff --git a/config/locales/en.rb b/config/locales/en.rb index 69d6ebc..ed52d23 100644 --- a/config/locales/en.rb +++ b/config/locales/en.rb @@ -210,6 +210,10 @@ :your_public_key => "Your public key", :hint => "It's generally located in ~/.ssh/id_rsa.pub or ~/.ssh/id_dsa.pub. If you want to use multiple keys you'll have to add each of them seperately. <br />The key should be in the format of: <br /><code>ssh-algorithm base64-content you@somehost</code>", }, + :hooks => { + :repository_web_hooks => "Repository Web Hooks", + :add_hook => "Add Hook" + }, :users => { :activated => "Activated?", :suspended => "Suspended?", diff --git a/config/routes.rb b/config/routes.rb index 6dcd998..53e6d96 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,7 @@ ActionController::Routing::Routes.draw do |map| :auto_complete_for_group_name => :post, :auto_complete_for_user_login => :post } + repo.resources :hooks repo.formatted_commits_feed "commits/*branch/feed.:format", :controller => "commits", :action => "feed", :conditions => {:feed => :get} diff --git a/db/migrate/20090616085408_create_web_hooks.rb b/db/migrate/20090616085408_create_web_hooks.rb new file mode 100644 index 0000000..c3739cd --- /dev/null +++ b/db/migrate/20090616085408_create_web_hooks.rb @@ -0,0 +1,17 @@ +class CreateWebHooks < ActiveRecord::Migration + def self.up + create_table :hooks do |t| + t.integer :user_id + t.integer :repository_id + t.string :url + t.string :last_response + + t.timestamps + end + add_index :hooks, :repository_id + end + + def self.down + drop_table :hooks + end +end diff --git a/test/functional/hooks_controller_test.rb b/test/functional/hooks_controller_test.rb new file mode 100644 index 0000000..b918899 --- /dev/null +++ b/test/functional/hooks_controller_test.rb @@ -0,0 +1,108 @@ +# encoding: utf-8 +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ + +require File.dirname(__FILE__) + '/../test_helper' + +class HooksControllerTest < ActionController::TestCase + + def setup + @project = projects(:johans) + @repository = @project.repositories.mainlines.first + login_as :johan + end + + should_render_in_global_context + + context "index" do + should "require login" do + session[:user_id] = nil + get :index, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_redirected_to(new_sessions_path) + end + + should "require reposítory adminship" do + login_as :moe + get :index, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_match(/only repository admins are allowed/, flash[:error]) + assert_redirected_to(project_path(@project)) + end + + should "set find the correct owner and repository" do + get :index, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_equal @project, assigns(:owner) + assert_equal @repository, assigns(:repository) + end + + should "be successfull" do + get :index, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_response :success + assert_not_nil assigns(:hooks) + end + end + + context "new / create" do + setup do + @project = projects(:johans) + @repository = @project.repositories.mainlines.first + login_as :johan + end + + should "require login" do + session[:user_id] = nil + get :new, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_redirected_to(new_sessions_path) + end + + should "require reposítory adminship" do + login_as :moe + get :new, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_match(/only repository admins are allowed/, flash[:error]) + assert_redirected_to(project_path(@project)) + end + + should "be successfull" do + get :new, :project_id => @project.to_param, :repository_id => @repository.to_param + assert_response :success + assert assigns(:hook).new_record? + assert_equal users(:johan), assigns(:hook).user + end + + should "create a new hook" do + assert_difference("@repository.hooks.count") do + post :create, :project_id => @project.to_param, + :repository_id => @repository.to_param, :hook => { + :url => "http://google.com" + } + assert_response :redirect + end + assert_redirected_to project_repository_hooks_path(@project, @repository) + assert_equal users(:johan), assigns(:hook).user + end + + should "not create a new hook when invalid data is submitted" do + assert_no_difference("@repository.hooks.count") do + post :create, :project_id => @project.to_param, + :repository_id => @repository.to_param, :hook => { + :url => '' + } + end + assert_response :success + assert_template "new" + end + end +end diff --git a/test/unit/helpers/hooks_helper_test.rb b/test/unit/helpers/hooks_helper_test.rb new file mode 100644 index 0000000..24c0cc4 --- /dev/null +++ b/test/unit/helpers/hooks_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class HooksHelperTest < ActionView::TestCase +end diff --git a/test/unit/hook_test.rb b/test/unit/hook_test.rb new file mode 100644 index 0000000..0ec4f5c --- /dev/null +++ b/test/unit/hook_test.rb @@ -0,0 +1,29 @@ +# encoding: utf-8 +#-- +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +#++ + +require File.dirname(__FILE__) + '/../test_helper' + +class HookTest < ActiveSupport::TestCase + + should_belong_to :repository + should_validate_presence_of :user, :repository, :url + + should_eventually "only allow N hooks per repository" do + flunk + end +end diff --git a/test/unit/repository_test.rb b/test/unit/repository_test.rb index 9ee37ac..66c5172 100644 --- a/test/unit/repository_test.rb +++ b/test/unit/repository_test.rb @@ -39,6 +39,8 @@ class RepositoryTest < ActiveSupport::TestCase should_validate_uniqueness_of :hashed_path should_validate_uniqueness_of :name, :scoped_to => :project_id, :case_sensitive => false + should_have_many :hooks, :dependent => :destroy + should " only accept names with alphanum characters in it" do @repository.name = "foo bar" assert !@repository.valid?, 'valid? should be false' |