Add basics for private repositories
[gitorious:yousource.git] / app / models / committership.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2010 Marko Peltola <marko@markopeltola.com>
4 #   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
5 #   Copyright (C) 2007 Johan Sørensen <johan@johansorensen.com>
6 #   Copyright (C) 2008 David A. Cuadrado <krawek@gmail.com>
7 #   Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
8 #
9 #   This program is free software: you can redistribute it and/or modify
10 #   it under the terms of the GNU Affero General Public License as published by
11 #   the Free Software Foundation, either version 3 of the License, or
12 #   (at your option) any later version.
13 #
14 #   This program is distributed in the hope that it will be useful,
15 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 #   GNU Affero General Public License for more details.
18 #
19 #   You should have received a copy of the GNU Affero General Public License
20 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 #++
22
23 class Committership < ActiveRecord::Base
24
25   CAN_VIEW   = 1 << 3   #TODO: what???
26   CAN_REVIEW = 1 << 4
27   CAN_COMMIT = 1 << 5
28   CAN_ADMIN  = 1 << 6
29
30   PERMISSION_TABLE = {
31     :view => CAN_VIEW,
32     :review => CAN_REVIEW,
33     :commit => CAN_COMMIT,
34     :admin => CAN_ADMIN
35   }
36
37   belongs_to :committer, :polymorphic => true
38   belongs_to :repository
39   belongs_to :creator, :class_name => 'User'
40   has_many :messages, :as => :notifiable
41
42   validates_presence_of :committer_id, :committer_type, :repository_id
43   validates_uniqueness_of :committer_id, :scope => [:committer_type, :repository_id],
44     :message => 'is already a committer to this repository'
45
46   attr_protected :permissions
47
48   after_create :notify_repository_owners
49   after_create :add_new_committer_event
50   after_destroy :add_removed_committer_event
51   before_destroy :nullify_messages
52
53   named_scope :groups, :conditions => { :committer_type => "Group" }
54   named_scope :users,  :conditions => { :committer_type => "User" }
55   named_scope :viewers, :conditions => ["(permissions & ?)", CAN_VIEW]
56   named_scope :reviewers, :conditions => ["(permissions & ?)", CAN_REVIEW]
57   named_scope :committers, :conditions => ["(permissions & ?)", CAN_COMMIT]
58   named_scope :admins, :conditions => ["(permissions & ?)", CAN_ADMIN]
59
60   def self.create_for_owner!(an_owner)
61     cs = new({:committer => an_owner})
62     cs.permissions = (CAN_VIEW | CAN_REVIEW | CAN_COMMIT | CAN_ADMIN)
63     cs.save!
64     cs
65   end
66
67   def self.create_with_permissions!(attrs, perms)
68     cs = new(attrs)
69     cs.permissions = perms
70     cs.save!
71     cs
72   end
73
74   def permission_mask_for(*perms)
75     perms.inject(0) do |memo, perm_symbol|
76       memo | PERMISSION_TABLE[perm_symbol]
77     end
78   end
79
80   def build_permissions(*perms)
81     perms = perms.flatten.compact.map{|p| p.to_sym }
82     self.permissions = permission_mask_for(*perms)
83   end
84
85   def permitted?(wants_to)
86     raise "unknown permission: #{wants_to.inspect}" if !PERMISSION_TABLE[wants_to]
87     (self.permissions & PERMISSION_TABLE[wants_to]) != 0
88   end
89
90   def viewer?
91     permitted?(:view)
92   end
93
94   def reviewer?
95     permitted?(:review)
96   end
97
98   def committer?
99     permitted?(:commit)
100   end
101
102   def admin?
103     permitted?(:admin)
104   end
105
106   def permission_list
107     PERMISSION_TABLE.keys.select{|perm| permitted?(perm) }
108   end
109
110   def breadcrumb_parent
111     Breadcrumb::Committerships.new(repository)
112   end
113
114   def title
115     new_record? ? "New collaborator" : "Collaborator"
116   end
117
118   # returns all the users in this committership, eg if it's a group it'll
119   # return an array of the group members, otherwise a single-member array of
120   # the user
121   def members
122     case committer
123     when Group
124       committer.members
125     else
126       [committer]
127     end
128   end
129
130   protected
131     def notify_repository_owners
132       return unless creator
133       recipients = repository.owners
134       recipients.each do |r|
135         message = Message.new({
136           :sender => creator,
137           :recipient => r,
138           :subject => I18n.t("committership.notification_subject"),
139           :body => I18n.t("committership.notification_body", {
140             :inviter => creator.title,
141             :user => committer.title,
142             :repository => repository.name,
143             :project => repository.project.title
144           }),
145           :notifiable => self
146         })
147         message.save
148       end
149     end
150
151     def add_new_committer_event
152       repository.project.create_event(Action::ADD_COMMITTER, repository,
153                                       creator, committer.title)
154     end
155
156     def add_removed_committer_event
157       return unless repository
158       repository.project.create_event(Action::REMOVE_COMMITTER, repository,
159                                       creator, committer.title)
160     end
161
162     def nullify_messages
163       messages.update_all({:notifiable_id => nil, :notifiable_type => nil})
164     end
165 end