Commit caf065007a49a58f8005c0a8d2cb0140719af8d2

Authored by Dmitriy Zaporozhets
2 parents 4c903035 749d3383

Merge branch 'feature/improve_deploy_keys' of /home/git/repositories/gitlab/gitlabhq

app/controllers/deploy_keys_controller.rb
@@ -5,7 +5,8 @@ class DeployKeysController < ProjectResourceController @@ -5,7 +5,8 @@ class DeployKeysController < ProjectResourceController
5 before_filter :authorize_admin_project! 5 before_filter :authorize_admin_project!
6 6
7 def index 7 def index
8 - @keys = @project.deploy_keys.all 8 + @enabled_keys = @project.deploy_keys.all
  9 + @available_keys = available_keys - @enabled_keys
9 end 10 end
10 11
11 def show 12 def show
@@ -19,8 +20,9 @@ class DeployKeysController < ProjectResourceController @@ -19,8 +20,9 @@ class DeployKeysController < ProjectResourceController
19 end 20 end
20 21
21 def create 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 redirect_to project_deploy_keys_path(@project) 26 redirect_to project_deploy_keys_path(@project)
25 else 27 else
26 render "new" 28 render "new"
@@ -36,4 +38,22 @@ class DeployKeysController &lt; ProjectResourceController @@ -36,4 +38,22 @@ class DeployKeysController &lt; ProjectResourceController
36 format.js { render nothing: true } 38 format.js { render nothing: true }
37 end 39 end
38 end 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 end 59 end
app/models/deploy_key.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class DeployKey < Key
  2 + has_many :deploy_keys_projects, dependent: :destroy
  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) }
  6 +end
app/models/deploy_keys_project.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class DeployKeysProject < ActiveRecord::Base
  2 + attr_accessible :key_id, :project_id
  3 +
  4 + belongs_to :project
  5 + belongs_to :deploy_key
  6 +
  7 + validates :deploy_key_id, presence: true
  8 + validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
  9 +
  10 + validates :project_id, presence: true
  11 +end
app/models/key.rb
@@ -16,7 +16,6 @@ require &#39;digest/md5&#39; @@ -16,7 +16,6 @@ require &#39;digest/md5&#39;
16 16
17 class Key < ActiveRecord::Base 17 class Key < ActiveRecord::Base
18 belongs_to :user 18 belongs_to :user
19 - belongs_to :project  
20 19
21 attr_accessible :key, :title 20 attr_accessible :key, :title
22 21
@@ -29,7 +28,7 @@ class Key &lt; ActiveRecord::Base @@ -29,7 +28,7 @@ class Key &lt; ActiveRecord::Base
29 delegate :name, :email, to: :user, prefix: true 28 delegate :name, :email, to: :user, prefix: true
30 29
31 def strip_white_space 30 def strip_white_space
32 - self.key = self.key.strip unless self.key.blank? 31 + self.key = key.strip unless key.blank?
33 end 32 end
34 33
35 def fingerprintable_key 34 def fingerprintable_key
@@ -47,20 +46,12 @@ class Key &lt; ActiveRecord::Base @@ -47,20 +46,12 @@ class Key &lt; ActiveRecord::Base
47 errors.add(:key, "can't be fingerprinted") if $?.exitstatus != 0 46 errors.add(:key, "can't be fingerprinted") if $?.exitstatus != 0
48 end 47 end
49 48
50 - def is_deploy_key  
51 - project.present?  
52 - end  
53 -  
54 # projects that has this key 49 # projects that has this key
55 def projects 50 def projects
56 - if is_deploy_key  
57 - [project]  
58 - else  
59 - user.authorized_projects  
60 - end 51 + user.authorized_projects
61 end 52 end
62 53
63 def shell_id 54 def shell_id
64 - "key-#{self.id}" 55 + "key-#{id}"
65 end 56 end
66 end 57 end
app/models/project.rb
@@ -55,7 +55,6 @@ class Project &lt; ActiveRecord::Base @@ -55,7 +55,6 @@ class Project &lt; ActiveRecord::Base
55 has_many :users_projects, dependent: :destroy 55 has_many :users_projects, dependent: :destroy
56 has_many :notes, dependent: :destroy 56 has_many :notes, dependent: :destroy
57 has_many :snippets, dependent: :destroy 57 has_many :snippets, dependent: :destroy
58 - has_many :deploy_keys, dependent: :destroy, class_name: "Key", foreign_key: "project_id"  
59 has_many :hooks, dependent: :destroy, class_name: "ProjectHook" 58 has_many :hooks, dependent: :destroy, class_name: "ProjectHook"
60 has_many :protected_branches, dependent: :destroy 59 has_many :protected_branches, dependent: :destroy
61 has_many :user_team_project_relationships, dependent: :destroy 60 has_many :user_team_project_relationships, dependent: :destroy
@@ -65,6 +64,9 @@ class Project &lt; ActiveRecord::Base @@ -65,6 +64,9 @@ class Project &lt; ActiveRecord::Base
65 has_many :user_team_user_relationships, through: :user_teams 64 has_many :user_team_user_relationships, through: :user_teams
66 has_many :user_teams_members, through: :user_team_user_relationships 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 delegate :name, to: :owner, allow_nil: true, prefix: true 70 delegate :name, to: :owner, allow_nil: true, prefix: true
69 71
70 # Validations 72 # Validations
app/models/user.rb
@@ -89,7 +89,7 @@ class User &lt; ActiveRecord::Base @@ -89,7 +89,7 @@ class User &lt; ActiveRecord::Base
89 89
90 has_many :personal_projects, through: :namespace, source: :projects 90 has_many :personal_projects, through: :namespace, source: :projects
91 has_many :projects, through: :users_projects 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 has_many :owned_projects, through: :namespaces, source: :projects 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 @@ @@ -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,6 +18,6 @@
18 = link_to "here", help_ssh_path 18 = link_to "here", help_ssh_path
19 19
20 .actions 20 .actions
21 - = f.submit 'Save', class: "btn-save btn" 21 + = f.submit 'Create', class: "btn-create btn"
22 = link_to "Cancel", project_deploy_keys_path(@project), class: "btn btn-cancel" 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,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 = render "projects/settings_nav" 1 = render "projects/settings_nav"
2 2
3 %p.slead 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,4 +12,4 @@
12 %hr 12 %hr
13 %pre= @key.key 13 %pre= @key.key
14 .pull-right 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 - file_name = content_data[:file_name] 2 - file_name = content_data[:file_name]
3 - commit = content_data[:commit] 3 - commit = content_data[:commit]
4 4
config/routes.rb
@@ -215,7 +215,13 @@ Gitlab::Application.routes.draw do @@ -215,7 +215,13 @@ Gitlab::Application.routes.draw do
215 end 215 end
216 end 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 resources :protected_branches, only: [:index, :create, :destroy] 225 resources :protected_branches, only: [:index, :create, :destroy]
220 226
221 resources :refs, only: [] do 227 resources :refs, only: [] do
db/migrate/20130506085413_add_type_to_key.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class AddTypeToKey < ActiveRecord::Migration
  2 + def change
  3 + add_column :keys, :type, :string
  4 + end
  5 +end
