Commit 00a1f5bc2cc2c98bda3818e770eaae95e664480a

Authored by Dmitriy Zaporozhets
1 parent 91995909

Project has now correct owner and creator. Increased test coverage

app/controllers/dashboard_controller.rb
... ... @@ -20,7 +20,7 @@ class DashboardController < ApplicationController
20 20  
21 21 @projects = @projects.page(params[:page]).per(30)
22 22  
23   - @events = Event.in_projects(current_user.project_ids)
  23 + @events = Event.in_projects(current_user.authorized_projects.pluck(:id))
24 24 @events = @event_filter.apply_filter(@events)
25 25 @events = @events.limit(20).offset(params[:offset] || 0)
26 26  
... ...
app/controllers/groups_controller.rb
... ... @@ -70,7 +70,7 @@ class GroupsController < ApplicationController
70 70 end
71 71  
72 72 def projects
73   - @projects ||= group.projects.authorized_for(current_user).sorted_by_activity
  73 + @projects ||= current_user.authorized_projects.where(namespace_id: group.id).sorted_by_activity
74 74 end
75 75  
76 76 def project_ids
... ...
app/models/project.rb
... ... @@ -32,7 +32,7 @@ class Project < ActiveRecord::Base
32 32 attr_accessible :name, :path, :description, :default_branch, :issues_enabled,
33 33 :wall_enabled, :merge_requests_enabled, :wiki_enabled, as: [:default, :admin]
34 34  
35   - attr_accessible :namespace_id, :owner_id, as: :admin
  35 + attr_accessible :namespace_id, :creator_id, as: :admin
36 36  
37 37 attr_accessor :error_code
38 38  
... ... @@ -40,10 +40,10 @@ class Project < ActiveRecord::Base
40 40 belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'"
41 41 belongs_to :namespace
42 42  
43   - # TODO: replace owner with creator.
44   - # With namespaces a project owner will be a namespace owner
45   - # so this field makes sense only for global projects
46   - belongs_to :owner, class_name: "User"
  43 + belongs_to :creator,
  44 + class_name: "User",
  45 + foreign_key: "creator_id"
  46 +
47 47 has_many :users, through: :users_projects
48 48 has_many :events, dependent: :destroy
49 49 has_many :merge_requests, dependent: :destroy
... ... @@ -62,7 +62,7 @@ class Project < ActiveRecord::Base
62 62 delegate :name, to: :owner, allow_nil: true, prefix: true
63 63  
64 64 # Validations
65   - validates :owner, presence: true
  65 + validates :creator, presence: true
