Commit 8a86fe7bb0785ea69e591fd287430eb5448ac64e

Authored by Andrey Kumanyaev
Committed by Dmitriy Zaporozhets
1 parent f6c482c0

Added UserTeam core models (team and m-t-m relationships) and updated other models

app/models/concerns/issuable.rb
... ... @@ -22,6 +22,7 @@ module Issuable
22 22 scope :opened, where(closed: false)
23 23 scope :closed, where(closed: true)
24 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 26 scope :assigned, ->(u) { where(assignee_id: u.id)}
26 27 scope :recent, order("created_at DESC")
27 28  
... ...
app/models/project.rb
... ... @@ -33,28 +33,31 @@ class Project < ActiveRecord::Base
33 33 attr_accessor :error_code
34 34  
35 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 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 40 has_one :last_event, class_name: 'Event', order: 'events.created_at DESC', foreign_key: 'project_id'
56 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 61 delegate :name, to: :owner, allow_nil: true, prefix: true
59 62  
60 63 # Validations
... ... @@ -77,6 +80,8 @@ class Project < ActiveRecord::Base
77 80 # Scopes
78 81 scope :without_user, ->(user) { where("id NOT IN (:ids)", ids: user.authorized_projects.map(&:id) ) }
79 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 85 scope :in_namespace, ->(namespace) { where(namespace_id: namespace.id) }
81 86 scope :sorted_by_activity, ->() { order("(SELECT max(events.created_at) FROM events WHERE events.project_id = projects.id) DESC") }
82 87 scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
... ...
app/models/user.rb
... ... @@ -45,18 +45,27 @@ class User < ActiveRecord::Base
45 45 attr_accessor :force_random_password
46 46  
47 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 70 validates :name, presence: true
62 71 validates :bio, length: { within: 0..255 }
... ... @@ -80,6 +89,8 @@ class User < ActiveRecord::Base
80 89 scope :blocked, where(blocked: true)
81 90 scope :active, where(blocked: false)
82 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 96 # Class methods
... ...
app/models/user_team.rb 0 → 100644
... ... @@ -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
... ...
app/models/user_team_project_relationship.rb 0 → 100644
... ... @@ -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
... ...
app/models/user_team_user_relationship.rb 0 → 100644
... ... @@ -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 &lt; ActiveRecord::Base
39 39 scope :reporters, where(project_access: REPORTER)
40 40 scope :developers, where(project_access: DEVELOPER)
41 41 scope :masters, where(project_access: MASTER)
  42 +
42 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 47 class << self
45 48  
... ...
db/migrate/20121219183753_create_user_teams.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class CreateUserTeams < ActiveRecord::Migration
  2 + def change
  3 + create_table :user_teams do |t|
  4 + t.string :name
  5 + t.string :path
  6 + t.integer :owner_id
  7 +
  8 + t.timestamps
  9 + end
  10 + end
  11 +end
... ...
db/migrate/20121220064104_create_user_team_project_relationships.rb 0 → 100644
... ... @@ -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 @@
  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 =&gt; 20130110172407) do
213 213 t.string "name"
214 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 241 create_table "users", :force => true do |t|
217 242 t.string "email", :default => "", :null => false
218 243 t.string "encrypted_password", :default => "", :null => false
... ...
spec/models/user_team_project_relationship_spec.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require 'spec_helper'
  2 +
  3 +describe UserTeamProjectRelationship do
  4 + pending "add some examples to (or delete) #{__FILE__}"
  5 +end
... ...
spec/models/user_team_spec.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require 'spec_helper'
  2 +
  3 +describe UserTeam do
  4 + pending "add some examples to (or delete) #{__FILE__}"
  5 +end
... ...
spec/models/user_team_user_relationship_spec.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require 'spec_helper'
  2 +
  3 +describe UserTeamUserRelationship do
  4 + pending "add some examples to (or delete) #{__FILE__}"
  5 +end
... ...