]> BookStack Code Mirror - bookstack/commitdiff
Merge branch 'floviolleau-db-prefixes' of https://github.com/floviolleau/BookStack...
authorDan Brown <redacted>
Wed, 29 Sep 2021 17:13:38 +0000 (18:13 +0100)
committerDan Brown <redacted>
Wed, 29 Sep 2021 17:13:38 +0000 (18:13 +0100)
22 files changed:
.env.example.complete
app/Actions/ActivityService.php
app/Actions/TagRepo.php
app/Auth/UserRepo.php
app/Console/Commands/RegenerateSearch.php
app/Http/Controllers/Auth/RegisterController.php
app/Providers/AppServiceProvider.php
app/Providers/AuthServiceProvider.php
app/Providers/RouteServiceProvider.php
app/Uploads/AttachmentService.php
app/Uploads/ImageService.php
database/migrations/2016_04_20_192649_create_joint_permissions_table.php
database/migrations/2021_09_26_044614_add_activities_ip_column.php [new file with mode: 0644]
resources/lang/en/settings.php
resources/views/settings/audit.blade.php
tests/AuditLogTest.php
tests/Auth/AuthTest.php
tests/Auth/SocialAuthTest.php
tests/Auth/UserInviteTest.php
tests/PublicActionTest.php
tests/RecycleBinTest.php
tests/ThemeTest.php

index 970ec16d95e0cd01e7efcb673a1bda208398e25a..e28fedad9c58246ad2bc5cfc479ce780291bd707 100644 (file)
@@ -42,6 +42,14 @@ APP_TIMEZONE=UTC
 # overrides can be made. Defaults to disabled.
 APP_THEME=false
 
+# Trusted Proxies
+# Used to indicate trust of systems that proxy to the application so
+# certain header values (Such as "X-Forwarded-For") can be used from the
+# incoming proxy request to provide origin detail.
+# Set to an IP address, or multiple comma seperated IP addresses.
+# Can alternatively be set to "*" to trust all proxy addresses.
+APP_PROXIES=null
+
 # Database details
 # Host can contain a port (localhost:3306) or a separate DB_PORT option can be used.
 DB_HOST=localhost