66 66 validates :description, length: { within: 0..2000 }
67 67 validates :name, presence: true, length: { within: 0..255 },
68 68 format: { with: Gitlab::Regex.project_name_regex,
... ... @@ -89,8 +89,7 @@ class Project < ActiveRecord::Base
89 89  
90 90 class << self
91 91 def authorized_for user
92   - projects = includes(:users_projects, :namespace)
93   - projects = projects.where("users_projects.user_id = :user_id or projects.owner_id = :user_id or namespaces.owner_id = :user_id", user_id: user.id)
  92 + raise "DERECATED"
94 93 end
95 94  
96 95 def active
... ... @@ -104,8 +103,10 @@ class Project &lt; ActiveRecord::Base
104 103 def find_with_namespace(id)
105 104 if id.include?("/")
106 105 id = id.split("/")
107   - namespace_id = Namespace.find_by_path(id.first).id
108   - where(namespace_id: namespace_id).find_by_path(id.second)
  106 + namespace = Namespace.find_by_path(id.first)
  107 + return nil unless namespace
  108 +
  109 + where(namespace_id: namespace.id).find_by_path(id.second)
109 110 else
110 111 where(path: id, namespace_id: nil).last
111 112 end
... ... @@ -125,7 +126,7 @@ class Project &lt; ActiveRecord::Base
125 126 #
126 127 project.path = project.name.dup.parameterize
127 128  
128   - project.owner = user
  129 + project.creator = user
129 130  
130 131 # Apply namespace if user has access to it
131 132 # else fallback to user namespace
... ... @@ -174,8 +175,8 @@ class Project &lt; ActiveRecord::Base
174 175 end
175 176  
176 177 def check_limit
177   - unless owner.can_create_project?
178   - errors[:base] << ("Your own projects limit is #{owner.projects_limit}! Please contact administrator to increase it")
  178 + unless creator.can_create_project?
  179 + errors[:base] << ("Your own projects limit is #{creator.projects_limit}! Please contact administrator to increase it")
179 180 end
180 181 rescue
181 182 errors[:base] << ("Can't check your ability to create project")
... ... @@ -268,4 +269,12 @@ class Project &lt; ActiveRecord::Base
268 269 Notify.project_was_moved_email(member.id).deliver
269 270 end
270 271 end
  272 +
  273 + def owner
  274 + if namespace
  275 + namespace_owner
  276 + else
  277 + creator
  278 + end
  279 + end
271 280 end
... ...
app/models/user.rb
... ... @@ -51,7 +51,6 @@ class User &lt; ActiveRecord::Base
51 51 has_many :groups, class_name: "Group", foreign_key: :owner_id
52 52  
53 53 has_many :keys, dependent: :destroy
54   - has_many :projects, through: :users_projects
55 54 has_many :users_projects, dependent: :destroy
56 55 has_many :issues, foreign_key: :author_id, dependent: :destroy
57 56 has_many :notes, foreign_key: :author_id, dependent: :destroy
... ... @@ -82,6 +81,9 @@ class User &lt; ActiveRecord::Base
82 81 scope :active, where(blocked: false)
83 82 scope :alphabetically, order('name ASC')
84 83  
  84 + #
  85 + # Class methods
  86 + #
85 87 class << self
86 88 def filter filter_name
87 89 case filter_name
... ... @@ -126,9 +128,63 @@ class User &lt; ActiveRecord::Base
126 128 end
127 129 end
128 130  
  131 + #
  132 + # Instance methods
  133 + #
129 134 def generate_password
130 135 if self.force_random_password
131 136 self.password = self.password_confirmation = Devise.friendly_token.first(8)
132 137 end
133 138 end
  139 +
  140 +
  141 + # Namespaces user has access to
  142 + def namespaces
  143 + namespaces = []
  144 +
  145 + # Add user account namespace
  146 + namespaces << self.namespace if self.namespace
  147 +
  148 + # Add groups you can manage
  149 + namespaces += if admin
  150 + Group.all
  151 + else
  152 + groups.all
  153 + end
  154 + namespaces
  155 + end
  156 +
  157 + # Groups where user is an owner
  158 + def owned_groups
  159 + groups
  160 + end
  161 +
  162 + # Groups user has access to
  163 + def authorized_groups
  164 + @authorized_groups ||= begin
  165 + groups = Group.where(id: self.authorized_projects.pluck(:namespace_id)).all
  166 + groups = groups + self.groups
  167 + groups.uniq
  168 + end
  169 + end
  170 +
  171 +
  172 + # Projects user has access to
  173 + def authorized_projects
  174 + project_ids = users_projects.pluck(:project_id)
  175 + project_ids = project_ids | owned_projects.pluck(:id)
  176 + Project.where(id: project_ids)
  177 + end
  178 +
  179 + # Projects in user namespace
  180 + def personal_projects
  181 + Project.personal(self)
  182 + end
  183 +
  184 + # Projects where user is an owner
  185 + def owned_projects
  186 + Project.where("(projects.namespace_id IN (:namespaces)) OR
  187 + (projects.namespace_id IS NULL AND projects.creator_id = :user_id)",
  188 + namespaces: namespaces.map(&:id), user_id: self.id)
  189 + end
134 190 end
... ...
app/roles/account.rb
... ... @@ -25,7 +25,7 @@ module Account
25 25 end
26 26  
27 27 def can_create_project?
28   - projects_limit > my_own_projects.count
  28 + projects_limit > personal_projects.count
29 29 end
30 30  
31 31 def can_create_group?
... ... @@ -56,10 +56,6 @@ module Account
56 56 MergeRequest.where("author_id = :id or assignee_id = :id", id: self.id)
57 57 end
58 58  
59   - def project_ids
60   - projects.map(&:id)
61   - end
62   -
63 59 # Remove user from all projects and
64 60 # set blocked attribute to true
65 61 def block
... ... @@ -86,22 +82,7 @@ module Account
86 82 end
87 83  
88 84 def projects_sorted_by_activity
89   - projects.sorted_by_activity
90   - end
91   -
92   - def namespaces
93   - namespaces = []
94   -
95   - # Add user account namespace
96   - namespaces << self.namespace if self.namespace
97   -
98   - # Add groups you can manage
99   - namespaces += if admin
100   - Group.all
101   - else
102   - groups.all
103   - end
104   - namespaces
  85 + authorized_projects.sorted_by_activity
105 86 end
106 87  
107 88 def several_namespaces?
... ... @@ -111,20 +92,4 @@ module Account
111 92 def namespace_id
112 93 namespace.try :id
113 94 end
114   -
115   - def authorized_groups
116   - @authorized_groups ||= begin
117   - groups = Group.where(id: self.projects.pluck(:namespace_id)).all
118   - groups = groups + self.groups
119   - groups.uniq
120   - end
121   - end
122   -
123   - def authorized_projects
124   - Project.authorized_for(self)
125   - end
126   -
127   - def my_own_projects
128   - Project.personal(self)
129   - end
130 95 end
... ...
app/roles/namespaced_project.rb
... ... @@ -50,14 +50,6 @@ module NamespacedProject
50 50 namespace.try(:owner)
51 51 end
52 52  
53   - def chief
54   - if namespace
55   - namespace_owner
56   - else
57   - owner
58   - end
59   - end
60   -
61 53 def path_with_namespace
62 54 if namespace
63 55 namespace.path + '/' + path
... ...
app/views/admin/projects/show.html.haml
... ... @@ -49,8 +49,8 @@
49 49 %b
50 50 Owned by:
51 51 %td
52   - - if @project.chief
53   - = link_to @project.chief.name, admin_user_path(@project.chief)
  52 + - if @project.owner
  53 + = link_to @project.owner_name, admin_user_path(@project.owner)
54 54 - else
55 55 (deleted)
56 56 %tr
... ... @@ -58,7 +58,7 @@
58 58 %b
59 59 Created by:
60 60 %td
61   - = @project.owner_name || '(deleted)'
  61 + = @project.creator.try(:name) || '(deleted)'
62 62 %tr
63 63 %td
64 64 %b
... ...
app/views/dashboard/_groups.html.haml
... ... @@ -17,4 +17,4 @@
17 17 &rarr;
18 18 %span.last_activity
19 19 %strong Projects:
20   - %span= group.projects.authorized_for(current_user).count
  20 + %span= current_user.authorized_projects.where(namespace_id: group.id).count
... ...
db/migrate/20130102143055_rename_owner_to_creator_for_project.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +class RenameOwnerToCreatorForProject < ActiveRecord::Migration
  2 + def change
  3 + rename_column :projects, :owner_id, :creator_id
  4 + end
  5 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20121219095402) do
  14 +ActiveRecord::Schema.define(:version => 20130102143055) do
