source: trunk/server/www/app/controllers/galleries_controller.php @ 294

Last change on this file since 294 was 294, checked in by sander, 11 years ago

Fix access control errors with results that are part of public galleries

File size: 10.4 KB
Line 
1<?php
2/**
3 * Officeshots.org - Test your office documents in different applications
4 * Copyright (C) 2009 Stichting Lone Wolves
5 * Written by Sander Marechal <s.marechal@jejik.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21/**
22 * The galleries controller
23 */
24class GalleriesController extends AppController
25{
26        /** @var array The components this controller uses */
27        public $components = array('AuthCert');
28       
29        /** The controller helpers */
30        public $helpers = array('Html', 'Form', 'Javascript', 'RequestModel', 'ResultModel', 'ValidatorModel');
31
32        /** The models this controller uses */
33        public $uses = array('Gallery', 'Request', 'User');
34
35        /**
36         * Set the auth permissions for this controller
37         * @return void
38         */
39        public function beforeFilter()
40        {
41                parent::beforeFilter();
42                $this->AuthCert->allow('index', 'view');
43        }
44
45        /**
46         * Check if the current user has write access to the gallery
47         * @param string $slug The unique gallery slug
48         */
49        private function _checkAccess($slug)
50        {
51                $gallery = $this->Gallery->find('first', array(
52                        'conditions' => array('Gallery.slug' => $slug),
53                        'recursive' => -1,
54                ));
55
56                // Gallery does not exist
57                if (empty($gallery)) {
58                        return false;
59                }
60
61                // User owns the gallery
62                if ($gallery['Gallery']['user_id'] == $this->AuthCert->user('id')) {
63                        return true;
64                }
65
66                // Gallery is assigned to a group the user is a member of
67                if (!empty($gallery['Gallery']['group_id'])) {
68                        return $this->User->Group->has_member($this->AuthCert->user('id'), $gallery['Gallery']['group_id']);
69                }
70
71                return false;
72        }
73
74        /**
75         * Sort an array of Galleries threaded, like find('threaded') would do
76         */
77        private function _sortThreaded($results)
78        {
79                $return = $idMap = array();
80                $ids = Set::extract($results, '{n}.Gallery.id');
81
82                foreach ($results as $result) {
83                        $result['children'] = array();
84                        $id = $result['Gallery']['id'];
85                        $parentId = $result['Gallery']['parent_id'];
86                        if (isset($idMap[$id]['children'])) {
87                                $idMap[$id] = array_merge($result, (array)$idMap[$id]);
88                        } else {
89                                $idMap[$id] = array_merge($result, array('children' => array()));
90                        }
91                        if (!$parentId || !in_array($parentId, $ids)) {
92                                $return[] =& $idMap[$id];
93                        } else {
94                                $idMap[$parentId]['children'][] =& $idMap[$id];
95                        }
96                }
97                if (count($return) > 1) {
98                        $ids = array_unique(Set::extract('/Gallery/parent_id', $return));
99                        if (count($ids) > 1) {
100                                $root = $return[0]['Gallery']['parent_id'];
101                                foreach ($return as $key => $value) {
102                                        if ($value['Gallery']['parent_id'] != $root) {
103                                                unset($return[$key]);
104                                        }
105                                }
106                        }
107                }
108                return $return;
109        }
110
111        /**
112         * Show a list of all galleries
113         */
114        public function index()
115        {
116                $this->Gallery->contain(array('User', 'Request'));
117                $galleries = $this->paginate('Gallery', array('Gallery.parent_id' => null));
118
119                foreach ($galleries as &$gallery) {
120                        $gallery['Gallery']['num_documents'] = $this->Gallery->requestCount($gallery['Gallery']['id'], true);
121                }
122
123                $this->set('galleries', $galleries);
124        }
125
126        /**
127         * View a gallery
128         * @param string $slug The gallery slug
129         */
130        public function view($slug = null)
131        {
132                if (!$slug) {
133                        $this->Session->setFlash(__('Invalid Gallery.', true));
134                        $this->redirect(array('action'=>'index'));
135                }
136
137                // Get the gallery
138                $gallery = $this->Gallery->find('first', array(
139                        'conditions' => array('Gallery.slug' => $slug),
140                        'contain' => array(
141                                'Request',
142                                'Request.Validator' => array('order' => 'Validator.name ASC'),
143                                'Request.Job',
144                                'Request.Job.Application',
145                                'Request.Job.Platform',
146                                'Request.Job.Result',
147                                'Request.Job.Result.Validator',
148                        ),
149                ));
150
151                // Get the children of this gallery
152                // TODO: Do this without recursion below Request because it generates ridiculous amounts of
153                // duplicate queries that slow the system *a lot*
154                $children = $this->Gallery->find('all', array(
155                        'conditions' => array(
156                                'Gallery.lft >' => $gallery['Gallery']['lft'],
157                                'Gallery.rght <' => $gallery['Gallery']['rght'],
158                        ),
159                        'contain' => array('Request'),
160                ));
161
162                foreach ($children as &$child) {
163                        foreach ($child['Request'] as &$request) {
164                                $request['Validator'] = $this->Request->Validator->find('all', array(
165                                        'conditions' => array('Validator.parent_id' => $request['id']),
166                                        'order'      => 'Validator.name ASC',
167                                        'recursive'  => -1,
168                                ));
169
170                                $request['Job'] = $this->Request->Job->find('all', array(
171                                        'conditions' => array('Job.request_id' => $request['id']),
172                                        'contain' => array(
173                                                'Application',
174                                                'Platform',
175                                                'Result',
176                                                'Result.Validator'
177                                        ),
178                                ));
179
180                                // Fix array layout to match a regular query layout
181                                foreach ($request['Job'] as &$job) {
182                                        foreach ($job['Job'] as $attr => $value) {
183                                                $job[$attr] = $value;
184                                        }
185                                        unset($job['Job']);
186                                }
187                        }
188                }
189
190                $gallery['children'] = $this->_sortThreaded($children);
191
192                // Get the path to this gallery
193                $path = $this->Gallery->getpath($gallery['Gallery']['id']);
194                array_pop($path);
195
196                // Check access
197                $access = $this->_checkAccess($slug);
198                $this->set(compact('gallery', 'path', 'access'));
199        }
200
201        /**
202         * Add a new gallery
203         */
204        public function add()
205        {
206                if (!empty($this->data)) {
207                        $this->data['Gallery']['user_id'] = $this->AuthCert->user('id');
208
209                        $this->Gallery->create();
210                        if ($this->Gallery->save($this->data)) {
211                                $this->Session->setFlash(__('The Gallery has been saved', true));
212                                $gallery = $this->Gallery->read('slug', $this->Gallery->id);
213                                $this->redirect(array('action' => 'view', $gallery['Gallery']['slug']));
214                        } else {
215                                $this->Session->setFlash(__('The Gallery could not be saved. Please, try again.', true));
216                        }
217                }
218
219                $groups = $this->User->find('first', array(
220                        'contain' => array('Group'),
221                        'conditions' => array('User.id' => $this->AuthCert->user('id')),
222                ));
223
224                $groups = array_combine(
225                        Set::extract('/Group/id', $groups),
226                        Set::extract('/Group/name', $groups)
227                );
228
229                $this->set(compact('groups'));
230                $this->render('edit');
231        }
232
233        /**
234         * Edit a gallery
235         * @param string $slug the unique gallery slug
236         */
237        public function edit($slug = null)
238        {
239                if (!empty($this->data)) {
240                        $slug = $this->Gallery->read('slug', $this->data['Gallery']['id']);
241                }
242
243                if (!$slug && empty($this->data)) {
244                        $this->Session->setFlash(__('Invalid Gallery', true));
245                        $this->redirect(array('action' => 'index'));
246                }
247
248                if (!$this->_checkAccess($slug)) {
249                        $this->Session->setFlash(__('You are not allowed to edit this gallery', true));
250                        $this->redirect(array('action' => 'view', $slug));
251                }
252
253                if (!empty($this->data)) {
254                        if ($this->Gallery->save($this->data)) {
255                                $this->Session->setFlash(__('The Gallery has been saved', true));
256                                $this->redirect(array('action' => 'view', $this->data['Gallery']['slug']));
257                        } else {
258                                $this->Session->setFlash(__('The Gallery could not be saved. Please, try again.', true));
259                        }
260                } else {
261                        $this->data = $this->Gallery->find('first', array(
262                                'conditions' => array('Gallery.slug' => $slug),
263                                'recursive' => -1,
264                        ));
265                }
266
267                $groups = $this->User->find('first', array(
268                        'contain' => array('Group'),
269                        'conditions' => array('User.id' => $this->AuthCert->user('id')),
270                ));
271
272                $groups = array_combine(
273                        Set::extract('/Group/id', $groups),
274                        Set::extract('/Group/name', $groups)
275                );
276
277                $this->set(compact('groups'));
278        }
279
280        /**
281         * Delete a gallery
282         * @param string $slug the unique gallery slug
283         */
284        public function delete($slug = null)
285        {
286                if (!$slug) {
287                        $this->Session->setFlash(__('Invalid Gallery', true));
288                        $this->redirect(array('action'=>'index'));
289                }
290
291                if (!$this->_checkAccess($slug)) {
292                        $this->Session->setFlash(__('You are not allowed to delete this gallery', true));
293                        $this->redirect(array('action' => 'view', $slug));
294                }
295
296                $gallery = $this->Gallery->find('first', array(
297                        'recursive' => -1,
298                        'conditions' => array('Gallery.slug' => $slug),
299                ));
300
301                if ($this->Gallery->del($gallery['Gallery']['id'])) {
302                        $this->Session->setFlash(__('Gallery deleted', true));
303                        $this->redirect(array('action'=>'index'));
304                }
305        }
306
307        /**
308         * Add a document to the gallery
309         * @param string $slug the unique gallery slug
310         */
311        public function add_document($slug)
312        {
313                if (!$this->_checkAccess($slug)) {
314                        $this->Session->setFlash(__('You are not allowed to edit this gallery', true));
315                        $this->redirect(array('action' => 'view', $slug));
316                }
317
318                if (!empty($this->data)) {
319                        $gallery = $this->Gallery->find('first', array(
320                                'conditions' => array('Gallery.slug' => $slug),
321                                'recursive' => -1,
322                        ));
323
324                        if (!$this->Gallery->addRequest(array_shift($this->data['Gallery']['requests']), $gallery['Gallery']['id'])) {
325                                $this->Session->setFlash(__('The document could not be added.', true));
326                        }
327               
328                        $this->redirect(array('action' => 'view', $slug));
329                }
330
331                $tmp_requests = $this->Request->find('all', array(
332                        'conditions' => array('Request.user_id' => $this->AuthCert->user('id')),
333                        'order' => 'Request.created DESC',
334                        'recursive' => -1,
335                ));
336
337                $requests = array();
338                foreach ($tmp_requests as $request) {
339                        $requests[$request['Request']['id']] = $request['Request']['created'] . ': '
340                                . $request['Request']['filename']
341                                . ' (' . $request['Request']['result_count']
342                                . '/'  . $request['Request']['job_count'] . ')';
343                }
344
345                $this->set(compact('slug', 'requests'));
346        }
347
348        /**
349         * Remove a document from a gallery
350         * @param string $slug the unique gallery slug
351         * @param string $request_id The request ID
352         */
353        public function remove_document($slug, $request_id)
354        {
355                if (!$this->_checkAccess($slug)) {
356                        $this->Session->setFlash(__('You are not allowed to edit this gallery', true));
357                        $this->redirect(array('action' => 'view', $slug));
358                }
359
360                $gallery = $this->Gallery->find('first', array(
361                        'conditions' => array('Gallery.slug' => $slug),
362                        'recursive' => -1,
363                ));
364
365                if (!$this->Gallery->removeRequest($request_id, $gallery['Gallery']['id'])) {
366                        $this->Session->setFlash(__('The document could not be removed.', true));
367                }
368               
369                $this->redirect(array('action' => 'view', $slug));
370        }
371}
372
373?>
Note: See TracBrowser for help on using the repository browser.