Skip to content

Commit

Permalink
Connected account migrations leave behind an alias
Browse files Browse the repository at this point in the history
  • Loading branch information
thommcgrath committed Nov 21, 2024
1 parent cc09e70 commit 9e99c00
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 12 deletions.
34 changes: 27 additions & 7 deletions Website/api/v4/classes/ServiceToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,16 @@ public static function Fetch(string $tokenId): ?static {
}
}

public static function ResolveAlias(string $oldTokenId): ?string {
$database = BeaconCommon::Database();
$rows = $database->Query('SELECT new_service_token_id FROM public.service_token_aliases WHERE old_service_token_id = $1;', $oldTokenId);
if ($rows->RecordCount() === 1) {
return $rows->Field('new_service_token_id');
} else {
return null;
}
}

public static function Lookup(string $userId, ?string $provider = null, ?string $tokenId = null): array {
$database = BeaconCommon::Database();
$placeholder = 2;
Expand Down Expand Up @@ -290,7 +300,7 @@ public static function RefreshExpiring(): void {
}
}

public function MoveToUser(string|User $user): bool {
public function MoveToUser(string|User $user): void {
if ($user instanceof User) {
$userId = $user->UserId();
} else {
Expand All @@ -305,23 +315,33 @@ public function MoveToUser(string|User $user): bool {
$newTokenId = static::StaticTokenId($userId, $this->provider, $this->accessToken);
break;
default:
return false;
return;
}

$database = BeaconCommon::Database();
$database->BeginTransaction();
$rows = $database->Query('SELECT token_id FROM public.service_tokens WHERE token_id = $1;', $newTokenId);
if ($rows->RecordCount() !== 0) {
$database->Rollback();
return false;
if ($rows->RecordCount() === 0) {
// The new account does not have the token, so we update it
$database->Query('UPDATE public.service_tokens SET user_id = $2, token_id = $3 WHERE token_id = $1;', $this->tokenId, $userId, $newTokenId);
} else {
// The new account already has a token with the same uuid, so we delete this one instead
$database->Query('DELETE FROM public.service_tokens WHERE token_id = $1;', $this->tokenId);
$returnValue = false;
}
$rows = $database->Query('SELECT old_service_token_id, new_service_token_id FROM public.service_token_aliases WHERE old_service_token_id = $1;', $this->tokenId);
if ($rows->RecordCount() === 0) {
// There is no alias from the old id to the new id
$database->Query('INSERT INTO public.service_token_aliases (old_service_token_id, new_service_token_id) VALUES ($1, $2);', $this->tokenId, $newTokenId);
} elseif ($rows->Field('new_service_token_id') !== $newTokenId) {
// There is an alias for the old id, but it puts to the wrong new id, so we update it
$database->Query('UPDATE public.service_token_aliases SET new_service_token_id = $2 WHERE old_service_token_id = $1;', $this->tokenId, $newTokenId);
}
$database->Query('UPDATE public.service_tokens SET user_id = $2, token_id = $3 WHERE token_id = $1;', $this->tokenId, $userId, $newTokenId);
$database->Commit();

$this->tokenId = $newTokenId;
$this->userId = $userId;
$this->userName = $user->Username() ?? 'Anonymous';
return true;
}

public function TokenId(): string {
Expand Down
16 changes: 15 additions & 1 deletion Website/api/v4/requests/tokens/get.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
function handleRequest(array $context): Response {
$tokenId = $context['pathParameters']['tokenId'];

$token = ServiceToken::Fetch($tokenId);
$token = fetchToken($tokenId);
if (is_null($token)) {
return Response::NewJsonError('Token not found', $tokenId, 404);
}
Expand All @@ -20,4 +20,18 @@ function handleRequest(array $context): Response {
return Response::NewJson($token->JSON($authenticatedAsUser), 200);
}

function fetchToken(string $tokenId): ?ServiceToken {
$token = ServiceToken::Fetch($tokenId);
if (is_null($token) === false) {
return $token;
}

$newTokenId = ServiceToken::ResolveAlias($tokenId);
if (is_null($newTokenId)) {
return null;
}

return ServiceToken::Fetch($newTokenId);
}

?>
5 changes: 1 addition & 4 deletions Website/api/v4/requests/users/merge.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,7 @@ function MergeUser(User $authenticatedUser, array $anonymousUser): Response {
// Service tokens are special because their uuid includes the user id
$tokens = ServiceToken::Lookup($userId);
foreach ($tokens as $token) {
// Returns true on success, false if the accounts already has the same service
if ($token->MoveToUser($authenticatedUser) === false) {
$token->Delete();
}
$token->MoveToUser($authenticatedUser);
}

// Migrating project members is hard
Expand Down

0 comments on commit 9e99c00

Please sign in to comment.