Commit 386a8f8c authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents 2cd8473c 6c3cc909
...@@ -18,6 +18,7 @@ class Import::BaseController < ApplicationController ...@@ -18,6 +18,7 @@ class Import::BaseController < ApplicationController
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
# deprecated: being replaced by app/services/import/base_service.rb
def find_or_create_namespace(names, owner) def find_or_create_namespace(names, owner)
names = params[:target_namespace].presence || names names = params[:target_namespace].presence || names
...@@ -32,6 +33,7 @@ class Import::BaseController < ApplicationController ...@@ -32,6 +33,7 @@ class Import::BaseController < ApplicationController
current_user.namespace current_user.namespace
end end
# deprecated: being replaced by app/services/import/base_service.rb
def project_save_error(project) def project_save_error(project)
project.errors.full_messages.join(', ') project.errors.full_messages.join(', ')
end end
......
...@@ -41,28 +41,21 @@ class Import::GithubController < Import::BaseController ...@@ -41,28 +41,21 @@ class Import::GithubController < Import::BaseController
end end
def create def create
repo = client.repo(params[:repo_id].to_i) result = Import::GithubService.new(client, current_user, import_params).execute(access_params, provider)
project_name = params[:new_name].presence || repo.name
namespace_path = params[:target_namespace].presence || current_user.namespace_path if result[:status] == :success
target_namespace = find_or_create_namespace(namespace_path, current_user.namespace_path) render json: ProjectSerializer.new.represent(result[:project])
if can?(current_user, :create_projects, target_namespace)
project = Gitlab::LegacyGithubImport::ProjectCreator
.new(repo, project_name, target_namespace, current_user, access_params, type: provider)
.execute(extra_project_attrs)
if project.persisted?
render json: ProjectSerializer.new.represent(project)
else
render json: { errors: project_save_error(project) }, status: :unprocessable_entity
end
else else
render json: { errors: 'This namespace has already been taken! Please choose another one.' }, status: :unprocessable_entity render json: { errors: result[:message] }, status: result[:http_status]
end end
end end
private private
def import_params
params.permit(:repo_id, :new_name, :target_namespace)
end
def client def client
@client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], client_options) @client ||= Gitlab::LegacyGithubImport::Client.new(session[access_token_key], client_options)
end end
...@@ -126,10 +119,6 @@ class Import::GithubController < Import::BaseController ...@@ -126,10 +119,6 @@ class Import::GithubController < Import::BaseController
{} {}
end end
def extra_project_attrs
{}
end
def extra_import_params def extra_import_params
{} {}
end end
......
...@@ -180,8 +180,6 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -180,8 +180,6 @@ class Projects::IssuesController < Projects::ApplicationController
end end
def import_csv def import_csv
return render_404 unless Feature.enabled?(:issues_import_csv)
if uploader = UploadService.new(project, params[:file]).execute if uploader = UploadService.new(project, params[:file]).execute
ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id) ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id)
......
# frozen_string_literal: true
module Import
class BaseService < ::BaseService
def initialize(client, user, params)
@client = client
@current_user = user
@params = params
end
private
def find_or_create_namespace(namespace, owner)
namespace = params[:target_namespace].presence || namespace
return current_user.namespace if namespace == owner
group = Groups::NestedCreateService.new(current_user, group_path: namespace).execute
group.errors.any? ? current_user.namespace : group
rescue => e
Gitlab::AppLogger.error(e)
current_user.namespace
end
def project_save_error(project)
project.errors.full_messages.join(', ')
end
def success(project)
super().merge(project: project, status: :success)
end
end
end
# frozen_string_literal: true
module Import
class GithubService < Import::BaseService
attr_accessor :client
attr_reader :params, :current_user
def execute(access_params, provider)
unless authorized?
return error('This namespace has already been taken! Please choose another one.', :unprocessable_entity)
end
project = Gitlab::LegacyGithubImport::ProjectCreator
.new(repo, project_name, target_namespace, current_user, access_params, type: provider)
.execute(extra_project_attrs)
if project.persisted?
success(project)
else
error(project_save_error(project), :unprocessable_entity)
end
end
def repo
@repo ||= client.repo(params[:repo_id].to_i)
end
def project_name
@project_name ||= params[:new_name].presence || repo.name
end
def namespace_path
@namespace_path ||= params[:target_namespace].presence || current_user.namespace_path
end
def target_namespace
@target_namespace ||= find_or_create_namespace(namespace_path, current_user.namespace_path)
end
def extra_project_attrs
{}
end
def authorized?
can?(current_user, :create_projects, target_namespace)
end
end
end
- show_feed_buttons = local_assigns.fetch(:show_feed_buttons, true) - show_feed_buttons = local_assigns.fetch(:show_feed_buttons, true)
- show_import_button = local_assigns.fetch(:show_import_button, true) && Feature.enabled?(:issues_import_csv) && can?(current_user, :import_issues, @project) - show_import_button = local_assigns.fetch(:show_import_button, true) && can?(current_user, :import_issues, @project)
- show_export_button = local_assigns.fetch(:show_export_button, true) - show_export_button = local_assigns.fetch(:show_export_button, true)
.nav-controls.issues-nav-controls .nav-controls.issues-nav-controls
......
- button_path = local_assigns.fetch(:button_path, false) - button_path = local_assigns.fetch(:button_path, false)
- project_select_button = local_assigns.fetch(:project_select_button, false) - project_select_button = local_assigns.fetch(:project_select_button, false)
- show_import_button = local_assigns.fetch(:show_import_button, false) && Feature.enabled?(:issues_import_csv) && can?(current_user, :import_issues, @project) - show_import_button = local_assigns.fetch(:show_import_button, false) && can?(current_user, :import_issues, @project)
- has_button = button_path || project_select_button - has_button = button_path || project_select_button
- closed_issues_count = issuables_count_for_state(:issues, :closed) - closed_issues_count = issuables_count_for_state(:issues, :closed)
- opened_issues_count = issuables_count_for_state(:issues, :opened) - opened_issues_count = issuables_count_for_state(:issues, :opened)
......
# Import API
## Import repository from GitHub
Import your projects from GitHub to GitLab via the API.
```
POST /import/github
```
| Attribute | Type | Required | Description |
|------------|---------|----------|---------------------|
| `personal_access_token` | string | yes | GitHub personal access token |
| `repo_id` | integer | yes | GitHub repository ID |
| `new_name` | string | no | New repo name |
| `target_namespace` | string | yes | Namespace to import repo into |
```bash
curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data "personal_access_token=abc123&repo_id=12345&target_namespace=root" https://gitlab.example.com/api/v4/import/github
```
Example response:
```json
{
"id": 27,
"name": "my-repo",
"full_path": "/root/my-repo",
"full_name": "Administrator / my-repo"
}
```
...@@ -117,6 +117,7 @@ module API ...@@ -117,6 +117,7 @@ module API
mount ::API::GroupMilestones mount ::API::GroupMilestones
mount ::API::Groups mount ::API::Groups
mount ::API::GroupVariables mount ::API::GroupVariables
mount ::API::ImportGithub
mount ::API::Internal mount ::API::Internal
mount ::API::Issues mount ::API::Issues
mount ::API::JobArtifacts mount ::API::JobArtifacts
......
# frozen_string_literal: true
module API
class ImportGithub < Grape::API
rescue_from Octokit::Unauthorized, with: :provider_unauthorized
helpers do
def client
@client ||= Gitlab::LegacyGithubImport::Client.new(params[:personal_access_token], client_options)
end
def access_params
{ github_access_token: params[:personal_access_token] }
end
def client_options
{}
end
def provider
:github
end
end
desc 'Import a GitHub project' do
detail 'This feature was introduced in GitLab 11.3.4.'
success Entities::ProjectEntity
end
params do
requires :personal_access_token, type: String, desc: 'GitHub personal access token'
requires :repo_id, type: Integer, desc: 'GitHub repository ID'
optional :new_name, type: String, desc: 'New repo name'
requires :target_namespace, type: String, desc: 'Namespace to import repo into'
end
post 'import/github' do
result = Import::GithubService.new(client, current_user, params).execute(access_params, provider)
if result[:status] == :success
present ProjectSerializer.new.represent(result[:project])
else
status result[:http_status]
{ errors: result[:message] }
end
end
end
end
...@@ -1030,19 +1030,6 @@ describe Projects::IssuesController do ...@@ -1030,19 +1030,6 @@ describe Projects::IssuesController do
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') } let(:file) { fixture_file_upload('spec/fixtures/csv_comma.csv') }
context 'feature disabled' do
it 'returns 404' do
sign_in(user)
project.add_maintainer(user)
stub_feature_flags(issues_import_csv: false)
import_csv
expect(response).to have_gitlab_http_status :not_found
end
end
context 'unauthorized' do context 'unauthorized' do
it 'returns 404 for guests' do it 'returns 404 for guests' do
sign_out(:user) sign_out(:user)
......
require 'spec_helper'
describe API::ImportGithub do
include ApiHelpers
let(:token) { "asdasd12345" }
let(:provider) { :github }
let(:access_params) { { github_access_token: token } }
describe "POST /import/github" do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:provider_username) { user.username }
let(:provider_user) { OpenStruct.new(login: provider_username) }
let(:provider_repo) do
OpenStruct.new(
name: 'vim',
full_name: "#{provider_username}/vim",
owner: OpenStruct.new(login: provider_username)
)
end
before do
Grape::Endpoint.before_each do |endpoint|
allow(endpoint).to receive(:client).and_return(double('client', user: provider_user, repo: provider_repo).as_null_object)
end
end
it 'returns 201 response when the project is imported successfully' do
allow(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, access_params, type: provider)
.and_return(double(execute: project))
post api("/import/github", user), params: {
target_namespace: user.namespace_path,
personal_access_token: token,
repo_id: 1234
}
expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash
expect(json_response['name']).to eq(project.name)
end
it 'returns 422 response when user can not create projects in the chosen namespace' do
other_namespace = create(:group, name: 'other_namespace')
post api("/import/github", user), params: {
target_namespace: other_namespace.name,
personal_access_token: token,
repo_id: 1234
}
expect(response).to have_gitlab_http_status(422)
end
end
end
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