✨ Ajoute la vérification de la passphrase avant affichage
This commit is contained in:
		| @@ -32,6 +32,10 @@ class AuthenticatedSessionController extends Controller | ||||
|  | ||||
|         $request->session()->regenerate(); | ||||
|  | ||||
|         if (empty(Auth::user()->checkword)) { | ||||
|             return redirect(route('user.first')); | ||||
|         } | ||||
|  | ||||
|         return redirect()->intended(route('pages.index')); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| namespace App\Http\Controllers; | ||||
|  | ||||
| use DateTime; | ||||
| use http\Env\Response; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
| @@ -42,8 +41,11 @@ class PageController extends Controller | ||||
|             } | ||||
|         }, Storage::disk('pages')->files(Auth::user()->getAuthIdentifier())); | ||||
|  | ||||
|         $user = Auth::user(); | ||||
|  | ||||
|         return view('pages.index', [ | ||||
|             'pages' => $pages, | ||||
|             'checkword' => $user->checkword, | ||||
|             'pages'     => $pages, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										25
									
								
								app/Http/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Http/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Controllers; | ||||
|  | ||||
| use App\Http\Requests\User\WordCheckRequest; | ||||
| use App\Models\User; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
|  | ||||
| class UserController extends Controller | ||||
| { | ||||
|     public function first() | ||||
|     { | ||||
|         return view('user.first'); | ||||
|     } | ||||
|  | ||||
|     public function storeFirst(WordCheckRequest $request) | ||||
|     { | ||||
|         $validated = $request->validated(); | ||||
|         $user = User::where('id', Auth::user()->getAuthIdentifier())->firstOrFail(); | ||||
|         $user->checkword = $validated['checkword']; | ||||
|         $user->save(); | ||||
|  | ||||
|         return response()->json(['success' => true]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								app/Http/Requests/User/WordCheckRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								app/Http/Requests/User/WordCheckRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace App\Http\Requests\User; | ||||
|  | ||||
| use Illuminate\Foundation\Http\FormRequest; | ||||
|  | ||||
| class WordCheckRequest extends FormRequest | ||||
| { | ||||
|     /** | ||||
|      * Determine if the user is authorized to make this request. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize() | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the validation rules that apply to the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         return [ | ||||
|             'checkword' => ['required', 'string'], | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								database/migrations/2022_02_24_154221_add_user_checkword.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								database/migrations/2022_02_24_154221_add_user_checkword.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| use Illuminate\Database\Migrations\Migration; | ||||
| use Illuminate\Database\Schema\Blueprint; | ||||
| use Illuminate\Support\Facades\Schema; | ||||
|  | ||||
| return new class extends Migration | ||||
| { | ||||
|     /** | ||||
|      * Run the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function up() | ||||
|     { | ||||
|         Schema::table('users', function (Blueprint $table) { | ||||
|             $table->string('checkword')->nullable(true); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reverse the migrations. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function down() | ||||
|     { | ||||
|         Schema::table('users', function (Blueprint $table) { | ||||
|             $table->dropColumn('checkword'); | ||||
|         }); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										3
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								public/css/app.css
									
									
									
									
										vendored
									
									
								
							| @@ -12081,6 +12081,9 @@ select { | ||||
| .justify-between { | ||||
|   justify-content: space-between; | ||||
| } | ||||
| .justify-items-center { | ||||
|   justify-items: center; | ||||
| } | ||||
| .space-x-8 > :not([hidden]) ~ :not([hidden]) { | ||||
|   --tw-space-x-reverse: 0; | ||||
|   margin-right: calc(2rem * var(--tw-space-x-reverse)); | ||||
|   | ||||
							
								
								
									
										271
									
								
								public/js/app.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										271
									
								
								public/js/app.js
									
									
									
									
										vendored
									
									
								
							| @@ -29637,7 +29637,9 @@ __webpack_require__(/*! ./bootstrap */ "./resources/js/bootstrap.js"); | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| __webpack_require__(/*! ./components/pages/App.tsx */ "./resources/js/components/pages/App.tsx"); | ||||
| __webpack_require__(/*! ./components/pages/App */ "./resources/js/components/pages/App.tsx"); | ||||
| 
 | ||||
| __webpack_require__(/*! ./components/user/First */ "./resources/js/components/user/First.tsx"); | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| @@ -29657,7 +29659,9 @@ __webpack_require__.r(__webpack_exports__); | ||||
| /* harmony import */ var _List__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./List */ "./resources/js/components/pages/List.tsx"); | ||||
| /* harmony import */ var _Prompt__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Prompt */ "./resources/js/components/pages/Prompt.tsx"); | ||||
| /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); | ||||
| /* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/Divider/Divider.js"); | ||||
| /* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/Divider/Divider.js"); | ||||
| /* harmony import */ var storage_encryption__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! storage-encryption */ "./node_modules/storage-encryption/build/index.js"); | ||||
| /* harmony import */ var storage_encryption__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(storage_encryption__WEBPACK_IMPORTED_MODULE_5__); | ||||
| function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } | ||||
| 
 | ||||
