diff --git a/app/assets/stylesheets/sections/projects.scss b/app/assets/stylesheets/sections/projects.scss index 072ade80ad3130fe649e0cc466739b83d8315ab8..4bdc56d2884a62dd66d86b39f3d5550d1ea6373d 100644 --- a/app/assets/stylesheets/sections/projects.scss +++ b/app/assets/stylesheets/sections/projects.scss @@ -42,9 +42,6 @@ line-height: 20px; padding: 8px; } - label { - color: #888; - } .btn { padding: 6px 10px; margin-left: 10px; diff --git a/app/contexts/project_update_context.rb b/app/contexts/project_update_context.rb deleted file mode 100644 index f6d69e7b62db147cabc74c80f4445b58d18aafeb..0000000000000000000000000000000000000000 --- a/app/contexts/project_update_context.rb +++ /dev/null @@ -1,24 +0,0 @@ -class ProjectUpdateContext < BaseContext - def execute(role = :default) - namespace_id = params[:project].delete(:namespace_id) - params[:project].delete(:public) unless can?(current_user, :change_public_mode, project) - - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin - - if allowed_transfer && namespace_id.present? - if namespace_id == Namespace.global_id - if project.namespace.present? - # Transfer to global namespace from anyone - project.transfer(nil) - end - elsif namespace_id.to_i != project.namespace_id - # Transfer to someone namespace - namespace = Namespace.find(namespace_id) - project.transfer(namespace) - end - end - - project.update_attributes(params[:project], as: role) - end -end - diff --git a/app/contexts/projects/create_context.rb b/app/contexts/projects/create_context.rb new file mode 100644 index 0000000000000000000000000000000000000000..5329443c5f71119cbc192cb4f223b7489414296f --- /dev/null +++ b/app/contexts/projects/create_context.rb @@ -0,0 +1,64 @@ +module Projects + class CreateContext < BaseContext + def execute + # get namespace id + namespace_id = params[:project].delete(:namespace_id) + + @project = Project.new(params[:project]) + + # Parametrize path for project + # + # Ex. + # 'GitLab HQ'.parameterize => "gitlab-hq" + # + @project.path = @project.name.dup.parameterize + + + if namespace_id + # Find matching namespace and check if it allowed + # for current user if namespace_id passed. + if allowed_namespace?(current_user, namespace_id) + @project.namespace_id = namespace_id unless namespace_id == Namespace.global_id + else + deny_namespace + return @project + end + else + # Set current user namespace if namespace_id is nil + @project.namespace_id = current_user.id + end + + Project.transaction do + @project.creator = current_user + @project.save! + + # Add user as project master + @project.users_projects.create!(project_access: UsersProject::MASTER, user: current_user) + + # when project saved no team member exist so + # project repository should be updated after first user add + @project.update_repository + end + + @project + rescue => ex + @project.errors.add(:base, "Can't save project. Please try again later") + @project + end + + protected + + def deny_namespace + @project.errors.add(:namespace, "is not valid") + end + + def allowed_namespace?(user, namespace_id) + if namespace_id == Namespace.global_id + return user.admin + else + namespace = Namespace.find_by_id(namespace_id) + current_user.can?(:manage_namespace, namespace) + end + end + end +end diff --git a/app/contexts/projects/update_context.rb b/app/contexts/projects/update_context.rb new file mode 100644 index 0000000000000000000000000000000000000000..e5d09b7df7f047b7c183bd5354659f321486047b --- /dev/null +++ b/app/contexts/projects/update_context.rb @@ -0,0 +1,25 @@ +module Projects + class UpdateContext < BaseContext + def execute(role = :default) + namespace_id = params[:project].delete(:namespace_id) + params[:project].delete(:public) unless can?(current_user, :change_public_mode, project) + + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin + + if allowed_transfer && namespace_id.present? + if namespace_id == Namespace.global_id + if project.namespace.present? + # Transfer to global namespace from anyone + project.transfer(nil) + end + elsif namespace_id.to_i != project.namespace_id + # Transfer to someone namespace + namespace = Namespace.find(namespace_id) + project.transfer(namespace) + end + end + + project.update_attributes(params[:project], as: role) + end + end +end diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index fc78db9e3a7d21d23721ce01d4e2b5f62c0889e4..fc2793a72e7b5959fd1f1910b840b53d06240f27 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -29,7 +29,7 @@ class Admin::ProjectsController < AdminController end def update - status = ProjectUpdateContext.new(project, current_user, params).execute(:admin) + status = Projects::UpdateContext.new(project, current_user, params).execute(:admin) if status redirect_to [:admin, @project], notice: 'Project was successfully updated.' diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 6f1180eaa6b0bb431cf12c629e185ce878861e45..46096f280b895949a34eee412b7233a76e203899 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -19,7 +19,7 @@ class ProjectsController < ProjectResourceController end def create - @project = Project.create_by_user(params[:project], current_user) + @project = Projects::CreateContext.new(nil, current_user, params).execute respond_to do |format| flash[:notice] = 'Project was successfully created.' if @project.saved? @@ -35,7 +35,7 @@ class ProjectsController < ProjectResourceController end def update - status = ProjectUpdateContext.new(project, current_user, params).execute + status = Projects::UpdateContext.new(project, current_user, params).execute respond_to do |format| if status diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb index 2d25c8f854d7c0975b577cd46518d33691bae8c2..6d0c6c981917dce72d8f5dc8f36efbd09f650e8b 100644 --- a/app/helpers/namespaces_helper.rb +++ b/app/helpers/namespaces_helper.rb @@ -1,12 +1,13 @@ module NamespacesHelper def namespaces_options(selected = :current_user, scope = :default) - groups = current_user.owned_groups.select {|n| n.type == 'Group'} + if current_user.admin + groups = Group.all + users = Namespace.root + else + groups = current_user.owned_groups.select {|n| n.type == 'Group'} + users = current_user.namespaces.reject {|n| n.type == 'Group'} + end - users = if scope == :all - Namespace.root - else - current_user.namespaces.reject {|n| n.type == 'Group'} - end global_opts = ["Global", [['/', Namespace.global_id]] ] group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ] diff --git a/app/models/ability.rb b/app/models/ability.rb index 362877f0b223ab8338ae0e9df92a5597b80faf32..c0da9396baa3feb55a3241101ba331594b4f90c7 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -7,7 +7,7 @@ class Ability when "Note" then note_abilities(object, subject) when "Snippet" then snippet_abilities(object, subject) when "MergeRequest" then merge_request_abilities(object, subject) - when "Group" then group_abilities(object, subject) + when "Group", "Namespace" then group_abilities(object, subject) else [] end end @@ -102,7 +102,8 @@ class Ability # Only group owner and administrators can manage group if group.owner == user || user.admin? rules << [ - :manage_group + :manage_group, + :manage_namespace ] end diff --git a/app/models/project.rb b/app/models/project.rb index 62f89e2cd1becbcc7f2aac6aead662e348fc3937..fa38093b7d5364e44cdc2d530fed762a4642d749 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -116,55 +116,6 @@ class Project < ActiveRecord::Base end end - def create_by_user(params, user) - namespace_id = params.delete(:namespace_id) - - project = Project.new params - - Project.transaction do - - # Parametrize path for project - # - # Ex. - # 'GitLab HQ'.parameterize => "gitlab-hq" - # - project.path = project.name.dup.parameterize - - project.creator = user - - # Apply namespace if user has access to it - # else fallback to user namespace - if namespace_id != Namespace.global_id - project.namespace_id = user.namespace_id - - if namespace_id - group = Group.find_by_id(namespace_id) - if user.can? :manage_group, group - project.namespace_id = namespace_id - end - end - end - - project.save! - - # Add user as project master - project.users_projects.create!(project_access: UsersProject::MASTER, user: user) - - # when project saved no team member exist so - # project repository should be updated after first user add - project.update_repository - end - - project - rescue Gitlab::Gitolite::AccessDenied => ex - project.error_code = :gitolite - project - rescue => ex - project.error_code = :db - project.errors.add(:base, "Can't save project. Please try again later") - project - end - def access_options UsersProject.access_roles end diff --git a/app/models/user.rb b/app/models/user.rb index 7e69f3db84c6ce508874481704e517c44e4f3a0b..7a75379e5008662fd666bda146af875caa470dc7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -152,11 +152,8 @@ class User < ActiveRecord::Base namespaces << self.namespace if self.namespace # Add groups you can manage - namespaces += if admin - Group.all - else - groups.all - end + namespaces += groups.all + namespaces end @@ -234,6 +231,10 @@ class User < ActiveRecord::Base end end + def can_select_namespace? + several_namespaces? || admin + end + def can? action, subject abilities.allowed?(self, action, subject) end diff --git a/app/views/dashboard/_sidebar.html.haml b/app/views/dashboard/_sidebar.html.haml index ca57cd30732b0ef5b42fe1ebcd1aeac182ff0839..9830cdf4f6b85ee1d1d46116edd240a7945c02e3 100644 --- a/app/views/dashboard/_sidebar.html.haml +++ b/app/views/dashboard/_sidebar.html.haml @@ -9,6 +9,6 @@ %hr .gitlab-promo - = link_to "Homepage", "http://gitlabhq.com" - = link_to "Blog", "http://blog.gitlabhq.com" + = link_to "Homepage", "http://gitlab.org" + = link_to "Blog", "http://blog.gitlab.org" = link_to "@gitlabhq", "https://twitter.com/gitlabhq" diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 64f931ca887a6b0f5854bad97a9d6f3dcbf1ee7e..687463b672cb731c8136803abb4198f72c044bdc 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -6,6 +6,11 @@ %small = @user.email + .right + = link_to destroy_user_session_path, class: "logout", method: :delete do + %small + %i.icon-signout + Logout %hr = form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f| diff --git a/app/views/projects/_form.html.haml b/app/views/projects/_form.html.haml index 8bf96f399f8bbe7df96e4df1d315ba80a8da10c5..aa76048302a21c4fb68cf9aeb37d53989ee65af3 100644 --- a/app/views/projects/_form.html.haml +++ b/app/views/projects/_form.html.haml @@ -9,19 +9,11 @@ Project name is .input = f.text_field :name, placeholder: "Example Project", class: "xxlarge" - %fieldset - %legend Advanced settings: - .control-group - = f.label :path do - Repository - .controls - = text_field_tag :ppath, @repository.path_to_repo, class: "xxlarge", readonly: true - + - unless @repository.heads.empty? + .clearfix + = f.label :default_branch, "Default Branch" + .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;") - - unless @repository.heads.empty? - .clearfix - = f.label :default_branch, "Default Branch" - .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;") %fieldset.features %legend Features: @@ -87,4 +79,4 @@ - unless @project.new_record? - if can?(current_user, :remove_project, @project) .right - = link_to 'Remove', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger" + = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger" diff --git a/app/views/projects/_new_form.html.haml b/app/views/projects/_new_form.html.haml index 2391c750bc85371f3bd505ca89ba06c92af3ac4d..131a4de42184218ede8675bc1a764c3b5288ae40 100644 --- a/app/views/projects/_new_form.html.haml +++ b/app/views/projects/_new_form.html.haml @@ -9,10 +9,10 @@ = f.text_field :name, placeholder: "Example Project", class: "xxlarge" = f.submit 'Create project', class: "btn success project-submit" - - if current_user.several_namespaces? + - if current_user.can_select_namespace? .clearfix = f.label :namespace_id do - %span.cgray Namespace + %span Namespace .input = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'} %hr diff --git a/app/views/projects/create.js.haml b/app/views/projects/create.js.haml index d388988676d216e386be6a59e5647ba351b2f409..296c8688f479ad104538f295081e39d6b7111cb8 100644 --- a/app/views/projects/create.js.haml +++ b/app/views/projects/create.js.haml @@ -2,11 +2,9 @@ :plain location.href = "#{project_path(@project)}"; - else - - if @project.git_error? - location.href = "#{errors_githost_path}"; - -else :plain $('.project_new_holder').show(); $("#new_project").replaceWith("#{escape_javascript(render('new_form'))}"); $('.save-project-loader').hide(); new Projects(); + $('select.chosen').chosen() diff --git a/features/project/project.feature b/features/project/project.feature index ad3d06bb41f9b9df88c374593bd4385bdce4a43c..23fef69ee488215dfd6ca1ab1cb8c7eb8bcbdf7b 100644 --- a/features/project/project.feature +++ b/features/project/project.feature @@ -1,4 +1,4 @@ -Feature: Projects +Feature: Project Feature Background: Given I sign in as a user And I own project "Shop" diff --git a/features/steps/project/project.rb b/features/steps/project/project.rb index 7a85f57a218cdd465a03ea72c5c1d84e53e36e94..e9ef1495dd1f7bfae63aa9555813101b24a1bd22 100644 --- a/features/steps/project/project.rb +++ b/features/steps/project/project.rb @@ -1,4 +1,4 @@ -class Projects < Spinach::FeatureSteps +class ProjectFeature < Spinach::FeatureSteps include SharedAuthentication include SharedProject include SharedPaths diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb index 3150be5ef185d6f04d2ad7fe0fc62e5f051fcdce..1623edb80d00af8ef51d92d709928bd137521263 100644 --- a/features/steps/shared/project.rb +++ b/features/steps/shared/project.rb @@ -47,7 +47,6 @@ module SharedProject Then 'I should see project settings' do current_path.should == edit_project_path(@project) page.should have_content("Project name is") - page.should have_content("Advanced settings:") page.should have_content("Features:") end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 55c81f3158acb10e899a0ba93b19edb920d4d245..c4717d111550f61a90eb58d5b743c7b8fde0b115 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -43,7 +43,7 @@ module Gitlab :wall_enabled, :merge_requests_enabled, :wiki_enabled] - @project = Project.create_by_user(attrs, current_user) + @project = Projects::CreateContext.new(nil, attrs, current_user).execute if @project.saved? present @project, with: Entities::Project else