Commit cbd78922ee43c0124458e2867071f752cae712f4

Authored by Dmitriy Zaporozhets
2 parents 09b877ef dda6b0ab

Merge branch 'deploy_keys'

Conflicts:
	app/views/layouts/project.html.haml
	db/schema.rb
app/controllers/deploy_keys_controller.rb 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +class DeployKeysController < ApplicationController
  2 + respond_to :js, :html
  3 + layout "project"
  4 + before_filter :project
  5 +
  6 + # Authorize
  7 + before_filter :add_project_abilities
  8 + before_filter :authorize_admin_project!
  9 +
  10 + def project
  11 + @project ||= Project.find_by_code(params[:project_id])
  12 + end
  13 +
  14 + def index
  15 + @keys = @project.deploy_keys.all
  16 + end
  17 +
  18 + def show
  19 + @key = @project.deploy_keys.find(params[:id])
  20 + end
  21 +
  22 + def new
  23 + @key = @project.deploy_keys.new
  24 +
  25 + respond_with(@key)
  26 + end
  27 +
  28 + def create
  29 + @key = @project.deploy_keys.new(params[:key])
  30 + @key.save
  31 +
  32 + respond_with(@key)
  33 + end
  34 +
  35 + def destroy
  36 + @key = @project.deploy_keys.find(params[:id])
  37 + @key.destroy
  38 +
  39 + respond_to do |format|
  40 + format.html { redirect_to project_deploy_keys_url }
  41 + format.js { render :nothing => true }
  42 + end
  43 + end
  44 +end
... ...
app/models/key.rb
1 1 class Key < ActiveRecord::Base
2 2 belongs_to :user
  3 + belongs_to :project
3 4  
4 5 validates :title,
5 6 :presence => true,
... ... @@ -15,7 +16,11 @@ class Key &lt; ActiveRecord::Base
15 16 after_destroy :repository_delete_key
16 17  
17 18 def set_identifier
18   - self.identifier = "#{user.identifier}_#{Time.now.to_i}"
  19 + if is_deploy_key
  20 + self.identifier = "deploy_#{project.code}_#{Time.now.to_i}"
  21 + else
  22 + self.identifier = "#{user.identifier}_#{Time.now.to_i}"
  23 + end
19 24 end
20 25  
21 26 def update_repository
... ... @@ -31,10 +36,18 @@ class Key &lt; ActiveRecord::Base
31 36 c.update_projects(projects)
32 37 end
33 38 end
  39 +
  40 + def is_deploy_key
  41 + true if project_id
  42 + end
34 43  
35 44 #projects that has this key
36 45 def projects
37   - user.projects
  46 + if is_deploy_key
  47 + [project]
  48 + else
  49 + user.projects
  50 + end
38 51 end
39 52 end
40 53 # == Schema Information
... ...
app/models/project.rb
... ... @@ -14,6 +14,7 @@ class Project &lt; ActiveRecord::Base
14 14 has_many :users, :through => :users_projects
15 15 has_many :notes, :dependent => :destroy
16 16 has_many :snippets, :dependent => :destroy
  17 + has_many :deploy_keys, :dependent => :destroy, :foreign_key => "project_id", :class_name => "Key"
17 18 has_many :web_hooks, :dependent => :destroy
18 19  
19 20 acts_as_taggable
... ... @@ -199,7 +200,7 @@ class Project &lt; ActiveRecord::Base
199 200 def repository_readers
200 201 keys = Key.joins({:user => :users_projects}).
201 202 where("users_projects.project_id = ? AND users_projects.repo_access = ?", id, Repository::REPO_R)
202   - keys.map(&:identifier)
  203 + keys.map(&:identifier) + deploy_keys.map(&:identifier)
203 204 end
204 205  
205 206 def repository_writers
... ...
app/views/deploy_keys/_form.html.haml 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +%div
  2 + = form_for [@project, @key], :url => project_deploy_keys_path, :remote => true do |f|
  3 + -if @key.errors.any?
  4 + %ul
  5 + - @key.errors.full_messages.each do |msg|
  6 + %li= msg
  7 +
  8 + .form-row
  9 + = f.label :title
  10 + = f.text_field :title, :style => "width:300px"
  11 + .form-row
  12 + = f.label :key
  13 + = f.text_area :key, :style => "width:300px; height:130px"
  14 + .form-row
  15 + = f.submit 'Save', :class => "grey-button"
  16 +
