diff --git a/app/Activity/ActivityType.php b/app/Activity/ActivityType.php index 09b2ae73c56..2a3e674199a 100644 --- a/app/Activity/ActivityType.php +++ b/app/Activity/ActivityType.php @@ -9,6 +9,8 @@ class ActivityType const PAGE_DELETE = 'page_delete'; const PAGE_RESTORE = 'page_restore'; const PAGE_MOVE = 'page_move'; + const PAGE_ENCRYPTED = 'page_encrypted'; + const PAGE_DECRYPTED = 'page_decrypted'; const CHAPTER_CREATE = 'chapter_create'; const CHAPTER_UPDATE = 'chapter_update'; diff --git a/app/App/HomeController.php b/app/App/HomeController.php index 0585e0af5cc..7aa22574031 100644 --- a/app/App/HomeController.php +++ b/app/App/HomeController.php @@ -43,9 +43,16 @@ public function index( $recents = $this->isSignedIn() ? $recentlyViewed->run(12 * $recentFactor, 1) : $this->queries->books->visibleForList()->orderBy('created_at', 'desc')->take(12 * $recentFactor)->get(); + $recents = $recents->filter(function ($recent) { + if ($recent instanceof Page) { + return !$recent->is_encrypted; + } + return true; + }); $favourites = $topFavourites->run(6); $recentlyUpdatedPages = $this->queries->pages->visibleForList() ->where('draft', false) + ->where('is_encrypted', false) ->orderBy('updated_at', 'desc') ->take($favourites->count() > 0 ? 5 : 10) ->get(); diff --git a/app/Entities/Controllers/PageController.php b/app/Entities/Controllers/PageController.php index eab53bb2510..600187377e9 100644 --- a/app/Entities/Controllers/PageController.php +++ b/app/Entities/Controllers/PageController.php @@ -23,6 +23,7 @@ use Exception; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Hash; use Illuminate\Validation\ValidationException; use Throwable; @@ -198,6 +199,10 @@ public function edit(Request $request, string $bookSlug, string $pageSlug) $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); + if (session()->get('is_decrypt') == 'FOR_EDIT') { + $page->html = decrypt($page->html); + } + $editorData = new PageEditorData($page, $this->entityQueries, $request->query('editor', '')); if ($editorData->getWarnings()) { $this->showWarningNotification(implode("\n", $editorData->getWarnings())); @@ -222,6 +227,11 @@ public function update(Request $request, string $bookSlug, string $pageSlug) $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); $this->checkOwnablePermission('page-update', $page); + if (session()->get('is_decrypt') == 'FOR_EDIT') { + $request['html'] = encrypt($request['html']); + session()->put('is_decrypt', 'NONE'); + } + $this->pageRepo->update($page, $request->all()); return redirect($page->getUrl()); @@ -467,4 +477,51 @@ public function copy(Request $request, Cloner $cloner, string $bookSlug, string return redirect($pageCopy->getUrl()); } + + public function encrypt(Request $request, string $bookSlug, string $pageSlug) + { + $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + return $this->pageRepo->encryptPageContent($request->all(), $page); + } + + public function decrypt(Request $request, string $bookSlug, string $pageSlug) + { + $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + return $this->pageRepo->decryptPageContent($request->all(), $page); + } + + public function updateEncryption(Request $request, string $bookSlug, string $pageSlug) + { + $this->validate($request, [ + 'html' => ['required'], + 'password' => ['required'], + 'is_encrypted' => ['required','boolean'], + ]); + + $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + $this->pageRepo->update($page, $request->all()); + return response()->json(['message' => 'Encryption Update SuccessFully','success' => true]); + } + + public function updateDecryption(Request $request, string $bookSlug, string $pageSlug) + { + $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + if ($this->validateDecryptPassword($request, $bookSlug, $pageSlug)) { + if ($request->has('is_decrypt')) { + session()->put('is_decrypt', $request->get('is_decrypt')); + } + $this->pageRepo->update($page, $request->all()); + return response()->json(['contents' => [],'message' => 'Decrypted SuccessFully','success' => true]); + } else { + return response()->json(['contents' => [],'message' => 'Decrypt Password is Wrong','success' => false]); + } + } + + public function validateDecryptPassword(Request $request, string $bookSlug, string $pageSlug) + { + $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + return Hash::check($request->get('password'), $page->password) ? + response()->json(['success' => true]) : + response()->json(['success' => false]); + } } diff --git a/app/Entities/Controllers/PageExportController.php b/app/Entities/Controllers/PageExportController.php index be97f1930bd..2abf27e6d45 100644 --- a/app/Entities/Controllers/PageExportController.php +++ b/app/Entities/Controllers/PageExportController.php @@ -2,6 +2,7 @@ namespace BookStack\Entities\Controllers; +use BookStack\Entities\Models\Page; use BookStack\Entities\Queries\PageQueries; use BookStack\Entities\Tools\ExportFormatter; use BookStack\Entities\Tools\PageContent; @@ -28,6 +29,7 @@ public function __construct( public function pdf(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + $this->validatePageEncrypted($page); $page->html = (new PageContent($page))->render(); $pdfContent = $this->exportFormatter->pageToPdf($page); @@ -43,6 +45,7 @@ public function pdf(string $bookSlug, string $pageSlug) public function html(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + $this->validatePageEncrypted($page); $page->html = (new PageContent($page))->render(); $containedHtml = $this->exportFormatter->pageToContainedHtml($page); @@ -57,7 +60,8 @@ public function html(string $bookSlug, string $pageSlug) public function plainText(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); - $pageText = $this->exportFormatter->pageToPlainText($page); + $this->validatePageEncrypted($page); + $pageText = $this->exportFormatter->pageToPlainText($page, $page->is_encrypted); return $this->download()->directly($pageText, $pageSlug . '.txt'); } @@ -70,8 +74,23 @@ public function plainText(string $bookSlug, string $pageSlug) public function markdown(string $bookSlug, string $pageSlug) { $page = $this->queries->findVisibleBySlugsOrFail($bookSlug, $pageSlug); + $this->validatePageEncrypted($page); $pageText = $this->exportFormatter->pageToMarkdown($page); return $this->download()->directly($pageText, $pageSlug . '.md'); } + + public function validatePageEncrypted(Page $page) + { + if ($page->is_encrypted) { + if (session()->get('is_decrypt') == 'FOR_EXPORT') { + $page->html = decrypt($page->html); + session()->put('is_decrypt', 'NONE'); + return true; + } else { + return redirect($page->getUrl()); + } + } + return true; + } } diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index 499ef4d7288..bc4bbad7179 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -33,7 +33,7 @@ class Page extends BookChild { use HasFactory; - protected $fillable = ['name', 'priority']; + protected $fillable = ['name', 'priority','is_encrypted','password']; public string $textField = 'text'; public string $htmlField = 'html'; diff --git a/app/Entities/Queries/PageQueries.php b/app/Entities/Queries/PageQueries.php index 06298f470b9..3f09e061f86 100644 --- a/app/Entities/Queries/PageQueries.php +++ b/app/Entities/Queries/PageQueries.php @@ -11,11 +11,11 @@ class PageQueries implements ProvidesEntityQueries protected static array $contentAttributes = [ 'name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', 'template', 'html', 'text', 'created_at', 'updated_at', 'priority', - 'created_by', 'updated_by', 'owned_by', + 'created_by', 'updated_by', 'owned_by', 'is_encrypted', ]; protected static array $listAttributes = [ 'name', 'id', 'slug', 'book_id', 'chapter_id', 'draft', - 'template', 'text', 'created_at', 'updated_at', 'priority', 'owned_by', + 'template', 'text', 'created_at', 'updated_at', 'priority', 'owned_by', 'is_encrypted', ]; public function start(): Builder diff --git a/app/Entities/Repos/BaseRepo.php b/app/Entities/Repos/BaseRepo.php index 033350743e0..6aee507dc64 100644 --- a/app/Entities/Repos/BaseRepo.php +++ b/app/Entities/Repos/BaseRepo.php @@ -8,6 +8,7 @@ use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\HasCoverImage; use BookStack\Entities\Models\HasHtmlDescription; +use BookStack\Entities\Models\Page; use BookStack\Entities\Queries\PageQueries; use BookStack\Exceptions\ImageUploadException; use BookStack\References\ReferenceStore; @@ -75,7 +76,9 @@ public function update(Entity $entity, array $input) } $entity->rebuildPermissions(); - $entity->indexForSearch(); + if ((array_key_exists('is_encrypted', $input) && $input['is_encrypted'] == true) || !(($entity instanceof Page) && $entity->is_encrypted == true)) { + $entity->indexForSearch(); + } $this->referenceStore->updateForEntity($entity); if ($oldUrl !== $entity->getUrl()) { diff --git a/app/Entities/Repos/PageRepo.php b/app/Entities/Repos/PageRepo.php index 1bc15392cec..2050db00a11 100644 --- a/app/Entities/Repos/PageRepo.php +++ b/app/Entities/Repos/PageRepo.php @@ -19,6 +19,8 @@ use BookStack\References\ReferenceStore; use BookStack\References\ReferenceUpdater; use Exception; +use Illuminate\Support\Facades\Hash; +use Str; class PageRepo { @@ -97,6 +99,11 @@ public function update(Page $page, array $input): Page $oldName = $page->name; $oldMarkdown = $page->markdown; + //Make Hashable decrypt Password + if (array_key_exists('password', $input)) { + $input['password'] = Hash::make($input['password']); + } + $this->updateTemplateStatusAndContentFromInput($page, $input); $this->baseRepo->update($page, $input); @@ -116,7 +123,15 @@ public function update(Page $page, array $input): Page $this->revisionRepo->storeNewForPage($page, $summary); } - Activity::add(ActivityType::PAGE_UPDATE, $page); + if (array_key_exists('is_encrypted', $input)) { + if ($input['is_encrypted'] == true) { + Activity::add(ActivityType::PAGE_ENCRYPTED, $page); + } else if ($input['is_encrypted'] == false) { + Activity::add(ActivityType::PAGE_DECRYPTED, $page); + } + } else if (!array_key_exists('is_decrypt', $input)) { + Activity::add(ActivityType::PAGE_UPDATE, $page); + } return $page; } @@ -279,4 +294,26 @@ protected function getNewPriority(Page $page): int return (new BookContents($page->book))->getLastPriority() + 1; } + + public function encryptPageContent(array $data, Page $page) + { + if (!$page->is_encrypted) { + $content = encrypt($data['content']); + return response()->json(['content' => $content,'message' => 'Encrypted SuccessFully','success' => true]); + } else { + return response()->json(['content' => '','message' => 'Already Encrypted','success' => false]); + } + } + + public function decryptPageContent(array $data, Page $page) + { + if ($page->is_encrypted) { + if (Hash::check($data['password'], $page->password)) { + $content = decrypt($data['content']); + return response()->json(['content' => $content,'message' => 'Decrypted SuccessFully','success' => true]); + } else { + return response()->json(['contents' => [],'message' => 'Decrypt Password is Wrong','success' => false]); + } + } + } } diff --git a/app/Entities/Tools/BookContents.php b/app/Entities/Tools/BookContents.php index 7fa2134b7fa..94a5373a12a 100644 --- a/app/Entities/Tools/BookContents.php +++ b/app/Entities/Tools/BookContents.php @@ -42,6 +42,12 @@ public function getLastPriority(): int public function getTree(bool $showDrafts = false, bool $renderPages = false): Collection { $pages = $this->getPages($showDrafts, $renderPages); + + // Check For Encrypted Pages + $pages->each(function ($page) { + $page->html = $page->is_encrypted ? '

This page is encrypted

' : $page->html; + }); + $chapters = $this->book->chapters()->scopes('visible')->get(); $all = collect()->concat($pages)->concat($chapters); $chapterMap = $chapters->keyBy('id'); diff --git a/app/Entities/Tools/ExportFormatter.php b/app/Entities/Tools/ExportFormatter.php index beddfe8e6e0..b1d9a1b86cf 100644 --- a/app/Entities/Tools/ExportFormatter.php +++ b/app/Entities/Tools/ExportFormatter.php @@ -36,6 +36,7 @@ public function pageToContainedHtml(Page $page): string 'format' => 'html', 'cspContent' => $this->cspService->getCspMetaTagValue(), 'locale' => user()->getLocale(), + 'export' => true, ])->render(); return $this->containHtml($pageHtml); @@ -50,7 +51,7 @@ public function chapterToContainedHtml(Chapter $chapter): string { $pages = $chapter->getVisiblePages(); $pages->each(function ($page) { - $page->html = (new PageContent($page))->render(); + $page->html = $page->is_encrypted ? "

This page is Encrypted

" : (new PageContent($page))->render(); }); $html = view('exports.chapter', [ 'chapter' => $chapter, @@ -95,6 +96,7 @@ public function pageToPdf(Page $page): string 'format' => 'pdf', 'engine' => $this->pdfGenerator->getActiveEngine(), 'locale' => user()->getLocale(), + 'export' => true, ])->render(); return $this->htmlToPdf($html); @@ -109,7 +111,7 @@ public function chapterToPdf(Chapter $chapter): string { $pages = $chapter->getVisiblePages(); $pages->each(function ($page) { - $page->html = (new PageContent($page))->render(); + $page->html = $page->is_encrypted ? "

This page is Encrypted

" : (new PageContent($page))->render(); }); $html = view('exports.chapter', [ @@ -270,6 +272,9 @@ public function chapterToPlainText(Chapter $chapter): string $parts = []; foreach ($chapter->getVisiblePages() as $page) { + if ($page->is_encrypted) { + $page->html = "

This page is Encrypted

"; + } $parts[] = $this->pageToPlainText($page, false, true); } @@ -290,6 +295,9 @@ public function bookToPlainText(Book $book): string if ($bookChild->isA('chapter')) { $parts[] = $this->chapterToPlainText($bookChild); } else { + if ($bookChild->is_encrypted) { + $bookChild->html = "

This page is Encrypted

"; + } $parts[] = $this->pageToPlainText($bookChild, true, true); } } @@ -317,6 +325,9 @@ public function chapterToMarkdown(Chapter $chapter): string $text = '# ' . $chapter->name . "\n\n"; $text .= $chapter->description . "\n\n"; foreach ($chapter->pages as $page) { + if ($page->is_encrypted) { + $page->html = "

This page is Encrypted

"; + } $text .= $this->pageToMarkdown($page) . "\n\n"; } @@ -334,6 +345,9 @@ public function bookToMarkdown(Book $book): string if ($bookChild instanceof Chapter) { $text .= $this->chapterToMarkdown($bookChild) . "\n\n"; } else { + if ($bookChild->is_encrypted) { + $bookChild->html = "

This page is Encrypted

"; + } $text .= $this->pageToMarkdown($bookChild) . "\n\n"; } } diff --git a/app/Permissions/Models/EntityPermission.php b/app/Permissions/Models/EntityPermission.php index 1ef9c2886f5..63951a82858 100644 --- a/app/Permissions/Models/EntityPermission.php +++ b/app/Permissions/Models/EntityPermission.php @@ -18,7 +18,7 @@ */ class EntityPermission extends Model { - public const PERMISSIONS = ['view', 'create', 'update', 'delete']; + public const PERMISSIONS = ['view', 'create', 'update', 'delete', 'encrypt']; protected $fillable = ['role_id', 'view', 'create', 'update', 'delete']; public $timestamps = false; diff --git a/app/Search/SearchRunner.php b/app/Search/SearchRunner.php index 9716f8053be..116324c41d8 100644 --- a/app/Search/SearchRunner.php +++ b/app/Search/SearchRunner.php @@ -159,6 +159,9 @@ protected function buildQuery(SearchOptions $searchOpts, string $entityType): El $inputTerm = str_replace('\\', '\\\\', $exact->value); $query->where('name', 'like', '%' . $inputTerm . '%') ->orWhere($entityModelInstance->textField, 'like', '%' . $inputTerm . '%'); + if ($entityModelInstance instanceof Page) { + $query->Where('is_encrypted', '!=', 1); + } }; $exact->negated ? $entityQuery->whereNot($filter) : $entityQuery->where($filter); diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 8d8da61ec18..c72cc7ce40b 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -98,7 +98,7 @@ public function saveNew(string $imageName, string $imageData, string $type, int 'type' => $type, 'uploaded_to' => $uploadedTo, ]; - + dump($this->storage->getPublicUrl($fullPath)); if (user()->id !== 0) { $userId = user()->id; $imageDetails['created_by'] = $userId; diff --git a/database/.gitignore b/database/.gitignore old mode 100644 new mode 100755 diff --git a/database/migrations/2024_11_25_123200_add_new_permissions.php b/database/migrations/2024_11_25_123200_add_new_permissions.php new file mode 100644 index 00000000000..1d15615b24b --- /dev/null +++ b/database/migrations/2024_11_25_123200_add_new_permissions.php @@ -0,0 +1,42 @@ +where('display_name', '=', 'admin')->first()->id; + + // Create & attach new entity permissions + $ops = ['Encrypt All','Encrypt Own']; + foreach ($ops as $op) { + $permissionId = DB::table('role_permissions')->insertGetId([ + 'name' => strtolower('Page') . '-' . strtolower(str_replace(' ', '-', $op)), + 'display_name' => $op . ' ' . 'Page' . 's', + 'created_at' => Carbon::now()->toDateTimeString(), + 'updated_at' => Carbon::now()->toDateTimeString(), + ]); + DB::table('permission_role')->insert([ + 'role_id' => $adminRoleId, + 'permission_id' => $permissionId, + ]); + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // + } +}; diff --git a/database/migrations/2024_11_27_080138_add_is_encrypted_column_in_pages.php b/database/migrations/2024_11_27_080138_add_is_encrypted_column_in_pages.php new file mode 100755 index 00000000000..ce5ba932491 --- /dev/null +++ b/database/migrations/2024_11_27_080138_add_is_encrypted_column_in_pages.php @@ -0,0 +1,29 @@ +boolean('is_encrypted')->after('priority')->default(false); + $table->text('decrypt_password')->after('is_encrypted'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('pages', function (Blueprint $table) { + // + }); + } +}; diff --git a/database/migrations/2024_12_03_062042_add_encrypt_column_in_entity_permissions.php b/database/migrations/2024_12_03_062042_add_encrypt_column_in_entity_permissions.php new file mode 100755 index 00000000000..7ecaae1f617 --- /dev/null +++ b/database/migrations/2024_12_03_062042_add_encrypt_column_in_entity_permissions.php @@ -0,0 +1,28 @@ +boolean('encrypt'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('entity_permissions', function (Blueprint $table) { + $table->removeColumn('encrypt'); + }); + } +}; diff --git a/database/migrations/2024_12_04_130801_rename_decrypt_password_to_password_in_pages_table.php b/database/migrations/2024_12_04_130801_rename_decrypt_password_to_password_in_pages_table.php new file mode 100755 index 00000000000..18985df298c --- /dev/null +++ b/database/migrations/2024_12_04_130801_rename_decrypt_password_to_password_in_pages_table.php @@ -0,0 +1,28 @@ +renameColumn('decrypt_password', 'password'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('pages', function (Blueprint $table) { + // + }); + } +}; diff --git a/lang/ar/common.php b/lang/ar/common.php index 454b36a9448..e27ccefcf73 100644 --- a/lang/ar/common.php +++ b/lang/ar/common.php @@ -53,6 +53,10 @@ 'download' => 'تنزيل', 'open_in_tab' => 'فتح في علامة تبويب', 'open' => 'فتح', + 'encrypt' => 'تشفير', + 'encrypt_desc' => 'أدخل كلمة مرور للتشفير وتذكرها لعرض المحتوى أو فك تشفيره.', + 'decrypt' => 'فك التشفير', + 'decrypt_desc' => 'أدخل كلمة مرور لفك التشفير.', // Sort Options 'sort_options' => 'خيارات الفرز', diff --git a/lang/bg/common.php b/lang/bg/common.php index 30298e63941..ee2bff917df 100644 --- a/lang/bg/common.php +++ b/lang/bg/common.php @@ -53,6 +53,11 @@ 'download' => 'Изтегляне', 'open_in_tab' => 'Отваряне в раздел', 'open' => 'Open', + 'encrypt' => 'Криптиране', + 'encrypt_desc' => 'Въведете парола за криптиране и я запомнете, за да видите или декриптирате съдържанието.', + 'decrypt' => 'Декриптиране', + 'decrypt_desc' => 'Въведете парола за декриптиране.', + // Sort Options 'sort_options' => 'Опции за сортиране', diff --git a/lang/bs/common.php b/lang/bs/common.php index 4e4631a0d9d..d09e1402d1c 100644 --- a/lang/bs/common.php +++ b/lang/bs/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Šifriranje', + 'encrypt_desc' => 'Unesite lozinku za šifriranje i zapamtite je kako biste vidjeli ili dešifrirali sadržaj.', + 'decrypt' => 'Dešifriranje', + 'decrypt_desc' => 'Unesite lozinku za dešifriranje.', // Sort Options 'sort_options' => 'Opcije sortiranja', diff --git a/lang/ca/common.php b/lang/ca/common.php index f4ad19230b7..3dad554b623 100644 --- a/lang/ca/common.php +++ b/lang/ca/common.php @@ -53,6 +53,10 @@ 'download' => 'Baixa', 'open_in_tab' => 'Obre en una pestanya', 'open' => 'Obre', + 'encrypt' => 'Encriptar', + 'encrypt_desc' => 'Introduïu una contrasenya per a l’encriptació i recordeu-la per veure o desencriptar el contingut.', + 'decrypt' => 'Desencriptar', + 'decrypt_desc' => 'Introduïu una contrasenya per desencriptar.', // Sort Options 'sort_options' => 'Opcions d’ordenació', diff --git a/lang/cs/common.php b/lang/cs/common.php index 1e20b17e7dc..5c600276297 100644 --- a/lang/cs/common.php +++ b/lang/cs/common.php @@ -53,6 +53,11 @@ 'download' => 'Stáhnout', 'open_in_tab' => 'Otevřít v nové záložce', 'open' => 'Otevřít', + 'encrypt' => 'Šifrovat', + 'encrypt_desc' => 'Zadejte heslo pro šifrování a zapamatujte si ho pro zobrazení nebo dešifrování obsahu.', + 'decrypt' => 'Dešifrovat', + 'decrypt_desc' => 'Zadejte heslo pro dešifrování.', + // Sort Options 'sort_options' => 'Možnosti řazení', diff --git a/lang/cy/common.php b/lang/cy/common.php index c8c770b7118..15aa25c441b 100644 --- a/lang/cy/common.php +++ b/lang/cy/common.php @@ -53,6 +53,10 @@ 'download' => 'Llwytho i lawr', 'open_in_tab' => 'Agor mewn Tab', 'open' => 'Agor', + 'encrypt' => 'Amgryptio', + 'encrypt_desc' => 'Rhowch gyfrinair i amgryptio a’i gofio i weld neu ddatgryptio’r cynnwys.', + 'decrypt' => 'Dadgryptio', + 'decrypt_desc' => 'Rhowch gyfrinair i ddatgryptio.', // Sort Options 'sort_options' => 'Trefnu\'r opsiynau', diff --git a/lang/da/common.php b/lang/da/common.php index 75060b28b3f..e15b9e67bc1 100644 --- a/lang/da/common.php +++ b/lang/da/common.php @@ -53,6 +53,10 @@ 'download' => 'Hent', 'open_in_tab' => 'Åben i ny fane', 'open' => 'Åbn', + 'encrypt' => 'Krypter', + 'encrypt_desc' => 'Indtast en adgangskode til kryptering, og husk den for at se eller dekryptere indholdet.', + 'decrypt' => 'Dekrypter', + 'decrypt_desc' => 'Indtast en adgangskode til dekryptering.', // Sort Options 'sort_options' => 'Sorteringsindstillinger', diff --git a/lang/de/common.php b/lang/de/common.php index 8ff91da0a25..458aa0d07b1 100644 --- a/lang/de/common.php +++ b/lang/de/common.php @@ -53,6 +53,10 @@ 'download' => 'Herunterladen', 'open_in_tab' => 'In neuem Tab öffnen', 'open' => 'Öffnen', + 'encrypt' => 'Verschlüsseln', + 'encrypt_desc' => 'Geben Sie ein Passwort zur Verschlüsselung ein und merken Sie es sich, um den Inhalt anzuzeigen oder zu entschlüsseln.', + 'decrypt' => 'Entschlüsseln', + 'decrypt_desc' => 'Geben Sie ein Passwort zur Entschlüsselung ein.', // Sort Options 'sort_options' => 'Sortieroptionen', diff --git a/lang/de_informal/common.php b/lang/de_informal/common.php index e033b63d22e..e4da838df79 100644 --- a/lang/de_informal/common.php +++ b/lang/de_informal/common.php @@ -53,6 +53,10 @@ 'download' => 'Herunterladen', 'open_in_tab' => 'In Tab öffnen', 'open' => 'Öffnen', + 'encrypt' => 'Verschlüsseln', + 'encrypt_desc' => 'Geben Sie ein Passwort zur Verschlüsselung ein und merken Sie es sich, um den Inhalt anzuzeigen oder zu entschlüsseln.', + 'decrypt' => 'Entschlüsseln', + 'decrypt_desc' => 'Geben Sie ein Passwort zur Entschlüsselung ein.', // Sort Options 'sort_options' => 'Sortieroptionen', diff --git a/lang/el/common.php b/lang/el/common.php index d1b6bd9f790..c0319815c37 100644 --- a/lang/el/common.php +++ b/lang/el/common.php @@ -53,6 +53,10 @@ 'download' => 'Λήψη', 'open_in_tab' => 'Άνοιγμα σε Καρτέλα', 'open' => 'Open', + 'encrypt' => 'Κρυπτογράφηση', + 'encrypt_desc' => 'Εισαγάγετε έναν κωδικό πρόσβασης για κρυπτογράφηση και θυμηθείτε τον για να δείτε ή να αποκρυπτογραφήσετε το περιεχόμενο.', + 'decrypt' => 'Αποκρυπτογράφηση', + 'decrypt_desc' => 'Εισαγάγετε έναν κωδικό πρόσβασης για αποκρυπτογράφηση.', // Sort Options 'sort_options' => 'Επιλογές ταξινόμησης', diff --git a/lang/en/activities.php b/lang/en/activities.php index 092398ef0e1..7813e6b159a 100644 --- a/lang/en/activities.php +++ b/lang/en/activities.php @@ -16,6 +16,10 @@ 'page_restore_notification' => 'Page successfully restored', 'page_move' => 'moved page', 'page_move_notification' => 'Page successfully moved', + 'page_encrypted' => 'page encrypted', + 'page_encrypted_notification' => 'Page successfully encrypted', + 'page_decrypted' => 'page decrypted', + 'page_decrypted_notification' => 'Page successfully decrypted', // Chapters 'chapter_create' => 'created chapter', diff --git a/lang/en/common.php b/lang/en/common.php index b05169bb2c4..92128866c86 100644 --- a/lang/en/common.php +++ b/lang/en/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Encrypt', + 'encrypt_desc' => 'Enter a password for encryption and remember it to view or decrypt the content', + 'decrypt' => 'Decrypt', + 'decrypt_desc' => 'Enter a Password For Decryption', // Sort Options 'sort_options' => 'Sort Options', diff --git a/lang/es/common.php b/lang/es/common.php index 14eee82d97c..232dcd5c0ff 100644 --- a/lang/es/common.php +++ b/lang/es/common.php @@ -53,6 +53,10 @@ 'download' => 'Descargar', 'open_in_tab' => 'Abrir en una nueva pestaña', 'open' => 'Abrir', + 'encrypt' => 'Encriptar', + 'encrypt_desc' => 'Ingrese una contraseña para la encriptación y recuérdela para ver o desencriptar el contenido.', + 'decrypt' => 'Desencriptar', + 'decrypt_desc' => 'Ingrese una contraseña para desencriptar.', // Sort Options 'sort_options' => 'Opciones de ordenación', diff --git a/lang/es_AR/common.php b/lang/es_AR/common.php index ebac11119d3..4d3a6364590 100644 --- a/lang/es_AR/common.php +++ b/lang/es_AR/common.php @@ -53,6 +53,10 @@ 'download' => 'Descargar', 'open_in_tab' => 'Abrir en una pestaña', 'open' => 'Abrir', + 'encrypt' => 'Encriptar', + 'encrypt_desc' => 'Ingrese una contraseña para encriptar y recuérdela para ver o desencriptar el contenido.', + 'decrypt' => 'Desencriptar', + 'decrypt_desc' => 'Ingrese una contraseña para desencriptar.', // Sort Options 'sort_options' => 'Opciones de Orden', diff --git a/lang/et/common.php b/lang/et/common.php index a53060a00e6..d8c44990f18 100644 --- a/lang/et/common.php +++ b/lang/et/common.php @@ -53,6 +53,10 @@ 'download' => 'Laadi alla', 'open_in_tab' => 'Ava vahelehel', 'open' => 'Ava', + 'encrypt' => 'Krüpteeri', + 'encrypt_desc' => 'Sisestage krüpteerimiseks parool ja jätke see meelde, et sisu vaadata või dekrüpteerida.', + 'decrypt' => 'Dekrüpteeri', + 'decrypt_desc' => 'Sisestage parool dekrüpteerimiseks.', // Sort Options 'sort_options' => 'Sorteerimise valikud', diff --git a/lang/eu/common.php b/lang/eu/common.php index 35a67b349ab..4bdc3f5c237 100644 --- a/lang/eu/common.php +++ b/lang/eu/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Zifratzea', + 'encrypt_desc' => 'Sartu zifratze pasahitza eta gorde edukia ikusteko edo deszifratzeko.', + 'decrypt' => 'Deszifratu', + 'decrypt_desc' => 'Sartu deszifratzeko pasahitza.', // Sort Options 'sort_options' => 'Ordenatzeko aukerak', diff --git a/lang/fa/common.php b/lang/fa/common.php index 765c1e6271d..d5e5ba435df 100644 --- a/lang/fa/common.php +++ b/lang/fa/common.php @@ -53,6 +53,10 @@ 'download' => 'دانلود', 'open_in_tab' => 'باز کردن در تب جدید', 'open' => 'بازکردن', + 'encrypt' => 'رمزگذاری', + 'encrypt_desc' => 'یک رمز عبور برای رمزگذاری وارد کنید و آن را برای مشاهده یا رمزگشایی محتوا به خاطر بسپارید.', + 'decrypt' => 'رمزگشایی', + 'decrypt_desc' => 'یک رمز عبور برای رمزگشایی وارد کنید.', // Sort Options 'sort_options' => 'گزینه‌های مرتب سازی', diff --git a/lang/fi/common.php b/lang/fi/common.php index d6efe8e0347..168d44efbb5 100644 --- a/lang/fi/common.php +++ b/lang/fi/common.php @@ -53,6 +53,10 @@ 'download' => 'Lataa', 'open_in_tab' => 'Avaa välilehdessä', 'open' => 'Avaa', + 'encrypt' => 'Salaus', + 'encrypt_desc' => 'Anna salaus salasana ja muista se nähdäksesi tai purkaaksesi sisällön salauksen.', + 'decrypt' => 'Pura salaus', + 'decrypt_desc' => 'Anna salauksen purkamisen salasana.', // Sort Options 'sort_options' => 'Järjestyksen asetukset', diff --git a/lang/fr/common.php b/lang/fr/common.php index 282a72e4569..e5afd555f96 100644 --- a/lang/fr/common.php +++ b/lang/fr/common.php @@ -53,6 +53,10 @@ 'download' => 'Télécharger', 'open_in_tab' => 'Ouvrir dans un onglet', 'open' => 'Ouvert', + 'encrypt' => 'Crypter', + 'encrypt_desc' => 'Entrez un mot de passe pour le cryptage et mémorisez-le pour afficher ou décrypter le contenu.', + 'decrypt' => 'Décrypter', + 'decrypt_desc' => 'Entrez un mot de passe pour décrypter.', // Sort Options 'sort_options' => 'Options de tri', diff --git a/lang/he/common.php b/lang/he/common.php index a427df954fe..c469fe43545 100644 --- a/lang/he/common.php +++ b/lang/he/common.php @@ -53,6 +53,10 @@ 'download' => 'הורדה', 'open_in_tab' => 'פתח בכרטיסייה חדשה', 'open' => 'Open', + 'encrypt' => 'הצפנה', + 'encrypt_desc' => 'הזן סיסמה להצפנה וזכור אותה כדי לצפות או לפענח את התוכן.', + 'decrypt' => 'פענוח', + 'decrypt_desc' => 'הזן סיסמה לפענוח.', // Sort Options 'sort_options' => 'אפשרויות מיון', diff --git a/lang/hr/common.php b/lang/hr/common.php index 3c9ed610bc6..992ae209c9e 100644 --- a/lang/hr/common.php +++ b/lang/hr/common.php @@ -53,6 +53,10 @@ 'download' => 'Preuzmi', 'open_in_tab' => 'Otvori u Kartici', 'open' => 'Open', + 'encrypt' => 'Šifriraj', + 'encrypt_desc' => 'Unesite lozinku za šifriranje i zapamtite je kako biste mogli pregledati ili dešifrirati sadržaj.', + 'decrypt' => 'Dešifriraj', + 'decrypt_desc' => 'Unesite lozinku za dešifriranje.', // Sort Options 'sort_options' => 'Razvrstaj opcije', diff --git a/lang/hu/common.php b/lang/hu/common.php index 29a87e19edf..11ace29d362 100644 --- a/lang/hu/common.php +++ b/lang/hu/common.php @@ -53,6 +53,10 @@ 'download' => 'Letöltés', 'open_in_tab' => 'Megnyitás új tab-on', 'open' => 'Megnyitás', + 'encrypt' => 'Titkosítás', + 'encrypt_desc' => 'Adjon meg egy jelszót a titkosításhoz, és jegyezze meg, hogy megtekinthesse vagy visszafejthesse a tartalmat.', + 'decrypt' => 'Dekódolás', + 'decrypt_desc' => 'Adjon meg egy jelszót a dekódoláshoz.', // Sort Options 'sort_options' => 'Rendezési beállítások', diff --git a/lang/id/common.php b/lang/id/common.php index 06e9421c87b..a9876aaaf11 100644 --- a/lang/id/common.php +++ b/lang/id/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Enkripsi', + 'encrypt_desc' => 'Masukkan kata sandi untuk enkripsi dan ingat untuk melihat atau mendekripsi konten.', + 'decrypt' => 'Dekripsi', + 'decrypt_desc' => 'Masukkan kata sandi untuk dekripsi.', // Sort Options 'sort_options' => 'Opsi Sortir', diff --git a/lang/it/common.php b/lang/it/common.php index 113ddb01405..d1a67d44afe 100644 --- a/lang/it/common.php +++ b/lang/it/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Apri nella scheda', 'open' => 'Apri', + 'encrypt' => 'Criptare', + 'encrypt_desc' => 'Inserisci una password per la crittografia e ricordala per visualizzare o decriptare il contenuto.', + 'decrypt' => 'Decriptare', + 'decrypt_desc' => 'Inserisci una password per decriptare.', // Sort Options 'sort_options' => 'Opzioni Ordinamento', diff --git a/lang/ja/common.php b/lang/ja/common.php index 097974d8e96..a0b3398d7fe 100644 --- a/lang/ja/common.php +++ b/lang/ja/common.php @@ -53,6 +53,10 @@ 'download' => 'ダウンロード', 'open_in_tab' => 'タブで開く', 'open' => '開く', + 'encrypt' => '暗号化', + 'encrypt_desc' => '暗号化のためのパスワードを入力し、それを覚えておいてコンテンツを表示または復号してください。', + 'decrypt' => '復号化', + 'decrypt_desc' => '復号化するためのパスワードを入力してください。', // Sort Options 'sort_options' => '並べ替えオプション', diff --git a/lang/ko/common.php b/lang/ko/common.php index 246a3aebc36..ac114be79d7 100644 --- a/lang/ko/common.php +++ b/lang/ko/common.php @@ -53,6 +53,10 @@ 'download' => '내려받기', 'open_in_tab' => '탭에서 열기', 'open' => '열기 ', + 'encrypt' => '암호화', + 'encrypt_desc' => '암호화를 위해 비밀번호를 입력하고 내용을 보거나 해독하려면 기억하세요.', + 'decrypt' => '복호화', + 'decrypt_desc' => '복호화를 위해 비밀번호를 입력하세요.', // Sort Options 'sort_options' => '정렬 기준', diff --git a/lang/lt/common.php b/lang/lt/common.php index e375c835ceb..d4a1f2ea318 100644 --- a/lang/lt/common.php +++ b/lang/lt/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Užšifruoti', + 'encrypt_desc' => 'Įveskite slaptažodį šifravimui ir prisiminkite jį, kad galėtumėte peržiūrėti arba iššifruoti turinį.', + 'decrypt' => 'Iššifruoti', + 'decrypt_desc' => 'Įveskite slaptažodį iššifravimui.', // Sort Options 'sort_options' => 'Rūšiuoti pasirinkimus', diff --git a/lang/lv/common.php b/lang/lv/common.php index 584b24cb2e7..95568b0427d 100644 --- a/lang/lv/common.php +++ b/lang/lv/common.php @@ -53,6 +53,10 @@ 'download' => 'Lejupielādēt', 'open_in_tab' => 'Atvērt cilnē', 'open' => 'Atvērt', + 'encrypt' => 'Šifrēt', + 'encrypt_desc' => 'Ievadiet paroli šifrēšanai un atcerieties to, lai skatītu vai atšifrētu saturu.', + 'decrypt' => 'Atšifrēt', + 'decrypt_desc' => 'Ievadiet paroli atšifrēšanai.', // Sort Options 'sort_options' => 'Kārtošanas Opcijas', diff --git a/lang/nb/common.php b/lang/nb/common.php index 0e9e19b6e59..33042ae670d 100644 --- a/lang/nb/common.php +++ b/lang/nb/common.php @@ -53,6 +53,10 @@ 'download' => 'Last ned', 'open_in_tab' => 'Åpne i fane', 'open' => 'Åpne', + 'encrypt' => 'Krypter', + 'encrypt_desc' => 'Skriv inn et passord for kryptering, og husk det for å se eller dekryptere innholdet.', + 'decrypt' => 'Dekrypter', + 'decrypt_desc' => 'Skriv inn et passord for dekryptering.', // Sort Options 'sort_options' => 'Sorteringsalternativer', diff --git a/lang/nl/common.php b/lang/nl/common.php index 844fe91d1af..7fa08579865 100644 --- a/lang/nl/common.php +++ b/lang/nl/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open als Tabblad', 'open' => 'Open', + 'encrypt' => 'Versleutelen', + 'encrypt_desc' => 'Voer een wachtwoord in voor versleuteling en onthoud het om de inhoud te bekijken of te ontsleutelen.', + 'decrypt' => 'Ontsleutelen', + 'decrypt_desc' => 'Voer een wachtwoord in om te ontsleutelen.', // Sort Options 'sort_options' => 'Sorteeropties', diff --git a/lang/nn/common.php b/lang/nn/common.php index 3d623dbc492..4d4d8da862b 100644 --- a/lang/nn/common.php +++ b/lang/nn/common.php @@ -53,6 +53,10 @@ 'download' => 'Last ned', 'open_in_tab' => 'Opne i fane', 'open' => 'Opne', + 'encrypt' => 'Krypter', + 'encrypt_desc' => 'Skriv inn eit passord for kryptering, og hugs det for å sjå eller dekryptere innhaldet.', + 'decrypt' => 'Dekrypter', + 'decrypt_desc' => 'Skriv inn eit passord for dekryptering.', // Sort Options 'sort_options' => 'Sorteringsalternativ', diff --git a/lang/pl/common.php b/lang/pl/common.php index 4d5a346b2b5..d3f5ed727c9 100644 --- a/lang/pl/common.php +++ b/lang/pl/common.php @@ -53,6 +53,10 @@ 'download' => 'Pobierz', 'open_in_tab' => 'Otwórz w karcie', 'open' => 'Otwórz', + 'encrypt' => 'Szyfrować', + 'encrypt_desc' => 'Wprowadź hasło do szyfrowania i zapamiętaj je, aby wyświetlić lub odszyfrować zawartość.', + 'decrypt' => 'Odszyfrować', + 'decrypt_desc' => 'Wprowadź hasło do odszyfrowania.', // Sort Options 'sort_options' => 'Opcje sortowania', diff --git a/lang/pt/common.php b/lang/pt/common.php index 3e005700245..53028f3e973 100644 --- a/lang/pt/common.php +++ b/lang/pt/common.php @@ -53,6 +53,10 @@ 'download' => 'Transferir', 'open_in_tab' => 'Abrir em novo separador', 'open' => 'Abrir', + 'encrypt' => 'Criptografar', + 'encrypt_desc' => 'Digite uma senha para criptografar e lembre-se dela para visualizar ou descriptografar o conteúdo.', + 'decrypt' => 'Descriptografar', + 'decrypt_desc' => 'Digite uma senha para descriptografar.', // Sort Options 'sort_options' => 'Opções de Ordenação', diff --git a/lang/pt_BR/common.php b/lang/pt_BR/common.php index f5e6d230d43..846c59c6661 100644 --- a/lang/pt_BR/common.php +++ b/lang/pt_BR/common.php @@ -58,6 +58,10 @@ 'download' => 'Baixar ', 'open_in_tab' => 'Abrir na aba', 'open' => 'Abrir', + 'encrypt' => 'Criptografar', + 'encrypt_desc' => 'Digite uma senha para criptografar e lembre-se dela para visualizar ou descriptografar o conteúdo.', + 'decrypt' => 'Descriptografar', + 'decrypt_desc' => 'Digite uma senha para descriptografar.', // Sort Options 'sort_options' => 'Opções de Ordenação', diff --git a/lang/ro/common.php b/lang/ro/common.php index 1de631183f6..9a7bd9172df 100644 --- a/lang/ro/common.php +++ b/lang/ro/common.php @@ -53,6 +53,10 @@ 'download' => 'Descarcă', 'open_in_tab' => 'Deschide in tab', 'open' => 'Open', + 'encrypt' => 'Criptare', + 'encrypt_desc' => 'Introduceți o parolă pentru criptare și rețineți-o pentru a vizualiza sau decripta conținutul.', + 'decrypt' => 'Decriptare', + 'decrypt_desc' => 'Introduceți o parolă pentru decriptare.', // Sort Options 'sort_options' => 'Opțiuni ordonare', diff --git a/lang/ru/common.php b/lang/ru/common.php index d3860bba461..a15eaa9425e 100644 --- a/lang/ru/common.php +++ b/lang/ru/common.php @@ -53,6 +53,10 @@ 'download' => 'Загрузить', 'open_in_tab' => 'Открыть во вкладке', 'open' => 'Открыть', + 'encrypt' => 'Шифрование', + 'encrypt_desc' => 'Введите пароль для шифрования и запомните его, чтобы просматривать или расшифровывать содержимое.', + 'decrypt' => 'Расшифровка', + 'decrypt_desc' => 'Введите пароль для расшифровки.', // Sort Options 'sort_options' => 'Параметры сортировки', diff --git a/lang/sk/common.php b/lang/sk/common.php index 12828d6c2e5..9a190aa7440 100644 --- a/lang/sk/common.php +++ b/lang/sk/common.php @@ -53,6 +53,10 @@ 'download' => 'Stiahnuť', 'open_in_tab' => 'Otvoriť na novej karte', 'open' => 'Open', + 'encrypt' => 'Šifrovať', + 'encrypt_desc' => 'Zadajte heslo na šifrovanie a zapamätajte si ho, aby ste mohli zobraziť alebo dešifrovať obsah.', + 'decrypt' => 'Dešifrovať', + 'decrypt_desc' => 'Zadajte heslo na dešifrovanie.', // Sort Options 'sort_options' => 'Možnosti triedenia', diff --git a/lang/sl/common.php b/lang/sl/common.php index 4bad22048c6..13079b101ed 100644 --- a/lang/sl/common.php +++ b/lang/sl/common.php @@ -53,6 +53,10 @@ 'download' => 'Download', 'open_in_tab' => 'Open in Tab', 'open' => 'Open', + 'encrypt' => 'Šifriraj', + 'encrypt_desc' => 'Vnesite geslo za šifriranje in si ga zapomnite, da si boste lahko ogledali ali dešifrirali vsebino.', + 'decrypt' => 'Dešifriraj', + 'decrypt_desc' => 'Vnesite geslo za dešifriranje.', // Sort Options 'sort_options' => 'Možnosti razvrščanja', diff --git a/lang/sv/common.php b/lang/sv/common.php index 8fe80899f0e..824e3df433d 100644 --- a/lang/sv/common.php +++ b/lang/sv/common.php @@ -53,6 +53,10 @@ 'download' => 'Ladda ner', 'open_in_tab' => 'Öppna i flik', 'open' => 'Öppna', + 'encrypt' => 'Kryptera', + 'encrypt_desc' => 'Ange ett lösenord för kryptering och kom ihåg det för att visa eller dekryptera innehållet.', + 'decrypt' => 'Dekryptera', + 'decrypt_desc' => 'Ange ett lösenord för dekryptering.', // Sort Options 'sort_options' => 'Sorteringsalternativ', diff --git a/lang/tr/common.php b/lang/tr/common.php index 3e416d37bfc..543937d1a1d 100644 --- a/lang/tr/common.php +++ b/lang/tr/common.php @@ -53,6 +53,10 @@ 'download' => 'İndir', 'open_in_tab' => 'Sekmede aç', 'open' => 'Open', + 'encrypt' => 'Şifrele', + 'encrypt_desc' => 'Şifreleme için bir parola girin ve içeriği görüntülemek veya şifresini çözmek için hatırlayın.', + 'decrypt' => 'Şifre Çöz', + 'decrypt_desc' => 'Şifre çözme için bir parola girin.', // Sort Options 'sort_options' => 'Sıralama Seçenekleri', diff --git a/lang/uk/common.php b/lang/uk/common.php index d384e392447..04c56cd4b75 100644 --- a/lang/uk/common.php +++ b/lang/uk/common.php @@ -53,6 +53,10 @@ 'download' => 'Завантажити', 'open_in_tab' => 'Відкрити в новій вкладці', 'open' => 'Відкрити', + 'encrypt' => 'Шифрувати', + 'encrypt_desc' => 'Введіть пароль для шифрування і запам’ятайте його, щоб переглядати або дешифрувати вміст.', + 'decrypt' => 'Розшифрувати', + 'decrypt_desc' => 'Введіть пароль для розшифрування.', // Sort Options 'sort_options' => 'Параметри сортування', diff --git a/lang/uz/common.php b/lang/uz/common.php index fcbb2ea84a8..89d81de73f7 100644 --- a/lang/uz/common.php +++ b/lang/uz/common.php @@ -53,6 +53,10 @@ 'download' => 'Yuklab olish', 'open_in_tab' => 'Tabda ochish', 'open' => 'Open', + 'encrypt' => 'Shifrlash', + 'encrypt_desc' => 'Shifrlash uchun parolni kiriting va mazmunni ko‘rish yoki shifrdan chiqarish uchun uni eslab qoling.', + 'decrypt' => 'Shifrdan chiqarish', + 'decrypt_desc' => 'Shifrdan chiqarish uchun parolni kiriting.', // Sort Options 'sort_options' => 'Saralash opsiyalari', diff --git a/lang/vi/common.php b/lang/vi/common.php index 16929a2fbae..38991ebfffa 100644 --- a/lang/vi/common.php +++ b/lang/vi/common.php @@ -53,6 +53,10 @@ 'download' => 'Tải về', 'open_in_tab' => 'Mở trong thẻ mới', 'open' => 'Open', + 'encrypt' => 'Mã hóa', + 'encrypt_desc' => 'Nhập mật khẩu để mã hóa và nhớ nó để xem hoặc giải mã nội dung.', + 'decrypt' => 'Giải mã', + 'decrypt_desc' => 'Nhập mật khẩu để giải mã.', // Sort Options 'sort_options' => 'Tùy Chọn Sắp Xếp', diff --git a/lang/zh_CN/common.php b/lang/zh_CN/common.php index bc391354e69..832621df8b6 100644 --- a/lang/zh_CN/common.php +++ b/lang/zh_CN/common.php @@ -53,6 +53,10 @@ 'download' => '下载', 'open_in_tab' => '在标签页中打开。', 'open' => '打开', + 'encrypt' => '加密', + 'encrypt_desc' => '输入密码进行加密,并记住它以查看或解密内容。', + 'decrypt' => '解密', + 'decrypt_desc' => '输入密码进行解密。', // Sort Options 'sort_options' => '排序选项', diff --git a/lang/zh_TW/common.php b/lang/zh_TW/common.php index 8b003a7303b..c67b07b8ea9 100644 --- a/lang/zh_TW/common.php +++ b/lang/zh_TW/common.php @@ -53,6 +53,10 @@ 'download' => '下載', 'open_in_tab' => '在新分頁中開啟', 'open' => '開啟', + 'encrypt' => '加密', + 'encrypt_desc' => '輸入密碼進行加密,並記住它以檢視或解密內容。', + 'decrypt' => '解密', + 'decrypt_desc' => '輸入密碼進行解密。', // Sort Options 'sort_options' => '排序選項', diff --git a/resources/icons/encrypt.svg b/resources/icons/encrypt.svg new file mode 100644 index 00000000000..93c1ff71d93 --- /dev/null +++ b/resources/icons/encrypt.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/icons/shield-lock.svg b/resources/icons/shield-lock.svg new file mode 100644 index 00000000000..c425c68711e --- /dev/null +++ b/resources/icons/shield-lock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/icons/shield-unlock.svg b/resources/icons/shield-unlock.svg new file mode 100644 index 00000000000..954293cfe76 --- /dev/null +++ b/resources/icons/shield-unlock.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/icons/unlock.svg b/resources/icons/unlock.svg new file mode 100644 index 00000000000..3233f3a9e47 --- /dev/null +++ b/resources/icons/unlock.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/js/components/custom-checkbox.js b/resources/js/components/custom-checkbox.js index a5f1d566424..0d732dd895a 100644 --- a/resources/js/components/custom-checkbox.js +++ b/resources/js/components/custom-checkbox.js @@ -27,6 +27,7 @@ export class CustomCheckbox extends Component { stateChange() { const checked = this.checkbox.checked ? 'true' : 'false'; + this.checkbox.value = this.checkbox.checked ? 'true' : 'false'; this.display.setAttribute('aria-checked', checked); } diff --git a/resources/js/components/encrypt-decrypt-manager.js b/resources/js/components/encrypt-decrypt-manager.js new file mode 100644 index 00000000000..5de19858259 --- /dev/null +++ b/resources/js/components/encrypt-decrypt-manager.js @@ -0,0 +1,215 @@ +import {Component} from './component'; + +export class EncryptDecryptManager extends Component { + + setup() { + this.container = this.$el; + this.encryptBtn = this.$refs.encryptBtn; + this.decryptSubmitBtn = this.$refs.decryptSubmitBtn; + this.decryptPassword = this.$refs.decryptPasswordInput; + this.editBtn = this.$refs.editBtn; + this.invalidMsg = this.$refs.invalidPassword; + this.exportMenu = this.$refs.exportMenu; + + this.url = this.$opts.url; + this.pageName = this.$opts.pageName; + this.pageIsEncrypted = this.$opts.pageEncrypted; + + this.encryptDialog = document.querySelector('.encrypt-decrypt-dialog'); + this.contentPart = document.querySelector('.page-content'); + this.pageDetailContent = document.querySelector('.page-content').querySelector('.page-detail-content'); + this.encryptInfo = document.querySelector('.page-content').querySelector('.encrypt-message'); + + this.invalidPassword = this.encryptDialog.querySelector('.invalid-password'); + this.passwordInput = this.encryptDialog.querySelector('#page-encrypt-password'); + + this.is_decrypt = false; + + this.setupListener(); + } + + setupListener() { + this.encryptBtn.addEventListener('click', async event => { + event.preventDefault(); + const response = await this.openDialog(); + if (response) { + // eslint-disable-next-line radix + if (parseInt(this.pageIsEncrypted) === 1) { + this.decryptContent(this.passwordInput.value, true, false); + } else { + this.encryptContent(); + } + } + }); + + // eslint-disable-next-line radix + if (parseInt(this.pageIsEncrypted) === 1) { + this.contentPart.addEventListener('mousedown', event => event.preventDefault()); + this.contentPart.addEventListener('selectstart', event => event.preventDefault()); + this.contentPart.addEventListener('copy', event => event.preventDefault()); + this.decryptPassword.addEventListener('input', () => { this.invalidMsg.classList.add('hidden'); }); + this.decryptSubmitBtn.addEventListener('click', () => this.decryptContent(this.decryptPassword.value)); + this.editBtn.addEventListener('click', event => this.decryptContentOnEdit(event)); + this.decryptPassword.addEventListener('keydown', event => { + if (event.key === 'Enter') { + this.decryptContent(this.decryptPassword.value); + } + }); + this.passwordInput.addEventListener('input', () => { + this.invalidPassword.classList.add('hidden'); + }); + + this.exportMenu.querySelectorAll('a').forEach(anchor => { + anchor.addEventListener('click', event => this.decryptForExport(event, anchor)); + }); + } + } + + encryptContent() { + const decryptPassword = this.passwordInput.value; + if (decryptPassword.length > 6) { + const contents = this.pageDetailContent.innerHTML; + + window.$http.post(`${this.url}/encrypt`, {content: contents}).then(resp => { + if (resp.data.success) { + const data = { + html: resp.data.content, + is_encrypted: true, + password: decryptPassword, + }; + this.updateData(data, true, false); + } + }); + } + } + + async decryptContent(decryptPassword, updateDecryption = false) { + if (decryptPassword.length > 6) { + if (this.is_decrypt && updateDecryption) { + const decryptData = { + html: this.pageDetailContent.innerHTML, + is_encrypted: false, + password: decryptPassword, + }; + this.updateData(decryptData, false, false); + } else { + const decryptData = { + content: this.pageDetailContent.innerHTML, + password: decryptPassword, + }; + window.$http.post(`${this.url}/decrypt`, decryptData).then(async resp => { + if (resp.data.success) { + this.decryptPassword.value = ''; + + if (updateDecryption) { + const data = { + html: resp.data.content, + is_encrypted: false, + password: decryptPassword, + }; + this.updateData(data, false, false); + } else { + this.pageDetailContent.innerHTML = resp.data.content; + this.is_decrypt = true; + this.encryptInfo.classList.add('hidden'); + } + } else if (updateDecryption) { + this.invalidPassword.innerHTML = resp.data.message; + this.invalidPassword.classList.remove('hidden'); + const response = await this.openDialog(); + if (response) { + this.decryptContent(this.passwordInput.value, updateDecryption); + } + } else { + this.invalidMsg.innerHTML = resp.data.message; + this.invalidMsg.classList.remove('hidden'); + } + }); + } + } else if (updateDecryption) { + this.invalidPassword.innerHTML = 'Password Length Should be More Than 6'; + this.invalidPassword.classList.remove('hidden'); + const response = await this.openDialog(); + if (response) { + this.decryptContent(this.passwordInput.value, updateDecryption); + } + } else { + this.invalidMsg.innerHTML = 'Password Length Should be More Than 6'; + this.invalidMsg.classList.remove('hidden'); + } + } + + async openDialog() { + this.encryptDialog.querySelector('#page-encrypt-password').value = ''; + const dialog = window.$components.firstOnElement(this.encryptDialog, 'confirm-dialog'); + const response = await dialog.show(); + return response; + } + + async decryptContentOnEdit(event) { + event.preventDefault(); + const response = await this.openDialog(); + if (response) { + const decryptPassword = this.encryptDialog.querySelector('#page-encrypt-password').value; + + const data = { + is_decrypt: 'FOR_EDIT', + password: decryptPassword, + }; + + this.updateData(data, false, true, this.editBtn.getAttribute('href')); + } + } + + async updateData(data, updateEncryption, tmpDecrypt = false, link = this.url) { + try { + if (updateEncryption) { + window.$http.put(`${this.url}/update-encryption`, data).then(resp => { + if (resp.data.success) { + window.location.reload(); + } + }); + } else { + window.$http.put(`${this.url}/update-decryption`, data).then(resp => { + if (resp.data.success) { + if (tmpDecrypt) { + window.location.href = link; + } else { + window.location.reload(); + } + } else { + this.invalidMsg.value = resp.data.message; + this.invalidMsg.classList.remove('hidden'); + } + }); + } + } catch (error) { + console.error(error); + } + } + + async decryptForExport(event, element) { + event.preventDefault(); + const link = element.getAttribute('href'); + const response = await this.openDialog(); + if (response) { + const decryptPassword = this.encryptDialog.querySelector('#page-encrypt-password').value; + + window.$http.post(`${this.url}/validate-password`, {password: decryptPassword}).then(async resp => { + if (resp.data.success) { + const data = { + is_decrypt: 'FOR_EXPORT', + password: decryptPassword, + }; + + this.updateData(data, false, true, link); + } else { + this.invalidPassword.innerHTML = 'Invalid Password'; + this.invalidPassword.classList.remove('hidden'); + this.decryptForExport(event, element); + } + }); + } + } + +} diff --git a/resources/js/components/index.js b/resources/js/components/index.js index 8ad5e14cb2e..2d12ebb052e 100644 --- a/resources/js/components/index.js +++ b/resources/js/components/index.js @@ -19,6 +19,7 @@ export {Dropdown} from './dropdown'; export {DropdownSearch} from './dropdown-search'; export {Dropzone} from './dropzone'; export {EditorToolbox} from './editor-toolbox'; +export {EncryptDecryptManager} from './encrypt-decrypt-manager'; export {EntityPermissions} from './entity-permissions'; export {EntitySearch} from './entity-search'; export {EntitySelector} from './entity-selector'; diff --git a/resources/sass/styles.scss b/resources/sass/styles.scss index 636367e3aeb..a95e6ab69b7 100644 --- a/resources/sass/styles.scss +++ b/resources/sass/styles.scss @@ -230,4 +230,8 @@ $loadingSize: 10px; transform: rotate(180deg); } } +} + +.permission-asset-table{ + overflow-y: auto; } \ No newline at end of file diff --git a/resources/views/common/confirm-dialog.blade.php b/resources/views/common/confirm-dialog.blade.php index 736a1c49b7d..7fa4d0601b6 100644 --- a/resources/views/common/confirm-dialog.blade.php +++ b/resources/views/common/confirm-dialog.blade.php @@ -1,7 +1,7 @@