Skip to content

Commit 8a44144

Browse files
authored
Merge pull request #16954 from grokability/develop
Merge dev into master
2 parents ee82c70 + 186f322 commit 8a44144

File tree

4 files changed

+74
-25
lines changed

4 files changed

+74
-25
lines changed

app/Http/Controllers/Users/UsersController.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ private function filterDisplayable($permissions)
178178
* @author [A. Gianotto] [<[email protected]>]
179179
* @since [v1.0]
180180
* @param $permissions
181-
* @return \Illuminate\Contracts\View\View
181+
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
182182
* @internal param int $id
183183
* @throws \Illuminate\Auth\Access\AuthorizationException
184184
*/
@@ -190,6 +190,10 @@ public function edit(User $user)
190190

191191
if ($user) {
192192

193+
if ($user->trashed()) {
194+
return redirect()->route('users.show', $user->id);
195+
}
196+
193197
$permissions = config('permissions');
194198
$groups = Group::pluck('name', 'id');
195199

app/Listeners/CheckoutableListener.php

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ public function onCheckedOut($event)
7676
* 4. If the admin CC email is set, even if the item being checked out doesn't have an email address (location, etc)
7777
*/
7878

79-
if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() ||
80-
$this->checkoutableShouldSendEmail($event)) {
79+
if ($event->checkoutable->requireAcceptance() /* does category require acceptance? */ ||
80+
$event->checkoutable->getEula() /* is there *some* kind of EULA? */ ||
81+
$this->checkoutableShouldSendEmail($event) /* does the category have 'checkin_email' [sic] set? */) {
8182

8283

8384
// Send a checkout email to the admin CC addresses, even if the target has no email
@@ -171,30 +172,28 @@ public function onCheckedIn($event)
171172
$notifiable = $this->getNotifiableUsers($event);
172173

173174
// Send email notifications
174-
try {
175-
/**
176-
* Send an email if any of the following conditions are met:
177-
* 1. The asset requires acceptance
178-
* 2. The item has a EULA
179-
* 3. The item should send an email at check-in/check-out
180-
* 4. If the admin CC email is set, even if the item being checked in doesn't have an email address (location, etc)
181-
*/
175+
if ($this->checkoutableShouldSendEmail($event)) {
176+
try {
177+
/**
178+
* Send a check-in n email *only* if the item should send an email at check-in/check-out
179+
*/
182180

183-
// Send a checkout email to the admin's CC addresses, even if the target has no email
184-
if (!empty($ccEmails)) {
185-
Mail::to($ccEmails)->send($mailable);
186-
Log::info('Checkin Mail sent to CC addresses');
187-
}
181+
// Send a checkout email to the admin's CC addresses, even if the target has no email
182+
if (!empty($ccEmails)) {
183+
Mail::to($ccEmails)->send($mailable);
184+
Log::info('Checkin Mail sent to CC addresses');
185+
}
188186

189-
// Send a checkout email to the target if it has an email
190-
if (!empty($notifiable->email)) {
191-
Mail::to($notifiable)->send($mailable);
192-
Log::info('Checkin Mail sent to checkout target');
187+
// Send a checkout email to the target if it has an email
188+
if (!empty($notifiable->email)) {
189+
Mail::to($notifiable)->send($mailable);
190+
Log::info('Checkin Mail sent to checkout target');
191+
}
192+
} catch (ClientException $e) {
193+
Log::debug("Exception caught during checkin email: " . $e->getMessage());
194+
} catch (Exception $e) {
195+
Log::debug("Exception caught during checkin email: " . $e->getMessage());
193196
}
194-
} catch (ClientException $e) {
195-
Log::debug("Exception caught during checkin email: " . $e->getMessage());
196-
} catch (Exception $e) {
197-
Log::debug("Exception caught during checkin email: " . $e->getMessage());
198197
}
199198

200199
// Send Webhook notification

app/Rules/UserCannotSwitchCompaniesIfItemsAssigned.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class UserCannotSwitchCompaniesIfItemsAssigned implements ValidationRule
1515
*/
1616
public function validate(string $attribute, mixed $value, Closure $fail): void
1717
{
18-
$user = User::find(request()->route('user')->id);
18+
$user = request()->route('user');
1919

2020
if (($value) && ($user->allAssignedCount() > 0) && (Setting::getSettings()->full_multiple_companies_support=='1')) {
2121

tests/Feature/Users/Ui/UpdateUserTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use App\Models\Asset;
66
use App\Models\Company;
77
use App\Models\User;
8+
use Error;
89
use Tests\TestCase;
910

1011
class UpdateUserTest extends TestCase
@@ -16,6 +17,15 @@ public function testPageRenders()
1617
->assertOk();
1718
}
1819

20+
public function testCannotViewEditPageForSoftDeletedUser()
21+
{
22+
$user = User::factory()->trashed()->create();
23+
24+
$this->actingAs(User::factory()->superuser()->create())
25+
->get(route('users.edit', $user->id))
26+
->assertRedirectToRoute('users.show', $user->id);
27+
}
28+
1929
public function testUsersCanBeActivatedWithNumber()
2030
{
2131
$admin = User::factory()->superuser()->create();
@@ -161,4 +171,40 @@ public function testMultiCompanyUserCanBeUpdatedIfHasAssetInSameCompany()
161171

162172
$this->followRedirects($response)->assertSee('success');
163173
}
174+
175+
/**
176+
* This can occur if the user edit screen is open in one tab and
177+
* the user is deleted in another before the edit form is submitted.
178+
* @link https://app.shortcut.com/grokability/story/29166
179+
*/
180+
public function testAttemptingToUpdateDeletedUserIsHandledGracefully()
181+
{
182+
[$companyA, $companyB] = Company::factory()->count(2)->create();
183+
$user = User::factory()->for($companyA)->create();
184+
Asset::factory()->assignedToUser($user)->create();
185+
186+
$id = $user->id;
187+
188+
$user->delete();
189+
190+
$response = $this->actingAs(User::factory()->editUsers()->create())
191+
->put(route('users.update', $id), [
192+
'first_name' => 'test',
193+
'username' => 'test',
194+
'company_id' => $companyB->id,
195+
]);
196+
197+
$this->assertFalse($response->exceptions->contains(function ($exception) {
198+
// Avoid hard 500
199+
return $exception instanceof Error;
200+
}));
201+
202+
// As of now, the user will be updated but not be restored
203+
$this->assertDatabaseHas('users', [
204+
'id' => $id,
205+
'first_name' => 'test',
206+
'username' => 'test',
207+
'company_id' => $companyB->id,
208+
]);
209+
}
164210
}

0 commit comments

Comments
 (0)