Commit 1882baa1aaa1c195cce55678b2b8a12e1b59db34

Authored by Dmitriy Zaporozhets
1 parent 8e4625af

Feature: Deploy keys between projects

app/controllers/deploy_keys_controller.rb
... ... @@ -5,7 +5,8 @@ class DeployKeysController < ProjectResourceController
5 5 before_filter :authorize_admin_project!
6 6  
7 7 def index
8   - @keys = @project.deploy_keys.all
  8 + @enabled_keys = @project.deploy_keys.all
  9 + @available_keys = available_keys - @enabled_keys
9 10 end
10 11  
11 12 def show
... ... @@ -19,8 +20,9 @@ class DeployKeysController < ProjectResourceController
19 20 end
20 21  
21 22 def create
22   - @key = @project.deploy_keys.new(params[:key])
23   - if @key.save
  23 + @key = DeployKey.new(params[:deploy_key])
  24 +
  25 + if @key.valid? && @project.deploy_keys << @key
24 26 redirect_to project_deploy_keys_path(@project)
25 27 else
26 28 render "new"
... ... @@ -36,4 +38,22 @@ class DeployKeysController &lt; ProjectResourceController
36 38 format.js { render nothing: true }
37 39 end
38 40 end
  41 +
  42 + def enable
  43 + project.deploy_keys << available_keys.find(params[:id])
  44 +
  45 + redirect_to project_deploy_keys_path(@project)
  46 + end
  47 +
  48 + def disable
  49 + @project.deploy_keys_projects.where(deploy_key_id: params[:id]).last.destroy
  50 +
  51 + redirect_to project_deploy_keys_path(@project)
  52 + end
  53 +
  54 + protected
  55 +
  56 + def available_keys
  57 + @available_keys ||= DeployKey.in_projects(current_user.owned_projects)
  58 + end
39 59 end
... ...
app/models/deploy_key.rb
1 1 class DeployKey < Key
2 2 has_many :deploy_keys_projects, dependent: :destroy
3 3 has_many :projects, through: :deploy_keys_projects
  4 +
  5 + scope :in_projects, ->(projects) { joins(:deploy_keys_projects).where('deploy_keys_projects.project_id in (?)', projects) }
4 6 end
... ...
app/models/key.rb
... ... @@ -46,10 +46,6 @@ class Key &lt; ActiveRecord::Base
46 46 errors.add(:key, "can't be fingerprinted") if $?.exitstatus != 0
47 47 end
48 48  
49   - def is_deploy_key
50   - project.present?
51   - end
52   -
53 49 # projects that has this key
54 50 def projects
55 51 user.authorized_projects
... ...
app/models/project.rb
... ... @@ -55,7 +55,6 @@ class Project &lt; ActiveRecord::Base
55 55 has_many :users_projects, dependent: :destroy
56 56 has_many :notes, dependent: :destroy
57 57 has_many :snippets, dependent: :destroy
58   - has_many :deploy_keys, dependent: :destroy, class_name: "Key", foreign_key: "project_id"
59 58 has_many :hooks, dependent: :destroy, class_name: "ProjectHook"
60 59 has_many :protected_branches, dependent: :destroy
61 60 has_many :user_team_project_relationships, dependent: :destroy
... ... @@ -65,6 +64,9 @@ class Project &lt; ActiveRecord::Base
65 64 has_many :user_team_user_relationships, through: :user_teams
66 65 has_many :user_teams_members, through: :user_team_user_relationships
67 66  
  67 + has_many :deploy_keys_projects, dependent: :destroy
  68 + has_many :deploy_keys, through: :deploy_keys_projects
  69 +
68 70 delegate :name, to: :owner, allow_nil: true, prefix: true
69 71  
70 72 # Validations
... ...
app/models/user.rb
... ... @@ -89,7 +89,7 @@ class User &lt; ActiveRecord::Base
89 89  
90 90 has_many :personal_projects, through: :namespace, source: :projects
91 91 has_many :projects, through: :users_projects
92   - has_many :own_projects, foreign_key: :creator_id
  92 + has_many :own_projects, foreign_key: :creator_id, class_name: 'Project'
