Commit 232d61d59808e6f0c731d135d728800c4b13ae27

Authored by GitLab
1 parent c7c1a97c

Refactor project creation. Added logout link to profile page

app/assets/stylesheets/sections/projects.scss
@@ -42,9 +42,6 @@ @@ -42,9 +42,6 @@
42 line-height: 20px; 42 line-height: 20px;
43 padding: 8px; 43 padding: 8px;
44 } 44 }
45 - label {  
46 - color: #888;  
47 - }  
48 .btn { 45 .btn {
49 padding: 6px 10px; 46 padding: 6px 10px;
50 margin-left: 10px; 47 margin-left: 10px;
app/contexts/project_update_context.rb
@@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
1 -class ProjectUpdateContext < BaseContext  
2 - def execute(role = :default)  
3 - namespace_id = params[:project].delete(:namespace_id)  
4 - params[:project].delete(:public) unless can?(current_user, :change_public_mode, project)  
5 -  
6 - allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin  
7 -  
8 - if allowed_transfer && namespace_id.present?  
9 - if namespace_id == Namespace.global_id  
10 - if project.namespace.present?  
11 - # Transfer to global namespace from anyone  
12 - project.transfer(nil)  
13 - end  
14 - elsif namespace_id.to_i != project.namespace_id  
15 - # Transfer to someone namespace  
16 - namespace = Namespace.find(namespace_id)  
17 - project.transfer(namespace)  
18 - end  
19 - end  
20 -  
21 - project.update_attributes(params[:project], as: role)  
22 - end  
23 -end  
24 -  
app/contexts/projects/create_context.rb 0 → 100644
@@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
  1 +module Projects
  2 + class CreateContext < BaseContext
  3 + def execute
  4 + # get namespace id
  5 + namespace_id = params[:project].delete(:namespace_id)
  6 +
  7 + @project = Project.new(params[:project])
  8 +
  9 + # Parametrize path for project
  10 + #
  11 + # Ex.
  12 + # 'GitLab HQ'.parameterize => "gitlab-hq"
  13 + #
  14 + @project.path = @project.name.dup.parameterize
  15 +
  16 +
  17 + if namespace_id
  18 + # Find matching namespace and check if it allowed
  19 + # for current user if namespace_id passed.
  20 + if allowed_namespace?(current_user, namespace_id)
  21 + @project.namespace_id = namespace_id unless namespace_id == Namespace.global_id
  22 + else
  23 + deny_namespace
  24 + return @project
  25 + end
  26 + else
  27 + # Set current user namespace if namespace_id is nil
  28 + @project.namespace_id = current_user.id
  29 + end
  30 +
  31 + Project.transaction do
  32 + @project.creator = current_user
  33 + @project.save!
  34 +
  35 + # Add user as project master
  36 + @project.users_projects.create!(project_access: UsersProject::MASTER, user: current_user)
  37 +
  38 + # when project saved no team member exist so
  39 + # project repository should be updated after first user add
  40 + @project.update_repository
  41 + end
  42 +
  43 + @project
  44 + rescue => ex
  45 + @project.errors.add(:base, "Can't save project. Please try again later")
  46 + @project
  47 + end
  48 +
  49 + protected
  50 +
  51 + def deny_namespace
  52 + @project.errors.add(:namespace, "is not valid")
  53 + end
  54 +
  55 + def allowed_namespace?(user, namespace_id)
  56 + if namespace_id == Namespace.global_id
  57 + return user.admin
  58 + else
  59 + namespace = Namespace.find_by_id(namespace_id)
  60 + current_user.can?(:manage_namespace, namespace)
  61 + end
  62 + end
  63 + end
  64 +end
app/contexts/projects/update_context.rb 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +module Projects
  2 + class UpdateContext < BaseContext
  3 + def execute(role = :default)
  4 + namespace_id = params[:project].delete(:namespace_id)
  5 + params[:project].delete(:public) unless can?(current_user, :change_public_mode, project)
  6 +
  7 + allowed_transfer = can?(current_user, :change_namespace, project) || role == :admin
  8 +
  9 + if allowed_transfer && namespace_id.present?
  10 + if namespace_id == Namespace.global_id
  11 + if project.namespace.present?
  12 + # Transfer to global namespace from anyone
  13 + project.transfer(nil)
  14 + end
  15 + elsif namespace_id.to_i != project.namespace_id
  16 + # Transfer to someone namespace
  17 + namespace = Namespace.find(namespace_id)
  18 + project.transfer(namespace)
  19 + end
  20 + end
  21 +
  22 + project.update_attributes(params[:project], as: role)
  23 + end
  24 + end
  25 +end
app/controllers/admin/projects_controller.rb
@@ -29,7 +29,7 @@ class Admin::ProjectsController &lt; AdminController @@ -29,7 +29,7 @@ class Admin::ProjectsController &lt; AdminController
29 end 29 end
30 30
31 def update 31 def update
32 - status = ProjectUpdateContext.new(project, current_user, params).execute(:admin) 32 + status = Projects::UpdateContext.new(project, current_user, params).execute(:admin)
33 33
34 if status 34 if status
35 redirect_to [:admin, @project], notice: 'Project was successfully updated.' 35 redirect_to [:admin, @project], notice: 'Project was successfully updated.'
app/controllers/projects_controller.rb
@@ -19,7 +19,7 @@ class ProjectsController &lt; ProjectResourceController @@ -19,7 +19,7 @@ class ProjectsController &lt; ProjectResourceController
19 end 19 end
20 20
21 def create 21 def create
22 - @project = Project.create_by_user(params[:project], current_user) 22 + @project = Projects::CreateContext.new(nil, current_user, params).execute
23 23
24 respond_to do |format| 24 respond_to do |format|
25 flash[:notice] = 'Project was successfully created.' if @project.saved? 25 flash[:notice] = 'Project was successfully created.' if @project.saved?
@@ -35,7 +35,7 @@ class ProjectsController &lt; ProjectResourceController @@ -35,7 +35,7 @@ class ProjectsController &lt; ProjectResourceController
35 end 35 end
36 36
37 def update 37 def update
38 - status = ProjectUpdateContext.new(project, current_user, params).execute 38 + status = Projects::UpdateContext.new(project, current_user, params).execute
39 39
40 respond_to do |format| 40 respond_to do |format|
41 if status 41 if status
app/helpers/namespaces_helper.rb
1 module NamespacesHelper 1 module NamespacesHelper
2 def namespaces_options(selected = :current_user, scope = :default) 2 def namespaces_options(selected = :current_user, scope = :default)
3 - groups = current_user.owned_groups.select {|n| n.type == 'Group'} 3 + if current_user.admin
  4 + groups = Group.all
  5 + users = Namespace.root
  6 + else
  7 + groups = current_user.owned_groups.select {|n| n.type == 'Group'}
  8 + users = current_user.namespaces.reject {|n| n.type == 'Group'}
  9 + end
4 10
5 - users = if scope == :all  
6 - Namespace.root  
7 - else  
8 - current_user.namespaces.reject {|n| n.type == 'Group'}  
9 - end  
10 11
11 global_opts = ["Global", [['/', Namespace.global_id]] ] 12 global_opts = ["Global", [['/', Namespace.global_id]] ]
12 group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ] 13 group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
app/models/ability.rb
@@ -7,7 +7,7 @@ class Ability @@ -7,7 +7,7 @@ class Ability
7 when "Note" then note_abilities(object, subject) 7 when "Note" then note_abilities(object, subject)
8 when "Snippet" then snippet_abilities(object, subject) 8 when "Snippet" then snippet_abilities(object, subject)
9 when "MergeRequest" then merge_request_abilities(object, subject) 9 when "MergeRequest" then merge_request_abilities(object, subject)
10 - when "Group" then group_abilities(object, subject) 10 + when "Group", "Namespace" then group_abilities(object, subject)
11 else [] 11 else []
12 end 12 end
13 end 13 end
@@ -102,7 +102,8 @@ class Ability @@ -102,7 +102,8 @@ class Ability
102 # Only group owner and administrators can manage group 102 # Only group owner and administrators can manage group
103 if group.owner == user || user.admin? 103 if group.owner == user || user.admin?
104 rules << [ 104 rules << [
105 - :manage_group 105 + :manage_group,
  106 + :manage_namespace
106 ] 107 ]
107 end 108 end
108 109
app/models/project.rb
@@ -116,55 +116,6 @@ class Project &lt; ActiveRecord::Base @@ -116,55 +116,6 @@ class Project &lt; ActiveRecord::Base
116 end 116 end
117 end 117 end
118 118
119 - def create_by_user(params, user)  
120 - namespace_id = params.delete(:namespace_id)  
121 -  
122 - project = Project.new params  
123 -  
124 - Project.transaction do  
125 -  
126 - # Parametrize path for project  
127 - #  
128 - # Ex.  
129 - # 'GitLab HQ'.parameterize => "gitlab-hq"  
130 - #  
131 - project.path = project.name.dup.parameterize  
132 -  
133 - project.creator = user  
134 -  
135 - # Apply namespace if user has access to it  
136 - # else fallback to user namespace  
137 - if namespace_id != Namespace.global_id  
138 - project.namespace_id = user.namespace_id  
139 -  
140 - if namespace_id  
141 - group = Group.find_by_id(namespace_id)  
142 - if user.can? :manage_group, group  
143 - project.namespace_id = namespace_id  
144 - end  
145 - end  
146 - end  
147 -  
148 - project.save!  
149 -  
150 - # Add user as project master  
151 - project.users_projects.create!(project_access: UsersProject::MASTER, user: user)  
152 -  
153 - # when project saved no team member exist so  
154 - # project repository should be updated after first user add  
155 - project.update_repository  
156 - end  
157 -  
158 - project  
159 - rescue Gitlab::Gitolite::AccessDenied => ex  
160 - project.error_code = :gitolite  
161 - project  
162 - rescue => ex  
163 - project.error_code = :db  
164 - project.errors.add(:base, "Can't save project. Please try again later")  
165 - project  
166 - end  
167 -  
168 def access_options 119 def access_options
169 UsersProject.access_roles 120 UsersProject.access_roles
170 end 121 end
app/models/user.rb
@@ -152,11 +152,8 @@ class User &lt; ActiveRecord::Base @@ -152,11 +152,8 @@ class User &lt; ActiveRecord::Base
152 namespaces << self.namespace if self.namespace 152 namespaces << self.namespace if self.namespace
153 153
154 # Add groups you can manage 154 # Add groups you can manage
155 - namespaces += if admin  
156 - Group.all  
157 - else  
158 - groups.all  
159 - end 155 + namespaces += groups.all
  156 +
160 namespaces 157 namespaces
161 end 158 end
162 159
@@ -234,6 +231,10 @@ class User &lt; ActiveRecord::Base @@ -234,6 +231,10 @@ class User &lt; ActiveRecord::Base
234 end 231 end
235 end 232 end
236 233
  234 + def can_select_namespace?
  235 + several_namespaces? || admin
  236 + end
  237 +
237 def can? action, subject 238 def can? action, subject
238 abilities.allowed?(self, action, subject) 239 abilities.allowed?(self, action, subject)
239 end 240 end
app/views/dashboard/_sidebar.html.haml
@@ -9,6 +9,6 @@ @@ -9,6 +9,6 @@
9 9
10 %hr 10 %hr
11 .gitlab-promo 11 .gitlab-promo
12 - = link_to "Homepage", "http://gitlabhq.com"  
13 - = link_to "Blog", "http://blog.gitlabhq.com" 12 + = link_to "Homepage", "http://gitlab.org"
  13 + = link_to "Blog", "http://blog.gitlab.org"
14 = link_to "@gitlabhq", "https://twitter.com/gitlabhq" 14 = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
app/views/profiles/show.html.haml
@@ -6,6 +6,11 @@ @@ -6,6 +6,11 @@
6 %small 6 %small
7 = @user.email 7 = @user.email
8 8
  9 + .right
  10 + = link_to destroy_user_session_path, class: "logout", method: :delete do
  11 + %small
  12 + %i.icon-signout
  13 + Logout
9 %hr 14 %hr
10 15
11 = form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f| 16 = form_for @user, url: profile_path, method: :put, html: { class: "edit_user form-horizontal" } do |f|
app/views/projects/_form.html.haml
@@ -9,19 +9,11 @@ @@ -9,19 +9,11 @@
9 Project name is 9 Project name is
10 .input 10 .input
11 = f.text_field :name, placeholder: "Example Project", class: "xxlarge" 11 = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
12 - %fieldset  
13 - %legend Advanced settings:  
14 - .control-group  
15 - = f.label :path do  
16 - Repository  
17 - .controls  
18 - = text_field_tag :ppath, @repository.path_to_repo, class: "xxlarge", readonly: true  
19 - 12 + - unless @repository.heads.empty?
  13 + .clearfix
  14 + = f.label :default_branch, "Default Branch"
  15 + .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;")
20 16
21 - - unless @repository.heads.empty?  
22 - .clearfix  
23 - = f.label :default_branch, "Default Branch"  
24 - .input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;")  
25 17
26 %fieldset.features 18 %fieldset.features
27 %legend Features: 19 %legend Features:
@@ -87,4 +79,4 @@ @@ -87,4 +79,4 @@
87 - unless @project.new_record? 79 - unless @project.new_record?
88 - if can?(current_user, :remove_project, @project) 80 - if can?(current_user, :remove_project, @project)
89 .right 81 .right
90 - = link_to 'Remove', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger" 82 + = link_to 'Remove Project', @project, confirm: 'Removed project can not be restored! Are you sure?', method: :delete, class: "btn danger"
app/views/projects/_new_form.html.haml
@@ -9,10 +9,10 @@ @@ -9,10 +9,10 @@
9 = f.text_field :name, placeholder: "Example Project", class: "xxlarge" 9 = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
10 = f.submit 'Create project', class: "btn success project-submit" 10 = f.submit 'Create project', class: "btn success project-submit"
11 11
12 - - if current_user.several_namespaces? 12 + - if current_user.can_select_namespace?
13 .clearfix 13 .clearfix
14 = f.label :namespace_id do 14 = f.label :namespace_id do
15 - %span.cgray Namespace 15 + %span Namespace
16 .input 16 .input
17 = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'} 17 = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
18 %hr 18 %hr
app/views/projects/create.js.haml
@@ -2,11 +2,9 @@ @@ -2,11 +2,9 @@
2 :plain 2 :plain
3 location.href = "#{project_path(@project)}"; 3 location.href = "#{project_path(@project)}";
4 - else 4 - else
5 - - if @project.git_error?  
6 - location.href = "#{errors_githost_path}";  
7 - -else  
8 :plain 5 :plain
9 $('.project_new_holder').show(); 6 $('.project_new_holder').show();
10 $("#new_project").replaceWith("#{escape_javascript(render('new_form'))}"); 7 $("#new_project").replaceWith("#{escape_javascript(render('new_form'))}");
11 $('.save-project-loader').hide(); 8 $('.save-project-loader').hide();
12 new Projects(); 9 new Projects();
  10 + $('select.chosen').chosen()
features/project/project.feature
1 -Feature: Projects 1 +Feature: Project Feature
2 Background: 2 Background:
3 Given I sign in as a user 3 Given I sign in as a user
4 And I own project "Shop" 4 And I own project "Shop"
features/steps/project/project.rb
1 -class Projects < Spinach::FeatureSteps 1 +class ProjectFeature < Spinach::FeatureSteps
2 include SharedAuthentication 2 include SharedAuthentication
3 include SharedProject 3 include SharedProject
4 include SharedPaths 4 include SharedPaths
features/steps/shared/project.rb
@@ -47,7 +47,6 @@ module SharedProject @@ -47,7 +47,6 @@ module SharedProject
47 Then 'I should see project settings' do 47 Then 'I should see project settings' do
48 current_path.should == edit_project_path(@project) 48 current_path.should == edit_project_path(@project)
49 page.should have_content("Project name is") 49 page.should have_content("Project name is")
50 - page.should have_content("Advanced settings:")  
51 page.should have_content("Features:") 50 page.should have_content("Features:")
52 end 51 end
53 52
lib/api/projects.rb
@@ -43,7 +43,7 @@ module Gitlab @@ -43,7 +43,7 @@ module Gitlab
43 :wall_enabled, 43 :wall_enabled,
44 :merge_requests_enabled, 44 :merge_requests_enabled,
45 :wiki_enabled] 45 :wiki_enabled]
46 - @project = Project.create_by_user(attrs, current_user) 46 + @project = Projects::CreateContext.new(nil, attrs, current_user).execute
47 if @project.saved? 47 if @project.saved?
48 present @project, with: Entities::Project 48 present @project, with: Entities::Project
49 else 49 else