Commit 80fd5b67 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'ce_non_conflict' into 'master'

CE upstream

See merge request !305
parents cb8b5c32 45ec0d25
...@@ -9,7 +9,7 @@ v 7.8.0 ...@@ -9,7 +9,7 @@ v 7.8.0
- Cleaner UI for web editor - Cleaner UI for web editor
- Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger) - Add diff syntax highlighting in email-on-push service notifications (Hannes Rosenögger)
- Add API endpoint to fetch all changes on a MergeRequest (Jeroen van Baarsen) - Add API endpoint to fetch all changes on a MergeRequest (Jeroen van Baarsen)
- - View note image attachments in new tab when clicked instead of downloading them
- -
- Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger) - Allow more variations for commit messages closing issues (Julien Bianchi and Hannes Rosenögger)
- -
...@@ -32,10 +32,12 @@ v 7.8.0 ...@@ -32,10 +32,12 @@ v 7.8.0
- Disable blacklist validation for project names - Disable blacklist validation for project names
- Allow configuring protection of the default branch upon first push (Marco Wessel) - Allow configuring protection of the default branch upon first push (Marco Wessel)
- -
- Add gitlab.com importer
- Add an ability to login with gitlab.com
- -
- Add a commit calendar to the user profile (Hannes Rosenögger) - Add a commit calendar to the user profile (Hannes Rosenögger)
- -
- - Submit comment on command-enter
- -
- Fix long broadcast message cut-off on left sidebar (Visay Keo) - Fix long broadcast message cut-off on left sidebar (Visay Keo)
- Add Project Avatars (Steven Thonus and Hannes Rosenögger) - Add Project Avatars (Steven Thonus and Hannes Rosenögger)
...@@ -49,7 +51,7 @@ v 7.8.0 ...@@ -49,7 +51,7 @@ v 7.8.0
- -
- Add action property to merge request hook (Julien Bianchi) - Add action property to merge request hook (Julien Bianchi)
- -
- - Remove duplicates from group milestone participants list.
- -
- -
- Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger) - Add a new API function that retrieves all issues assigned to a single milestone (Justin Whear and Hannes Rosenögger)
......
...@@ -29,6 +29,7 @@ gem 'omniauth-twitter' ...@@ -29,6 +29,7 @@ gem 'omniauth-twitter'
gem 'omniauth-github' gem 'omniauth-github'
gem 'omniauth-shibboleth' gem 'omniauth-shibboleth'
gem 'omniauth-kerberos' gem 'omniauth-kerberos'
gem 'omniauth-gitlab'
gem 'doorkeeper', '2.1.0' gem 'doorkeeper', '2.1.0'
gem "rack-oauth2", "~> 1.0.5" gem "rack-oauth2", "~> 1.0.5"
......
...@@ -333,6 +333,9 @@ GEM ...@@ -333,6 +333,9 @@ GEM
omniauth-github (1.1.1) omniauth-github (1.1.1)
omniauth (~> 1.0) omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
omniauth-gitlab (1.0.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
omniauth-google-oauth2 (0.2.5) omniauth-google-oauth2 (0.2.5)
omniauth (> 1.0) omniauth (> 1.0)
omniauth-oauth2 (~> 1.1) omniauth-oauth2 (~> 1.1)
...@@ -695,6 +698,7 @@ DEPENDENCIES ...@@ -695,6 +698,7 @@ DEPENDENCIES
octokit (= 3.7.0) octokit (= 3.7.0)
omniauth (~> 1.1.3) omniauth (~> 1.1.3)
omniauth-github omniauth-github
omniauth-gitlab
omniauth-google-oauth2 omniauth-google-oauth2
omniauth-kerberos omniauth-kerberos
omniauth-shibboleth omniauth-shibboleth
......
class @ImporterStatus
constructor: (@jobs_url, @import_url) ->
this.initStatusPage()
this.setAutoUpdate()
initStatusPage: ->
$(".btn-add-to-import").click (event) =>
new_namespace = null
tr = $(event.currentTarget).closest("tr")
id = tr.attr("id").replace("repo_", "")
if tr.find(".import-target input").length > 0
new_namespace = tr.find(".import-target input").prop("value")
tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
$.post @import_url, {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
setAutoUpdate: ->
setInterval (=>
$.get @jobs_url, (data) =>
$.each data, (i, job) =>
job_item = $("#project_" + job.id)
status_field = job_item.find(".job-status")
if job.import_status == 'finished'
job_item.removeClass("active").addClass("success")
status_field.html('<span class="cgreen"><i class="fa fa-check"></i> done</span>')
else if job.import_status == 'started'
status_field.html("<i class='fa fa-spinner fa-spin'></i> started")
else
status_field.html(job.import_status)
), 4000
\ No newline at end of file
...@@ -59,7 +59,7 @@ class @Notes ...@@ -59,7 +59,7 @@ class @Notes
@notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea' @notes_forms = '.js-main-target-form textarea, .js-discussion-note-form textarea'
$(document).on('keypress', @notes_forms, (e)-> $(document).on('keypress', @notes_forms, (e)->
if e.keyCode == 10 || (e.ctrlKey && e.keyCode == 13) if e.keyCode == 10 || ((e.metaKey || e.ctrlKey) && e.keyCode == 13)
$(@).parents('form').submit() $(@).parents('form').submit()
) )
......
...@@ -5,7 +5,8 @@ class FilesController < ApplicationController ...@@ -5,7 +5,8 @@ class FilesController < ApplicationController
if uploader.file_storage? if uploader.file_storage?
if can?(current_user, :read_project, note.project) if can?(current_user, :read_project, note.project)
send_file uploader.file.path, disposition: 'attachment' disposition = uploader.image? ? 'inline' : 'attachment'
send_file uploader.file.path, disposition: disposition
else else
not_found! not_found!
end end
......
class Import::BaseController < ApplicationController
private
def get_or_create_namespace
existing_namespace = Namespace.find_by("path = ? OR name = ?", @target_namespace, @target_namespace)
if existing_namespace
if existing_namespace.owner == current_user
namespace = existing_namespace
else
@already_been_taken = true
return false
end
else
namespace = Group.create(name: @target_namespace, path: @target_namespace, owner: current_user)
namespace.add_owner(current_user)
namespace
end
end
end
class GithubImportsController < ApplicationController class Import::GithubController < Import::BaseController
before_filter :github_auth, except: :callback before_filter :github_auth, except: :callback
rescue_from Octokit::Unauthorized, with: :github_unauthorized rescue_from Octokit::Unauthorized, with: :github_unauthorized
def callback def callback
token = client.auth_code.get_token(params[:code]).token token = client.get_token(params[:code])
current_user.github_access_token = token current_user.github_access_token = token
current_user.save current_user.save
redirect_to status_github_import_url redirect_to status_import_github_url
end end
def status def status
@repos = octo_client.repos @repos = client.repos
octo_client.orgs.each do |org| client.orgs.each do |org|
@repos += octo_client.repos(org.login) @repos += client.repos(org.login)
end end
@already_added_projects = current_user.created_projects.where(import_type: "github") @already_added_projects = current_user.created_projects.where(import_type: "github")
already_added_projects_names = @already_added_projects.pluck(:import_source) already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.reject!{|repo| already_added_projects_names.include? repo.full_name} @repos.reject!{ |repo| already_added_projects_names.include? repo.full_name }
end end
def jobs def jobs
...@@ -29,36 +29,19 @@ class GithubImportsController < ApplicationController ...@@ -29,36 +29,19 @@ class GithubImportsController < ApplicationController
def create def create
@repo_id = params[:repo_id].to_i @repo_id = params[:repo_id].to_i
repo = octo_client.repo(@repo_id) repo = client.repo(@repo_id)
target_namespace = params[:new_namespace].presence || repo.owner.login @target_namespace = params[:new_namespace].presence || repo.owner.login
existing_namespace = Namespace.find_by("path = ? OR name = ?", target_namespace, target_namespace)
if existing_namespace
if existing_namespace.owner == current_user
namespace = existing_namespace
else
@already_been_taken = true
@target_namespace = target_namespace
@project_name = repo.name @project_name = repo.name
render and return
end
else
namespace = Group.create(name: target_namespace, path: target_namespace, owner: current_user)
namespace.add_owner(current_user)
end
@project = Gitlab::Github::ProjectCreator.new(repo, namespace, current_user).execute namespace = get_or_create_namespace || (render and return)
@project = Gitlab::GithubImport::ProjectCreator.new(repo, namespace, current_user).execute
end end
private private
def client def client
@client ||= Gitlab::Github::Client.new.client @client ||= Gitlab::GithubImport::Client.new(current_user.github_access_token)
end
def octo_client
Octokit.auto_paginate = true
@octo_client ||= Octokit::Client.new(access_token: current_user.github_access_token)
end end
def github_auth def github_auth
...@@ -68,10 +51,7 @@ class GithubImportsController < ApplicationController ...@@ -68,10 +51,7 @@ class GithubImportsController < ApplicationController
end end
def go_to_github_for_permissions def go_to_github_for_permissions
redirect_to client.auth_code.authorize_url({ redirect_to client.authorize_url(callback_import_github_url)
redirect_uri: callback_github_import_url,
scope: "repo, user, user:email"
})
end end
def github_unauthorized def github_unauthorized
......
class Import::GitlabController < Import::BaseController
before_filter :gitlab_auth, except: :callback
rescue_from OAuth2::Error, with: :gitlab_unauthorized
def callback
token = client.get_token(params[:code], callback_import_gitlab_url)
current_user.gitlab_access_token = token
current_user.save
redirect_to status_import_gitlab_url
end
def status
@repos = client.projects
@already_added_projects = current_user.created_projects.where(import_type: "gitlab")
already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos.to_a.reject!{ |repo| already_added_projects_names.include? repo["path_with_namespace"] }
end
def jobs
jobs = current_user.created_projects.where(import_type: "gitlab").to_json(only: [:id, :import_status])
render json: jobs
end
def create
@repo_id = params[:repo_id].to_i
repo = client.project(@repo_id)
@target_namespace = params[:new_namespace].presence || repo["namespace"]["path"]
@project_name = repo["name"]
namespace = get_or_create_namespace || (render and return)
@project = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, current_user).execute
end
private
def client
@client ||= Gitlab::GitlabImport::Client.new(current_user.gitlab_access_token)
end
def gitlab_auth
if current_user.gitlab_access_token.blank?
go_to_gitlab_for_permissions
end
end
def go_to_gitlab_for_permissions
redirect_to client.authorize_url(callback_import_gitlab_url)
end
def gitlab_unauthorized
go_to_gitlab_for_permissions
end
end
class RegistrationsController < Devise::RegistrationsController class RegistrationsController < Devise::RegistrationsController
before_filter :signup_enabled? before_filter :signup_enabled?
def new
redirect_to(new_user_session_path)
end
def destroy def destroy
current_user.destroy current_user.destroy
......
...@@ -12,7 +12,7 @@ module OauthHelper ...@@ -12,7 +12,7 @@ module OauthHelper
end end
def default_providers def default_providers
[:twitter, :github, :google_oauth2, :ldap] [:twitter, :github, :gitlab, :google_oauth2, :ldap]
end end
def enabled_oauth_providers def enabled_oauth_providers
...@@ -21,7 +21,7 @@ module OauthHelper ...@@ -21,7 +21,7 @@ module OauthHelper
def enabled_social_providers def enabled_social_providers
enabled_oauth_providers.select do |name| enabled_oauth_providers.select do |name|
[:twitter, :github, :google_oauth2, :kerberos].include?(name.to_sym) [:twitter, :gitlab, :github, :google_oauth2, :kerberos,].include?(name.to_sym)
end end
end end
......
...@@ -254,6 +254,10 @@ module ProjectsHelper ...@@ -254,6 +254,10 @@ module ProjectsHelper
enabled_oauth_providers.include?(:github) enabled_oauth_providers.include?(:github)
end end
def gitlab_import_enabled?
enabled_oauth_providers.include?(:gitlab)
end
def membership_locked? def membership_locked?
if @project.group && @project.group.membership_lock if @project.group && @project.group.membership_lock
true true
......
...@@ -66,15 +66,15 @@ class GroupMilestone ...@@ -66,15 +66,15 @@ class GroupMilestone
end end
def issues def issues
@group_issues ||= milestones.map { |milestone| milestone.issues }.flatten.group_by(&:state) @group_issues ||= milestones.map(&:issues).flatten.group_by(&:state)
end end
def merge_requests def merge_requests
@group_merge_requests ||= milestones.map { |milestone| milestone.merge_requests }.flatten.group_by(&:state) @group_merge_requests ||= milestones.map(&:merge_requests).flatten.group_by(&:state)
end end
def participants def participants
milestones.map { |milestone| milestone.participants.uniq }.reject(&:empty?).flatten @group_participants ||= milestones.map(&:participants).flatten.compact.uniq
end end
def opened_issues def opened_issues
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
%tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"} %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
%td= project.import_source %td= project.import_source
%td %td
%strong= link_to project.name_with_namespace, project %strong= link_to project.path_with_namespace, project
%td.job-status %td.job-status
- if project.import_status == 'finished' - if project.import_status == 'finished'
%span.cgreen %span.cgreen
...@@ -34,30 +34,6 @@ ...@@ -34,30 +34,6 @@
%td.import-actions.job-status %td.import-actions.job-status
= button_tag "Add", class: "btn btn-add-to-import" = button_tag "Add", class: "btn btn-add-to-import"
:coffeescript :coffeescript
$(".btn-add-to-import").click () -> $ ->
new_namespace = null new ImporterStatus("#{jobs_import_github_path}", "#{import_github_path}")
tr = $(this).closest("tr")
id = tr.attr("id").replace("repo_", "")
if tr.find(".import-target input").length > 0
new_namespace = tr.find(".import-target input").prop("value")
tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
$.post "#{github_import_url}", {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
setInterval (->
$.get "#{jobs_github_import_path}", (data)->
$.each data, (i, job) ->
job_item = $("#project_" + job.id)
status_field = job_item.find(".job-status")
if job.import_status == 'finished'
job_item.removeClass("active").addClass("success")
status_field.html('<span class="cgreen"><i class="fa fa-check"></i> done</span>')
else if job.import_status == 'started'
status_field.html("<i class='fa fa-spinner fa-spin'></i> started")
else
status_field.html(job.import_status)
), 4000
%h3.page-title
%i.fa.fa-github
Import repositories from GitLab.com
%p.light
Select projects you want to import.
%hr
%table.table.import-jobs
%thead
%tr
%th From GitLab.com
%th To GitLab private 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
%strong= link_to project.path_with_namespace, project
%td.job-status
- if project.import_status == 'finished'
%span.cgreen
%i.fa.fa-check
done
- else
= project.human_import_status_name
- @repos.each do |repo|
%tr{id: "repo_#{repo["id"]}"}
%td= repo["path_with_namespace"]
%td.import-target
= repo["path_with_namespace"]
%td.import-actions.job-status
= button_tag "Add", class: "btn btn-add-to-import"
:coffeescript
$ ->
new ImporterStatus("#{jobs_import_gitlab_path}", "#{import_gitlab_url}")
...@@ -7,16 +7,3 @@ ...@@ -7,16 +7,3 @@
.modal-body .modal-body
You need to setup integration with GitHub first. 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' = link_to 'How to setup integration with GitHub', 'https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/integration/github.md'
:javascript
$(function(){
var import_modal = $('#github_import_modal').modal({modal: true, show:false});
$('.how_to_import_link').bind("click", function(e){
e.preventDefault();
import_modal.show();
});
$('.modal-header .close').bind("click", function(){
import_modal.hide();
})
})
%div#gitlab_import_modal.modal.hide
.modal-dialog
.modal-content
.modal-header
%a.close{href: "#", "data-dismiss" => "modal"} ×
%h3 GitLab OAuth import
.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
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
.col-sm-2 .col-sm-2
.col-sm-10 .col-sm-10
- if github_import_enabled? - if github_import_enabled?
= link_to status_github_import_path do = link_to status_import_github_path do
%i.fa.fa-github %i.fa.fa-github
Import projects from GitHub Import projects from GitHub
- else - else
...@@ -53,6 +53,19 @@ ...@@ -53,6 +53,19 @@
Import projects from GitHub Import projects from GitHub
= render 'github_import_modal' = render 'github_import_modal'
.project-import.form-group
.col-sm-2
.col-sm-10
- if gitlab_import_enabled?
= link_to status_import_gitlab_path do
%i.fa.fa-heart
Import projects from GitLab.com
- else
= link_to '#', class: 'how_to_import_link light' do
%i.fa.fa-heart
Import projects from GitLab.com
= render 'gitlab_import_modal'
%hr.prepend-botton-10 %hr.prepend-botton-10
.form-group .form-group
...@@ -79,3 +92,11 @@ ...@@ -79,3 +92,11 @@
%i.fa.fa-spinner.fa-spin %i.fa.fa-spinner.fa-spin
Creating project &amp; repository. Creating project &amp; repository.
%p Please wait a moment, this page will automatically refresh when ready. %p Please wait a moment, this page will automatically refresh when ready.
:coffeescript
$ ->
$('.how_to_import_link').bind 'click', (e) ->
e.preventDefault()
import_modal = $(this).parent().find(".modal").show()
$('.modal-header .close').bind 'click', ->
$(".modal").hide()
\ No newline at end of file
...@@ -10,10 +10,12 @@ class RepositoryImportWorker ...@@ -10,10 +10,12 @@ class RepositoryImportWorker
project.path_with_namespace, project.path_with_namespace,
project.import_url) project.import_url)
if project.import_type == 'github' result_of_data_import = if project.import_type == 'github'
result_of_data_import = Gitlab::Github::Importer.new(project).execute Gitlab::GithubImport::Importer.new(project).execute
elsif project.import_type == 'gitlab'
Gitlab::GitlabImport::Importer.new(project).execute
else else
result_of_data_import = true true
end end
if result && result_of_data_import if result && result_of_data_import
......
...@@ -27,7 +27,7 @@ Doorkeeper.configure do ...@@ -27,7 +27,7 @@ Doorkeeper.configure do
# Access token expiration time (default 2 hours). # Access token expiration time (default 2 hours).
# If you want to disable expiration, set this to nil. # If you want to disable expiration, set this to nil.
# access_token_expires_in 2.hours access_token_expires_in nil
# Reuse access token for the same resource owner within an application (disabled by default) # Reuse access token for the same resource owner within an application (disabled by default)
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383 # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
......
...@@ -52,15 +52,26 @@ Gitlab::Application.routes.draw do ...@@ -52,15 +52,26 @@ Gitlab::Application.routes.draw do
end end
get '/s/:username' => 'snippets#user_index', as: :user_snippets, constraints: { username: /.*/ } get '/s/:username' => 'snippets#user_index', as: :user_snippets, constraints: { username: /.*/ }
# #
# Github importer area # Import
# #
resource :github_import, only: [:create, :new] do namespace :import do
resource :github, only: [:create, :new], controller: :github do
get :status get :status
get :callback get :callback
get :jobs get :jobs
end end
resource :gitlab, only: [:create, :new], controller: :gitlab do
get :status
get :callback
get :jobs
end
end
# #
# Explore area # Explore area
# #
......
# GitLab OAuth2 OmniAuth Provider
To enable the GitLab OmniAuth provider you must register your application with GitLab. GitLab will generate a client ID and secret key for you to use.
1. Sign in to GitLab.
1. Navigate to your settings.
1. Select "Applications" in the left menu.
1. Select "New application".
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.
- Redirect URI:
```
http://gitlab.example.com/import/gitlab/callback
http://gitlab.example.com/users/auth/gitlab/callback
```
The first link is required for the importer and second for the authorization.
1. Select "Submit".
1. You should now see a Application ID and Secret. Keep this page open as you continue configuration.
1. On your GitLab server, open the configuration file.
```sh
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
1. Find the section dealing with OmniAuth. See [Initial OmniAuth Configuration](README.md#initial-omniauth-configuration) for more details.
1. Under `providers:` uncomment (or add) lines that look like the following:
```
- { 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 SECRET' to the secret from the GitLab application page.
1. Save the configuration file.
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a GitLab icon below the regular sign in form. Click the icon to begin the authentication process. GitLab 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.
...@@ -68,14 +68,17 @@ git diff origin/7-3-stable:config/gitlab.yml.example origin/7-4-stable:config/gi ...@@ -68,14 +68,17 @@ git diff origin/7-3-stable:config/gitlab.yml.example origin/7-4-stable:config/gi
sudo -u git -H editor config/unicorn.rb sudo -u git -H editor config/unicorn.rb
``` ```
#### Change nginx https settings #### Change Nginx HTTPS settings
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your setting * HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your setting
#### MySQL Databases: Update database.yml config file #### MySQL Databases: Update database.yml config file
* Add `collation: utf8_general_ci` to config/database.yml as seen in [config/database.yml.mysql](config/database.yml.mysql) * Add `collation: utf8_general_ci` to `config/database.yml` as seen in [config/database.yml.mysql](/config/database.yml.mysql)
```
sudo -u git -H editor config/database.yml
```
### 5. Start application ### 5. Start application
......
module Gitlab module Gitlab
module Github module GithubImport
class Client class Client
attr_reader :client attr_reader :client, :api
def initialize def initialize(access_token)
@client = ::OAuth2::Client.new( @client = ::OAuth2::Client.new(
config.app_id, config.app_id,
config.app_secret, config.app_secret,
github_options github_options
) )
if access_token
::Octokit.auto_paginate = true
@api = ::Octokit::Client.new(access_token: access_token)
end
end
def authorize_url(redirect_uri)
client.auth_code.authorize_url({
redirect_uri: redirect_uri,
scope: "repo, user, user:email"
})
end
def get_token(code)
client.auth_code.get_token(code).token
end
def method_missing(method, *args, &block)
if api.respond_to?(method)
api.send(method, *args, &block)
else
super(method, *args, &block)
end
end
def respond_to?(method)
api.respond_to?(method) || super
end end
private private
def config def config
Gitlab.config.omniauth.providers.select{|provider| provider.name == "github"}.first Gitlab.config.omniauth.providers.find{|provider| provider.name == "github"}
end end
def github_options def github_options
......
module Gitlab module Gitlab
module Github module GithubImport
class Importer class Importer
attr_reader :project attr_reader :project, :client
def initialize(project) def initialize(project)
@project = project @project = project
@client = Client.new(project.creator.github_access_token)
@formatter = Gitlab::ImportFormatter.new
end end
def execute def execute
client = octo_client(project.creator.github_access_token)
#Issues && Comments #Issues && Comments
client.list_issues(project.import_source, state: :all).each do |issue| client.list_issues(project.import_source, state: :all).each do |issue|
if issue.pull_request.nil? if issue.pull_request.nil?
body = "*Created by: #{issue.user.login}*\n\n#{issue.body}"
body = @formatter.author_line(issue.user.login, issue.body)
if issue.comments > 0 if issue.comments > 0
body += "\n\n\n**Imported comments:**\n" body += @formatter.comments_header
client.issue_comments(project.import_source, issue.number).each do |c| client.issue_comments(project.import_source, issue.number).each do |c|
body += "\n\n*By #{c.user.login} on #{c.created_at}*\n\n#{c.body}" body += @formatter.comment_to_md(c.user.login, c.created_at, c.body)
end end
end end
...@@ -34,13 +36,9 @@ module Gitlab ...@@ -34,13 +36,9 @@ module Gitlab
private private
def octo_client(access_token)
::Octokit.auto_paginate = true
::Octokit::Client.new(access_token: access_token)
end
def gl_user_id(project, github_id) def gl_user_id(project, github_id)
user = User.joins(:identities).find_by("identities.extern_uid = ?", github_id.to_s) user = User.joins(:identities).
find_by("identities.extern_uid = ? AND identities.provider = 'github'", github_id.to_s)
(user && user.id) || project.creator_id (user && user.id) || project.creator_id
end end
end end
......
module Gitlab module Gitlab
module Github module GithubImport
class ProjectCreator class ProjectCreator
attr_reader :repo, :namespace, :current_user attr_reader :repo, :namespace, :current_user
......
module Gitlab
module GitlabImport
class Client
attr_reader :client, :api
PER_PAGE = 100
def initialize(access_token)
@client = ::OAuth2::Client.new(
config.app_id,
config.app_secret,
github_options
)
if access_token
@api = OAuth2::AccessToken.from_hash(@client, access_token: access_token)
end
end
def authorize_url(redirect_uri)
client.auth_code.authorize_url({
redirect_uri: redirect_uri,
scope: "api"
})
end
def get_token(code, redirect_uri)
client.auth_code.get_token(code, redirect_uri: redirect_uri).token
end
def issues(project_identifier)
lazy_page_iterator(PER_PAGE) do |page|
api.get("/api/v3/projects/#{project_identifier}/issues?per_page=#{PER_PAGE}&page=#{page}").parsed
end
end
def issue_comments(project_identifier, issue_id)
lazy_page_iterator(PER_PAGE) do |page|
api.get("/api/v3/projects/#{project_identifier}/issues/#{issue_id}/notes?per_page=#{PER_PAGE}&page=#{page}").parsed
end
end
def project(id)
api.get("/api/v3/projects/#{id}").parsed
end
def projects
lazy_page_iterator(PER_PAGE) do |page|
api.get("/api/v3/projects?per_page=#{PER_PAGE}&page=#{page}").parsed
end
end
private
def lazy_page_iterator(per_page)
Enumerator.new do |y|
page = 1
loop do
items = yield(page)
items.each do |item|
y << item
end
break if items.empty? || items.size < per_page
page += 1
end
end
end
def config
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'
}
end
end
end
end
module Gitlab
module GitlabImport
class Importer
attr_reader :project, :client
def initialize(project)
@project = project
@client = Client.new(project.creator.gitlab_access_token)
@formatter = Gitlab::ImportFormatter.new
end
def execute
project_identifier = URI.encode(project.import_source, '/')
#Issues && Comments
issues = client.issues(project_identifier)
issues.each do |issue|
body = @formatter.author_line(issue["author"]["name"], issue["description"])
comments = client.issue_comments(project_identifier, issue["id"])
if comments.any?
body += @formatter.comments_header
end
comments.each do |comment|
body += @formatter.comment_to_md(comment["author"]["name"], comment["created_at"], comment["body"])
end
project.issues.create!(
description: body,
title: issue["title"],
state: issue["state"],
author_id: gl_user_id(project, issue["author"]["id"])
)
end
true
end
private
def gl_user_id(project, gitlab_id)
user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'gitlab'", gitlab_id.to_s)
(user && user.id) || project.creator_id
end
end
end
end
module Gitlab
module GitlabImport
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["path"],
description: repo["description"],
namespace: namespace,
creator: current_user,
visibility_level: repo["visibility_level"],
import_type: "gitlab",
import_source: repo["path_with_namespace"],
import_url: repo["http_url_to_repo"].sub("://", "://oauth2:#{current_user.gitlab_access_token}@")
)
if @project.save!
@project.reload
if @project.import_failed?
@project.import_retry
else
@project.import_start
end
end
@project
end
end
end
end
module Gitlab
class ImportFormatter
def comment_to_md(author, date, body)
"\n\n*By #{author} on #{date}*\n\n#{body}"
end
def comments_header
"\n\n\n**Imported comments:**\n"
end
def author_line(author, body)
"*Created by: #{author}*\n\n#{body}"
end
end
end
require 'spec_helper' require 'spec_helper'
describe GithubImportsController do describe Import::GithubController do
let(:user) { create(:user, github_access_token: 'asd123') } let(:user) { create(:user, github_access_token: 'asd123') }
before do before do
...@@ -10,13 +10,13 @@ describe GithubImportsController do ...@@ -10,13 +10,13 @@ describe GithubImportsController do
describe "GET callback" do describe "GET callback" do
it "updates access token" do it "updates access token" do
token = "asdasd12345" token = "asdasd12345"
Gitlab::Github::Client.any_instance.stub_chain(:client, :auth_code, :get_token, :token).and_return(token) Gitlab::GithubImport::Client.any_instance.stub(:get_token).and_return(token)
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "github") Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "github")
get :callback get :callback
user.reload.github_access_token.should == token user.reload.github_access_token.should == token
controller.should redirect_to(status_github_import_url) controller.should redirect_to(status_import_github_url)
end end
end end
...@@ -27,8 +27,8 @@ describe GithubImportsController do ...@@ -27,8 +27,8 @@ describe GithubImportsController do
it "assigns variables" do it "assigns variables" do
@project = create(:project, import_type: 'github', creator_id: user.id) @project = create(:project, import_type: 'github', creator_id: user.id)
controller.stub_chain(:octo_client, :repos).and_return([@repo]) controller.stub_chain(:client, :repos).and_return([@repo])
controller.stub_chain(:octo_client, :orgs).and_return([]) controller.stub_chain(:client, :orgs).and_return([])
get :status get :status
...@@ -38,8 +38,8 @@ describe GithubImportsController do ...@@ -38,8 +38,8 @@ describe GithubImportsController do
it "does not show already added project" do it "does not show already added project" do
@project = create(:project, import_type: 'github', creator_id: user.id, import_source: 'asd/vim') @project = create(:project, import_type: 'github', creator_id: user.id, import_source: 'asd/vim')
controller.stub_chain(:octo_client, :repos).and_return([@repo]) controller.stub_chain(:client, :repos).and_return([@repo])
controller.stub_chain(:octo_client, :orgs).and_return([]) controller.stub_chain(:client, :orgs).and_return([])
get :status get :status
...@@ -55,9 +55,9 @@ describe GithubImportsController do ...@@ -55,9 +55,9 @@ describe GithubImportsController do
it "takes already existing namespace" do it "takes already existing namespace" do
namespace = create(:namespace, name: "john", owner: user) namespace = create(:namespace, name: "john", owner: user)
Gitlab::Github::ProjectCreator.should_receive(:new).with(@repo, namespace, user). Gitlab::GithubImport::ProjectCreator.should_receive(:new).with(@repo, namespace, user).
and_return(double(execute: true)) and_return(double(execute: true))
controller.stub_chain(:octo_client, :repo).and_return(@repo) controller.stub_chain(:client, :repo).and_return(@repo)
post :create, format: :js post :create, format: :js
end end
......
require 'spec_helper'
describe Import::GitlabController do
let(:user) { create(:user, gitlab_access_token: 'asd123') }
before do
sign_in(user)
end
describe "GET callback" do
it "updates access token" do
token = "asdasd12345"
Gitlab::GitlabImport::Client.any_instance.stub_chain(:client, :auth_code, :get_token, :token).and_return(token)
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "gitlab")
get :callback
user.reload.gitlab_access_token.should == token
controller.should redirect_to(status_import_gitlab_url)
end
end
describe "GET status" do
before do
@repo = OpenStruct.new(path: 'vim', path_with_namespace: 'asd/vim')
end
it "assigns variables" do
@project = create(:project, import_type: 'gitlab', 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: 'gitlab', 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 = {
path: 'vim',
path_with_namespace: 'asd/vim',
owner: {name: "john"},
namespace: {path: "john"}
}.with_indifferent_access
end
it "takes already existing namespace" do
namespace = create(:namespace, name: "john", owner: user)
Gitlab::GitlabImport::ProjectCreator.should_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
require 'spec_helper' require 'spec_helper'
describe 'Users', feature: true do describe 'Users', feature: true do
describe "GET /users/sign_up" do describe "GET /users/sign_in" do
before do
ApplicationSetting.any_instance.stub(signup_enabled?: true)
end
it "should create a new user account" do it "should create a new user account" do
visit new_user_registration_path visit new_user_session_path
fill_in "user_name", with: "Name Surname" fill_in "user_name", with: "Name Surname"
fill_in "user_username", with: "Great" fill_in "user_username", with: "Great"
fill_in "user_email", with: "name@mail.com" fill_in "user_email", with: "name@mail.com"
fill_in "user_password", with: "password1234" fill_in "user_password_sign_up", with: "password1234"
fill_in "user_password_confirmation", with: "password1234" expect { click_button "Sign up" }.to change { User.count }.by(1)
expect { click_button "Sign up" }.to change {User.count}.by(1)
end end
end end
end end
require 'spec_helper'
describe Gitlab::GitlabImport::ProjectCreator do
let(:user) { create(:user, gitlab_access_token: "asdffg") }
let(:repo) {{
name: 'vim',
path: 'vim',
visibility_level: Gitlab::VisibilityLevel::PRIVATE,
path_with_namespace: 'asd/vim',
http_url_to_repo: "https://gitlab.com/asd/vim.git",
owner: {name: "john"}}.with_indifferent_access
}
let(:namespace){ create(:namespace) }
it 'creates project' do
Project.any_instance.stub(:add_import_job)
project_creator = Gitlab::GitlabImport::ProjectCreator.new(repo, namespace, user)
project_creator.execute
project = Project.last
project.import_url.should == "https://oauth2:asdffg@gitlab.com/asd/vim.git"
project.visibility_level.should == Gitlab::VisibilityLevel::PRIVATE
end
end
...@@ -184,29 +184,13 @@ describe API::API, api: true do ...@@ -184,29 +184,13 @@ describe API::API, api: true do
end end
describe "GET /users/sign_up" do describe "GET /users/sign_up" do
context 'enabled' do
before do
ApplicationSetting.any_instance.stub(signup_enabled?: true)
end
it "should return sign up page if signup is enabled" do it "should redirect to sign in page" do
get "/users/sign_up"
response.status.should == 200
end
end
context 'disabled' do
before do
ApplicationSetting.any_instance.stub(signup_enabled?: false)
end
it "should redirect to sign in page if signup is disabled" do
get "/users/sign_up" get "/users/sign_up"
response.status.should == 302 response.status.should == 302
response.should redirect_to(new_user_session_path) response.should redirect_to(new_user_session_path)
end end
end end
end
describe "PUT /users/:id" do describe "PUT /users/:id" do
let!(:admin_user) { create(:admin) } let!(:admin_user) { create(:admin) }
......
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