Indefero

Indefero Git Source Tree

Root/src/IDF/Precondition.php

1<?php
2/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3/*
4# ***** BEGIN LICENSE BLOCK *****
5# This file is part of InDefero, an open source project management application.
6# Copyright (C) 2008 Céondo Ltd and contributors.
7#
8# InDefero is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# InDefero is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21#
22# ***** END LICENSE BLOCK ***** */
23
24class IDF_Precondition
25{
26 /**
27 * Check if the user has a base authorization to access a given
28 * tab. This used in the case of private project. You need to
29 * further control with the accessSource, accessIssues,
30 * etc. preconditions.
31 *
32 * @param Pluf_HTTP_Request
33 * @return mixed
34 */
35 static public function baseAccess($request)
36 {
37 if (!$request->project->private) {
38 return true;
39 }
40 if ($request->user->hasPerm('IDF.project-authorized-user', $request->project)) {
41 return true;
42 }
43 return self::projectMemberOrOwner($request);
44 }
45
46 /**
47 * Check if the user is project owner.
48 *
49 * @param Pluf_HTTP_Request
50 * @return mixed
51 */
52 static public function projectOwner($request)
53 {
54 $res = Pluf_Precondition::loginRequired($request);
55 if (true !== $res) {
56 return $res;
57 }
58 if ($request->user->hasPerm('IDF.project-owner', $request->project)) {
59 return true;
60 }
61 return new Pluf_HTTP_Response_Forbidden($request);
62 }
63
64 /**
65 * Check if the user is project owner or member.
66 *
67 * @param Pluf_HTTP_Request
68 * @return mixed
69 */
70 static public function projectMemberOrOwner($request)
71 {
72 $res = Pluf_Precondition::loginRequired($request);
73 if (true !== $res) {
74 return $res;
75 }
76 if ($request->user->hasPerm('IDF.project-owner', $request->project)
77 or
78 $request->user->hasPerm('IDF.project-member', $request->project)
79 ) {
80 return true;
81 }
82 return new Pluf_HTTP_Response_Forbidden($request);
83 }
84
85 /**
86 * Check if the user can access a given element.
87 *
88 * The rights are:
89 * - 'all' (default)
90 * - 'none'
91 * - 'login'
92 * - 'members'
93 * - 'owners'
94 *
95 * The order of the rights is such that a 'owner' is also a
96 * 'member' and of course a logged in person.
97 *
98 * @param Pluf_HTTP_Request
99 * @param string Control key
100 * @return mixed
101 */
102 static public function accessTabGeneric($request, $key)
103 {
104 switch ($request->conf->getVal($key, 'all')) {
105 case 'none':
106 return new Pluf_HTTP_Response_Forbidden($request);
107 case 'login':
108 return Pluf_Precondition::loginRequired($request);
109 case 'members':
110 return self::projectMemberOrOwner($request);
111 case 'owners':
112 return self::projectOwner($request);
113 case 'all':
114 default:
115 return true;
116 }
117 }
118
119 static public function accessSource($request)
120 {
121 $res = self::baseAccess($request);
122 if (true !== $res) {
123 return $res;
124 }
125 return self::accessTabGeneric($request, 'source_access_rights');
126 }
127
128 static public function accessIssues($request)
129 {
130 $res = self::baseAccess($request);
131 if (true !== $res) {
132 return $res;
133 }
134 return self::accessTabGeneric($request, 'issues_access_rights');
135 }
136
137 static public function accessDownloads($request)
138 {
139 $res = self::baseAccess($request);
140 if (true !== $res) {
141 return $res;
142 }
143 return self::accessTabGeneric($request, 'downloads_access_rights');
144 }
145
146 static public function accessWiki($request)
147 {
148 $res = self::baseAccess($request);
149 if (true !== $res) {
150 return $res;
151 }
152 return self::accessTabGeneric($request, 'wiki_access_rights');
153 }
154
155 static public function accessReview($request)
156 {
157 $res = self::baseAccess($request);
158 if (true !== $res) {
159 return $res;
160 }
161 return self::accessTabGeneric($request, 'review_access_rights');
162 }
163
164 /**
165 * Based on the request, it is automatically setting the user.
166 *
167 * API calls are not translated.
168 */
169 static public function apiSetUser($request)
170 {
171 // REQUEST is used to be used both for POST and GET requests.
172 if (!isset($request->REQUEST['_hash'])
173 or !isset($request->REQUEST['_login'])
174 or !isset($request->REQUEST['_salt'])) {
175 // equivalent to anonymous access.
176 return true;
177 }
178 $db =& Pluf::db();
179 $true = Pluf_DB_BooleanToDb(true, $db);
180 $sql = new Pluf_SQL('login=%s AND active='.$true,
181 $request->REQUEST['_login']);
182 $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen()));
183 if ($users->count() != 1 or !$users[0]->active) {
184 // Should return a special authentication error like user
185 // not found.
186 return true;
187 }
188 $hash = sha1($request->REQUEST['_salt'].sha1($users[0]->password));
189 if ($hash != $request->REQUEST['_hash']) {
190 return true; // Again need authentication error
191 }
192 $request->user = $users[0];
193 IDF_Middleware::setRights($request);
194 return true;
195 }
196
197 /**
198 * Based on the request, it is automatically setting the user.
199 *
200 * Authenticated feeds have a token set at the end of the url in
201 * the for of 'authenticated/url/token/234092384023woeiur/'. If
202 * you remove 'token/234092384023woeiur/' the url is not
203 * authenticated.
204 *
205 * If the user is already logged in and not anonymous and no token
206 * is given, then the user is unset and a non authenticated user
207 * is loaded. This is to avoid people to not understand why a
208 * normally not authenticated feed is providing authenticated
209 * data.
210 */
211 static public function feedSetUser($request)
212 {
213 if (!isset($request->project)) {
214 return true; // we do not act on non project pages at the
215 // moment.
216 }
217 if (!$request->user->isAnonymous()) {
218 // by default anonymous
219 $request->user = new Pluf_User();
220 IDF_Middleware::setRights($request);
221 }
222 $match = array();
223 if (!preg_match('#/token/([^/]+)/$#', $request->query, $match)) {
224 return true; // anonymous
225 }
226 $token = $match[1];
227 $hash = substr($token, 0, 2);
228 $encrypted = substr($token, 2);
229 if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) {
230 return true; // no match in the hash, anonymous
231 }
232 $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
233 list($userid, $projectid) = explode(':', $cr->decrypt($encrypted), 2);
234 if ($projectid != $request->project->id) {
235 return true; // anonymous
236 }
237 $user = new Pluf_User($userid);
238 if (!$user->active) {
239 return true; // anonymous
240 }
241 $request->user = $user;
242 IDF_Middleware::setRights($request);
243 return true;
244 }
245
246 /**
247 * Generate the token for the feed.
248 *
249 * @param IDF_Project
250 * @param Pluf_User
251 * @return string Token
252 */
253 static public function genFeedToken($project, $user)
254 {
255 $cr = new Pluf_Crypt(md5(Pluf::f('secret_key')));
256 $encrypted = trim($cr->encrypt($user->id.':'.$project->id), '~');
257 return substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted;
258 }
259}

Archive Download this file