added NamespacedProject role. Extended project info displayed for admin. Fixed project limit
This commit is contained in:
parent
44209861e8
commit
b01f8b63c2
18 changed files with 201 additions and 131 deletions
|
@ -49,6 +49,7 @@ class GroupsController < ApplicationController
|
|||
def people
|
||||
@project = group.projects.find(params[:project_id]) if params[:project_id]
|
||||
@users = @project ? @project.users : group.users
|
||||
@users.sort_by!(&:name)
|
||||
|
||||
if @project
|
||||
@team_member = @project.users_projects.new
|
||||
|
|
|
@ -16,7 +16,7 @@ class SnippetsController < ProjectResourceController
|
|||
respond_to :html
|
||||
|
||||
def index
|
||||
@snippets = @project.snippets
|
||||
@snippets = @project.snippets.fresh
|
||||
end
|
||||
|
||||
def new
|
||||
|
@ -60,7 +60,7 @@ class SnippetsController < ProjectResourceController
|
|||
redirect_to project_snippets_path(@project)
|
||||
end
|
||||
|
||||
def raw
|
||||
def raw
|
||||
send_data(
|
||||
@snippet.content,
|
||||
type: "text/plain",
|
||||
|
|
|
@ -25,6 +25,7 @@ class Project < ActiveRecord::Base
|
|||
include PushObserver
|
||||
include Authority
|
||||
include Team
|
||||
include NamespacedProject
|
||||
|
||||
class TransferError < StandardError; end
|
||||
|
||||
|
@ -178,7 +179,7 @@ class Project < ActiveRecord::Base
|
|||
end
|
||||
|
||||
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)
|
||||
errors.add(:path, "like #{path} is not allowed")
|
||||
|
@ -245,57 +246,11 @@ class Project < ActiveRecord::Base
|
|||
gitlab_ci_service && gitlab_ci_service.active
|
||||
end
|
||||
|
||||
def path_with_namespace
|
||||
if namespace
|
||||
namespace.path + '/' + path
|
||||
else
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
# For compatibility with old code
|
||||
def code
|
||||
path
|
||||
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
|
||||
case entity
|
||||
when 'issue' then
|
||||
|
@ -304,16 +259,4 @@ class Project < ActiveRecord::Base
|
|||
merge_requests
|
||||
end
|
||||
end
|
||||
|
||||
def namespace_owner
|
||||
namespace.try(:owner)
|
||||
end
|
||||
|
||||
def chief
|
||||
if namespace
|
||||
namespace_owner
|
||||
else
|
||||
owner
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,7 +56,6 @@ class User < ActiveRecord::Base
|
|||
has_many :issues, 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 :my_own_projects, class_name: "Project", foreign_key: :owner_id
|
||||
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 :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy
|
||||
|
@ -124,16 +123,4 @@ class User < ActiveRecord::Base
|
|||
self.password = self.password_confirmation = Devise.friendly_token.first(8)
|
||||
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
|
||||
|
|
|
@ -105,4 +105,20 @@ module Account
|
|||
def namespace_id
|
||||
namespace.try :id
|
||||
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
|
||||
|
|
59
app/roles/namespaced_project.rb
Normal file
59
app/roles/namespaced_project.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
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 @@
|
|||
.input
|
||||
= text_field_tag :ppath, @project.path_to_repo, class: "xlarge", disabled: true
|
||||
|
||||
- unless project.new_record?
|
||||
- if project.repo_exists?
|
||||
.clearfix
|
||||
= f.label :namespace_id
|
||||
.input
|
||||
= f.select :namespace_id, namespaces_options(@project.namespace_id, :all), {}, {class: 'chosen'}
|
||||
|
||||
%span.cred Be careful. Changing project namespace can have unintended side effects
|
||||
= f.label :default_branch, "Default Branch"
|
||||
.input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
|
||||
|
||||
- if project.repo_exists?
|
||||
.clearfix
|
||||
= f.label :default_branch, "Default Branch"
|
||||
.input= f.select(:default_branch, project.heads.map(&:name), {}, style: "width:210px;")
|
||||
%fieldset.adv_settings
|
||||
%legend Features:
|
||||
|
||||
- unless project.new_record?
|
||||
%fieldset.adv_settings
|
||||
%legend Features:
|
||||
.clearfix
|
||||
= f.label :issues_enabled, "Issues"
|
||||
.input= f.check_box :issues_enabled
|
||||
|
||||
.clearfix
|
||||
= f.label :issues_enabled, "Issues"
|
||||
.input= f.check_box :issues_enabled
|
||||
.clearfix
|
||||
= f.label :merge_requests_enabled, "Merge Requests"
|
||||
.input= f.check_box :merge_requests_enabled
|
||||
|
||||
.clearfix
|
||||
= f.label :merge_requests_enabled, "Merge Requests"
|
||||
.input= f.check_box :merge_requests_enabled
|
||||
.clearfix
|
||||
= f.label :wall_enabled, "Wall"
|
||||
.input= f.check_box :wall_enabled
|
||||
|
||||
.clearfix
|
||||
= f.label :wall_enabled, "Wall"
|
||||
.input= f.check_box :wall_enabled
|
||||
.clearfix
|
||||
= f.label :wiki_enabled, "Wiki"
|
||||
.input= f.check_box :wiki_enabled
|
||||
|
||||
.clearfix
|
||||
= f.label :wiki_enabled, "Wiki"
|
||||
.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.
|
||||
|
||||
- unless project.new_record?
|
||||
.actions
|
||||
= f.submit 'Save Project', class: "btn save-btn"
|
||||
= link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
|
||||
|
||||
.actions
|
||||
= f.submit 'Save Project', class: "btn save-btn"
|
||||
= link_to 'Cancel', admin_projects_path, class: "btn cancel-btn"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%h3.page_title
|
||||
Projects
|
||||
Projects (#{@projects.count})
|
||||
= link_to 'New Project', new_project_path, class: "btn small right"
|
||||
%br
|
||||
= form_tag admin_projects_path, method: :get, class: 'form-inline' do
|
||||
|
|
|
@ -47,21 +47,61 @@
|
|||
%tr
|
||||
%td
|
||||
%b
|
||||
Path:
|
||||
Owned by:
|
||||
%td
|
||||
%code= @project.path_to_repo
|
||||
- if @project.chief
|
||||
= link_to @project.chief.name, admin_user_path(@project.chief)
|
||||
- else
|
||||
(deleted)
|
||||
%tr
|
||||
%td
|
||||
%b
|
||||
Created by:
|
||||
%td
|
||||
= @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
|
||||
%td
|
||||
%b
|
||||
Post Receive File:
|
||||
%td
|
||||
= check_box_tag :post_receive_file, 1, @project.has_post_receive_file?, disabled: true
|
||||
|
||||
%br
|
||||
%h5
|
||||
Team
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
%h3.page_title
|
||||
Users
|
||||
Users (#{@admin_users.count})
|
||||
= link_to 'New User', new_admin_user_path, class: "btn small right"
|
||||
%br
|
||||
|
||||
|
@ -40,10 +40,13 @@
|
|||
%td= user.users_projects.count
|
||||
%td= link_to 'Edit', edit_admin_user_path(user), id: "edit_#{dom_id(user)}", class: "btn small"
|
||||
%td.bgred
|
||||
- if user.blocked
|
||||
= link_to 'Unblock', unblock_admin_user_path(user), method: :put, class: "btn small success"
|
||||
- if user == current_user
|
||||
%span.cred It's you!
|
||||
- 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"
|
||||
- if user.blocked
|
||||
= 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"
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
%b
|
||||
Blocked:
|
||||
%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
|
||||
%td
|
||||
%b
|
||||
|
|
|
@ -22,22 +22,21 @@
|
|||
%hr
|
||||
|
||||
-if @hooks.any?
|
||||
%h3
|
||||
Hooks
|
||||
%small (#{@hooks.count})
|
||||
%h3.page_title
|
||||
Hooks (#{@hooks.count})
|
||||
%br
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th URL
|
||||
%th Method
|
||||
%th
|
||||
- @hooks.each do |hook|
|
||||
%tr
|
||||
%td
|
||||
%span.badge.badge-info POST
|
||||
= link_to project_hook_path(@project, hook) do
|
||||
%strong= hook.url
|
||||
= link_to 'Test Hook', test_project_hook_path(@project, hook), class: "btn small right"
|
||||
%td POST
|
||||
%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 @@
|
|||
$('.project_new_holder').show();
|
||||
$("#new_project").replaceWith("#{escape_javascript(render('new_form'))}");
|
||||
$('.save-project-loader').hide();
|
||||
new Projects();
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
= time_ago_in_words(note.created_at)
|
||||
ago
|
||||
- else
|
||||
.alert-message.block-message
|
||||
%span All files attached to project wall, issues etc will be displayed here
|
||||
%p.slead All files attached to project wall, issues etc will be displayed here
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
%tr
|
||||
%td
|
||||
= image_tag gravatar_icon(snippet.author_email), class: "avatar s24"
|
||||
%a{href: project_snippet_path(snippet.project, snippet)}
|
||||
%strong= truncate(snippet.title, length: 60)
|
||||
%td
|
||||
= snippet.file_name
|
||||
%td
|
||||
%span.cgray
|
||||
- if snippet.expires_at
|
||||
- if snippet.expires_at
|
||||
= snippet.expires_at.to_date.to_s(:short)
|
||||
- else
|
||||
Never
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
= render "projects/project_head"
|
||||
|
||||
- if can? current_user, :write_snippet, @project
|
||||
.alert-message.block-message
|
||||
%h3.page_title
|
||||
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
|
||||
Add new snippet
|
||||
Share code pastes with others if it can't be in a git repository
|
||||
%br
|
||||
To add new snippet - click on button.
|
||||
|
||||
%br
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Title
|
||||
%th File Name
|
||||
%th Expires At
|
||||
= render @snippets.fresh
|
||||
- if @snippets.fresh.empty?
|
||||
= render @snippets
|
||||
- if @snippets.empty?
|
||||
%tr
|
||||
%td{colspan: 3}
|
||||
%h3.nothing_here_message Nothing here.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
= Project.access_options.key(access).pluralize
|
||||
%small= members.size
|
||||
%ul.unstyled
|
||||
- members.each do |up|
|
||||
- members.sort_by(&:user_name).each do |up|
|
||||
= render(partial: 'team_members/show', locals: {member: up})
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ describe User do
|
|||
it { should have_many(:users_projects).dependent(:destroy) }
|
||||
it { should have_many(:projects) }
|
||||
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(:events).class_name('Event').dependent(:destroy) }
|
||||
it { should have_many(:recent_events).class_name('Event') }
|
||||
|
@ -116,4 +115,16 @@ describe User do
|
|||
user.authentication_token.should_not be_blank
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue