Commit 875728b1 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'feature/admin_project_transfer' of /home/git/repositories/gitlab/gitlabhq

parents 77e3fab8 27ad8826
...@@ -17,6 +17,7 @@ v 6.3.0 ...@@ -17,6 +17,7 @@ v 6.3.0
- Fix 500 error for repos with newline in file name - Fix 500 error for repos with newline in file name
- Extended html titles - Extended html titles
- API: create/update repo files - API: create/update repo files
- Admin can transfer project to any namespace
v 6.2.0 v 6.2.0
- Public project pages are now visible to everyone (files, issues, wik, etc.) - Public project pages are now visible to everyone (files, issues, wik, etc.)
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
users_path: "/api/:version/users.json" users_path: "/api/:version/users.json"
user_path: "/api/:version/users/:id.json" user_path: "/api/:version/users/:id.json"
notes_path: "/api/:version/projects/:id/notes.json" notes_path: "/api/:version/projects/:id/notes.json"
namespaces_path: "/api/:version/namespaces.json"
# Get 20 (depends on api) recent notes # Get 20 (depends on api) recent notes
# and sort the ascending from oldest to newest # and sort the ascending from oldest to newest
...@@ -49,6 +50,20 @@ ...@@ -49,6 +50,20 @@
).done (users) -> ).done (users) ->
callback(users) callback(users)
# Return namespaces list. Filtered by query
namespaces: (query, callback) ->
url = Api.buildUrl(Api.namespaces_path)
$.ajax(
url: url
data:
private_token: gon.api_token
search: query
per_page: 20
dataType: "json"
).done (namespaces) ->
callback(namespaces)
buildUrl: (url) -> buildUrl: (url) ->
url = gon.relative_url_root + url if gon.relative_url_root? url = gon.relative_url_root + url if gon.relative_url_root?
return url.replace(':version', gon.api_version) return url.replace(':version', gon.api_version)
$ ->
namespaceFormatResult = (namespace) ->
markup = "<div class='namespace-result'>"
markup += "<span class='namespace-kind'>" + namespace.kind + "</span>"
markup += "<span class='namespace-path'>" + namespace.path + "</span>"
markup += "</div>"
markup
formatSelection = (namespace) ->
namespace.kind + ": " + namespace.path
$('.ajax-namespace-select').each (i, select) ->
$(select).select2
placeholder: "Search for namespace"
multiple: $(select).hasClass('multiselect')
minimumInputLength: 0
query: (query) ->
Api.namespaces query.term, (namespaces) ->
data = { results: namespaces }
query.callback(data)
dropdownCssClass: "ajax-namespace-dropdown"
formatResult: namespaceFormatResult
formatSelection: formatSelection
...@@ -358,3 +358,33 @@ table { ...@@ -358,3 +358,33 @@ table {
background: #555; background: #555;
color: #BBB; color: #BBB;
} }
.ajax-users-select {
width: 400px;
&.input-large {
width: 210px;
}
}
.user-result {
.user-image {
float: left;
}
.user-name {
}
.user-username {
color: #999;
}
}
.namespace-result {
.namespace-kind {
color: #AAA;
font-weight: normal;
}
.namespace-path {
margin-left: 10px;
font-weight: bolder;
}
}
.ajax-users-select {
width: 400px;
&.input-large {
width: 210px;
}
}
.user-result {
.user-image {
float: left;
}
.user-name {
}
.user-username {
color: #999;
}
}
/** Chosen.js selectbox style override **/ /** Chosen.js selectbox style override **/
.chosen-container { .chosen-container {
min-width: 100px; min-width: 100px;
......
class Admin::ProjectsController < Admin::ApplicationController class Admin::ProjectsController < Admin::ApplicationController
before_filter :project, only: [:edit, :show, :update, :destroy, :team_update] before_filter :project, only: [:show, :transfer]
before_filter :group, only: [:show, :transfer]
before_filter :repository, only: [:show, :transfer]
def index def index
owner_id = params[:owner_id] owner_id = params[:owner_id]
...@@ -14,8 +16,16 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -14,8 +16,16 @@ class Admin::ProjectsController < Admin::ApplicationController
end end
def show def show
@repository = @project.repository end
@group = @project.group
def transfer
result = ::Projects::TransferContext.new(@project, current_user, project: params).execute(:admin)
if result
redirect_to [:admin, @project]
else
render :show
end
end end
protected protected
...@@ -26,4 +36,12 @@ class Admin::ProjectsController < Admin::ApplicationController ...@@ -26,4 +36,12 @@ class Admin::ProjectsController < Admin::ApplicationController
@project = Project.find_with_namespace(id) @project = Project.find_with_namespace(id)
@project || render_404 @project || render_404
end end
def group
@group ||= project.group
end
def repository
@repository ||= project.repository
end
end end
...@@ -16,4 +16,13 @@ module NamespacesHelper ...@@ -16,4 +16,13 @@ module NamespacesHelper
grouped_options_for_select(options, selected) grouped_options_for_select(options, selected)
end end
def namespace_select_tag(id, opts = {})
css_class = "ajax-namespace-select "
css_class << "multiselect " if opts[:multiple]
css_class << (opts[:class] || '')
value = opts[:selected] || ''
hidden_field_tag(id, value, class: css_class)
end
end end
...@@ -87,4 +87,8 @@ class Namespace < ActiveRecord::Base ...@@ -87,4 +87,8 @@ class Namespace < ActiveRecord::Base
def send_update_instructions def send_update_instructions
projects.each(&:send_move_instructions) projects.each(&:send_move_instructions)
end end
def kind
type == 'Group' ? 'group' : 'user'
end
end end
...@@ -74,6 +74,23 @@ ...@@ -74,6 +74,23 @@
%span.cgreen %span.cgreen
%i.icon-lock %i.icon-lock
Private Private
.ui-box
.title
Transfer project
.ui-box-body
= form_for @project, url: transfer_admin_project_path(@project), method: :put do |f|
.control-group
= f.label :namespace_id, "Namespace"
.controls
= namespace_select_tag :namespace_id, selected: params[:namespace_id], class: 'input-large'
.control-group
.controls
= f.submit 'Transfer', class: 'btn btn-primary'
.span6 .span6
- if @group - if @group
.ui-box .ui-box
......
...@@ -89,7 +89,13 @@ Gitlab::Application.routes.draw do ...@@ -89,7 +89,13 @@ Gitlab::Application.routes.draw do
resources :broadcast_messages, only: [:index, :create, :destroy] resources :broadcast_messages, only: [:index, :create, :destroy]
resource :logs, only: [:show] resource :logs, only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show] resource :background_jobs, controller: 'background_jobs', only: [:show]
resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show]
resources :projects, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ }, only: [:index, :show] do
member do
put :transfer
end
end
root to: "dashboard#index" root to: "dashboard#index"
end end
......
...@@ -40,5 +40,6 @@ module API ...@@ -40,5 +40,6 @@ module API
mount ProjectHooks mount ProjectHooks
mount Services mount Services
mount Files mount Files
mount Namespaces
end end
end end
...@@ -136,5 +136,9 @@ module API ...@@ -136,5 +136,9 @@ module API
expose :target_id, :target_type, :author_id expose :target_id, :target_type, :author_id
expose :data, :target_title expose :data, :target_title
end end
class Namespace < Grape::Entity
expose :id, :path, :kind
end
end end
end end
module API
# namespaces API
class Namespaces < Grape::API
before {
authenticate!
authenticated_as_admin!
}
resource :namespaces do
# Get a namespaces list
#
# Example Request:
# GET /namespaces
get do
@namespaces = Namespace.scoped
@namespaces = @namespaces.search(params[:search]) if params[:search].present?
@namespaces = paginate @namespaces
present @namespaces, with: Entities::Namespace
end
end
end
end
require 'spec_helper'
describe API::API do
include ApiHelpers
before(:each) { ActiveRecord::Base.observers.enable(:user_observer) }
after(:each) { ActiveRecord::Base.observers.disable(:user_observer) }
let(:admin) { create(:admin) }
let!(:group1) { create(:group) }
let!(:group2) { create(:group) }
describe "GET /namespaces" do
context "when unauthenticated" do
it "should return authentication error" do
get api("/namespaces")
response.status.should == 401
end
end
context "when authenticated as admin" do
it "admin: should return an array of all namespaces" do
get api("/namespaces", admin)
response.status.should == 200
json_response.should be_an Array
# Admin namespace + 2 group namespaces
json_response.length.should == 3
end
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