Authorization for data on dashboard and index pages
[gitorious:mainline.git] / app / models / committership_authorization.rb
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2012 Gitorious AS
4 #
5 #   This program is free software: you can redistribute it and/or modify
6 #   it under the terms of the GNU Affero General Public License as published by
7 #   the Free Software Foundation, either version 3 of the License, or
8 #   (at your option) any later version.
9 #
10 #   This program is distributed in the hope that it will be useful,
11 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #   GNU Affero General Public License for more details.
14 #
15 #   You should have received a copy of the GNU Affero General Public License
16 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #++
18 require "gitorious/authorization/typed_authorization"
19
20 class CommittershipAuthorization < Gitorious::Authorization::TypedAuthorization
21   ### Abilities
22   ability :can_read
23   ability :can_edit
24   ability :can_delete
25   ability :can_grant_access
26
27   def can_read_project?(user, project)
28     return true if !private_repos
29     return true if project.owner == user
30     return true if project.project_memberships.count == 0
31     project.project_memberships.any? { |m| is_member?(user, m.member) }
32   end
33
34   def can_read_repository?(user, repository)
35     return true if repository.project.nil?
36     can_read_project?(user, repository.project)
37   end
38
39   def can_read_message?(user, message)
40     [message.sender, message.recipient].include?(user)
41   end
42
43   # TODO: Needs more polymorphism
44   def can_push?(user, repository)
45     if repository.wiki?
46       can_write_to_wiki?(user, repository)
47     else
48       committers(repository).include?(user)
49     end
50   end
51
52   def can_delete_project?(candidate, project)
53     admin?(candidate, project) && project.repositories.clones.count == 0
54   end
55
56   def can_delete_repository?(candidate, repository)
57     admin?(candidate, repository)
58   end
59
60   def can_edit_comment?(user, comment)
61     comment.creator?(user) && comment.recently_created?
62   end
63
64   def can_grant_access_project?(candidate, project)
65     private_repos && admin?(candidate, project)
66   end
67
68   def can_request_merge?(user, repository)
69     !repository.mainline? && can_push?(user, repository)
70   end
71
72   def can_resolve_merge_request?(user, merge_request)
73     return false unless user.is_a?(User)
74     return true if user === merge_request.user
75     return reviewers(merge_request.target_repository).include?(user)
76   end
77
78   def can_reopen_merge_request?(user, merge_request)
79     merge_request.can_reopen? && can_resolve_merge_request?(user, merge_request)
80   end
81
82   ### Roles
83
84   def committer?(candidate, repository)
85     candidate.is_a?(User) ? committers(repository).include?(candidate) : false
86   end
87
88   def reviewer?(candidate, repository)
89     candidate.is_a?(User) ? reviewers(repository).include?(candidate) : false
90   end
91
92   def is_member?(candidate, thing)
93     candidate == thing || (thing.respond_to?(:member?) && thing.member?(candidate))
94   end
95
96   ###
97
98   def repository_admin?(candidate, repository)
99     candidate.is_a?(User) ? administrators(repository).include?(candidate) : false
100   end
101
102   def project_admin?(candidate, project)
103     admin?(candidate, project.owner)
104   end
105
106   def group_admin?(candidate, group)
107     group.user_role(candidate) == Role.admin
108   end
109
110   def group_committer?(candidate, group)
111     [Role.admin, Role.member].include?(group.user_role(candidate))
112   end
113
114   def site_admin?(user)
115     user.is_a?(User) && user.is_admin
116   end
117
118   # returns an array of users who have commit bits to this repository either
119   # directly through the owner, or "indirectly" through the associated
120   # groups
121   def committers(repository)
122     repository.committerships.committers.map{|c| c.members }.flatten.compact.uniq
123   end
124
125   # Returns a list of Users who can review things (as per their Committership)
126   def reviewers(repository)
127     repository.committerships.reviewers.map{|c| c.members }.flatten.compact.uniq
128   end
129
130   # The list of users who can admin this repo, either directly as
131   # committerships or indirectly as members of a group
132   def administrators(repository)
133     repository.committerships.admins.map{|c| c.members }.flatten.compact.uniq
134   end
135
136   def review_repositories(user)
137     user.committerships.reviewers
138   end
139
140   def filter_authorized(actor, collection)
141     collection.select { |item| can_read?(actor, item) }
142   end
143
144   private
145   def can_write_to_wiki?(user, repository)
146     case repository.wiki_permissions
147     when Repository::WIKI_WRITABLE_EVERYONE
148       return true
149     when Repository::WIKI_WRITABLE_PROJECT_MEMBERS
150       return repository.project.member?(user)
151     end
152   end
153
154   def private_repos
155     GitoriousConfig["enable_private_repositories"]
156   end
157 end