Skip to content

Commit fabe9ce

Browse files
committed
Integrate multis into main accounts
The purpose of this is twofold: * Allow players to navigate their main/multi accounts without having to log in and out. * Synchronize things between the two accounts when it doesn't make sense to have two values (i.e. e-mail address, user preferences, bans, etc.). Add a new table `account_link_login`, which associates a `login_id` (the new primary key replacing `account_id` in the `account` table) with an `account_id` (the primary key of `account_link_login`). Each "login" (`account`) can be associated with multiple "accounts" (`account_link_login`). This is a little confusing, since ideally the `account` table would be renamed `login` (or similar), but we are probably a bit too heavily invested in the original infrastructure to completely change it now. We provide a way on the "Play Game" page to switch to/create multis, including an option to link an existing account as a multi. Adds two helper methods to SmrAccount: * getLinkedAccountList - finds all accounts associated with login * getLinkedAccount - returns an account if it is associated with login
1 parent 43e9568 commit fabe9ce

10 files changed

+210
-10
lines changed
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Rename `account.account_id` to `account.login_id`
2+
ALTER TABLE account CHANGE `account_id` `login_id` smallint(6) unsigned NOT NULL AUTO_INCREMENT;
3+
4+
-- Add `account_link_login` table
5+
CREATE TABLE account_link_login (
6+
`account_id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
7+
`login_id` smallint(6) unsigned NOT NULL,
8+
PRIMARY KEY (`account_id`)
9+
) ENGINE=MyISAM AUTO_INCREMENT=1;
10+
11+
-- Fill in `account_link_login` from the rows of `account`,
12+
-- setting account_id = login_id.
13+
INSERT INTO account_link_login (account_id, login_id)
14+
SELECT login_id, login_id as account_id FROM account;

engine/Default/game_play.php

+32
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,41 @@
88
$template->assign('Message',$var['msg']);
99
}
1010

11+
// ***************************************
12+
// ** Accounts
13+
// ***************************************
14+
15+
if (isset($var['switch_account_id'])) {
16+
// Override default account (and do sanity checks)
17+
$account = $account->getLinkedAccount($var['switch_account_id']);
18+
SmrSession::updateAccount($account->getAccountID());
19+
}
20+
21+
// Get linked accounts (order the current account first, for simplicity)
22+
$linkedAccounts = $account->getLinkedAccountList();
23+
if (key($linkedAccounts) != $account->getAccountID()) {
24+
$linkedAccounts = array_reverse($linkedAccounts);
25+
}
26+
$template->assign('AccountLabels', array_values($linkedAccounts));
27+
28+
if (count($linkedAccounts) == SmrAccount::MAX_LINKED_ACCOUNTS) {
29+
end($linkedAccounts);
30+
$otherAccountID = key($linkedAccounts);
31+
$switchContainer = create_container('skeleton.php', 'game_play.php');
32+
$switchContainer['switch_account_id'] = $otherAccountID;
33+
} else {
34+
$switchContainer = create_container('skeleton.php', 'switch_account_create.php');
35+
}
36+
$template->assign('SwitchAccountHREF', SmrSession::getNewHREF($switchContainer));
37+
38+
1139
$template->assign('UserRankingLink',SmrSession::getNewHREF(create_container('skeleton.php', 'rankings_view.php')));
1240
$template->assign('UserRankName',$account->getRankName());
1341

42+
// ***************************************
43+
// ** Play Game
44+
// ***************************************
45+
1446
$games = array();
1547
$games['Play'] = array();
1648
$game_id_list = array();
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
$template->assign('PageTopic', 'Create Multi Account');
4+
5+
$container = create_container('switch_account_create_processing.php');
6+
$container['action'] = 'Create';
7+
$template->assign('CreateHREF', SmrSession::getNewHREF($container));
8+
$container['action'] = 'Link';
9+
$template->assign('LinkHREF', SmrSession::getNewHREF($container));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
if (count($account->getLinkedAccountList()) >= SmrAccount::MAX_LINKED_ACCOUNTS) {
4+
create_error('Cannot create another linked account!');
5+
}
6+
7+
if ($var['action'] == 'Create') {
8+
// Create a new multi account
9+
$db->query('INSERT INTO account_link_login (login_id) VALUES ('.$account->getLoginID().')');
10+
$newAccountID = $db->getInsertID();
11+
12+
$container = create_container('skeleton.php', 'game_play.php');
13+
$container['switch_account_id'] = $newAccountID;
14+
15+
} elseif ($var['action'] == 'Link') {
16+
$login = $_REQUEST['multi_account_login'];
17+
$password = $_REQUEST['multi_account_password'];
18+
19+
// Link an existing multi account
20+
$db->query('SELECT login_id FROM account ' .
21+
'WHERE login = '.$db->escapeString($login).' AND ' .
22+
'password = '.$db->escapeString(md5($password)).' LIMIT 1');
23+
if (!$db->nextRecord()) {
24+
create_error('Could not find a matching account. If you believe this is an error, please contact an admin.');
25+
}
26+
$multiLoginID = $db->getInt('login_id');
27+
28+
// Sanity check: multi ID > current ID
29+
if ($multiLoginID <= $account->getLoginID()) {
30+
create_error('Multi account must be newer than main account!');
31+
}
32+
33+
// update the account_link_login to reflect the new login association
34+
// For existing accounts login_id == account_id
35+
$db->query('UPDATE account_link_login SET login_id='.$db->escapeNumber($account->getLoginID()).' WHERE account_id='.$db->escapeNumber($multiLoginID));
36+
37+
// delete the old login
38+
$db->query('DELETE FROM account WHERE login_id='.$db->escapeNumber($multiLoginID));
39+
40+
41+
}

htdocs/login_create.php

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
<h1>Create Login</h1>
3232
<p align='justify'>
3333
Creating multiple logins is not allowed.
34-
<a href='https://wiki.smrealms.de/rules' target="_blank" style='font-weight:bold;'>Click HERE</a> for more information.
3534
</p>
3635

3736
<form action='login_create_processing.php' method='POST'>

htdocs/login_processing.php

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
}
7676

7777
$db->query('SELECT account_id,old_account_id FROM account ' .
78+
'JOIN account_link_login USING (login_id) ' .
7879
'WHERE login = '.$db->escapeString($login).' AND ' .
7980
'password = '.$db->escapeString(md5($password)).' LIMIT 1');
8081
if ($db->nextRecord()) {

lib/Default/AbstractSmrAccount.class.inc

+46-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ abstract class AbstractSmrAccount {
33
const USER_RANKINGS_EACH_STAT_POW = .9;
44
const USER_RANKINGS_TOTAL_SCORE_POW = .3;
55
const USER_RANKINGS_RANK_BOUNDARY = 5.2;
6+
const MAX_LINKED_ACCOUNTS = 2;
7+
68
protected static $USER_RANKINGS_SCORE = array(
79
// [Stat, a, b]
810
// Used as: pow(Stat * a, USER_RANKINGS_EACH_STAT_POW) * b
@@ -35,6 +37,7 @@ abstract class AbstractSmrAccount {
3537
protected $db;
3638

3739
protected $account_id;
40+
protected $login_id;
3841
protected $login;
3942
protected $password;
4043
protected $email;
@@ -91,7 +94,7 @@ abstract class AbstractSmrAccount {
9194

9295
public static function &getAccountByName($login,$forceUpdate = false) {
9396
$db = new SmrMySqlDatabase();
94-
$db->query('SELECT account_id FROM account WHERE login = '.$db->escapeString($login).' LIMIT 1');
97+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE login = '.$db->escapeString($login).' LIMIT 1');
9598
if($db->nextRecord())
9699
return self::getAccount($db->getField('account_id'),$forceUpdate);
97100
$return = null;
@@ -100,7 +103,7 @@ abstract class AbstractSmrAccount {
100103

101104
public static function &getAccountByHofName($hofName,$forceUpdate = false) {
102105
$db = new SmrMySqlDatabase();
103-
$db->query('SELECT account_id FROM account WHERE hof_name = '.$db->escapeString($hofName).' LIMIT 1');
106+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE hof_name = '.$db->escapeString($hofName).' LIMIT 1');
104107
if($db->nextRecord())
105108
return self::getAccount($db->getField('account_id'),$forceUpdate);
106109
$return = null;
@@ -109,7 +112,7 @@ abstract class AbstractSmrAccount {
109112

110113
public static function getAccountByDiscordId($id, $forceUpdate=false) {
111114
$db = new SmrMySqlDatabase();
112-
$db->query('SELECT account_id FROM account where discord_id = '.$db->escapeString($id).' LIMIT 1');
115+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) where discord_id = '.$db->escapeString($id).' LIMIT 1');
113116
if ($db->nextRecord()) {
114117
return self::getAccount($db->getField('account_id'), $forceUpdate);
115118
} else {
@@ -119,7 +122,7 @@ abstract class AbstractSmrAccount {
119122

120123
public static function &getAccountByIrcNick($nick, $forceUpdate = false) {
121124
$db = new SmrMySqlDatabase();
122-
$db->query('SELECT account_id FROM account WHERE irc_nick = '.$db->escapeString($nick).' LIMIT 1');
125+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE irc_nick = '.$db->escapeString($nick).' LIMIT 1');
123126
if($db->nextRecord())
124127
return self::getAccount($db->getField('account_id'), $forceUpdate);
125128
$return = null;
@@ -128,7 +131,7 @@ abstract class AbstractSmrAccount {
128131

129132
public static function &findAccountByIrcNick($nick, $forceUpdate = false) {
130133
$db = new SmrMySqlDatabase();
131-
$db->query('SELECT account_id FROM account WHERE irc_nick LIKE '.$db->escapeString($nick).' LIMIT 2');
134+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE irc_nick LIKE '.$db->escapeString($nick).' LIMIT 2');
132135
if($db->getNumRows() > 1) {
133136
$return = true;
134137
return $return;
@@ -171,12 +174,13 @@ abstract class AbstractSmrAccount {
171174

172175
function __construct($accountID) {
173176
$this->db = new SmrMySqlDatabase();
174-
$this->db->query('SELECT * FROM account WHERE account_id = '.$this->db->escapeNumber($accountID).' LIMIT 1');
177+
$this->db->query('SELECT * FROM account JOIN account_link_login USING (login_id) WHERE account_id = '.$this->db->escapeNumber($accountID).' LIMIT 1');
175178

176179
if ($this->db->nextRecord()) {
177180
$row = $this->db->getRow();
178181
$this->account_id = $row['account_id'];
179182

183+
$this->login_id = $row['login_id'];
180184
$this->login = $row['login'];
181185
$this->password = $row['password'];
182186
$this->email = $row['email'];
@@ -298,7 +302,7 @@ abstract class AbstractSmrAccount {
298302
', friendly_colour = ' . $this->db->escapeString($this->friendlyColour, true, true).
299303
', neutral_colour = ' . $this->db->escapeString($this->neutralColour, true, true).
300304
', enemy_colour = ' . $this->db->escapeString($this->enemyColour, true, true).
301-
' WHERE account_id = '.$this->db->escapeNumber($this->account_id).' LIMIT 1');
305+
' WHERE login_id = '.$this->db->escapeNumber($this->login_id).' LIMIT 1');
302306
$this->hasChanged = false;
303307
}
304308

@@ -741,6 +745,10 @@ abstract class AbstractSmrAccount {
741745
return false;
742746
}
743747

748+
public function getLoginID() {
749+
return $this->login_id;
750+
}
751+
744752
public function getLogin() {
745753
return $this->login;
746754
}
@@ -1291,6 +1299,36 @@ abstract class AbstractSmrAccount {
12911299
public function getPersonalHofHREF() {
12921300
return SmrSession::getNewHREF(create_container('skeleton.php','hall_of_fame_player_detail.php',array('account_id' => $this->getAccountID())));
12931301
}
1294-
}
12951302

1303+
/**
1304+
* Return an array of account_ids associated with this login.
1305+
* We assume that each login has only MAX_LINKED_ACCOUNTS accounts and
1306+
* that the smallest ID (created first) is the primary account_id.
1307+
*/
1308+
public function getLinkedAccountList() {
1309+
$this->db->query('SELECT account_id FROM account_link_login WHERE login_id='.$this->db->escapeNumber($this->getLoginID()).' ORDER BY account_id ASC LIMIT '.$this->db->escapeNumber(self::MAX_LINKED_ACCOUNTS));
1310+
$result = array();
1311+
while ($this->db->nextRecord()) {
1312+
$name = count($result) == 0 ? 'Main' : 'Multi';
1313+
$result[$this->db->getInt('account_id')] = $name;
1314+
}
1315+
return $result;
1316+
}
1317+
1318+
/**
1319+
* Returns another account that is linked to this login.
1320+
*/
1321+
public function getLinkedAccount($accountID) {
1322+
if ($accountID == $this->getAccountID()) {
1323+
return $this;
1324+
}
1325+
$linkedAccounts = $this->getLinkedAccountList();
1326+
if (isset($linkedAccounts[$accountID])) {
1327+
return $this::getAccount($accountID);
1328+
} else {
1329+
throw new Exception('No linked account with ID: ' . $accountID);
1330+
}
1331+
}
1332+
1333+
}
12961334
?>

lib/Default/SmrSession.class.inc

+11
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,17 @@ class SmrSession {
253253
$db = new SmrMySqlDatabase();
254254
}
255255

256+
/**
257+
* Updates the `account_id` attribute of the session.
258+
*/
259+
public static function updateAccount($accountID) {
260+
if (self::$account_id == $accountID) {
261+
return;
262+
}
263+
self::$account_id = $accountID;
264+
self::$db->query('UPDATE active_session SET account_id=' . self::$db->escapeNumber(self::$account_id) . ' WHERE session_id=' . self::$db->escapeString(self::$session_id));
265+
}
266+
256267
public static function updateSN() {
257268
self::$db = new SmrSessionMySqlDatabase();
258269
if(!USING_AJAX)

templates/Default/engine/Default/game_play.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
echo $Message; ?><br /><br /><?php
77
} ?>
88

9+
10+
<b class="yellow">Accounts</b><br />
11+
You are on your <?php echo $AccountLabels[0]; ?> account.
12+
<a href="<?php echo $SwitchAccountHREF; ?>">[Switch to <?php echo $AccountLabels[1]; ?>]</a>
13+
<br /><br />
14+
915
<a href="<?php echo $ThisAccount->getUserRankingHREF(); ?>"><b class="yellow">Rankings</b></a>
1016
<br />You are ranked as <?php $this->doAn($ThisAccount->getRankName()); ?> <span style="font-size:125%;color:greenyellow;"><?php echo $UserRankName ?></span> player.<br /><br />
1117

@@ -133,4 +139,4 @@
133139
else {
134140
?><p>There are no previous games.</p><?php
135141
} ?>
136-
</div>
142+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<h2>Create New Multi Account</h2>
2+
<p>All players are allowed a second ("multi") account in addition to their
3+
primary ("main") account. It is created only through this interface, so
4+
<b>DO NOT</b> create a second login!</p>
5+
6+
<p>There are very specific rules about how you can use you multi account.
7+
<a href='https://wiki.smrealms.de/rules' target="_blank" style='font-weight:bold;'>Click HERE</a> for more information.</p>
8+
9+
<p>If you have an existing multi account, please link it below instead of
10+
creating a new one.</p>
11+
12+
<div class="buttonA">
13+
<a class="buttonA" href="<?php echo $CreateHREF; ?>">Create Multi</a>
14+
</div>
15+
<br /><br /><br />
16+
17+
<h2>Link Existing Multi Account</h2>
18+
19+
<p>If you are logged in on an existing multi account, <b>DO NOT CONTINUE</b>.
20+
Instead, please log into your main account and link your multi account from
21+
there.</p>
22+
23+
<p><span class="bold red">WARNING</span>: When you do this, your multi login
24+
will be deleted. This action cannot be undone! However, your multi account
25+
data will then be associated as the multi of the account you are currently
26+
logged in as.</p>
27+
28+
<p>If you are at all unsure how to procede, please contact an admin for
29+
assistance.</p>
30+
31+
<form id="LinkOldAccountForm" method="POST" action="<?php echo $LinkHREF; ?>">
32+
<table>
33+
<tr>
34+
<th colspan="2">Enter Existing Account Credentials</th>
35+
</tr>
36+
<tr>
37+
<td>Login:</td>
38+
<td><input type="text" name="multi_account_login"/></td>
39+
</tr>
40+
<tr>
41+
<td>Password:</td>
42+
<td><input type="password" name="multi_account_password"/></td>
43+
</tr>
44+
<tr>
45+
<td></td>
46+
<td><input type="submit" name="action" value="Link Account" id="InputFields" /></td>
47+
</tr>
48+
</table>
49+
</form>

0 commit comments

Comments
 (0)