15 15  
16 16 create_table "events", :force => true do |t|
17 17 t.string "target_type"
... ... @@ -148,7 +148,7 @@ ActiveRecord::Schema.define(:version =&gt; 20121219095402) do
148 148 t.datetime "created_at", :null => false
149 149 t.datetime "updated_at", :null => false
150 150 t.boolean "private_flag", :default => true, :null => false
151   - t.integer "owner_id"
  151 + t.integer "creator_id"
152 152 t.string "default_branch"
153 153 t.boolean "issues_enabled", :default => true, :null => false
154 154 t.boolean "wall_enabled", :default => true, :null => false
... ... @@ -157,8 +157,8 @@ ActiveRecord::Schema.define(:version =&gt; 20121219095402) do
157 157 t.integer "namespace_id"
158 158 end
159 159  
  160 + add_index "projects", ["creator_id"], :name => "index_projects_on_owner_id"
160 161 add_index "projects", ["namespace_id"], :name => "index_projects_on_namespace_id"
161   - add_index "projects", ["owner_id"], :name => "index_projects_on_owner_id"
162 162  
163 163 create_table "protected_branches", :force => true do |t|
164 164 t.integer "project_id", :null => false
... ...
spec/factories.rb
... ... @@ -9,7 +9,7 @@ FactoryGirl.define do
9 9  
10 10 sequence(:url) { Faker::Internet.uri('http') }
11 11  
12   - factory :user, aliases: [:author, :assignee, :owner] do
  12 + factory :user, aliases: [:author, :assignee, :owner, :creator] do
13 13 email { Faker::Internet.email }
14 14 name
15 15 username { Faker::Internet.user_name }
... ... @@ -26,7 +26,7 @@ FactoryGirl.define do
26 26 factory :project do
27 27 sequence(:name) { |n| "project#{n}" }
28 28 path { name.downcase.gsub(/\s/, '_') }
29   - owner
  29 + creator
30 30 end
31 31  
32 32 factory :group do
... ...
spec/models/project_security_spec.rb
... ... @@ -8,7 +8,7 @@ describe Project do
8 8 @u1 = create(:user)
9 9 @u2 = create(:user)
10 10 @u3 = create(:user)
11   - @u4 = @p1.chief
  11 + @u4 = @p1.owner