db/migrate/20130506090604_create_deploy_keys_projects.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class CreateDeployKeysProjects < ActiveRecord::Migration
  2 + def change
  3 + create_table :deploy_keys_projects do |t|
  4 + t.integer :deploy_key_id, null: false
  5 + t.integer :project_id, null: false
  6 +
  7 + t.timestamps
  8 + end
  9 + end
  10 +end
db/migrate/20130506095501_remove_project_id_from_key.rb 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +class RemoveProjectIdFromKey < ActiveRecord::Migration
  2 + def up
  3 + puts 'Migrate deploy keys: '
  4 + Key.where('project_id IS NOT NULL').update_all(type: 'DeployKey')
  5 +
  6 + DeployKey.all.each do |key|
  7 + project = Project.find_by_id(key.project_id)
  8 + if project
  9 + project.deploy_keys << key
  10 + print '.'
  11 + end
  12 + end
  13 +
  14 + puts 'Done'
  15 +
  16 + remove_column :keys, :project_id
  17 + end
  18 +
  19 + def down
  20 + add_column :keys, :project_id, :integer
  21 + end
  22 +end
@@ -11,7 +11,14 @@ @@ -11,7 +11,14 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20130410175022) do 14 +ActiveRecord::Schema.define(:version => 20130506095501) do
  15 +
  16 + create_table "deploy_keys_projects", :force => true do |t|
  17 + t.integer "deploy_key_id", :null => false
  18 + t.integer "project_id", :null => false
  19 + t.datetime "created_at", :null => false
  20 + t.datetime "updated_at", :null => false
  21 + end
15 22
16 create_table "events", :force => true do |t| 23 create_table "events", :force => true do |t|
17 t.string "target_type" 24 t.string "target_type"
@@ -46,8 +53,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -46,8 +53,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
46 t.integer "assignee_id" 53 t.integer "assignee_id"
47 t.integer "author_id" 54 t.integer "author_id"
48 t.integer "project_id" 55 t.integer "project_id"
49 - t.datetime "created_at"  
50 - t.datetime "updated_at" 56 + t.datetime "created_at", :null => false
  57 + t.datetime "updated_at", :null => false
51 t.integer "position", :default => 0 58 t.integer "position", :default => 0
52 t.string "branch_name" 59 t.string "branch_name"
53 t.text "description" 60 t.text "description"
@@ -64,16 +71,15 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -64,16 +71,15 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
64 71
65 create_table "keys", :force => true do |t| 72 create_table "keys", :force => true do |t|
66 t.integer "user_id" 73 t.integer "user_id"
67 - t.datetime "created_at"  
68 - t.datetime "updated_at" 74 + t.datetime "created_at", :null => false
  75 + t.datetime "updated_at", :null => false
69 t.text "key" 76 t.text "key"
70 t.string "title" 77 t.string "title"
71 t.string "identifier" 78 t.string "identifier"
72 - t.integer "project_id" 79 + t.string "type"
73 end 80 end
74 81
75 add_index "keys", ["identifier"], :name => "index_keys_on_identifier" 82 add_index "keys", ["identifier"], :name => "index_keys_on_identifier"
76 - add_index "keys", ["project_id"], :name => "index_keys_on_project_id"  
77 add_index "keys", ["user_id"], :name => "index_keys_on_user_id" 83 add_index "keys", ["user_id"], :name => "index_keys_on_user_id"
78 84
79 create_table "merge_requests", :force => true do |t| 85 create_table "merge_requests", :force => true do |t|
@@ -83,8 +89,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -83,8 +89,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
83 t.integer "author_id" 89 t.integer "author_id"
84 t.integer "assignee_id" 90 t.integer "assignee_id"
85 t.string "title" 91 t.string "title"
86 - t.datetime "created_at"  
87 - t.datetime "updated_at" 92 + t.datetime "created_at", :null => false
  93 + t.datetime "updated_at", :null => false
88 t.text "st_commits", :limit => 2147483647 94 t.text "st_commits", :limit => 2147483647
89 t.text "st_diffs", :limit => 2147483647 95 t.text "st_diffs", :limit => 2147483647
90 t.integer "milestone_id" 96 t.integer "milestone_id"
@@ -133,8 +139,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -133,8 +139,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
133 t.text "note" 139 t.text "note"
134 t.string "noteable_type" 140 t.string "noteable_type"
135 t.integer "author_id" 141 t.integer "author_id"
136 - t.datetime "created_at"  
137 - t.datetime "updated_at" 142 + t.datetime "created_at", :null => false
  143 + t.datetime "updated_at", :null => false
138 t.integer "project_id" 144 t.integer "project_id"
139 t.string "attachment" 145 t.string "attachment"
140 t.string "line_code" 146 t.string "line_code"
@@ -152,8 +158,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -152,8 +158,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
152 t.string "name" 158 t.string "name"
153 t.string "path" 159 t.string "path"
154 t.text "description" 160 t.text "description"
155 - t.datetime "created_at"  
156 - t.datetime "updated_at" 161 + t.datetime "created_at", :null => false
  162 + t.datetime "updated_at", :null => false
