diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php index 03ec2c110..57ca58beb 100644 --- a/app/Http/Controllers/ChapterController.php +++ b/app/Http/Controllers/ChapterController.php @@ -117,7 +117,7 @@ class ChapterController extends Controller $this->checkOwnablePermission('chapter-update', $chapter); $chapter->fill($request->all()); $chapter->slug = $this->chapterRepo->findSuitableSlug($chapter->name, $book->id, $chapter->id); - $chapter->updated_by = auth()->user()->id; + $chapter->updated_by = user()->id; $chapter->save(); Activity::add($chapter, 'chapter_update', $book->id); return redirect($chapter->getUrl()); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 43292d941..2dabc417b 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -33,17 +33,16 @@ abstract class Controller extends BaseController $this->middleware(function ($request, $next) { // Get a user instance for the current user - $user = auth()->user(); - if (!$user) $user = User::getDefault(); - - // Share variables with views - view()->share('signedIn', auth()->check()); - view()->share('currentUser', $user); + $user = user(); // Share variables with controllers $this->currentUser = $user; $this->signedIn = auth()->check(); + // Share variables with views + view()->share('signedIn', $this->signedIn); + view()->share('currentUser', $user); + return $next($request); }); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 4c56516dc..51c5d25bb 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -57,7 +57,7 @@ class UserController extends Controller { $this->checkPermission('users-manage'); $authMethod = config('auth.method'); - $roles = $this->userRepo->getAssignableRoles(); + $roles = $this->userRepo->getAllRoles(); return view('users/create', ['authMethod' => $authMethod, 'roles' => $roles]); } @@ -126,12 +126,13 @@ class UserController extends Controller return $this->currentUser->id == $id; }); - $authMethod = config('auth.method'); - $user = $this->user->findOrFail($id); + + $authMethod = ($user->system_name) ? 'system' : config('auth.method'); + $activeSocialDrivers = $socialAuthService->getActiveDrivers(); $this->setPageTitle('User Profile'); - $roles = $this->userRepo->getAssignableRoles(); + $roles = $this->userRepo->getAllRoles(); return view('users/edit', ['user' => $user, 'activeSocialDrivers' => $activeSocialDrivers, 'authMethod' => $authMethod, 'roles' => $roles]); } diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php index fdc4dd8d4..1af02035d 100644 --- a/app/Repos/BookRepo.php +++ b/app/Repos/BookRepo.php @@ -132,8 +132,8 @@ class BookRepo extends EntityRepo { $book = $this->book->newInstance($input); $book->slug = $this->findSuitableSlug($book->name); - $book->created_by = auth()->user()->id; - $book->updated_by = auth()->user()->id; + $book->created_by = user()->id; + $book->updated_by = user()->id; $book->save(); $this->permissionService->buildJointPermissionsForEntity($book); return $book; @@ -149,7 +149,7 @@ class BookRepo extends EntityRepo { $book->fill($input); $book->slug = $this->findSuitableSlug($book->name, $book->id); - $book->updated_by = auth()->user()->id; + $book->updated_by = user()->id; $book->save(); $this->permissionService->buildJointPermissionsForEntity($book); return $book; diff --git a/app/Repos/ChapterRepo.php b/app/Repos/ChapterRepo.php index c12a9f0f2..96f5b2d1e 100644 --- a/app/Repos/ChapterRepo.php +++ b/app/Repos/ChapterRepo.php @@ -98,8 +98,8 @@ class ChapterRepo extends EntityRepo { $chapter = $this->chapter->newInstance($input); $chapter->slug = $this->findSuitableSlug($chapter->name, $book->id); - $chapter->created_by = auth()->user()->id; - $chapter->updated_by = auth()->user()->id; + $chapter->created_by = user()->id; + $chapter->updated_by = user()->id; $chapter = $book->chapters()->save($chapter); $this->permissionService->buildJointPermissionsForEntity($chapter); return $chapter; diff --git a/app/Repos/EntityRepo.php b/app/Repos/EntityRepo.php index c94601738..42b0b6b7b 100644 --- a/app/Repos/EntityRepo.php +++ b/app/Repos/EntityRepo.php @@ -132,9 +132,8 @@ class EntityRepo */ public function getUserDraftPages($count = 20, $page = 0) { - $user = auth()->user(); return $this->page->where('draft', '=', true) - ->where('created_by', '=', $user->id) + ->where('created_by', '=', user()->id) ->orderBy('updated_at', 'desc') ->skip($count * $page)->take($count)->get(); } diff --git a/app/Repos/PageRepo.php b/app/Repos/PageRepo.php index 93ff61b62..537dd9bd0 100644 --- a/app/Repos/PageRepo.php +++ b/app/Repos/PageRepo.php @@ -148,8 +148,8 @@ class PageRepo extends EntityRepo { $page = $this->page->newInstance(); $page->name = 'New Page'; - $page->created_by = auth()->user()->id; - $page->updated_by = auth()->user()->id; + $page->created_by = user()->id; + $page->updated_by = user()->id; $page->draft = true; if ($chapter) $page->chapter_id = $chapter->id; @@ -330,7 +330,7 @@ class PageRepo extends EntityRepo } // Update with new details - $userId = auth()->user()->id; + $userId = user()->id; $page->fill($input); $page->html = $this->formatHtml($input['html']); $page->text = strip_tags($page->html); @@ -363,7 +363,7 @@ class PageRepo extends EntityRepo $page->fill($revision->toArray()); $page->slug = $this->findSuitableSlug($page->name, $book->id, $page->id); $page->text = strip_tags($page->html); - $page->updated_by = auth()->user()->id; + $page->updated_by = user()->id; $page->save(); return $page; } @@ -381,7 +381,7 @@ class PageRepo extends EntityRepo $revision->page_id = $page->id; $revision->slug = $page->slug; $revision->book_slug = $page->book->slug; - $revision->created_by = auth()->user()->id; + $revision->created_by = user()->id; $revision->created_at = $page->updated_at; $revision->type = 'version'; $revision->summary = $summary; @@ -404,7 +404,7 @@ class PageRepo extends EntityRepo */ public function saveUpdateDraft(Page $page, $data = []) { - $userId = auth()->user()->id; + $userId = user()->id; $drafts = $this->userUpdateDraftsQuery($page, $userId)->get(); if ($drafts->count() > 0) { @@ -535,7 +535,7 @@ class PageRepo extends EntityRepo $query = $this->pageRevision->where('type', '=', 'update_draft') ->where('page_id', '=', $page->id) ->where('updated_at', '>', $page->updated_at) - ->where('created_by', '!=', auth()->user()->id) + ->where('created_by', '!=', user()->id) ->with('createdBy'); if ($minRange !== null) { diff --git a/app/Repos/PermissionsRepo.php b/app/Repos/PermissionsRepo.php index e026d83e8..24497c911 100644 --- a/app/Repos/PermissionsRepo.php +++ b/app/Repos/PermissionsRepo.php @@ -35,7 +35,7 @@ class PermissionsRepo */ public function getAllRoles() { - return $this->role->where('hidden', '=', false)->get(); + return $this->role->all(); } /** @@ -45,7 +45,7 @@ class PermissionsRepo */ public function getAllRolesExcept(Role $role) { - return $this->role->where('id', '!=', $role->id)->where('hidden', '=', false)->get(); + return $this->role->where('id', '!=', $role->id)->get(); } /** @@ -90,8 +90,6 @@ class PermissionsRepo { $role = $this->role->findOrFail($roleId); - if ($role->hidden) throw new PermissionsException("Cannot update a hidden role"); - $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $this->assignRolePermissions($role, $permissions); diff --git a/app/Repos/UserRepo.php b/app/Repos/UserRepo.php index 127db9fb5..ab3716fca 100644 --- a/app/Repos/UserRepo.php +++ b/app/Repos/UserRepo.php @@ -199,9 +199,9 @@ class UserRepo * Get the roles in the system that are assignable to a user. * @return mixed */ - public function getAssignableRoles() + public function getAllRoles() { - return $this->role->visible(); + return $this->role->all(); } /** @@ -211,7 +211,7 @@ class UserRepo */ public function getRestrictableRoles() { - return $this->role->where('hidden', '=', false)->where('system_name', '=', '')->get(); + return $this->role->where('system_name', '!=', 'admin')->get(); } } \ No newline at end of file diff --git a/app/Services/ActivityService.php b/app/Services/ActivityService.php index f6fea33a1..e41036238 100644 --- a/app/Services/ActivityService.php +++ b/app/Services/ActivityService.php @@ -19,7 +19,7 @@ class ActivityService { $this->activity = $activity; $this->permissionService = $permissionService; - $this->user = auth()->user(); + $this->user = user(); } /** diff --git a/app/Services/ImageService.php b/app/Services/ImageService.php index aa1375487..a56626246 100644 --- a/app/Services/ImageService.php +++ b/app/Services/ImageService.php @@ -108,8 +108,8 @@ class ImageService 'uploaded_to' => $uploadedTo ]; - if (auth()->user() && auth()->user()->id !== 0) { - $userId = auth()->user()->id; + if (user()->id !== 0) { + $userId = user()->id; $imageDetails['created_by'] = $userId; $imageDetails['updated_by'] = $userId; } diff --git a/app/Services/PermissionService.php b/app/Services/PermissionService.php index 341a69edb..bb78f0b0a 100644 --- a/app/Services/PermissionService.php +++ b/app/Services/PermissionService.php @@ -614,7 +614,7 @@ class PermissionService private function currentUser() { if ($this->currentUserModel === false) { - $this->currentUserModel = auth()->user() ? auth()->user() : new User(); + $this->currentUserModel = user(); } return $this->currentUserModel; diff --git a/app/Services/SocialAuthService.php b/app/Services/SocialAuthService.php index b28a97ea4..d76a7231b 100644 --- a/app/Services/SocialAuthService.php +++ b/app/Services/SocialAuthService.php @@ -100,7 +100,7 @@ class SocialAuthService $socialAccount = $this->socialAccount->where('driver_id', '=', $socialId)->first(); $user = $this->userRepo->getByEmail($socialUser->getEmail()); $isLoggedIn = auth()->check(); - $currentUser = auth()->user(); + $currentUser = user(); // When a user is not logged in and a matching SocialAccount exists, // Simply log the user into the application. @@ -214,9 +214,9 @@ class SocialAuthService public function detachSocialAccount($socialDriver) { session(); - auth()->user()->socialAccounts()->where('driver', '=', $socialDriver)->delete(); + user()->socialAccounts()->where('driver', '=', $socialDriver)->delete(); session()->flash('success', title_case($socialDriver) . ' account successfully detached'); - return redirect(auth()->user()->getEditUrl()); + return redirect(user()->getEditUrl()); } } \ No newline at end of file diff --git a/app/Services/ViewService.php b/app/Services/ViewService.php index aac9831f7..1a9ee5f70 100644 --- a/app/Services/ViewService.php +++ b/app/Services/ViewService.php @@ -18,7 +18,7 @@ class ViewService public function __construct(View $view, PermissionService $permissionService) { $this->view = $view; - $this->user = auth()->user(); + $this->user = user(); $this->permissionService = $permissionService; } @@ -84,7 +84,7 @@ class ViewService ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type'); if ($filterModel) $query = $query->where('viewable_type', '=', get_class($filterModel)); - $query = $query->where('user_id', '=', auth()->user()->id); + $query = $query->where('user_id', '=', user()->id); $viewables = $query->with('viewable')->orderBy('updated_at', 'desc') ->skip($count * $page)->take($count)->get()->pluck('viewable'); diff --git a/app/User.php b/app/User.php index 8c39d81be..09b189cbb 100644 --- a/app/User.php +++ b/app/User.php @@ -5,6 +5,7 @@ use Illuminate\Auth\Authenticatable; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Notifications\Notifiable; class User extends Model implements AuthenticatableContract, CanResetPasswordContract @@ -36,21 +37,30 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon protected $permissions; /** - * Returns a default guest user. + * Returns the default public user. + * @return User */ public static function getDefault() { - return new static([ - 'email' => 'guest', - 'name' => 'Guest' - ]); + return static::where('system_name', '=', 'public')->first(); + } + + /** + * Check if the user is the default public user. + * @return bool + */ + public function isDefault() + { + return $this->system_name === 'public'; } /** * The roles that belong to the user. + * @return BelongsToMany */ public function roles() { + if ($this->id === 0) return ; return $this->belongsToMany(Role::class); } diff --git a/app/helpers.php b/app/helpers.php index dd835fbf6..ad1c7dd20 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -36,6 +36,16 @@ function versioned_asset($file = '') throw new InvalidArgumentException("File {$file} not defined in asset manifest."); } +/** + * Helper method to get the current User. + * Defaults to public 'Guest' user if not logged in. + * @return \BookStack\User + */ +function user() +{ + return auth()->user() ?: \BookStack\User::getDefault(); +} + /** * Check if the current user has a permission. * If an ownable element is passed in the jointPermissions are checked against @@ -47,7 +57,7 @@ function versioned_asset($file = '') function userCan($permission, Ownable $ownable = null) { if ($ownable === null) { - return auth()->user() && auth()->user()->can($permission); + return user() && user()->can($permission); } // Check permission on ownable item diff --git a/database/migrations/2016_09_29_101449_remove_hidden_roles.php b/database/migrations/2016_09_29_101449_remove_hidden_roles.php new file mode 100644 index 000000000..f666cad2c --- /dev/null +++ b/database/migrations/2016_09_29_101449_remove_hidden_roles.php @@ -0,0 +1,66 @@ +dropColumn('hidden'); + }); + + // Add column to mark system users + Schema::table('users', function(Blueprint $table) { + $table->string('system_name')->nullable()->index(); + }); + + // Insert our new public system user. + $publicUserId = DB::table('users')->insertGetId([ + 'email' => 'guest@example.com', + 'name' => 'Guest', + 'system_name' => 'public', + 'email_confirmed' => true, + 'created_at' => \Carbon\Carbon::now(), + 'updated_at' => \Carbon\Carbon::now(), + ]); + + // Get the public role + $publicRole = DB::table('roles')->where('system_name', '=', 'public')->first(); + + // Connect the new public user to the public role + DB::table('role_user')->insert([ + 'user_id' => $publicUserId, + 'role_id' => $publicRole->id + ]); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('roles', function(Blueprint $table) { + $table->boolean('hidden')->default(false); + $table->index('hidden'); + }); + + DB::table('users')->where('system_name', '=', 'public')->delete(); + + Schema::table('users', function(Blueprint $table) { + $table->dropColumn('system_name'); + }); + + DB::table('roles')->where('system_name', '=', 'public')->update(['hidden' => true]); + } +} diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php index 757729763..ac25eb3b5 100644 --- a/resources/views/settings/index.blade.php +++ b/resources/views/settings/index.blade.php @@ -79,7 +79,7 @@