From 919660678bec2b94eaa84ac60d0313f5ef07dfb7 Mon Sep 17 00:00:00 2001
From: Dan Brown <ssddanbrown@googlemail.com>
Date: Tue, 25 Sep 2018 12:30:50 +0100
Subject: [PATCH] Re-structured the app code to be feature based rather than
 code type based

---
 app/{ => Actions}/Activity.php                |   5 +-
 app/{Services => Actions}/ActivityService.php |   9 +-
 app/{ => Actions}/Comment.php                 |   4 +-
 app/{Repos => Actions}/CommentRepo.php        |  22 ++--
 app/{ => Actions}/Tag.php                     |   4 +-
 app/{Repos => Actions}/TagRepo.php            |  17 ++-
 app/{ => Actions}/View.php                    |   4 +-
 app/{Services => Actions}/ViewService.php     |  17 +--
 .../Access}/EmailConfirmationService.php      |  12 +-
 app/{Services => Auth/Access}/Ldap.php        |   2 +-
 app/{Services => Auth/Access}/LdapService.php |  18 +--
 .../Access}/SocialAuthService.php             |   8 +-
 .../Permissions}/EntityPermission.php         |   4 +-
 .../Permissions}/JointPermission.php          |   6 +-
 .../Permissions}/PermissionService.php        |  54 +++++----
 .../Permissions}/PermissionsRepo.php          |  13 +-
 app/{ => Auth/Permissions}/RolePermission.php |   5 +-
 app/{ => Auth}/Role.php                       |  16 ++-
 app/{ => Auth}/SocialAccount.php              |   5 +-
 app/{ => Auth}/User.php                       |   6 +-
 app/{Repos => Auth}/UserRepo.php              |  23 ++--
 app/Console/Commands/CleanupImages.php        |   4 +-
 app/Console/Commands/ClearActivity.php        |   2 +-
 app/Console/Commands/ClearRevisions.php       |   2 +-
 app/Console/Commands/CreateAdmin.php          |   2 +-
 app/Console/Commands/DeleteUsers.php          |   4 +-
 .../Commands/RegeneratePermissions.php        |   4 +-
 app/Console/Commands/RegenerateSearch.php     |   4 +-
 app/{ => Entities}/Book.php                   |  14 ++-
 app/{ => Entities}/Bookshelf.php              |  13 +-
 app/{ => Entities}/Chapter.php                |  15 ++-
 app/{ => Entities}/Entity.php                 |  22 +++-
 app/Entities/EntityProvider.php               |   7 ++
 app/{Repos => Entities}/EntityRepo.php        | 111 +++++++++---------
 app/{Services => Entities}/ExportService.php  |  21 ++--
 app/{ => Entities}/Page.php                   |  19 ++-
 app/{ => Entities}/PageRevision.php           |   6 +-
 app/{Services => Entities}/SearchService.php  |  21 ++--
 app/{ => Entities}/SearchTerm.php             |   4 +-
 app/{Services => }/Facades/Activity.php       |   2 +-
 app/{Services => }/Facades/Images.php         |   2 +-
 app/{Services => }/Facades/Setting.php        |   2 +-
 app/{Services => }/Facades/Views.php          |   2 +-
 app/Http/Controllers/AttachmentController.php |   8 +-
 app/Http/Controllers/Auth/LoginController.php |  10 +-
 .../Controllers/Auth/RegisterController.php   |  20 ++--
 app/Http/Controllers/BookController.php       |  12 +-
 app/Http/Controllers/BookshelfController.php  |  14 +--
 app/Http/Controllers/ChapterController.php    |   8 +-
 app/Http/Controllers/CommentController.php    |   8 +-
 app/Http/Controllers/Controller.php           |   2 +-
 app/Http/Controllers/HomeController.php       |   2 +-
 app/Http/Controllers/ImageController.php      |   6 +-
 app/Http/Controllers/PageController.php       |  10 +-
 app/Http/Controllers/PermissionController.php |   4 +-
 app/Http/Controllers/SearchController.php     |   8 +-
 app/Http/Controllers/SettingController.php    |   2 +-
 app/Http/Controllers/TagController.php        |   2 +-
 app/Http/Controllers/UserController.php       |  10 +-
 app/Ownable.php                               |   2 +
 app/Providers/AppServiceProvider.php          |  24 +++-
 app/Providers/AuthServiceProvider.php         |   2 +-
 app/Providers/CustomFacadeProvider.php        |  18 +--
 app/Providers/LdapUserProvider.php            |  10 +-
 app/{ => Settings}/Setting.php                |   4 +-
 app/{Services => Settings}/SettingService.php |  10 +-
 app/{ => Uploads}/Attachment.php              |   5 +-
 .../AttachmentService.php                     |   5 +-
 app/{ => Uploads}/Image.php                   |   3 +-
 app/{Repos => Uploads}/ImageRepo.php          |  14 +--
 app/{Services => Uploads}/ImageService.php    |   9 +-
 app/{Services => Uploads}/UploadService.php   |   4 +-
 app/helpers.php                               |  10 +-
 config/app.php                                |   8 +-
 config/auth.php                               |   2 +-
 config/services.php                           |   2 +-
 database/factories/ModelFactory.php           |  18 +--
 ...15_12_07_195238_add_image_upload_types.php |   2 +-
 ..._08_04_115700_create_bookshelves_table.php |  12 +-
 database/seeds/DummyContentSeeder.php         |  28 ++---
 database/seeds/LargeContentSeeder.php         |  14 +--
 .../views/components/page-picker.blade.php    |   2 +-
 resources/views/errors/404.blade.php          |   6 +-
 resources/views/settings/index.blade.php      |   4 +-
 tests/ActivityTrackingTest.php                |   6 +-
 tests/AttachmentTest.php                      |  14 +--
 tests/Auth/AuthTest.php                       |   7 +-
 tests/Auth/LdapTest.php                       |   6 +-
 tests/Auth/SocialAuthTest.php                 |   6 +-
 tests/BrowserKitTest.php                      |  19 +--
 tests/CommandsTest.php                        |   8 +-
 tests/Entity/BookShelfTest.php                |   4 +-
 tests/Entity/CommentSettingTest.php           |   2 +-
 tests/Entity/CommentTest.php                  |   6 +-
 tests/Entity/EntitySearchTest.php             |  16 +--
 tests/Entity/EntityTest.php                   |  10 +-
 tests/Entity/ExportTest.php                   |   4 +-
 tests/Entity/MarkdownTest.php                 |   2 +-
 tests/Entity/PageContentTest.php              |   4 +-
 tests/Entity/PageDraftTest.php                |  10 +-
 tests/Entity/PageRevisionTest.php             |   2 +-
 tests/Entity/SortTest.php                     |   8 +-
 tests/Entity/TagTest.php                      |  12 +-
 tests/ImageTest.php                           |   8 +-
 tests/Permissions/RestrictionsTest.php        |  46 ++++----
 tests/Permissions/RolesTest.php               |  80 ++++++-------
 tests/PublicActionTest.php                    |  20 ++--
 tests/SharedTestHelpers.php                   |  30 ++---
 tests/UserProfileTest.php                     |   4 +-
 109 files changed, 684 insertions(+), 531 deletions(-)
 rename app/{ => Actions}/Activity.php (93%)
 rename app/{Services => Actions}/ActivityService.php (96%)
 rename app/{ => Actions}/Comment.php (94%)
 rename app/{Repos => Actions}/CommentRepo.php (76%)
 rename app/{ => Actions}/Tag.php (85%)
 rename app/{Repos => Actions}/TagRepo.php (91%)
 rename app/{ => Actions}/View.php (82%)
 rename app/{Services => Actions}/ViewService.php (85%)
 rename app/{Services => Auth/Access}/EmailConfirmationService.php (93%)
 rename app/{Services => Auth/Access}/Ldap.php (98%)
 rename app/{Services => Auth/Access}/LdapService.php (96%)
 rename app/{Services => Auth/Access}/SocialAuthService.php (98%)
 rename app/{ => Auth/Permissions}/EntityPermission.php (84%)
 rename app/{ => Auth/Permissions}/JointPermission.php (80%)
 rename app/{Services => Auth/Permissions}/PermissionService.php (95%)
 rename app/{Repos => Auth/Permissions}/PermissionsRepo.php (93%)
 rename app/{ => Auth/Permissions}/RolePermission.php (83%)
 rename app/{ => Auth}/Role.php (77%)
 rename app/{ => Auth}/SocialAccount.php (71%)
 rename app/{ => Auth}/User.php (97%)
 rename app/{Repos => Auth}/UserRepo.php (94%)
 rename app/{ => Entities}/Book.php (91%)
 rename app/{ => Entities}/Bookshelf.php (91%)
 rename app/{ => Entities}/Chapter.php (86%)
 rename app/{ => Entities}/Entity.php (88%)
 create mode 100644 app/Entities/EntityProvider.php
 rename app/{Repos => Entities}/EntityRepo.php (94%)
 rename app/{Services => Entities}/ExportService.php (94%)
 rename app/{ => Entities}/Page.php (89%)
 rename app/{ => Entities}/PageRevision.php (93%)
 rename app/{Services => Entities}/SearchService.php (97%)
 rename app/{ => Entities}/SearchTerm.php (85%)
 rename app/{Services => }/Facades/Activity.php (85%)
 rename app/{Services => }/Facades/Images.php (85%)
 rename app/{Services => }/Facades/Setting.php (85%)
 rename app/{Services => }/Facades/Views.php (85%)
 rename app/{ => Settings}/Setting.php (68%)
 rename app/{Services => Settings}/SettingService.php (97%)
 rename app/{ => Uploads}/Attachment.php (90%)
 rename app/{Services => Uploads}/AttachmentService.php (98%)
 rename app/{ => Uploads}/Image.php (88%)
 rename app/{Repos => Uploads}/ImageRepo.php (95%)
 rename app/{Services => Uploads}/ImageService.php (98%)
 rename app/{Services => Uploads}/UploadService.php (93%)

diff --git a/app/Activity.php b/app/Actions/Activity.php
similarity index 93%
rename from app/Activity.php
rename to app/Actions/Activity.php
index c01da1f6c..1ae1811e1 100644
--- a/app/Activity.php
+++ b/app/Actions/Activity.php
@@ -1,6 +1,9 @@
 <?php
 
-namespace BookStack;
+namespace BookStack\Actions;
+
+use BookStack\Auth\User;
+use BookStack\Model;
 
 /**
  * @property string  key
diff --git a/app/Services/ActivityService.php b/app/Actions/ActivityService.php
similarity index 96%
rename from app/Services/ActivityService.php
rename to app/Actions/ActivityService.php
index 3fc7e7ee0..7b1046d22 100644
--- a/app/Services/ActivityService.php
+++ b/app/Actions/ActivityService.php
@@ -1,7 +1,8 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Actions;
 
-use BookStack\Activity;
-use BookStack\Entity;
+use BookStack\Actions\Activity;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Entities\Entity;
 use Session;
 
 class ActivityService
@@ -12,7 +13,7 @@ class ActivityService
 
     /**
      * ActivityService constructor.
-     * @param Activity $activity
+     * @param \BookStack\Actions\Activity $activity
      * @param PermissionService $permissionService
      */
     public function __construct(Activity $activity, PermissionService $permissionService)