| function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } | ||||
| @@ -29677,13 +29681,16 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| var app = document.getElementById('app'); | ||||
| var word = "shikiryu"; | ||||
| var sessionPassphrase = sessionStorage.getItem("key"); | ||||
| var pages = []; | ||||
| var getPageContentUrl = ""; | ||||
| var postUrl = ""; | ||||
| var removeUrl = ""; | ||||
| var csrf = ""; | ||||
| var getPageContentUrl, | ||||
|     postUrl, | ||||
|     removeUrl, | ||||
|     checkword, | ||||
|     csrf = ""; | ||||
| 
 | ||||
| if (app) { | ||||
|   getPageContentUrl = "" + app.getAttribute('data-url'); | ||||
| @@ -29691,6 +29698,7 @@ if (app) { | ||||
|   postUrl = "" + app.getAttribute('data-post'); | ||||
|   removeUrl = "" + app.getAttribute('data-remove'); | ||||
|   csrf = "" + app.getAttribute('data-csrf'); | ||||
|   checkword = "" + app.getAttribute('data-checkword'); | ||||
|   react_dom__WEBPACK_IMPORTED_MODULE_0__.render( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(App, null), app); | ||||
| } | ||||
| 
 | ||||
| @@ -29705,28 +29713,70 @@ function App() { | ||||
|       passphrase = _useState4[0], | ||||
|       setPassphrase = _useState4[1]; | ||||
| 
 | ||||
|   return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|     className: "container" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|     className: "row justify-content-center" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|     className: "col-md-8" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_Prompt__WEBPACK_IMPORTED_MODULE_3__["default"], { | ||||
|     open: passphrase === null, | ||||
|     setOpen: setPassphrase | ||||
|   }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_List__WEBPACK_IMPORTED_MODULE_2__["default"], { | ||||
|     pages: listPages, | ||||
|     url: getPageContentUrl, | ||||
|     passphrase: passphrase, | ||||
|     setPassphrase: setPassphrase, | ||||
|     csrf: csrf, | ||||
|     removeUrl: removeUrl | ||||
|   }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_Form__WEBPACK_IMPORTED_MODULE_1__["default"], { | ||||
|     setListPages: setListPages, | ||||
|     csrf: csrf, | ||||
|     url: postUrl, | ||||
|     passphrase: passphrase | ||||
|   }))))); | ||||
|   var updatePassphrase = function updatePassphrase(newPassphrase) { | ||||
|     setPassphrase(newPassphrase); | ||||
|     return result(checkPassphrase()); | ||||
|   }; | ||||
| 
 | ||||
|   var checkPassphrase = function checkPassphrase() { | ||||
|     if (checkword === "" || checkword === null || checkword === "null") { | ||||
|       console.error("checkword is empty !"); // return (<Redirect to="/first" />);
 | ||||
| 
 | ||||
|       return false; // TODO redirect to first
 | ||||
|     } | ||||
| 
 | ||||
|     localStorage.setItem("checkword", checkword); | ||||
|     var key = "" + sessionStorage.getItem("key"); | ||||
| 
 | ||||
|     if (key === "" || key === null || key === "null") { | ||||
|       console.error("key is empty 🤔 !"); // return (<Redirect to="/first" />);
 | ||||
| 
 | ||||
|       return false; // TODO redirect to first ?
 | ||||
|     } | ||||
| 
 | ||||
|     var encryptStorage = new storage_encryption__WEBPACK_IMPORTED_MODULE_5__.EncryptStorage(key); | ||||
|     var decrypted_word = encryptStorage.decrypt("checkword"); | ||||
|     return decrypted_word === word; | ||||
|   }; | ||||
| 
 | ||||
