Commit a52529f9 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'bitbucket-import'

Conflicts:
	app/views/import/gitorious/status.html.haml
	db/schema.rb
parents 7475f4f0 56f51bed
......@@ -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.
......
......@@ -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"
......
......@@ -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
......
......@@ -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
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
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
......
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
......
......@@ -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
......@@ -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
......@@ -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
......
......@@ -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'
......
......@@ -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")
%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}")
%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
......
%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
......
%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
......
%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
......@@ -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
......@@ -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
......@@ -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
......
......@@ -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
......@@ -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'}
......
path = File.expand_path("~/.ssh/id_rsa.pub")
Gitlab::BitbucketImport.public_key = File.read(path) if File.exist?(path)
......@@ -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
......
class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration
def change
add_column :users, :bitbucket_access_token, :string
add_column :users, :bitbucket_access_token_secret, :string
end
end
......@@ -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
......
# 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.
# 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
......@@ -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
......@@ -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.
......
......@@ -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)
......
......@@ -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.
......
module Gitlab
module BitbucketImport
mattr_accessor :public_key
@public_key = nil
end
end
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
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
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
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
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
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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!(
......
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
......
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
......@@ -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
......
......@@ -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
......
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
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)
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment