From 9c7fffb6559facdcf8bbda680795f70d836293bf Mon Sep 17 00:00:00 2001
From: Douwe Maan <douwe@gitlab.com>
Date: Tue, 17 Mar 2015 14:55:43 +0100
Subject: [PATCH] Delete deploy key when last connection to a project is
 destroyed.

---
 CHANGELOG                                     |  1 +
 .../projects/deploy_keys_controller.rb        |  5 +--
 app/models/deploy_keys_project.rb             |  8 +++++
 spec/models/deploy_keys_project_spec.rb       | 33 +++++++++++++++++++
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index bd66a92933..23744c0405 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -74,6 +74,7 @@ v 7.9.0 (unreleased)
   - Raise recommended number of unicorn workers from 2 to 3
   - Use same layout and interactivity for project members as group members.
   - Prevent gitlab-shell character encoding issues by receiving its changes as raw data.
+  - Delete deploy key when last connection to a project is destroyed.
 
 v 7.8.4
   - Fix issue_tracker_id substitution in custom issue trackers
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index b7cc305899..2ecde8381e 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -37,7 +37,8 @@ class Projects::DeployKeysController < Projects::ApplicationController
     @key.destroy
 
     respond_to do |format|
-      format.html { redirect_to project_deploy_keys_url }
+      format.html { redirect_to namespace_project_deploy_keys_path(@project.namespace,
+                                                   @project) }
       format.js { render nothing: true }
     end
   end
@@ -50,7 +51,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
   end
 
   def disable
-    @project.deploy_keys_projects.where(deploy_key_id: params[:id]).last.destroy
+    @project.deploy_keys_projects.find_by(deploy_key_id: params[:id]).destroy
 
     redirect_to namespace_project_deploy_keys_path(@project.namespace,
                                                    @project)
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index f23d8205dd..7e88903b9a 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -16,4 +16,12 @@ class DeployKeysProject < ActiveRecord::Base
   validates :deploy_key_id, presence: true
   validates :deploy_key_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
   validates :project_id, presence: true
+
+  after_destroy :destroy_orphaned_deploy_key
+
+  private
+
+  def destroy_orphaned_deploy_key
+    self.deploy_key.destroy if self.deploy_key.deploy_keys_projects.length == 0
+  end
 end
diff --git a/spec/models/deploy_keys_project_spec.rb b/spec/models/deploy_keys_project_spec.rb
index aacd9bf38b..f351aab923 100644
--- a/spec/models/deploy_keys_project_spec.rb
+++ b/spec/models/deploy_keys_project_spec.rb
@@ -21,4 +21,37 @@ describe DeployKeysProject do
     it { is_expected.to validate_presence_of(:project_id) }
     it { is_expected.to validate_presence_of(:deploy_key_id) }
   end
+
+  describe "Destroying" do
+    let(:project)     { create(:project) }
+    subject           { create(:deploy_keys_project, project: project) }
+    let(:deploy_key)  { subject.deploy_key }
+
+    context "when the deploy key is only used by this project" do
+      it "destroys the deploy key" do
+        subject.destroy
+
+        expect {
+          deploy_key.reload
+        }.to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
+
+    context "when the deploy key is used by more than one project" do
+
+      let!(:other_project) { create(:project) }
+
+      before do
+        other_project.deploy_keys << deploy_key
+      end
+
+      it "doesn't destroy the deploy key" do
+        subject.destroy
+
+        expect {
+          deploy_key.reload
+        }.not_to raise_error(ActiveRecord::RecordNotFound)
+      end
+    end
+  end
 end
-- 
2.30.9