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 42 line-height: 20px;
43 43 padding: 8px;
44 44 }
45   - label {
46   - color: #888;
47   - }
48 45 .btn {
49 46 padding: 6px 10px;
50 47 margin-left: 10px;
... ...
app/contexts/project_update_context.rb
... ... @@ -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 @@
  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 @@
  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 29 end
30 30  
31 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 34 if status
35 35 redirect_to [:admin, @project], notice: 'Project was successfully updated.'
... ...
app/controllers/projects_controller.rb
... ... @@ -19,7 +19,7 @@ class ProjectsController &lt; ProjectResourceController
19 19 end
20 20  
21 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 24 respond_to do |format|
25 25 flash[:notice] = 'Project was successfully created.' if @project.saved?
... ... @@ -35,7 +35,7 @@ class ProjectsController &lt; ProjectResourceController
35 35 end
36 36  
37 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 40 respond_to do |format|
41 41 if status
... ...
app/helpers/namespaces_helper.rb
1 1 module NamespacesHelper
2 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 12 global_opts = ["Global", [['/', Namespace.global_id]] ]
12 13 group_opts = ["Groups", groups.map {|g| [g.human_name, g.id]} ]
... ...
app/models/ability.rb
... ... @@ -7,7 +7,7 @@ class Ability
7 7 when "Note" then note_abilities(object, subject)
8 8 when "Snippet" then snippet_abilities(object, subject)
9 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 11 else []
12 12 end
13 13 end
... ... @@ -102,7 +102,8 @@ class Ability
102 102 # Only group owner and administrators can manage group
103 103 if group.owner == user || user.admin?
104 104 rules << [
105   - :manage_group
  105 + :manage_group,
  106 + :manage_namespace
106 107 ]
107 108 end
108 109  
... ...
app/models/project.rb
... ... @@ -116,55 +116,6 @@ class Project &lt; ActiveRecord::Base
116 116 end
117 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 119 def access_options
169 120 UsersProject.access_roles
170 121 end
... ...
app/models/user.rb
... ... @@ -152,11 +152,8 @@ class User &lt; ActiveRecord::Base
152 152 namespaces << self.namespace if self.namespace
153 153  
154 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 157 namespaces
161 158 end
162 159  
... ... @@ -234,6 +231,10 @@ class User &lt; ActiveRecord::Base
234 231 end
235 232 end
236 233  
  234 + def can_select_namespace?
  235 + several_namespaces? || admin
  236 + end
  237 +
237 238 def can? action, subject
238 239 abilities.allowed?(self, action, subject)
239 240 end
... ...
app/views/dashboard/_sidebar.html.haml
... ... @@ -9,6 +9,6 @@
9 9  
10 10 %hr
11 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 14 = link_to "@gitlabhq", "https://twitter.com/gitlabhq"
... ...
app/views/profiles/show.html.haml
... ... @@ -6,6 +6,11 @@
6 6 %small
7 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 14 %hr
10 15  
11 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 9 Project name is
10 10 .input
11 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 18 %fieldset.features
27 19 %legend Features:
... ... @@ -87,4 +79,4 @@
87 79 - unless @project.new_record?
88 80 - if can?(current_user, :remove_project, @project)
89 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 9 = f.text_field :name, placeholder: "Example Project", class: "xxlarge"
10 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 13 .clearfix
14 14 = f.label :namespace_id do
15   - %span.cgray Namespace
  15 + %span Namespace
16 16 .input
17 17 = f.select :namespace_id, namespaces_options(params[:namespace_id] || :current_user), {}, {class: 'chosen'}
18 18 %hr
... ...
app/views/projects/create.js.haml
... ... @@ -2,11 +2,9 @@
2 2 :plain
3 3 location.href = "#{project_path(@project)}";
4 4 - else
5   - - if @project.git_error?
6   - location.href = "#{errors_githost_path}";
7   - -else
8 5 :plain
9 6 $('.project_new_holder').show();
10 7 $("#new_project").replaceWith("#{escape_javascript(render('new_form'))}");
11 8 $('.save-project-loader').hide();
12 9 new Projects();
  10 + $('select.chosen').chosen()
... ...
features/project/project.feature
1   -Feature: Projects
  1 +Feature: Project Feature
2 2 Background:
3 3 Given I sign in as a user
4 4 And I own project "Shop"
... ...
features/steps/project/project.rb
1   -class Projects < Spinach::FeatureSteps
  1 +class ProjectFeature < Spinach::FeatureSteps
2 2 include SharedAuthentication
3 3 include SharedProject
4 4 include SharedPaths
... ...
features/steps/shared/project.rb
... ... @@ -47,7 +47,6 @@ module SharedProject
47 47 Then 'I should see project settings' do
48 48 current_path.should == edit_project_path(@project)
49 49 page.should have_content("Project name is")
50   - page.should have_content("Advanced settings:")
51 50 page.should have_content("Features:")
52 51 end
53 52  
... ...
lib/api/projects.rb
... ... @@ -43,7 +43,7 @@ module Gitlab
43 43 :wall_enabled,
44 44 :merge_requests_enabled,
45 45 :wiki_enabled]
46   - @project = Project.create_by_user(attrs, current_user)
  46 + @project = Projects::CreateContext.new(nil, attrs, current_user).execute
47 47 if @project.saved?
48 48 present @project, with: Entities::Project
49 49 else
... ...