]> BookStack Code Mirror - bookstack/commitdiff
Permissions: Cleanup after review of enum implementation PR 5793/head
authorDan Brown <redacted>
Wed, 10 Sep 2025 10:36:54 +0000 (11:36 +0100)
committerDan Brown <redacted>
Wed, 10 Sep 2025 10:36:54 +0000 (11:36 +0100)
19 files changed:
app/Activity/Tools/CommentTree.php
app/Activity/Tools/TagClassGenerator.php
app/Entities/Controllers/PageController.php
app/Entities/Repos/ChapterRepo.php
app/Entities/Repos/PageRepo.php
app/Entities/Tools/Cloner.php
app/Entities/Tools/PageEditorData.php
app/Entities/Tools/PermissionsUpdater.php
app/Exports/ImportRepo.php
app/Exports/ZipExports/ZipExportReferences.php
app/Exports/ZipExports/ZipImportRunner.php
app/Sorting/BookSorter.php
app/Uploads/Controllers/DrawioImageController.php
app/Users/Controllers/UserAccountController.php
app/Users/Controllers/UserApiController.php
app/Users/Controllers/UserSearchController.php
resources/views/entities/book-tree.blade.php
resources/views/pages/parts/image-manager-form.blade.php
resources/views/pages/show.blade.php

index af9b7ecb2929b7682cd09bbd122cf505e5a831c8..66df294308676d384f50dc37db5b4dc735600b32 100644 (file)
@@ -4,6 +4,7 @@ namespace BookStack\Activity\Tools;
 
 use BookStack\Activity\Models\Comment;
 use BookStack\Entities\Models\Page;
