Skip to content

Commit 090ed22

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 8eebfaf commit 090ed22

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;
@@ -110,7 +113,7 @@ abstract class AbstractSmrAccount {
110113

111114
public static function &getAccountByHofName($hofName,$forceUpdate = false) {
112115
$db = new SmrMySqlDatabase();
113-
$db->query('SELECT account_id FROM account WHERE hof_name = '.$db->escapeString($hofName).' LIMIT 1');
116+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE hof_name = '.$db->escapeString($hofName).' LIMIT 1');
114117
if($db->nextRecord())
115118
return self::getAccount($db->getField('account_id'),$forceUpdate);
116119
$return = null;
@@ -119,7 +122,7 @@ abstract class AbstractSmrAccount {
119122

120123
public static function getAccountByDiscordId($id, $forceUpdate=false) {
121124
$db = new SmrMySqlDatabase();
122-
$db->query('SELECT account_id FROM account where discord_id = '.$db->escapeString($id).' LIMIT 1');
125+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) where discord_id = '.$db->escapeString($id).' LIMIT 1');
123126
if ($db->nextRecord()) {
124127
return self::getAccount($db->getField('account_id'), $forceUpdate);
125128
} else {
@@ -129,7 +132,7 @@ abstract class AbstractSmrAccount {
129132

130133
public static function &getAccountByIrcNick($nick, $forceUpdate = false) {
131134
$db = new SmrMySqlDatabase();
132-
$db->query('SELECT account_id FROM account WHERE irc_nick = '.$db->escapeString($nick).' LIMIT 1');
135+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE irc_nick = '.$db->escapeString($nick).' LIMIT 1');
133136
if($db->nextRecord())
134137
return self::getAccount($db->getField('account_id'), $forceUpdate);
135138
$return = null;
@@ -138,7 +141,7 @@ abstract class AbstractSmrAccount {
138141

139142
public static function &findAccountByIrcNick($nick, $forceUpdate = false) {
140143
$db = new SmrMySqlDatabase();
141-
$db->query('SELECT account_id FROM account WHERE irc_nick LIKE '.$db->escapeString($nick).' LIMIT 2');
144+
$db->query('SELECT account_id FROM account JOIN account_link_login USING (login_id) WHERE irc_nick LIKE '.$db->escapeString($nick).' LIMIT 2');
142145
if($db->getNumRows() > 1) {
143146
$return = true;
144147
return $return;
@@ -181,12 +184,13 @@ abstract class AbstractSmrAccount {
181184

182185
function __construct($accountID) {
183186
$this->db = new SmrMySqlDatabase();
184-
$this->db->query('SELECT * FROM account WHERE account_id = '.$this->db->escapeNumber($accountID).' LIMIT 1');
187+
$this->db->query('SELECT * FROM account JOIN account_link_login USING (login_id) WHERE account_id = '.$this->db->escapeNumber($accountID).' LIMIT 1');
185188

186189
if ($this->db->nextRecord()) {
187190
$row = $this->db->getRow();
188191
$this->account_id = $row['account_id'];
189192

193+
$this->login_id = $row['login_id'];
190194
$this->login = $row['login'];
191195
$this->password = $row['password'];
192196
$this->email = $row['email'];
@@ -308,7 +312,7 @@ abstract class AbstractSmrAccount {
308312
', friendly_colour = ' . $this->db->escapeString($this->friendlyColour, true, true).
309313
', neutral_colour = ' . $this->db->escapeString($this->neutralColour, true, true).
310314
', enemy_colour = ' . $this->db->escapeString($this->enemyColour, true, true).
311-
' WHERE account_id = '.$this->db->escapeNumber($this->account_id).' LIMIT 1');
315+
' WHERE login_id = '.$this->db->escapeNumber($this->login_id).' LIMIT 1');
312316
$this->hasChanged = false;
313317
}
314318

@@ -751,6 +755,10 @@ abstract class AbstractSmrAccount {
751755
return false;
752756
}
753757

758+
public function getLoginID() {
759+
return $this->login_id;
760+
}
761+
754762
public function getLogin() {
755763
return $this->login;
756764
}
@@ -1301,6 +1309,36 @@ abstract class AbstractSmrAccount {
13011309
public function getPersonalHofHREF() {
13021310
return SmrSession::getNewHREF(create_container('skeleton.php','hall_of_fame_player_detail.php',array('account_id' => $this->getAccountID())));
13031311
}
1304-
}
13051312

1313+
/**
1314+
* Return an array of account_ids associated with this login.
1315+
* We assume that each login has only MAX_LINKED_ACCOUNTS accounts and
1316+
* that the smallest ID (created first) is the primary account_id.
1317+
*/
1318+
public function getLinkedAccountList() {
1319+
$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));
1320+
$result = array();
1321+
while ($this->db->nextRecord()) {
1322+
$name = count($result) == 0 ? 'Main' : 'Multi';
1323+
$result[$this->db->getInt('account_id')] = $name;
1324+
}
1325+
return $result;
1326+
}
1327+
1328+
/**
1329+
* Returns another account that is linked to this login.
1330+
*/
1331+
public function getLinkedAccount($accountID) {
1332+
if ($accountID == $this->getAccountID()) {
1333+
return $this;
1334+
}
1335+
$linkedAccounts = $this->getLinkedAccountList();
1336+
if (isset($linkedAccounts[$accountID])) {
1337+
return $this::getAccount($accountID);
1338+
} else {
1339+
throw new Exception('No linked account with ID: ' . $accountID);
1340+
}
1341+
}
1342+
1343+
}
13061344
?>

lib/Default/SmrSession.class.inc

+11
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,17 @@ class SmrSession {
266266
self::$db->query('UPDATE active_session SET game_id=' . self::$db->escapeNumber(self::$game_id) . ' WHERE session_id=' . self::$db->escapeString(self::$session_id));
267267
}
268268

269+
/**
270+
* Updates the `account_id` attribute of the session.
271+
*/
272+
public static function updateAccount($accountID) {
273+
if (self::$account_id == $accountID) {
274+
return;
275+
}
276+
self::$account_id = $accountID;
277+
self::$db->query('UPDATE active_session SET account_id=' . self::$db->escapeNumber(self::$account_id) . ' WHERE session_id=' . self::$db->escapeString(self::$session_id));
278+
}
279+
269280
public static function updateSN() {
270281
self::$db = new SmrSessionMySqlDatabase();
271282
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)