Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG2
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock5
-rw-r--r--app/assets/images/authbuttons/bitbucket_32.pngbin0 -> 2713 bytes
-rw-r--r--app/assets/images/authbuttons/bitbucket_64.pngbin0 -> 2163 bytes
-rw-r--r--app/controllers/application_controller.rb13
-rw-r--r--app/controllers/import/bitbucket_controller.rb79
-rw-r--r--app/controllers/import/github_controller.rb5
-rw-r--r--app/controllers/import/gitlab_controller.rb5
-rw-r--r--app/helpers/oauth_helper.rb6
-rw-r--r--app/helpers/projects_helper.rb8
-rw-r--r--app/models/project.rb2
-rw-r--r--app/models/user.rb1
-rw-r--r--app/views/import/base/create.js.haml7
-rw-r--r--app/views/import/bitbucket/status.html.haml46
-rw-r--r--app/views/import/github/status.html.haml11
-rw-r--r--app/views/import/gitlab/status.html.haml15
-rw-r--r--app/views/import/gitorious/status.html.haml13
-rw-r--r--app/views/projects/_bitbucket_import_modal.html.haml13
-rw-r--r--app/views/projects/_github_import_modal.html.haml10
-rw-r--r--app/views/projects/_gitlab_import_modal.html.haml10
-rw-r--r--app/views/projects/new.html.haml13
-rw-r--r--app/workers/repository_import_worker.rb34
-rw-r--r--config/gitlab.yml.example18
-rw-r--r--config/initializers/public_key.rb2
-rw-r--r--config/routes.rb6
-rw-r--r--db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb6
-rw-r--r--db/schema.rb40
-rw-r--r--doc/integration/bitbucket.md121
-rw-r--r--doc/integration/github.md29
-rw-r--r--doc/integration/gitlab.md18
-rw-r--r--doc/integration/google.md14
-rw-r--r--doc/integration/omniauth.md1
-rw-r--r--doc/integration/twitter.md14
-rw-r--r--lib/gitlab/bitbucket_import.rb6
-rw-r--r--lib/gitlab/bitbucket_import/client.rb99
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb52
-rw-r--r--lib/gitlab/bitbucket_import/key_adder.rb23
-rw-r--r--lib/gitlab/bitbucket_import/key_deleter.rb23
-rw-r--r--lib/gitlab/bitbucket_import/project_creator.rb39
-rw-r--r--lib/gitlab/github_import/client.rb6
-rw-r--r--lib/gitlab/github_import/importer.rb2
-rw-r--r--lib/gitlab/gitlab_import/client.rb10
-rw-r--r--lib/gitlab/gitlab_import/importer.rb2
-rw-r--r--lib/gitlab/import_formatter.rb2
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb78
-rw-r--r--spec/controllers/import/github_controller_spec.rb1
-rw-r--r--spec/controllers/import/gitlab_controller_spec.rb1
-rw-r--r--spec/lib/gitlab/bitbucket_import/project_creator_spec.rb22
-rw-r--r--spec/lib/gitlab/github_import/project_creator_spec.rb (renamed from spec/lib/gitlab/github/project_creator.rb)7
-rw-r--r--spec/lib/gitlab/gitlab_import/project_creator_spec.rb (renamed from spec/lib/gitlab/gitlab_import/project_creator.rb)5
51 files changed, 818 insertions, 128 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 90591684757..9220411b3d7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,8 @@ v 7.8.1
- Fix the warning for LDAP users about need to set password
- Fix avatars which were not shown for non logged in users
- Fix urls for the issues when relative url was enabled
+ - Add Bitbucket omniauth provider.
+ - Add Bitbucket importer.
v 7.8.0
- Fix access control and protection against XSS for note attachments and other uploads.
diff --git a/Gemfile b/Gemfile
index 20d612e8617..62f2c6d255d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -30,6 +30,7 @@ gem 'omniauth-github'
gem 'omniauth-shibboleth'
gem 'omniauth-kerberos'
gem 'omniauth-gitlab'
+gem 'omniauth-bitbucket'
gem 'doorkeeper', '2.1.0'
gem "rack-oauth2", "~> 1.0.5"
diff --git a/Gemfile.lock b/Gemfile.lock
index e4d43bb56b3..6949d14b185 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -338,6 +338,10 @@ GEM
omniauth (1.1.4)
hashie (>= 1.2, < 3)
rack
+ omniauth-bitbucket (0.0.2)
+ multi_json (~> 1.7)
+ omniauth (~> 1.1)
+ omniauth-oauth (~> 1.0)
omniauth-github (1.1.1)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
@@ -701,6 +705,7 @@ DEPENDENCIES
nprogress-rails
octokit (= 3.7.0)
omniauth (~> 1.1.3)
+ omniauth-bitbucket
omniauth-github
omniauth-gitlab
omniauth-google-oauth2
diff --git a/app/assets/images/authbuttons/bitbucket_32.png b/app/assets/images/authbuttons/bitbucket_32.png
new file mode 100644
index 00000000000..27702eb973d
--- /dev/null
+++ b/app/assets/images/authbuttons/bitbucket_32.png
Binary files differ
diff --git a/app/assets/images/authbuttons/bitbucket_64.png b/app/assets/images/authbuttons/bitbucket_64.png
new file mode 100644
index 00000000000..4b90a57bc7d
--- /dev/null
+++ b/app/assets/images/authbuttons/bitbucket_64.png
Binary files differ
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index eb3be08df56..7940b5cb3f4 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -16,6 +16,7 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :abilities, :can?, :current_application_settings
+ helper_method :github_import_enabled?, :gitlab_import_enabled?, :bitbucket_import_enabled?
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
@@ -313,4 +314,16 @@ class ApplicationController < ActionController::Base
set_filter_values(merge_requests)
merge_requests
end
+
+ def github_import_enabled?
+ OauthHelper.enabled_oauth_providers.include?(:github)
+ end
+
+ def gitlab_import_enabled?
+ OauthHelper.enabled_oauth_providers.include?(:gitlab)
+ end
+
+ def bitbucket_import_enabled?
+ OauthHelper.enabled_oauth_providers.include?(:bitbucket) && Gitlab::BitbucketImport.public_key.present?
+ end
end
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
new file mode 100644
index 00000000000..83ebc5fddca
--- /dev/null
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -0,0 +1,79 @@
+class Import::BitbucketController < Import::BaseController
+ before_filter :verify_bitbucket_import_enabled
+ before_filter :bitbucket_auth, except: :callback
+
+ rescue_from OAuth::Error, with: :bitbucket_unauthorized
+
+ def callback
+ request_token = session.delete(:oauth_request_token)
+ raise "Session expired!" if request_token.nil?
+
+ request_token.symbolize_keys!
+
+ access_token = client.get_token(request_token, params[:oauth_verifier], callback_import_bitbucket_url)
+
+ current_user.bitbucket_access_token = access_token.token
+ current_user.bitbucket_access_token_secret = access_token.secret
+
+ current_user.save
+ redirect_to status_import_bitbucket_url
+ end
+
+ def status
+ @repos = client.projects
+
+ @already_added_projects = current_user.created_projects.where(import_type: "bitbucket")
+ already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+ @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" }
+ end
+
+ def jobs
+ jobs = current_user.created_projects.where(import_type: "bitbucket").to_json(only: [:id, :import_status])
+ render json: jobs
+ end
+
+ def create
+ @repo_id = params[:repo_id] || ""
+ repo = client.project(@repo_id.gsub("___", "/"))
+ @target_namespace = params[:new_namespace].presence || repo["owner"]
+ @project_name = repo["slug"]
+
+ namespace = get_or_create_namespace || (render and return)
+
+ unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user).execute
+ @access_denied = true
+ render
+ return
+ end
+
+ @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user).execute
+ end
+
+ private
+
+ def client
+ @client ||= Gitlab::BitbucketImport::Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+ end
+
+ def verify_bitbucket_import_enabled
+ not_found! unless bitbucket_import_enabled?
+ end
+
+ def bitbucket_auth
+ if current_user.bitbucket_access_token.blank?
+ go_to_bitbucket_for_permissions
+ end
+ end
+
+ def go_to_bitbucket_for_permissions
+ request_token = client.request_token(callback_import_bitbucket_url)
+ session[:oauth_request_token] = request_token
+
+ redirect_to client.authorize_url(request_token, callback_import_bitbucket_url)
+ end
+
+ def bitbucket_unauthorized
+ go_to_bitbucket_for_permissions
+ end
+end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index c869c7c86f3..dc7668ee6fd 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -1,4 +1,5 @@
class Import::GithubController < Import::BaseController
+ before_filter :verify_github_import_enabled
before_filter :github_auth, except: :callback
rescue_from Octokit::Unauthorized, with: :github_unauthorized
@@ -44,6 +45,10 @@ class Import::GithubController < Import::BaseController
@client ||= Gitlab::GithubImport::Client.new(current_user.github_access_token)
end
+ def verify_github_import_enabled
+ not_found! unless github_import_enabled?
+ end
+
def github_auth
if current_user.github_access_token.blank?
go_to_github_for_permissions
diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb
index a51ea36aff8..74f992b4699 100644
--- a/app/controllers/import/gitlab_controller.rb
+++ b/app/controllers/import/gitlab_controller.rb
@@ -1,4 +1,5 @@
class Import::GitlabController < Import::BaseController
+ before_filter :verify_gitlab_import_enabled
before_filter :gitlab_auth, except: :callback
rescue_from OAuth2::Error, with: :gitlab_unauthorized
@@ -41,6 +42,10 @@ class Import::GitlabController < Import::BaseController
@client ||= Gitlab::GitlabImport::Client.new(current_user.gitlab_access_token)
end
+ def verify_gitlab_import_enabled
+ not_found! unless gitlab_import_enabled?
+ end
+
def gitlab_auth
if current_user.gitlab_access_token.blank?
go_to_gitlab_for_permissions
diff --git a/app/helpers/oauth_helper.rb b/app/helpers/oauth_helper.rb
index c7bc9307a58..1a0ad17b607 100644
--- a/app/helpers/oauth_helper.rb
+++ b/app/helpers/oauth_helper.rb
@@ -4,7 +4,7 @@ module OauthHelper
end
def default_providers
- [:twitter, :github, :gitlab, :google_oauth2, :ldap]
+ [:twitter, :github, :gitlab, :bitbucket, :google_oauth2, :ldap]
end
def enabled_oauth_providers
@@ -13,11 +13,13 @@ module OauthHelper
def enabled_social_providers
enabled_oauth_providers.select do |name|
- [:twitter, :gitlab, :github, :google_oauth2].include?(name.to_sym)
+ [:twitter, :gitlab, :github, :bitbucket, :google_oauth2].include?(name.to_sym)
end
end
def additional_providers
enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
end
+
+ extend self
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 900afde4d9b..c85ad12634d 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -265,12 +265,4 @@ module ProjectsHelper
"success"
end
end
-
- def github_import_enabled?
- enabled_oauth_providers.include?(:github)
- end
-
- def gitlab_import_enabled?
- enabled_oauth_providers.include?(:gitlab)
- end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 967e4de22a9..1606a83158d 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -136,7 +136,7 @@ class Project < ActiveRecord::Base
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
validates :import_url,
- format: { with: URI::regexp(%w(git http https)), message: 'should be a valid url' },
+ format: { with: URI::regexp(%w(ssh git http https)), message: 'should be a valid url' },
if: :import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
diff --git a/app/models/user.rb b/app/models/user.rb
index a43493d15fb..a4850982899 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -46,6 +46,7 @@
# github_access_token :string(255)
# notification_email :string(255)
# password_automatically_set :boolean default(FALSE)
+# bitbucket_access_token :string(255)
#
require 'carrierwave/orm/activerecord'
diff --git a/app/views/import/base/create.js.haml b/app/views/import/base/create.js.haml
index cd4c9fbf360..8ebdf4f1a20 100644
--- a/app/views/import/base/create.js.haml
+++ b/app/views/import/base/create.js.haml
@@ -10,9 +10,16 @@
target_field.append("/" + project_name)
target_field.data("project_name", project_name)
target_field.find('input').prop("value", origin_namespace)
+- elsif @access_denied
+ :plain
+ job = $("tr#repo_#{@repo_id}")
+ job.find(".import-actions").html("<p class='alert alert-danger'>Access denied! Please verify you can add deploy keys to this repository.</p>"")
- else
:plain
job = $("tr#repo_#{@repo_id}")
job.attr("id", "project_#{@project.id}")
+ target_field = job.find(".import-target")
+ target_field.empty()
+ target_field.append('<strong>#{link_to @project.path_with_namespace, @project}</strong>')
$("table.import-jobs tbody").prepend(job)
job.addClass("active").find(".import-actions").html("<i class='fa fa-spinner fa-spin'></i> started")
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
new file mode 100644
index 00000000000..90c97393b51
--- /dev/null
+++ b/app/views/import/bitbucket/status.html.haml
@@ -0,0 +1,46 @@
+%h3.page-title
+ %i.fa.fa-bitbucket
+ Import projects from Bitbucket
+
+%p.light
+ Select projects you want to import.
+%hr
+%p
+ = button_tag 'Import all projects', class: "btn btn-success js-import-all"
+
+%table.table.import-jobs
+ %thead
+ %tr
+ %th From Bitbucket
+ %th To GitLab
+ %th Status
+ %tbody
+ - @already_added_projects.each do |project|
+ %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
+ %td
+ = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank"
+ %td
+ %strong= link_to project.path_with_namespace, project
+ %td.job-status
+ - if project.import_status == 'finished'
+ %span.cgreen
+ %i.fa.fa-check
+ done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
+ - else
+ = project.human_import_status_name
+
+ - @repos.each do |repo|
+ %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+ %td
+ = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+ %td.import-target
+ = "#{repo["owner"]}/#{repo["slug"]}"
+ %td.import-actions.job-status
+ = button_tag "Import", class: "btn js-add-to-import"
+
+:coffeescript
+ $ ->
+ new ImporterStatus("#{jobs_import_bitbucket_path}", "#{import_bitbucket_path}")
diff --git a/app/views/import/github/status.html.haml b/app/views/import/github/status.html.haml
index 84d9903fe15..957022f382f 100644
--- a/app/views/import/github/status.html.haml
+++ b/app/views/import/github/status.html.haml
@@ -1,6 +1,6 @@
%h3.page-title
%i.fa.fa-github
- Import repositories from GitHub.com
+ Import projects from GitHub
%p.light
Select projects you want to import.
@@ -17,7 +17,8 @@
%tbody
- @already_added_projects.each do |project|
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td= project.import_source
+ %td
+ = link_to project.import_source, "https://github.com/#{project.import_source}", target: "_blank"
%td
%strong= link_to project.path_with_namespace, project
%td.job-status
@@ -25,12 +26,16 @@
%span.cgreen
%i.fa.fa-check
done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo.id}"}
- %td= repo.full_name
+ %td
+ = link_to repo.full_name, "https://github.com/#{repo.full_name}", target: "_blank"
%td.import-target
= repo.full_name
%td.import-actions.job-status
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index d1e48dfad20..db161681206 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -1,6 +1,6 @@
%h3.page-title
- %i.fa.fa-github
- Import repositories from GitLab.com
+ %i.fa.fa-heart
+ Import projects from GitLab.com
%p.light
Select projects you want to import.
@@ -12,12 +12,13 @@
%thead
%tr
%th From GitLab.com
- %th To GitLab private instance
+ %th To this GitLab instance
%th Status
%tbody
- @already_added_projects.each do |project|
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td= project.import_source
+ %td
+ = link_to project.import_source, "https://gitlab.com/#{project.import_source}", target: "_blank"
%td
%strong= link_to project.path_with_namespace, project
%td.job-status
@@ -25,12 +26,16 @@
%span.cgreen
%i.fa.fa-check
done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo["id"]}"}
- %td= repo["path_with_namespace"]
+ %td
+ = link_to repo["path_with_namespace"], "https://gitlab.com/#{repo["path_with_namespace"]}", target: "_blank"
%td.import-target
= repo["path_with_namespace"]
%td.import-actions.job-status
diff --git a/app/views/import/gitorious/status.html.haml b/app/views/import/gitorious/status.html.haml
index 8ede5c3e840..e06e068fdb4 100644
--- a/app/views/import/gitorious/status.html.haml
+++ b/app/views/import/gitorious/status.html.haml
@@ -1,6 +1,6 @@
%h3.page-title
%i.icon-gitorious.icon-gitorious-big
- Import repositories from Gitorious.org
+ Import projects from Gitorious.org
%p.light
Select projects you want to import.
@@ -11,13 +11,14 @@
%table.table.import-jobs
%thead
%tr
- %th From Gitorious
+ %th From Gitorious.org
%th To GitLab
%th Status
%tbody
- @already_added_projects.each do |project|
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
- %td= project.import_source
+ %td
+ = link_to project.import_source, "https://gitorious.org/#{project.import_source}", target: "_blank"
%td
%strong= link_to project.path_with_namespace, project
%td.job-status
@@ -25,12 +26,16 @@
%span.cgreen
%i.fa.fa-check
done
+ - elsif project.import_status == 'started'
+ %i.fa.fa-spinner.fa-spin
+ started
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo.id}"}
- %td= repo.full_name
+ %td
+ = link_to repo.full_name, "https://gitorious.org/#{repo.full_name}", target: "_blank"
%td.import-target
= repo.full_name
%td.import-actions.job-status
diff --git a/app/views/projects/_bitbucket_import_modal.html.haml b/app/views/projects/_bitbucket_import_modal.html.haml
new file mode 100644
index 00000000000..5c52f91927d
--- /dev/null
+++ b/app/views/projects/_bitbucket_import_modal.html.haml
@@ -0,0 +1,13 @@
+%div#bitbucket_import_modal.modal.hide
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %a.close{href: "#", "data-dismiss" => "modal"} ×
+ %h3 Import projects from Bitbucket
+ .modal-body
+ To enable importing projects from Bitbucket,
+ - if current_user.admin?
+ you need to
+ - else
+ your GitLab administrator needs to
+ == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/butbucket.md'}. \ No newline at end of file
diff --git a/app/views/projects/_github_import_modal.html.haml b/app/views/projects/_github_import_modal.html.haml
index 99325e66119..e88a0f7d689 100644
--- a/app/views/projects/_github_import_modal.html.haml
+++ b/app/views/projects/_github_import_modal.html.haml
@@ -3,7 +3,11 @@
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
- %h3 GitHub OAuth import
+ %h3 Import projects from GitHub
.modal-body
- You need to setup integration with GitHub first.
- = link_to 'How to setup integration with GitHub', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md' \ No newline at end of file
+ To enable importing projects from GitHub,
+ - if current_user.admin?
+ you need to
+ - else
+ your GitLab administrator needs to
+ == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md'}. \ No newline at end of file
diff --git a/app/views/projects/_gitlab_import_modal.html.haml b/app/views/projects/_gitlab_import_modal.html.haml
index e7503f023b1..52212b6ae02 100644
--- a/app/views/projects/_gitlab_import_modal.html.haml
+++ b/app/views/projects/_gitlab_import_modal.html.haml
@@ -3,7 +3,11 @@
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
- %h3 GitLab OAuth import
+ %h3 Import projects from GitLab.com
.modal-body
- You need to setup integration with GitLab first.
- = link_to 'How to setup integration with GitLab', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/gitlab.md' \ No newline at end of file
+ To enable importing projects from GitLab.com,
+ - if current_user.admin?
+ you need to
+ - else
+ your GitLab administrator needs to
+ == #{link_to 'setup OAuth integration', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/gitlab.md'}. \ No newline at end of file
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index b41d5f52d12..025c4fd5506 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -53,6 +53,19 @@
Import projects from GitHub
= render 'github_import_modal'
+ .project-import.form-group
+ .col-sm-2
+ .col-sm-10
+ - if bitbucket_import_enabled?
+ = link_to status_import_bitbucket_path do
+ %i.fa.fa-bitbucket
+ Import projects from Bitbucket
+ - else
+ = link_to '#', class: 'how_to_import_link light' do
+ %i.fa.fa-bitbucket
+ Import projects from Bitbucket
+ = render 'bitbucket_import_modal'
+
- unless request.host == 'gitlab.com'
.project-import.form-group
.col-sm-2
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 5f9970d3795..437640d2305 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -6,25 +6,27 @@ class RepositoryImportWorker
def perform(project_id)
project = Project.find(project_id)
- result = gitlab_shell.send(:import_repository,
+
+ import_result = gitlab_shell.send(:import_repository,
project.path_with_namespace,
project.import_url)
+ return project.import_fail unless import_result
- result_of_data_import = if project.import_type == 'github'
- Gitlab::GithubImport::Importer.new(project).execute
- elsif project.import_type == 'gitlab'
- Gitlab::GitlabImport::Importer.new(project).execute
- else
- true
- end
+ data_import_result = if project.import_type == 'github'
+ Gitlab::GithubImport::Importer.new(project).execute
+ elsif project.import_type == 'gitlab'
+ Gitlab::GitlabImport::Importer.new(project).execute
+ elsif project.import_type == 'bitbucket'
+ Gitlab::BitbucketImport::Importer.new(project).execute
+ else
+ true
+ end
+ return project.import_fail unless data_import_result
- if result && result_of_data_import
- project.import_finish
- project.save
- project.satellite.create unless project.satellite.exists?
- project.update_repository_size
- else
- project.import_fail
- end
+ project.import_finish
+ project.save
+ project.satellite.create unless project.satellite.exists?
+ project.update_repository_size
+ Gitlab::BitbucketImport::KeyDeleter.new(project).execute if project.import_type == 'bitbucket'
end
end
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 044b1f66b25..6dff07cf9df 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -207,17 +207,19 @@ production: &base
# arguments, followed by optional 'args' which can be either a hash or an array.
# Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
providers:
- # - { name: 'google_oauth2', app_id: 'YOUR APP ID',
- # app_secret: 'YOUR APP SECRET',
+ # - { name: 'google_oauth2', app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET',
# args: { access_type: 'offline', approval_prompt: '' } }
- # - { name: 'twitter', app_id: 'YOUR APP ID',
- # app_secret: 'YOUR APP SECRET'}
- # - { name: 'github', app_id: 'YOUR APP ID',
- # app_secret: 'YOUR APP SECRET',
+ # - { name: 'twitter', app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET'}
+ # - { name: 'github', app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET',
# args: { scope: 'user:email' } }
- # - { name: 'gitlab', app_id: 'YOUR APP ID',
- # app_secret: 'YOUR APP SECRET',
+ # - { name: 'gitlab', app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET',
# args: { scope: 'api' } }
+ # - { name: 'bitbucket', app_id: 'YOUR_APP_ID',
+ # app_secret: 'YOUR_APP_SECRET'}
diff --git a/config/initializers/public_key.rb b/config/initializers/public_key.rb
new file mode 100644
index 00000000000..75d74e3625d
--- /dev/null
+++ b/config/initializers/public_key.rb
@@ -0,0 +1,2 @@
+path = File.expand_path("~/.ssh/id_rsa.pub")
+Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path)
diff --git a/config/routes.rb b/config/routes.rb
index ecd439aecea..450895cbdb7 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -68,6 +68,12 @@ Gitlab::Application.routes.draw do
get :jobs
end
+ resource :bitbucket, only: [:create, :new], controller: :bitbucket do
+ get :status
+ get :callback
+ get :jobs
+ end
+
resource :gitorious, only: [:create, :new], controller: :gitorious do
get :status
get :callback
diff --git a/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
new file mode 100644
index 00000000000..23ac1b399ec
--- /dev/null
+++ b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
@@ -0,0 +1,6 @@
+class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration
+ def change
+ add_column :users, :bitbucket_access_token, :string
+ add_column :users, :bitbucket_access_token_secret, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d34eab75085..2659efe4df9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -334,12 +334,12 @@ ActiveRecord::Schema.define(version: 20150223022001) do
t.string "import_url"
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
+ t.string "avatar"
t.string "import_status"
t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.string "import_type"
t.string "import_source"
- t.string "avatar"
end
add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
@@ -410,12 +410,12 @@ ActiveRecord::Schema.define(version: 20150223022001) do
end
create_table "users", force: true do |t|
- t.string "email", default: "", null: false
- t.string "encrypted_password", default: "", null: false
+ t.string "email", default: "", null: false
+ t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
- t.integer "sign_in_count", default: 0
+ t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
@@ -423,22 +423,22 @@ ActiveRecord::Schema.define(version: 20150223022001) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
- t.boolean "admin", default: false, null: false
- t.integer "projects_limit", default: 10
- t.string "skype", default: "", null: false
- t.string "linkedin", default: "", null: false
- t.string "twitter", default: "", null: false
+ t.boolean "admin", default: false, null: false
+ t.integer "projects_limit", default: 10
+ t.string "skype", default: "", null: false
+ t.string "linkedin", default: "", null: false
+ t.string "twitter", default: "", null: false
t.string "authentication_token"
- t.integer "theme_id", default: 1, null: false
+ t.integer "theme_id", default: 1, null: false
t.string "bio"
- t.integer "failed_attempts", default: 0
+ t.integer "failed_attempts", default: 0
t.datetime "locked_at"
t.string "username"
- t.boolean "can_create_group", default: true, null: false
- t.boolean "can_create_team", default: true, null: false
+ t.boolean "can_create_group", default: true, null: false
+ t.boolean "can_create_team", default: true, null: false
t.string "state"
- t.integer "color_scheme_id", default: 1, null: false
- t.integer "notification_level", default: 1, null: false
+ t.integer "color_scheme_id", default: 1, null: false
+ t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at"
t.integer "created_by_id"
t.datetime "last_credential_check_at"
@@ -447,13 +447,15 @@ ActiveRecord::Schema.define(version: 20150223022001) do
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
- t.boolean "hide_no_ssh_key", default: false
- t.string "website_url", default: "", null: false
+ t.boolean "hide_no_ssh_key", default: false
+ t.string "website_url", default: "", null: false
t.string "github_access_token"
t.string "gitlab_access_token"
t.string "notification_email"
- t.boolean "hide_no_password", default: false
- t.boolean "password_automatically_set", default: false
+ t.boolean "hide_no_password", default: false
+ t.boolean "password_automatically_set", default: false
+ t.string "bitbucket_access_token"
+ t.string "bitbucket_access_token_secret"
end
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
new file mode 100644
index 00000000000..cc6389f5aaf
--- /dev/null
+++ b/doc/integration/bitbucket.md
@@ -0,0 +1,121 @@
+# Integrate your server with Bitbucket
+
+Import projects from Bitbucket and login to your GitLab instance with your Bitbucket account.
+
+To enable the Bitbucket OmniAuth provider you must register your application with Bitbucket.
+Bitbucket will generate an application ID and secret key for you to use.
+
+1. Sign in to Bitbucket.
+
+1. Navigate to your individual user settings or a team's settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or a team - that is entirely up to you.
+
+1. Select "OAuth" in the left menu.
+
+1. Select "Add consumer".
+
+1. Provide the required details.
+ - Name: This can be anything. Consider something like "\<Organization\>'s GitLab" or "\<Your Name\>'s GitLab" or something else descriptive.
+ - Application description: Fill this in if you wish.
+ - URL: The URL to your GitLab installation. 'https://gitlab.company.com'
+1. Select "Save".
+
+1. You should now see a Key and Secret in the list of OAuth customers.
+ Keep this page open as you continue configuration.
+
+1. On your GitLab server, open the configuration file.
+
+ For omnibus package:
+
+ ```sh
+ sudo editor /etc/gitlab/gitlab.rb
+ ```
+
+ For instalations from source:
+
+ ```sh
+ cd /home/git/gitlab
+
+ sudo -u git -H editor config/gitlab.yml
+ ```
+
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
+
+1. Add the provider configuration:
+
+ For omnibus package:
+
+ ```ruby
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "bitbucket",
+ "app_id" => "YOUR_KEY",
+ "app_secret" => "YOUR_APP_SECRET",
+ "url" => "https://bitbucket.org/"
+ }
+ ]
+ ```
+
+ For installation from source:
+
+ ```
+ - { name: 'bitbucket', app_id: 'YOUR_KEY',
+ app_secret: 'YOUR_APP_SECRET' }
+ ```
+
+1. Change 'YOUR_APP_ID' to the key from the Bitbucket application page from step 7.
+
+1. Change 'YOUR_APP_SECRET' to the secret from the Bitbucket application page from step 7.
+
+1. Save the configuration file.
+
+1. Restart GitLab for the changes to take effect.
+
+On the sign in page there should now be a Bitbucket icon below the regular sign in form.
+Click the icon to begin the authentication process. Bitbucket will ask the user to sign in and authorize the GitLab application.
+If everything goes well the user will be returned to GitLab and will be signed in.
+
+## Bitbucket project import
+
+To allow projects to be imported directly into GitLab, Bitbucket requires two extra setup steps compared to GitHub and GitLab.com.
+
+Bitbucket doesn't allow OAuth applications to clone repositories over HTTPS, and instead requires GitLab to use SSH and identify itself using your GitLab server's SSH key.
+
+### Step 1: Known hosts
+
+To allow GitLab to connect to Bitbucket over SSH, you need to add 'bitbucket.org' to your GitLab server's known SSH hosts. Take the following steps to do so:
+
+1. Manually connect to 'bitbucket.org' over SSH, while logged in as the `git` account that GitLab will use:
+
+ ```sh
+ ssh git@bitbucket.org
+ ```
+
+1. Verify the RSA key fingerprint you'll see in the response matches the one in the [Bitbucket documentation](https://confluence.atlassian.com/display/BITBUCKET/Use+the+SSH+protocol+with+Bitbucket#UsetheSSHprotocolwithBitbucket-KnownhostorBitbucket'spublickeyfingerprints) (the specific IP address doesn't matter):
+
+ ```sh
+ The authenticity of host 'bitbucket.org (207.223.240.182)' can't be established.
+ RSA key fingerprint is 97:8c:1b:f2:6f:14:6b:5c:3b:ec:aa:46:46:74:7c:40.
+ Are you sure you want to continue connecting (yes/no)?
+ ```
+
+1. If the fingerprint matches, type `yes` to continue connecting and have 'bitbucket.org' be added to your known hosts.
+
+1. Your GitLab server is now able to connect to Bitbucket over SSH. Continue to step 2:
+
+### Step 2: Public key
+
+To be able to access repositories on Bitbucket, GitLab will automatically register your public key with Bitbucket as a deploy key for the repositories to be imported. Your public key needs to be at `~/.ssh/id_rsa.pub`, which will expand to `/home/git/.ssh/id_rsa.pub` in most configurations.
+
+If you have that file in place, you're all set and should see the "Import projects from Bitbucket" option enabled. If you don't, do the following:
+
+1. Create a new SSH key:
+
+ ```sh
+ sudo -u git -H ssh-keygen
+ ```
+
+ Make sure to use an **empty passphrase**.
+
+2. Restart GitLab to allow it to find the new public key.
+
+You should now see the "Import projects from Bitbucket" option on the New Project page enabled.
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 137d7e9d632..a9f1bc31bb4 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,6 +1,9 @@
-# GitHub OAuth2 OmniAuth Provider
+# Integrate your server with GitHub
-To enable the GitHub OmniAuth provider you must register your application with GitHub. GitHub will generate a client ID and secret key for you to use.
+Import projects from GitHub and login to your GitLab instance with your GitHub account.
+
+To enable the GitHub OmniAuth provider you must register your application with GitHub.
+GitHub will generate an application ID and secret key for you to use.
1. Sign in to GitHub.
@@ -17,7 +20,9 @@ To enable the GitHub OmniAuth provider you must register your application with G
- Authorization callback URL: 'https://gitlab.company.com/'
1. Select "Register application".
-1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot). Keep this page open as you continue configuration. ![GitHub app](github_app.png)
+1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
+ Keep this page open as you continue configuration.
+ ![GitHub app](github_app.png)
1. On your GitLab server, open the configuration file.
@@ -35,7 +40,7 @@ To enable the GitHub OmniAuth provider you must register your application with G
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for inital settings.
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
@@ -45,8 +50,8 @@ To enable the GitHub OmniAuth provider you must register your application with G
gitlab_rails['omniauth_providers'] = [
{
"name" => "github",
- "app_id" => "YOUR APP ID",
- "app_secret" => "YOUR APP SECRET",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET",
"url" => "https://github.com/",
"args" => { "scope" => "user:email" } }
}
@@ -56,17 +61,19 @@ To enable the GitHub OmniAuth provider you must register your application with G
For installation from source:
```
- - { name: 'github', app_id: 'YOUR APP ID',
- app_secret: 'YOUR APP SECRET',
+ - { name: 'github', app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
args: { scope: 'user:email' } }
```
-1. Change 'YOUR APP ID' to the client ID from the GitHub application page from step 7.
+1. Change 'YOUR_APP_ID' to the client ID from the GitHub application page from step 7.
-1. Change 'YOUR APP SECRET' to the client secret from the GitHub application page from step 7.
+1. Change 'YOUR_APP_SECRET' to the client secret from the GitHub application page from step 7.
1. Save the configuration file.
1. Restart GitLab for the changes to take effect.
-On the sign in page there should now be a GitHub icon below the regular sign in form. Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application. If everything goes well the user will be returned to GitLab and will be signed in.
+On the sign in page there should now be a GitHub icon below the regular sign in form.
+Click the icon to begin the authentication process. GitHub will ask the user to sign in and authorize the GitLab application.
+If everything goes well the user will be returned to GitLab and will be signed in. \ No newline at end of file
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index 87400bed5b5..49ffaa62af8 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -3,7 +3,7 @@
Import projects from GitLab.com and login to your GitLab instance with your GitLab.com account.
To enable the GitLab.com OmniAuth provider you must register your application with GitLab.com.
-GitLab.com will generate a application ID and secret key for you to use.
+GitLab.com will generate an application ID and secret key for you to use.
1. Sign in to GitLab.com
@@ -46,7 +46,7 @@ GitLab.com will generate a application ID and secret key for you to use.
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for inital settings.
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
@@ -56,8 +56,8 @@ GitLab.com will generate a application ID and secret key for you to use.
gitlab_rails['omniauth_providers'] = [
{
"name" => "gitlab",
- "app_id" => "YOUR APP ID",
- "app_secret" => "YOUR APP SECRET",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET",
"args" => { "scope" => "api" } }
}
]
@@ -66,14 +66,14 @@ GitLab.com will generate a application ID and secret key for you to use.
For installations from source:
```
- - { name: 'gitlab', app_id: 'YOUR APP ID',
- app_secret: 'YOUR APP SECRET',
+ - { name: 'gitlab', app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
args: { scope: 'api' } }
```
-1. Change 'YOUR APP ID' to the Application ID from the GitLab application page.
+1. Change 'YOUR_APP_ID' to the Application ID from the GitLab.com application page.
-1. Change 'YOUR APP SECRET' to the secret from the GitLab application page.
+1. Change 'YOUR_APP_SECRET' to the secret from the GitLab.com application page.
1. Save the configuration file.
@@ -81,4 +81,4 @@ GitLab.com will generate a application ID and secret key for you to use.
On the sign in page there should now be a GitLab.com icon below the regular sign in form.
Click the icon to begin the authentication process. GitLab.com will ask the user to sign in and authorize the GitLab application.
-If everything goes well the user will be returned to your GitLab instance and will be signed in.
+If everything goes well the user will be returned to your GitLab instance and will be signed in. \ No newline at end of file
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 168077c2770..d7b741ece69 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -43,7 +43,7 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings.
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
@@ -53,8 +53,8 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
gitlab_rails['omniauth_providers'] = [
{
"name" => "google_oauth2",
- "app_id" => "YOUR APP ID",
- "app_secret" => "YOUR APP SECRET",
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET",
"args" => { "access_type" => "offline", "approval_prompt" => '' } }
}
]
@@ -63,14 +63,14 @@ To enable the Google OAuth2 OmniAuth provider you must register your application
For installations from source:
```
- - { name: 'google_oauth2', app_id: 'YOUR APP ID',
- app_secret: 'YOUR APP SECRET',
+ - { name: 'google_oauth2', app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET',
args: { access_type: 'offline', approval_prompt: '' } }
```
-1. Change 'YOUR APP ID' to the client ID from the Google Developer page from step 10.
+1. Change 'YOUR_APP_ID' to the client ID from the Google Developer page from step 10.
-1. Change 'YOUR APP SECRET' to the client secret from the Google Developer page from step 10.
+1. Change 'YOUR_APP_SECRET' to the client secret from the Google Developer page from step 10.
1. Save the configuration file.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index c92fa3ee4b7..24f7b4bb4b4 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -70,6 +70,7 @@ Now we can choose one or more of the Supported Providers below to continue confi
## Supported Providers
- [GitHub](github.md)
+- [Bitbucket](bitbucket.md)
- [GitLab.com](gitlab.md)
- [Google](google.md)
- [Shibboleth](shibboleth.md)
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index 2d517b2fbc9..fe9091ad9a8 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -47,7 +47,7 @@ To enable the Twitter OmniAuth provider you must register your application with
sudo -u git -H editor config/gitlab.yml
```
-1. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for inital settings.
+1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
@@ -57,8 +57,8 @@ To enable the Twitter OmniAuth provider you must register your application with
gitlab_rails['omniauth_providers'] = [
{
"name" => "twitter",
- "app_id" => "YOUR APP ID",
- "app_secret" => "YOUR APP SECRET"
+ "app_id" => "YOUR_APP_ID",
+ "app_secret" => "YOUR_APP_SECRET"
}
]
```
@@ -66,13 +66,13 @@ To enable the Twitter OmniAuth provider you must register your application with
For installations from source:
```
- - { name: 'twitter', app_id: 'YOUR APP ID',
- app_secret: 'YOUR APP SECRET' }
+ - { name: 'twitter', app_id: 'YOUR_APP_ID',
+ app_secret: 'YOUR_APP_SECRET' }
```
-1. Change 'YOUR APP ID' to the API key from Twitter page in step 11.
+1. Change 'YOUR_APP_ID' to the API key from Twitter page in step 11.
-1. Change 'YOUR APP SECRET' to the API secret from the Twitter page in step 11.
+1. Change 'YOUR_APP_SECRET' to the API secret from the Twitter page in step 11.
1. Save the configuration file.
diff --git a/lib/gitlab/bitbucket_import.rb b/lib/gitlab/bitbucket_import.rb
new file mode 100644
index 00000000000..7298152e7e9
--- /dev/null
+++ b/lib/gitlab/bitbucket_import.rb
@@ -0,0 +1,6 @@
+module Gitlab
+ module BitbucketImport
+ mattr_accessor :public_key
+ @public_key = nil
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/client.rb b/lib/gitlab/bitbucket_import/client.rb
new file mode 100644
index 00000000000..c907bebaef6
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/client.rb
@@ -0,0 +1,99 @@
+module Gitlab
+ module BitbucketImport
+ class Client
+ attr_reader :consumer, :api
+
+ def initialize(access_token = nil, access_token_secret = nil)
+ @consumer = ::OAuth::Consumer.new(
+ config.app_id,
+ config.app_secret,
+ bitbucket_options
+ )
+
+ if access_token && access_token_secret
+ @api = ::OAuth::AccessToken.new(@consumer, access_token, access_token_secret)
+ end
+ end
+
+ def request_token(redirect_uri)
+ request_token = consumer.get_request_token(oauth_callback: redirect_uri)
+
+ {
+ oauth_token: request_token.token,
+ oauth_token_secret: request_token.secret,
+ oauth_callback_confirmed: request_token.callback_confirmed?.to_s
+ }
+ end
+
+ def authorize_url(request_token, redirect_uri)
+ request_token = ::OAuth::RequestToken.from_hash(consumer, request_token) if request_token.is_a?(Hash)
+
+ if request_token.callback_confirmed?
+ request_token.authorize_url
+ else
+ request_token.authorize_url(oauth_callback: redirect_uri)
+ end
+ end
+
+ def get_token(request_token, oauth_verifier, redirect_uri)
+ request_token = ::OAuth::RequestToken.from_hash(consumer, request_token) if request_token.is_a?(Hash)
+
+ if request_token.callback_confirmed?
+ request_token.get_access_token(oauth_verifier: oauth_verifier)
+ else
+ request_token.get_access_token(oauth_callback: redirect_uri)
+ end
+ end
+
+ def user
+ JSON.parse(api.get("/api/1.0/user").body)
+ end
+
+ def issues(project_identifier)
+ JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues").body)
+ end
+
+ def issue_comments(project_identifier, issue_id)
+ JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/issues/#{issue_id}/comments").body)
+ end
+
+ def project(project_identifier)
+ JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}").body)
+ end
+
+ def find_deploy_key(project_identifier, key)
+ JSON.parse(api.get("/api/1.0/repositories/#{project_identifier}/deploy-keys").body).find do |deploy_key|
+ deploy_key["key"].chomp == key.chomp
+ end
+ end
+
+ def add_deploy_key(project_identifier, key)
+ deploy_key = find_deploy_key(project_identifier, key)
+ return if deploy_key
+
+ JSON.parse(api.post("/api/1.0/repositories/#{project_identifier}/deploy-keys", key: key, label: "GitLab import key").body)
+ end
+
+ def delete_deploy_key(project_identifier, key)
+ deploy_key = find_deploy_key(project_identifier, key)
+ return unless deploy_key
+
+ api.delete("/api/1.0/repositories/#{project_identifier}/deploy-keys/#{deploy_key["pk"]}").code == "204"
+ end
+
+ def projects
+ JSON.parse(api.get("/api/1.0/user/repositories").body).select { |repo| repo["scm"] == "git" }
+ end
+
+ private
+
+ def config
+ Gitlab.config.omniauth.providers.find { |provider| provider.name == "bitbucket"}
+ end
+
+ def bitbucket_options
+ OmniAuth::Strategies::Bitbucket.default_options[:client_options]
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
new file mode 100644
index 00000000000..42c93707caa
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -0,0 +1,52 @@
+module Gitlab
+ module BitbucketImport
+ class Importer
+ attr_reader :project, :client
+
+ def initialize(project)
+ @project = project
+ @client = Client.new(project.creator.bitbucket_access_token, project.creator.bitbucket_access_token_secret)
+ @formatter = Gitlab::ImportFormatter.new
+ end
+
+ def execute
+ project_identifier = project.import_source
+
+ return true unless client.project(project_identifier)["has_issues"]
+
+ #Issues && Comments
+ issues = client.issues(project_identifier)
+
+ issues["issues"].each do |issue|
+ body = @formatter.author_line(issue["reported_by"]["username"], issue["content"])
+
+ comments = client.issue_comments(project_identifier, issue["local_id"])
+
+ if comments.any?
+ body += @formatter.comments_header
+ end
+
+ comments.each do |comment|
+ body += @formatter.comment(comment["author_info"]["username"], comment["utc_created_on"], comment["content"])
+ end
+
+ project.issues.create!(
+ description: body,
+ title: issue["title"],
+ state: %w(resolved invalid duplicate wontfix).include?(issue["status"]) ? 'closed' : 'opened',
+ author_id: gl_user_id(project, issue["reported_by"]["username"])
+ )
+ end
+
+ true
+ end
+
+ private
+
+ def gl_user_id(project, bitbucket_id)
+ user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
+ (user && user.id) || project.creator_id
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/key_adder.rb b/lib/gitlab/bitbucket_import/key_adder.rb
new file mode 100644
index 00000000000..9931aa7e029
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/key_adder.rb
@@ -0,0 +1,23 @@
+module Gitlab
+ module BitbucketImport
+ class KeyAdder
+ attr_reader :repo, :current_user, :client
+
+ def initialize(repo, current_user)
+ @repo, @current_user = repo, current_user
+ @client = Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+ end
+
+ def execute
+ return false unless BitbucketImport.public_key.present?
+
+ project_identifier = "#{repo["owner"]}/#{repo["slug"]}"
+ client.add_deploy_key(project_identifier, BitbucketImport.public_key)
+
+ true
+ rescue
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/key_deleter.rb b/lib/gitlab/bitbucket_import/key_deleter.rb
new file mode 100644
index 00000000000..1a24a86fc37
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/key_deleter.rb
@@ -0,0 +1,23 @@
+module Gitlab
+ module BitbucketImport
+ class KeyDeleter
+ attr_reader :project, :current_user, :client
+
+ def initialize(project)
+ @project = project
+ @current_user = project.creator
+ @client = Client.new(current_user.bitbucket_access_token, current_user.bitbucket_access_token_secret)
+ end
+
+ def execute
+ return false unless BitbucketImport.public_key.present?
+
+ client.delete_deploy_key(project.import_source, BitbucketImport.public_key)
+
+ true
+ rescue
+ false
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
new file mode 100644
index 00000000000..db33af2c2da
--- /dev/null
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -0,0 +1,39 @@
+module Gitlab
+ module BitbucketImport
+ class ProjectCreator
+ attr_reader :repo, :namespace, :current_user
+
+ def initialize(repo, namespace, current_user)
+ @repo = repo
+ @namespace = namespace
+ @current_user = current_user
+ end
+
+ def execute
+ @project = Project.new(
+ name: repo["name"],
+ path: repo["slug"],
+ description: repo["description"],
+ namespace: namespace,
+ creator: current_user,
+ visibility_level: repo["is_private"] ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC,
+ import_type: "bitbucket",
+ import_source: "#{repo["owner"]}/#{repo["slug"]}",
+ import_url: "ssh://git@bitbucket.org/#{repo["owner"]}/#{repo["slug"]}.git"
+ )
+
+ if @project.save!
+ @project.reload
+
+ if @project.import_failed?
+ @project.import_retry
+ else
+ @project.import_start
+ end
+ end
+
+ @project
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index c9904fe8779..676d226bddd 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -46,11 +46,7 @@ module Gitlab
end
def github_options
- {
- site: 'https://api.github.com',
- authorize_url: 'https://github.com/login/oauth/authorize',
- token_url: 'https://github.com/login/oauth/access_token'
- }
+ OmniAuth::Strategies::GitHub.default_options[:client_options]
end
end
end
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index bc2b645b2d9..23832b3233c 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -20,7 +20,7 @@ module Gitlab
body += @formatter.comments_header
client.issue_comments(project.import_source, issue.number).each do |c|
- body += @formatter.comment_to_md(c.user.login, c.created_at, c.body)
+ body += @formatter.comment(c.user.login, c.created_at, c.body)
end
end
diff --git a/lib/gitlab/gitlab_import/client.rb b/lib/gitlab/gitlab_import/client.rb
index 2206b68da99..ecf4ff94e39 100644
--- a/lib/gitlab/gitlab_import/client.rb
+++ b/lib/gitlab/gitlab_import/client.rb
@@ -9,7 +9,7 @@ module Gitlab
@client = ::OAuth2::Client.new(
config.app_id,
config.app_secret,
- github_options
+ gitlab_options
)
if access_token
@@ -70,12 +70,8 @@ module Gitlab
Gitlab.config.omniauth.providers.find{|provider| provider.name == "gitlab"}
end
- def github_options
- {
- site: 'https://gitlab.com/',
- authorize_url: 'oauth/authorize',
- token_url: 'oauth/token'
- }
+ def gitlab_options
+ OmniAuth::Strategies::GitLab.default_options[:client_options]
end
end
end
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
index 5f9b14399a4..c5304a0699b 100644
--- a/lib/gitlab/gitlab_import/importer.rb
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -25,7 +25,7 @@ module Gitlab
end
comments.each do |comment|
- body += @formatter.comment_to_md(comment["author"]["name"], comment["created_at"], comment["body"])
+ body += @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"])
end
project.issues.create!(
diff --git a/lib/gitlab/import_formatter.rb b/lib/gitlab/import_formatter.rb
index ebb4b87f7e3..72e041a90b1 100644
--- a/lib/gitlab/import_formatter.rb
+++ b/lib/gitlab/import_formatter.rb
@@ -1,6 +1,6 @@
module Gitlab
class ImportFormatter
- def comment_to_md(author, date, body)
+ def comment(author, date, body)
"\n\n*By #{author} on #{date}*\n\n#{body}"
end
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
new file mode 100644
index 00000000000..5dd4124061c
--- /dev/null
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -0,0 +1,78 @@
+require 'spec_helper'
+
+describe Import::BitbucketController do
+ let(:user) { create(:user, bitbucket_access_token: 'asd123', bitbucket_access_token_secret: "sekret") }
+
+ before do
+ sign_in(user)
+ controller.stub(:bitbucket_import_enabled?).and_return(true)
+ end
+
+ describe "GET callback" do
+ before do
+ session[:oauth_request_token] = {}
+ end
+
+ it "updates access token" do
+ token = "asdasd12345"
+ secret = "sekrettt"
+ access_token = double(token: token, secret: secret)
+ Gitlab::BitbucketImport::Client.any_instance.stub(:get_token).and_return(access_token)
+ Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket")
+
+ get :callback
+
+ expect(user.reload.bitbucket_access_token).to eq(token)
+ expect(user.reload.bitbucket_access_token_secret).to eq(secret)
+ expect(controller).to redirect_to(status_import_bitbucket_url)
+ end
+ end
+
+ describe "GET status" do
+ before do
+ @repo = OpenStruct.new(slug: 'vim', owner: 'asd')
+ end
+
+ it "assigns variables" do
+ @project = create(:project, import_type: 'bitbucket', creator_id: user.id)
+ controller.stub_chain(:client, :projects).and_return([@repo])
+
+ get :status
+
+ expect(assigns(:already_added_projects)).to eq([@project])
+ expect(assigns(:repos)).to eq([@repo])
+ end
+
+ it "does not show already added project" do
+ @project = create(:project, import_type: 'bitbucket', creator_id: user.id, import_source: 'asd/vim')
+ controller.stub_chain(:client, :projects).and_return([@repo])
+
+ get :status
+
+ expect(assigns(:already_added_projects)).to eq([@project])
+ expect(assigns(:repos)).to eq([])
+ end
+ end
+
+ describe "POST create" do
+ before do
+ @repo = {
+ slug: 'vim',
+ owner: "john"
+ }.with_indifferent_access
+ end
+
+ it "takes already existing namespace" do
+ namespace = create(:namespace, name: "john", owner: user)
+ expect(Gitlab::BitbucketImport::KeyAdder).
+ to receive(:new).with(@repo, user).
+ and_return(double(execute: true))
+ expect(Gitlab::BitbucketImport::ProjectCreator).
+ to receive(:new).with(@repo, namespace, user).
+ and_return(double(execute: true))
+ controller.stub_chain(:client, :project).and_return(@repo)
+
+ post :create, format: :js
+ end
+ end
+end
diff --git a/spec/controllers/import/github_controller_spec.rb b/spec/controllers/import/github_controller_spec.rb
index 3b779855d3f..b8820413406 100644
--- a/spec/controllers/import/github_controller_spec.rb
+++ b/spec/controllers/import/github_controller_spec.rb
@@ -5,6 +5,7 @@ describe Import::GithubController do
before do
sign_in(user)
+ controller.stub(:github_import_enabled?).and_return(true)
end
describe "GET callback" do
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
index 287aa315db5..b6b86b1bcee 100644
--- a/spec/controllers/import/gitlab_controller_spec.rb
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -5,6 +5,7 @@ describe Import::GitlabController do
before do
sign_in(user)
+ controller.stub(:gitlab_import_enabled?).and_return(true)
end
describe "GET callback" do
diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
new file mode 100644
index 00000000000..f5523105848
--- /dev/null
+++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe Gitlab::BitbucketImport::ProjectCreator do
+ let(:user) { create(:user, bitbucket_access_token: "asdffg", bitbucket_access_token_secret: "sekret") }
+ let(:repo) { {
+ name: 'Vim',
+ slug: 'vim',
+ is_private: true,
+ owner: "asd"}.with_indifferent_access
+ }
+ let(:namespace){ create(:namespace) }
+
+ it 'creates project' do
+ allow_any_instance_of(Project).to receive(:add_import_job)
+
+ project_creator = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, user)
+ project = project_creator.execute
+
+ expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git")
+ expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
+ end
+end
diff --git a/spec/lib/gitlab/github/project_creator.rb b/spec/lib/gitlab/github_import/project_creator_spec.rb
index 3686ddbf170..8d594a112d4 100644
--- a/spec/lib/gitlab/github/project_creator.rb
+++ b/spec/lib/gitlab/github_import/project_creator_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Github::ProjectCreator do
+describe Gitlab::GithubImport::ProjectCreator do
let(:user) { create(:user, github_access_token: "asdffg") }
let(:repo) { OpenStruct.new(
login: 'vim',
@@ -15,9 +15,8 @@ describe Gitlab::Github::ProjectCreator do
it 'creates project' do
allow_any_instance_of(Project).to receive(:add_import_job)
- project_creator = Gitlab::Github::ProjectCreator.new(repo, namespace, user)
- project_creator.execute
- project = Project.last
+ project_creator = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, user)
+ project = project_creator.execute
expect(project.import_url).to eq("https://asdffg@gitlab.com/asd/vim.git")
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
diff --git a/spec/lib/gitlab/gitlab_import/project_creator.rb b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
index e5d917830b0..4c0d64ed138 100644
--- a/spec/lib/gitlab/gitlab_import/project_creator.rb
+++ b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::GitlabImport::ProjectCreator do
let(:user) { create(:user, gitlab_access_token: "asdffg") }
- let(:repo) {{
+ let(:repo) { {
name: 'vim',
path: 'vim',
visibility_level: Gitlab::VisibilityLevel::PRIVATE,
@@ -16,8 +16,7 @@ describe Gitlab::GitlabImport::ProjectCreator do
allow_any_instance_of(Project).to receive(:add_import_job)
project_creator = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, user)
- project_creator.execute
- project = Project.last
+ project = project_creator.execute
expect(project.import_url).to eq("https://oauth2:asdffg@gitlab.com/asd/vim.git")
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)