summaryrefslogtreecommitdiff
path: root/app/models/users_project.rb
blob: 60bdf7a3cfb15278b6d4d2dbba6d0b3b7633d138 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# == Schema Information
#
# Table name: users_projects
#
#  id                 :integer          not null, primary key
#  user_id            :integer          not null
#  project_id         :integer          not null
#  created_at         :datetime
#  updated_at         :datetime
#  project_access     :integer          default(0), not null
#  notification_level :integer          default(3), not null
#

class UsersProject < ActiveRecord::Base
  include Gitlab::ShellAdapter
  include Notifiable
  include Gitlab::Access

  belongs_to :user
  belongs_to :project

  validates :user, presence: true
  validates :user_id, uniqueness: { scope: [:project_id], message: "already exists in project" }
  validates :project_access, inclusion: { in: Gitlab::Access.values }, presence: true
  validates :project, presence: true

  delegate :name, :username, :email, to: :user, prefix: true

  scope :guests, -> { where(project_access: GUEST) }
  scope :reporters, -> { where(project_access: REPORTER) }
  scope :developers, -> { where(project_access: DEVELOPER) }
  scope :masters,  -> { where(project_access: MASTER) }

  scope :in_project, ->(project) { where(project_id: project.id) }
  scope :in_projects, ->(projects) { where(project_id: projects.map { |p| p.id }) }
  scope :with_user, ->(user) { where(user_id: user.id) }

  after_create :post_create_hook
  after_update :post_update_hook
  after_destroy :post_destroy_hook

  class << self

    # Add users to project teams with passed access option
    #
    # access can be an integer representing a access code
    # or symbol like :master representing role
    #
    # Ex.
    #   add_users_into_projects(
    #     project_ids,
    #     user_ids,
    #     UsersProject::MASTER
    #   )
    #
    #   add_users_into_projects(
    #     project_ids,
    #     user_ids,
    #     :master
    #   )
    #
    def add_users_into_projects(project_ids, user_ids, access)
      project_access = if roles_hash.has_key?(access)
                         roles_hash[access]
                       elsif roles_hash.values.include?(access.to_i)
                         access
                       else
                         raise "Non valid access"
                       end

      UsersProject.transaction do
        project_ids.each do |project_id|
          user_ids.each do |user_id|
            users_project = UsersProject.new(project_access: project_access, user_id: user_id)
            users_project.project_id = project_id
            users_project.save
          end
        end
      end

      true
    rescue
      false
    end

    def truncate_teams(project_ids)
      UsersProject.transaction do
        users_projects = UsersProject.where(project_id: project_ids)
        users_projects.each do |users_project|
          users_project.destroy
        end
      end

      true
    rescue
      false
    end

    def truncate_team project
      truncate_teams [project.id]
    end

    def roles_hash
      Gitlab::Access.sym_options
    end

    def access_roles
      Gitlab::Access.options
    end
  end

  def access_field
    project_access
  end

  def owner?
    project.owner == user
  end

  def post_create_hook
    Event.create(
      project_id: self.project.id,
      action: Event::JOINED,
      author_id: self.user.id
    )

    notification_service.new_team_member(self) unless owner?
    system_hook_service.execute_hooks_for(self, :create)
  end

  def post_update_hook
    notification_service.update_team_member(self) if self.project_access_changed?
  end

  def post_destroy_hook
    Event.create(
      project_id: self.project.id,
      action: Event::LEFT,
      author_id: self.user.id
    )

    system_hook_service.execute_hooks_for(self, :destroy)
  end

  def notification_service
    NotificationService.new
  end

  def system_hook_service
    SystemHooksService.new
  end
end