diff --git a/app/Comment.php b/app/Actions/Comment.php
similarity index 94%
rename from app/Comment.php
rename to app/Actions/Comment.php
index 2800ab21a..f138ee4a1 100644
--- a/app/Comment.php
+++ b/app/Actions/Comment.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Actions;
+
+use BookStack\Ownable;
 
 class Comment extends Ownable
 {
diff --git a/app/Repos/CommentRepo.php b/app/Actions/CommentRepo.php
similarity index 76%
rename from app/Repos/CommentRepo.php
rename to app/Actions/CommentRepo.php
index 7f89e7f8d..3422d141b 100644
--- a/app/Repos/CommentRepo.php
+++ b/app/Actions/CommentRepo.php
@@ -1,7 +1,7 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Actions;
 
-use BookStack\Comment;
-use BookStack\Entity;
+use BookStack\Actions\Comment;
+use BookStack\Entities\Entity;
 
 /**
  * Class CommentRepo
@@ -11,13 +11,13 @@ class CommentRepo
 {
 
     /**
-     * @var Comment $comment
+     * @var \BookStack\Actions\Comment $comment
      */
     protected $comment;
 
     /**
      * CommentRepo constructor.
-     * @param Comment $comment
+     * @param \BookStack\Actions\Comment $comment
      */
     public function __construct(Comment $comment)
     {
@@ -27,7 +27,7 @@ class CommentRepo
     /**
      * Get a comment by ID.
      * @param $id
-     * @return Comment|\Illuminate\Database\Eloquent\Model
+     * @return \BookStack\Actions\Comment|\Illuminate\Database\Eloquent\Model
      */
     public function getById($id)
     {
@@ -36,9 +36,9 @@ class CommentRepo
 
     /**
      * Create a new comment on an entity.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @param array $data
-     * @return Comment
+     * @return \BookStack\Actions\Comment
      */
     public function create(Entity $entity, $data = [])
     {
@@ -53,7 +53,7 @@ class CommentRepo
 
     /**
      * Update an existing comment.
-     * @param Comment $comment
+     * @param \BookStack\Actions\Comment $comment
      * @param array $input
      * @return mixed
      */
@@ -66,7 +66,7 @@ class CommentRepo
 
     /**
      * Delete a comment from the system.
-     * @param Comment $comment
+     * @param \BookStack\Actions\Comment $comment
      * @return mixed
      */
     public function delete($comment)
@@ -76,7 +76,7 @@ class CommentRepo
 
     /**
      * Get the next local ID relative to the linked entity.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @return int
      */
     protected function getNextLocalId(Entity $entity)
diff --git a/app/Tag.php b/app/Actions/Tag.php
similarity index 85%
rename from app/Tag.php
rename to app/Actions/Tag.php
index 51f622c38..38d0458e4 100644
--- a/app/Tag.php
+++ b/app/Actions/Tag.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Actions;
+
+use BookStack\Model;
 
 /**
  * Class Attribute
diff --git a/app/Repos/TagRepo.php b/app/Actions/TagRepo.php
similarity index 91%
rename from app/Repos/TagRepo.php
rename to app/Actions/TagRepo.php
index ab1805ab3..87023674c 100644
--- a/app/Repos/TagRepo.php
+++ b/app/Actions/TagRepo.php
@@ -1,8 +1,7 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Actions;
 
-use BookStack\Tag;
-use BookStack\Entity;
-use BookStack\Services\PermissionService;
+use BookStack\Entities\Entity;
+use BookStack\Auth\Permissions\PermissionService;
 
 /**
  * Class TagRepo
@@ -17,9 +16,9 @@ class TagRepo
 
     /**
      * TagRepo constructor.
-     * @param Tag $attr
-     * @param Entity $ent
-     * @param PermissionService $ps
+     * @param \BookStack\Actions\Tag $attr
+     * @param \BookStack\Entities\Entity $ent
+     * @param \BookStack\Auth\Permissions\PermissionService $ps
      */
     public function __construct(Tag $attr, Entity $ent, PermissionService $ps)
     {
@@ -107,7 +106,7 @@ class TagRepo
 
     /**
      * Save an array of tags to an entity
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @param array $tags
      * @return array|\Illuminate\Database\Eloquent\Collection
      */
@@ -128,7 +127,7 @@ class TagRepo
     /**
      * Create a new Tag instance from user input.
      * @param $input
-     * @return Tag
+     * @return \BookStack\Actions\Tag
      */
     protected function newInstanceFromInput($input)
     {
diff --git a/app/View.php b/app/Actions/View.php
similarity index 82%
rename from app/View.php
rename to app/Actions/View.php
index c02550c7c..e9841293b 100644
--- a/app/View.php
+++ b/app/Actions/View.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Actions;
+
+use BookStack\Model;
 
 class View extends Model
 {
diff --git a/app/Services/ViewService.php b/app/Actions/ViewService.php
similarity index 85%
rename from app/Services/ViewService.php
rename to app/Actions/ViewService.php
index cd869018c..d5f8002fc 100644
--- a/app/Services/ViewService.php
+++ b/app/Actions/ViewService.php
@@ -1,7 +1,7 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Actions;
 
-use BookStack\Entity;
-use BookStack\View;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Entities\Entity;
 
 class ViewService
 {
@@ -10,8 +10,8 @@ class ViewService
 
     /**
      * ViewService constructor.
-     * @param View $view
-     * @param PermissionService $permissionService
+     * @param \BookStack\Actions\View $view
+     * @param \BookStack\Auth\Permissions\PermissionService $permissionService
      */
     public function __construct(View $view, PermissionService $permissionService)
     {
@@ -50,12 +50,13 @@ class ViewService
      * Get the entities with the most views.
      * @param int $count
      * @param int $page
-     * @param bool|false|array $filterModel
+     * @param Entity|false|array $filterModel
      * @param string $action - used for permission checking
      * @return
      */
     public function getPopular($count = 10, $page = 0, $filterModel = false, $action = 'view')
     {
+        // TODO - Standardise input filter
         $skipCount = $count * $page;
         $query = $this->permissionService->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type', $action)
             ->select('*', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
@@ -65,7 +66,7 @@ class ViewService
         if ($filterModel && is_array($filterModel)) {
             $query->whereIn('viewable_type', $filterModel);
         } else if ($filterModel) {
-            $query->where('viewable_type', '=', get_class($filterModel));
+            $query->where('viewable_type', '=', $filterModel->getMorphClass());
         }
 
         return $query->with('viewable')->skip($skipCount)->take($count)->get()->pluck('viewable');
@@ -89,7 +90,7 @@ class ViewService
             ->filterRestrictedEntityRelations($this->view, 'views', 'viewable_id', 'viewable_type');
 
         if ($filterModel) {
-            $query = $query->where('viewable_type', '=', get_class($filterModel));
+            $query = $query->where('viewable_type', '=', $filterModel->getMorphClass());
         }
         $query = $query->where('user_id', '=', $user->id);
 
diff --git a/app/Services/EmailConfirmationService.php b/app/Auth/Access/EmailConfirmationService.php
similarity index 93%
rename from app/Services/EmailConfirmationService.php
rename to app/Auth/Access/EmailConfirmationService.php
index 9ee69ef1a..b14eb8c3f 100644
--- a/app/Services/EmailConfirmationService.php
+++ b/app/Auth/Access/EmailConfirmationService.php
@@ -1,11 +1,11 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Auth\Access;
 
 use BookStack\Notifications\ConfirmEmail;
-use BookStack\Repos\UserRepo;
+use BookStack\Auth\UserRepo;
 use Carbon\Carbon;
 use BookStack\Exceptions\ConfirmationEmailException;
 use BookStack\Exceptions\UserRegistrationException;
-use BookStack\User;
+use BookStack\Auth\User;
 use Illuminate\Database\Connection as Database;
 
 class EmailConfirmationService
@@ -16,7 +16,7 @@ class EmailConfirmationService
     /**
      * EmailConfirmationService constructor.
      * @param Database $db
-     * @param UserRepo $users
+     * @param \BookStack\Auth\UserRepo $users
      */
     public function __construct(Database $db, UserRepo $users)
     {
@@ -27,7 +27,7 @@ class EmailConfirmationService
     /**
      * Create new confirmation for a user,
      * Also removes any existing old ones.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @throws ConfirmationEmailException
      */
     public function sendConfirmation(User $user)
@@ -88,7 +88,7 @@ class EmailConfirmationService
 
     /**
      * Delete all email confirmations that belong to a user.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @return mixed
      */
     public function deleteConfirmationsByUser(User $user)
diff --git a/app/Services/Ldap.php b/app/Auth/Access/Ldap.php
similarity index 98%
rename from app/Services/Ldap.php
rename to app/Auth/Access/Ldap.php
index 29270daf5..468c37626 100644
--- a/app/Services/Ldap.php
+++ b/app/Auth/Access/Ldap.php
@@ -1,4 +1,4 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Auth\Access;
 
 /**
  * Class Ldap
diff --git a/app/Services/LdapService.php b/app/Auth/Access/LdapService.php
similarity index 96%
rename from app/Services/LdapService.php
rename to app/Auth/Access/LdapService.php
index 16cee9f7d..4fbf29365 100644
--- a/app/Services/LdapService.php
+++ b/app/Auth/Access/LdapService.php
@@ -1,9 +1,11 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Auth\Access;
 
+use BookStack\Auth\Access;
 use BookStack\Exceptions\LdapException;
-use BookStack\Repos\UserRepo;
-use BookStack\Role;
-use BookStack\User;
+use BookStack\Auth\UserRepo;
+use BookStack\Auth\Role;
+use BookStack\Auth\User;
+use BookStack\Auth\Access\Ldap;
 use Illuminate\Contracts\Auth\Authenticatable;
 use Illuminate\Database\Eloquent\Builder;
 
@@ -24,9 +26,9 @@ class LdapService
     /**
      * LdapService constructor.
      * @param Ldap $ldap
-     * @param UserRepo $userRepo
+     * @param \BookStack\Auth\UserRepo $userRepo
      */
-    public function __construct(Ldap $ldap, UserRepo $userRepo)
+    public function __construct(Access\Ldap $ldap, UserRepo $userRepo)
     {
         $this->ldap = $ldap;
         $this->config = config('services.ldap');
@@ -298,7 +300,7 @@ class LdapService
 
     /**
      * Sync the LDAP groups to the user roles for the current user
-     * @param \BookStack\User $user
+     * @param \BookStack\Auth\User $user
      * @param string $username
      * @throws LdapException
      */
@@ -347,7 +349,7 @@ class LdapService
     /**
      * Check a role against an array of group names to see if it matches.
      * Checked against role 'external_auth_id' if set otherwise the name of the role.
-     * @param Role $role
+     * @param \BookStack\Auth\Role $role
      * @param array $groupNames
      * @return bool
      */
diff --git a/app/Services/SocialAuthService.php b/app/Auth/Access/SocialAuthService.php
similarity index 98%
rename from app/Services/SocialAuthService.php
rename to app/Auth/Access/SocialAuthService.php
index 9017dfebe..005380f5b 100644
--- a/app/Services/SocialAuthService.php
+++ b/app/Auth/Access/SocialAuthService.php
@@ -1,11 +1,11 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Auth\Access;
 
 use BookStack\Exceptions\SocialSignInAccountNotUsed;
 use Laravel\Socialite\Contracts\Factory as Socialite;
 use BookStack\Exceptions\SocialDriverNotConfigured;
 use BookStack\Exceptions\UserRegistrationException;
-use BookStack\Repos\UserRepo;
-use BookStack\SocialAccount;
+use BookStack\Auth\UserRepo;
+use BookStack\Auth\SocialAccount;
 use Laravel\Socialite\Contracts\User as SocialUser;
 
 class SocialAuthService
@@ -19,7 +19,7 @@ class SocialAuthService
 
     /**
      * SocialAuthService constructor.
-     * @param UserRepo      $userRepo
+     * @param \BookStack\Auth\UserRepo      $userRepo
      * @param Socialite     $socialite
      * @param SocialAccount $socialAccount
      */
diff --git a/app/EntityPermission.php b/app/Auth/Permissions/EntityPermission.php
similarity index 84%
rename from app/EntityPermission.php
rename to app/Auth/Permissions/EntityPermission.php
index 0f49e07f5..ef61e03ce 100644
--- a/app/EntityPermission.php
+++ b/app/Auth/Permissions/EntityPermission.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth\Permissions;
+
+use BookStack\Model;
 
 class EntityPermission extends Model
 {
diff --git a/app/JointPermission.php b/app/Auth/Permissions/JointPermission.php
similarity index 80%
rename from app/JointPermission.php
rename to app/Auth/Permissions/JointPermission.php
index 6d0b0212e..71c1979fc 100644
--- a/app/JointPermission.php
+++ b/app/Auth/Permissions/JointPermission.php
@@ -1,4 +1,8 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth\Permissions;
+
+use BookStack\Entities\Entity;
+use BookStack\Model;
+use BookStack\Auth\Role;
 
 class JointPermission extends Model
 {
diff --git a/app/Services/PermissionService.php b/app/Auth/Permissions/PermissionService.php
similarity index 95%
rename from app/Services/PermissionService.php
rename to app/Auth/Permissions/PermissionService.php
index 045824517..aae3980c1 100644
--- a/app/Services/PermissionService.php
+++ b/app/Auth/Permissions/PermissionService.php
@@ -1,15 +1,16 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Auth\Permissions;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Chapter;
-use BookStack\Entity;
-use BookStack\EntityPermission;
-use BookStack\JointPermission;
+use BookStack\Auth\Permissions;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
+use BookStack\Auth\Permissions\EntityPermission;
+use BookStack\Auth\Permissions\JointPermission;
 use BookStack\Ownable;
-use BookStack\Page;
-use BookStack\Role;
-use BookStack\User;
+use BookStack\Entities\Page;
+use BookStack\Auth\Role;
+use BookStack\Auth\User;
 use Illuminate\Database\Connection;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Query\Builder as QueryBuilder;
@@ -44,12 +45,12 @@ class PermissionService
      * @param Connection $db
      * @param Bookshelf $bookshelf
      * @param Book $book
-     * @param Chapter $chapter
-     * @param Page $page
+     * @param \BookStack\Entities\Chapter $chapter
+     * @param \BookStack\Entities\Page $page
      */
     public function __construct(
         JointPermission $jointPermission,
-        EntityPermission $entityPermission,
+        Permissions\EntityPermission $entityPermission,
         Role $role,
         Connection $db,
         Bookshelf $bookshelf,
@@ -78,7 +79,7 @@ class PermissionService
 
     /**
      * Prepare the local entity cache and ensure it's empty
-     * @param Entity[] $entities
+     * @param \BookStack\Entities\Entity[] $entities
      */
     protected function readyEntityCache($entities = [])
     {
@@ -115,7 +116,7 @@ class PermissionService
     /**
      * Get a chapter via ID, Checks local cache
      * @param $chapterId
-     * @return Book
+     * @return \BookStack\Entities\Book
      */
     protected function getChapter($chapterId)
     {
@@ -234,7 +235,7 @@ class PermissionService
 
     /**
      * Rebuild the entity jointPermissions for a particular entity.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @throws \Throwable
      */
     public function buildJointPermissionsForEntity(Entity $entity)
@@ -329,7 +330,7 @@ class PermissionService
 
     /**
      * Delete all of the entity jointPermissions for a list of entities.
-     * @param Entity[] $entities
+     * @param \BookStack\Entities\Entity[] $entities
      * @throws \Throwable
      */
     protected function deleteManyJointPermissionsForEntities($entities)
@@ -410,7 +411,7 @@ class PermissionService
 
     /**
      * Get the actions related to an entity.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @return array
      */
     protected function getActions(Entity $entity)
@@ -496,7 +497,7 @@ class PermissionService
     /**
      * Create an array of data with the information of an entity jointPermissions.
      * Used to build data for bulk insertion.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @param Role $role
      * @param $action
      * @param $permissionAll
@@ -554,7 +555,7 @@ class PermissionService
     /**
      * Check if an entity has restrictions set on itself or its
      * parent tree.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @param $action
      * @return bool|mixed
      */
@@ -635,7 +636,7 @@ class PermissionService
     /**
      * Add restrictions for a generic entity
      * @param string $entityType
-     * @param Builder|Entity $query
+     * @param Builder|\BookStack\Entities\Entity $query
      * @param string $action
      * @return Builder
      */
@@ -703,12 +704,13 @@ class PermissionService
         $this->currentAction = 'view';
         $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn];
 
-        $q = $query->where(function ($query) use ($tableDetails) {
-            $query->where(function ($query) use (&$tableDetails) {
-                $query->whereExists(function ($permissionQuery) use (&$tableDetails) {
+        $pageMorphClass = $this->page->getMorphClass();
+        $q = $query->where(function ($query) use ($tableDetails, $pageMorphClass) {
+            $query->where(function ($query) use (&$tableDetails, $pageMorphClass) {
+                $query->whereExists(function ($permissionQuery) use (&$tableDetails, $pageMorphClass) {
                     $permissionQuery->select('id')->from('joint_permissions')
                         ->whereRaw('joint_permissions.entity_id=' . $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn'])
-                        ->where('entity_type', '=', 'Bookstack\\Page')
+                        ->where('entity_type', '=', $pageMorphClass)
                         ->where('action', '=', $this->currentAction)
                         ->whereIn('role_id', $this->getRoles())
                         ->where(function ($query) {
@@ -726,7 +728,7 @@ class PermissionService
 
     /**
      * Get the current user
-     * @return User
+     * @return \BookStack\Auth\User
      */
     private function currentUser()
     {
diff --git a/app/Repos/PermissionsRepo.php b/app/Auth/Permissions/PermissionsRepo.php
similarity index 93%
rename from app/Repos/PermissionsRepo.php
rename to app/Auth/Permissions/PermissionsRepo.php
index 68c9270be..98a8a9f14 100644
--- a/app/Repos/PermissionsRepo.php
+++ b/app/Auth/Permissions/PermissionsRepo.php
@@ -1,9 +1,10 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Auth\Permissions;
 
+use BookStack\Auth\Permissions;
 use BookStack\Exceptions\PermissionsException;
-use BookStack\RolePermission;
-use BookStack\Role;
-use BookStack\Services\PermissionService;
+use BookStack\Auth\Permissions\RolePermission;
+use BookStack\Auth\Role;
+use BookStack\Auth\Permissions\PermissionService;
 use Setting;
 
 class PermissionsRepo
@@ -19,9 +20,9 @@ class PermissionsRepo
      * PermissionsRepo constructor.
      * @param RolePermission $permission
      * @param Role $role
-     * @param PermissionService $permissionService
+     * @param \BookStack\Auth\Permissions\PermissionService $permissionService
      */
-    public function __construct(RolePermission $permission, Role $role, PermissionService $permissionService)
+    public function __construct(RolePermission $permission, Role $role, Permissions\PermissionService $permissionService)
     {
         $this->permission = $permission;
         $this->role = $role;
diff --git a/app/RolePermission.php b/app/Auth/Permissions/RolePermission.php
similarity index 83%
rename from app/RolePermission.php
rename to app/Auth/Permissions/RolePermission.php
index 366c16749..8b07b3073 100644
--- a/app/RolePermission.php
+++ b/app/Auth/Permissions/RolePermission.php
@@ -1,4 +1,7 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth\Permissions;
+
+use BookStack\Auth\Role;
+use BookStack\Model;
 
 class RolePermission extends Model
 {
diff --git a/app/Role.php b/app/Auth/Role.php
similarity index 77%
rename from app/Role.php
rename to app/Auth/Role.php
index 54a5bb180..b32954767 100644
--- a/app/Role.php
+++ b/app/Auth/Role.php
@@ -1,4 +1,8 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth;
+
+use BookStack\Auth\Permissions\JointPermission;
+use BookStack\Model;
+use BookStack\Auth\Permissions\RolePermission;
 
 class Role extends Model
 {
@@ -27,7 +31,7 @@ class Role extends Model
      */
     public function permissions()
     {
-        return $this->belongsToMany(RolePermission::class, 'permission_role', 'role_id', 'permission_id');
+        return $this->belongsToMany(Permissions\RolePermission::class, 'permission_role', 'role_id', 'permission_id');
     }
 
     /**
@@ -48,18 +52,18 @@ class Role extends Model
 
     /**
      * Add a permission to this role.
-     * @param RolePermission $permission
+     * @param \BookStack\Auth\Permissions\RolePermission $permission
      */
-    public function attachPermission(RolePermission $permission)
+    public function attachPermission(Permissions\RolePermission $permission)
     {
         $this->permissions()->attach($permission->id);
     }
 
     /**
      * Detach a single permission from this role.
-     * @param RolePermission $permission
+     * @param \BookStack\Auth\Permissions\RolePermission $permission
      */
-    public function detachPermission(RolePermission $permission)
+    public function detachPermission(Permissions\RolePermission $permission)
     {
         $this->permissions()->detach($permission->id);
     }
diff --git a/app/SocialAccount.php b/app/Auth/SocialAccount.php
similarity index 71%
rename from app/SocialAccount.php
rename to app/Auth/SocialAccount.php
index fdba6a04f..7d0dbaafc 100644
--- a/app/SocialAccount.php
+++ b/app/Auth/SocialAccount.php
@@ -1,4 +1,7 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth;
+
+use BookStack\Auth\User;
+use BookStack\Model;
 
 class SocialAccount extends Model
 {
diff --git a/app/User.php b/app/Auth/User.php
similarity index 97%
rename from app/User.php
rename to app/Auth/User.php
index d1e9b38a7..0f3de122c 100644
--- a/app/User.php
+++ b/app/Auth/User.php
@@ -1,6 +1,10 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Auth;
 
+use BookStack\Uploads\Image;
+use BookStack\Model;
 use BookStack\Notifications\ResetPassword;
+use BookStack\Auth\Role;
+use BookStack\Auth\SocialAccount;
 use Illuminate\Auth\Authenticatable;
 use Illuminate\Auth\Passwords\CanResetPassword;
 use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
diff --git a/app/Repos/UserRepo.php b/app/Auth/UserRepo.php
similarity index 94%
rename from app/Repos/UserRepo.php
rename to app/Auth/UserRepo.php
index 5143366fe..87c0328d6 100644
--- a/app/Repos/UserRepo.php
+++ b/app/Auth/UserRepo.php
@@ -1,10 +1,11 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Auth;
 
 use Activity;
+use BookStack\Entities\EntityRepo;
 use BookStack\Exceptions\NotFoundException;
-use BookStack\Image;
-use BookStack\Role;
-use BookStack\User;
+use BookStack\Uploads\Image;
+use BookStack\Auth\Role;
+use BookStack\Auth\User;
 use Exception;
 use Images;
 
@@ -80,7 +81,7 @@ class UserRepo
      * Creates a new user and attaches a role to them.
      * @param array $data
      * @param boolean $verifyEmail
-     * @return User
+     * @return \BookStack\Auth\User
      */
     public function registerNew(array $data, $verifyEmail = false)
     {
@@ -122,7 +123,7 @@ class UserRepo
 
     /**
      * Checks if the give user is the only admin.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @return bool
      */
     public function isOnlyAdmin(User $user)
@@ -142,7 +143,7 @@ class UserRepo
      * Create a new basic instance of user.
      * @param array $data
      * @param boolean $verifyEmail
-     * @return User
+     * @return \BookStack\Auth\User
      */
     public function create(array $data, $verifyEmail = false)
     {
@@ -157,7 +158,7 @@ class UserRepo
 
     /**
      * Remove the given user from storage, Delete all related content.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @throws Exception
      */
     public function destroy(User $user)
@@ -174,7 +175,7 @@ class UserRepo
 
     /**
      * Get the latest activity for a user.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @param int $count
      * @param int $page
      * @return array
@@ -186,7 +187,7 @@ class UserRepo
 
     /**
      * Get the recently created content for this given user.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @param int $count
      * @return mixed
      */
@@ -207,7 +208,7 @@ class UserRepo
 
     /**
      * Get asset created counts for the give user.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @return array
      */
     public function getAssetCounts(User $user)
diff --git a/app/Console/Commands/CleanupImages.php b/app/Console/Commands/CleanupImages.php
index 8e1539702..f2e2d9fbd 100644
--- a/app/Console/Commands/CleanupImages.php
+++ b/app/Console/Commands/CleanupImages.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Services\ImageService;
+use BookStack\Uploads\ImageService;
 use Illuminate\Console\Command;
 use Symfony\Component\Console\Output\OutputInterface;
 
@@ -30,7 +30,7 @@ class CleanupImages extends Command
 
     /**
      * Create a new command instance.
-     * @param ImageService $imageService
+     * @param \BookStack\Uploads\ImageService $imageService
      */
     public function __construct(ImageService $imageService)
     {
diff --git a/app/Console/Commands/ClearActivity.php b/app/Console/Commands/ClearActivity.php
index 66babd9a9..932ba7ddd 100644
--- a/app/Console/Commands/ClearActivity.php
+++ b/app/Console/Commands/ClearActivity.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Activity;
+use BookStack\Actions\Activity;
 use Illuminate\Console\Command;
 
 class ClearActivity extends Command
diff --git a/app/Console/Commands/ClearRevisions.php b/app/Console/Commands/ClearRevisions.php
index f0c8a5e85..15f1fcc0a 100644
--- a/app/Console/Commands/ClearRevisions.php
+++ b/app/Console/Commands/ClearRevisions.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\PageRevision;
+use BookStack\Entities\PageRevision;
 use Illuminate\Console\Command;
 
 class ClearRevisions extends Command
diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php
index c7a9969e8..6bfc54469 100644
--- a/app/Console/Commands/CreateAdmin.php
+++ b/app/Console/Commands/CreateAdmin.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Repos\UserRepo;
+use BookStack\Auth\UserRepo;
 use Illuminate\Console\Command;
 
 class CreateAdmin extends Command
diff --git a/app/Console/Commands/DeleteUsers.php b/app/Console/Commands/DeleteUsers.php
index 6dba83e13..68c5bb738 100644
--- a/app/Console/Commands/DeleteUsers.php
+++ b/app/Console/Commands/DeleteUsers.php
@@ -2,8 +2,8 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\User;
-use BookStack\Repos\UserRepo;
+use BookStack\Auth\User;
+use BookStack\Auth\UserRepo;
 use Illuminate\Console\Command;
 
 class DeleteUsers extends Command
diff --git a/app/Console/Commands/RegeneratePermissions.php b/app/Console/Commands/RegeneratePermissions.php
index 9cd577a17..430b8fcb0 100644
--- a/app/Console/Commands/RegeneratePermissions.php
+++ b/app/Console/Commands/RegeneratePermissions.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Services\PermissionService;
+use BookStack\Auth\Permissions\PermissionService;
 use Illuminate\Console\Command;
 
 class RegeneratePermissions extends Command
@@ -31,7 +31,7 @@ class RegeneratePermissions extends Command
     /**
      * Create a new command instance.
      *
-     * @param PermissionService $permissionService
+     * @param \BookStack\Auth\\BookStack\Auth\Permissions\PermissionService $permissionService
      */
     public function __construct(PermissionService $permissionService)
     {
diff --git a/app/Console/Commands/RegenerateSearch.php b/app/Console/Commands/RegenerateSearch.php
index 1a0005544..d27d73edc 100644
--- a/app/Console/Commands/RegenerateSearch.php
+++ b/app/Console/Commands/RegenerateSearch.php
@@ -2,7 +2,7 @@
 
 namespace BookStack\Console\Commands;
 
-use BookStack\Services\SearchService;
+use BookStack\Entities\SearchService;
 use Illuminate\Console\Command;
 
 class RegenerateSearch extends Command
@@ -26,7 +26,7 @@ class RegenerateSearch extends Command
     /**
      * Create a new command instance.
      *
-     * @param SearchService $searchService
+     * @param \BookStack\Entities\SearchService $searchService
      */
     public function __construct(SearchService $searchService)
     {
diff --git a/app/Book.php b/app/Entities/Book.php
similarity index 91%
rename from app/Book.php
rename to app/Entities/Book.php
index 4e944ce10..b8a29322d 100644
--- a/app/Book.php
+++ b/app/Entities/Book.php
@@ -1,4 +1,7 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Uploads\Image;
+use BookStack\Entities\Page;
 
 class Book extends Entity
 {
@@ -6,6 +9,15 @@ class Book extends Entity
 
     protected $fillable = ['name', 'description', 'image_id'];
 
+    /**
+     * Get the morph class for this model.
+     * @return string
+     */
+    public function getMorphClass()
+    {
+        return 'BookStack\\Book';
+    }
+
     /**
      * Get the url for this book.
      * @param string|bool $path
diff --git a/app/Bookshelf.php b/app/Entities/Bookshelf.php
similarity index 91%
rename from app/Bookshelf.php
rename to app/Entities/Bookshelf.php
index 9468575c3..c37e36b59 100644
--- a/app/Bookshelf.php
+++ b/app/Entities/Bookshelf.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Uploads\Image;
 
 class Bookshelf extends Entity
 {
@@ -8,6 +10,15 @@ class Bookshelf extends Entity
 
     protected $fillable = ['name', 'description', 'image_id'];
 
+    /**
+     * Get the morph class for this model.
+     * @return string
+     */
+    public function getMorphClass()
+    {
+        return 'BookStack\\Bookshelf';
+    }
+
     /**
      * Get the books in this shelf.
      * Should not be used directly since does not take into account permissions.
diff --git a/app/Chapter.php b/app/Entities/Chapter.php
similarity index 86%
rename from app/Chapter.php
rename to app/Entities/Chapter.php
index 88b4c134c..8638e3c9e 100644
--- a/app/Chapter.php
+++ b/app/Entities/Chapter.php
@@ -1,4 +1,8 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Entities\Book;
+use BookStack\Entities\Entity;
+use BookStack\Entities\Page;
 
 class Chapter extends Entity
 {
@@ -6,6 +10,15 @@ class Chapter extends Entity
 
     protected $fillable = ['name', 'description', 'priority', 'book_id'];
 
+    /**
+     * Get the morph class for this model.
+     * @return string
+     */
+    public function getMorphClass()
+    {
+        return 'BookStack\\Chapter';
+    }
+
     /**
      * Get the book this chapter is within.
      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
diff --git a/app/Entity.php b/app/Entities/Entity.php
similarity index 88%
rename from app/Entity.php
rename to app/Entities/Entity.php
index 252a3e07a..87d679fdb 100644
--- a/app/Entity.php
+++ b/app/Entities/Entity.php
@@ -1,5 +1,12 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
 
+use BookStack\Actions\Activity;
+use BookStack\Actions\Comment;
+use BookStack\Auth\Permissions\EntityPermission;
+use BookStack\Auth\Permissions\JointPermission;
+use BookStack\Ownable;
+use BookStack\Actions\Tag;
+use BookStack\Actions\View;
 use Illuminate\Database\Eloquent\Relations\MorphMany;
 
 class Entity extends Ownable
@@ -15,6 +22,17 @@ class Entity extends Ownable
      */
     public $searchFactor = 1.0;
 
+    /**
+     * Get the morph class for this model.
+     * Set here since, due to folder changes, the namespace used
+     * in the database no longer matches the class namespace.
+     * @return string
+     */
+    public function getMorphClass()
+    {
+        return 'BookStack\\Entity';
+    }
+
     /**
      * Compares this entity to another given entity.
      * Matches by comparing class and id.
@@ -158,7 +176,7 @@ class Entity extends Ownable
             return null;
         }
 
-        return app('BookStack\\' . $className);
+        return app('BookStack\\Entities\\' . $className);
     }
 
     /**
diff --git a/app/Entities/EntityProvider.php b/app/Entities/EntityProvider.php
new file mode 100644
index 000000000..51e3ad060
--- /dev/null
+++ b/app/Entities/EntityProvider.php
@@ -0,0 +1,7 @@
+<?php namespace BookStack\Entities;
+
+
+class EntityProvider
+{
+    // TODO -
+}
\ No newline at end of file
diff --git a/app/Repos/EntityRepo.php b/app/Entities/EntityRepo.php
similarity index 94%
rename from app/Repos/EntityRepo.php
rename to app/Entities/EntityRepo.php
index d6736886e..2031807ee 100644
--- a/app/Repos/EntityRepo.php
+++ b/app/Entities/EntityRepo.php
@@ -1,17 +1,18 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Entities;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Chapter;
-use BookStack\Entity;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
 use BookStack\Exceptions\NotFoundException;
 use BookStack\Exceptions\NotifyException;
-use BookStack\Page;
-use BookStack\PageRevision;
-use BookStack\Services\AttachmentService;
-use BookStack\Services\PermissionService;
-use BookStack\Services\SearchService;
-use BookStack\Services\ViewService;
+use BookStack\Entities\Page;
+use BookStack\Entities\PageRevision;
+use BookStack\Actions\TagRepo;
+use BookStack\Uploads\AttachmentService;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Entities\SearchService;
+use BookStack\Actions\ViewService;
 use Carbon\Carbon;
 use DOMDocument;
 use DOMXPath;
@@ -20,12 +21,12 @@ use Illuminate\Support\Collection;
 class EntityRepo
 {
     /**
-     * @var Bookshelf
+     * @var \BookStack\Entities\Bookshelf
      */
     public $bookshelf;
 
     /**
-     * @var Book $book
+     * @var \BookStack\Entities\Book $book
      */
     public $book;
 
@@ -61,7 +62,7 @@ class EntityRepo
     protected $viewService;
 
     /**
-     * @var TagRepo
+     * @var \BookStack\Actions\TagRepo
      */
     protected $tagRepo;
 
@@ -72,14 +73,14 @@ class EntityRepo
 
     /**
      * EntityRepo constructor.
-     * @param Bookshelf $bookshelf
-     * @param Book $book
+     * @param \BookStack\Entities\Bookshelf $bookshelf
+     * @param \BookStack\Entities\Book $book
      * @param Chapter $chapter
-     * @param Page $page
-     * @param PageRevision $pageRevision
+     * @param \BookStack\Entities\Page $page
+     * @param \BookStack\Entities\PageRevision $pageRevision
      * @param ViewService $viewService
      * @param PermissionService $permissionService
-     * @param TagRepo $tagRepo
+     * @param \BookStack\Actions\TagRepo $tagRepo
      * @param SearchService $searchService
      */
     public function __construct(
@@ -113,7 +114,7 @@ class EntityRepo
     /**
      * Get an entity instance via type.
      * @param $type
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      */
     protected function getEntity($type)
     {
@@ -152,7 +153,7 @@ class EntityRepo
      * @param integer $id
      * @param bool $allowDrafts
      * @param bool $ignorePermissions
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      */
     public function getById($type, $id, $allowDrafts = false, $ignorePermissions = false)
     {
@@ -168,7 +169,7 @@ class EntityRepo
      * @param string $type
      * @param string $slug
      * @param string|bool $bookSlug
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      * @throws NotFoundException
      */
     public function getBySlug($type, $slug, $bookSlug = false)
@@ -343,7 +344,7 @@ class EntityRepo
     /**
      * Get the child items for a chapter sorted by priority but
      * with draft items floated to the top.
-     * @param Bookshelf $bookshelf
+     * @param \BookStack\Entities\Bookshelf $bookshelf
      * @return \Illuminate\Database\Eloquent\Collection|static[]
      */
     public function getBookshelfChildren(Bookshelf $bookshelf)
@@ -355,7 +356,7 @@ class EntityRepo
      * Get all child objects of a book.
      * Returns a sorted collection of Pages and Chapters.
      * Loads the book slug onto child elements to prevent access database access for getting the slug.
-     * @param Book $book
+     * @param \BookStack\Entities\Book $book
      * @param bool $filterDrafts
      * @param bool $renderPages
      * @return mixed
@@ -368,13 +369,13 @@ class EntityRepo
         $tree = [];
 
         foreach ($q as $index => $rawEntity) {
-            if ($rawEntity->entity_type === 'BookStack\\Page') {
+            if ($rawEntity->entity_type ===  $this->page->getMorphClass()) {
                 $entities[$index] = $this->page->newFromBuilder($rawEntity);
                 if ($renderPages) {
                     $entities[$index]->html = $rawEntity->html;
                     $entities[$index]->html = $this->renderPage($entities[$index]);
                 };
-            } else if ($rawEntity->entity_type === 'BookStack\\Chapter') {
+            } else if ($rawEntity->entity_type === $this->chapter->getMorphClass()) {
                 $entities[$index] = $this->chapter->newFromBuilder($rawEntity);
                 $key = $entities[$index]->entity_type . ':' . $entities[$index]->id;
                 $parents[$key] = $entities[$index];
@@ -390,7 +391,7 @@ class EntityRepo
             if ($entity->chapter_id === 0 || $entity->chapter_id === '0') {
                 continue;
             }
-            $parentKey = 'BookStack\\Chapter:' . $entity->chapter_id;
+            $parentKey = $this->chapter->getMorphClass() . ':' . $entity->chapter_id;
             if (!isset($parents[$parentKey])) {
                 $tree[] = $entity;
                 continue;
@@ -405,7 +406,7 @@ class EntityRepo
     /**
      * Get the child items for a chapter sorted by priority but
      * with draft items floated to the top.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @return \Illuminate\Database\Eloquent\Collection|static[]
      */
     public function getChapterChildren(Chapter $chapter)
@@ -417,7 +418,7 @@ class EntityRepo
 
     /**
      * Get the next sequential priority for a new child element in the given book.
-     * @param Book $book
+     * @param \BookStack\Entities\Book $book
      * @return int
      */
     public function getNewBookPriority(Book $book)
@@ -428,7 +429,7 @@ class EntityRepo
 
     /**
      * Get a new priority for a new page to be added to the given chapter.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @return int
      */
     public function getNewChapterPriority(Chapter $chapter)
@@ -477,7 +478,7 @@ class EntityRepo
     /**
      * Updates entity restrictions from a request
      * @param $request
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      */
     public function updateEntityPermissionsFromRequest($request, Entity $entity)
     {
@@ -507,7 +508,7 @@ class EntityRepo
      * @param string $type
      * @param array $input
      * @param bool|Book $book
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      */
     public function createFromInput($type, $input = [], $book = false)
     {
@@ -531,9 +532,9 @@ class EntityRepo
      * Update entity details from request input.
      * Used for books and chapters
      * @param string $type
-     * @param Entity $entityModel
+     * @param \BookStack\Entities\Entity $entityModel
      * @param array $input
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      */
     public function updateFromInput($type, Entity $entityModel, $input = [])
     {
@@ -556,7 +557,7 @@ class EntityRepo
     /**
      * Sync the books assigned to a shelf from a comma-separated list
      * of book IDs.
-     * @param Bookshelf $shelf
+     * @param \BookStack\Entities\Bookshelf $shelf
      * @param string $books
      */
     public function updateShelfBooks(Bookshelf $shelf, string $books)
@@ -581,7 +582,7 @@ class EntityRepo
      * @param integer $newBookId
      * @param Entity $entity
      * @param bool $rebuildPermissions
-     * @return Entity
+     * @return \BookStack\Entities\Entity
      */
     public function changeBook($type, $newBookId, Entity $entity, $rebuildPermissions = false)
     {
@@ -639,7 +640,7 @@ class EntityRepo
      * Get a new draft page instance.
      * @param Book $book
      * @param Chapter|bool $chapter
-     * @return Page
+     * @return \BookStack\Entities\Page
      */
     public function getDraftPage(Book $book, $chapter = false)
     {
@@ -689,10 +690,10 @@ class EntityRepo
 
     /**
      * Create a copy of a page in a new location with a new name.
-     * @param Page $page
-     * @param Entity $newParent
+     * @param \BookStack\Entities\Page $page
+     * @param \BookStack\Entities\Entity $newParent
      * @param string $newName
-     * @return Page
+     * @return \BookStack\Entities\Page
      */
     public function copyPage(Page $page, Entity $newParent, $newName = '')
     {
@@ -728,7 +729,7 @@ class EntityRepo
      * Saves a page revision into the system.
      * @param Page $page
      * @param null|string $summary
-     * @return PageRevision
+     * @return \BookStack\Entities\PageRevision
      */
     public function savePageRevision(Page $page, $summary = null)
     {
@@ -902,7 +903,7 @@ class EntityRepo
 
     /**
      * Get the plain text version of a page's content.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @return string
      */
     public function pageToPlainText(Page $page)
@@ -971,10 +972,10 @@ class EntityRepo
 
     /**
      * Updates a page with any fillable data and saves it into the database.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @param int $book_id
      * @param array $input
-     * @return Page
+     * @return \BookStack\Entities\Page
      */
     public function updatePage(Page $page, $book_id, $input)
     {
@@ -1019,7 +1020,7 @@ class EntityRepo
 
     /**
      * The base query for getting user update drafts.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @param $userId
      * @return mixed
      */
@@ -1033,7 +1034,7 @@ class EntityRepo
 
     /**
      * Checks whether a user has a draft version of a particular page or not.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @param $userId
      * @return bool
      */
@@ -1072,7 +1073,7 @@ class EntityRepo
      * Checks for edits since last page updated.
      * Passing in a minuted range will check for edits
      * within the last x minutes.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @param null $minRange
      * @return bool
      */
@@ -1108,7 +1109,7 @@ class EntityRepo
      * @param Page $page
      * @param Book $book
      * @param  int $revisionId
-     * @return Page
+     * @return \BookStack\Entities\Page
      */
     public function restorePageRevision(Page $page, Book $book, $revisionId)
     {
@@ -1184,8 +1185,8 @@ class EntityRepo
 
     /**
      * Change the page's parent to the given entity.
-     * @param Page $page
-     * @param Entity $parent
+     * @param \BookStack\Entities\Page $page
+     * @param \BookStack\Entities\Entity $parent
      */
     public function changePageParent(Page $page, Entity $parent)
     {
@@ -1201,7 +1202,7 @@ class EntityRepo
 
     /**
      * Destroy a bookshelf instance
-     * @param Bookshelf $shelf
+     * @param \BookStack\Entities\Bookshelf $shelf
      * @throws \Throwable
      */
     public function destroyBookshelf(Bookshelf $shelf)
@@ -1212,7 +1213,7 @@ class EntityRepo
 
     /**
      * Destroy the provided book and all its child entities.
-     * @param Book $book
+     * @param \BookStack\Entities\Book $book
      * @throws NotifyException
      * @throws \Throwable
      */
@@ -1230,7 +1231,7 @@ class EntityRepo
 
     /**
      * Destroy a chapter and its relations.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @throws \Throwable
      */
     public function destroyChapter(Chapter $chapter)
@@ -1272,7 +1273,7 @@ class EntityRepo
 
     /**
      * Destroy or handle the common relations connected to an entity.
-     * @param Entity $entity
+     * @param \BookStack\Entities\Entity $entity
      * @throws \Throwable
      */
     protected function destroyEntityCommonRelations(Entity $entity)
@@ -1289,7 +1290,7 @@ class EntityRepo
     /**
      * Copy the permissions of a bookshelf to all child books.
      * Returns the number of books that had permissions updated.
-     * @param Bookshelf $bookshelf
+     * @param \BookStack\Entities\Bookshelf $bookshelf
      * @return int
      * @throws \Throwable
      */
diff --git a/app/Services/ExportService.php b/app/Entities/ExportService.php
similarity index 94%
rename from app/Services/ExportService.php
rename to app/Entities/ExportService.php
index 01e87f167..fc0e4d114 100644
--- a/app/Services/ExportService.php
+++ b/app/Entities/ExportService.php
@@ -1,9 +1,10 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Entities;
 
-use BookStack\Book;
-use BookStack\Chapter;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
+use BookStack\Entities\Book;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
+use BookStack\Uploads\ImageService;
 
 class ExportService
 {
@@ -24,7 +25,7 @@ class ExportService
     /**
      * Convert a page to a self-contained HTML file.
      * Includes required CSS & image content. Images are base64 encoded into the HTML.
-     * @param Page $page
+     * @param \BookStack\Entities\Page $page
      * @return mixed|string
      * @throws \Throwable
      */
@@ -39,7 +40,7 @@ class ExportService
 
     /**
      * Convert a chapter to a self-contained HTML file.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @return mixed|string
      * @throws \Throwable
      */
@@ -89,7 +90,7 @@ class ExportService
 
     /**
      * Convert a chapter to a PDF file.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @return mixed|string
      * @throws \Throwable
      */
@@ -108,7 +109,7 @@ class ExportService
 
     /**
      * Convert a book to a PDF file
-     * @param Book $book
+     * @param \BookStack\Entities\Book $book
      * @return string
      * @throws \Throwable
      */
@@ -208,7 +209,7 @@ class ExportService
 
     /**
      * Convert a chapter into a plain text string.
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Chapter $chapter
      * @return string
      */
     public function chapterToPlainText(Chapter $chapter)
diff --git a/app/Page.php b/app/Entities/Page.php
similarity index 89%
rename from app/Page.php
rename to app/Entities/Page.php
index 5c03e7d66..59de338cb 100644
--- a/app/Page.php
+++ b/app/Entities/Page.php
@@ -1,4 +1,10 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Uploads\Attachment;
+use BookStack\Entities\Book;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
+use BookStack\Entities\PageRevision;
 
 class Page extends Entity
 {
@@ -8,6 +14,15 @@ class Page extends Entity
 
     public $textField = 'text';
 
+    /**
+     * Get the morph class for this model.
+     * @return string
+     */
+    public function getMorphClass()
+    {
+        return 'BookStack\\Page';
+    }
+
     /**
      * Converts this page into a simplified array.
      * @return mixed
@@ -115,7 +130,7 @@ class Page extends Entity
 
     /**
      * Get the current revision for the page if existing
-     * @return \BookStack\PageRevision|null
+     * @return \BookStack\Entities\PageRevision|null
      */
     public function getCurrentRevision()
     {
diff --git a/app/PageRevision.php b/app/Entities/PageRevision.php
similarity index 93%
rename from app/PageRevision.php
rename to app/Entities/PageRevision.php
index ffcc4f9d2..502a71588 100644
--- a/app/PageRevision.php
+++ b/app/Entities/PageRevision.php
@@ -1,4 +1,8 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Entities\Page;
+use BookStack\Model;
+use BookStack\Auth\User;
 
 class PageRevision extends Model
 {
diff --git a/app/Services/SearchService.php b/app/Entities/SearchService.php
similarity index 97%
rename from app/Services/SearchService.php
rename to app/Entities/SearchService.php
index dfde645a1..0bfdab7ea 100644
--- a/app/Services/SearchService.php
+++ b/app/Entities/SearchService.php
@@ -1,11 +1,12 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Entities;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Chapter;
-use BookStack\Entity;
-use BookStack\Page;
-use BookStack\SearchTerm;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
+use BookStack\Entities\Page;
+use BookStack\Entities\SearchTerm;
+use BookStack\Auth\Permissions\PermissionService;
 use Illuminate\Database\Connection;
 use Illuminate\Database\Query\Builder;
 use Illuminate\Database\Query\JoinClause;
@@ -36,8 +37,8 @@ class SearchService
      * SearchService constructor.
      * @param SearchTerm $searchTerm
      * @param Bookshelf $bookshelf
-     * @param Book $book
-     * @param Chapter $chapter
+     * @param \BookStack\Entities\Book $book
+     * @param \BookStack\Entities\Chapter $chapter
      * @param Page $page
      * @param Connection $db
      * @param PermissionService $permissionService
@@ -352,7 +353,7 @@ class SearchService
 
     /**
      * Index multiple Entities at once
-     * @param Entity[] $entities
+     * @param \BookStack\Entities\Entity[] $entities
      */
     protected function indexEntities($entities)
     {
diff --git a/app/SearchTerm.php b/app/Entities/SearchTerm.php
similarity index 85%
rename from app/SearchTerm.php
rename to app/Entities/SearchTerm.php
index ee6c72190..886c4dbc1 100644
--- a/app/SearchTerm.php
+++ b/app/Entities/SearchTerm.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Entities;
+
+use BookStack\Model;
 
 class SearchTerm extends Model
 {
diff --git a/app/Services/Facades/Activity.php b/app/Facades/Activity.php
similarity index 85%
rename from app/Services/Facades/Activity.php
rename to app/Facades/Activity.php
index d24e39dba..30e4b785f 100644
--- a/app/Services/Facades/Activity.php
+++ b/app/Facades/Activity.php
@@ -1,4 +1,4 @@
-<?php namespace BookStack\Services\Facades;
+<?php namespace BookStack\Facades;
 
 use Illuminate\Support\Facades\Facade;
 
diff --git a/app/Services/Facades/Images.php b/app/Facades/Images.php
similarity index 85%
rename from app/Services/Facades/Images.php
rename to app/Facades/Images.php
index ff455287c..fdbd35a99 100644
--- a/app/Services/Facades/Images.php
+++ b/app/Facades/Images.php
@@ -1,4 +1,4 @@
-<?php namespace BookStack\Services\Facades;
+<?php namespace BookStack\Facades;
 
 use Illuminate\Support\Facades\Facade;
 
diff --git a/app/Services/Facades/Setting.php b/app/Facades/Setting.php
similarity index 85%
rename from app/Services/Facades/Setting.php
rename to app/Facades/Setting.php
index ec6e484da..80feef89b 100644
--- a/app/Services/Facades/Setting.php
+++ b/app/Facades/Setting.php
@@ -1,4 +1,4 @@
-<?php namespace BookStack\Services\Facades;
+<?php namespace BookStack\Facades;
 
 use Illuminate\Support\Facades\Facade;
 
diff --git a/app/Services/Facades/Views.php b/app/Facades/Views.php
similarity index 85%
rename from app/Services/Facades/Views.php
rename to app/Facades/Views.php
index f990bc171..f5357112e 100644
--- a/app/Services/Facades/Views.php
+++ b/app/Facades/Views.php
@@ -1,4 +1,4 @@
-<?php namespace BookStack\Services\Facades;
+<?php namespace BookStack\Facades;
 
 use Illuminate\Support\Facades\Facade;
 
diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php
index 74644aa2f..535543177 100644
--- a/app/Http/Controllers/AttachmentController.php
+++ b/app/Http/Controllers/AttachmentController.php
@@ -1,10 +1,10 @@
 <?php namespace BookStack\Http\Controllers;
 
 use BookStack\Exceptions\FileUploadException;
-use BookStack\Attachment;
+use BookStack\Uploads\Attachment;
 use BookStack\Exceptions\NotFoundException;
-use BookStack\Repos\EntityRepo;
-use BookStack\Services\AttachmentService;
+use BookStack\Entities\EntityRepo;
+use BookStack\Uploads\AttachmentService;
 use Illuminate\Http\Request;
 
 class AttachmentController extends Controller
@@ -15,7 +15,7 @@ class AttachmentController extends Controller
 
     /**
      * AttachmentController constructor.
-     * @param AttachmentService $attachmentService
+     * @param \BookStack\Uploads\AttachmentService $attachmentService
      * @param Attachment $attachment
      * @param EntityRepo $entityRepo
      */
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
index c0541c9e2..8ef46c298 100644
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -4,9 +4,9 @@ namespace BookStack\Http\Controllers\Auth;
 
 use BookStack\Exceptions\AuthException;
 use BookStack\Http\Controllers\Controller;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\LdapService;
-use BookStack\Services\SocialAuthService;
+use BookStack\Auth\UserRepo;
+use BookStack\Auth\Access\LdapService;
+use BookStack\Auth\Access\SocialAuthService;
 use Illuminate\Contracts\Auth\Authenticatable;
 use Illuminate\Foundation\Auth\AuthenticatesUsers;
 use Illuminate\Http\Request;
@@ -43,9 +43,9 @@ class LoginController extends Controller
     /**
      * Create a new controller instance.
      *
-     * @param SocialAuthService $socialAuthService
+     * @param \BookStack\Auth\\BookStack\Auth\Access\SocialAuthService $socialAuthService
      * @param LdapService $ldapService
-     * @param UserRepo $userRepo
+     * @param \BookStack\Auth\UserRepo $userRepo
      */
     public function __construct(SocialAuthService $socialAuthService, LdapService $ldapService, UserRepo $userRepo)
     {
diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php
index 385994324..dd60c7416 100644
--- a/app/Http/Controllers/Auth/RegisterController.php
+++ b/app/Http/Controllers/Auth/RegisterController.php
@@ -5,11 +5,11 @@ namespace BookStack\Http\Controllers\Auth;
 use BookStack\Exceptions\SocialSignInAccountNotUsed;
 use BookStack\Exceptions\SocialSignInException;
 use BookStack\Exceptions\UserRegistrationException;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\EmailConfirmationService;
-use BookStack\Services\SocialAuthService;
-use BookStack\SocialAccount;
-use BookStack\User;
+use BookStack\Auth\UserRepo;
+use BookStack\Auth\Access\EmailConfirmationService;
+use BookStack\Auth\Access\SocialAuthService;
+use BookStack\Auth\SocialAccount;
+use BookStack\Auth\User;
 use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
@@ -48,11 +48,11 @@ class RegisterController extends Controller
     /**
      * Create a new controller instance.
      *
-     * @param SocialAuthService $socialAuthService
-     * @param EmailConfirmationService $emailConfirmationService
-     * @param UserRepo $userRepo
+     * @param \BookStack\Auth\Access\SocialAuthService $socialAuthService
+     * @param \BookStack\Auth\EmailConfirmationService $emailConfirmationService
+     * @param \BookStack\Auth\UserRepo $userRepo
      */
-    public function __construct(SocialAuthService $socialAuthService, EmailConfirmationService $emailConfirmationService, UserRepo $userRepo)
+    public function __construct(\BookStack\Auth\Access\SocialAuthService $socialAuthService, \BookStack\Auth\Access\EmailConfirmationService $emailConfirmationService, UserRepo $userRepo)
     {
         $this->middleware('guest')->only(['getRegister', 'postRegister', 'socialRegister']);
         $this->socialAuthService = $socialAuthService;
@@ -119,7 +119,7 @@ class RegisterController extends Controller
     /**
      * Create a new user instance after a valid registration.
      * @param  array  $data
-     * @return User
+     * @return \BookStack\Auth\User
      */
     protected function create(array $data)
     {
diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php
index ea39a771e..045bcd344 100644
--- a/app/Http/Controllers/BookController.php
+++ b/app/Http/Controllers/BookController.php
@@ -1,10 +1,10 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
-use BookStack\Book;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\ExportService;
+use BookStack\Entities\Book;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\UserRepo;
+use BookStack\Entities\ExportService;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
@@ -19,8 +19,8 @@ class BookController extends Controller
     /**
      * BookController constructor.
      * @param EntityRepo $entityRepo
-     * @param UserRepo $userRepo
-     * @param ExportService $exportService
+     * @param \BookStack\Auth\UserRepo $userRepo
+     * @param \BookStack\Entities\ExportService $exportService
      */
     public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService)
     {
diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php
index 8c7f7819e..c1938d754 100644
--- a/app/Http/Controllers/BookshelfController.php
+++ b/app/Http/Controllers/BookshelfController.php
@@ -1,11 +1,11 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\ExportService;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\UserRepo;
+use BookStack\Entities\ExportService;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
@@ -19,9 +19,9 @@ class BookshelfController extends Controller
 
     /**
      * BookController constructor.
-     * @param EntityRepo $entityRepo
+     * @param \BookStack\Entities\EntityRepo $entityRepo
      * @param UserRepo $userRepo
-     * @param ExportService $exportService
+     * @param \BookStack\Entities\ExportService $exportService
      */
     public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService)
     {
diff --git a/app/Http/Controllers/ChapterController.php b/app/Http/Controllers/ChapterController.php
index 1fe231a65..a3f26f7cd 100644
--- a/app/Http/Controllers/ChapterController.php
+++ b/app/Http/Controllers/ChapterController.php
@@ -1,9 +1,9 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\ExportService;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\UserRepo;
+use BookStack\Entities\ExportService;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
@@ -19,7 +19,7 @@ class ChapterController extends Controller
      * ChapterController constructor.
      * @param EntityRepo $entityRepo
      * @param UserRepo $userRepo
-     * @param ExportService $exportService
+     * @param \BookStack\Entities\ExportService $exportService
      */
     public function __construct(EntityRepo $entityRepo, UserRepo $userRepo, ExportService $exportService)
     {
diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php
index 7bf0a2aac..673684cc0 100644
--- a/app/Http/Controllers/CommentController.php
+++ b/app/Http/Controllers/CommentController.php
@@ -1,8 +1,8 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
-use BookStack\Repos\CommentRepo;
-use BookStack\Repos\EntityRepo;
+use BookStack\Actions\CommentRepo;
+use BookStack\Entities\EntityRepo;
 use Illuminate\Database\Eloquent\ModelNotFoundException;
 use Illuminate\Http\Request;
 
@@ -13,8 +13,8 @@ class CommentController extends Controller
 
     /**
      * CommentController constructor.
-     * @param EntityRepo $entityRepo
-     * @param CommentRepo $commentRepo
+     * @param \BookStack\Entities\EntityRepo $entityRepo
+     * @param \BookStack\Actions\CommentRepo $commentRepo
      */
     public function __construct(EntityRepo $entityRepo, CommentRepo $commentRepo)
     {
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
index 33b57b7d9..9c1527e98 100644
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -8,7 +8,7 @@ use Illuminate\Http\Exceptions\HttpResponseException;
 use Illuminate\Http\Request;
 use Illuminate\Routing\Controller as BaseController;
 use Illuminate\Foundation\Validation\ValidatesRequests;
-use BookStack\User;
+use BookStack\Auth\User;
 
 abstract class Controller extends BaseController
 {
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
index e47250318..e9469fafb 100644
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -1,7 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use Activity;
-use BookStack\Repos\EntityRepo;
+use BookStack\Entities\EntityRepo;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
diff --git a/app/Http/Controllers/ImageController.php b/app/Http/Controllers/ImageController.php
index eb92ae9a8..a64608e8e 100644
--- a/app/Http/Controllers/ImageController.php
+++ b/app/Http/Controllers/ImageController.php
@@ -2,11 +2,11 @@
 
 use BookStack\Exceptions\ImageUploadException;
 use BookStack\Exceptions\NotFoundException;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\ImageRepo;
+use BookStack\Entities\EntityRepo;
+use BookStack\Uploads\ImageRepo;
 use Illuminate\Filesystem\Filesystem as File;
 use Illuminate\Http\Request;
-use BookStack\Image;
+use BookStack\Uploads\Image;
 use BookStack\Repos\PageRepo;
 
 class ImageController extends Controller
diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php
index 80bbe56c1..df8549739 100644
--- a/app/Http/Controllers/PageController.php
+++ b/app/Http/Controllers/PageController.php
@@ -2,9 +2,9 @@
 
 use Activity;
 use BookStack\Exceptions\NotFoundException;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\ExportService;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\UserRepo;
+use BookStack\Entities\ExportService;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Views;
@@ -19,8 +19,8 @@ class PageController extends Controller
 
     /**
      * PageController constructor.
-     * @param EntityRepo $entityRepo
-     * @param ExportService $exportService
+     * @param \BookStack\Entities\EntityRepo $entityRepo
+     * @param \BookStack\Entities\ExportService $exportService
      * @param UserRepo $userRepo
      */
     public function __construct(EntityRepo $entityRepo, ExportService $exportService, UserRepo $userRepo)
diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php
index 5695705d0..215184b73 100644
--- a/app/Http/Controllers/PermissionController.php
+++ b/app/Http/Controllers/PermissionController.php
@@ -1,7 +1,7 @@
 <?php namespace BookStack\Http\Controllers;
 
 use BookStack\Exceptions\PermissionsException;
-use BookStack\Repos\PermissionsRepo;
+use BookStack\Auth\Permissions\PermissionsRepo;
 use Illuminate\Http\Request;
 
 class PermissionController extends Controller
@@ -11,7 +11,7 @@ class PermissionController extends Controller
 
     /**
      * PermissionController constructor.
-     * @param PermissionsRepo $permissionsRepo
+     * @param \BookStack\Auth\Permissions\PermissionsRepo $permissionsRepo
      */
     public function __construct(PermissionsRepo $permissionsRepo)
     {
diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php
index 49f9885ad..6ae08a280 100644
--- a/app/Http/Controllers/SearchController.php
+++ b/app/Http/Controllers/SearchController.php
@@ -1,8 +1,8 @@
 <?php namespace BookStack\Http\Controllers;
 
-use BookStack\Repos\EntityRepo;
-use BookStack\Services\SearchService;
-use BookStack\Services\ViewService;
+use BookStack\Entities\EntityRepo;
+use BookStack\Entities\SearchService;
+use BookStack\Actions\ViewService;
 use Illuminate\Http\Request;
 
 class SearchController extends Controller
@@ -97,7 +97,7 @@ class SearchController extends Controller
             $entities = $this->searchService->searchEntities($searchTerm, 'all', 1, 20, $permission)['results'];
         } else {
             $entityNames = $entityTypes->map(function ($type) {
-                return 'BookStack\\' . ucfirst($type);
+                return 'BookStack\\' . ucfirst($type); // TODO - Extract this elsewhere, too specific and stringy
             })->toArray();
             $entities = $this->viewService->getPopular(20, 0, $entityNames, $permission);
         }
diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php
index d9d66042e..01fb68fe0 100644
--- a/app/Http/Controllers/SettingController.php
+++ b/app/Http/Controllers/SettingController.php
@@ -1,6 +1,6 @@
 <?php namespace BookStack\Http\Controllers;
 
-use BookStack\Services\ImageService;
+use BookStack\Uploads\ImageService;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Setting;
diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php
index 815d9e8d5..6abbeeeba 100644
--- a/app/Http/Controllers/TagController.php
+++ b/app/Http/Controllers/TagController.php
@@ -1,6 +1,6 @@
 <?php namespace BookStack\Http\Controllers;
 
-use BookStack\Repos\TagRepo;
+use BookStack\Actions\TagRepo;
 use Illuminate\Http\Request;
 
 class TagController extends Controller
diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php
index f6bd13e6f..93e4c3450 100644
--- a/app/Http/Controllers/UserController.php
+++ b/app/Http/Controllers/UserController.php
@@ -3,9 +3,9 @@
 use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
-use BookStack\Repos\UserRepo;
-use BookStack\Services\SocialAuthService;
-use BookStack\User;
+use BookStack\Auth\UserRepo;
+use BookStack\Auth\Access\SocialAuthService;
+use BookStack\Auth\User;
 
 class UserController extends Controller
 {
@@ -16,7 +16,7 @@ class UserController extends Controller
     /**
      * UserController constructor.
      * @param User     $user
-     * @param UserRepo $userRepo
+     * @param \BookStack\Auth\UserRepo $userRepo
      */
     public function __construct(User $user, UserRepo $userRepo)
     {
@@ -101,7 +101,7 @@ class UserController extends Controller
     /**
      * Show the form for editing the specified user.
      * @param  int              $id
-     * @param SocialAuthService $socialAuthService
+     * @param \BookStack\Auth\Access\SocialAuthService $socialAuthService
      * @return Response
      */
     public function edit($id, SocialAuthService $socialAuthService)
diff --git a/app/Ownable.php b/app/Ownable.php
index fe58e05ed..e660a0500 100644
--- a/app/Ownable.php
+++ b/app/Ownable.php
@@ -1,5 +1,7 @@
 <?php namespace BookStack;
 
+use BookStack\Auth\User;
+
 abstract class Ownable extends Model
 {
     /**
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index b06b2f3a2..ef4c657d9 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -1,8 +1,15 @@
 <?php namespace BookStack\Providers;
 
-use BookStack\Services\SettingService;
-use BookStack\Setting;
+use Blade;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
+use BookStack\Settings\SettingService;
+use BookStack\Settings\Setting;
+use Illuminate\Database\Eloquent\Relations\Relation;
 use Illuminate\Support\ServiceProvider;
+use Schema;
 use Validator;
 
 class AppServiceProvider extends ServiceProvider
@@ -20,12 +27,21 @@ class AppServiceProvider extends ServiceProvider
             return in_array($value->getMimeType(), $imageMimes);
         });
 
-        \Blade::directive('icon', function ($expression) {
+        // Custom blade view directives
+        Blade::directive('icon', function ($expression) {
             return "<?php echo icon($expression); ?>";
         });
 
         // Allow longer string lengths after upgrade to utf8mb4
-        \Schema::defaultStringLength(191);
+        Schema::defaultStringLength(191);
+
+        // Set morph-map due to namespace changes
+        Relation::morphMap([
+            'BookStack\\Bookshelf' => Bookshelf::class,
+            'BookStack\\Book' => Book::class,
+            'BookStack\\Chapter' => Chapter::class,
+            'BookStack\\Page' => Page::class,
+        ]);
     }
 
     /**
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
index d1fac56e6..6e5b6ffde 100644
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -3,7 +3,7 @@
 namespace BookStack\Providers;
 
 use Auth;
-use BookStack\Services\LdapService;
+use BookStack\Auth\Access\LdapService;
 use Illuminate\Support\ServiceProvider;
 
 class AuthServiceProvider extends ServiceProvider
diff --git a/app/Providers/CustomFacadeProvider.php b/app/Providers/CustomFacadeProvider.php
index c81a5529d..2a5b101db 100644
--- a/app/Providers/CustomFacadeProvider.php
+++ b/app/Providers/CustomFacadeProvider.php
@@ -2,18 +2,18 @@
 
 namespace BookStack\Providers;
 
-use BookStack\Activity;
-use BookStack\Image;
-use BookStack\Services\ImageService;
-use BookStack\Services\PermissionService;
-use BookStack\Services\ViewService;
-use BookStack\Setting;
-use BookStack\View;
+use BookStack\Actions\Activity;
+use BookStack\Uploads\Image;
+use BookStack\Uploads\ImageService;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Actions\ViewService;
+use BookStack\Settings\Setting;
+use BookStack\Actions\View;
 use Illuminate\Contracts\Cache\Repository;
 use Illuminate\Contracts\Filesystem\Factory;
 use Illuminate\Support\ServiceProvider;
-use BookStack\Services\ActivityService;
-use BookStack\Services\SettingService;
+use BookStack\Actions\ActivityService;
+use BookStack\Settings\SettingService;
 use Intervention\Image\ImageManager;
 
 class CustomFacadeProvider extends ServiceProvider
diff --git a/app/Providers/LdapUserProvider.php b/app/Providers/LdapUserProvider.php
index 1dc789c3b..7f676eace 100644
--- a/app/Providers/LdapUserProvider.php
+++ b/app/Providers/LdapUserProvider.php
@@ -2,9 +2,9 @@
 
 namespace BookStack\Providers;
 
-use BookStack\Role;
-use BookStack\Services\LdapService;
-use BookStack\User;
+use BookStack\Auth\Role;
+use BookStack\Auth\Access\LdapService;
+use BookStack\Auth\User;
 use Illuminate\Contracts\Auth\Authenticatable;
 use Illuminate\Contracts\Auth\UserProvider;
 
@@ -19,7 +19,7 @@ class LdapUserProvider implements UserProvider
     protected $model;
 
     /**
-     * @var LdapService
+     * @var \BookStack\Auth\LdapService
      */
     protected $ldapService;
 
@@ -27,7 +27,7 @@ class LdapUserProvider implements UserProvider
     /**
      * LdapUserProvider constructor.
      * @param             $model
-     * @param LdapService $ldapService
+     * @param \BookStack\Auth\LdapService $ldapService
      */
     public function __construct($model, LdapService $ldapService)
     {
diff --git a/app/Setting.php b/app/Settings/Setting.php
similarity index 68%
rename from app/Setting.php
rename to app/Settings/Setting.php
index 0af3652db..1a52920ee 100644
--- a/app/Setting.php
+++ b/app/Settings/Setting.php
@@ -1,4 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Settings;
+
+use BookStack\Model;
 
 class Setting extends Model
 {
diff --git a/app/Services/SettingService.php b/app/Settings/SettingService.php
similarity index 97%
rename from app/Services/SettingService.php
rename to app/Settings/SettingService.php
index 7ec3ef93a..756640485 100644
--- a/app/Services/SettingService.php
+++ b/app/Settings/SettingService.php
@@ -1,7 +1,7 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Settings;
 
-use BookStack\Setting;
-use BookStack\User;
+use BookStack\Settings\Setting;
+use BookStack\Auth\User;
 use Illuminate\Contracts\Cache\Repository as Cache;
 
 /**
@@ -55,7 +55,7 @@ class SettingService
 
     /**
      * Get a user-specific setting from the database or cache.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @param $key
      * @param bool $default
      * @return bool|string
@@ -174,7 +174,7 @@ class SettingService
 
     /**
      * Put a user-specific setting into the database.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @param $key
      * @param $value
      * @return bool
diff --git a/app/Attachment.php b/app/Uploads/Attachment.php
similarity index 90%
rename from app/Attachment.php
rename to app/Uploads/Attachment.php
index 6749130d9..11c1408eb 100644
--- a/app/Attachment.php
+++ b/app/Uploads/Attachment.php
@@ -1,4 +1,7 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Uploads;
+
+use BookStack\Entities\Page;
+use BookStack\Ownable;
 
 class Attachment extends Ownable
 {
diff --git a/app/Services/AttachmentService.php b/app/Uploads/AttachmentService.php
similarity index 98%
rename from app/Services/AttachmentService.php
rename to app/Uploads/AttachmentService.php
index 3a6f95dcc..26e341111 100644
--- a/app/Services/AttachmentService.php
+++ b/app/Uploads/AttachmentService.php
@@ -1,7 +1,8 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Uploads;
 
 use BookStack\Exceptions\FileUploadException;
-use BookStack\Attachment;
+use BookStack\Uploads\Attachment;
+use BookStack\Uploads\UploadService;
 use Exception;
 use Symfony\Component\HttpFoundation\File\UploadedFile;
 
diff --git a/app/Image.php b/app/Uploads/Image.php
similarity index 88%
rename from app/Image.php
rename to app/Uploads/Image.php
index acc82df90..df6d9fb0d 100644
--- a/app/Image.php
+++ b/app/Uploads/Image.php
@@ -1,5 +1,6 @@
-<?php namespace BookStack;
+<?php namespace BookStack\Uploads;
 
+use BookStack\Ownable;
 use Images;
 
 class Image extends Ownable
diff --git a/app/Repos/ImageRepo.php b/app/Uploads/ImageRepo.php
similarity index 95%
rename from app/Repos/ImageRepo.php
rename to app/Uploads/ImageRepo.php
index 4ccd719ad..194a0d583 100644
--- a/app/Repos/ImageRepo.php
+++ b/app/Uploads/ImageRepo.php
@@ -1,9 +1,9 @@
-<?php namespace BookStack\Repos;
+<?php namespace BookStack\Uploads;
 
-use BookStack\Image;
-use BookStack\Page;
-use BookStack\Services\ImageService;
-use BookStack\Services\PermissionService;
+use BookStack\Uploads\Image;
+use BookStack\Entities\Page;
+use BookStack\Uploads\ImageService;
+use BookStack\Auth\Permissions\PermissionService;
 use Symfony\Component\HttpFoundation\File\UploadedFile;
 
 class ImageRepo
@@ -18,8 +18,8 @@ class ImageRepo
      * ImageRepo constructor.
      * @param Image $image
      * @param ImageService $imageService
-     * @param PermissionService $permissionService
-     * @param Page $page
+     * @param \BookStack\Auth\\BookStack\Auth\Permissions\PermissionService $permissionService
+     * @param \BookStack\Entities\Page $page
      */
     public function __construct(Image $image, ImageService $imageService, PermissionService $permissionService, Page $page)
     {
diff --git a/app/Services/ImageService.php b/app/Uploads/ImageService.php
similarity index 98%
rename from app/Services/ImageService.php
rename to app/Uploads/ImageService.php
index 7b73c457c..9ecf9492e 100644
--- a/app/Services/ImageService.php
+++ b/app/Uploads/ImageService.php
@@ -1,8 +1,9 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Uploads;
 
 use BookStack\Exceptions\ImageUploadException;
-use BookStack\Image;
-use BookStack\User;
+use BookStack\Uploads\Image;
+use BookStack\Auth\User;
+use BookStack\Uploads\UploadService;
 use DB;
 use Exception;
 use Intervention\Image\Exception\NotSupportedException;
@@ -281,7 +282,7 @@ class ImageService extends UploadService
 
     /**
      * Save a gravatar image and set a the profile image for a user.
-     * @param User $user
+     * @param \BookStack\Auth\User $user
      * @param int $size
      * @return mixed
      * @throws Exception
diff --git a/app/Services/UploadService.php b/app/Uploads/UploadService.php
similarity index 93%
rename from app/Services/UploadService.php
rename to app/Uploads/UploadService.php
index df597a40f..292e61e30 100644
--- a/app/Services/UploadService.php
+++ b/app/Uploads/UploadService.php
@@ -1,9 +1,9 @@
-<?php namespace BookStack\Services;
+<?php namespace BookStack\Uploads;
 
 use Illuminate\Contracts\Filesystem\Factory as FileSystem;
 use Illuminate\Contracts\Filesystem\Filesystem as FileSystemInstance;
 
-class UploadService
+abstract class UploadService
 {
 
     /**
diff --git a/app/helpers.php b/app/helpers.php
index 50b41ec05..9f2f74c18 100644
--- a/app/helpers.php
+++ b/app/helpers.php
@@ -30,11 +30,11 @@ function versioned_asset($file = '')
 /**
  * Helper method to get the current User.
  * Defaults to public 'Guest' user if not logged in.
- * @return \BookStack\User
+ * @return \BookStack\Auth\User
  */
 function user()
 {
-    return auth()->user() ?: \BookStack\User::getDefault();
+    return auth()->user() ?: \BookStack\Auth\User::getDefault();
 }
 
 /**
@@ -61,7 +61,7 @@ function userCan($permission, Ownable $ownable = null)
     }
 
     // Check permission on ownable item
-    $permissionService = app(\BookStack\Services\PermissionService::class);
+    $permissionService = app(\BookStack\Auth\Permissions\PermissionService::class);
     return $permissionService->checkOwnableUserAccess($ownable, $permission);
 }
 
@@ -69,11 +69,11 @@ function userCan($permission, Ownable $ownable = null)
  * Helper to access system settings.
  * @param $key
  * @param bool $default
- * @return bool|string|\BookStack\Services\SettingService
+ * @return bool|string|\BookStack\Settings\SettingService
  */
 function setting($key = null, $default = false)
 {
-    $settingService = resolve(\BookStack\Services\SettingService::class);
+    $settingService = resolve(\BookStack\Settings\SettingService::class);
     if (is_null($key)) {
         return $settingService;
     }
diff --git a/config/app.php b/config/app.php
index 9b5ac2f8c..7529697fa 100755
--- a/config/app.php
+++ b/config/app.php
@@ -274,10 +274,10 @@ return [
          * Custom
          */
 
-        'Activity' => BookStack\Services\Facades\Activity::class,
-        'Setting'  => BookStack\Services\Facades\Setting::class,
-        'Views'    => BookStack\Services\Facades\Views::class,
-        'Images'   => BookStack\Services\Facades\Images::class,
+        'Activity' => BookStack\Facades\Activity::class,
+        'Setting'  => BookStack\Facades\Setting::class,
+        'Views'    => BookStack\Facades\Views::class,
+        'Images'   => BookStack\Facades\Images::class,
 
     ],
 
diff --git a/config/auth.php b/config/auth.php
index ceeab5c71..f0e699809 100644
--- a/config/auth.php
+++ b/config/auth.php
@@ -70,7 +70,7 @@ return [
     'providers' => [
         'users' => [
             'driver' => env('AUTH_METHOD', 'standard') === 'standard' ? 'eloquent' : env('AUTH_METHOD'),
-            'model' => BookStack\User::class,
+            'model' => \BookStack\Auth\User::class,
         ],
 
         // 'users' => [
diff --git a/config/services.php b/config/services.php
index 2b0f260cd..711040386 100644
--- a/config/services.php
+++ b/config/services.php
@@ -38,7 +38,7 @@ return [
     ],
 
     'stripe'   => [
-        'model'  => BookStack\User::class,
+        'model'  => \BookStack\Auth\User::class,
         'key'    => '',
         'secret' => '',
     ],
diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php
index 3d6ed1d63..de6b0b276 100644
--- a/database/factories/ModelFactory.php
+++ b/database/factories/ModelFactory.php
@@ -11,7 +11,7 @@
 |
 */
 
-$factory->define(BookStack\User::class, function ($faker) {
+$factory->define(\BookStack\Auth\User::class, function ($faker) {
     return [
         'name' => $faker->name,
         'email' => $faker->email,
@@ -21,7 +21,7 @@ $factory->define(BookStack\User::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Bookshelf::class, function ($faker) {
+$factory->define(\BookStack\Entities\Bookshelf::class, function ($faker) {
     return [
         'name' => $faker->sentence,
         'slug' => str_random(10),
@@ -29,7 +29,7 @@ $factory->define(BookStack\Bookshelf::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Book::class, function ($faker) {
+$factory->define(\BookStack\Entities\Book::class, function ($faker) {
     return [
         'name' => $faker->sentence,
         'slug' => str_random(10),
@@ -37,7 +37,7 @@ $factory->define(BookStack\Book::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Chapter::class, function ($faker) {
+$factory->define(\BookStack\Entities\Chapter::class, function ($faker) {
     return [
         'name' => $faker->sentence,
         'slug' => str_random(10),
@@ -45,7 +45,7 @@ $factory->define(BookStack\Chapter::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Page::class, function ($faker) {
+$factory->define(\BookStack\Entities\Page::class, function ($faker) {
     $html = '<p>' . implode('</p>', $faker->paragraphs(5)) . '</p>';
     return [
         'name' => $faker->sentence,
@@ -56,21 +56,21 @@ $factory->define(BookStack\Page::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Role::class, function ($faker) {
+$factory->define(\BookStack\Auth\Role::class, function ($faker) {
     return [
         'display_name' => $faker->sentence(3),
         'description' => $faker->sentence(10)
     ];
 });
 
-$factory->define(BookStack\Tag::class, function ($faker) {
+$factory->define(\BookStack\Actions\Tag::class, function ($faker) {
     return [
         'name' => $faker->city,
         'value' => $faker->sentence(3)
     ];
 });
 
-$factory->define(BookStack\Image::class, function ($faker) {
+$factory->define(\BookStack\Uploads\Image::class, function ($faker) {
     return [
         'name' => $faker->slug . '.jpg',
         'url' => $faker->url,
@@ -80,7 +80,7 @@ $factory->define(BookStack\Image::class, function ($faker) {
     ];
 });
 
-$factory->define(BookStack\Comment::class, function($faker) {
+$factory->define(\BookStack\Actions\Comment::class, function($faker) {
     $text = $faker->paragraph(1);
     $html = '<p>' . $text. '</p>';
     return [
diff --git a/database/migrations/2015_12_07_195238_add_image_upload_types.php b/database/migrations/2015_12_07_195238_add_image_upload_types.php
index eed937611..515bc9d8d 100644
--- a/database/migrations/2015_12_07_195238_add_image_upload_types.php
+++ b/database/migrations/2015_12_07_195238_add_image_upload_types.php
@@ -1,6 +1,6 @@
 <?php
 
-use BookStack\Image;
+use BookStack\Uploads\Image;
 use Illuminate\Database\Schema\Blueprint;
 use Illuminate\Database\Migrations\Migration;
 
diff --git a/database/migrations/2018_08_04_115700_create_bookshelves_table.php b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
index e4dca8c0b..eab3216bb 100644
--- a/database/migrations/2018_08_04_115700_create_bookshelves_table.php
+++ b/database/migrations/2018_08_04_115700_create_bookshelves_table.php
@@ -119,11 +119,11 @@ class CreateBookshelvesTable extends Migration
         Schema::dropIfExists('bookshelves');
 
         // Drop related polymorphic items
-        DB::table('activities')->where('entity_type', '=', 'BookStack\Bookshelf')->delete();
-        DB::table('views')->where('viewable_type', '=', 'BookStack\Bookshelf')->delete();
-        DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Bookshelf')->delete();
-        DB::table('tags')->where('entity_type', '=', 'BookStack\Bookshelf')->delete();
-        DB::table('search_terms')->where('entity_type', '=', 'BookStack\Bookshelf')->delete();
-        DB::table('comments')->where('entity_type', '=', 'BookStack\Bookshelf')->delete();
+        DB::table('activities')->where('entity_type', '=', 'BookStack\Entities\Bookshelf')->delete();
+        DB::table('views')->where('viewable_type', '=', 'BookStack\Entities\Bookshelf')->delete();
+        DB::table('entity_permissions')->where('restrictable_type', '=', 'BookStack\Entities\Bookshelf')->delete();
+        DB::table('tags')->where('entity_type', '=', 'BookStack\Entities\Bookshelf')->delete();
+        DB::table('search_terms')->where('entity_type', '=', 'BookStack\Entities\Bookshelf')->delete();
+        DB::table('comments')->where('entity_type', '=', 'BookStack\Entities\Bookshelf')->delete();
     }
 }
diff --git a/database/seeds/DummyContentSeeder.php b/database/seeds/DummyContentSeeder.php
index dcf589352..ce3cd1307 100644
--- a/database/seeds/DummyContentSeeder.php
+++ b/database/seeds/DummyContentSeeder.php
@@ -12,39 +12,39 @@ class DummyContentSeeder extends Seeder
     public function run()
     {
         // Create an editor user
-        $editorUser = factory(\BookStack\User::class)->create();
-        $editorRole = \BookStack\Role::getRole('editor');
+        $editorUser = factory(\BookStack\Auth\User::class)->create();
+        $editorRole = \BookStack\Auth\Role::getRole('editor');
         $editorUser->attachRole($editorRole);
 
         // Create a viewer user
-        $viewerUser = factory(\BookStack\User::class)->create();
-        $role = \BookStack\Role::getRole('viewer');
+        $viewerUser = factory(\BookStack\Auth\User::class)->create();
+        $role = \BookStack\Auth\Role::getRole('viewer');
         $viewerUser->attachRole($role);
 
         $byData = ['created_by' => $editorUser->id, 'updated_by' => $editorUser->id];
 
-        factory(\BookStack\Book::class, 5)->create($byData)
+        factory(\BookStack\Entities\Book::class, 5)->create($byData)
             ->each(function($book) use ($editorUser, $byData) {
-                $chapters = factory(\BookStack\Chapter::class, 3)->create($byData)
+                $chapters = factory(\BookStack\Entities\Chapter::class, 3)->create($byData)
                     ->each(function($chapter) use ($editorUser, $book, $byData){
-                        $pages = factory(\BookStack\Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id]));
+                        $pages = factory(\BookStack\Entities\Page::class, 3)->make(array_merge($byData, ['book_id' => $book->id]));
                         $chapter->pages()->saveMany($pages);
                     });
-                $pages = factory(\BookStack\Page::class, 3)->make($byData);
+                $pages = factory(\BookStack\Entities\Page::class, 3)->make($byData);
                 $book->chapters()->saveMany($chapters);
                 $book->pages()->saveMany($pages);
             });
 
-        $largeBook = factory(\BookStack\Book::class)->create(array_merge($byData, ['name' => 'Large book' . str_random(10)]));
-        $pages = factory(\BookStack\Page::class, 200)->make($byData);
-        $chapters = factory(\BookStack\Chapter::class, 50)->make($byData);
+        $largeBook = factory(\BookStack\Entities\Book::class)->create(array_merge($byData, ['name' => 'Large book' . str_random(10)]));
+        $pages = factory(\BookStack\Entities\Page::class, 200)->make($byData);
+        $chapters = factory(\BookStack\Entities\Chapter::class, 50)->make($byData);
         $largeBook->pages()->saveMany($pages);
         $largeBook->chapters()->saveMany($chapters);
 
-        $shelves = factory(\BookStack\Bookshelf::class, 10)->create($byData);
+        $shelves = factory(\BookStack\Entities\Bookshelf::class, 10)->create($byData);
         $largeBook->shelves()->attach($shelves->pluck('id'));
 
-        app(\BookStack\Services\PermissionService::class)->buildJointPermissions();
-        app(\BookStack\Services\SearchService::class)->indexAllEntities();
+        app(\BookStack\Auth\Permissions\PermissionService::class)->buildJointPermissions();
+        app(\BookStack\Entities\SearchService::class)->indexAllEntities();
     }
 }
diff --git a/database/seeds/LargeContentSeeder.php b/database/seeds/LargeContentSeeder.php
index 129ede997..136b6cb6a 100644
--- a/database/seeds/LargeContentSeeder.php
+++ b/database/seeds/LargeContentSeeder.php
@@ -12,16 +12,16 @@ class LargeContentSeeder extends Seeder
     public function run()
     {
         // Create an editor user
-        $editorUser = factory(\BookStack\User::class)->create();
-        $editorRole = \BookStack\Role::getRole('editor');
+        $editorUser = factory(\BookStack\Auth\User::class)->create();
+        $editorRole = \BookStack\Auth\Role::getRole('editor');
         $editorUser->attachRole($editorRole);
 
-        $largeBook = factory(\BookStack\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
-        $pages = factory(\BookStack\Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
-        $chapters = factory(\BookStack\Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $largeBook = factory(\BookStack\Entities\Book::class)->create(['name' => 'Large book' . str_random(10), 'created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $pages = factory(\BookStack\Entities\Page::class, 200)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
+        $chapters = factory(\BookStack\Entities\Chapter::class, 50)->make(['created_by' => $editorUser->id, 'updated_by' => $editorUser->id]);
         $largeBook->pages()->saveMany($pages);
         $largeBook->chapters()->saveMany($chapters);
-        app(\BookStack\Services\PermissionService::class)->buildJointPermissions();
-        app(\BookStack\Services\SearchService::class)->indexAllEntities();
+        app(\BookStack\Auth\Permissions\PermissionService::class)->buildJointPermissions();
+        app(\BookStack\Entities\SearchService::class)->indexAllEntities();
     }
 }
diff --git a/resources/views/components/page-picker.blade.php b/resources/views/components/page-picker.blade.php
index 91d8eb646..7a3285fa7 100644
--- a/resources/views/components/page-picker.blade.php
+++ b/resources/views/components/page-picker.blade.php
@@ -3,7 +3,7 @@
 <div page-picker>
     <div class="input-base">
         <span @if($value) style="display: none" @endif page-picker-default class="text-muted italic">{{ $placeholder }}</span>
-        <a @if(!$value) style="display: none" @endif href="{{ baseUrl('/link/' . $value) }}" target="_blank" class="text-page" page-picker-display>#{{$value}}, {{$value ? \BookStack\Page::find($value)->name : '' }}</a>
+        <a @if(!$value) style="display: none" @endif href="{{ baseUrl('/link/' . $value) }}" target="_blank" class="text-page" page-picker-display>#{{$value}}, {{$value ? \BookStack\Entities\Page::find($value)->name : '' }}</a>
     </div>
     <br>
     <input type="hidden" value="{{$value}}" name="{{$name}}" id="{{$name}}">
diff --git a/resources/views/errors/404.blade.php b/resources/views/errors/404.blade.php
index d614edca8..9c431828a 100644
--- a/resources/views/errors/404.blade.php
+++ b/resources/views/errors/404.blade.php
@@ -18,19 +18,19 @@
             <div class="col-md-4">
                 <div class="card">
                     <h3 class="text-muted">@icon('page') {{ trans('entities.pages_popular') }}</h3>
-                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Page::class]), 'style' => 'compact'])
+                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Entities\Page::class]), 'style' => 'compact'])
                 </div>
             </div>
             <div class="col-md-4">
                 <div class="card">
                     <h3 class="text-muted">@icon('book') {{ trans('entities.books_popular') }}</h3>
-                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Book::class]), 'style' => 'compact'])
+                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Entities\Book::class]), 'style' => 'compact'])
                 </div>
             </div>
             <div class="col-md-4">
                 <div class="card">
                     <h3 class="text-muted">@icon('chapter') {{ trans('entities.chapters_popular') }}</h3>
-                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Chapter::class]), 'style' => 'compact'])
+                    @include('partials.entity-list', ['entities' => Views::getPopular(10, 0, [\BookStack\Entities\Chapter::class]), 'style' => 'compact'])
                 </div>
             </div>
         </div>
diff --git a/resources/views/settings/index.blade.php b/resources/views/settings/index.blade.php
index 3c563a61c..26b81899e 100644
--- a/resources/views/settings/index.blade.php
+++ b/resources/views/settings/index.blade.php
@@ -127,9 +127,9 @@
                         <div class="form-group">
                             <label for="setting-registration-role">{{ trans('settings.reg_default_role') }}</label>
                             <select id="setting-registration-role" name="setting-registration-role" @if($errors->has('setting-registration-role')) class="neg" @endif>
-                                @foreach(\BookStack\Role::all() as $role)
+                                @foreach(\BookStack\Auth\Role::all() as $role)
                                     <option value="{{$role->id}}" data-role-name="{{ $role->name }}"
-                                            @if(setting('registration-role', \BookStack\Role::first()->id) == $role->id) selected @endif
+                                            @if(setting('registration-role', \BookStack\Auth\Role::first()->id) == $role->id) selected @endif
                                     >
                                         {{ $role->display_name }}
                                     </option>
diff --git a/tests/ActivityTrackingTest.php b/tests/ActivityTrackingTest.php
index bb65fbcf4..f47bc44a3 100644
--- a/tests/ActivityTrackingTest.php
+++ b/tests/ActivityTrackingTest.php
@@ -1,12 +1,14 @@
 <?php namespace Tests;
 
 
+use BookStack\Entities\Book;
+
 class ActivityTrackingTest extends BrowserKitTest
 {
 
     public function test_recently_viewed_books()
     {
-        $books = \BookStack\Book::all()->take(10);
+        $books = Book::all()->take(10);
 
         $this->asAdmin()->visit('/books')
             ->dontSeeInElement('#recents', $books[0]->name)
@@ -20,7 +22,7 @@ class ActivityTrackingTest extends BrowserKitTest
 
     public function test_popular_books()
     {
-        $books = \BookStack\Book::all()->take(10);
+        $books = Book::all()->take(10);
 
         $this->asAdmin()->visit('/books')
             ->dontSeeInElement('#popular', $books[0]->name)
diff --git a/tests/AttachmentTest.php b/tests/AttachmentTest.php
index bb3a92706..373d9eb5a 100644
--- a/tests/AttachmentTest.php
+++ b/tests/AttachmentTest.php
@@ -1,8 +1,8 @@
 <?php namespace Tests;
 
-use BookStack\Attachment;
-use BookStack\Page;
-use BookStack\Services\PermissionService;
+use BookStack\Uploads\Attachment;
+use BookStack\Entities\Page;
+use BookStack\Auth\Permissions\PermissionService;
 
 class AttachmentTest extends TestCase
 {
@@ -44,8 +44,8 @@ class AttachmentTest extends TestCase
      */
     protected function deleteUploads()
     {
-        $fileService = $this->app->make(\BookStack\Services\AttachmentService::class);
-        foreach (\BookStack\Attachment::all() as $file) {
+        $fileService = $this->app->make(\BookStack\Uploads\AttachmentService::class);
+        foreach (\BookStack\Uploads\Attachment::all() as $file) {
             $fileService->deleteFile($file);
         }
     }
@@ -144,7 +144,7 @@ class AttachmentTest extends TestCase
             'uploaded_to' => $page->id,
         ]);
 
-        $attachmentId = \BookStack\Attachment::first()->id;
+        $attachmentId = \BookStack\Uploads\Attachment::first()->id;
 
         $update = $this->call('PUT', 'attachments/' . $attachmentId, [
             'uploaded_to' => $page->id,
@@ -175,7 +175,7 @@ class AttachmentTest extends TestCase
         $filePath = base_path('storage/' . $this->getUploadPath($fileName));
         $this->assertTrue(file_exists($filePath), 'File at path ' . $filePath . ' does not exist');
 
-        $attachment = \BookStack\Attachment::first();
+        $attachment = \BookStack\Uploads\Attachment::first();
         $this->delete($attachment->getUrl());
 
         $this->assertDatabaseMissing('attachments', [
diff --git a/tests/Auth/AuthTest.php b/tests/Auth/AuthTest.php
index b456de964..0aa0e2a23 100644
--- a/tests/Auth/AuthTest.php
+++ b/tests/Auth/AuthTest.php
@@ -1,7 +1,8 @@
 <?php namespace Tests;
 
 use BookStack\Notifications\ConfirmEmail;
-use BookStack\User;
+use BookStack\Auth\User;
+use BookStack\Settings\SettingService;
 use Illuminate\Support\Facades\Notification;
 
 class AuthTest extends BrowserKitTest
@@ -21,7 +22,7 @@ class AuthTest extends BrowserKitTest
 
     public function test_public_viewing()
     {
-        $settings = app('BookStack\Services\SettingService');
+        $settings = app(SettingService::class);
         $settings->put('app-public', 'true');
         $this->visit('/')
             ->seePageIs('/')
@@ -248,7 +249,7 @@ class AuthTest extends BrowserKitTest
 
     public function test_user_cannot_be_deleted_if_last_admin()
     {
-        $adminRole = \BookStack\Role::getRole('admin');
+        $adminRole = \BookStack\Auth\Role::getRole('admin');
         // Ensure we currently only have 1 admin user
         $this->assertEquals(1, $adminRole->users()->count());
         $user = $adminRole->users->first();
diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php
index 289daa932..25d8a5906 100644
--- a/tests/Auth/LdapTest.php
+++ b/tests/Auth/LdapTest.php
@@ -1,7 +1,7 @@
 <?php namespace Tests;
-use BookStack\Role;
-use BookStack\Services\Ldap;
-use BookStack\User;
+use BookStack\Auth\Role;
+use BookStack\Auth\Access\Ldap;
+use BookStack\Auth\User;
 use Mockery\MockInterface;
 
 class LdapTest extends BrowserKitTest
diff --git a/tests/Auth/SocialAuthTest.php b/tests/Auth/SocialAuthTest.php
index 5bfe0c222..572c32f46 100644
--- a/tests/Auth/SocialAuthTest.php
+++ b/tests/Auth/SocialAuthTest.php
@@ -6,7 +6,7 @@ class SocialAuthTest extends TestCase
     public function test_social_registration()
     {
         // http://docs.mockery.io/en/latest/reference/startup_methods.html
-        $user = factory(\BookStack\User::class)->make();
+        $user = factory(\BookStack\Auth\User::class)->make();
 
         $this->setSettings(['registration-enabled' => 'true']);
         config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
@@ -86,7 +86,7 @@ class SocialAuthTest extends TestCase
             'APP_URL' => 'http://localhost'
         ]);
 
-        $user = factory(\BookStack\User::class)->make();
+        $user = factory(\BookStack\Auth\User::class)->make();
         $mockSocialite = \Mockery::mock('Laravel\Socialite\Contracts\Factory');
         $this->app['Laravel\Socialite\Contracts\Factory'] = $mockSocialite;
         $mockSocialDriver = \Mockery::mock('Laravel\Socialite\Contracts\Provider');
@@ -125,7 +125,7 @@ class SocialAuthTest extends TestCase
             'APP_URL' => 'http://localhost', 'services.google.auto_register' => true, 'services.google.auto_confirm' => true
         ]);
 
-        $user = factory(\BookStack\User::class)->make();
+        $user = factory(\BookStack\Auth\User::class)->make();
         $mockSocialite = \Mockery::mock('Laravel\Socialite\Contracts\Factory');
         $this->app['Laravel\Socialite\Contracts\Factory'] = $mockSocialite;
         $mockSocialDriver = \Mockery::mock('Laravel\Socialite\Contracts\Provider');
diff --git a/tests/BrowserKitTest.php b/tests/BrowserKitTest.php
index 86f61a764..ab0d9d898 100644
--- a/tests/BrowserKitTest.php
+++ b/tests/BrowserKitTest.php
@@ -1,8 +1,9 @@
 <?php namespace Tests;
 
-use BookStack\Entity;
-use BookStack\Role;
-use BookStack\Services\PermissionService;
+use BookStack\Entities\Entity;
+use BookStack\Auth\Role;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Settings\SettingService;
 use Illuminate\Contracts\Console\Kernel;
 use Illuminate\Foundation\Testing\DatabaseTransactions;
 use Laravel\BrowserKitTesting\TestCase;
@@ -46,7 +47,7 @@ abstract class BrowserKitTest extends TestCase
      */
     public function getNormalUser()
     {
-        return \BookStack\User::where('system_name', '=', null)->get()->last();
+        return \BookStack\Auth\User::where('system_name', '=', null)->get()->last();
     }
 
     /**
@@ -55,7 +56,7 @@ abstract class BrowserKitTest extends TestCase
      */
     protected function setSettings($settingsArray)
     {
-        $settings = app('BookStack\Services\SettingService');
+        $settings = app(SettingService::class);
         foreach ($settingsArray as $key => $value) {
             $settings->put($key, $value);
         }
@@ -70,9 +71,9 @@ abstract class BrowserKitTest extends TestCase
     protected function createEntityChainBelongingToUser($creatorUser, $updaterUser = false)
     {
         if ($updaterUser === false) $updaterUser = $creatorUser;
-        $book = factory(\BookStack\Book::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]);
-        $chapter = factory(\BookStack\Chapter::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id]);
-        $page = factory(\BookStack\Page::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id, 'chapter_id' => $chapter->id]);
+        $book = factory(\BookStack\Entities\Book::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id]);
+        $chapter = factory(\BookStack\Entities\Chapter::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id]);
+        $page = factory(\BookStack\Entities\Page::class)->create(['created_by' => $creatorUser->id, 'updated_by' => $updaterUser->id, 'book_id' => $book->id, 'chapter_id' => $chapter->id]);
         $restrictionService = $this->app[PermissionService::class];
         $restrictionService->buildJointPermissionsForEntity($book);
         return [
@@ -100,7 +101,7 @@ abstract class BrowserKitTest extends TestCase
      */
     protected function getNewBlankUser($attributes = [])
     {
-        $user = factory(\BookStack\User::class)->create($attributes);
+        $user = factory(\BookStack\Auth\User::class)->create($attributes);
         return $user;
     }
 
diff --git a/tests/CommandsTest.php b/tests/CommandsTest.php
index 25516c317..1533df792 100644
--- a/tests/CommandsTest.php
+++ b/tests/CommandsTest.php
@@ -1,9 +1,9 @@
 <?php namespace Tests;
 
-use BookStack\JointPermission;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
-use BookStack\User;
+use BookStack\Auth\Permissions\JointPermission;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\User;
 
 class CommandsTest extends TestCase
 {
diff --git a/tests/Entity/BookShelfTest.php b/tests/Entity/BookShelfTest.php
index 9071e3c06..5d71ec6f6 100644
--- a/tests/Entity/BookShelfTest.php
+++ b/tests/Entity/BookShelfTest.php
@@ -1,7 +1,7 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
 
 class BookShelfTest extends TestCase
 {
diff --git a/tests/Entity/CommentSettingTest.php b/tests/Entity/CommentSettingTest.php
index 29df8b327..2683f57cb 100644
--- a/tests/Entity/CommentSettingTest.php
+++ b/tests/Entity/CommentSettingTest.php
@@ -5,7 +5,7 @@ class CommentSettingTest extends BrowserKitTest {
 
   public function setUp() {
       parent::setUp();
-      $this->page = \BookStack\Page::first();
+      $this->page = \BookStack\Entities\Page::first();
   }
 
   public function test_comment_disable () {
diff --git a/tests/Entity/CommentTest.php b/tests/Entity/CommentTest.php
index 04716c1c2..2b943f96f 100644
--- a/tests/Entity/CommentTest.php
+++ b/tests/Entity/CommentTest.php
@@ -1,7 +1,7 @@
 <?php namespace Tests;
 
-use BookStack\Page;
-use BookStack\Comment;
+use BookStack\Entities\Page;
+use BookStack\Actions\Comment;
 
 class CommentTest extends TestCase
 {
@@ -23,7 +23,7 @@ class CommentTest extends TestCase
         $this->assertDatabaseHas('comments', [
             'local_id' => 1,
             'entity_id' => $page->id,
-            'entity_type' => 'BookStack\\Page',
+            'entity_type' => Page::newModelInstance()->getMorphClass(),
             'text' => $comment->text,
             'parent_id' => 2
         ]);
diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php
index 301f0d02d..4114d4af9 100644
--- a/tests/Entity/EntitySearchTest.php
+++ b/tests/Entity/EntitySearchTest.php
@@ -1,16 +1,16 @@
 <?php namespace Tests;
 
 
-use BookStack\Bookshelf;
-use BookStack\Chapter;
-use BookStack\Page;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
 
 class EntitySearchTest extends TestCase
 {
 
     public function test_page_search()
     {
-        $book = \BookStack\Book::all()->first();
+        $book = \BookStack\Entities\Book::all()->first();
         $page = $book->pages->first();
 
         $search = $this->asEditor()->get('/search?term=' . urlencode($page->name));
@@ -54,7 +54,7 @@ class EntitySearchTest extends TestCase
 
     public function test_book_search()
     {
-        $book = \BookStack\Book::first();
+        $book = \BookStack\Entities\Book::first();
         $page = $book->pages->last();
         $chapter = $book->chapters->last();
 
@@ -67,7 +67,7 @@ class EntitySearchTest extends TestCase
 
     public function test_chapter_search()
     {
-        $chapter = \BookStack\Chapter::has('pages')->first();
+        $chapter = \BookStack\Entities\Chapter::has('pages')->first();
         $page = $chapter->pages[0];
 
         $pageTestResp = $this->asEditor()->get('/search/chapter/' . $chapter->id . '?term=' . urlencode($page->name));
@@ -77,11 +77,11 @@ class EntitySearchTest extends TestCase
     public function test_tag_search()
     {
         $newTags = [
-            new \BookStack\Tag([
+            new \BookStack\Actions\Tag([
                 'name' => 'animal',
                 'value' => 'cat'
             ]),
-            new \BookStack\Tag([
+            new \BookStack\Actions\Tag([
                 'name' => 'color',
                 'value' => 'red'
             ])
diff --git a/tests/Entity/EntityTest.php b/tests/Entity/EntityTest.php
index f8ca8ea12..90082deaf 100644
--- a/tests/Entity/EntityTest.php
+++ b/tests/Entity/EntityTest.php
@@ -1,10 +1,10 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Chapter;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\UserRepo;
+use BookStack\Entities\Book;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\UserRepo;
 use Carbon\Carbon;
 
 class EntityTest extends BrowserKitTest
diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php
index 5fff84b8d..51090650c 100644
--- a/tests/Entity/ExportTest.php
+++ b/tests/Entity/ExportTest.php
@@ -1,8 +1,8 @@
 <?php namespace Tests;
 
 
-use BookStack\Chapter;
-use BookStack\Page;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
 
 class ExportTest extends TestCase
 {
diff --git a/tests/Entity/MarkdownTest.php b/tests/Entity/MarkdownTest.php
index b85e92565..c481e444f 100644
--- a/tests/Entity/MarkdownTest.php
+++ b/tests/Entity/MarkdownTest.php
@@ -7,7 +7,7 @@ class MarkdownTest extends BrowserKitTest
     public function setUp()
     {
         parent::setUp();
-        $this->page = \BookStack\Page::first();
+        $this->page = \BookStack\Entities\Page::first();
     }
 
     protected function setMarkdownEditor()
diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php
index 8b0e180da..4c0d1c47a 100644
--- a/tests/Entity/PageContentTest.php
+++ b/tests/Entity/PageContentTest.php
@@ -1,7 +1,7 @@
 <?php namespace Tests;
 
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
 
 class PageContentTest extends TestCase
 {
diff --git a/tests/Entity/PageDraftTest.php b/tests/Entity/PageDraftTest.php
index d9341ace6..baae9bded 100644
--- a/tests/Entity/PageDraftTest.php
+++ b/tests/Entity/PageDraftTest.php
@@ -9,8 +9,8 @@ class PageDraftTest extends BrowserKitTest
     public function setUp()
     {
         parent::setUp();
-        $this->page = \BookStack\Page::first();
-        $this->entityRepo = app('\BookStack\Repos\EntityRepo');
+        $this->page = \BookStack\Entities\Page::first();
+        $this->entityRepo = app('\BookStack\Entities\EntityRepo');
     }
 
     public function test_draft_content_shows_if_available()
@@ -48,7 +48,7 @@ class PageDraftTest extends BrowserKitTest
 
     public function test_alert_message_shows_if_someone_else_editing()
     {
-        $nonEditedPage = \BookStack\Page::take(10)->get()->last();
+        $nonEditedPage = \BookStack\Entities\Page::take(10)->get()->last();
         $addedContent = '<p>test message content</p>';
         $this->asAdmin()->visit($this->page->getUrl() . '/edit')
             ->dontSeeInField('html', $addedContent);
@@ -67,7 +67,7 @@ class PageDraftTest extends BrowserKitTest
 
     public function test_draft_pages_show_on_homepage()
     {
-        $book = \BookStack\Book::first();
+        $book = \BookStack\Entities\Book::first();
         $this->asAdmin()->visit('/')
             ->dontSeeInElement('#recent-drafts', 'New Page')
             ->visit($book->getUrl() . '/create-page')
@@ -77,7 +77,7 @@ class PageDraftTest extends BrowserKitTest
 
     public function test_draft_pages_not_visible_by_others()
     {
-        $book = \BookStack\Book::first();
+        $book = \BookStack\Entities\Book::first();
         $chapter = $book->chapters->first();
         $newUser = $this->getEditor();
 
diff --git a/tests/Entity/PageRevisionTest.php b/tests/Entity/PageRevisionTest.php
index 390042dbf..015320dd7 100644
--- a/tests/Entity/PageRevisionTest.php
+++ b/tests/Entity/PageRevisionTest.php
@@ -1,7 +1,7 @@
 <?php namespace Entity;
 
 
-use BookStack\Page;
+use BookStack\Entities\Page;
 use Tests\TestCase;
 
 class PageRevisionTest extends TestCase
diff --git a/tests/Entity/SortTest.php b/tests/Entity/SortTest.php
index ea5ab665d..689ca690f 100644
--- a/tests/Entity/SortTest.php
+++ b/tests/Entity/SortTest.php
@@ -1,9 +1,9 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Chapter;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
+use BookStack\Entities\Book;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
 
 class SortTest extends TestCase
 {
diff --git a/tests/Entity/TagTest.php b/tests/Entity/TagTest.php
index 7e1166388..70b8c960b 100644
--- a/tests/Entity/TagTest.php
+++ b/tests/Entity/TagTest.php
@@ -1,10 +1,10 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Chapter;
-use BookStack\Tag;
-use BookStack\Page;
-use BookStack\Services\PermissionService;
+use BookStack\Entities\Book;
+use BookStack\Entities\Chapter;
+use BookStack\Actions\Tag;
+use BookStack\Entities\Page;
+use BookStack\Auth\Permissions\PermissionService;
 
 class TagTest extends BrowserKitTest
 {
@@ -13,7 +13,7 @@ class TagTest extends BrowserKitTest
 
     /**
      * Get an instance of a page that has many tags.
-     * @param Tag[]|bool $tags
+     * @param \BookStack\Actions\Tag[]|bool $tags
      * @return mixed
      */
     protected function getEntityWithTags($class, $tags = false)
diff --git a/tests/ImageTest.php b/tests/ImageTest.php
index 0f1e772e9..d5c13cd95 100644
--- a/tests/ImageTest.php
+++ b/tests/ImageTest.php
@@ -1,9 +1,9 @@
 <?php namespace Tests;
 
-use BookStack\Image;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
-use BookStack\Services\ImageService;
+use BookStack\Uploads\Image;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
+use BookStack\Uploads\ImageService;
 
 class ImageTest extends TestCase
 {
diff --git a/tests/Permissions/RestrictionsTest.php b/tests/Permissions/RestrictionsTest.php
index 540125fd1..cc4211843 100644
--- a/tests/Permissions/RestrictionsTest.php
+++ b/tests/Permissions/RestrictionsTest.php
@@ -1,16 +1,18 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Entity;
-use BookStack\User;
-use BookStack\Repos\EntityRepo;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
+use BookStack\Auth\User;
+use BookStack\Entities\EntityRepo;
+use BookStack\Entities\Page;
 
 class RestrictionsTest extends BrowserKitTest
 {
 
     /**
-     * @var User
+     * @var \BookStack\Auth\User
      */
     protected $user;
 
@@ -223,7 +225,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_chapter_view_restriction()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $chapterPage = $chapter->pages->first();
 
         $chapterUrl = $chapter->getUrl();
@@ -248,7 +250,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_chapter_create_restriction()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
 
         $chapterUrl = $chapter->getUrl();
         $this->actingAs($this->user)
@@ -275,7 +277,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_chapter_update_restriction()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $chapterPage = $chapter->pages->first();
 
         $chapterUrl = $chapter->getUrl();
@@ -300,7 +302,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_chapter_delete_restriction()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $chapterPage = $chapter->pages->first();
 
         $chapterUrl = $chapter->getUrl();
@@ -325,7 +327,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_page_view_restriction()
     {
-        $page = \BookStack\Page::first();
+        $page = \BookStack\Entities\Page::first();
 
         $pageUrl = $page->getUrl();
         $this->actingAs($this->user)
@@ -345,7 +347,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_page_update_restriction()
     {
-        $page = \BookStack\Chapter::first();
+        $page = Chapter::first();
 
         $pageUrl = $page->getUrl();
         $this->actingAs($this->user)
@@ -365,7 +367,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_page_delete_restriction()
     {
-        $page = \BookStack\Page::first();
+        $page = \BookStack\Entities\Page::first();
 
         $pageUrl = $page->getUrl();
         $this->actingAs($this->user)
@@ -394,7 +396,7 @@ class RestrictionsTest extends BrowserKitTest
             ->seeInDatabase('bookshelves', ['id' => $shelf->id, 'restricted' => true])
             ->seeInDatabase('entity_permissions', [
                 'restrictable_id' => $shelf->id,
-                'restrictable_type' => 'BookStack\Bookshelf',
+                'restrictable_type' => Bookshelf::newModelInstance()->getMorphClass(),
                 'role_id' => '2',
                 'action' => 'view'
             ]);
@@ -411,7 +413,7 @@ class RestrictionsTest extends BrowserKitTest
             ->seeInDatabase('books', ['id' => $book->id, 'restricted' => true])
             ->seeInDatabase('entity_permissions', [
                 'restrictable_id' => $book->id,
-                'restrictable_type' => 'BookStack\Book',
+                'restrictable_type' => Book::newModelInstance()->getMorphClass(),
                 'role_id' => '2',
                 'action' => 'view'
             ]);
@@ -419,7 +421,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_chapter_restriction_form()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $this->asAdmin()->visit($chapter->getUrl() . '/permissions')
             ->see('Chapter Permissions')
             ->check('restricted')
@@ -428,7 +430,7 @@ class RestrictionsTest extends BrowserKitTest
             ->seeInDatabase('chapters', ['id' => $chapter->id, 'restricted' => true])
             ->seeInDatabase('entity_permissions', [
                 'restrictable_id' => $chapter->id,
-                'restrictable_type' => 'BookStack\Chapter',
+                'restrictable_type' => Chapter::newModelInstance()->getMorphClass(),
                 'role_id' => '2',
                 'action' => 'update'
             ]);
@@ -436,7 +438,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_page_restriction_form()
     {
-        $page = \BookStack\Page::first();
+        $page = \BookStack\Entities\Page::first();
         $this->asAdmin()->visit($page->getUrl() . '/permissions')
             ->see('Page Permissions')
             ->check('restricted')
@@ -445,7 +447,7 @@ class RestrictionsTest extends BrowserKitTest
             ->seeInDatabase('pages', ['id' => $page->id, 'restricted' => true])
             ->seeInDatabase('entity_permissions', [
                 'restrictable_id' => $page->id,
-                'restrictable_type' => 'BookStack\Page',
+                'restrictable_type' => Page::newModelInstance()->getMorphClass(),
                 'role_id' => '2',
                 'action' => 'delete'
             ]);
@@ -453,7 +455,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_restricted_pages_not_visible_in_book_navigation_on_pages()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $page = $chapter->pages->first();
         $page2 = $chapter->pages[2];
 
@@ -466,7 +468,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_restricted_pages_not_visible_in_book_navigation_on_chapters()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $page = $chapter->pages->first();
 
         $this->setEntityRestrictions($page, []);
@@ -478,7 +480,7 @@ class RestrictionsTest extends BrowserKitTest
 
     public function test_restricted_pages_not_visible_on_chapter_pages()
     {
-        $chapter = \BookStack\Chapter::first();
+        $chapter = Chapter::first();
         $page = $chapter->pages->first();
 
         $this->setEntityRestrictions($page, []);
diff --git a/tests/Permissions/RolesTest.php b/tests/Permissions/RolesTest.php
index e0f827d02..95cb7cd57 100644
--- a/tests/Permissions/RolesTest.php
+++ b/tests/Permissions/RolesTest.php
@@ -1,9 +1,9 @@
 <?php namespace Tests;
 
-use BookStack\Bookshelf;
-use BookStack\Page;
-use BookStack\Repos\PermissionsRepo;
-use BookStack\Role;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Page;
+use BookStack\Auth\Permissions\PermissionsRepo;
+use BookStack\Auth\Role;
 use Laravel\BrowserKitTesting\HttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
@@ -24,7 +24,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_cannot_delete_admin_role()
     {
-        $adminRole = \BookStack\Role::getRole('admin');
+        $adminRole = \BookStack\Auth\Role::getRole('admin');
         $deletePageUrl = '/settings/roles/delete/' . $adminRole->id;
         $this->asAdmin()->visit($deletePageUrl)
             ->press('Confirm')
@@ -108,7 +108,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_restrictions_manage_all_permission()
     {
-        $page = \BookStack\Page::take(1)->get()->first();
+        $page = \BookStack\Entities\Page::take(1)->get()->first();
         $this->actingAs($this->user)->visit($page->getUrl())
             ->dontSee('Permissions')
             ->visit($page->getUrl() . '/permissions')
@@ -122,7 +122,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_restrictions_manage_own_permission()
     {
-        $otherUsersPage = \BookStack\Page::first();
+        $otherUsersPage = \BookStack\Entities\Page::first();
         $content = $this->createEntityChainBelongingToUser($this->user);
         // Check can't restrict other's content
         $this->actingAs($this->user)->visit($otherUsersPage->getUrl())
@@ -214,7 +214,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_bookshelves_edit_all_permission()
     {
-        $otherShelf = \BookStack\Bookshelf::first();
+        $otherShelf = \BookStack\Entities\Bookshelf::first();
         $this->checkAccessPermission('bookshelf-update-all', [
             $otherShelf->getUrl('/edit')
         ], [
@@ -225,7 +225,7 @@ class RolesTest extends BrowserKitTest
     public function test_bookshelves_delete_own_permission()
     {
         $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
-        $otherShelf = \BookStack\Bookshelf::first();
+        $otherShelf = \BookStack\Entities\Bookshelf::first();
         $ownShelf = $this->newShelf(['name' => 'test-shelf', 'slug' => 'test-shelf']);
         $ownShelf->forceFill(['created_by' => $this->user->id, 'updated_by' => $this->user->id])->save();
         $this->regenEntityPermissions($ownShelf);
@@ -249,7 +249,7 @@ class RolesTest extends BrowserKitTest
     public function test_bookshelves_delete_all_permission()
     {
         $this->giveUserPermissions($this->user, ['bookshelf-update-all']);
-        $otherShelf = \BookStack\Bookshelf::first();
+        $otherShelf = \BookStack\Entities\Bookshelf::first();
         $this->checkAccessPermission('bookshelf-delete-all', [
             $otherShelf->getUrl('/delete')
         ], [
@@ -279,7 +279,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_books_edit_own_permission()
     {
-        $otherBook = \BookStack\Book::take(1)->get()->first();
+        $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
         $this->checkAccessPermission('book-update-own', [
             $ownBook->getUrl() . '/edit'
@@ -295,7 +295,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_books_edit_all_permission()
     {
-        $otherBook = \BookStack\Book::take(1)->get()->first();
+        $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
         $this->checkAccessPermission('book-update-all', [
             $otherBook->getUrl() . '/edit'
         ], [
@@ -306,7 +306,7 @@ class RolesTest extends BrowserKitTest
     public function test_books_delete_own_permission()
     {
         $this->giveUserPermissions($this->user, ['book-update-all']);
-        $otherBook = \BookStack\Book::take(1)->get()->first();
+        $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
         $this->checkAccessPermission('book-delete-own', [
             $ownBook->getUrl() . '/delete'
@@ -327,7 +327,7 @@ class RolesTest extends BrowserKitTest
     public function test_books_delete_all_permission()
     {
         $this->giveUserPermissions($this->user, ['book-update-all']);
-        $otherBook = \BookStack\Book::take(1)->get()->first();
+        $otherBook = \BookStack\Entities\Book::take(1)->get()->first();
         $this->checkAccessPermission('book-delete-all', [
             $otherBook->getUrl() . '/delete'
         ], [
@@ -342,7 +342,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_chapter_create_own_permissions()
     {
-        $book = \BookStack\Book::take(1)->get()->first();
+        $book = \BookStack\Entities\Book::take(1)->get()->first();
         $ownBook = $this->createEntityChainBelongingToUser($this->user)['book'];
         $this->checkAccessPermission('chapter-create-own', [
             $ownBook->getUrl('/create-chapter')
@@ -364,7 +364,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_chapter_create_all_permissions()
     {
-        $book = \BookStack\Book::take(1)->get()->first();
+        $book = \BookStack\Entities\Book::take(1)->get()->first();
         $this->checkAccessPermission('chapter-create-all', [
             $book->getUrl('/create-chapter')
         ], [
@@ -380,7 +380,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_chapter_edit_own_permission()
     {
-        $otherChapter = \BookStack\Chapter::take(1)->get()->first();
+        $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
         $this->checkAccessPermission('chapter-update-own', [
             $ownChapter->getUrl() . '/edit'
@@ -396,7 +396,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_chapter_edit_all_permission()
     {
-        $otherChapter = \BookStack\Chapter::take(1)->get()->first();
+        $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
         $this->checkAccessPermission('chapter-update-all', [
             $otherChapter->getUrl() . '/edit'
         ], [
@@ -407,7 +407,7 @@ class RolesTest extends BrowserKitTest
     public function test_chapter_delete_own_permission()
     {
         $this->giveUserPermissions($this->user, ['chapter-update-all']);
-        $otherChapter = \BookStack\Chapter::take(1)->get()->first();
+        $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
         $ownChapter = $this->createEntityChainBelongingToUser($this->user)['chapter'];
         $this->checkAccessPermission('chapter-delete-own', [
             $ownChapter->getUrl() . '/delete'
@@ -429,7 +429,7 @@ class RolesTest extends BrowserKitTest
     public function test_chapter_delete_all_permission()
     {
         $this->giveUserPermissions($this->user, ['chapter-update-all']);
-        $otherChapter = \BookStack\Chapter::take(1)->get()->first();
+        $otherChapter = \BookStack\Entities\Chapter::take(1)->get()->first();
         $this->checkAccessPermission('chapter-delete-all', [
             $otherChapter->getUrl() . '/delete'
         ], [
@@ -445,8 +445,8 @@ class RolesTest extends BrowserKitTest
 
     public function test_page_create_own_permissions()
     {
-        $book = \BookStack\Book::first();
-        $chapter = \BookStack\Chapter::first();
+        $book = \BookStack\Entities\Book::first();
+        $chapter = \BookStack\Entities\Chapter::first();
 
         $entities = $this->createEntityChainBelongingToUser($this->user);
         $ownBook = $entities['book'];
@@ -470,7 +470,7 @@ class RolesTest extends BrowserKitTest
 
         foreach ($accessUrls as $index => $url) {
             $this->actingAs($this->user)->visit($url);
-            $expectedUrl = \BookStack\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
+            $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
             $this->seePageIs($expectedUrl);
         }
 
@@ -492,8 +492,8 @@ class RolesTest extends BrowserKitTest
 
     public function test_page_create_all_permissions()
     {
-        $book = \BookStack\Book::take(1)->get()->first();
-        $chapter = \BookStack\Chapter::take(1)->get()->first();
+        $book = \BookStack\Entities\Book::take(1)->get()->first();
+        $chapter = \BookStack\Entities\Chapter::take(1)->get()->first();
         $baseUrl = $book->getUrl() . '/page';
         $createUrl = $book->getUrl('/create-page');
 
@@ -514,7 +514,7 @@ class RolesTest extends BrowserKitTest
 
         foreach ($accessUrls as $index => $url) {
             $this->actingAs($this->user)->visit($url);
-            $expectedUrl = \BookStack\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
+            $expectedUrl = \BookStack\Entities\Page::where('draft', '=', true)->orderBy('id', 'desc')->first()->getUrl();
             $this->seePageIs($expectedUrl);
         }
 
@@ -533,7 +533,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_page_edit_own_permission()
     {
-        $otherPage = \BookStack\Page::take(1)->get()->first();
+        $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
         $this->checkAccessPermission('page-update-own', [
             $ownPage->getUrl() . '/edit'
@@ -549,7 +549,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_page_edit_all_permission()
     {
-        $otherPage = \BookStack\Page::take(1)->get()->first();
+        $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
         $this->checkAccessPermission('page-update-all', [
             $otherPage->getUrl() . '/edit'
         ], [
@@ -560,7 +560,7 @@ class RolesTest extends BrowserKitTest
     public function test_page_delete_own_permission()
     {
         $this->giveUserPermissions($this->user, ['page-update-all']);
-        $otherPage = \BookStack\Page::take(1)->get()->first();
+        $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
         $ownPage = $this->createEntityChainBelongingToUser($this->user)['page'];
         $this->checkAccessPermission('page-delete-own', [
             $ownPage->getUrl() . '/delete'
@@ -582,7 +582,7 @@ class RolesTest extends BrowserKitTest
     public function test_page_delete_all_permission()
     {
         $this->giveUserPermissions($this->user, ['page-update-all']);
-        $otherPage = \BookStack\Page::take(1)->get()->first();
+        $otherPage = \BookStack\Entities\Page::take(1)->get()->first();
         $this->checkAccessPermission('page-delete-all', [
             $otherPage->getUrl() . '/delete'
         ], [
@@ -598,7 +598,7 @@ class RolesTest extends BrowserKitTest
 
     public function test_public_role_visible_in_user_edit_screen()
     {
-        $user = \BookStack\User::first();
+        $user = \BookStack\Auth\User::first();
         $this->asAdmin()->visit('/settings/users/' . $user->id)
             ->seeElement('#roles-admin')
             ->seeElement('#roles-public');
@@ -633,8 +633,8 @@ class RolesTest extends BrowserKitTest
     public function test_image_delete_own_permission()
     {
         $this->giveUserPermissions($this->user, ['image-update-all']);
-        $page = \BookStack\Page::first();
-        $image = factory(\BookStack\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]);
+        $page = \BookStack\Entities\Page::first();
+        $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $this->user->id, 'updated_by' => $this->user->id]);
 
         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
             ->seeStatusCode(403);
@@ -650,8 +650,8 @@ class RolesTest extends BrowserKitTest
     {
         $this->giveUserPermissions($this->user, ['image-update-all']);
         $admin = $this->getAdmin();
-        $page = \BookStack\Page::first();
-        $image = factory(\BookStack\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
+        $page = \BookStack\Entities\Page::first();
+        $image = factory(\BookStack\Uploads\Image::class)->create(['uploaded_to' => $page->id, 'created_by' => $admin->id, 'updated_by' => $admin->id]);
 
         $this->actingAs($this->user)->json('delete', '/images/' . $image->id)
             ->seeStatusCode(403);
@@ -672,7 +672,7 @@ class RolesTest extends BrowserKitTest
     {
         // To cover issue fixed in f99c8ff99aee9beb8c692f36d4b84dc6e651e50a.
         $page = Page::first();
-        $viewerRole = \BookStack\Role::getRole('viewer');
+        $viewerRole = \BookStack\Auth\Role::getRole('viewer');
         $viewer = $this->getViewer();
         $this->actingAs($viewer)->visit($page->getUrl())->assertResponseStatus(200);
 
@@ -690,14 +690,14 @@ class RolesTest extends BrowserKitTest
     {
         $admin = $this->getAdmin();
         // Book links
-        $book = factory(\BookStack\Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
+        $book = factory(\BookStack\Entities\Book::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id]);
         $this->updateEntityPermissions($book);
         $this->actingAs($this->getViewer())->visit($book->getUrl())
             ->dontSee('Create a new page')
             ->dontSee('Add a chapter');
 
         // Chapter links
-        $chapter = factory(\BookStack\Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
+        $chapter = factory(\BookStack\Entities\Chapter::class)->create(['created_by' => $admin->id, 'updated_by' => $admin->id, 'book_id' => $book->id]);
         $this->updateEntityPermissions($chapter);
         $this->actingAs($this->getViewer())->visit($chapter->getUrl())
             ->dontSee('Create a new page')
@@ -781,7 +781,7 @@ class RolesTest extends BrowserKitTest
     }
 
     private function addComment($page) {
-        $comment = factory(\BookStack\Comment::class)->make();
+        $comment = factory(\BookStack\Actions\Comment::class)->make();
         $url = "/ajax/page/$page->id/comment";
         $request = [
             'text' => $comment->text,
@@ -794,7 +794,7 @@ class RolesTest extends BrowserKitTest
     }
 
     private function updateComment($commentId) {
-        $comment = factory(\BookStack\Comment::class)->make();
+        $comment = factory(\BookStack\Actions\Comment::class)->make();
         $url = "/ajax/comment/$commentId";
         $request = [
             'text' => $comment->text,
diff --git a/tests/PublicActionTest.php b/tests/PublicActionTest.php
index dadb37e46..671b5ee42 100644
--- a/tests/PublicActionTest.php
+++ b/tests/PublicActionTest.php
@@ -6,18 +6,18 @@ class PublicActionTest extends BrowserKitTest
     public function test_app_not_public()
     {
         $this->setSettings(['app-public' => 'false']);
-        $book = \BookStack\Book::orderBy('name', 'asc')->first();
+        $book = \BookStack\Entities\Book::orderBy('name', 'asc')->first();
         $this->visit('/books')->seePageIs('/login');
         $this->visit($book->getUrl())->seePageIs('/login');
 
-        $page = \BookStack\Page::first();
+        $page = \BookStack\Entities\Page::first();
         $this->visit($page->getUrl())->seePageIs('/login');
     }
 
     public function test_books_viewable()
     {
         $this->setSettings(['app-public' => 'true']);
-        $books = \BookStack\Book::orderBy('name', 'asc')->take(10)->get();
+        $books = \BookStack\Entities\Book::orderBy('name', 'asc')->take(10)->get();
         $bookToVisit = $books[1];
 
         // Check books index page is showing
@@ -34,7 +34,7 @@ class PublicActionTest extends BrowserKitTest
     public function test_chapters_viewable()
     {
         $this->setSettings(['app-public' => 'true']);
-        $chapterToVisit = \BookStack\Chapter::first();
+        $chapterToVisit = \BookStack\Entities\Chapter::first();
         $pageToVisit = $chapterToVisit->pages()->first();
 
         // Check chapters index page is showing
@@ -52,15 +52,15 @@ class PublicActionTest extends BrowserKitTest
     public function test_public_page_creation()
     {
         $this->setSettings(['app-public' => 'true']);
-        $publicRole = \BookStack\Role::getSystemRole('public');
+        $publicRole = \BookStack\Auth\Role::getSystemRole('public');
         // Grant all permissions to public
         $publicRole->permissions()->detach();
-        foreach (\BookStack\RolePermission::all() as $perm) {
+        foreach (\BookStack\Auth\Permissions\RolePermission::all() as $perm) {
             $publicRole->attachPermission($perm);
         }
-        $this->app[\BookStack\Services\PermissionService::class]->buildJointPermissionForRole($publicRole);
+        $this->app[\BookStack\Auth\Permissions\PermissionService::class]->buildJointPermissionForRole($publicRole);
 
-        $chapter = \BookStack\Chapter::first();
+        $chapter = \BookStack\Entities\Chapter::first();
         $this->visit($chapter->book->getUrl());
         $this->visit($chapter->getUrl())
             ->click('New Page')
@@ -71,7 +71,7 @@ class PublicActionTest extends BrowserKitTest
             'name' => 'My guest page'
         ])->seePageIs($chapter->book->getUrl('/page/my-guest-page/edit'));
 
-        $user = \BookStack\User::getDefault();
+        $user = \BookStack\Auth\User::getDefault();
         $this->seeInDatabase('pages', [
             'name' => 'My guest page',
             'chapter_id' => $chapter->id,
@@ -82,7 +82,7 @@ class PublicActionTest extends BrowserKitTest
 
     public function test_content_not_listed_on_404_for_public_users()
     {
-        $page = \BookStack\Page::first();
+        $page = \BookStack\Entities\Page::first();
         $this->asAdmin()->visit($page->getUrl());
         \Auth::logout();
         view()->share('pageTitle', '');
diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php
index ad983423c..80fab874c 100644
--- a/tests/SharedTestHelpers.php
+++ b/tests/SharedTestHelpers.php
@@ -1,15 +1,15 @@
 <?php namespace Tests;
 
-use BookStack\Book;
-use BookStack\Bookshelf;
-use BookStack\Chapter;
-use BookStack\Entity;
-use BookStack\Page;
-use BookStack\Repos\EntityRepo;
-use BookStack\Repos\PermissionsRepo;
-use BookStack\Role;
-use BookStack\Services\PermissionService;
-use BookStack\Services\SettingService;
+use BookStack\Entities\Book;
+use BookStack\Entities\Bookshelf;
+use BookStack\Entities\Chapter;
+use BookStack\Entities\Entity;
+use BookStack\Entities\Page;
+use BookStack\Entities\EntityRepo;
+use BookStack\Auth\Permissions\PermissionsRepo;
+use BookStack\Auth\Role;
+use BookStack\Auth\Permissions\PermissionService;
+use BookStack\Settings\SettingService;
 
 trait SharedTestHelpers
 {
@@ -67,7 +67,7 @@ trait SharedTestHelpers
      */
     protected function getViewer($attributes = [])
     {
-        $user = \BookStack\Role::getRole('viewer')->users()->first();
+        $user = \BookStack\Auth\Role::getRole('viewer')->users()->first();
         if (!empty($attributes)) $user->forceFill($attributes)->save();
         return $user;
     }
@@ -85,7 +85,7 @@ trait SharedTestHelpers
     /**
      * Create and return a new bookshelf.
      * @param array $input
-     * @return Bookshelf
+     * @return \BookStack\Entities\Bookshelf
      */
     public function newShelf($input = ['name' => 'test shelf', 'description' => 'My new test shelf']) {
         return $this->app[EntityRepo::class]->createFromInput('bookshelf', $input, false);
@@ -104,7 +104,7 @@ trait SharedTestHelpers
      * Create and return a new test chapter
      * @param array $input
      * @param Book $book
-     * @return Chapter
+     * @return \BookStack\Entities\Chapter
      */
     public function newChapter($input = ['name' => 'test chapter', 'description' => 'My new test chapter'], Book $book) {
         return $this->app[EntityRepo::class]->createFromInput('chapter', $input, $book);
@@ -164,10 +164,10 @@ trait SharedTestHelpers
 
     /**
      * Give the given user some permissions.
-     * @param \BookStack\User $user
+     * @param \BookStack\Auth\User $user
      * @param array $permissions
      */
-    protected function giveUserPermissions(\BookStack\User $user, $permissions = [])
+    protected function giveUserPermissions(\BookStack\Auth\User $user, $permissions = [])
     {
         $newRole = $this->createNewRole($permissions);
         $user->attachRole($newRole);
diff --git a/tests/UserProfileTest.php b/tests/UserProfileTest.php
index c1e254090..0c29f63c5 100644
--- a/tests/UserProfileTest.php
+++ b/tests/UserProfileTest.php
@@ -7,7 +7,7 @@ class UserProfileTest extends BrowserKitTest
     public function setUp()
     {
         parent::setUp();
-        $this->user = \BookStack\User::all()->last();
+        $this->user = \BookStack\Auth\User::all()->last();
     }
 
     public function test_profile_page_shows_name()
@@ -87,7 +87,7 @@ class UserProfileTest extends BrowserKitTest
 
     public function test_guest_profile_cannot_be_deleted()
     {
-        $guestUser = \BookStack\User::getDefault();
+        $guestUser = \BookStack\Auth\User::getDefault();
         $this->asAdmin()->visit('/settings/users/' . $guestUser->id . '/delete')
             ->see('Delete User')->see('Guest')
             ->press('Confirm')