157 t.integer "creator_id" 163 t.integer "creator_id"
158 t.string "default_branch" 164 t.string "default_branch"
159 t.boolean "issues_enabled", :default => true, :null => false 165 t.boolean "issues_enabled", :default => true, :null => false
@@ -197,8 +203,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -197,8 +203,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
197 t.text "content" 203 t.text "content"
198 t.integer "author_id", :null => false 204 t.integer "author_id", :null => false
199 t.integer "project_id", :null => false 205 t.integer "project_id", :null => false
200 - t.datetime "created_at"  
201 - t.datetime "updated_at" 206 + t.datetime "created_at", :null => false
  207 + t.datetime "updated_at", :null => false
202 t.string "file_name" 208 t.string "file_name"
203 t.datetime "expires_at" 209 t.datetime "expires_at"
204 end 210 end
@@ -217,6 +223,9 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -217,6 +223,9 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
217 t.datetime "created_at" 223 t.datetime "created_at"
218 end 224 end
219 225
  226 + add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"
  227 + add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context"
  228 +
220 create_table "tags", :force => true do |t| 229 create_table "tags", :force => true do |t|
221 t.string "name" 230 t.string "name"
222 end 231 end
@@ -248,41 +257,42 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -248,41 +257,42 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
248 end 257 end
249 258
250 create_table "users", :force => true do |t| 259 create_table "users", :force => true do |t|
251 - t.string "email", :default => "", :null => false  
252 - t.string "encrypted_password", :limit => 128, :default => "", :null => false 260 + t.string "email", :default => "", :null => false
  261 + t.string "encrypted_password", :default => "", :null => false
253 t.string "reset_password_token" 262 t.string "reset_password_token"
254 t.datetime "reset_password_sent_at" 263 t.datetime "reset_password_sent_at"
255 t.datetime "remember_created_at" 264 t.datetime "remember_created_at"
256 - t.integer "sign_in_count", :default => 0 265 + t.integer "sign_in_count", :default => 0
257 t.datetime "current_sign_in_at" 266 t.datetime "current_sign_in_at"
258 t.datetime "last_sign_in_at" 267 t.datetime "last_sign_in_at"
259 t.string "current_sign_in_ip" 268 t.string "current_sign_in_ip"
260 t.string "last_sign_in_ip" 269 t.string "last_sign_in_ip"
261 - t.datetime "created_at"  
262 - t.datetime "updated_at" 270 + t.datetime "created_at", :null => false
  271 + t.datetime "updated_at", :null => false
263 t.string "name" 272 t.string "name"
264 - t.boolean "admin", :default => false, :null => false  
265 - t.integer "projects_limit", :default => 10  
266 - t.string "skype", :default => "", :null => false  
267 - t.string "linkedin", :default => "", :null => false  
268 - t.string "twitter", :default => "", :null => false 273 + t.boolean "admin", :default => false, :null => false
  274 + t.integer "projects_limit", :default => 10
  275 + t.string "skype", :default => "", :null => false
  276 + t.string "linkedin", :default => "", :null => false
  277 + t.string "twitter", :default => "", :null => false
269 t.string "authentication_token" 278 t.string "authentication_token"
270 - t.integer "theme_id", :default => 1, :null => false 279 + t.integer "theme_id", :default => 1, :null => false
271 t.string "bio" 280 t.string "bio"
272 - t.integer "failed_attempts", :default => 0 281 + t.integer "failed_attempts", :default => 0
273 t.datetime "locked_at" 282 t.datetime "locked_at"
274 t.string "extern_uid" 283 t.string "extern_uid"
275 t.string "provider" 284 t.string "provider"
276 t.string "username" 285 t.string "username"
277 - t.boolean "can_create_group", :default => true, :null => false  
278 - t.boolean "can_create_team", :default => true, :null => false 286 + t.boolean "can_create_group", :default => true, :null => false
  287 + t.boolean "can_create_team", :default => true, :null => false
279 t.string "state" 288 t.string "state"
280 - t.integer "color_scheme_id", :default => 1, :null => false  
281 - t.integer "notification_level", :default => 1, :null => false 289 + t.integer "color_scheme_id", :default => 1, :null => false
  290 + t.integer "notification_level", :default => 1, :null => false
282 end 291 end
283 292
284 add_index "users", ["admin"], :name => "index_users_on_admin" 293 add_index "users", ["admin"], :name => "index_users_on_admin"
285 add_index "users", ["email"], :name => "index_users_on_email", :unique => true 294 add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  295 + add_index "users", ["extern_uid", "provider"], :name => "index_users_on_extern_uid_and_provider", :unique => true
286 add_index "users", ["name"], :name => "index_users_on_name" 296 add_index "users", ["name"], :name => "index_users_on_name"
287 add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true 297 add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
288 add_index "users", ["username"], :name => "index_users_on_username" 298 add_index "users", ["username"], :name => "index_users_on_username"
@@ -290,8 +300,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -290,8 +300,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
290 create_table "users_projects", :force => true do |t| 300 create_table "users_projects", :force => true do |t|
291 t.integer "user_id", :null => false 301 t.integer "user_id", :null => false
292 t.integer "project_id", :null => false 302 t.integer "project_id", :null => false
293 - t.datetime "created_at"  
294 - t.datetime "updated_at" 303 + t.datetime "created_at", :null => false
  304 + t.datetime "updated_at", :null => false
295 t.integer "project_access", :default => 0, :null => false 305 t.integer "project_access", :default => 0, :null => false
296 t.integer "notification_level", :default => 3, :null => false 306 t.integer "notification_level", :default => 3, :null => false
297 end 307 end
@@ -303,8 +313,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do @@ -303,8 +313,8 @@ ActiveRecord::Schema.define(:version =&gt; 20130410175022) do
303 create_table "web_hooks", :force => true do |t| 313 create_table "web_hooks", :force => true do |t|
304 t.string "url" 314 t.string "url"
305 t.integer "project_id" 315 t.integer "project_id"
306 - t.datetime "created_at"  
307 - t.datetime "updated_at" 316 + t.datetime "created_at", :null => false
  317 + t.datetime "updated_at", :null => false