index dce7dc7b2595df00a1652bcfbcce7124de811b62..f8a0825bbd8794b9ae1c89a5986a21219f08fb02 100644 (file)
@@ -11,6 +11,7 @@ use BookStack\Interfaces\Loggable;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Relations\Relation;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Request;
 
 class ActivityService
 {
@@ -55,9 +56,11 @@ class ActivityService
      */
     protected function newActivityForUser(string $type): Activity
     {
+        $ip = request()->ip() ?? '';
         return $this->activity->newInstance()->forceFill([
             'type'     => strtolower($type),
             'user_id'  => user()->id,
+            'ip'       => config('app.env') === 'demo' ? '127.0.0.1' : $ip,
         ]);
     }
 
index ca65b78e8e2dab7b7742204f6decd8e0c5a908f2..b892efe577901191c4a7fea292e134eefbff86ea 100644 (file)
@@ -4,8 +4,8 @@ namespace BookStack\Actions;
 
 use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Entities\Models\Entity;
-use DB;
 use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
 
 class TagRepo
 {
index e1a040fc2ceb8850dd52b046556690add64bd606..6d48f12402060edbbe56f5660301dc1183ca5dcc 100644 (file)
@@ -15,7 +15,7 @@ use Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Pagination\LengthAwarePaginator;
-use Log;
+use Illuminate\Support\Facades\Log;
 
 class UserRepo
 {
index 3dc3ec0af0e98b33bd3f1d741540dd13e1d319c5..50e81a2b8e2578edeb8b2d2208f158def6a0256f 100644 (file)
@@ -3,8 +3,8 @@
 namespace BookStack\Console\Commands;
 
 use BookStack\Entities\Tools\SearchIndex;
-use DB;
 use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
 
 class RegenerateSearch extends Command
 {
index bd1ffeac2e6661f3c391613c30d8315d7e58d0d7..209827d6db800d7a75a7a568ec9a1af8468f4355 100644 (file)
@@ -12,7 +12,7 @@ use BookStack\Http\Controllers\Controller;
 use Illuminate\Foundation\Auth\RegistersUsers;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Hash;
-use Validator;
+use Illuminate\Support\Facades\Validator;
 
 class RegisterController extends Controller
 {
index 59704f4a1898311aff5ed176d7c2e93955e6ed27..8334bb179ae73b4e08982271d37dd4b0cf2ee971 100644 (file)
@@ -2,7 +2,6 @@
 
 namespace BookStack\Providers;
 
-use Blade;
 use BookStack\Auth\Access\LoginService;
 use BookStack\Auth\Access\SocialAuthService;
 use BookStack\Entities\BreadcrumbsViewComposer;
@@ -15,11 +14,12 @@ use BookStack\Settings\SettingService;
 use BookStack\Util\CspService;
 use Illuminate\Contracts\Cache\Repository;
 use Illuminate\Database\Eloquent\Relations\Relation;
+use Illuminate\Support\Facades\Blade;
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Support\Facades\URL;
 use Illuminate\Support\Facades\View;
 use Illuminate\Support\ServiceProvider;
 use Laravel\Socialite\Contracts\Factory as SocialiteFactory;
-use Schema;
-use URL;
 
 class AppServiceProvider extends ServiceProvider
 {
index 71b7ab016200bb085c5383584463313c673c1eb6..37b0e83b9ac9b6a6e4b390aa4e30d5f0c7d906b5 100644 (file)
@@ -2,7 +2,6 @@
 
 namespace BookStack\Providers;
 
-use Auth;
 use BookStack\Api\ApiTokenGuard;
 use BookStack\Auth\Access\ExternalBaseUserProvider;
 use BookStack\Auth\Access\Guards\LdapSessionGuard;
@@ -10,6 +9,7 @@ use BookStack\Auth\Access\Guards\Saml2SessionGuard;
 use BookStack\Auth\Access\LdapService;
 use BookStack\Auth\Access\LoginService;
 use BookStack\Auth\Access\RegistrationService;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\ServiceProvider;
 
 class AuthServiceProvider extends ServiceProvider
index 8f0dab400c7efd4ce00902d7ef94874a654e516e..b60443a452895fc19a8c4a5dcffdfeb03f339b52 100644 (file)
@@ -3,7 +3,7 @@
 namespace BookStack\Providers;
 
 use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
-use Route;
+use Illuminate\Support\Facades\Route;
 
 class RouteServiceProvider extends ServiceProvider
 {
index 298d53a04c109ff42175318fd3ed69f9166ea375..b4cb1b88b15e26b0d982174b97fa5b80ed13c385 100644 (file)
@@ -7,8 +7,8 @@ use Exception;
 use Illuminate\Contracts\Filesystem\Factory as FileSystem;
 use Illuminate\Contracts\Filesystem\FileNotFoundException;
 use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
+use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Str;
-use Log;
 use Symfony\Component\HttpFoundation\File\UploadedFile;
 
 class AttachmentService
index 51ddf9bdc55912c3884e9b126aa3b92634a66ab2..2c38c24f4f7c5f6d31646722937516e42b4cb042 100644 (file)
@@ -3,7 +3,6 @@
 namespace BookStack\Uploads;
 
 use BookStack\Exceptions\ImageUploadException;
-use DB;
 use ErrorException;
 use Exception;
 use Illuminate\Contracts\Cache\Repository as Cache;
@@ -11,6 +10,7 @@ use Illuminate\Contracts\Filesystem\Factory as FileSystem;
 use Illuminate\Contracts\Filesystem\FileNotFoundException;
 use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
 use Illuminate\Contracts\Filesystem\Filesystem as Storage;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Str;
 use Intervention\Image\Exception\NotSupportedException;
 use Intervention\Image\ImageManager;
index 5b43c7d549de1265fd5fee0eea91f4fd5b499ebd..8c3d9124c75e4067b9041288b3eb11ac856a32c4 100644 (file)
@@ -2,6 +2,7 @@
 
 use Illuminate\Database\Migrations\Migration;
 use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Str;
 
 class CreateJointPermissionsTable extends Migration
 {
@@ -53,7 +54,7 @@ class CreateJointPermissionsTable extends Migration
 
         // Ensure unique name
         while (DB::table('roles')->where('name', '=', $publicRoleData['display_name'])->count() > 0) {
-            $publicRoleData['display_name'] = $publicRoleData['display_name'] . str_random(2);
+            $publicRoleData['display_name'] = $publicRoleData['display_name'] . Str::random(2);
         }
         $publicRoleId = DB::table('roles')->insertGetId($publicRoleData);
 
diff --git a/database/migrations/2021_09_26_044614_add_activities_ip_column.php b/database/migrations/2021_09_26_044614_add_activities_ip_column.php
new file mode 100644 (file)
index 0000000..68391b1
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddActivitiesIpColumn extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('activities', function (Blueprint $table) {
+            $table->string('ip', 45)->after('user_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('activities', function (Blueprint $table) {
+            $table->dropColumn('ip');
+        });
+    }
+}
index 4c1ae134527f068e244ed6081c2b3ad8af6f987d..0ab168b66998bca0de4807f94d181b9b12ed1683 100755 (executable)
@@ -119,6 +119,7 @@ return [
     'audit_table_user' => 'User',
     'audit_table_event' => 'Event',
     'audit_table_related' => 'Related Item or Detail',
+    'audit_table_ip' => 'IP Address',
     'audit_table_date' => 'Activity Date',
     'audit_date_from' => 'Date Range From',
     'audit_date_to' => 'Date Range To',
index 7a66cc3f37bd4b79bde88044034f864e5cdde3a7..84f180f3b41fbc43c07933aeab7a4b6910caa5d4 100644 (file)
@@ -62,6 +62,7 @@
                     <a href="{{ sortUrl('/settings/audit', $listDetails, ['sort' => 'key']) }}">{{ trans('settings.audit_table_event') }}</a>
                 </th>
                 <th>{{ trans('settings.audit_table_related') }}</th>
+                <th>{{ trans('settings.audit_table_ip') }}</th>
                 <th>
                     <a href="{{ sortUrl('/settings/audit', $listDetails, ['sort' => 'created_at']) }}">{{ trans('settings.audit_table_date') }}</a></th>
             </tr>
@@ -88,6 +89,7 @@
                             <div class="px-m">{{ $activity->detail }}</div>
                         @endif
                     </td>
+                    <td>{{ $activity->ip }}</td>
                     <td>{{ $activity->created_at }}</td>
                 </tr>
             @endforeach
index bc36a184d129f3465a9e9fc855dfcabd21b98d5d..9f6576a46dadcf6ba0dab8e8f8342f947d3dcc71 100644 (file)
@@ -140,4 +140,53 @@ class AuditLogTest extends TestCase
         $resp->assertSeeText($chapter->name);
         $resp->assertDontSeeText($page->name);
     }
+
+    public function test_ip_address_logged_and_visible()
+    {
+        config()->set('app.proxies', '*');
+        $editor = $this->getEditor();
+        /** @var Page $page */
+        $page = Page::query()->first();
+
+        $this->actingAs($editor)->put($page->getUrl(), [
+            'name' => 'Updated page',
+            'html' => '<p>Updated content</p>',
+        ], [
+            'X-Forwarded-For' => '192.123.45.1'
+        ])->assertRedirect($page->refresh()->getUrl());
+
+        $this->assertDatabaseHas('activities', [
+            'type' => ActivityType::PAGE_UPDATE,
+            'ip' => '192.123.45.1',
+            'user_id' => $editor->id,
+            'entity_id' => $page->id,
+        ]);
+
+        $resp = $this->asAdmin()->get('/settings/audit');
+        $resp->assertSee('192.123.45.1');
+    }
+
+    public function test_ip_address_not_logged_in_demo_mode()
+    {
+        config()->set('app.proxies', '*');
+        config()->set('app.env', 'demo');
+        $editor = $this->getEditor();
+        /** @var Page $page */
+        $page = Page::query()->first();
+
+        $this->actingAs($editor)->put($page->getUrl(), [
+            'name' => 'Updated page',
+            'html' => '<p>Updated content</p>',
+        ], [
+            'X-Forwarded-For' => '192.123.45.1',
+            'REMOTE_ADDR' => '192.123.45.2',
+        ])->assertRedirect($page->refresh()->getUrl());
+
+        $this->assertDatabaseHas('activities', [
+            'type' => ActivityType::PAGE_UPDATE,
+            'ip' => '127.0.0.1',
+            'user_id' => $editor->id,
+            'entity_id' => $page->id,
+        ]);
+    }
 }
index a718b14b670f5c40e7f198a216d1908e3c58c100..d037b57011fada64a1c1755ab9418b9ea03af828 100644 (file)
@@ -7,7 +7,7 @@ use BookStack\Auth\User;
 use BookStack\Entities\Models\Page;
 use BookStack\Notifications\ConfirmEmail;
 use BookStack\Notifications\ResetPassword;
-use DB;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Notification;
 use Tests\TestCase;
 use Tests\TestResponse;
index 44b9e4ce1ce94425654887ae404b80d8e9ec2644..f70263dd278ae1a8bf93efe26c896bda300d97e3 100644 (file)
@@ -5,7 +5,7 @@ namespace Tests\Auth;
 use BookStack\Actions\ActivityType;
 use BookStack\Auth\SocialAccount;
 use BookStack\Auth\User;
-use DB;
+use Illuminate\Support\Facades\DB;
 use Laravel\Socialite\Contracts\Factory;
 use Laravel\Socialite\Contracts\Provider;
 use Mockery;
index c5c4b01af065ea607471c64562e554f8c51feed3..dcf9e23df9b829a10cfd175800d058247c1333fe 100644 (file)
@@ -6,9 +6,9 @@ use BookStack\Auth\Access\UserInviteService;
 use BookStack\Auth\User;
 use BookStack\Notifications\UserInvite;
 use Carbon\Carbon;
-use DB;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\Str;
-use Notification;
 use Tests\TestCase;
 
 class UserInviteTest extends TestCase
index ae0c0ff95c6d454f649f0fe535b374a775a4d459..499c0c9f9710ab0bbd4c6f7401743c325dc2c6be 100644 (file)
@@ -2,7 +2,6 @@
 
 namespace Tests;
 
-use Auth;
 use BookStack\Auth\Permissions\PermissionService;
 use BookStack\Auth\Permissions\RolePermission;
 use BookStack\Auth\Role;
@@ -10,6 +9,7 @@ use BookStack\Auth\User;
 use BookStack\Entities\Models\Book;
 use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Page;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\View;
 
 class PublicActionTest extends TestCase
index 1c54452124fbb088631edb961931739377244270..f3e30c0d07d442f894347f7599e97e3e1c9218fc 100644 (file)
@@ -8,8 +8,8 @@ use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Deletion;
 use BookStack\Entities\Models\Entity;
 use BookStack\Entities\Models\Page;
-use DB;
 use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\DB;
 
 class RecycleBinTest extends TestCase
 {
index bab85be7a5e4ff9f8c0dd8bff3abbc785cb54cbc..2cab765ae4345c6958d2a2e54988dffb8cccab4b 100644 (file)
@@ -7,9 +7,9 @@ use BookStack\Entities\Models\Page;
 use BookStack\Entities\Tools\PageContent;
 use BookStack\Facades\Theme;
 use BookStack\Theming\ThemeEvents;
-use File;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Illuminate\Support\Facades\File;
 use League\CommonMark\ConfigurableEnvironmentInterface;
 
 class ThemeTest extends TestCase