12 12  
13 13 @abilities = Six.new
14 14 @abilities << Ability
... ...
spec/models/project_spec.rb
... ... @@ -24,7 +24,7 @@ describe Project do
24 24 describe "Associations" do
25 25 it { should belong_to(:group) }
26 26 it { should belong_to(:namespace) }
27   - it { should belong_to(:owner).class_name('User') }
  27 + it { should belong_to(:creator).class_name('User') }
28 28 it { should have_many(:users) }
29 29 it { should have_many(:events).dependent(:destroy) }
30 30 it { should have_many(:merge_requests).dependent(:destroy) }
... ... @@ -41,7 +41,7 @@ describe Project do
41 41  
42 42 describe "Mass assignment" do
43 43 it { should_not allow_mass_assignment_of(:namespace_id) }
44   - it { should_not allow_mass_assignment_of(:owner_id) }
  44 + it { should_not allow_mass_assignment_of(:creator_id) }
45 45 it { should_not allow_mass_assignment_of(:private_flag) }
46 46 end
47 47  
... ... @@ -55,20 +55,15 @@ describe Project do
55 55 it { should validate_presence_of(:path) }
56 56 it { should validate_uniqueness_of(:path) }
57 57 it { should ensure_length_of(:path).is_within(0..255) }
58   - # TODO: Formats
59   -
60 58 it { should ensure_length_of(:description).is_within(0..2000) }
61   -
62   - # TODO: Formats
63   -
64   - it { should validate_presence_of(:owner) }
  59 + it { should validate_presence_of(:creator) }
65 60 it { should ensure_inclusion_of(:issues_enabled).in_array([true, false]) }
66 61 it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) }
67 62 it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) }
68 63 it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) }
69 64  
70 65 it "should not allow new projects beyond user limits" do
71   - project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
  66 + project.stub(:creator).and_return(double(can_create_project?: false, projects_limit: 1))
72 67 project.should_not be_valid
73 68 project.errors[:base].first.should match(/Your own projects limit is 1/)
74 69 end
... ... @@ -134,7 +129,7 @@ describe Project do
134 129 it { should respond_to(:transfer) }
135 130 it { should respond_to(:name_with_namespace) }
136 131 it { should respond_to(:namespace_owner) }
137   - it { should respond_to(:chief) }
  132 + it { should respond_to(:owner) }
138 133 it { should respond_to(:path_with_namespace) }
139 134 end
140 135  
... ... @@ -211,4 +206,75 @@ describe Project do
211 206 @merge_request.last_commit.id.should == "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
212 207 end
213 208 end
  209 +
  210 + describe :create_by_user do
  211 + before do
  212 + @user = create :user
  213 + @opts = {
  214 + name: "GitLab"
  215 + }
  216 + end
  217 +
  218 + context 'user namespace' do
  219 + before do
  220 + @project = Project.create_by_user(@opts, @user)
  221 + end
  222 +
  223 + it { @project.should be_valid }
  224 + it { @project.owner.should == @user }
  225 + it { @project.namespace.should == @user.namespace }
  226 + end
  227 +
  228 + context 'user namespace' do
  229 + before do
  230 + @group = create :group, owner: @user
  231 + @opts.merge!(namespace_id: @group.id)
  232 + @project = Project.create_by_user(@opts, @user)
  233 + end
  234 +
  235 + it { @project.should be_valid }
  236 + it { @project.owner.should == @user }
  237 + it { @project.namespace.should == @group }
  238 + end
  239 + end
  240 +
  241 + describe :find_with_namespace do
  242 + context 'with namespace' do
  243 + before do
  244 + @group = create :group, name: 'gitlab'
  245 + @project = create(:project, name: 'gitlab-ci', namespace: @group)
  246 + end
  247 +
  248 + it { Project.find_with_namespace('gitlab/gitlab-ci').should == @project }
  249 + it { Project.find_with_namespace('gitlab-ci').should be_nil }
  250 + end
  251 +
  252 + context 'w/o namespace' do
  253 + before do
  254 + @project = create(:project, name: 'gitlab-ci')
  255 + end
  256 +
  257 + it { Project.find_with_namespace('gitlab-ci').should == @project }
  258 + it { Project.find_with_namespace('gitlab/gitlab-ci').should be_nil }
  259 + end
  260 + end
  261 +
  262 + describe :to_param do
  263 + context 'with namespace' do
  264 + before do
  265 + @group = create :group, name: 'gitlab'
  266 + @project = create(:project, name: 'gitlab-ci', namespace: @group)
  267 + end
  268 +
  269 + it { @project.to_param.should == "gitlab/gitlab-ci" }
  270 + end
  271 +
  272 + context 'w/o namespace' do
  273 + before do
  274 + @project = create(:project, name: 'gitlab-ci')
  275 + end
  276 +
  277 + it { @project.to_param.should == "gitlab-ci" }
  278 + end
  279 + end