308 t.string "type", :default => "ProjectHook" 318 t.string "type", :default => "ProjectHook"
309 t.integer "service_id" 319 t.integer "service_id"
310 end 320 end
features/project/deploy_keys.feature 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +Feature: Project Deploy Keys
  2 + Background:
  3 + Given I sign in as a user
  4 + And I own project "Shop"
  5 +
  6 + Scenario: I should see deploy keys list
  7 + Given project has deploy key
  8 + When I visit project deploy keys page
  9 + Then I should see project deploy keys
  10 +
  11 + Scenario: I add new deploy key
  12 + Given I visit project deploy keys page
  13 + When I click 'New Deploy Key'
  14 + And I submit new deploy key
  15 + Then I should be on deploy keys page
  16 + And I should see newly created deploy key
  17 +
  18 + Scenario: I attach deploy key to project
  19 + Given other project has deploy key
  20 + And I visit project deploy keys page
  21 + When I click attach deploy key
  22 + Then I should be on deploy keys page
  23 + And I should see newly created deploy key
features/steps/project/deploy_keys.rb 0 → 100644
@@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
  1 +class Spinach::Features::ProjectDeployKeys < Spinach::FeatureSteps
  2 + include SharedAuthentication
  3 + include SharedProject
  4 + include SharedPaths
  5 +
  6 + step 'project has deploy key' do
  7 + create(:deploy_keys_project, project: @project)
  8 + end
  9 +
  10 + step 'I should see project deploy keys' do
  11 + within '.enabled-keys' do
  12 + page.should have_content deploy_key.title
  13 + end
  14 + end
  15 +
  16 + step 'I click \'New Deploy Key\'' do
  17 + click_link 'New Deploy Key'
  18 + end
  19 +
  20 + step 'I submit new deploy key' do
  21 + fill_in "deploy_key_title", with: "laptop"
  22 + fill_in "deploy_key_key", with: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzrEJUIR6Y03TCE9rIJ+GqTBvgb8t1jI9h5UBzCLuK4VawOmkLornPqLDrGbm6tcwM/wBrrLvVOqi2HwmkKEIecVO0a64A4rIYScVsXIniHRS6w5twyn1MD3sIbN+socBDcaldECQa2u1dI3tnNVcs8wi77fiRe7RSxePsJceGoheRQgC8AZ510UdIlO+9rjIHUdVN7LLyz512auAfYsgx1OfablkQ/XJcdEwDNgi9imI6nAXhmoKUm1IPLT2yKajTIC64AjLOnE0YyCh6+7RFMpiMyu1qiOCpdjYwTgBRiciNRZCH8xIedyCoAmiUgkUT40XYHwLuwiPJICpkAzp7Q== user@laptop"
  23 + click_button "Create"
  24 + end
  25 +
  26 + step 'I should be on deploy keys page' do
  27 + current_path.should == project_deploy_keys_path(@project)
  28 + end
  29 +
  30 + step 'I should see newly created deploy key' do
  31 + within '.enabled-keys' do
  32 + page.should have_content(deploy_key.title)
  33 + end
  34 + end
  35 +
  36 + step 'other project has deploy key' do
  37 + @second_project = create :project, namespace: current_user.namespace
  38 + create(:deploy_keys_project, project: @second_project)
  39 + end
  40 +
  41 + step 'I click attach deploy key' do
  42 + within '.available-keys' do
  43 + click_link 'Enable'
  44 + end
  45 + end
  46 +
  47 + protected
  48 +
  49 + def deploy_key
  50 + @project.deploy_keys.last
  51 + end
  52 +end