... ...
app/views/deploy_keys/_show.html.haml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +%a.update-item{:href => project_deploy_key_path(key.project, key)}
  2 + %span.update-title
  3 + = key.title
  4 + %span.update-author
  5 + Added
  6 + = time_ago_in_words(key.created_at)
  7 + ago
... ...
app/views/deploy_keys/create.js.haml 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +- if @key.valid?
  2 + :plain
  3 + $("#new_key_dialog").dialog("close");
  4 + $("#keys-table .data").append("#{escape_javascript(render(:partial => 'show', :locals => {:key => @key} ))}");
  5 + $("#no_ssh_key_defined").hide();
  6 +- else
  7 + :plain
  8 + $("#new_key_dialog").empty();
  9 + $("#new_key_dialog").append("#{escape_javascript(render('form'))}");
... ...
app/views/deploy_keys/edit.html.haml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +%h1 Editing key
  2 +
  3 += render 'form'
  4 +
  5 += link_to 'Show', @key
  6 +\|
  7 += link_to 'Back', project_deploy_keys_path
... ...
app/views/deploy_keys/index.html.haml 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 += render "repositories/head"
  2 +
  3 +%div#keys-table{ :class => "update-data ui-box ui-box-small ui-box-big" }
  4 + .data
  5 + - @keys.each do |key|
  6 + = render(:partial => 'show', :locals => {:key => key})
  7 +
  8 +:javascript
  9 + $('.delete-key').live('ajax:success', function() {
  10 + $(this).closest('.update-item').fadeOut(); });
  11 +
... ...
app/views/deploy_keys/new.html.haml 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +%h1 New key
  2 +
  3 += render 'form'
  4 +
  5 += link_to 'Back', project_deploy_keys_path
... ...
app/views/deploy_keys/new.js.haml 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +:plain
  2 + var new_key_dialog = $("<div id='new_key_dialog'></div>");
  3 + new_key_dialog.html("#{escape_javascript(render('form'))}");
  4 + $(new_key_dialog).dialog({
  5 + width: 350,
  6 + resizable: false,
  7 + draggable: false,
  8 + title: "Add new public key",
  9 + close: function(event, ui) { $("#new_key_dialog").remove();},
  10 + modal: true
  11 + });
... ...
app/views/deploy_keys/show.html.haml 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +.ui-box.width-100p
  2 + %h3= @key.title
  3 + .data
  4 + %pre= @key.key
  5 + .clear
  6 + .buttons
  7 + = link_to 'Remove', project_deploy_key_path(@key.project, @key), :confirm => 'Are you sure?', :method => :delete, :class => "red-button delete-key right"
  8 + .clear
  9 +
  10 +
... ...
app/views/layouts/project.html.haml
... ... @@ -44,5 +44,6 @@
44 44 %span{ :class => "number" }= @project.merge_requests.opened.count
45 45  
46 46  
  47 +
47 48 .project-content
48 49 = yield
... ...
app/views/repositories/_head.html.haml
... ... @@ -11,13 +11,18 @@
11 11 = link_to project_hooks_path, :class => "tab #{'active' if controller.controller_name == "hooks" }" do
12 12 %span
13 13 Hooks
14   - -#= link_to "#", :class => "tab" do
15   - %span
16   - Deploy Keys
  14 + - if can? current_user, :admin_project, @project
  15 + = link_to project_deploy_keys_path(@project), :class => "tab #{'active' if controller.controller_name == "deploy_keys"}" do
  16 + %span
  17 + Deploy Keys
17 18  
18 19 - if current_page?(project_hooks_path(@project))
19 20 - if can? current_user, :admin_project, @project
20 21 = link_to new_project_hook_path(@project), :class => "add_new", :title => "New Web Hook" do
21 22 = image_tag "add_new.png", :width => 14
22 23  
  24 + - if current_page?(project_deploy_keys_path(@project))
  25 + - if can? current_user, :admin_project, @project
  26 + = link_to new_project_deploy_key_path(@project), :class => "add_new", :title => "New Deploy Key", :remote => true do
  27 + = image_tag "add_new.png", :width => 14
23 28  
... ...
config/routes.rb
... ... @@ -53,6 +53,8 @@ Gitlab::Application.routes.draw do
53 53 end
54 54 end
55 55  
  56 + resources :deploy_keys
  57 +