93 93 has_many :owned_projects, through: :namespaces, source: :projects
94 94  
95 95 #
... ...
app/views/deploy_keys/_deploy_key.html.haml 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +%li
  2 + .pull-right
  3 + - if @available_keys.include?(deploy_key)
  4 + = link_to enable_project_deploy_key_path(@project, deploy_key), class: 'btn btn-small', method: :put do
  5 + %i.icon-plus
  6 + Enable
  7 + - else
  8 + - if deploy_key.projects.count > 1
  9 + = link_to disable_project_deploy_key_path(@project, deploy_key), class: 'btn btn-small', method: :put do
  10 + %i.icon-off
  11 + Disable
  12 + - else
  13 + = link_to 'Remove', project_deploy_key_path(@project, deploy_key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
  14 +
  15 +
  16 + = link_to project_deploy_key_path(@project, deploy_key) do
  17 + %i.icon-key
  18 + %strong= deploy_key.title
  19 +
  20 + %p.light.prepend-top-10
  21 + - deploy_key.projects.map(&:name_with_namespace).each do |project_name|
  22 + %span.label= project_name
  23 + %small.pull-right
  24 + Created #{time_ago_in_words(deploy_key.created_at)} ago
  25 +
... ...
app/views/deploy_keys/_form.html.haml
... ... @@ -18,6 +18,6 @@
18 18 = link_to "here", help_ssh_path
19 19  
20 20 .actions
21   - = f.submit 'Save', class: "btn-save btn"
  21 + = f.submit 'Create', class: "btn-create btn"
22 22 = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel"
23 23  
... ...
app/views/deploy_keys/_show.html.haml
... ... @@ -1,12 +0,0 @@
1   -%tr
2   - %td
3   - %a{href: project_deploy_key_path(key.project, key)}
4   - %strong= key.title
5   - %td
6   - %span.update-author
7   - Added
8   - = time_ago_in_words(key.created_at)
9   - ago
10   - %td
11   - = link_to 'Remove', project_deploy_key_path(key.project, key), confirm: 'Are you sure?', method: :delete, class: "btn btn-remove delete-key btn-small pull-right"
12   -
app/views/deploy_keys/index.html.haml
1 1 = render "projects/settings_nav"
2 2  
3 3 %p.slead
4   - Deploy keys allow read-only access to repository. They can be used for CI, staging or production servers. A deploy key can be added to only one project. If you need to add the same key to multiple projects you can create a deploy user and add that user to multiple projects.
  4 + Deploy keys allow read-only access to repository. They can be used for CI, staging or production servers
5 5  
6   - - if can? current_user, :admin_project, @project
7   - = link_to new_project_deploy_key_path(@project), class: "btn btn-small", title: "New Deploy Key" do
8   - Add Deploy Key
9   -- if @keys.any?
10   - %table
11   - %thead
12   - %tr
13   - %th Keys
14   - %th
15   - %th
16   - - @keys.each do |key|
17   - = render(partial: 'show', locals: {key: key})
  6 +%p
  7 + You can create a deploy key or add existing one
  8 + = link_to new_project_deploy_key_path(@project), class: "btn btn-primary pull-right", title: "New Deploy Key" do
  9 + %i.icon-plus
  10 + New Deploy Key
  11 +
  12 +%hr.clearfix
  13 +
  14 +.row
  15 + .span6.enabled-keys
  16 + %h5.cgreen
  17 + Enabled deploy keys
  18 + %small for this project
  19 + %ul.bordered-list
  20 + = render @enabled_keys
  21 + .span6.available-keys
  22 + %h5
  23 + Available deploy keys
  24 + %small from projects you are able to manage
  25 + %ul.bordered-list
  26 + = render @available_keys
... ...
app/views/deploy_keys/show.html.haml
... ... @@ -12,4 +12,4 @@
12 12 %hr
13 13 %pre= @key.key
14 14 .pull-right
15   - = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
  15 + = link_to 'Remove', project_deploy_key_path(@project, @key), confirm: 'Are you sure?', method: :delete, class: "btn-remove btn delete-key"
... ...
app/views/refs/logs_tree.js.haml
1   -- @logs.each do |content_data|
  1 +- @logs.each do |content_data|
2 2 - file_name = content_data[:file_name]
3 3 - commit = content_data[:commit]
4 4  
... ...
config/routes.rb
... ... @@ -215,7 +215,13 @@ Gitlab::Application.routes.draw do
215 215 end
216 216 end
217 217  
218   - resources :deploy_keys
  218 + resources :deploy_keys do
  219 + member do
  220 + put :enable
  221 + put :disable
  222 + end
  223 + end
  224 +
219 225 resources :protected_branches, only: [:index, :create, :destroy]
220 226  
221 227 resources :refs, only: [] do
... ...
spec/features/projects_deploy_keys_spec.rb
... ... @@ -1,67 +0,0 @@
1   -require 'spec_helper'
2   -
3   -describe "Projects", "DeployKeys" do
4   - let(:project) { create(:project) }
5   -
6   - before do
7   - login_as :user
8   - project.team << [@user, :master]
9   - end
10   -
11   - describe "GET /keys" do
12   - before do
13   - @key = create(: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" 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("New Deploy 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: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzrEJUIR6Y03TCE9rIJ+GqTBvgb8t1jI9h5UBzCLuK4VawOmkLornPqLDrGbm6tcwM/wBrrLvVOqi2HwmkKEIecVO0a64A4rIYScVsXIniHRS6w5twyn1MD3sIbN+socBDcaldECQa2u1dI3tnNVcs8wi77fiRe7RSxePsJceGoheRQgC8AZ510UdIlO+9rjIHUdVN7LLyz512auAfYsgx1OfablkQ/XJcdEwDNgi9imI6nAXhmoKUm1IPLT2yKajTIC64AjLOnE0YyCh6+7RFMpiMyu1qiOCpdjYwTgBRiciNRZCH8xIedyCoAmiUgkUT40XYHwLuwiPJICpkAzp7Q== user@laptop"
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 have_content "laptop"
54   - end
55   - end
56   - end
57   -
58   - describe "Show page" do
59   - before do
60   - @key = create(:key, project: project)
61   - visit project_deploy_key_path(project, @key)
62   - end
63   -
64   - it { page.should have_content @key.title }
65   - it { page.should have_content @key.key[0..10] }
66   - end
67   -end