features/steps/shared/paths.rb
1 module SharedPaths 1 module SharedPaths
2 include Spinach::DSL 2 include Spinach::DSL
3 3
4 - When 'I visit new project page' do 4 + step 'I visit new project page' do
5 visit new_project_path 5 visit new_project_path
6 end 6 end
7 7
@@ -9,23 +9,23 @@ module SharedPaths @@ -9,23 +9,23 @@ module SharedPaths
9 # Group 9 # Group
10 # ---------------------------------------- 10 # ----------------------------------------
11 11
12 - When 'I visit group page' do 12 + step 'I visit group page' do
13 visit group_path(current_group) 13 visit group_path(current_group)
14 end 14 end
15 15
16 - When 'I visit group issues page' do 16 + step 'I visit group issues page' do
17 visit issues_group_path(current_group) 17 visit issues_group_path(current_group)
18 end 18 end
19 19
20 - When 'I visit group merge requests page' do 20 + step 'I visit group merge requests page' do
21 visit merge_requests_group_path(current_group) 21 visit merge_requests_group_path(current_group)
22 end 22 end
23 23
24 - When 'I visit group people page' do 24 + step 'I visit group people page' do
25 visit people_group_path(current_group) 25 visit people_group_path(current_group)
26 end 26 end
27 27
28 - When 'I visit group settings page' do 28 + step 'I visit group settings page' do
29 visit edit_group_path(current_group) 29 visit edit_group_path(current_group)
30 end 30 end
31 31
@@ -33,27 +33,27 @@ module SharedPaths @@ -33,27 +33,27 @@ module SharedPaths
33 # Dashboard 33 # Dashboard
34 # ---------------------------------------- 34 # ----------------------------------------
35 35
36 - Given 'I visit dashboard page' do 36 + step 'I visit dashboard page' do
37 visit dashboard_path 37 visit dashboard_path
38 end 38 end
39 39
40 - Given 'I visit dashboard projects page' do 40 + step 'I visit dashboard projects page' do
41 visit projects_dashboard_path 41 visit projects_dashboard_path
42 end 42 end
43 43
44 - Given 'I visit dashboard issues page' do 44 + step 'I visit dashboard issues page' do
45 visit issues_dashboard_path 45 visit issues_dashboard_path
46 end 46 end
47 47
48 - Given 'I visit dashboard merge requests page' do 48 + step 'I visit dashboard merge requests page' do
49 visit merge_requests_dashboard_path 49 visit merge_requests_dashboard_path
50 end 50 end
51 51
52 - Given 'I visit dashboard search page' do 52 + step 'I visit dashboard search page' do
53 visit search_path 53 visit search_path
54 end 54 end
55 55
56 - Given 'I visit dashboard help page' do 56 + step 'I visit dashboard help page' do
57 visit help_path 57 visit help_path
58 end 58 end
59 59
@@ -61,23 +61,23 @@ module SharedPaths @@ -61,23 +61,23 @@ module SharedPaths
61 # Profile 61 # Profile
62 # ---------------------------------------- 62 # ----------------------------------------
63 63
64 - Given 'I visit profile page' do 64 + step 'I visit profile page' do
65 visit profile_path 65 visit profile_path
66 end 66 end
67 67
68 - Given 'I visit profile account page' do 68 + step 'I visit profile account page' do
69 visit account_profile_path 69 visit account_profile_path
70 end 70 end
71 71
72 - Given 'I visit profile SSH keys page' do 72 + step 'I visit profile SSH keys page' do
73 visit keys_path 73 visit keys_path
74 end 74 end
75 75
76 - Given 'I visit profile design page' do 76 + step 'I visit profile design page' do
77 visit design_profile_path 77 visit design_profile_path
78 end 78 end
79 79
80 - Given 'I visit profile history page' do 80 + step 'I visit profile history page' do
81 visit history_profile_path 81 visit history_profile_path
82 end 82 end
83 83
@@ -85,35 +85,35 @@ module SharedPaths @@ -85,35 +85,35 @@ module SharedPaths
85 # Admin 85 # Admin
86 # ---------------------------------------- 86 # ----------------------------------------
87 87
88 - Given 'I visit admin page' do 88 + step 'I visit admin page' do
89 visit admin_root_path 89 visit admin_root_path
90 end 90 end
91 91
92 - Given 'I visit admin projects page' do 92 + step 'I visit admin projects page' do
93 visit admin_projects_path 93 visit admin_projects_path
94 end 94 end
95 95
96 - Given 'I visit admin users page' do 96 + step 'I visit admin users page' do
97 visit admin_users_path 97 visit admin_users_path
98 end 98 end
99 99
100 - Given 'I visit admin logs page' do 100 + step 'I visit admin logs page' do
101 visit admin_logs_path 101 visit admin_logs_path
102 end 102 end
103 103
104 - Given 'I visit admin hooks page' do 104 + step 'I visit admin hooks page' do
105 visit admin_hooks_path 105 visit admin_hooks_path
106 end 106 end
107 107
108 - Given 'I visit admin Resque page' do 108 + step 'I visit admin Resque page' do
109 visit admin_resque_path 109 visit admin_resque_path
110 end 110 end
111 111
112 - And 'I visit admin groups page' do 112 + step 'I visit admin groups page' do
113 visit admin_groups_path 113 visit admin_groups_path
114 end 114 end
115 115
116 - When 'I visit admin teams page' do 116 + step 'I visit admin teams page' do
117 visit admin_teams_path 117 visit admin_teams_path
118 end 118 end
119 119
@@ -121,145 +121,149 @@ module SharedPaths @@ -121,145 +121,149 @@ module SharedPaths
121 # Generic Project 121 # Generic Project
122 # ---------------------------------------- 122 # ----------------------------------------
123 123
124 - Given "I visit my project's home page" do 124 + step "I visit my project's home page" do
125 visit project_path(@project) 125 visit project_path(@project)
126 end 126 end
127 127
128 - Given "I visit my project's settings page" do 128 + step "I visit my project's settings page" do
129 visit edit_project_path(@project) 129 visit edit_project_path(@project)
130 end 130 end
131 131
132 - Given "I visit my project's files page" do 132 + step "I visit my project's files page" do
133 visit project_tree_path(@project, root_ref) 133 visit project_tree_path(@project, root_ref)
134 end 134 end
135 135
136 - Given "I visit my project's commits page" do 136 + step "I visit my project's commits page" do
137 visit project_commits_path(@project, root_ref, {limit: 5}) 137 visit project_commits_path(@project, root_ref, {limit: 5})
138 end 138 end
139 139
140 - Given "I visit my project's commits page for a specific path" do 140 + step "I visit my project's commits page for a specific path" do
141 visit project_commits_path(@project, root_ref + "/app/models/project.rb", {limit: 5}) 141 visit project_commits_path(@project, root_ref + "/app/models/project.rb", {limit: 5})
142 end 142 end
143 143
144 - Given 'I visit my projects commits stats page' do 144 + step 'I visit my projects commits stats page' do
145 visit stats_project_repository_path(@project) 145 visit stats_project_repository_path(@project)
146 end 146 end
147 147
148 - Given "I visit my project's network page" do 148 + step "I visit my project's network page" do
149 # Stub Graph max_size to speed up test (10 commits vs. 650) 149 # Stub Graph max_size to speed up test (10 commits vs. 650)
150 Network::Graph.stub(max_count: 10) 150 Network::Graph.stub(max_count: 10)
151 151
152 visit project_graph_path(@project, root_ref) 152 visit project_graph_path(@project, root_ref)
153 end 153 end
154 154
155 - Given "I visit my project's issues page" do 155 + step "I visit my project's issues page" do
156 visit project_issues_path(@project) 156 visit project_issues_path(@project)
157 end 157 end
158 158
159 - Given "I visit my project's merge requests page" do 159 + step "I visit my project's merge requests page" do
160 visit project_merge_requests_path(@project) 160 visit project_merge_requests_path(@project)
161 end 161 end
162 162
163 - Given "I visit my project's wall page" do 163 + step "I visit my project's wall page" do
164 visit project_wall_path(@project) 164 visit project_wall_path(@project)
165 end 165 end
166 166
167 - Given "I visit my project's wiki page" do 167 + step "I visit my project's wiki page" do
168 visit project_wiki_path(@project, :home) 168 visit project_wiki_path(@project, :home)
169 end 169 end
170 170
171 - When 'I visit project hooks page' do 171 + step 'I visit project hooks page' do
172 visit project_hooks_path(@project) 172 visit project_hooks_path(@project)
173 end 173 end
174 174
  175 + step 'I visit project deploy keys page' do
  176 + visit project_deploy_keys_path(@project)
  177 + end
  178 +
