Commit 8a86fe7bb0785ea69e591fd287430eb5448ac64e
Committed by
Dmitriy Zaporozhets
1 parent
f6c482c0
Exists in
master
and in
4 other branches
Added UserTeam core models (team and m-t-m relationships) and updated other models
Showing
14 changed files
with
249 additions
and
29 deletions
Show diff stats
app/models/concerns/issuable.rb
@@ -22,6 +22,7 @@ module Issuable | @@ -22,6 +22,7 @@ module Issuable | ||
22 | scope :opened, where(closed: false) | 22 | scope :opened, where(closed: false) |
23 | scope :closed, where(closed: true) | 23 | scope :closed, where(closed: true) |
24 | scope :of_group, ->(group) { where(project_id: group.project_ids) } | 24 | scope :of_group, ->(group) { where(project_id: group.project_ids) } |
25 | + scope :of_user_team, ->(team) { where(project_id: team.project_ids, assignee_id: team.member_ids) } | ||
25 | scope :assigned, ->(u) { where(assignee_id: u.id)} | 26 | scope :assigned, ->(u) { where(assignee_id: u.id)} |
26 | scope :recent, order("created_at DESC") | 27 | scope :recent, order("created_at DESC") |
27 | 28 |
app/models/project.rb
@@ -33,28 +33,31 @@ class Project < ActiveRecord::Base | @@ -33,28 +33,31 @@ class Project < ActiveRecord::Base | ||
33 | attr_accessor :error_code | 33 | attr_accessor :error_code |
34 | 34 | ||
35 | # Relations | 35 | # Relations |
36 | - belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" | 36 | + belongs_to :creator, foreign_key: "creator_id", class_name: "User" |
37 | + belongs_to :group, foreign_key: "namespace_id", conditions: "type = 'Group'" | ||
37 | belongs_to :namespace | 38 | belongs_to :namespace |
38 | 39 | ||
39 | - belongs_to :creator, | ||
40 | - class_name: "User", | ||
41 | - foreign_key: "creator_id" | ||
42 | - | ||
43 | - has_many :users, through: :users_projects | ||
44 | - has_many :events, dependent: :destroy | ||
45 | - has_many :merge_requests, dependent: :destroy | ||
46 | - has_many :issues, dependent: :destroy, order: "closed, created_at DESC" | ||
47 | - has_many :milestones, dependent: :destroy | ||
48 | - has_many :users_projects, dependent: :destroy | ||
49 | - has_many :notes, dependent: :destroy | ||
50 | - has_many :snippets, dependent: :destroy | ||
51 | - has_many :deploy_keys, dependent: :destroy, foreign_key: "project_id", class_name: "Key" | ||
52 | - has_many :hooks, dependent: :destroy, class_name: "ProjectHook" | ||
53 | - has_many :wikis, dependent: :destroy | ||
54 | - has_many :protected_branches, dependent: :destroy | ||
55 | has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id' | 40 | has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id' |
56 | has_one :gitlab_ci_service, dependent: :destroy | 41 | has_one :gitlab_ci_service, dependent: :destroy |
57 | 42 | ||
43 | + has_many :events, dependent: :destroy | ||
44 | + has_many :merge_requests, dependent: :destroy | ||
45 | + has_many :issues, dependent: :destroy, order: "closed, created_at DESC" | ||
46 | + has_many :milestones, dependent: :destroy | ||
47 | + has_many :users_projects, dependent: :destroy | ||
48 | + has_many :notes, dependent: :destroy | ||
49 | + has_many :snippets, dependent: :destroy | ||
50 | + has_many :deploy_keys, dependent: :destroy, class_name: "Key", foreign_key: "project_id" | ||
51 | + has_many :hooks, dependent: :destroy, class_name: "ProjectHook" | ||
52 | + has_many :wikis, dependent: :destroy | ||
53 | + has_many :protected_branches, dependent: :destroy | ||
54 | + has_many :user_team_project_relationships, dependent: :destroy | ||
55 | + | ||
56 | + has_many :users, through: :users_projects | ||
57 | + has_many :user_teams, through: :user_team_project_relationships | ||
58 | + has_many :user_team_user_relationships, through: :user_teams | ||
59 | + has_many :user_teams_members, through: :user_team_user_relationships | ||
60 | + | ||
58 | delegate :name, to: :owner, allow_nil: true, prefix: true | 61 | delegate :name, to: :owner, allow_nil: true, prefix: true |
59 | 62 | ||
60 | # Validations | 63 | # Validations |
@@ -77,6 +80,8 @@ class Project < ActiveRecord::Base | @@ -77,6 +80,8 @@ class Project < ActiveRecord::Base | ||
77 | # Scopes | 80 | # Scopes |
78 | scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } | 81 | scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) } |
79 | scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) } | 82 | scope :not_in_group, ->(group) { where("id NOT IN (:ids)", ids: group.project_ids ) } |
83 | + scope :without_team, ->(team) { where("id NOT IN (:ids)", ids: team.projects.map(&:id)) } | ||
84 | + scope :in_team, ->(team) { where("id IN (:ids)", ids: team.projects.map(&:id)) } | ||
80 | scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) } | 85 | scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) } |
81 | scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } | 86 | scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") } |
82 | scope :personal, ->(user) { where(namespace_id: user.namespace_id) } | 87 | scope :personal, ->(user) { where(namespace_id: user.namespace_id) } |
app/models/user.rb
@@ -45,18 +45,27 @@ class User < ActiveRecord::Base | @@ -45,18 +45,27 @@ class User < ActiveRecord::Base | ||
45 | attr_accessor :force_random_password | 45 | attr_accessor :force_random_password |
46 | 46 | ||
47 | # Namespace for personal projects | 47 | # Namespace for personal projects |
48 | - has_one :namespace, class_name: "Namespace", foreign_key: :owner_id, conditions: 'type IS NULL', dependent: :destroy | ||
49 | - has_many :groups, class_name: "Group", foreign_key: :owner_id | ||
50 | - | ||
51 | - has_many :keys, dependent: :destroy | ||
52 | - has_many :users_projects, dependent: :destroy | ||
53 | - has_many :issues, foreign_key: :author_id, dependent: :destroy | ||
54 | - has_many :notes, foreign_key: :author_id, dependent: :destroy | ||
55 | - has_many :merge_requests, foreign_key: :author_id, dependent: :destroy | ||
56 | - has_many :events, class_name: "Event", foreign_key: :author_id, dependent: :destroy | ||
57 | - has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" | ||
58 | - has_many :assigned_issues, class_name: "Issue", foreign_key: :assignee_id, dependent: :destroy | ||
59 | - has_many :assigned_merge_requests, class_name: "MergeRequest", foreign_key: :assignee_id, dependent: :destroy | 48 | + has_one :namespace, dependent: :destroy, foreign_key: :owner_id, class_name: "Namespace", conditions: 'type IS NULL' |
49 | + | ||
50 | + has_many :keys, dependent: :destroy | ||
51 | + has_many :users_projects, dependent: :destroy | ||
52 | + has_many :issues, dependent: :destroy, foreign_key: :author_id | ||
53 | + has_many :notes, dependent: :destroy, foreign_key: :author_id | ||
54 | + has_many :merge_requests, dependent: :destroy, foreign_key: :author_id | ||
55 | + has_many :events, dependent: :destroy, foreign_key: :author_id, class_name: "Event" | ||
56 | + has_many :assigned_issues, dependent: :destroy, foreign_key: :assignee_id, class_name: "Issue" | ||
57 | + has_many :assigned_merge_requests, dependent: :destroy, foreign_key: :assignee_id, class_name: "MergeRequest" | ||
58 | + | ||
59 | + has_many :groups, class_name: "Group", foreign_key: :owner_id | ||
60 | + has_many :recent_events, class_name: "Event", foreign_key: :author_id, order: "id DESC" | ||
61 | + | ||
62 | + has_many :projects, through: :users_projects | ||
63 | + | ||
64 | + has_many :user_team_user_relationships, dependent: :destroy | ||
65 | + | ||
66 | + has_many :user_teams, through: :user_team_user_relationships | ||
67 | + has_many :user_team_project_relationships, through: :user_teams | ||
68 | + has_many :team_projects, through: :user_team_project_relationships | ||
60 | 69 | ||
61 | validates :name, presence: true | 70 | validates :name, presence: true |
62 | validates :bio, length: { within: 0..255 } | 71 | validates :bio, length: { within: 0..255 } |
@@ -80,6 +89,8 @@ class User < ActiveRecord::Base | @@ -80,6 +89,8 @@ class User < ActiveRecord::Base | ||
80 | scope :blocked, where(blocked: true) | 89 | scope :blocked, where(blocked: true) |
81 | scope :active, where(blocked: false) | 90 | scope :active, where(blocked: false) |
82 | scope :alphabetically, order('name ASC') | 91 | scope :alphabetically, order('name ASC') |
92 | + scope :in_team, ->(team){ where(id: team.member_ids) } | ||
93 | + scope :not_in_team, ->(team){ where('users.id NOT IN (:ids)', ids: team.member_ids) } | ||
83 | 94 | ||
84 | # | 95 | # |
85 | # Class methods | 96 | # Class methods |
@@ -0,0 +1,87 @@ | @@ -0,0 +1,87 @@ | ||
1 | +class UserTeam < ActiveRecord::Base | ||
2 | + attr_accessible :name, :owner_id, :path | ||
3 | + | ||
4 | + belongs_to :owner, class_name: User | ||
5 | + | ||
6 | + has_many :user_team_project_relationships, dependent: :destroy | ||
7 | + has_many :user_team_user_relationships, dependent: :destroy | ||
8 | + | ||
9 | + has_many :projects, through: :user_team_project_relationships | ||
10 | + has_many :members, through: :user_team_user_relationships, source: :user | ||
11 | + | ||
12 | + validates :name, presence: true, uniqueness: true | ||
13 | + validates :owner, presence: true | ||
14 | + validates :path, uniqueness: true, presence: true, length: { within: 1..255 }, | ||
15 | + format: { with: Gitlab::Regex.path_regex, | ||
16 | + message: "only letters, digits & '_' '-' '.' allowed. Letter should be first" } | ||
17 | + | ||
18 | + scope :with_member, ->(user){ joins(:user_team_user_relationships).where(user_team_user_relationships: {user_id: user.id}) } | ||
19 | + scope :created_by, ->(user){ where(owner_id: user) } | ||
20 | + | ||
21 | + class << self | ||
22 | + def search query | ||
23 | + where("name LIKE :query OR path LIKE :query", query: "%#{query}%") | ||
24 | + end | ||
25 | + | ||
26 | + def global_id | ||
27 | + 'GLN' | ||
28 | + end | ||
29 | + | ||
30 | + def access_roles | ||
31 | + UsersProject.access_roles | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + def to_param | ||
36 | + path | ||
37 | + end | ||
38 | + | ||
39 | + def assign_to_projects(projects, access) | ||
40 | + projects.each do |project| | ||
41 | + assign_to_project(project, access) | ||
42 | + end | ||
43 | + end | ||
44 | + | ||
45 | + def assign_to_project(project, access) | ||
46 | + Gitlab::UserTeamManager.assign(self, project, access) | ||
47 | + end | ||
48 | + | ||
49 | + def resign_from_project(project) | ||
50 | + Gitlab::UserTeamManager.resign(self, project) | ||
51 | + end | ||
52 | + | ||
53 | + def add_members(users, access, group_admin) | ||
54 | + users.each do |user| | ||
55 | + add_member(user, access, group_admin) | ||
56 | + end | ||
57 | + end | ||
58 | + | ||
59 | + def add_member(user, access, group_admin) | ||
60 | + Gitlab::UserTeamManager.add_member_into_team(self, user, access, group_admin) | ||
61 | + end | ||
62 | + | ||
63 | + def remove_member(user) | ||
64 | + Gitlab::UserTeamManager.remove_member_from_team(self, user) | ||
65 | + end | ||
66 | + | ||
67 | + def max_project_access(project) | ||
68 | + user_team_project_relationships.find_by_project_id(project).greatest_access | ||
69 | + end | ||
70 | + | ||
71 | + def human_max_project_access(project) | ||
72 | + self.class.access_roles.invert[max_project_access(project)] | ||
73 | + end | ||
74 | + | ||
75 | + def default_projects_access(member) | ||
76 | + user_team_user_relationships.find_by_user_id(member).permission | ||
77 | + end | ||
78 | + | ||
79 | + def human_default_projects_access(member) | ||
80 | + self.class.access_roles.invert[default_projects_access(member)] | ||
81 | + end | ||
82 | + | ||
83 | + def admin?(member) | ||
84 | + user_team_user_relationships.with_user(member).first.group_admin? | ||
85 | + end | ||
86 | + | ||
87 | +end |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +class UserTeamProjectRelationship < ActiveRecord::Base | ||
2 | + attr_accessible :greatest_access, :project_id, :user_team_id | ||
3 | + | ||
4 | + belongs_to :user_team | ||
5 | + belongs_to :project | ||
6 | + | ||
7 | + validates :project, presence: true | ||
8 | + validates :user_team, presence: true | ||
9 | + validate :check_greatest_access | ||
10 | + | ||
11 | + scope :with_project, ->(project){ where(project_id: project.id) } | ||
12 | + | ||
13 | + private | ||
14 | + | ||
15 | + def check_greatest_access | ||
16 | + errors.add(:base, :incorrect_access_code) unless correct_access? | ||
17 | + end | ||
18 | + | ||
19 | + def correct_access? | ||
20 | + return false if greatest_access.blank? | ||
21 | + return true if UsersProject.access_roles.has_value?(greatest_access) | ||
22 | + false | ||
23 | + end | ||
24 | +end |
@@ -0,0 +1,15 @@ | @@ -0,0 +1,15 @@ | ||
1 | +class UserTeamUserRelationship < ActiveRecord::Base | ||
2 | + attr_accessible :group_admin, :permission, :user_id, :user_team_id | ||
3 | + | ||
4 | + belongs_to :user_team | ||
5 | + belongs_to :user | ||
6 | + | ||
7 | + validates :user_team, presence: true | ||
8 | + validates :user, presence: true | ||
9 | + | ||
10 | + scope :with_user, ->(user) { where(user_id: user.id) } | ||
11 | + | ||
12 | + def user_name | ||
13 | + user.name | ||
14 | + end | ||
15 | +end |
app/models/users_project.rb
@@ -39,7 +39,10 @@ class UsersProject < ActiveRecord::Base | @@ -39,7 +39,10 @@ class UsersProject < ActiveRecord::Base | ||
39 | scope :reporters, where(project_access: REPORTER) | 39 | scope :reporters, where(project_access: REPORTER) |
40 | scope :developers, where(project_access: DEVELOPER) | 40 | scope :developers, where(project_access: DEVELOPER) |
41 | scope :masters, where(project_access: MASTER) | 41 | scope :masters, where(project_access: MASTER) |
42 | + | ||
42 | scope :in_project, ->(project) { where(project_id: project.id) } | 43 | scope :in_project, ->(project) { where(project_id: project.id) } |
44 | + scope :in_projects, ->(projects) { where(project_id: projects.map(&:id)) } | ||
45 | + scope :with_user, ->(user) { where(user_id: user.id) } | ||
43 | 46 | ||
44 | class << self | 47 | class << self |
45 | 48 |
db/migrate/20121220064104_create_user_team_project_relationships.rb
0 → 100644
@@ -0,0 +1,11 @@ | @@ -0,0 +1,11 @@ | ||
1 | +class CreateUserTeamProjectRelationships < ActiveRecord::Migration | ||
2 | + def change | ||
3 | + create_table :user_team_project_relationships do |t| | ||
4 | + t.integer :project_id | ||
5 | + t.integer :user_team_id | ||
6 | + t.integer :greatest_access | ||
7 | + | ||
8 | + t.timestamps | ||
9 | + end | ||
10 | + end | ||
11 | +end |
db/migrate/20121220064453_create_user_team_user_relationships.rb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +class CreateUserTeamUserRelationships < ActiveRecord::Migration | ||
2 | + def change | ||
3 | + create_table :user_team_user_relationships do |t| | ||
4 | + t.integer :user_id | ||
5 | + t.integer :user_team_id | ||
6 | + t.boolean :group_admin | ||
7 | + t.integer :permission | ||
8 | + | ||
9 | + t.timestamps | ||
10 | + end | ||
11 | + end | ||
12 | +end |
db/schema.rb
@@ -213,6 +213,31 @@ ActiveRecord::Schema.define(:version => 20130110172407) do | @@ -213,6 +213,31 @@ ActiveRecord::Schema.define(:version => 20130110172407) do | ||
213 | t.string "name" | 213 | t.string "name" |
214 | end | 214 | end |
215 | 215 | ||
216 | + create_table "user_team_project_relationships", :force => true do |t| | ||
217 | + t.integer "project_id" | ||
218 | + t.integer "user_team_id" | ||
219 | + t.integer "greatest_access" | ||
220 | + t.datetime "created_at", :null => false | ||
221 | + t.datetime "updated_at", :null => false | ||
222 | + end | ||
223 | + | ||
224 | + create_table "user_team_user_relationships", :force => true do |t| | ||
225 | + t.integer "user_id" | ||
226 | + t.integer "user_team_id" | ||
227 | + t.boolean "group_admin" | ||
228 | + t.integer "permission" | ||
229 | + t.datetime "created_at", :null => false | ||
230 | + t.datetime "updated_at", :null => false | ||
231 | + end | ||
232 | + | ||
233 | + create_table "user_teams", :force => true do |t| | ||
234 | + t.string "name" | ||
235 | + t.string "path" | ||
236 | + t.integer "owner_id" | ||
237 | + t.datetime "created_at", :null => false | ||
238 | + t.datetime "updated_at", :null => false | ||
239 | + end | ||
240 | + | ||
216 | create_table "users", :force => true do |t| | 241 | create_table "users", :force => true do |t| |
217 | t.string "email", :default => "", :null => false | 242 | t.string "email", :default => "", :null => false |
218 | t.string "encrypted_password", :default => "", :null => false | 243 | t.string "encrypted_password", :default => "", :null => false |