Initial commit of TBG SMF Auth
Jeremy D

Jeremy D commited on 2011-09-28 09:24:33
Showing 7 changed files, with 501 additions and 0 deletions.

... ...
@@ -0,0 +1,19 @@
1
+SMF Authenication for The Bug Genie
2
+
3
+Allows The Bug Genie to autenicate with a running SMF installation.
4
+
5
+Author:
6
+Jeremy Darwood
7
+
8
+Copyright:
9
+2011 Jeremy Darwood. All rights reserved.
10
+
11
+Disclaimer:
12
+This package is provided "as is" and without any warranty. Any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the authors be liable to any party for any direct, indirect, incidental, special, exemplary, or consequential damages arising in any way out of the use or misuse of this package.
13
+
14
+License:
15
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
16
+[] Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers.
17
+[] Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution.
18
+[] Names of Author(s) may not be used to endorse or promote products derived from this Software without specific prior written permission.
19
+
... ...
@@ -0,0 +1 @@
1
+SMFAuth|1.0
0 2
\ No newline at end of file
... ...
@@ -0,0 +1,238 @@
1
+<?php
2
+
3
+	/**
4
+	 * SMF Authentication
5
+	 *
6
+	 * @author Jeremy Darwood
7
+	 * @license BSD
8
+	 * @copyright: 2011 Jeremy Darwood
9
+	 *
10
+	 * @version 0.1
11
+	 * @package auth_smf
12
+	 * @subpackage core
13
+	 */
14
+
15
+	/**
16
+	 * SMF Authentication
17
+	 *
18
+	 * @package auth_smf
19
+	 * @subpackage core
20
+	 */
21
+	class SMFAuth extends TBGModule
22
+	{
23
+		protected $_longname = 'SMF Authentication';
24
+		protected $_description = 'Allows authentication with a working SMF 2.0+ installtion';
25
+		protected $_module_config_title = 'SMF Authentication';
26
+		protected $_module_config_description = 'Configure server connection settings';
27
+		protected $_module_version = '0.1';
28
+		protected $_has_config_settings = true;
29
+
30
+		/**
31
+		 * Return an instance of this module
32
+		 *
33
+		 * @return SMF Authentication
34
+		 */
35
+		public static function getModule()
36
+		{
37
+			return TBGContext::getModule('auth_smf');
38
+		}
39
+
40
+		protected function _initialize()
41
+		{
42
+		}
43
+		
44
+		protected function _addRoutes()
45
+		{
46
+			$this->addRoute('smf_login', '/login/smf', 'autoLogin');
47
+
48
+		}
49
+
50
+		protected function _install($scope)
51
+		{
52
+		}
53
+
54
+		protected function _uninstall()
55
+		{
56
+		}
57
+		
58
+		public final function getType()
59
+		{
60
+			return parent::MODULE_AUTH;
61
+		}
62
+
63
+		public function getRoute()
64
+		{
65
+			return TBGContext::getRouting()->generate('smf_authentication_index');
66
+		}
67
+
68
+		/**
69
+		 * Handles saving the settings correctly.
70
+		 *
71
+		 */
72
+		public function postConfigSettings(TBGRequest $request)
73
+		{
74
+			$settings = array('ssi_location', 'login_groups', 'admin_groups', 'enabled_groups', 'access_groups', 'password_salt');
75
+			foreach ($settings as $setting)
76
+			{
77
+				if ($request->hasParameter($setting))
78
+				{
79
+					if (in_array($setting, array('login_groups', 'enabled_groups', 'access_groups', 'admin_groups')))
80
+						$value = serialize($request->getParameter($setting));
81
+					else
82
+						$value = $request->getParameter($setting);
83
+
84
+					$this->saveSetting($setting, $value);
85
+				}
86
+			}
87
+		}
88
+
89
+		/**
90
+		 * Attempts to connect to SMF.
91
+		 * @note: This could in the future detect SMF offline and disable integration.
92
+		 *
93
+		 */
94
+		public function connect()
95
+		{
96
+			$ssi_loc = $this->getSetting('ssi_location');
97
+
98
+			// Ignore errors about SMF trying to be pre-PHP 5.3 compatible.
99
+			try
100
+			{
101
+				require_once($ssi_loc . '/SSI.php');
102
+			}
103
+			catch (Exception $e)
104
+			{
105
+				// This ends SMF from trying to do url rewriting and fixes a loading issue in TBG.
106
+				ob_end_clean();
107
+			}
108
+
109
+			return true;
110
+		}
111
+		
112
+		public function bind()
113
+		{
114
+		}
115
+		
116
+		public function escape($string)
117
+		{
118
+		}
119
+
120
+		/**
121
+		 * Does the actual login by checking you have a valid SMF session.
122
+		 *
123
+		 */
124
+		public function doLogin($username, $password, $mode = 1)
125
+		{
126
+			global $user_info;
127
+
128
+			$ssi_loc = $this->getSetting('ssi_location');
129
+
130
+			// Ignore errors about SMF trying to be pre-PHP 5.3 compatible.
131
+			try
132
+			{
133
+				require_once($ssi_loc . '/SSI.php');
134
+			}
135
+			catch (Exception $e)
136
+			{
137
+				// This ends SMF from trying to do url rewriting and fixes a loading issue in TBG.
138
+				ob_end_clean();
139
+
140
+				// Because of the exception we caught from a deprecated warning, we have to call this manually.
141
+				loadUserSettings();
142
+			}
143
+
144
+			$logingroups = unserialize($this->getSetting('login_groups'));
145
+			$admingroups = unserialize($this->getSetting('admin_groups'));
146
+			$salt = $this->getSetting('password_salt');
147
+			$accessgroups = unserialize($this->getSetting('access_groups'));
148
+
149
+			// Are they even allowed to login?
150
+			if (!empty($logingroups) && !empty($logingroups[0]) && array_intersect($logingroups, $user_info['groups']) == array())
151
+				throw new Exception(TBGContext::getI18n()->__('You are not a member of a group allowed to log in'));
152
+
153
+			// Try to get the user.
154
+			$user = TBGUser::getByUsername($user_info['username']);
155
+			if ($user instanceof TBGUser)
156
+			{
157
+				if (time() - $this->getSetting('smf_auth_updated', $user->getID())> 3600)
158
+				{
159
+					$user->setBuddyname($user_info['username']);
160
+					$user->setRealname($user_info['name']);
161
+					$user->setPassword($user->getJoinedDate() . $user_info['username'] . $salt); // update password
162
+					$user->setEmail($user_info['email']); // update email address
163
+					$user->save();
164
+				}
165
+			}
166
+			else
167
+			{
168
+				// Only do this on the initial login.
169
+				if ($mode == 1)
170
+				{						
171
+					// create user
172
+					$user = new TBGUser();
173
+					$user->setUsername($user_info['username']);
174
+					$user->setRealname($user_info['name']);
175
+					$user->setBuddyname($user_info['username']);
176
+					$user->setEmail($user_info['email']);
177
+					$user->setEnabled();
178
+					$user->setActivated();
179
+					$user->setJoined();
180
+					$user->setPassword($user->getJoinedDate() . $user_info['username'] . $salt);
181
+					$user->save();
182
+				}
183
+				else
184
+					throw new Exception('User does not exist in TBG');
185
+			}
186
+
187
+			// Lets only do this every once in a while.
188
+			if (time() - $this->getSetting('smf_auth_updated', $user->getID())> 3600)
189
+			{
190
+				// Nobody admins the admins.
191
+				if (!empty($admingroups) && array_intersect($admingroups, $user_info['groups']))
192
+				{
193
+					$group = new TBGGroup();
194
+					$group->setID(1);
195
+					$user->setGroup($group);
196
+				}
197
+				else
198
+				{
199
+					$group = new TBGGroup();
200
+					$group->setID(2);
201
+					$user->setGroup($group);
202
+				}
203
+
204
+				// Give them the access they need!
205
+				if (!empty($accessgroups))
206
+				{
207
+					// First, clear out current teams.
208
+					$user->clearTeams();
209
+
210
+					// Then add back the ones they should be in.
211
+					foreach ($accessgroups as $smf_id => $tbg_groups)
212
+						if (in_array($smf_id, $user_info['groups']))
213
+							foreach ($tbg_groups as $tbgroup)
214
+							{
215
+								$team = new TBGTeam();
216
+								$team->setID($tbgroup);
217
+								$user->addToTeam($team);
218
+							}
219
+				}
220
+
221
+				// Update the time stamp so we don't keep doing this every page load.
222
+				$this->saveSetting('smf_auth_updated', time(), $user->getID());
223
+			}
224
+
225
+			// Set the cookies.
226
+			TBGContext::getResponse()->setCookie('tbg3_username', $user_info['username']);
227
+			TBGContext::getResponse()->setCookie('tbg3_password', TBGUser::hashPassword($user->getJoinedDate() . $user_info['username'] . $salt));
228
+
229
+			return TBGUsersTable::getTable()->getByUsername($user_info['username']);
230
+		}
231
+
232
+		public function verifyLogin($username)
233
+		{
234
+			// Most likely not the best idea to pass mode of 1, but it allows the direct login method to work.
235
+			return $this->doLogin($username, 'a', 1);
236
+		}
237
+	}
238
+
... ...
@@ -0,0 +1,68 @@
1
+<?php
2
+	/**
3
+	 * SMF Authentication
4
+	 *
5
+	 * @author Jeremy Darwood
6
+	 * @license BSD
7
+	 * @copyright: 2011 Jeremy Darwood
8
+	 *
9
+	 * @version 0.1
10
+	 * @package auth_smf
11
+	 * @subpackage core
12
+	 */
13
+
14
+	/**
15
+	 * action components for the smf_authentication module
16
+	 */
17
+	class auth_smfActionComponents extends TBGActionComponent
18
+	{
19
+		public function componentSettings()
20
+		{
21
+			global $smcFunc;
22
+
23
+			$ssi_loc = TBGContext::getModule('auth_smf')->getSetting('ssi_location');
24
+
25
+			// New setups we default the group and create a random hash.
26
+			if (empty($ssi_loc))
27
+			{
28
+				$this->smf_groups = array();
29
+				$this->new_salt = substr(sha1(mt_rand() . time()), rand(0, 3), rand(7, 9));
30
+
31
+				return;
32
+			}
33
+
34
+			// Ignore errors about SMF trying to be pre-PHP 5.3 compatible.
35
+			try
36
+			{
37
+				require_once($ssi_loc . '/SSI.php');
38
+			}
39
+			catch (Exception $e)
40
+			{
41
+				// This ends SMF from trying to do url rewriting and fixes a loading issue in TBG.
42
+				ob_end_clean();
43
+			}
44
+
45
+ 			if (!isset($smcFunc, $smcFunc['db_query']))
46
+			{
47
+				$this->smf_groups = array();
48
+				return;
49
+			}
50
+
51
+			// Load up the SMF groups.
52
+			$request = $smcFunc['db_query']('', '
53
+				SELECT id_group, group_name
54
+				FROM {db_prefix}membergroups
55
+				WHERE min_posts = {int:min_posts}',
56
+				array(
57
+					'min_posts' => -1,
58
+			));
59
+
60
+			$smf_groups = array();
61
+			while ($row = $smcFunc['db_fetch_assoc']($request))
62
+				$smf_groups[$row['id_group']] = $row['group_name'];
63
+			$smcFunc['db_free_result']($request);
64
+
65
+			$this->smf_groups = $smf_groups;
66
+		}
67
+	}
68
+
... ...
@@ -0,0 +1,31 @@
1
+<?php
2
+	/**
3
+	 * SMF Authentication
4
+	 *
5
+	 * @author Jeremy Darwood
6
+	 * @license BSD
7
+	 * @copyright: 2011 Jeremy Darwood
8
+	 *
9
+	 * @version 0.1
10
+	 * @package auth_smf
11
+	 * @subpackage core
12
+	 */
13
+
14
+	/**
15
+	 * actions for the smf_authentication module
16
+	 */
17
+	class auth_smfActions extends TBGAction
18
+	{
19
+
20
+		/**
21
+		 * Test the SMF connection
22
+		 *
23
+		 * @param TBGRequest $request
24
+		 */
25
+		public function runAutoLogin(TBGRequest $request)
26
+		{
27
+			TBGContext::getModule('auth_smf')->verifyLogin($request->getParameter('tbg3_username'));
28
+
29
+			$this->forward(TBGContext::getRouting()->generate('home'));
30
+		}
31
+	}
... ...
@@ -0,0 +1 @@
1
+SMF Authentication - Allows authentication against a working SMF 2.0 installation.
0 2
\ No newline at end of file
... ...
@@ -0,0 +1,143 @@
1
+<?php
2
+$login_groups = $module->getSetting('login_groups');
3
+$login_groups = !empty($login_groups) ? unserialize($login_groups) : array();
4
+
5
+$admin_groups = $module->getSetting('admin_groups');
6
+$admin_groups = !empty($admin_groups) ? unserialize($admin_groups) : array();
7
+
8
+$enabled_groups = $module->getSetting('enabled_groups');
9
+$enabled_groups = !empty($enabled_groups) ? unserialize($enabled_groups) : array();
10
+
11
+$access_groups = $module->getSetting('access_groups');
12
+$access_groups = !empty($access_groups) ? unserialize($access_groups) : array();
13
+
14
+$TBGgroups = TBGTeam::getAll();
15
+
16
+
17
+echo '<p>', __('Use this page to set up the connection details for your SMF Authenication. It is highly recommended that you read the online help before use, as misconfiguration may prevent you from accessing configuration pages to rectify issues.'), '</p>
18
+<div class="rounded_box yellow" style="margin-top: 5px">
19
+	<div class="header">', __('Important information'), '</div>
20
+	<p>', __('When you enable SMF Authenication as your authentication backend in Authentication configuration, you will lose access to all accounts which do not also exist in your SMF installation. This may mean you lose administrative access.'), '</p>
21
+	<p style="font-weight: bold; padding-top: 5px">', __('To resolve this issue, create a user with the same username as exists in SMF and make that one an administrator on TBG.'), '</p>
22
+</div>
23
+<form accept-charset="', TBGContext::getI18n()->getCharset(), '" action="', make_url('configure_module', array('config_module' => $module->getName())), '" enctype="multipart/form-data" method="post">
24
+	<div class="rounded_box borderless mediumgrey', $access_level == TBGSettings::ACCESS_FULL ? ' cut_bottom' : '', '" style="margin: 10px 0 0 0; width: 700px;', $access_level == TBGSettings::ACCESS_FULL ? ' border-bottom: 0;' : '', '">
25
+		<div class="header">', __('Connection details'), '</div>
26
+		<table style="width: 680px;" class="padded_table" cellpadding=0 cellspacing=0 id="smf_settings_table">
27
+			<tr>
28
+				<td style="padding: 5px;"><label for="ssi_location">', __('SSI Location'), '</label></td>
29
+				<td><input type="text" name="ssi_location" id="ssi_location" value="', $module->getSetting('ssi_location'), '" style="width: 100%;"></td>
30
+			</tr>
31
+			<tr>
32
+				<td class="config_explanation" colspan="2">', __('Location of your SMF 2.0+ installtion as absolute path on your server ie: /home/user/public_html/smf'), '</td>
33
+			</tr>
34
+
35
+			<tr>
36
+				<td style="padding: 5px;"><label for="password_salt">', __('Password Salt'), '</label></td>
37
+				<td><input type="text" name="password_salt" id="password_salt" value="';
38
+
39
+$salt = $module->getSetting('password_salt');
40
+if (empty($salt) && isset($new_salt))
41
+	echo $new_salt;
42
+else
43
+	echo $salt;
44
+
45
+	echo '" style="width: 100%;"></td>
46
+			</tr>
47
+			<tr>
48
+				<td class="config_explanation" colspan="2">', __('A random unique set of characters'), '</td>
49
+			</tr>
50
+
51
+
52
+			<tr>
53
+				<td style="padding: 5px;"><label for="login_groups">', __('Login Groups'), '</label></td>
54
+				<td><select name="login_groups[]" id="login_groups" multiple="multiple" style="width: 100%; height: 10em;">
55
+					<option value="0"', (empty($login_groups) || in_array(0, $login_groups)  ? ' selected="selected"' : ''), '>All groups</option>';
56
+
57
+foreach ($smf_groups as $id_group => $name)
58
+	echo '
59
+					<option value="', $id_group, '"', (!empty($login_groups) && in_array($id_group, $login_groups) ? ' selected="selected"' : ''), '>', $name, '</option>';
60
+
61
+echo '</select></td>
62
+			</tr>
63
+			<tr>
64
+				<td class="config_explanation" colspan="2">', __('Limit logins to selected groups, all others are annoymous users'), '</td>
65
+			</tr>
66
+
67
+
68
+			<tr>
69
+				<td style="padding: 5px;"><label for="admin_groups">', __('Administrator Groups'), '</label></td>
70
+				<td><select name="admin_groups[]" id="admin_groups" multiple="multiple" style="width: 100%; height: 10em;">';
71
+
72
+foreach ($smf_groups as $id_group => $name)
73
+	echo '
74
+					<option value="', $id_group, '"', (!empty($admin_groups) && in_array($id_group, $admin_groups) ? ' selected="selected"' : ''), '>', $name, '</option>';
75
+
76
+echo '</select></td>
77
+			</tr>
78
+			<tr>
79
+				<td class="config_explanation" colspan="2">', __('Limit logins to selected groups, all others are annoymous users'), '</td>
80
+			</tr>
81
+
82
+
83
+			<tr>
84
+				<td style="padding: 5px;"><label for="enabled_groups">', __('Enabled Access Groups'), '</label></td>
85
+				<td><select name="enabled_groups[]" id="enabled_groups" multiple="multiple" style="width: 100%; height: 10em;">';
86
+
87
+foreach ($smf_groups as $id_group => $name)
88
+	echo '
89
+					<option value="', $id_group, '"', (!empty($enabled_groups) && in_array($id_group, $enabled_groups) ? ' selected="selected"' : ''), '>', $name, '</option>';
90
+
91
+echo '</select></td>
92
+			</tr>
93
+			<tr>
94
+				<td class="config_explanation" colspan="2">', __('Select groups you wish to grant groups/teams on TBG'), '</td>
95
+			</tr>
96
+		</table>
97
+	</div>';
98
+
99
+if ($access_level == TBGSettings::ACCESS_FULL)
100
+	echo '
101
+	<div class="rounded_box iceblue borderless cut_top" style="margin: 0 0 5px 0; width: 700px; border-top: 0; padding: 8px 5px 2px 5px; height: 25px;">
102
+		<div style="float: left; font-size: 13px; padding-top: 2px;">', __('Click "%save%" to save the settings', array('%save%' => __('Save'))), '</div>
103
+		<input type="submit" id="submit_settings_button" style="float: right; padding: 0 10px 0 10px; font-size: 14px; font-weight: bold;" value="', __('Save'), '">
104
+	</div>';
105
+
106
+echo '
107
+	<div class="rounded_box borderless mediumgrey', $access_level == TBGSettings::ACCESS_FULL ? ' cut_bottom' : '', '" style="margin: 10px 0 0 0; width: 700px;', $access_level == TBGSettings::ACCESS_FULL ? ' border-bottom: 0;' : '', '">
108
+		<div class="header">', __('Group Access'), '</div>
109
+		<table style="width: 680px;" class="padded_table" cellpadding=0 cellspacing=0 id="smf_settings_table">';
110
+
111
+if (!empty($enabled_groups))
112
+foreach ($enabled_groups as $smf_id)
113
+{
114
+	// Doesn't exist anymore, we can't save those settings.
115
+	if (!isset($smf_groups[$smf_id]))
116
+		continue;
117
+
118
+	echo '
119
+			<tr>
120
+				<td style="padding: 5px;"><label for="access_groups[', $smf_id, ']">SMF: ', $smf_groups[$smf_id], '</label></td>
121
+				<td><select name="access_groups[', $smf_id, '][]" id="access_groups[', $smf_id, ']" multiple="multiple" style="width: 100%; height: 10em;">';
122
+
123
+	foreach ($TBGgroups as $id_group => $group)
124
+		echo '
125
+					<option value="', $id_group, '"', (!empty($access_groups[$smf_id]) && in_array($id_group, $access_groups[$smf_id]) ? ' selected="selected"' : ''), '>', $group->getName(), '</option>';
126
+
127
+	echo '</select></td>
128
+			</tr>';
129
+}
130
+
131
+echo '
132
+		</table>
133
+	</div>';
134
+
135
+if ($access_level == TBGSettings::ACCESS_FULL)
136
+	echo '
137
+	<div class="rounded_box iceblue borderless cut_top" style="margin: 0 0 5px 0; width: 700px; border-top: 0; padding: 8px 5px 2px 5px; height: 25px;">
138
+		<div style="float: left; font-size: 13px; padding-top: 2px;">', __('Click "%save%" to save the settings', array('%save%' => __('Save'))), '</div>
139
+		<input type="submit" id="submit_settings_button" style="float: right; padding: 0 10px 0 10px; font-size: 14px; font-weight: bold;" value="', __('Save'), '">
140
+	</div>';
141
+
142
+echo '
143
+</form>';
0 144
\ No newline at end of file
1 145