175 # ---------------------------------------- 179 # ----------------------------------------
176 # "Shop" Project 180 # "Shop" Project
177 # ---------------------------------------- 181 # ----------------------------------------
178 182
179 - And 'I visit project "Shop" page' do 183 + step 'I visit project "Shop" page' do
180 visit project_path(project) 184 visit project_path(project)
181 end 185 end
182 186
183 - When 'I visit edit project "Shop" page' do 187 + step 'I visit edit project "Shop" page' do
184 visit edit_project_path(project) 188 visit edit_project_path(project)
185 end 189 end
186 190
187 - Given 'I visit project branches page' do 191 + step 'I visit project branches page' do
188 visit branches_project_repository_path(@project) 192 visit branches_project_repository_path(@project)
189 end 193 end
190 194
191 - Given 'I visit compare refs page' do 195 + step 'I visit compare refs page' do
192 visit project_compare_index_path(@project) 196 visit project_compare_index_path(@project)
193 end 197 end
194 198
195 - Given 'I visit project commits page' do 199 + step 'I visit project commits page' do
196 visit project_commits_path(@project, root_ref, {limit: 5}) 200 visit project_commits_path(@project, root_ref, {limit: 5})
197 end 201 end
198 202
199 - Given 'I visit project commits page for stable branch' do 203 + step 'I visit project commits page for stable branch' do
200 visit project_commits_path(@project, 'stable', {limit: 5}) 204 visit project_commits_path(@project, 'stable', {limit: 5})
201 end 205 end
202 206
203 - Given 'I visit project source page' do 207 + step 'I visit project source page' do
204 visit project_tree_path(@project, root_ref) 208 visit project_tree_path(@project, root_ref)
205 end 209 end
206 210
207 - Given 'I visit blob file from repo' do 211 + step 'I visit blob file from repo' do
208 visit project_blob_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH)) 212 visit project_blob_path(@project, File.join(ValidCommit::ID, ValidCommit::BLOB_FILE_PATH))
209 end 213 end
210 214
211 - Given 'I visit project source page for "8470d70"' do 215 + step 'I visit project source page for "8470d70"' do
212 visit project_tree_path(@project, "8470d70") 216 visit project_tree_path(@project, "8470d70")
213 end 217 end
214 218
215 - Given 'I visit project tags page' do 219 + step 'I visit project tags page' do
216 visit tags_project_repository_path(@project) 220 visit tags_project_repository_path(@project)
217 end 221 end
218 222
219 - Given 'I visit project commit page' do 223 + step 'I visit project commit page' do
220 visit project_commit_path(@project, ValidCommit::ID) 224 visit project_commit_path(@project, ValidCommit::ID)
221 end 225 end
222 226
223 - And 'I visit project "Shop" issues page' do 227 + step 'I visit project "Shop" issues page' do
224 visit project_issues_path(project) 228 visit project_issues_path(project)
225 end 229 end
226 230
227 - Given 'I visit issue page "Release 0.4"' do 231 + step 'I visit issue page "Release 0.4"' do
228 issue = Issue.find_by_title("Release 0.4") 232 issue = Issue.find_by_title("Release 0.4")
229 visit project_issue_path(issue.project, issue) 233 visit project_issue_path(issue.project, issue)
230 end 234 end
231 235
232 - Given 'I visit project "Shop" labels page' do 236 + step 'I visit project "Shop" labels page' do
233 visit project_labels_path(project) 237 visit project_labels_path(project)
234 end 238 end
235 239
236 - Given 'I visit merge request page "Bug NS-04"' do 240 + step 'I visit merge request page "Bug NS-04"' do
237 mr = MergeRequest.find_by_title("Bug NS-04") 241 mr = MergeRequest.find_by_title("Bug NS-04")
238 visit project_merge_request_path(mr.project, mr) 242 visit project_merge_request_path(mr.project, mr)
239 end 243 end
240 244
241 - Given 'I visit merge request page "Bug NS-05"' do 245 + step 'I visit merge request page "Bug NS-05"' do
242 mr = MergeRequest.find_by_title("Bug NS-05") 246 mr = MergeRequest.find_by_title("Bug NS-05")
243 visit project_merge_request_path(mr.project, mr) 247 visit project_merge_request_path(mr.project, mr)
244 end 248 end
245 249
246 - And 'I visit project "Shop" merge requests page' do 250 + step 'I visit project "Shop" merge requests page' do
247 visit project_merge_requests_path(project) 251 visit project_merge_requests_path(project)
248 end 252 end
249 253
250 - Given 'I visit project "Shop" milestones page' do 254 + step 'I visit project "Shop" milestones page' do
251 visit project_milestones_path(project) 255 visit project_milestones_path(project)
252 end 256 end
253 257
254 - Then 'I visit project "Shop" team page' do 258 + step 'I visit project "Shop" team page' do
255 visit project_team_index_path(project) 259 visit project_team_index_path(project)
256 end 260 end
257 261
258 - Then 'I visit project "Shop" wall page' do 262 + step 'I visit project "Shop" wall page' do
259 visit project_wall_path(project) 263 visit project_wall_path(project)
260 end 264 end
261 265
262 - Given 'I visit project wiki page' do 266 + step 'I visit project wiki page' do
263 visit project_wiki_path(@project, :home) 267 visit project_wiki_path(@project, :home)
264 end 268 end
265 269
@@ -267,7 +271,7 @@ module SharedPaths @@ -267,7 +271,7 @@ module SharedPaths
267 # Public Projects 271 # Public Projects
268 # ---------------------------------------- 272 # ----------------------------------------
269 273
270 - Given 'I visit the public projects area' do 274 + step 'I visit the public projects area' do
271 visit public_root_path 275 visit public_root_path
272 end 276 end
273 277
lib/api/internal.rb
@@ -25,8 +25,8 @@ module Gitlab @@ -25,8 +25,8 @@ module Gitlab
25 return false unless project 25 return false unless project
26 26
27 27
28 - if key.is_deploy_key  
29 - project == key.project && git_cmd == 'git-upload-pack' 28 + if key.is_a? DeployKey
  29 + key.projects.include?(project) && git_cmd == 'git-upload-pack'