|   var result = function result(correct) { | ||||
|     var content; | ||||
| 
 | ||||
|     if (correct === true) { | ||||
|       content = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|         className: "col-md-8" | ||||
|       }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_List__WEBPACK_IMPORTED_MODULE_2__["default"], { | ||||
|         pages: listPages, | ||||
|         url: getPageContentUrl, | ||||
|         passphrase: passphrase, | ||||
|         setPassphrase: setPassphrase, | ||||
|         csrf: csrf, | ||||
|         removeUrl: removeUrl | ||||
|       }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_6__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_Form__WEBPACK_IMPORTED_MODULE_1__["default"], { | ||||
|         setListPages: setListPages, | ||||
|         csrf: csrf, | ||||
|         url: postUrl, | ||||
|         passphrase: passphrase | ||||
|       })); | ||||
|     } else if (correct === false) { | ||||
|       content = /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|         className: "col-md-8" | ||||
|       }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement(_Prompt__WEBPACK_IMPORTED_MODULE_3__["default"], { | ||||
|         open: true, | ||||
|         setOpen: updatePassphrase | ||||
|       })); | ||||
|     } else { | ||||
|       return correct; | ||||
|     } | ||||
| 
 | ||||
|     return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|       className: "container" | ||||
|     }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_4__.createElement("div", { | ||||
|       className: "row justify-content-center" | ||||
|     }, content))); | ||||
|   }; | ||||
| 
 | ||||
|   return result(checkPassphrase()); | ||||
| } | ||||
| 
 | ||||
| /***/ }), | ||||
| @@ -30004,7 +30054,8 @@ function Pages(_ref) { | ||||
|       setPassphrase: setPassphrase, | ||||
|       passphrase: passphrase, | ||||
|       csrf: csrf, | ||||
|       removeUrl: removeUrl | ||||
|       removeUrl: removeUrl, | ||||
|       key: page.id | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
| @@ -30292,10 +30343,9 @@ function Page(_ref2) { | ||||
|     id: page.id | ||||
|   }, alert_popup, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_9__["default"], null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_10__["default"], { | ||||
|     action: /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { | ||||
|       "aria-label": "settings" | ||||
|     }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_icons_material_MoreVert__WEBPACK_IMPORTED_MODULE_11__["default"], { | ||||
|       "aria-label": "settings", | ||||
|       onClick: handleMoreClick | ||||
|     })), | ||||
|     }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_icons_material_MoreVert__WEBPACK_IMPORTED_MODULE_11__["default"], null)), | ||||
|     title: title, | ||||
|     subheader: page.date | ||||
|   }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_12__["default"], { | ||||
| @@ -30303,10 +30353,9 @@ function Page(_ref2) { | ||||
|     timeout: "auto", | ||||
|     unmountOnExit: true | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_5__["default"], { | ||||
|     "aria-label": "remove" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_13__["default"], { | ||||
|     "aria-label": "remove", | ||||
|     onClick: remove | ||||
|   }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_14__["default"], { | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_icons_material__WEBPACK_IMPORTED_MODULE_13__["default"], null))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_14__["default"], { | ||||
|     disableSpacing: true | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1__.createElement(ExpandMore, { | ||||
|     expand: expanded, | ||||
| @@ -30382,6 +30431,158 @@ function Prompt(_ref) { | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ "./resources/js/components/user/First.tsx": | ||||
| /*!************************************************!*\ | ||||
|   !*** ./resources/js/components/user/First.tsx ***! | ||||
|   \************************************************/ | ||||
| /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { | ||||
| 
 | ||||
| "use strict"; | ||||
| __webpack_require__.r(__webpack_exports__); | ||||
| /* harmony export */ __webpack_require__.d(__webpack_exports__, { | ||||
| /* harmony export */   "default": () => (/* binding */ FirstPage) | ||||
| /* harmony export */ }); | ||||
| /* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/regenerator */ "./node_modules/@babel/runtime/regenerator/index.js"); | ||||
| /* harmony import */ var _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0__); | ||||
| /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react-dom */ "./node_modules/react-dom/index.js"); | ||||
| /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); | ||||
| /* harmony import */ var _mui_material__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @mui/material */ "./node_modules/@mui/material/TextField/TextField.js"); | ||||
| /* harmony import */ var storage_encryption__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! storage-encryption */ "./node_modules/storage-encryption/build/index.js"); | ||||
| /* harmony import */ var storage_encryption__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(storage_encryption__WEBPACK_IMPORTED_MODULE_3__); | ||||
| 
 | ||||
| 
 | ||||
| function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } | ||||
| 
 | ||||
