/app/controllers/import/bitbucket_controller.rb

https://gitlab.com/artofhuman/gitlab-ce · Ruby · 107 lines · 77 code · 25 blank · 5 comment · 7 complexity · 0edc7043b47dc7d2a30363abd177bad9 MD5 · raw file

  1. # frozen_string_literal: true
  2. class Import::BitbucketController < Import::BaseController
  3. before_action :verify_bitbucket_import_enabled
  4. before_action :bitbucket_auth, except: :callback
  5. rescue_from OAuth2::Error, with: :bitbucket_unauthorized
  6. rescue_from Bitbucket::Error::Unauthorized, with: :bitbucket_unauthorized
  7. def callback
  8. response = client.auth_code.get_token(params[:code], redirect_uri: callback_import_bitbucket_url)
  9. session[:bitbucket_token] = response.token
  10. session[:bitbucket_expires_at] = response.expires_at
  11. session[:bitbucket_expires_in] = response.expires_in
  12. session[:bitbucket_refresh_token] = response.refresh_token
  13. redirect_to status_import_bitbucket_url
  14. end
  15. # rubocop: disable CodeReuse/ActiveRecord
  16. def status
  17. bitbucket_client = Bitbucket::Client.new(credentials)
  18. repos = bitbucket_client.repos
  19. @repos, @incompatible_repos = repos.partition { |repo| repo.valid? }
  20. @already_added_projects = find_already_added_projects('bitbucket')
  21. already_added_projects_names = @already_added_projects.pluck(:import_source)
  22. @repos.to_a.reject! { |repo| already_added_projects_names.include?(repo.full_name) }
  23. end
  24. # rubocop: enable CodeReuse/ActiveRecord
  25. def jobs
  26. render json: find_jobs('bitbucket')
  27. end
  28. def create
  29. bitbucket_client = Bitbucket::Client.new(credentials)
  30. repo_id = params[:repo_id].to_s
  31. name = repo_id.gsub('___', '/')
  32. repo = bitbucket_client.repo(name)
  33. project_name = params[:new_name].presence || repo.name
  34. repo_owner = repo.owner
  35. repo_owner = current_user.username if repo_owner == bitbucket_client.user.username
  36. namespace_path = params[:new_namespace].presence || repo_owner
  37. target_namespace = find_or_create_namespace(namespace_path, current_user)
  38. if current_user.can?(:create_projects, target_namespace)
  39. # The token in a session can be expired, we need to get most recent one because
  40. # Bitbucket::Connection class refreshes it.
  41. session[:bitbucket_token] = bitbucket_client.connection.token
  42. project = Gitlab::BitbucketImport::ProjectCreator.new(repo, project_name, target_namespace, current_user, credentials).execute
  43. if project.persisted?
  44. render json: ProjectSerializer.new.represent(project)
  45. else
  46. render json: { errors: project_save_error(project) }, status: :unprocessable_entity
  47. end
  48. else
  49. render json: { errors: 'This namespace has already been taken! Please choose another one.' }, status: :unprocessable_entity
  50. end
  51. end
  52. private
  53. def client
  54. @client ||= OAuth2::Client.new(provider.app_id, provider.app_secret, options)
  55. end
  56. def provider
  57. Gitlab::Auth::OAuth::Provider.config_for('bitbucket')
  58. end
  59. def options
  60. OmniAuth::Strategies::Bitbucket.default_options[:client_options].deep_symbolize_keys
  61. end
  62. def verify_bitbucket_import_enabled
  63. render_404 unless bitbucket_import_enabled?
  64. end
  65. def bitbucket_auth
  66. go_to_bitbucket_for_permissions if session[:bitbucket_token].blank?
  67. end
  68. def go_to_bitbucket_for_permissions
  69. redirect_to client.auth_code.authorize_url(redirect_uri: callback_import_bitbucket_url)
  70. end
  71. def bitbucket_unauthorized
  72. go_to_bitbucket_for_permissions
  73. end
  74. def credentials
  75. {
  76. token: session[:bitbucket_token],
  77. expires_at: session[:bitbucket_expires_at],
  78. expires_in: session[:bitbucket_expires_in],
  79. refresh_token: session[:bitbucket_refresh_token]
  80. }
  81. end
  82. end