30 else 30 else
31 user = key.user 31 user = key.user
32 32
lib/api/projects.rb
@@ -531,8 +531,8 @@ module Gitlab @@ -531,8 +531,8 @@ module Gitlab
531 # POST /projects/:id/keys 531 # POST /projects/:id/keys
532 post ":id/keys" do 532 post ":id/keys" do
533 attrs = attributes_for_keys [:title, :key] 533 attrs = attributes_for_keys [:title, :key]
534 - key = user_project.deploy_keys.new attrs  
535 - if key.save 534 + key = DeployKey.new attrs
  535 + if key.valid? && user_project.deploy_keys << key
536 present key, with: Entities::SSHKey 536 present key, with: Entities::SSHKey
537 else 537 else
538 not_found! 538 not_found!
@@ -545,9 +545,8 @@ module Gitlab @@ -545,9 +545,8 @@ module Gitlab
545 # DELETE /projects/:id/keys/:id 545 # DELETE /projects/:id/keys/:id
546 delete ":id/keys/:key_id" do 546 delete ":id/keys/:key_id" do
547 key = user_project.deploy_keys.find params[:key_id] 547 key = user_project.deploy_keys.find params[:key_id]
548 - key.delete 548 + key.destroy
549 end 549 end
550 -  
551 end 550 end
552 end 551 end
553 end 552 end
lib/api/users.rb
@@ -174,7 +174,7 @@ module Gitlab @@ -174,7 +174,7 @@ module Gitlab
174 delete "keys/:id" do 174 delete "keys/:id" do
175 begin 175 begin
176 key = current_user.keys.find params[:id] 176 key = current_user.keys.find params[:id]
177 - key.delete 177 + key.destroy
178 rescue 178 rescue
179 end 179 end
180 end 180 end
lib/tasks/gitlab/check.rake
@@ -24,6 +24,7 @@ namespace :gitlab do @@ -24,6 +24,7 @@ namespace :gitlab do
24 check_init_script_up_to_date 24 check_init_script_up_to_date
25 check_satellites_exist 25 check_satellites_exist
26 check_redis_version 26 check_redis_version
  27 + check_git_version
27 28
28 finished_checking "GitLab" 29 finished_checking "GitLab"
29 end 30 end
@@ -663,4 +664,18 @@ namespace :gitlab do @@ -663,4 +664,18 @@ namespace :gitlab do
663 puts "FAIL. Please update gitlab-shell to v#{required_version}".red 664 puts "FAIL. Please update gitlab-shell to v#{required_version}".red
664 end 665 end
665 end 666 end
  667 +
  668 + def check_git_version
  669 + print "Git version >= 1.7.10 ? ... "
  670 +
  671 + if run_and_match("git --version", /git version 1.7.10.\d/)
  672 + puts "yes".green
  673 + else
  674 + puts "no".red
  675 + try_fixing_it(
  676 + "Update your git to a version >= 1.7.10"
  677 + )
  678 + fix_and_rerun
  679 + end
  680 + end
666 end 681 end
spec/factories.rb
@@ -158,8 +158,7 @@ FactoryGirl.define do @@ -158,8 +158,7 @@ FactoryGirl.define do
158 "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=" 158 "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
159 end 159 end
160 160
161 - factory :deploy_key do  
162 - project 161 + factory :deploy_key, class: 'DeployKey' do
163 end 162 end
164 163
165 factory :personal_key do 164 factory :personal_key do
@@ -222,4 +221,9 @@ FactoryGirl.define do @@ -222,4 +221,9 @@ FactoryGirl.define do
222 url 221 url
223 service 222 service
224 end 223 end
  224 +
  225 + factory :deploy_keys_project do
  226 + deploy_key
  227 + project
  228 + end
225 end 229 end
spec/features/projects_deploy_keys_spec.rb
@@ -1,67 +0,0 @@ @@ -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  
spec/models/deploy_key_spec.rb 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +# == Schema Information
  2 +#
  3 +# Table name: keys
  4 +#
  5 +# id :integer not null, primary key
  6 +# user_id :integer
  7 +# created_at :datetime not null
  8 +# updated_at :datetime not null
  9 +# key :text
  10 +# title :string(255)
  11 +# identifier :string(255)
  12 +# project_id :integer
  13 +#
  14 +
  15 +require 'spec_helper'
  16 +
  17 +describe DeployKey do
  18 + let(:project) { create(:project) }
  19 + let(:deploy_key) { create(:deploy_key, projects: [project]) }
  20 +
  21 + describe "Associations" do
  22 + it { should have_many(:deploy_keys_projects) }
  23 + it { should have_many(:projects) }
  24 + end
  25 +end
spec/models/deploy_keys_project_spec.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +require 'spec_helper'
  2 +
  3 +describe DeployKeysProject do
  4 + describe "Associations" do
  5 + it { should belong_to(:deploy_key) }
  6 + it { should belong_to(:project) }
  7 + end
  8 +
  9 + describe "Validation" do
  10 + it { should validate_presence_of(:project_id) }
  11 + it { should validate_presence_of(:deploy_key_id) }
  12 + end
  13 +end
spec/models/key_spec.rb
@@ -17,7 +17,6 @@ require &#39;spec_helper&#39; @@ -17,7 +17,6 @@ require &#39;spec_helper&#39;
17 describe Key do 17 describe Key do
18 describe "Associations" do 18 describe "Associations" do
19 it { should belong_to(:user) } 19 it { should belong_to(:user) }
20 - it { should belong_to(:project) }  
21 end 20 end
22 21
23 describe "Mass assignment" do 22 describe "Mass assignment" do
@@ -37,32 +36,15 @@ describe Key do @@ -37,32 +36,15 @@ describe Key do
37 end 36 end
38 37
39 context "validation of uniqueness" do 38 context "validation of uniqueness" do
  39 + let(:user) { create(:user) }
40 40
41 - context "as a deploy key" do  
42 - let!(:deploy_key) { create(:deploy_key) }  
43 -  
44 - it "does not accept the same key twice for a project" do  
45 - key = build(:key, project: deploy_key.project)  
46 - key.should_not be_valid  
47 - end  
48 -  
49 - it "does not accept the same key for another project" do  
50 - key = build(:key, project_id: 0)  
51 - key.should_not be_valid  
52 - end 41 + it "accepts the key once" do
  42 + build(:key, user: user).should be_valid
53 end 43 end
54 44
55 - context "as a personal key" do  
56 - let(:user) { create(:user) }  
57 -  
58 - it "accepts the key once" do  
59 - build(:key, user: user).should be_valid  
60 - end  
61 -  
62 - it "does not accepts the key twice" do  
63 - create(:key, user: user)  
64 - build(:key, user: user).should_not be_valid  
65 - end 45 + it "does not accepts the key twice" do
  46 + create(:key, user: user)
  47 + build(:key, user: user).should_not be_valid
66 end 48 end
67 end 49 end
68 50
spec/models/project_spec.rb
@@ -37,7 +37,8 @@ describe Project do @@ -37,7 +37,8 @@ describe Project do
37 it { should have_many(:users_projects).dependent(:destroy) } 37 it { should have_many(:users_projects).dependent(:destroy) }
38 it { should have_many(:notes).dependent(:destroy) } 38 it { should have_many(:notes).dependent(:destroy) }
39 it { should have_many(:snippets).dependent(:destroy) } 39 it { should have_many(:snippets).dependent(:destroy) }
40 - it { should have_many(:deploy_keys).dependent(:destroy) } 40 + it { should have_many(:deploy_keys_projects).dependent(:destroy) }
  41 + it { should have_many(:deploy_keys) }
41 it { should have_many(:hooks).dependent(:destroy) } 42 it { should have_many(:hooks).dependent(:destroy) }
42 it { should have_many(:protected_branches).dependent(:destroy) } 43 it { should have_many(:protected_branches).dependent(:destroy) }
43 it { should have_one(:forked_project_link).dependent(:destroy) } 44 it { should have_one(:forked_project_link).dependent(:destroy) }
spec/requests/api/projects_spec.rb
@@ -13,7 +13,6 @@ describe Gitlab::API do @@ -13,7 +13,6 @@ describe Gitlab::API do
13 let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') } 13 let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
14 let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) } 14 let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
15 let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) } 15 let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
16 - let(:key) { create(:key, project: project) }  
17 16
18 before { project.team << [user, :reporter] } 17 before { project.team << [user, :reporter] }
19 18
@@ -636,58 +635,61 @@ describe Gitlab::API do @@ -636,58 +635,61 @@ describe Gitlab::API do
636 end 635 end
637 end 636 end
638 637
639 - describe "GET /projects/:id/keys" do  
640 - it "should return array of ssh keys" do  
641 - project.deploy_keys << key  
642 - project.save  
643 - get api("/projects/#{project.id}/keys", user)  
644 - response.status.should == 200  
645 - json_response.should be_an Array  
646 - json_response.first['title'].should == key.title  
647 - end  
648 - end 638 + describe :deploy_keys do
  639 + let(:deploy_keys_project) { create(:deploy_keys_project, project: project) }
  640 + let(:deploy_key) { deploy_keys_project.deploy_key }
649 641
650 - describe "GET /projects/:id/keys/:key_id" do  
651 - it "should return a single key" do  
652 - project.deploy_keys << key  
653 - project.save  
654 - get api("/projects/#{project.id}/keys/#{key.id}", user)  
655 - response.status.should == 200  
656 - json_response['title'].should == key.title  
657 - end 642 + describe "GET /projects/:id/keys" do
  643 + before { deploy_key }
658 644
659 - it "should return 404 Not Found with invalid ID" do  
660 - get api("/projects/#{project.id}/keys/404", user)  
661 - response.status.should == 404 645 + it "should return array of ssh keys" do
  646 + get api("/projects/#{project.id}/keys", user)
  647 + response.status.should == 200
  648 + json_response.should be_an Array
  649 + json_response.first['title'].should == deploy_key.title
  650 + end
662 end 651 end
663 - end  
664 652
665 - describe "POST /projects/:id/keys" do  
666 - it "should not create an invalid ssh key" do  
667 - post api("/projects/#{project.id}/keys", user), { title: "invalid key" }  
668 - response.status.should == 404  
669 - end 653 + describe "GET /projects/:id/keys/:key_id" do
  654 + it "should return a single key" do
  655 + get api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
  656 + response.status.should == 200
  657 + json_response['title'].should == deploy_key.title
  658 + end
670 659
671 - it "should create new ssh key" do  
672 - key_attrs = attributes_for :key  
673 - expect {  
674 - post api("/projects/#{project.id}/keys", user), key_attrs  
675 - }.to change{ project.deploy_keys.count }.by(1) 660 + it "should return 404 Not Found with invalid ID" do
  661 + get api("/projects/#{project.id}/keys/404", user)
  662 + response.status.should == 404
  663 + end
676 end 664 end
677 - end  
678 665
679 - describe "DELETE /projects/:id/keys/:key_id" do  
680 - it "should delete existing key" do  
681 - project.deploy_keys << key  
682 - project.save  
683 - expect {  
684 - delete api("/projects/#{project.id}/keys/#{key.id}", user)  
685 - }.to change{ project.deploy_keys.count }.by(-1) 666 + describe "POST /projects/:id/keys" do
  667 + it "should not create an invalid ssh key" do
  668 + post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
  669 + response.status.should == 404
  670 + end
  671 +
  672 + it "should create new ssh key" do
  673 + key_attrs = attributes_for :key
  674 + expect {
  675 + post api("/projects/#{project.id}/keys", user), key_attrs
  676 + }.to change{ project.deploy_keys.count }.by(1)
  677 + end
686 end 678 end
687 679
688 - it "should return 404 Not Found with invalid ID" do  
689 - delete api("/projects/#{project.id}/keys/404", user)  
690 - response.status.should == 404 680 + describe "DELETE /projects/:id/keys/:key_id" do
  681 + before { deploy_key }
  682 +
  683 + it "should delete existing key" do
  684 + expect {
  685 + delete api("/projects/#{project.id}/keys/#{deploy_key.id}", user)
  686 + }.to change{ project.deploy_keys.count }.by(-1)
  687 + end
  688 +
  689 + it "should return 404 Not Found with invalid ID" do
  690 + delete api("/projects/#{project.id}/keys/404", user)
  691 + response.status.should == 404
  692 + end
691 end 693 end
692 end 694 end
693 end 695 end