Completed
Push — master ( 4c3b40...b5a957 )
by Paul
04:34
created

session_helper::isTfaRequired()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 23
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 23
rs 6.1404
cc 8
eloc 18
nc 8
nop 4
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
				if (isset($this->modules[$module->get_priority()])) {
96
					throw new module_exception($this->user->lang('TFA_DOUBLE_PRIORITY', $module->get_priority(), get_class($module), get_class($this->modules[$module->get_priority()])));
97
				}
98
				if ($module->is_enabled()) {
99
					$this->modules[$module->get_priority()] = $module;
100
				}
101
			}
102
		}
103
	}
104
105
	/**
106
	 * @param int $user_id
107
	 * @param bool $admin
108
	 * @param array $userdata
109
	 * @param bool $try
110
	 * @return bool
111
	 */
112
	public function isTfaRequired($user_id, $admin = false, $userdata = array(), $try = false)
113
	{
114
		if (sizeof($this->modules) == 0) {
115
			return false;
116
		}
117
		switch ($this->config['tfa_mode'])
118
		{
119
			case session_helper_interface::MODE_DISABLED:
120
				return false;
121
			case session_helper_interface::MODE_NOT_REQUIRED:
122
				return $this->isTfaRegistered($user_id);
123
			case session_helper_interface::MODE_REQUIRED_FOR_ACP_LOGIN:
124
				return $this->do_permission_check($user_id, $userdata, 'a_', $admin, $try);
125
			case session_helper_interface::MODE_REQUIRED_FOR_ADMIN:
126
				return $this->do_permission_check($user_id, $userdata, 'a_', true, $try);
127
			case session_helper_interface::MODE_REQUIRED_FOR_MODERATOR:
128
				return $this->do_permission_check($user_id, $userdata, array('m_', 'a_'), $admin, true);
129
			case session_helper_interface::MODE_REQUIRED:
130
				return true;
131
			default:
132
				return false;
133
		}
134
	}
135
136
	/**
137
	 * Check if the user has two factor authentication added to his account.
138
	 *
139
	 * @param int $user_id
140
	 * @return bool
141
	 */
142
	public function isTfaRegistered($user_id)
143
	{
144
		if (isset($this->user_array[$user_id]))
145
		{
146
			return $this->user_array[$user_id];
147
		}
148
		$sql = 'SELECT COUNT(registration_id) as reg_id FROM ' . $this->registration_table . ' WHERE user_id = ' . (int) $user_id;
149
		$result = $this->db->sql_query($sql);
150
		$row = $this->db->sql_fetchrow($result);
151
		$this->db->sql_freeresult($result);
152
153
		$this->user_array[$user_id] = $row && $row['reg_id'] > 0;
154
		return $this->user_array[$user_id];
155
	}
156
157
	/**
158
	 * Return the userdata for a specific user.
159
	 *
160
	 * @param int $user_id
161
	 * @param array $userdata
162
	 * @return array
163
	 */
164
	private function user_data($user_id, $userdata = array())
165
	{
166
		if (empty($userdata))
167
		{
168
			$sql = 'SELECT * FROM ' . $this->user_table . 'WHERE user_id = ' . (int) $user_id;
169
			$result = $this->db->sql_query($sql);
170
			$userdata = $this->db->sql_fetchrow($result);
171
			$this->db->sql_freeresult($result);
172
		}
173
		return $userdata;
174
	}
175
176
	/**
177
	 * @param int $user_id
178
	 * @param array $userdata
179
	 * @param string|array $permission
180
	 * @param bool $admin
181
	 * @param bool $try
182
	 * @return bool
183
	 */
184
	private function do_permission_check($user_id, $userdata, $permission, $admin, $try)
185
	{
186
		if ($this->isTfaRegistered($user_id))
187
		{
188
			return true;
189
		}
190
		$userdata = $this->user_data($user_id, $userdata);
191
		$at = new auth();
192
		$at->acl($userdata);
193
194
		if (!is_array($permission))
195
		{
196
			$permission = array($permission);
197
		}
198
		foreach ($permission as $perm)
199
		{
200
			if ($at->acl_get($perm) && ($admin || $try))
201
			{
202
				return true;
203
			}
204
		}
205
		return false;
206
	}
207
}
208