Issues (493)

lib/SP/Core/Acl/Actions.php (1 issue)

1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Core\Acl;
26
27
use RuntimeException;
28
use SP\DataModel\ActionData;
29
use SP\Storage\File\FileCacheInterface;
30
use SP\Storage\File\FileException;
31
use SP\Storage\File\XmlFileStorageInterface;
32
33
/**
34
 * Class Actions
35
 *
36
 * @package SP\Core\Acl
37
 */
38
final class Actions
39
{
40
    /**
41
     * Cache file name
42
     */
43
    const ACTIONS_CACHE_FILE = CACHE_PATH . DIRECTORY_SEPARATOR . 'actions.cache';
44
    /**
45
     * Cache expire time
46
     */
47
    const CACHE_EXPIRE = 86400;
48
    /**
49
     * @var int
50
     */
51
    protected $lastLoadTime;
52
    /**
53
     * @var  ActionData[]
54
     */
55
    protected $actions;
56
    /**
57
     * @var XmlFileStorageInterface
58
     */
59
    protected $xmlFileStorage;
60
    /**
61
     * @var FileCacheInterface
62
     */
63
    private $fileCache;
64
65
    /**
66
     * Action constructor.
67
     *
68
     * @param FileCacheInterface      $fileCache
69
     * @param XmlFileStorageInterface $xmlFileStorage
70
     *
71
     * @throws FileException
72
     */
73
    public function __construct(FileCacheInterface $fileCache, XmlFileStorageInterface $xmlFileStorage)
74
    {
75
        $this->xmlFileStorage = $xmlFileStorage;
76
        $this->fileCache = $fileCache;
77
78
        $this->loadCache();
79
    }
80
81
    /**
82
     * Loads actions from cache file
83
     *
84
     * @return void
85
     * @throws FileException
86
     */
87
    protected function loadCache()
88
    {
89
        try {
90
            if ($this->fileCache->isExpired(self::CACHE_EXPIRE)
91
                || $this->fileCache->isExpiredDate($this->xmlFileStorage->getFileHandler()->getFileTime())
92
            ) {
93
                $this->mapAndSave();
94
            } else {
95
                $this->actions = $this->fileCache->load();
96
97
                logger('Loaded actions cache', 'INFO');
98
            }
99
        } catch (FileException $e) {
100
            processException($e);
101
102
            $this->mapAndSave();
103
        }
104
    }
105
106
    /**
107
     * @throws FileException
108
     */
109
    protected function mapAndSave()
110
    {
111
        logger('ACTION CACHE MISS', 'INFO');
112
113
        $this->map();
114
        $this->saveCache();
115
    }
116
117
    /**
118
     * Sets an array of actions using id as key
119
     *
120
     * @throws FileException
121
     */
122
    protected function map()
123
    {
124
        $this->actions = [];
125
126
        foreach ($this->load() as $a) {
127
            if (isset($this->actions[$a['id']])) {
128
                throw new RuntimeException('Duplicated action id: ' . $a['id']);
129
            }
130
131
            $action = new ActionData();
132
            $action->id = $a['id'];
133
            $action->name = $a['name'];
134
            $action->text = $a['text'];
135
            $action->route = $a['route'];
136
137
            $this->actions[$action->id] = $action;
138
        }
139
    }
140
141
    /**
142
     * Loads actions from DB
143
     *
144
     * @return ActionData[]
145
     * @throws FileException
146
     */
147
    protected function load()
148
    {
149
        return $this->xmlFileStorage->load('actions')->getItems();
150
    }
151
152
    /**
153
     * Saves actions into cache file
154
     */
155
    protected function saveCache()
156
    {
157
        try {
158
            $this->fileCache->save($this->actions);
159
160
            logger('Saved actions cache', 'INFO');
161
        } catch (FileException $e) {
162
            processException($e);
163
        }
164
    }
165
166
    /**
167
     * Returns an action by id
168
     *
169
     * @param $id
170
     *
171
     * @return ActionData
172
     * @throws ActionNotFoundException
173
     */
174
    public function getActionById($id)
175
    {
176
        if (!isset($this->actions[$id])) {
177
            throw new ActionNotFoundException(__u('Action not found'));
178
        }
179
180
        return $this->actions[$id];
181
    }
182
183
    /**
184
     * @throws FileException
185
     */
186
    public function reset()
187
    {
188
        @unlink(self::ACTIONS_CACHE_FILE);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

188
        /** @scrutinizer ignore-unhandled */ @unlink(self::ACTIONS_CACHE_FILE);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
189
190
        $this->loadCache();
191
    }
192
}