From 4a39c5ad31e4e56abb3d2b8c74d61e7402604717 Mon Sep 17 00:00:00 2001 From: Wind-Explorer Date: Sat, 22 Jun 2024 23:59:44 +0800 Subject: [PATCH] Account creation --- client/package.json | 5 +- client/pnpm-lock.yaml | 150 ++++++++++++++++ client/src/App.tsx | 182 ++++++++++++++------ client/src/components/NextUIFormikInput.tsx | 32 ++++ client/src/config.ts | 5 + server/models/User.js | 4 +- server/package.json | 2 + server/pnpm-lock.yaml | 36 ++++ server/routes/users.js | 22 ++- 9 files changed, 380 insertions(+), 58 deletions(-) create mode 100644 client/src/components/NextUIFormikInput.tsx create mode 100644 client/src/config.ts diff --git a/client/package.json b/client/package.json index 64b9aa7..35e8229 100644 --- a/client/package.json +++ b/client/package.json @@ -11,9 +11,12 @@ }, "dependencies": { "@nextui-org/react": "^2.4.2", + "axios": "^1.7.2", + "formik": "^2.4.6", "framer-motion": "^11.2.10", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "yup": "^1.4.0" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index e064da6..fe8f86a 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -8,6 +8,12 @@ dependencies: '@nextui-org/react': specifier: ^2.4.2 version: 2.4.2(@types/react@18.3.3)(framer-motion@11.2.10)(react-dom@18.3.1)(react@18.3.1)(tailwindcss@3.4.4) + axios: + specifier: ^1.7.2 + version: 1.7.2 + formik: + specifier: ^2.4.6 + version: 2.4.6(react@18.3.1) framer-motion: specifier: ^11.2.10 version: 11.2.10(react-dom@18.3.1)(react@18.3.1) @@ -17,6 +23,9 @@ dependencies: react-dom: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + yup: + specifier: ^1.4.0 + version: 1.4.0 devDependencies: '@types/react': @@ -3247,6 +3256,13 @@ packages: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} dev: true + /@types/hoist-non-react-statics@3.3.5: + resolution: {integrity: sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==} + dependencies: + '@types/react': 18.3.3 + hoist-non-react-statics: 3.3.2 + dev: false + /@types/lodash.debounce@4.0.9: resolution: {integrity: sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==} dependencies: @@ -3489,6 +3505,10 @@ packages: engines: {node: '>=8'} dev: true + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + /autoprefixer@10.4.19(postcss@8.4.38): resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -3505,6 +3525,16 @@ packages: postcss-value-parser: 4.2.0 dev: true + /axios@1.7.2: + resolution: {integrity: sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==} + dependencies: + follow-redirects: 1.15.6 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -3633,6 +3663,13 @@ packages: color-string: 1.9.1 dev: false + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -3681,11 +3718,21 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true + /deepmerge@2.2.1: + resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} + engines: {node: '>=0.10.0'} + dev: false + /deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} dev: false + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + /detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} dev: false @@ -3945,6 +3992,16 @@ packages: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} dev: true + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + /foreground-child@3.2.1: resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} engines: {node: '>=14'} @@ -3952,6 +4009,31 @@ packages: cross-spawn: 7.0.3 signal-exit: 4.1.0 + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /formik@2.4.6(react@18.3.1): + resolution: {integrity: sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==} + peerDependencies: + react: '>=16.8.0' + dependencies: + '@types/hoist-non-react-statics': 3.3.5 + deepmerge: 2.2.1 + hoist-non-react-statics: 3.3.2 + lodash: 4.17.21 + lodash-es: 4.17.21 + react: 18.3.1 + react-fast-compare: 2.0.4 + tiny-warning: 1.0.3 + tslib: 2.6.3 + dev: false + /fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true @@ -4079,6 +4161,12 @@ packages: dependencies: function-bind: 1.1.2 + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} @@ -4243,6 +4331,10 @@ packages: p-locate: 5.0.0 dev: true + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: false + /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} dev: false @@ -4271,6 +4363,10 @@ packages: resolution: {integrity: sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==} dev: false + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -4299,6 +4395,18 @@ packages: braces: 3.0.3 picomatch: 2.3.1 + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: @@ -4510,6 +4618,14 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + dev: false + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -4528,6 +4644,14 @@ packages: scheduler: 0.23.2 dev: false + /react-fast-compare@2.0.4: + resolution: {integrity: sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==} + dev: false + + /react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + /react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} @@ -4852,6 +4976,14 @@ packages: dependencies: any-promise: 1.3.0 + /tiny-case@1.0.3: + resolution: {integrity: sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==} + dev: false + + /tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + dev: false + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -4863,6 +4995,10 @@ packages: dependencies: is-number: 7.0.0 + /toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + dev: false + /ts-api-utils@1.3.0(typescript@5.4.5): resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -4891,6 +5027,11 @@ packages: engines: {node: '>=10'} dev: true + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: false + /typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} @@ -5063,3 +5204,12 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true + + /yup@1.4.0: + resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} + dependencies: + property-expr: 2.0.6 + tiny-case: 1.0.3 + toposort: 2.0.2 + type-fest: 2.19.0 + dev: false diff --git a/client/src/App.tsx b/client/src/App.tsx index 65e6058..4916836 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,61 +1,141 @@ -import { Button, Checkbox, Input, Link } from "@nextui-org/react"; -import { useState } from "react"; +import { Button, Checkbox, Link } from "@nextui-org/react"; +import { Formik, Form, Field, ErrorMessage } from "formik"; +import * as Yup from "yup"; +import axios from "axios"; +import config from "./config"; +import NextUIFormikInput from "./components/NextUIFormikInput"; + +const validationSchema = Yup.object({ + firstName: Yup.string() + .trim() + .min(1) + .max(100) + .required("First Name is required"), + lastName: Yup.string() + .trim() + .min(1) + .max(100) + .required("Last Name is required"), + email: Yup.string() + .trim() + .min(5) + .max(69) + .email("Invalid email format") + .required("Email is required"), + phoneNumber: Yup.string() + .trim() + .matches(/^[0-9]+$/, "Phone number must contain only numerical characters") + .length(8, "Phone number must be 8 digits") + .required("Phone number is required"), + password: Yup.string() + .trim() + .min(8, "Password must be at least 8 characters") + .required("Password is required"), + terms: Yup.boolean().oneOf( + [true], + "You must accept the terms and conditions" + ), +}); export default function App() { - const [userAgreedToTermsAndServices, setUserAgreedToTermsAndServices] = - useState(false); + const initialValues = { + firstName: "", + lastName: "", + email: "", + phoneNumber: "", + password: "", + terms: false, + }; + + const handleSubmit = async (values: any) => { + try { + const response = await axios.post( + config.serverAddress + "/users", + values + ); + console.log("User created successfully:", response.data); + } catch (error) { + console.error("Error creating user:", error); + } + }; + return (

ecoconnect

-
- - - - +65

- } - > - -
- - I have read and agreed to the Terms and Services - - + {({ isValid, dirty }) => ( +
+ + + + + +65 +

+ } + /> + +
+ + I have read and agreed to the{" "} + Terms and Services + + +
+ + + )} +
); diff --git a/client/src/components/NextUIFormikInput.tsx b/client/src/components/NextUIFormikInput.tsx new file mode 100644 index 0000000..cc670ee --- /dev/null +++ b/client/src/components/NextUIFormikInput.tsx @@ -0,0 +1,32 @@ +import { Input } from "@nextui-org/react"; +import { useField } from "formik"; + +interface NextUIFormikInputProps { + label: string; + name: string; + type: string; + placeholder: string; + labelPlacement?: "inside" | "outside"; + startContent?: JSX.Element; +} + +const NextUIFormikInput = ({ + label, + startContent, + ...props +}: NextUIFormikInputProps) => { + const [field, meta] = useField(props.name); + + return ( + + ); +}; + +export default NextUIFormikInput; diff --git a/client/src/config.ts b/client/src/config.ts new file mode 100644 index 0000000..59dd237 --- /dev/null +++ b/client/src/config.ts @@ -0,0 +1,5 @@ +const config = { + serverAddress: "http://localhost:5183", +}; + +export default config; diff --git a/server/models/User.js b/server/models/User.js index a1a4d9a..8c9e79a 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -3,7 +3,7 @@ module.exports = (sequelize, DataTypes) => { "User", { id: { - type: DataTypes.INTEGER(), + type: DataTypes.STRING(36), allowNull: false, primaryKey: true, }, @@ -23,7 +23,7 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.STRING(8), allowNull: false, }, - passwordHash: { + password: { type: DataTypes.STRING(255), allowNull: false, }, diff --git a/server/package.json b/server/package.json index aaae287..24d3e8b 100644 --- a/server/package.json +++ b/server/package.json @@ -10,12 +10,14 @@ "keywords": [], "author": "Wind_Explorer", "dependencies": { + "argon2": "^0.40.3", "cors": "^2.8.5", "dotenv": "^16.4.5", "express": "^4.19.2", "mysql2": "^3.10.1", "nodemon": "^3.1.3", "sequelize": "^6.37.3", + "uuid": "^10.0.0", "yup": "^1.4.0" } } diff --git a/server/pnpm-lock.yaml b/server/pnpm-lock.yaml index d5cbca4..7c79478 100644 --- a/server/pnpm-lock.yaml +++ b/server/pnpm-lock.yaml @@ -5,6 +5,9 @@ settings: excludeLinksFromLockfile: false dependencies: + argon2: + specifier: ^0.40.3 + version: 0.40.3 cors: specifier: ^2.8.5 version: 2.8.5 @@ -23,12 +26,20 @@ dependencies: sequelize: specifier: ^6.37.3 version: 6.37.3(mysql2@3.10.1) + uuid: + specifier: ^10.0.0 + version: 10.0.0 yup: specifier: ^1.4.0 version: 1.4.0 packages: + /@phc/format@1.0.0: + resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} + engines: {node: '>=10'} + dev: false + /@types/debug@4.1.12: resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} dependencies: @@ -65,6 +76,16 @@ packages: picomatch: 2.3.1 dev: false + /argon2@0.40.3: + resolution: {integrity: sha512-FrSmz4VeM91jwFvvjsQv9GYp6o/kARWoYKjbjDB2U5io1H3e5X67PYGclFDeQff6UXIhUd4aHR3mxCdBbMMuQw==} + engines: {node: '>=16.17.0'} + requiresBuild: true + dependencies: + '@phc/format': 1.0.0 + node-addon-api: 8.0.0 + node-gyp-build: 4.8.1 + dev: false + /array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: false @@ -579,6 +600,16 @@ packages: engines: {node: '>= 0.6'} dev: false + /node-addon-api@8.0.0: + resolution: {integrity: sha512-ipO7rsHEBqa9STO5C5T10fj732ml+5kLN1cAG8/jdHd56ldQeGj3Q7+scUS+VHK/qy1zLEwC4wMK5+yM0btPvw==} + engines: {node: ^18 || ^20 || >= 21} + dev: false + + /node-gyp-build@4.8.1: + resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} + hasBin: true + dev: false + /nodemon@3.1.3: resolution: {integrity: sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==} engines: {node: '>=10'} @@ -904,6 +935,11 @@ packages: engines: {node: '>= 0.4.0'} dev: false + /uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + dev: false + /uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true diff --git a/server/routes/users.js b/server/routes/users.js index 523fc51..853e233 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -2,25 +2,39 @@ const express = require("express"); const yup = require("yup"); const { Op } = require("sequelize"); const { User } = require("../models"); +const argon2 = require("argon2"); const router = express.Router(); +const { v4: uuidV4 } = require("uuid"); let validationSchema = yup.object({ - id: yup.number().min(0).required(), + id: yup.string().trim().min(36).max(36).required(), firstName: yup.string().trim().min(1).max(100).required(), lastName: yup.string().trim().min(1).max(100).required(), email: yup.string().trim().min(5).max(69).email().required(), - phoneNumber: yup.string().trim().length(8).required(), - passwordHash: yup.string().trim().min(128).max(255).required(), + phoneNumber: yup + .string() + .trim() + .matches(/^[0-9]+$/) + .length(8) + .required(), + password: yup.string().trim().max(255).required(), }); router.post("/", async (req, res) => { let data = req.body; try { + data.id = uuidV4(); + data.password = await argon2.hash(data.password); + + console.log("Validating schema..."); data = await validationSchema.validate(data, { abortEarly: false }); - // Process valid data + + console.log("Creating user..."); let result = await User.create(data); res.json(result); + console.log("Success!"); } catch (err) { + console.log("Error caught! Info: " + err); res.status(400).json({ errors: err.errors }); } });