From adf100a42ffdbcc25eda717c8a80e0ba0458f437 Mon Sep 17 00:00:00 2001
From: Christoph Wurst <christoph@winzerhof-wurst.at>
Date: Mon, 7 Sep 2020 11:21:16 +0200
Subject: [PATCH] Fix undefined class property access after upgrade from 19 to
 20

The serialized data in 19 has one property less and this was not
considered in the code. Hence adding a fallback. Moreover I'm changing
the deserialization into an array instead of object, as that is the
safer option.

Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
---
 .../Authentication/LoginCredentials/Store.php |  9 ++-
 .../LoginCredentials/StoreTest.php            | 76 +++++++++++++++++++
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/lib/private/Authentication/LoginCredentials/Store.php b/lib/private/Authentication/LoginCredentials/Store.php
index 6dd7dc3fb73..0a3b57b9c6c 100644
--- a/lib/private/Authentication/LoginCredentials/Store.php
+++ b/lib/private/Authentication/LoginCredentials/Store.php
@@ -111,8 +111,13 @@ class Store implements IStore {
 		}
 
 		if ($trySession && $this->session->exists('login_credentials')) {
-			$creds = json_decode($this->session->get('login_credentials'));
-			return new Credentials($creds->uid, $creds->loginName, $creds->password);
+			/** @var array $creds */
+			$creds = json_decode($this->session->get('login_credentials'), true);
+			return new Credentials(
+				$creds['uid'],
+				$creds['loginName'] ?? $this->session->get('loginname') ?? $creds['uid'], // Pre 20 didn't have a loginName property, hence fall back to the session value and then to the UID
+				$creds['password']
+			);
 		}
 
 		// If we reach this line, an exception was thrown.
diff --git a/tests/lib/Authentication/LoginCredentials/StoreTest.php b/tests/lib/Authentication/LoginCredentials/StoreTest.php
index 67cb0a18297..ad8a074660c 100644
--- a/tests/lib/Authentication/LoginCredentials/StoreTest.php
+++ b/tests/lib/Authentication/LoginCredentials/StoreTest.php
@@ -35,6 +35,7 @@ use OCP\ILogger;
 use OCP\ISession;
 use OCP\Session\Exceptions\SessionNotAvailableException;
 use Test\TestCase;
+use function json_encode;
 
 class StoreTest extends TestCase {
 
@@ -140,6 +141,81 @@ class StoreTest extends TestCase {
 		$this->store->getLoginCredentials();
 	}
 
+	public function testGetLoginCredentialsPartialCredentialsAndSessionName() {
+		$uid = 'id987';
+		$user = 'user987';
+		$password = '7389374';
+
+		$this->session->expects($this->once())
+			->method('getId')
+			->willReturn('sess2233');
+		$this->tokenProvider->expects($this->once())
+			->method('getToken')
+			->with('sess2233')
+			->will($this->throwException(new InvalidTokenException()));
+		$this->session->expects($this->once())
+			->method('exists')
+			->with($this->equalTo('login_credentials'))
+			->willReturn(true);
+		$this->session->expects($this->exactly(2))
+			->method('get')
+			->willReturnMap([
+				[
+					'login_credentials',
+					json_encode([
+						'uid' => $uid,
+						'password' => $password,
+					])
+				],
+				[
+					'loginname',
+					$user,
+				],
+			]);
+		$expected = new Credentials($uid, $user, $password);
+
+		$actual = $this->store->getLoginCredentials();
+
+		$this->assertEquals($expected, $actual);
+	}
+
+	public function testGetLoginCredentialsPartialCredentials() {
+		$uid = 'id987';
+		$password = '7389374';
+
+		$this->session->expects($this->once())
+			->method('getId')
+			->willReturn('sess2233');
+		$this->tokenProvider->expects($this->once())
+			->method('getToken')
+			->with('sess2233')
+			->will($this->throwException(new InvalidTokenException()));
+		$this->session->expects($this->once())
+			->method('exists')
+			->with($this->equalTo('login_credentials'))
+			->willReturn(true);
+		$this->session->expects($this->exactly(2))
+			->method('get')
+			->willReturnMap([
+				[
+					'login_credentials',
+					json_encode([
+						'uid' => $uid,
+						'password' => $password,
+					])
+				],
+				[
+					'loginname',
+					null,
+				],
+			]);
+		$expected = new Credentials($uid, $uid, $password);
+
+		$actual = $this->store->getLoginCredentials();
+
+		$this->assertEquals($expected, $actual);
+	}
+
 	public function testGetLoginCredentialsInvalidTokenLoginCredentials() {
 		$uid = 'id987';
 		$user = 'user987';
-- 
GitLab