Commit b01f8b63 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

added NamespacedProject role. Extended project info displayed for admin. Fixed project limit

parent 44209861
...@@ -49,6 +49,7 @@ class GroupsController < ApplicationController ...@@ -49,6 +49,7 @@ class GroupsController < ApplicationController
def people def people
@project = group.projects.find(params[:project_id]) if params[:project_id] @project = group.projects.find(params[:project_id]) if params[:project_id]
@users = @project ? @project.users : group.users @users = @project ? @project.users : group.users
@users.sort_by!(&:name)
if @project if @project
@team_member = @project.users_projects.new @team_member = @project.users_projects.new
......
...@@ -16,7 +16,7 @@ class SnippetsController < ProjectResourceController ...@@ -16,7 +16,7 @@ class SnippetsController < ProjectResourceController
respond_to :html respond_to :html
def index def index
@snippets = @project.snippets @snippets = @project.snippets.fresh
end end
def new def new
...@@ -60,7 +60,7 @@ class SnippetsController < ProjectResourceController ...@@ -60,7 +60,7 @@ class SnippetsController < ProjectResourceController
redirect_to project_snippets_path(@project) redirect_to project_snippets_path(@project)
end end
def raw def raw
send_data( send_data(
@snippet.content, @snippet.content,
type: "text/plain", type: "text/plain",
......
...@@ -25,6 +25,7 @@ class Project < ActiveRecord::Base ...@@ -25,6 +25,7 @@ class Project < ActiveRecord::Base
include PushObserver include PushObserver
include Authority include Authority
include Team include Team
include NamespacedProject
class TransferError < StandardError; end class TransferError < StandardError; end
...@@ -178,7 +179,7 @@ class Project < ActiveRecord::Base ...@@ -178,7 +179,7 @@ class Project < ActiveRecord::Base
end end
def repo_name def repo_name
denied_paths = %w(gitolite-admin groups projects dashboard) denied_paths = %w(gitolite-admin groups projects dashboard help )
if denied_paths.include?(path) if denied_paths.include?(path)
errors.add(:path, "like #{path} is not allowed") errors.add(:path, "like #{path} is not allowed")
...@@ -245,57 +246,11 @@ class Project < ActiveRecord::Base ...@@ -245,57 +246,11 @@ class Project < ActiveRecord::Base
gitlab_ci_service && gitlab_ci_service.active gitlab_ci_service && gitlab_ci_service.active
end end
def path_with_namespace
if namespace
namespace.path + '/' + path
else
path
end
end
# For compatibility with old code # For compatibility with old code
def code def code
path path
end end
def transfer(new_namespace)
Project.transaction do
old_namespace = namespace
self.namespace = new_namespace
old_dir = old_namespace.try(:path) || ''
new_dir = new_namespace.try(:path) || ''
old_repo = if old_dir.present?
File.join(old_dir, self.path)
else
self.path
end
if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
raise TransferError.new("Project with same path in target namespace already exists")
end
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
git_host.move_repository(old_repo, self)
save!
end
rescue Gitlab::ProjectMover::ProjectMoveError => ex
raise TransferError.new(ex.message)
end
def name_with_namespace
@name_with_namespace ||= begin
if namespace
namespace.human_name + " / " + name
else
name
end
end
end
def items_for entity def items_for entity
case entity case entity
when 'issue' then when 'issue' then
...@@ -304,16 +259,4 @@ class Project < ActiveRecord::Base ...@@ -304,16 +259,4 @@ class Project < ActiveRecord::Base
merge_requests merge_requests
end end
end end
def namespace_owner
namespace.try(:owner)
end
def chief
if namespace
namespace_owner
else
owner
end
end
end end
...@@ -56,7 +56,6 @@ class User < ActiveRecord::Base ...@@ -56,7 +56,6 @@ class User < ActiveRecord::Base
has_many :issues, foreign_key: :author_id, dependent: :destroy has_many :issues, foreign_key: :author_id, dependent: :destroy
has_many :notes, foreign_key: :author_id, dependent: :destroy has_many :notes, foreign_key: :author_id, dependent: :destroy
has_many :merge_requests, foreign_key: :author_id, dependent: :destroy has_many :merge_requests, foreign_key: :author_id, dependent: :destroy
has_many :my_own_projects, class_name: "Project", foreign_key: :owner_id
has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy
has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC"
has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
...@@ -124,16 +123,4 @@ class User < ActiveRecord::Base ...@@ -124,16 +123,4 @@ class User < ActiveRecord::Base
self.password = self.password_confirmation = Devise.friendly_token.first(8) self.password = self.password_confirmation = Devise.friendly_token.first(8)
end end
end end
def authorized_groups
@authorized_groups ||= begin
groups = Group.where(id: self.projects.pluck(:namespace_id)).all
groups = groups + self.groups
groups.uniq
end
end
def authorized_projects
Project.authorized_for(self)
end
end end
...@@ -105,4 +105,20 @@ module Account ...@@ -105,4 +105,20 @@ module Account
def namespace_id def namespace_id
namespace.try :id namespace.try :id
end end
def authorized_groups
@authorized_groups ||= begin
groups = Group.where(id: self.projects.pluck(:namespace_id)).all
groups = groups + self.groups
groups.uniq
end
end
def authorized_projects
Project.authorized_for(self)
end
def my_own_projects
Project.personal(self)
end
end end
module NamespacedProject
def transfer(new_namespace)
Project.transaction do
old_namespace = namespace
self.namespace = new_namespace
old_dir = old_namespace.try(:path) || ''
new_dir = new_namespace.try(:path) || ''
old_repo = if old_dir.present?
File.join(old_dir, self.path)
else
self.path
end
if Project.where(path: self.path, namespace_id: new_namespace.try(:id)).present?
raise TransferError.new("Project with same path in target namespace already exists")
end
Gitlab::ProjectMover.new(self, old_dir, new_dir).execute
git_host.move_repository(old_repo, self)
save!
end
rescue Gitlab::ProjectMover::ProjectMoveError => ex
raise TransferError.new(ex.message)
end
def name_with_namespace
@name_with_namespace ||= begin
if namespace
namespace.human_name + " / " + name
else
name
end
end
end
def namespace_owner
namespace.try(:owner)
end
def chief
if namespace
namespace_owner
else
owner
end
end
def path_with_namespace
if namespace
namespace.path + '/' + path
else
path
end
end
end
...@@ -19,43 +19,47 @@ ...@@ -19,43 +19,47 @@
.input .input
= text_field_tag :ppath, @project.path_to_repo, class: "xlarge", disabled: true = text_field_tag :ppath, @project.path_to_repo, class: "xlarge", disabled: true
- unless project.new_record? - if project.repo_exists?
.clearfix .clearfix
= f.label :namespace_id = f.label :default_branch, "Default Branch"
.input .input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
= f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'}
&nbsp;
%span.cred Be careful. Changing project namespace can have unintended side effects
- if project.repo_exists? %fieldset.adv_settings
.clearfix %legend Features:
= f.label :default_branch, "Default Branch"
.input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
- unless project.new_record? .clearfix
%fieldset.adv_settings = f.label :issues_enabled, "Issues"
%legend Features: .input= f.check_box :issues_enabled
.clearfix .clearfix
= f.label :issues_enabled, "Issues" = f.label :merge_requests_enabled, "Merge Requests"
.input= f.check_box :issues_enabled .input= f.check_box :merge_requests_enabled
.clearfix .clearfix
= f.label :merge_requests_enabled, "Merge Requests" = f.label :wall_enabled, "Wall"
.input= f.check_box :merge_requests_enabled .input= f.check_box :wall_enabled
.clearfix .clearfix
= f.label :wall_enabled, "Wall" = f.label :wiki_enabled, "Wiki"
.input= f.check_box :wall_enabled .input= f.check_box :wiki_enabled
%fieldset.features
%legend Transfer:
.control-group
= f.label :namespace_id do
%span Namespace
.controls
= f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'}
%br
%ul.prepend-top-10.cred
%li Be careful. Changing project namespace can have unintended side effects
%li You can transfer project only to namespaces you can manage
%li You will need to update your local repositories to point to the new location.
.clearfix
= f.label :wiki_enabled, "Wiki"
.input= f.check_box :wiki_enabled
- unless project.new_record? .actions
.actions = f.submit 'Save Project', class: "btn save-btn"
= f.submit 'Save Project', class: "btn save-btn" = link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
= link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
......
%h3.page_title %h3.page_title
Projects Projects (#{@projects.count})
= link_to 'New Project', new_project_path, class: "btn small right" = link_to 'New Project', new_project_path, class: "btn small right"
%br %br
= form_tag admin_projects_path, method: :get, class: 'form-inline' do = form_tag admin_projects_path, method: :get, class: 'form-inline' do
......
...@@ -47,21 +47,61 @@ ...@@ -47,21 +47,61 @@
%tr %tr
%td %td
%b %b
Path: Owned by:
%td %td
%code= @project.path_to_repo - if @project.chief
= link_to @project.chief.name, admin_user_path(@project.chief)
- else
(deleted)
%tr %tr
%td %td
%b %b
Created by: Created by:
%td %td
= @project.owner_name || '(deleted)' = @project.owner_name || '(deleted)'
%tr
%td
%b
Created at:
%td
= @project.created_at.stamp("March 1, 1999")
%table.zebra-striped
%thead
%tr
%th Repository
%th
%tr
%td
%b
FS Path:
%td
%code= @project.path_to_repo
%tr
%td
%b
Smart HTTP:
%td
= link_to @project.http_url_to_repo
%tr
%td
%b
SSH:
%td
= link_to @project.ssh_url_to_repo
%tr
%td
%b
Last commit at:
%td
= last_commit(@project)
%tr %tr
%td %td
%b %b
Post Receive File: Post Receive File:
%td %td
= check_box_tag :post_receive_file, 1, @project.has_post_receive_file?, disabled: true = check_box_tag :post_receive_file, 1, @project.has_post_receive_file?, disabled: true
%br %br
%h5 %h5
Team Team
......
%h3.page_title %h3.page_title
Users Users (#{@admin_users.count})
= link_to 'New User', new_admin_user_path, class: "btn small right" = link_to 'New User', new_admin_user_path, class: "btn small right"
%br %br
...@@ -40,10 +40,13 @@ ...@@ -40,10 +40,13 @@
%td= user.users_projects.count %td= user.users_projects.count
%td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small" %td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
%td.bgred %td.bgred
- if user.blocked - if user == current_user
= link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success" %span.cred It's you!
- else - else
= link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger" - if user.blocked
= link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small danger" = link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
- else
= link_to 'Block', block_admin_user_path(user), confirm: 'USER WILL BE BLOCKED! Are you sure?', method: :put, class: "btn small danger"
= link_to 'Destroy', [:admin, user], confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?", method: :delete, class: "btn small danger"
= paginate @admin_users, theme: "admin" = paginate @admin_users, theme: "admin"
...@@ -37,6 +37,12 @@ ...@@ -37,6 +37,12 @@
%b %b
Blocked: Blocked:
%td= check_box_tag "blocked", 1, @admin_user.blocked, disabled: :disabled %td= check_box_tag "blocked", 1, @admin_user.blocked, disabled: :disabled
%tr
%td
%b
Created at:
%td
= @admin_user.created_at.stamp("March 1, 1999")
%tr %tr
%td %td
%b %b
......
...@@ -22,22 +22,21 @@ ...@@ -22,22 +22,21 @@
%hr %hr
-if @hooks.any? -if @hooks.any?
%h3 %h3.page_title
Hooks Hooks (#{@hooks.count})
%small (#{@hooks.count})
%br %br
%table %table
%thead %thead
%tr %tr
%th URL %th URL
%th Method
%th %th
- @hooks.each do |hook| - @hooks.each do |hook|
%tr %tr
%td %td
%span.badge.badge-info POST
= link_to project_hook_path(@project, hook) do = link_to project_hook_path(@project, hook) do
%strong= hook.url %strong= hook.url
= link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small right"
%td POST
%td %td
= link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small right" .right
= link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small grouped"
= link_to 'Remove', project_hook_path(@project, hook), confirm: 'Are you sure?', method: :delete, class: "danger btn small grouped"
...@@ -9,3 +9,4 @@ ...@@ -9,3 +9,4 @@
$('.project_new_holder').show(); $('.project_new_holder').show();
$("#new_project").replaceWith("#{escape_javascript(render('new_form'))}"); $("#new_project").replaceWith("#{escape_javascript(render('new_form'))}");
$('.save-project-loader').hide(); $('.save-project-loader').hide();
new Projects();
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
= time_ago_in_words(note.created_at) = time_ago_in_words(note.created_at)
ago ago
- else - else
.alert-message.block-message %p.slead All files attached to project wall, issues etc will be displayed here
%span All files attached to project wall, issues etc will be displayed here
%tr %tr
%td %td
= image_tag gravatar_icon(snippet.author_email), class: "avatar s24"
%a{href: project_snippet_path(snippet.project, snippet)} %a{href: project_snippet_path(snippet.project, snippet)}
%strong= truncate(snippet.title, length: 60) %strong= truncate(snippet.title, length: 60)
%td %td
= snippet.file_name = snippet.file_name
%td %td
%span.cgray %span.cgray
- if snippet.expires_at - if snippet.expires_at
= snippet.expires_at.to_date.to_s(:short) = snippet.expires_at.to_date.to_s(:short)
- else - else
Never Never
= render "projects/project_head" = render "projects/project_head"
- if can? current_user, :write_snippet, @project %h3.page_title
.alert-message.block-message Snippets
%small share code pastes with others out of git repository
- if can? current_user, :write_snippet, @project
= link_to new_project_snippet_path(@project), class: "btn small add_new right", title: "New Snippet" do = link_to new_project_snippet_path(@project), class: "btn small add_new right", title: "New Snippet" do
Add new snippet Add new snippet
Share code pastes with others if it can't be in a git repository %br
%br
To add new snippet - click on button.
%table %table
%thead %thead
%tr %tr
%th Title %th Title
%th File Name %th File Name
%th Expires At %th Expires At
= render @snippets.fresh = render @snippets
- if @snippets.fresh.empty? - if @snippets.empty?
%tr %tr
%td{colspan: 3} %td{colspan: 3}
%h3.nothing_here_message Nothing here. %h3.nothing_here_message Nothing here.
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
= Project.access_options.key(access).pluralize = Project.access_options.key(access).pluralize
%small= members.size %small= members.size
%ul.unstyled %ul.unstyled
- members.each do |up| - members.sort_by(&:user_name).each do |up|
= render(partial: 'team_members/show', locals: {member: up}) = render(partial: 'team_members/show', locals: {member: up})
......
...@@ -41,7 +41,6 @@ describe User do ...@@ -41,7 +41,6 @@ describe User do
it { should have_many(:users_projects).dependent(:destroy) } it { should have_many(:users_projects).dependent(:destroy) }
it { should have_many(:projects) } it { should have_many(:projects) }
it { should have_many(:groups) } it { should have_many(:groups) }
it { should have_many(:my_own_projects).class_name('Project') }
it { should have_many(:keys).dependent(:destroy) } it { should have_many(:keys).dependent(:destroy) }
it { should have_many(:events).class_name('Event').dependent(:destroy) } it { should have_many(:events).class_name('Event').dependent(:destroy) }
it { should have_many(:recent_events).class_name('Event') } it { should have_many(:recent_events).class_name('Event') }
...@@ -116,4 +115,16 @@ describe User do ...@@ -116,4 +115,16 @@ describe User do
user.authentication_token.should_not be_blank user.authentication_token.should_not be_blank
end end
end end
describe 'projects and namespaces' do
before do
ActiveRecord::Base.observers.enable(:user_observer)
@user = create :user
@project = create :project, namespace: @user.namespace
end
it { @user.authorized_projects.should include(@project) }
it { @user.my_own_projects.should include(@project) }
it { @user.several_namespaces?.should be_false }
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