diff --git a/app/Http/Controllers/Api/ReportsController.php b/app/Http/Controllers/Api/ReportsController.php index b0f64189d..931886fb2 100644 --- a/app/Http/Controllers/Api/ReportsController.php +++ b/app/Http/Controllers/Api/ReportsController.php @@ -83,11 +83,19 @@ class ReportsController extends Controller $offset = ($request->input('offset') > $total) ? $total : app('api_offset_value'); $limit = app('api_limit_value'); - $sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at'; $order = ($request->input('order') == 'asc') ? 'asc' : 'desc'; + switch ($request->input('sort')) { + case 'admin': + $actionlogs->OrderAdmin($order); + break; + default: + $sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at'; + $actionlogs = $actionlogs->orderBy($sort, $order); + break; + } - $actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get(); + $actionlogs = $actionlogs->skip($offset)->take($limit)->get(); return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE); } diff --git a/app/Models/Actionlog.php b/app/Models/Actionlog.php index 33e9707f2..46592c9b0 100755 --- a/app/Models/Actionlog.php +++ b/app/Models/Actionlog.php @@ -7,7 +7,6 @@ use App\Presenters\Presentable; use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Auth; /** * Model for the Actionlog (the table that keeps a historical log of @@ -17,10 +16,12 @@ use Illuminate\Support\Facades\Auth; */ class Actionlog extends SnipeModel { + use CompanyableTrait; use HasFactory; // This is to manually set the source (via setActionSource()) for determineActionSource() protected ?string $source = null; + protected $with = ['admin']; protected $presenter = \App\Presenters\ActionlogPresenter::class; use SoftDeletes; @@ -66,7 +67,7 @@ class Actionlog extends SnipeModel 'company' => ['name'], 'admin' => ['first_name','last_name','username', 'email'], 'user' => ['first_name','last_name','username', 'email'], - 'assets' => ['asset_tag','name'], + 'assets' => ['asset_tag','name','model', 'model_number'], ]; /** @@ -372,4 +373,9 @@ class Actionlog extends SnipeModel { $this->source = $source; } + + public function scopeOrderAdmin($query, $order) + { + return $query->leftJoin('users as admin_sort', 'action_logs.user_id', '=', 'admin_sort.id')->select('action_logs.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order); + } } diff --git a/app/Models/Asset.php b/app/Models/Asset.php index cddca9802..b3bf126bd 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -2,7 +2,6 @@ namespace App\Models; -use App\Events\AssetCheckedOut; use App\Events\CheckoutableCheckedOut; use App\Exceptions\CheckoutNotAllowed; use App\Helpers\Helper; @@ -31,6 +30,7 @@ class Asset extends Depreciable { protected $presenter = AssetPresenter::class; + protected $with = ['model', 'admin']; use CompanyableTrait; use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait; @@ -716,7 +716,7 @@ class Asset extends Depreciable * @since [v1.0] * @return \Illuminate\Database\Eloquent\Relations\Relation */ - public function adminuser() + public function admin() { return $this->belongsTo(\App\Models\User::class, 'user_id'); } diff --git a/resources/views/reports/activity.blade.php b/resources/views/reports/activity.blade.php index a7e6f9f15..6ed55dc16 100644 --- a/resources/views/reports/activity.blade.php +++ b/resources/views/reports/activity.blade.php @@ -52,7 +52,7 @@ {{ trans('admin/hardware/table.serial') }} {{ trans('general.item') }} {{ trans('general.to') }} - {{ trans('general.notes') }} + {{ trans('general.notes') }} {{ trans('general.changed') }} {{ trans('admin/settings/general.login_ip') }} {{ trans('admin/settings/general.login_user_agent') }} diff --git a/tests/Feature/Assets/Api/StoreAssetTest.php b/tests/Feature/Assets/Api/StoreAssetTest.php index a3f598163..7ebfdf870 100644 --- a/tests/Feature/Assets/Api/StoreAssetTest.php +++ b/tests/Feature/Assets/Api/StoreAssetTest.php @@ -61,7 +61,7 @@ class StoreAssetTest extends TestCase $asset = Asset::find($response['payload']['id']); - $this->assertTrue($asset->adminuser->is($user)); + $this->assertTrue($asset->admin->is($user)); $this->assertEquals('2024-06-02', $asset->asset_eol_date); $this->assertEquals('random_string', $asset->asset_tag); @@ -456,7 +456,7 @@ class StoreAssetTest extends TestCase $asset = Asset::find($response['payload']['id']); - $this->assertTrue($asset->adminuser->is($user)); + $this->assertTrue($asset->admin->is($user)); $this->assertTrue($asset->checkedOutToUser()); $this->assertTrue($asset->assignedTo->is($userAssigned)); } @@ -482,7 +482,7 @@ class StoreAssetTest extends TestCase $asset = Asset::find($response['payload']['id']); - $this->assertTrue($asset->adminuser->is($user)); + $this->assertTrue($asset->admin->is($user)); $this->assertTrue($asset->checkedOutToLocation()); $this->assertTrue($asset->location->is($location)); } @@ -508,7 +508,7 @@ class StoreAssetTest extends TestCase $apiAsset = Asset::find($response['payload']['id']); - $this->assertTrue($apiAsset->adminuser->is($user)); + $this->assertTrue($apiAsset->admin->is($user)); $this->assertTrue($apiAsset->checkedOutToAsset()); // I think this makes sense, but open to a sanity check $this->assertTrue($asset->assignedAssets()->find($response['payload']['id'])->is($apiAsset)); diff --git a/tests/Feature/Assets/Ui/BulkEditAssetsTest.php b/tests/Feature/Assets/Ui/BulkEditAssetsTest.php index 02d39a7b4..76d0a9c34 100644 --- a/tests/Feature/Assets/Ui/BulkEditAssetsTest.php +++ b/tests/Feature/Assets/Ui/BulkEditAssetsTest.php @@ -165,7 +165,7 @@ class BulkEditAssetsTest extends TestCase }); } - public function testBulkEditAssetsRequiresAdminUserToUpdateEncryptedCustomFields() + public function testBulkEditAssetsRequiresadminToUpdateEncryptedCustomFields() { $this->markIncompleteIfMySQL('Custom Fields tests do not work on mysql'); $edit_user = User::factory()->editAssets()->create(); diff --git a/tests/Feature/Reporting/ActivityReportTest.php b/tests/Feature/Reporting/ActivityReportTest.php new file mode 100644 index 000000000..e094f86b6 --- /dev/null +++ b/tests/Feature/Reporting/ActivityReportTest.php @@ -0,0 +1,81 @@ +actingAsForApi(User::factory()->create()) + ->getJson(route('api.activity.index')) + ->assertForbidden(); + } + + public function testRecordsAreScopedToCompanyWhenMultipleCompanySupportEnabled() + { + $this->markTestIncomplete('This test returns strange results. Need to figure out why.'); + $this->settings->enableMultipleFullCompanySupport(); + + $companyA = Company::factory()->create(); + $companyB = Company::factory()->create(); + + $superUser = User::factory()->superuser()->make(); + + $userInCompanyA = User::factory() + ->viewUsers() + ->viewAssets() + ->canViewReports() + ->create(['company_id' => $companyA->id]); + + $userInCompanyB = User::factory() + ->viewUsers() + ->viewAssets() + ->canViewReports() + ->create(['company_id' => $companyB->id]); + + Asset::factory()->count(5)->create(['company_id' => $companyA->id]); + Asset::factory()->count(4)->create(['company_id' => $companyB->id]); + Asset::factory()->count(3)->create(); + + Actionlog::factory()->userUpdated()->count(5)->create(['company_id' => $companyA->id]); + Actionlog::factory()->userUpdated()->count(4)->create(['company_id' => $companyB->id]); + Actionlog::factory()->userUpdated()->count(3)->create(['company_id' => $companyB->id]); + + // I don't love this, since it doesn't test that we're actually storing the company ID appropriately + // but it's better than what we had + $response = $this->actingAsForApi($userInCompanyA) + ->getJson(route('api.activity.index')) + ->assertOk() + ->assertJsonStructure([ + 'rows', + ]) + ->assertJson(fn(AssertableJson $json) => $json->has('rows', 5)->etc()); + + + $this->actingAsForApi($userInCompanyB) + ->getJson( + route('api.activity.index')) + ->assertOk() + ->assertJsonStructure([ + 'rows', + ]) + ->assertJson(fn(AssertableJson $json) => $json->has('rows', 7)->etc()); + + + + + + } + +}