56 58 resources :refs, :only => [], :path => "/" do
57 59 collection do
58 60 get "switch"
... ...
db/migrate/20111231111825_add_project_id_to_key.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +class AddProjectIdToKey < ActiveRecord::Migration
  2 + def change
  3 + add_column :keys, :project_id, :integer, :null => true
  4 + change_column :keys, :user_id, :integer, :null => true
  5 + end
  6 +end
... ...
db/schema.rb
... ... @@ -39,12 +39,13 @@ ActiveRecord::Schema.define(:version =&gt; 20120110180749) do
39 39 end
40 40  
41 41 create_table "keys", :force => true do |t|
42   - t.integer "user_id", :null => false
  42 + t.integer "user_id"
43 43 t.datetime "created_at"
44 44 t.datetime "updated_at"
45 45 t.text "key"
46 46 t.string "title"
47 47 t.string "identifier"
  48 + t.integer "project_id"
48 49 end
49 50  
50 51 create_table "merge_requests", :force => true do |t|
... ...
spec/models/key_spec.rb
... ... @@ -2,7 +2,7 @@ require &#39;spec_helper&#39;
2 2  
3 3 describe Key do
4 4 describe "Associations" do
5   - it { should belong_to(:user) }
  5 + it { should belong_to(:user) or belong_to(:project) }
6 6 end
7 7  
8 8 describe "Validation" do
... ...
spec/requests/projects_deploy_keys_spec.rb 0 → 100644
... ... @@ -0,0 +1,68 @@
  1 +require 'spec_helper'
  2 +
  3 +describe "Projects", "DeployKeys" do
  4 + let(:project) { Factory :project }
  5 +
  6 + before do
  7 + login_as :user
  8 + project.add_access(@user, :read, :write, :admin)
  9 + end
  10 +
  11 + describe "GET /keys" do
  12 + before do
  13 + @key = Factory :key, :project => project
  14 + visit project_deploy_keys_path(project)
  15 + end
  16 +
  17 + subject { page }
  18 +
  19 + it { should have_content(@key.title) }
  20 +
  21 + describe "Destroy" do
  22 + before { visit project_deploy_key_path(project, @key) }
  23 +
  24 + it "should remove entry" do
  25 + expect {
  26 + click_link "Remove"
  27 + }.to change { project.deploy_keys.count }.by(-1)
  28 + end
  29 + end
  30 + end
  31 +
  32 + describe "New key", :js => true do
  33 + before do
  34 + visit project_deploy_keys_path(project)
  35 + click_link "New Deploy Key"
  36 + end
  37 +
  38 + it "should open new key popup" do
  39 + page.should have_content("Add new public key")
  40 + end
  41 +
  42 + describe "fill in" do
  43 + before do
  44 + fill_in "key_title", :with => "laptop"
  45 + fill_in "key_key", :with => "publickey234="
  46 + end
  47 +
  48 + it { expect { click_button "Save" }.to change {Key.count}.by(1) }
  49 +
  50 + it "should add new key to table" do
  51 + click_button "Save"
  52 +
  53 + page.should_not have_content("Add new public key")
  54 + page.should have_content "laptop"
  55 + end
  56 + end
  57 + end
  58 +
  59 + describe "Show page" do
  60 + before do
  61 + @key = Factory :key, :project => project
  62 + visit project_deploy_key_path(project, @key)
  63 + end
  64 +
  65 + it { page.should have_content @key.title }
  66 + it { page.should have_content @key.key[0..10] }
  67 + end
  68 +end
... ...
spec/requests/projects_security_spec.rb
... ... @@ -105,6 +105,15 @@ describe &quot;Projects&quot; do
105 105 it { edit_project_path(@project).should be_denied_for :visitor }
106 106 end
107 107  
  108 + describe "GET /project_code/deploy_keys" do
  109 + it { project_deploy_keys_path(@project).should be_allowed_for @u1 }
  110 + it { project_deploy_keys_path(@project).should be_denied_for @u3 }
  111 + it { project_deploy_keys_path(@project).should be_denied_for :admin }
  112 + it { project_deploy_keys_path(@project).should be_denied_for @u2 }
  113 + it { project_deploy_keys_path(@project).should be_denied_for :user }
  114 + it { project_deploy_keys_path(@project).should be_denied_for :visitor }
  115 + end
  116 +
108 117 describe "GET /project_code/issues" do
109 118 it { project_issues_path(@project).should be_allowed_for @u1 }
110 119 it { project_issues_path(@project).should be_allowed_for @u3 }
... ...