| function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } | ||||
| 
 | ||||
| function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } | ||||
| 
 | ||||
| function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } | ||||
| 
 | ||||
| function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||||
| 
 | ||||
| function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||||
| 
 | ||||
| var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) { | ||||
|   function adopt(value) { | ||||
|     return value instanceof P ? value : new P(function (resolve) { | ||||
|       resolve(value); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   return new (P || (P = Promise))(function (resolve, reject) { | ||||
|     function fulfilled(value) { | ||||
|       try { | ||||
|         step(generator.next(value)); | ||||
|       } catch (e) { | ||||
|         reject(e); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     function rejected(value) { | ||||
|       try { | ||||
|         step(generator["throw"](value)); | ||||
|       } catch (e) { | ||||
|         reject(e); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     function step(result) { | ||||
|       result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); | ||||
|     } | ||||
| 
 | ||||
|     step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| var encryptStorage = new storage_encryption__WEBPACK_IMPORTED_MODULE_3__.EncryptStorage('test'); // TODO la clef doit venir de l'utilisateur
 | ||||
| 
 | ||||
| var app = document.getElementById('first'); | ||||
| var word = "shikiryu"; | ||||
| var csrf, | ||||
|     url = ""; | ||||
| 
 | ||||
| if (app) { | ||||
|   url = "" + app.getAttribute('data-url'); | ||||
|   csrf = "" + app.getAttribute('data-csrf'); | ||||
|   react_dom__WEBPACK_IMPORTED_MODULE_1__.render( /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement(FirstPage, null), app); | ||||
| } | ||||
| 
 | ||||
| function FirstPage() { | ||||
|   var _this = this; | ||||
| 
 | ||||
|   var _useState = (0,react__WEBPACK_IMPORTED_MODULE_2__.useState)(""), | ||||
|       _useState2 = _slicedToArray(_useState, 2), | ||||
|       passphrase = _useState2[0], | ||||
|       setPassphrase = _useState2[1]; | ||||
| 
 | ||||
|   var onSubmit = function onSubmit(event) { | ||||
|     return __awaiter(_this, void 0, void 0, /*#__PURE__*/_babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().mark(function _callee() { | ||||
|       var encryptedFormData, response, json; | ||||
|       return _babel_runtime_regenerator__WEBPACK_IMPORTED_MODULE_0___default().wrap(function _callee$(_context) { | ||||
|         while (1) { | ||||
|           switch (_context.prev = _context.next) { | ||||
|             case 0: | ||||
|               event.preventDefault(); | ||||
|               sessionStorage.setItem("key", passphrase); | ||||
|               encryptStorage = new storage_encryption__WEBPACK_IMPORTED_MODULE_3__.EncryptStorage(passphrase); | ||||
|               encryptStorage.encrypt("checkword", word); | ||||
|               encryptedFormData = new FormData(); | ||||
|               encryptedFormData.append("checkword", "" + localStorage.getItem("key")); | ||||
|               encryptedFormData.append('_token', csrf); | ||||
|               _context.next = 9; | ||||
|               return fetch(url, { | ||||
|                 method: 'POST', | ||||
|                 body: encryptedFormData | ||||
|               }); | ||||
| 
 | ||||
|             case 9: | ||||
|               response = _context.sent; | ||||
|               _context.next = 12; | ||||
|               return response.json(); | ||||
| 
 | ||||
|             case 12: | ||||
|               json = _context.sent; | ||||
| 
 | ||||
|             case 13: | ||||
|             case "end": | ||||
|               return _context.stop(); | ||||
|           } | ||||
|         } | ||||
|       }, _callee); | ||||
|     })); | ||||
|   }; | ||||
| 
 | ||||
|   var updatePassphrase = function updatePassphrase(e) { | ||||
|     setPassphrase(e.target.value); | ||||
|   }; | ||||
| 
 | ||||
|   return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement("div", { | ||||
|     className: "container" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement("div", { | ||||
|     className: "row justify-content-center" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement("div", { | ||||
|     className: "col-md-8" | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement("form", { | ||||
|     action: url, | ||||
|     id: "postPage", | ||||
|     method: "post", | ||||
|     onSubmit: onSubmit | ||||
|   }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_2__.createElement(_mui_material__WEBPACK_IMPORTED_MODULE_4__["default"], { | ||||
|     id: "filled-basic", | ||||
|     label: "Passphrase", | ||||
|     variant: "filled", | ||||
|     onInput: updatePassphrase | ||||
|   })))))); | ||||
| } | ||||
| 
 | ||||
| /***/ }), | ||||
| 
 | ||||
| /***/ "./resources/js/bootstrap.js": | ||||
| /*!***********************************!*\ | ||||
|   !*** ./resources/js/bootstrap.js ***! | ||||
|   | ||||
| @@ -12,4 +12,5 @@ require('./bootstrap'); | ||||
|  * or customize the JavaScript scaffolding to fit your unique needs. | ||||
|  */ | ||||
|  | ||||
| require('./components/pages/App.tsx'); | ||||
| require('./components/pages/App'); | ||||
| require('./components/user/First'); | ||||
|   | ||||
| @@ -5,6 +5,7 @@ import Prompt from "./Prompt"; | ||||
| import {useState} from "react"; | ||||
| import * as React from 'react'; | ||||
| import {Divider, Paper} from "@mui/material"; | ||||
| import {EncryptStorage} from "storage-encryption"; | ||||
|  | ||||
| interface List { | ||||
|     id: string; | ||||
| @@ -12,19 +13,23 @@ interface List { | ||||
| } | ||||
|  | ||||
| const app = document.getElementById('app'); | ||||
| const word = "shikiryu"; | ||||
|  | ||||
| let sessionPassphrase = sessionStorage.getItem("key"); | ||||
| let pages: List[] = []; | ||||
| let getPageContentUrl = ""; | ||||
| let postUrl = ""; | ||||
| let removeUrl = ""; | ||||
| let csrf = ""; | ||||
| let getPageContentUrl, | ||||
|     postUrl, | ||||
|     removeUrl, | ||||
|     checkword, | ||||
|     csrf = ""; | ||||
|  | ||||
| if (app) { | ||||
|     getPageContentUrl   = "" + app.getAttribute('data-url'); | ||||
|     pages               = JSON.parse("" + app.getAttribute('data-list')); | ||||
|     postUrl             = "" + app.getAttribute('data-post'); | ||||
|     removeUrl           = "" + app.getAttribute('data-remove'); | ||||
|     csrf                = "" + app.getAttribute('data-csrf'); | ||||
|     checkword           = "" + app.getAttribute('data-checkword'); | ||||
|     ReactDOM.render(<App/>, app); | ||||
| } | ||||
|  | ||||
| @@ -32,28 +37,63 @@ export default function App() { | ||||
|     const [listPages, setListPages]     = useState(pages); | ||||
|     const [passphrase, setPassphrase]   = useState(sessionPassphrase); | ||||
|  | ||||
|     return ( | ||||
|         <div> | ||||
|             <div className="container"> | ||||
|                 <div className="row justify-content-center"> | ||||
|                     <div className="col-md-8"> | ||||
|                         {/*<div className="card">*/} | ||||
|                             {/*<Paper elevation={3}>*/} | ||||
|                                 <Prompt open={passphrase === null} setOpen={setPassphrase}/> | ||||
|                                 <Pages | ||||
|                                     pages={listPages} | ||||
|                                     url={getPageContentUrl} | ||||
|                                     passphrase={passphrase} | ||||
|                                     setPassphrase={setPassphrase} | ||||
|                                     csrf={csrf} | ||||
|                                     removeUrl={removeUrl}/> | ||||
|                                 <Divider/> | ||||
|                                 <PageForm setListPages={setListPages} csrf={csrf} url={postUrl} passphrase={passphrase}/> | ||||
|                             {/*</Paper>*/} | ||||
|                         {/*</div>*/} | ||||
|     const updatePassphrase = function(newPassphrase) { | ||||
|         setPassphrase(newPassphrase); | ||||
|         return result(checkPassphrase()); | ||||
|     }; | ||||
|  | ||||
|     const checkPassphrase = function() { | ||||
|         if (checkword === "" || checkword === null || checkword === "null") { | ||||
|             console.error("checkword is empty !"); | ||||
|             // return (<Redirect to="/first" />); | ||||
|             return false; // TODO redirect to first | ||||
|         } | ||||
|         localStorage.setItem("checkword", checkword); | ||||
|  | ||||
|         const key = ""+sessionStorage.getItem("key"); | ||||
|         if (key === "" || key === null || key === "null") { | ||||
|             console.error("key is empty 🤔 !"); | ||||
|             // return (<Redirect to="/first" />); | ||||
|             return false; // TODO redirect to first ? | ||||
|         } | ||||
|         let encryptStorage = new EncryptStorage(key); | ||||
|         const decrypted_word = encryptStorage.decrypt("checkword"); | ||||
|  | ||||
|         return decrypted_word === word; | ||||
|     }; | ||||
|  | ||||
|     const result = function(correct) { | ||||
|         let content; | ||||
|         if (correct === true) { | ||||
|             content = <div className="col-md-8"> | ||||
|                 <Pages | ||||
|                 pages={listPages} | ||||
|                 url={getPageContentUrl} | ||||
|                 passphrase={passphrase} | ||||
|                 setPassphrase={setPassphrase} | ||||
|                 csrf={csrf} | ||||
|                 removeUrl={removeUrl}/> | ||||
|             <Divider/> | ||||
|             <PageForm setListPages={setListPages} csrf={csrf} url={postUrl} passphrase={passphrase}/> | ||||
|             </div> | ||||
|         } else if (correct === false) { | ||||
|             content =  <div className="col-md-8"> | ||||
|                 <Prompt open={true} setOpen={updatePassphrase}/> | ||||
|             </div>; | ||||
|         } else { | ||||
|             return correct; | ||||
|         } | ||||
|  | ||||
|         return ( | ||||
|             <div> | ||||
|                 <div className="container"> | ||||
|                     <div className="row justify-content-center"> | ||||
|                         { content } | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     return result(checkPassphrase()); | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ export default function Pages({pages, url, removeUrl, csrf, passphrase, setPassp | ||||
|     const isPassphraseSet = passphrase !== null; | ||||
|  | ||||
|     let listPages = pages.map(page => | ||||
|         <Page page={page} url={url} setPassphrase={setPassphrase} passphrase={passphrase} csrf={csrf} removeUrl={removeUrl} /> | ||||
|         <Page page={page} url={url} setPassphrase={setPassphrase} passphrase={passphrase} csrf={csrf} removeUrl={removeUrl} key={page.id}/> | ||||
|     ) | ||||
|  | ||||
|     if (isPassphraseSet) { | ||||
|   | ||||
| @@ -88,16 +88,16 @@ export default function Page({page, url, removeUrl, csrf, passphrase, setPassphr | ||||
|                 <Card> | ||||
|                     <CardHeader | ||||
|                         action={ | ||||
|                             <IconButton aria-label="settings"> | ||||
|                                 <MoreVertIcon onClick={handleMoreClick} /> | ||||
|                             <IconButton aria-label="settings" onClick={handleMoreClick}> | ||||
|                                 <MoreVertIcon /> | ||||
|                             </IconButton> | ||||
|                         } | ||||
|                         title={title} | ||||
|                         subheader={page.date} | ||||
|                     /> | ||||
|                     <Collapse in={more} timeout="auto" unmountOnExit> | ||||
|                         <IconButton aria-label="remove"> | ||||
|                             <Delete onClick={remove} /> | ||||
|                         <IconButton aria-label="remove" onClick={remove} > | ||||
|                             <Delete /> | ||||
|                         </IconButton> | ||||
|                     </Collapse> | ||||
|                     <CardActions disableSpacing> | ||||
|   | ||||
							
								
								
									
										55
									
								
								resources/js/components/user/First.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								resources/js/components/user/First.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| import ReactDOM from 'react-dom'; | ||||
| import * as React from "react"; | ||||
| import {TextField} from "@mui/material"; | ||||
| import {EncryptStorage} from "storage-encryption"; | ||||
| import {useState} from "react"; | ||||
| let encryptStorage = new EncryptStorage('test'); // TODO la clef doit venir de l'utilisateur | ||||
|  | ||||
| const app = document.getElementById('first'); | ||||
| const word = "shikiryu"; | ||||
| let csrf, | ||||
|     url = ""; | ||||
|  | ||||
| if (app) { | ||||
|     url   = "" + app.getAttribute('data-url'); | ||||
|     csrf  = "" + app.getAttribute('data-csrf'); | ||||
|     ReactDOM.render(<FirstPage/>, app); | ||||
| } | ||||
|  | ||||
| export default function FirstPage() { | ||||
|     const [passphrase, setPassphrase] = useState(""); | ||||
|     const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => { | ||||
|         event.preventDefault(); | ||||
|         sessionStorage.setItem("key", passphrase); | ||||
|         encryptStorage = new EncryptStorage(passphrase); | ||||
|         encryptStorage.encrypt("checkword", word); | ||||
|         let encryptedFormData = new FormData(); | ||||
|         encryptedFormData.append("checkword", ""+localStorage.getItem("key")); | ||||
|         encryptedFormData.append('_token', csrf); | ||||
|  | ||||
|         let response = await fetch(url, { | ||||
|             method: 'POST', | ||||
|             body: encryptedFormData | ||||
|         }); | ||||
|  | ||||
|         const json = await response.json(); // TODO redirect if success | ||||
|     }; | ||||
|  | ||||
|     const updatePassphrase = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||
|         setPassphrase(e.target.value); | ||||
|     }; | ||||
|  | ||||
|     return ( | ||||
|         <div> | ||||
|             <div className="container"> | ||||
|                 <div className="row justify-content-center"> | ||||
|                     <div className="col-md-8"> | ||||
|                         <form action={url} id="postPage" method="post" onSubmit={onSubmit}> | ||||
|                             <TextField id="filled-basic" label="Passphrase" variant="filled" onInput={updatePassphrase}/> | ||||
|                         </form> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     ); | ||||
| } | ||||
| @@ -14,7 +14,9 @@ | ||||
|                          data-url="{{ route('pages.show', ['page' => 'replace_me']) }}" | ||||
|                          data-post="{{ route('pages.store') }}" | ||||
|                          data-remove="{{ route('pages.destroy', ['page' => 'replace_me']) }}" | ||||
|                          data-csrf="{{ csrf_token() }}"> | ||||
|                          data-csrf="{{ csrf_token() }}" | ||||
|                         data-checkword="{{ $checkword }}" | ||||
|                     > | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
							
								
								
									
										21
									
								
								resources/views/user/first.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								resources/views/user/first.blade.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| <x-app-layout> | ||||
|     <x-slot name="header"> | ||||
|         <h2 class="font-semibold text-xl text-gray-800 leading-tight"> | ||||
|             {{ __('Première connexion') }} | ||||
|         </h2> | ||||
|     </x-slot> | ||||
|  | ||||
|     <div class="py-12"> | ||||
|         <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> | ||||
|             <div class="bg-white overflow-hidden shadow-sm sm:rounded-lg"> | ||||
|                 <div class="p-6 bg-white border-b border-gray-200"> | ||||
|                     <div id="first" | ||||
|                          data-url="{{ route('user.storeFirst') }}" | ||||
|                          data-csrf="{{ csrf_token() }}"> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
|  | ||||
| </x-app-layout> | ||||
| @@ -1,6 +1,7 @@ | ||||
| <?php | ||||
|  | ||||
| use App\Http\Controllers\PageController; | ||||
| use App\Http\Controllers\UserController; | ||||
| use Illuminate\Support\Facades\Route; | ||||
|  | ||||
| /* | ||||
| @@ -21,6 +22,9 @@ Route::get('/', function () { | ||||
| Route::resource('pages', PageController::class) | ||||
|     ->middleware(['auth']); | ||||
|  | ||||
| Route::get('/first', [UserController::class, 'first'])->name('user.first'); | ||||
| Route::post('/first', [UserController::class, 'storeFirst'])->name('user.storeFirst'); | ||||
|  | ||||
| Route::get('/dashboard', function () { | ||||
|     return view('dashboard'); | ||||
| })->middleware(['auth'])->name('dashboard'); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user