Completed
Push — master ( b5a957...040c1d )
by Paul
03:38
created

session_helper::findModule()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.4286
cc 3
eloc 5
nc 3
nop 1
1
<?php
2
/**
3
*
4
* 2FA extension for the phpBB Forum Software package.
5
*
6
* @copyright (c) 2015 Paul Sohier
7
* @license GNU General Public License, version 2 (GPL-2.0)
8
*
9
*/
10
11
namespace paul999\tfa\helper;
12
13
use paul999\tfa\exceptions\module_exception;
14
use paul999\tfa\modules\module_interface;
15
use phpbb\auth\auth;
16
use phpbb\config\config;
17
use phpbb\db\driver\driver_interface;
18
use phpbb\di\service_collection;
19
use phpbb\user;
20
21
/**
22
 * helper method which is used to detect if a user needs to use 2FA
23
 */
24
class session_helper implements session_helper_interface
25
{
26
27
	/**
28
	 * @var driver_interface
29
	 */
30
	private $db;
31
32
	/**
33
	 * @var config
34
	 */
35
	private $config;
36
37
	/**
38
	 * @var user
39
	 */
40
	private $user;
41
42
	/**
43
	 * @var array
44
	 */
45
	private $modules;
46
47
	/**
48
	 * @var string
49
	 */
50
	private $registration_table;
51
52
	/**
53
	 * @var string
54
	 */
55
	private $user_table;
56
57
	/**
58
	 * @var array
59
	 */
60
	private $user_array = array();
61
62
	/**
63
	 * Constructor
64
	 *
65
	 * @access public
66
	 * @param driver_interface $db
67
	 * @param config $config
68
	 * @param user $user
69
	 * @param service_collection $modules
70
	 * @param string $registration_table
71
	 * @param string $user_table
72
	 */
73
	public function __construct(driver_interface $db, config $config, user $user, service_collection $modules, $registration_table, $user_table)
74
	{
75
		$this->db					= $db;
76
		$this->user_array			= $user;
0 ignored issues
show
Documentation Bug introduced by
It seems like $user of type object<phpbb\user> is incompatible with the declared type array of property $user_array.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
77
		$this->config				= $config;
78
		$this->registration_table	= $registration_table;
79
		$this->user_table			= $user_table;
80
81
		$this->validateModules($modules);
82
	}
83
84
	/**
85
	 * Register the tagged modules if they are enabled.
86
	 * @param service_collection $modules
87
	 */
88
	private function validateModules(service_collection $modules) {
89
		/**
90
		 * @var module_interface $module
91
		 */
92
		foreach ($modules as $module) {
93
			if ($module instanceof module_interface) {
94
				// Only add them if they are actually a module_interface.
95
				$priority = $module->get_priority($this->user->data['user_id']);
0 ignored issues
show
Bug introduced by
The property data cannot be accessed from this context as it is declared private in class phpbb\session.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
96
				if (isset($this->modules[$module->get_priority()])) {
97
					throw new module_exception($this->user->lang('TFA_DOUBLE_PRIORITY', $priority, get_class($module), get_class($this->modules[$priority])));
98
				}
99
				if ($module->is_enabled()) {
100
					$this->modules[$priority] = $module;
101
				}
102
			}
103
		}
104
	}
105
106
	/**
107
	 * @param $requested_module
108
	 * @return null|module_interface
109
	 */
110
	public function findModule($requested_module)
111
	{
112
		/**
113
		 * @var module_interface $module
114
		 */
115
		foreach ($this->getModules() as $module)
116
		{
117
			if (get_class($module) == $requested_module)
118
			{
119
				return $module;
120
			}
121
		}
122
		return null;
123
	}
124
125
	/**
126
	 * @return array
127
	 */
128
	public function getModules() {
129
		return $this->modules;
130
	}
131
132
	/**
133
	 * @param int $user_id
134
	 * @param bool $admin
135
	 * @param array $userdata
136
	 * @param bool $try
137
	 * @return bool
138
	 */
139
	public function isTfaRequired($user_id, $admin = false, $userdata = array(), $try = false)
140
	{
141
		if (sizeof($this->modules) == 0) {
142
			return false;
143
		}
144
		switch ($this->config['tfa_mode'])
145
		{
146
			case session_helper_interface::MODE_DISABLED:
147
				return false;
148
			case session_helper_interface::MODE_NOT_REQUIRED:
149
				return $this->isTfaRegistered($user_id);
150
			case session_helper_interface::MODE_REQUIRED_FOR_ACP_LOGIN:
151
				return $this->do_permission_check($user_id, $userdata, 'a_', $admin, $try);
152
			case session_helper_interface::MODE_REQUIRED_FOR_ADMIN:
153
				return $this->do_permission_check($user_id, $userdata, 'a_', true, $try);
154
			case session_helper_interface::MODE_REQUIRED_FOR_MODERATOR:
155
				return $this->do_permission_check($user_id, $userdata, array('m_', 'a_'), $admin, true);
156
			case session_helper_interface::MODE_REQUIRED:
157
				return true;
158
			default:
159
				return false;
160
		}
161
	}
162
163
	/**
164
	 * Check if the user has two factor authentication added to his account.
165
	 *
166
	 * @param int $user_id
167
	 * @return bool
168
	 */
169
	public function isTfaRegistered($user_id)
170
	{
171
		if (isset($this->user_array[$user_id]))
172
		{
173
			return $this->user_array[$user_id];
174
		}
175
176
		/**
177
		 * @var int $priority
178
		 * @var module_interface $module
179
		 */
180
		foreach ($this->modules as $priority => $module) {
181
			$this->user_array[$user_id] = $this->user[$user_id] || $module->is_usable($user_id);
182
		}
183
		return $this->user_array[$user_id];
184
	}
185
186
	/**
187
	 * Return the userdata for a specific user.
188
	 *
189
	 * @param int $user_id
190
	 * @param array $userdata
191
	 * @return array
192
	 */
193
	private function user_data($user_id, $userdata = array())
194
	{
195
		if (empty($userdata))
196
		{
197
			$sql = 'SELECT * FROM ' . $this->user_table . 'WHERE user_id = ' . (int) $user_id;
198
			$result = $this->db->sql_query($sql);
199
			$userdata = $this->db->sql_fetchrow($result);
200
			$this->db->sql_freeresult($result);
201
		}
202
		return $userdata;
203
	}
204
205
	/**
206
	 * @param int $user_id
207
	 * @param array $userdata
208
	 * @param string|array $permission
209
	 * @param bool $admin
210
	 * @param bool $try
211
	 * @return bool
212
	 */
213
	private function do_permission_check($user_id, $userdata, $permission, $admin, $try)
214
	{
215
		if ($this->isTfaRegistered($user_id))
216
		{
217
			return true;
218
		}
219
		$userdata = $this->user_data($user_id, $userdata);
220
		$at = new auth();
221
		$at->acl($userdata);
222
223
		if (!is_array($permission))
224
		{
225
			$permission = array($permission);
226
		}
227
		foreach ($permission as $perm)
228
		{
229
			if ($at->acl_get($perm) && ($admin || $try))
230
			{
231
				return true;
232
			}
233
		}
234
		return false;
235
	}
236
}
237