214 280 end
... ...
spec/models/user_spec.rb
... ... @@ -39,7 +39,6 @@ describe User do
39 39 describe "Associations" do
40 40 it { should have_one(:namespace) }
41 41 it { should have_many(:users_projects).dependent(:destroy) }
42   - it { should have_many(:projects) }
43 42 it { should have_many(:groups) }
44 43 it { should have_many(:keys).dependent(:destroy) }
45 44 it { should have_many(:events).class_name('Event').dependent(:destroy) }
... ... @@ -119,4 +118,71 @@ describe User do
119 118 user.authentication_token.should_not be_blank
120 119 end
121 120 end
  121 +
  122 + describe 'projects' do
  123 + before do
  124 + ActiveRecord::Base.observers.enable(:user_observer)
  125 + @user = create :user
  126 + @project = create :project, namespace: @user.namespace
  127 + end
  128 +
  129 + it { @user.authorized_projects.should include(@project) }
  130 + it { @user.owned_projects.should include(@project) }
  131 + it { @user.personal_projects.should include(@project) }
  132 + end
  133 +
  134 + describe 'groups' do
  135 + before do
  136 + ActiveRecord::Base.observers.enable(:user_observer)
  137 + @user = create :user
  138 + @group = create :group, owner: @user
  139 + end
  140 +
  141 + it { @user.several_namespaces?.should be_true }
  142 + it { @user.namespaces.should == [@user.namespace, @group] }
  143 + it { @user.authorized_groups.should == [@group] }
  144 + it { @user.owned_groups.should == [@group] }
  145 + end
  146 +
  147 + describe 'namespaced' do
  148 + before do
  149 + ActiveRecord::Base.observers.enable(:user_observer)
  150 + @user = create :user
  151 + @project = create :project, namespace: @user.namespace
  152 + end
  153 +
  154 + it { @user.several_namespaces?.should be_false }
  155 + it { @user.namespaces.should == [@user.namespace] }
  156 + end
  157 +
  158 + describe 'blocking user' do
  159 + let(:user) { create(:user, name: 'John Smith') }
  160 +
  161 + it "should block user" do
  162 + user.block
  163 + user.blocked.should be_true
  164 + end
  165 + end
  166 +
  167 + describe 'filter' do
  168 + before do
  169 + @user = create :user
  170 + @admin = create :user, admin: true
  171 + @blocked = create :user, blocked: true
  172 + end
  173 +
  174 + it { User.filter("admins").should == [@admin] }
  175 + it { User.filter("blocked").should == [@blocked] }
  176 + it { User.filter("wop").should == [@user, @admin, @blocked] }
  177 + it { User.filter(nil).should == [@user, @admin] }
  178 + end
  179 +
  180 + describe :not_in_project do
  181 + before do
  182 + @user = create :user
  183 + @project = create :project
  184 + end
  185 +
  186 + it { User.not_in_project(@project).should == [@user, @project.owner] }
  187 + end
122 188 end
... ...
spec/roles/account_role_spec.rb
... ... @@ -10,35 +10,4 @@ describe User, &quot;Account&quot; do
10 10 it { user.can_create_project?.should be_true }
11 11 it { user.first_name.should == 'John' }
12 12 end
13   -
14   - describe 'blocking user' do
15   - let(:user) { create(:user, name: 'John Smith') }
16   -
17   - it "should block user" do
18   - user.block
19   - user.blocked.should be_true
20   - end
21   - end
22   -
23   - describe 'projects' do
24   - before do
25   - ActiveRecord::Base.observers.enable(:user_observer)
26   - @user = create :user
27   - @project = create :project, namespace: @user.namespace
28   - end
29   -
30   - it { @user.authorized_projects.should include(@project) }
31   - it { @user.my_own_projects.should include(@project) }
32   - end
33   -
34   - describe 'namespaced' do
35   - before do
36   - ActiveRecord::Base.observers.enable(:user_observer)
37   - @user = create :user
38   - @project = create :project, namespace: @user.namespace
39   - end
40   -
41   - it { @user.several_namespaces?.should be_false }
42   - it { @user.namespaces.should == [@user.namespace] }
43   - end
44 13 end
... ...