+use BookStack\Permissions\Permission;
 
 class CommentTree
 {
@@ -70,7 +71,7 @@ class CommentTree
     public function canUpdateAny(): bool
     {
         foreach ($this->comments as $comment) {
-            if (userCan(\BookStack\Permissions\Permission::CommentUpdate, $comment)) {
+            if (userCan(Permission::CommentUpdate, $comment)) {
                 return true;
             }
         }
index 03586eb277fd669aee12f8d975a5aef05ff22fbf..0f7aa1fe0c4d6e4c5511b18af91f101e0448e113 100644 (file)
@@ -6,6 +6,7 @@ use BookStack\Activity\Models\Tag;
 use BookStack\Entities\Models\BookChild;
 use BookStack\Entities\Models\Entity;
 use BookStack\Entities\Models\Page;
+use BookStack\Permissions\Permission;
 
 class TagClassGenerator
 {
@@ -26,14 +27,14 @@ class TagClassGenerator
              array_push($classes, ...$this->generateClassesForTag($tag));
         }
 
-        if ($this->entity instanceof BookChild && userCan(\BookStack\Permissions\Permission::View, $this->entity->book)) {
+        if ($this->entity instanceof BookChild && userCan(Permission::BookView, $this->entity->book)) {
             $bookTags = $this->entity->book->tags;
             foreach ($bookTags as $bookTag) {
                  array_push($classes, ...$this->generateClassesForTag($bookTag, 'book-'));
             }
         }
 
-        if ($this->entity instanceof Page && $this->entity->chapter && userCan(\BookStack\Permissions\Permission::View, $this->entity->chapter)) {
+        if ($this->entity instanceof Page && $this->entity->chapter && userCan(Permission::ChapterView, $this->entity->chapter)) {
             $chapterTags = $this->entity->chapter->tags;
             foreach ($chapterTags as $chapterTag) {
                  array_push($classes, ...$this->generateClassesForTag($chapterTag, 'chapter-'));
index 1fe296537d0d3ae596adc81ff33133f5b5a39b5f..67ecb0bb3773bfdb5681b6272d899774b19f0d98 100644 (file)
@@ -342,7 +342,7 @@ class PageController extends Controller
 
         $this->showSuccessNotification(trans('entities.pages_delete_draft_success'));
 
-        if ($chapter && userCan(\BookStack\Permissions\Permission::View, $chapter)) {
+        if ($chapter && userCan(Permission::ChapterView, $chapter)) {
             return redirect($chapter->getUrl());
         }
 
index 10b9697ed1327cbaa6066415900afc7b536ab2de..5d4b5297841525b2709952e3d358610f8c3d8871 100644 (file)
@@ -11,6 +11,7 @@ use BookStack\Entities\Tools\TrashCan;
 use BookStack\Exceptions\MoveOperationException;
 use BookStack\Exceptions\PermissionsException;
 use BookStack\Facades\Activity;
+use BookStack\Permissions\Permission;
 use BookStack\Util\DatabaseTransaction;
 use Exception;
 
@@ -87,7 +88,7 @@ class ChapterRepo
             throw new MoveOperationException('Book to move chapter into not found');
         }
 
-        if (!userCan(\BookStack\Permissions\Permission::ChapterCreate, $parent)) {
+        if (!userCan(Permission::ChapterCreate, $parent)) {
             throw new PermissionsException('User does not have permission to create a chapter within the chosen book');
         }
 
index 4a9efd31daedaf0e0979aeb6e6d9ade833d0de5c..76377f9a6dd0916aefb49809a13e33892c262500 100644 (file)
@@ -16,6 +16,7 @@ use BookStack\Entities\Tools\TrashCan;
 use BookStack\Exceptions\MoveOperationException;
 use BookStack\Exceptions\PermissionsException;
 use BookStack\Facades\Activity;
+use BookStack\Permissions\Permission;
 use BookStack\References\ReferenceStore;
 use BookStack\References\ReferenceUpdater;
 use BookStack\Util\DatabaseTransaction;
@@ -55,7 +56,7 @@ class PageRepo
         }
 
         $defaultTemplate = $page->chapter->defaultTemplate ?? $page->book->defaultTemplate;
-        if ($defaultTemplate && userCan(\BookStack\Permissions\Permission::View, $defaultTemplate)) {
+        if ($defaultTemplate && userCan(Permission::PageView, $defaultTemplate)) {
             $page->forceFill([
                 'html'  => $defaultTemplate->html,
                 'markdown' => $defaultTemplate->markdown,
@@ -142,7 +143,7 @@ class PageRepo
 
     protected function updateTemplateStatusAndContentFromInput(Page $page, array $input): void
     {
-        if (isset($input['template']) && userCan(\BookStack\Permissions\Permission::TemplatesManage)) {
+        if (isset($input['template']) && userCan(Permission::TemplatesManage)) {
             $page->template = ($input['template'] === 'true');
         }
 
@@ -165,7 +166,7 @@ class PageRepo
             $pageContent->setNewHTML($input['html'], user());
         }
 
-        if (($newEditor !== $currentEditor || empty($page->editor)) && userCan(\BookStack\Permissions\Permission::EditorChange)) {
+        if (($newEditor !== $currentEditor || empty($page->editor)) && userCan(Permission::EditorChange)) {
             $page->editor = $newEditor->value;
         } elseif (empty($page->editor)) {
             $page->editor = $defaultEditor->value;
@@ -271,7 +272,7 @@ class PageRepo
             throw new MoveOperationException('Book or chapter to move page into not found');
         }
 
-        if (!userCan(\BookStack\Permissions\Permission::PageCreate, $parent)) {
+        if (!userCan(Permission::PageCreate, $parent)) {
             throw new PermissionsException('User does not have permission to create a page within the new parent');
         }
 
index 0af25a2c12910dba90a0dc5d803cc5d605297f9e..05618fef46150990369c1b202cfa55cbf19342a9 100644 (file)
@@ -12,6 +12,7 @@ use BookStack\Entities\Models\Page;
 use BookStack\Entities\Repos\BookRepo;
 use BookStack\Entities\Repos\ChapterRepo;
 use BookStack\Entities\Repos\PageRepo;
+use BookStack\Permissions\Permission;
 use BookStack\Uploads\Image;
 use BookStack\Uploads\ImageService;
 use Illuminate\Http\UploadedFile;
@@ -49,7 +50,7 @@ class Cloner
 
         $copyChapter = $this->chapterRepo->create($chapterDetails, $parent);
 
-        if (userCan(\BookStack\Permissions\Permission::PageCreate, $copyChapter)) {
+        if (userCan(Permission::PageCreate, $copyChapter)) {
             /** @var Page $page */
             foreach ($original->getVisiblePages() as $page) {
                 $this->clonePage($page, $copyChapter, $page->name);
@@ -61,7 +62,7 @@ class Cloner
 
     /**
      * Clone the given book.
-     * Clones all child chapters & pages.
+     * Clones all child chapters and pages.
      */
     public function cloneBook(Book $original, string $newName): Book
     {
@@ -74,11 +75,11 @@ class Cloner
         // Clone contents
         $directChildren = $original->getDirectVisibleChildren();
         foreach ($directChildren as $child) {
-            if ($child instanceof Chapter && userCan(\BookStack\Permissions\Permission::ChapterCreate, $copyBook)) {
+            if ($child instanceof Chapter && userCan(Permission::ChapterCreate, $copyBook)) {
                 $this->cloneChapter($child, $copyBook, $child->name);
             }
 
-            if ($child instanceof Page && !$child->draft && userCan(\BookStack\Permissions\Permission::PageCreate, $copyBook)) {
+            if ($child instanceof Page && !$child->draft && userCan(Permission::PageCreate, $copyBook)) {
                 $this->clonePage($child, $copyBook, $child->name);
             }
         }
@@ -86,7 +87,7 @@ class Cloner
         // Clone bookshelf relationships
         /** @var Bookshelf $shelf */
         foreach ($original->shelves as $shelf) {
-            if (userCan(\BookStack\Permissions\Permission::BookshelfUpdate, $shelf)) {
+            if (userCan(Permission::BookshelfUpdate, $shelf)) {
                 $shelf->appendBook($copyBook);
             }
         }
index fc32e9a434ba9a19e7ccb4088a5572646083d51c..b41b319095ecaaea6627fe868022f4dc3831db8f 100644 (file)
@@ -7,6 +7,7 @@ use BookStack\Entities\Models\Page;
 use BookStack\Entities\Queries\EntityQueries;
 use BookStack\Entities\Tools\Markdown\HtmlToMarkdown;
 use BookStack\Entities\Tools\Markdown\MarkdownToHtml;
+use BookStack\Permissions\Permission;
 
 class PageEditorData
 {
@@ -98,9 +99,9 @@ class PageEditorData
     {
         $editorType = PageEditorType::forPage($page) ?: PageEditorType::getSystemDefault();
 
-        // Use requested editor if valid and if we have permission
+        // Use the requested editor if valid and if we have permission
         $requestedType = PageEditorType::fromRequestValue($this->requestedEditor);
-        if ($requestedType && userCan(\BookStack\Permissions\Permission::EditorChange)) {
+        if ($requestedType && userCan(Permission::EditorChange)) {
             $editorType = $requestedType;
         }
 
index fbf92e2033e6d8e23495c088e588457beeabe2c4..fa9ae753c516e299b58b47f4ccc6071537d3f793 100644 (file)
@@ -150,7 +150,7 @@ class PermissionsUpdater
 
         /** @var Book $book */
         foreach ($shelfBooks as $book) {
-            if ($checkUserPermissions && !userCan(\BookStack\Permissions\Permission::RestrictionsManage, $book)) {
+            if ($checkUserPermissions && !userCan(Permission::RestrictionsManage, $book)) {
                 continue;
             }
             $book->permissions()->delete();
index 071fa532cbd1966d34322e45af80a0a39240c811..79db69fca8f16bd7bb6c12184c11295b1e8d9f7a 100644 (file)
@@ -16,6 +16,7 @@ use BookStack\Exports\ZipExports\ZipExportReader;
 use BookStack\Exports\ZipExports\ZipExportValidator;
 use BookStack\Exports\ZipExports\ZipImportRunner;
 use BookStack\Facades\Activity;
+use BookStack\Permissions\Permission;
 use BookStack\Uploads\FileStorage;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
@@ -46,7 +47,7 @@ class ImportRepo
     {
         $query = Import::query();
 
-        if (!userCan(\BookStack\Permissions\Permission::SettingsManage)) {
+        if (!userCan(Permission::SettingsManage)) {
             $query->where('created_by', user()->id);
         }
 
@@ -57,7 +58,7 @@ class ImportRepo
     {
         $query = Import::query();
 
-        if (!userCan(\BookStack\Permissions\Permission::SettingsManage)) {
+        if (!userCan(Permission::SettingsManage)) {
             $query->where('created_by', user()->id);
         }
 
index 621076acc95f1d5985be080ac80792f88152dbb4..64107cf21aa0a7ba68503f6adf6260addfb14cd7 100644 (file)
@@ -12,6 +12,7 @@ use BookStack\Exports\ZipExports\Models\ZipExportChapter;
 use BookStack\Exports\ZipExports\Models\ZipExportImage;
 use BookStack\Exports\ZipExports\Models\ZipExportModel;
 use BookStack\Exports\ZipExports\Models\ZipExportPage;
+use BookStack\Permissions\Permission;
 use BookStack\Uploads\Attachment;
 use BookStack\Uploads\Image;
 
@@ -135,7 +136,7 @@ class ZipExportReferences
             // Find and include images if in visibility
             $page = $model->getPage();
             $pageExportModel = $this->pages[$page->id] ?? ($exportModel instanceof ZipExportPage ? $exportModel : null);
-            if (isset($this->images[$model->id]) || ($page && $pageExportModel && userCan(\BookStack\Permissions\Permission::View, $page))) {
+            if (isset($this->images[$model->id]) || ($page && $pageExportModel && userCan(Permission::PageView, $page))) {
                 if (!isset($this->images[$model->id])) {
                     $exportImage = ZipExportImage::fromModel($model, $files);
                     $this->images[$model->id] = $exportImage;
index 09a946609c812964612cbb128f2aa6ea359f12f0..eafb527e87ebe77c7d060a78e17aafa1c6422954 100644 (file)
@@ -18,6 +18,7 @@ use BookStack\Exports\ZipExports\Models\ZipExportChapter;
 use BookStack\Exports\ZipExports\Models\ZipExportImage;
 use BookStack\Exports\ZipExports\Models\ZipExportPage;
 use BookStack\Exports\ZipExports\Models\ZipExportTag;
+use BookStack\Permissions\Permission;
 use BookStack\Uploads\Attachment;
 use BookStack\Uploads\AttachmentService;
 use BookStack\Uploads\FileStorage;
@@ -288,7 +289,7 @@ class ZipImportRunner
         $attachments = [];
 
         if ($exportModel instanceof ZipExportBook) {
-            if (!userCan(\BookStack\Permissions\Permission::BookCreateAll)) {
+            if (!userCan(Permission::BookCreateAll)) {
                 $errors[] = trans('errors.import_perms_books');
             }
             array_push($pages, ...$exportModel->pages);
@@ -317,11 +318,11 @@ class ZipImportRunner
 
         if (count($pages) > 0) {
             if ($parent) {
-                if (!userCan(\BookStack\Permissions\Permission::PageCreate, $parent)) {
+                if (!userCan(Permission::PageCreate, $parent)) {
                     $errors[] = trans('errors.import_perms_pages');
                 }
             } else {
-                $hasPermission = userCan(\BookStack\Permissions\Permission::PageCreateAll) || userCan(\BookStack\Permissions\Permission::PageCreateOwn);
+                $hasPermission = userCan(Permission::PageCreateAll) || userCan(Permission::PageCreateOwn);
                 if (!$hasPermission) {
                     $errors[] = trans('errors.import_perms_pages');
                 }
@@ -329,13 +330,13 @@ class ZipImportRunner
         }
 
         if (count($images) > 0) {
-            if (!userCan(\BookStack\Permissions\Permission::ImageCreateAll)) {
+            if (!userCan(Permission::ImageCreateAll)) {
                 $errors[] = trans('errors.import_perms_images');
             }
         }
 
         if (count($attachments) > 0) {
-            if (!userCan(\BookStack\Permissions\Permission::AttachmentCreateAll)) {
+            if (!userCan(Permission::AttachmentCreateAll)) {
                 $errors[] = trans('errors.import_perms_attachments');
             }
         }
index e1fd17238c060b1802cd37e54ac3a5601abf6841..1152101d29388040cbad7a8652a99cd37dc5ac02 100644 (file)
@@ -8,6 +8,7 @@ use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Entity;
 use BookStack\Entities\Models\Page;
 use BookStack\Entities\Queries\EntityQueries;
+use BookStack\Permissions\Permission;
 
 class BookSorter
 {
@@ -187,11 +188,11 @@ class BookSorter
 
         $hasNewParent = $newBook->id !== $model->book_id || ($model instanceof Page && $model->chapter_id !== ($sortMapItem->parentChapterId ?? 0));
         if ($model instanceof Chapter) {
-            $hasPermission = userCan(\BookStack\Permissions\Permission::BookUpdate, $currentParent)
-                && userCan(\BookStack\Permissions\Permission::BookUpdate, $newBook)
-                && userCan(\BookStack\Permissions\Permission::ChapterUpdate, $model)
-                && (!$hasNewParent || userCan(\BookStack\Permissions\Permission::ChapterCreate, $newBook))
-                && (!$hasNewParent || userCan(\BookStack\Permissions\Permission::ChapterDelete, $model));
+            $hasPermission = userCan(Permission::BookUpdate, $currentParent)
+                && userCan(Permission::BookUpdate, $newBook)
+                && userCan(Permission::ChapterUpdate, $model)
+                && (!$hasNewParent || userCan(Permission::ChapterCreate, $newBook))
+                && (!$hasNewParent || userCan(Permission::ChapterDelete, $model));
 
             if (!$hasPermission) {
                 return false;
@@ -210,13 +211,13 @@ class BookSorter
                 return false;
             }
 
-            $hasPageEditPermission = userCan(\BookStack\Permissions\Permission::PageUpdate, $model);
+            $hasPageEditPermission = userCan(Permission::PageUpdate, $model);
             $newParentInRightLocation = ($newParent instanceof Book || ($newParent instanceof Chapter && $newParent->book_id === $newBook->id));
             $newParentPermission = ($newParent instanceof Chapter) ? 'chapter-update' : 'book-update';
             $hasNewParentPermission = userCan($newParentPermission, $newParent);
 
-            $hasDeletePermissionIfMoving = (!$hasNewParent || userCan(\BookStack\Permissions\Permission::PageDelete, $model));
-            $hasCreatePermissionIfMoving = (!$hasNewParent || userCan(\BookStack\Permissions\Permission::PageCreate, $newParent));
+            $hasDeletePermissionIfMoving = (!$hasNewParent || userCan(Permission::PageDelete, $model));
+            $hasCreatePermissionIfMoving = (!$hasNewParent || userCan(Permission::PageCreate, $newParent));
 
             $hasPermission = $hasCurrentParentPermission
                 && $newParentInRightLocation
index c9b49b8909fddccef1f4d7c82a107edac7afdc08..f44acd997d2c1a07a5f0bc981fafbc1eefa210f1 100644 (file)
@@ -82,7 +82,7 @@ class DrawioImageController extends Controller
             return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
         }
 
-        if ($image->type !== 'drawio' || !userCan(\BookStack\Permissions\Permission::PageView, $image->getPage())) {
+        if ($image->type !== 'drawio' || !userCan(Permission::PageView, $image->getPage())) {
             return $this->jsonError(trans('errors.drawing_data_not_found'), 404);
         }
 
index 07e384b3a88e4acf2cc9306f3c5e28b79105f8da..a8baba5294b49848ea975006198681ead57f10ca 100644 (file)
@@ -63,9 +63,9 @@ class UserAccountController extends Controller
             'profile_image'    => array_merge(['nullable'], $this->getImageValidationRules()),
         ]);
 
-        $this->userRepo->update($user, $validated, userCan(\BookStack\Permissions\Permission::UsersManage));
+        $this->userRepo->update($user, $validated, userCan(Permission::UsersManage));
 
-        // Save profile image if in request
+        // Save the profile image if in request
         if ($request->hasFile('profile_image')) {
             $imageUpload = $request->file('profile_image');
             $imageRepo->destroyImage($user->avatar);
@@ -74,7 +74,7 @@ class UserAccountController extends Controller
             $user->save();
         }
 
-        // Delete the profile image if reset option is in request
+        // Delete the profile image if the reset option is in request
         if ($request->has('profile_image_reset')) {
             $imageRepo->destroyImage($user->avatar);
             $user->image_id = 0;
@@ -219,7 +219,7 @@ class UserAccountController extends Controller
         $this->preventAccessInDemoMode();
 
         $requestNewOwnerId = intval($request->get('new_owner_id')) ?: null;
-        $newOwnerId = userCan(\BookStack\Permissions\Permission::UsersManage) ? $requestNewOwnerId : null;
+        $newOwnerId = userCan(Permission::UsersManage) ? $requestNewOwnerId : null;
 
         $this->userRepo->destroy(user(), $newOwnerId);
 
index 28c4a387619de7d5ef2e118f21f6828d8e303843..9134b3cc13b32768a00b25ec68dde42ed7398d1b 100644 (file)
@@ -125,7 +125,7 @@ class UserApiController extends ApiController
     {
         $data = $this->validate($request, $this->rules($id)['update']);
         $user = $this->userRepo->getById($id);
-        $this->userRepo->update($user, $data, userCan(\BookStack\Permissions\Permission::UsersManage));
+        $this->userRepo->update($user, $data, userCan(Permission::UsersManage));
         $this->singleFormatter($user);
 
         return response()->json($user);
index a6596046a102fdee9596ccadbf042f81cf1b187a..a2543b7eed32723d5f8052d9f0365c46cdd6efc9 100644 (file)
@@ -3,6 +3,7 @@
 namespace BookStack\Users\Controllers;
 
 use BookStack\Http\Controller;
+use BookStack\Permissions\Permission;
 use BookStack\Users\Models\User;
 use Illuminate\Http\Request;
 
@@ -15,9 +16,9 @@ class UserSearchController extends Controller
     public function forSelect(Request $request)
     {
         $hasPermission = !user()->isGuest() && (
-            userCan(\BookStack\Permissions\Permission::UsersManage)
-                || userCan(\BookStack\Permissions\Permission::RestrictionsManageOwn)
-                || userCan(\BookStack\Permissions\Permission::RestrictionsManageAll)
+            userCan(Permission::UsersManage)
+                || userCan(Permission::RestrictionsManageOwn)
+                || userCan(Permission::RestrictionsManageAll)
         );
 
         if (!$hasPermission) {
index bcc52130671d36bdd67ff7c55d8533ef193e7b4f..c95b1eebc43f1c5eaccf72618cfb35be3ad34cc5 100644 (file)
@@ -5,7 +5,7 @@
     <h5>{{ trans('entities.books_navigation') }}</h5>
 
     <ul class="sidebar-page-list mt-xs menu entity-list">
-        @if (userCan(\BookStack\Permissions\Permission::View, $book))
+        @if (userCan(\BookStack\Permissions\Permission::BookView, $book))
             <li class="list-item-book book">
                 @include('entities.list-item-basic', ['entity' => $book, 'classes' => ($current->matches($book)? 'selected' : '')])
             </li>
index 2850caba9f314a92ebd8fcbb6883bd9ca9c86fec..4d675b81e11d159f9558a9db35933bb9fc4666b5 100644 (file)
         @if($image->createdBy)
             <div>@icon('user') {{ trans('components.image_uploaded_by', ['userName' => $image->createdBy->name]) }}</div>
         @endif
-        @if(($page = $image->getPage()) && userCan(\BookStack\Permissions\Permission::View, $page))
+        @if(($page = $image->getPage()) && userCan(\BookStack\Permissions\Permission::PageView, $page))
             <div>
                 @icon('page')
                 {!! trans('components.image_uploaded_to', [
index 2216cfd1f9c699354cfa062ed70025dbf3f02afc..fcec901571b827efb23a7fbb37e0f1e587573b20 100644 (file)
                     <span>{{ trans('common.edit') }}</span>
                 </a>
             @endif
-            @if(userCanOnAny(\BookStack\Permissions\Permission::Create, \BookStack\Entities\Models\Book::class) || userCanOnAny('create', \BookStack\Entities\Models\Chapter::class) || userCan(\BookStack\Permissions\Permission::PageCreateAll) || userCan(\BookStack\Permissions\Permission::PageCreateOwn))
+            @if(userCan(\BookStack\Permissions\Permission::PageCreateAll) || userCan(\BookStack\Permissions\Permission::PageCreateOwn) || userCanOnAny(\BookStack\Permissions\Permission::Create, \BookStack\Entities\Models\Book::class) || userCanOnAny(\BookStack\Permissions\Permission::Create, \BookStack\Entities\Models\Chapter::class))
                 <a href="{{ $page->getUrl('/copy') }}" data-shortcut="copy" class="icon-list-item">
                     <span>@icon('copy')</span>
                     <span>{{ trans('common.copy') }}</span>