Skip to content

Commit 0962b6e

Browse files
committed
fix(core): accept deprecated IANA timezone aliases
Signed-off-by: Peter Ringelmann <peter.ringelmann@nextcloud.com>
1 parent ba46df3 commit 0962b6e

5 files changed

Lines changed: 116 additions & 7 deletions

File tree

apps/provisioning_api/lib/Controller/UsersController.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,8 @@ public function editUser(string $userId, string $key, string $value): DataRespon
13581358
$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
13591359
break;
13601360
case self::USER_FIELD_TIMEZONE:
1361-
if (!in_array($value, \DateTimeZone::listIdentifiers())) {
1361+
// Older browsers still report deprecated aliases like Europe/Kiev.
1362+
if (!in_array($value, \DateTimeZone::listIdentifiers(\DateTimeZone::ALL_WITH_BC))) {
13621363
throw new OCSException($this->l10n->t('Invalid timezone'), 101);
13631364
}
13641365
$this->config->setUserValue($targetUser->getUID(), 'core', 'timezone', $value);

apps/provisioning_api/tests/Controller/UsersControllerTest.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,6 +2591,92 @@ public function testEditUserAdminEditChangeLanguageInvalidLanguage(): void {
25912591
$this->assertEquals([], $this->api->editUser('UserToEdit', 'language', 'ru')->getData());
25922592
}
25932593

2594+
public static function dataEditUserSelfEditChangeTimezone(): array {
2595+
return [
2596+
'primary identifier' => ['Europe/Kyiv'],
2597+
'backward compatible alias' => ['Europe/Kiev'],
2598+
'legacy region alias' => ['US/Eastern'],
2599+
];
2600+
}
2601+
2602+
#[\PHPUnit\Framework\Attributes\DataProvider('dataEditUserSelfEditChangeTimezone')]
2603+
public function testEditUserSelfEditChangeTimezone(string $timezone): void {
2604+
$loggedInUser = $this->createMock(IUser::class);
2605+
$loggedInUser
2606+
->expects($this->any())
2607+
->method('getUID')
2608+
->willReturn('UserToEdit');
2609+
$targetUser = $this->createMock(IUser::class);
2610+
$this->config->expects($this->once())
2611+
->method('setUserValue')
2612+
->with('UserToEdit', 'core', 'timezone', $timezone);
2613+
$this->userSession
2614+
->expects($this->once())
2615+
->method('getUser')
2616+
->willReturn($loggedInUser);
2617+
$this->userManager
2618+
->expects($this->once())
2619+
->method('get')
2620+
->with('UserToEdit')
2621+
->willReturn($targetUser);
2622+
$this->groupManager
2623+
->expects($this->atLeastOnce())
2624+
->method('isAdmin')
2625+
->with('UserToEdit')
2626+
->willReturn(false);
2627+
$targetUser
2628+
->expects($this->any())
2629+
->method('getUID')
2630+
->willReturn('UserToEdit');
2631+
2632+
$backend = $this->createMock(UserInterface::class);
2633+
$targetUser
2634+
->expects($this->any())
2635+
->method('getBackend')
2636+
->willReturn($backend);
2637+
2638+
$this->assertEquals([], $this->api->editUser('UserToEdit', 'timezone', $timezone)->getData());
2639+
}
2640+
2641+
public function testEditUserSelfEditChangeTimezoneInvalid(): void {
2642+
$this->expectException(OCSException::class);
2643+
2644+
$loggedInUser = $this->createMock(IUser::class);
2645+
$loggedInUser
2646+
->expects($this->any())
2647+
->method('getUID')
2648+
->willReturn('UserToEdit');
2649+
$targetUser = $this->createMock(IUser::class);
2650+
$this->config->expects($this->never())
2651+
->method('setUserValue');
2652+
$this->userSession
2653+
->expects($this->once())
2654+
->method('getUser')
2655+
->willReturn($loggedInUser);
2656+
$this->userManager
2657+
->expects($this->once())
2658+
->method('get')
2659+
->with('UserToEdit')
2660+
->willReturn($targetUser);
2661+
$this->groupManager
2662+
->expects($this->atLeastOnce())
2663+
->method('isAdmin')
2664+
->with('UserToEdit')
2665+
->willReturn(false);
2666+
$targetUser
2667+
->expects($this->any())
2668+
->method('getUID')
2669+
->willReturn('UserToEdit');
2670+
2671+
$backend = $this->createMock(UserInterface::class);
2672+
$targetUser
2673+
->expects($this->any())
2674+
->method('getBackend')
2675+
->willReturn($backend);
2676+
2677+
$this->api->editUser('UserToEdit', 'timezone', 'Mars/Olympus_Mons');
2678+
}
2679+
25942680
public function testEditUserSubadminUserAccessible(): void {
25952681
$this->appConfig
25962682
->expects($this->once())

lib/private/Authentication/Login/SetUserTimezoneCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function process(LoginData $loginData): LoginResult {
3838
}
3939

4040
private function isValidTimezone(?string $value): bool {
41-
return $value && in_array($value, \DateTimeZone::listIdentifiers());
41+
// Older browsers still report deprecated aliases like Europe/Kiev.
42+
return $value && in_array($value, \DateTimeZone::listIdentifiers(\DateTimeZone::ALL_WITH_BC));
4243
}
4344
}

tests/lib/Authentication/Login/ALoginTestCommand.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ protected function getLoggedInLoginDataWithRedirectUrl(): LoginData {
9191
return $data;
9292
}
9393

94-
protected function getLoggedInLoginDataWithTimezone(): LoginData {
94+
protected function getLoggedInLoginDataWithTimezone(?string $timezone = null): LoginData {
9595
$data = new LoginData(
9696
$this->request,
9797
$this->username,
9898
$this->password,
9999
true,
100100
null,
101-
$this->timezone,
101+
$timezone ?? $this->timezone,
102102
$this->timeZoneOffset
103103
);
104104
$data->setUser($this->user);

tests/lib/Authentication/Login/SetUserTimezoneCommandTest.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,17 @@ public function testProcessNoTimezoneSet(): void {
4545
$this->assertTrue($result->isSuccess());
4646
}
4747

48-
public function testProcess(): void {
49-
$data = $this->getLoggedInLoginDataWithTimezone();
48+
public static function dataAcceptedTimezone(): array {
49+
return [
50+
'primary identifier' => ['Europe/Vienna'],
51+
'backward compatible alias' => ['Europe/Kiev'],
52+
'legacy region alias' => ['US/Eastern'],
53+
];
54+
}
55+
56+
#[\PHPUnit\Framework\Attributes\DataProvider('dataAcceptedTimezone')]
57+
public function testProcess(string $timezone): void {
58+
$data = $this->getLoggedInLoginDataWithTimezone($timezone);
5059
$this->user->expects($this->once())
5160
->method('getUID')
5261
->willReturn($this->username);
@@ -65,7 +74,7 @@ public function testProcess(): void {
6574
$this->username,
6675
'core',
6776
'timezone',
68-
$this->timezone
77+
$timezone
6978
);
7079
$this->session->expects($this->once())
7180
->method('set')
@@ -79,6 +88,18 @@ public function testProcess(): void {
7988
$this->assertTrue($result->isSuccess());
8089
}
8190

91+
public function testProcessUnknownTimezone(): void {
92+
$data = $this->getLoggedInLoginDataWithTimezone('Mars/Olympus_Mons');
93+
$this->config->expects($this->never())
94+
->method('setUserValue');
95+
$this->session->expects($this->never())
96+
->method('set');
97+
98+
$result = $this->cmd->process($data);
99+
100+
$this->assertTrue($result->isSuccess());
101+
}
102+
82103
public function testProcessAlreadySet(): void {
83104
$data = $this->getLoggedInLoginDataWithTimezone();
84105
$this->user->expects($this->once())

0 commit comments

Comments
 (0)