Преглед изворни кода

New user creation now functional

Lee Morgan пре 2 недеља
родитељ
комит
d2a387e8d5

+ 1 - 0
example.env

@@ -0,0 +1 @@
+MONGODB_URI

+ 259 - 1
package-lock.json

@@ -7,6 +7,11 @@
 		"": {
 			"name": "recipes-leemorgan-dev",
 			"version": "0.0.1",
+			"dependencies": {
+				"bcrypt": "^6.0.0",
+				"mongoose": "^9.9.4",
+				"validator": "^13.15.35"
+			},
 			"devDependencies": {
 				"@sveltejs/adapter-auto": "^7.0.1",
 				"@sveltejs/kit": "^2.63.0",
@@ -65,6 +70,15 @@
 				"@jridgewell/sourcemap-codec": "^1.4.14"
 			}
 		},
+		"node_modules/@mongodb-js/saslprep": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.5.0.tgz",
+			"integrity": "sha512-Hk1SKJCMcCos38+vqDnZzlIo4XRj9yCGzYkjB4LcqpeXRIYfia1UWTz+VrueLxoU+uSRJzgkufxoRZg8gi52YA==",
+			"license": "MIT",
+			"dependencies": {
+				"sparse-bitfield": "^3.0.3"
+			}
+		},
 		"node_modules/@oxc-project/types": {
 			"version": "0.147.0",
 			"resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.147.0.tgz",
@@ -366,7 +380,6 @@
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz",
 			"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
-			"dev": true,
 			"license": "MIT"
 		},
 		"node_modules/@sveltejs/acorn-typescript": {
@@ -482,6 +495,21 @@
 			"dev": true,
 			"license": "MIT"
 		},
+		"node_modules/@types/webidl-conversions": {
+			"version": "7.0.3",
+			"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
+			"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
+			"license": "MIT"
+		},
+		"node_modules/@types/whatwg-url": {
+			"version": "13.0.0",
+			"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-13.0.0.tgz",
+			"integrity": "sha512-N8WXpbE6Wgri7KUSvrmQcqrMllKZ9uxkYWMt+mCSGwNc0Hsw9VQTW7ApqI4XNrx6/SaM2QQJCzMPDEXE058s+Q==",
+			"license": "MIT",
+			"dependencies": {
+				"@types/webidl-conversions": "*"
+			}
+		},
 		"node_modules/acorn": {
 			"version": "8.18.0",
 			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz",
@@ -515,6 +543,29 @@
 				"node": ">= 0.4"
 			}
 		},
+		"node_modules/bcrypt": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
+			"integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
+			"hasInstallScript": true,
+			"license": "MIT",
+			"dependencies": {
+				"node-addon-api": "^8.3.0",
+				"node-gyp-build": "^4.8.4"
+			},
+			"engines": {
+				"node": ">= 18"
+			}
+		},
+		"node_modules/bson": {
+			"version": "7.3.2",
+			"resolved": "https://registry.npmjs.org/bson/-/bson-7.3.2.tgz",
+			"integrity": "sha512-1w0ra+ho1cuE+w8jzwgzTFIimFtCfZeCoOsvIPQg6uyFCsp8M29U7bNNf5GrFh88TXbYg1g3TyKUGpd6O7q6zA==",
+			"license": "Apache-2.0",
+			"engines": {
+				"node": ">=20.19.0"
+			}
+		},
 		"node_modules/clsx": {
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
@@ -630,6 +681,15 @@
 				"@types/estree": "^1.0.6"
 			}
 		},
+		"node_modules/kareem": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/kareem/-/kareem-3.3.0.tgz",
+			"integrity": "sha512-kpSuLD3/7RenBnjnJdOHXCKC8dTd1JzeOiJhN0necWWci6cC+qX+VuwPnMVgb+a4+KNJSfgqahpnfWaeDXCimw==",
+			"license": "Apache-2.0",
+			"engines": {
+				"node": ">=18.0.0"
+			}
+		},
 		"node_modules/kleur": {
 			"version": "4.1.5",
 			"resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
@@ -930,6 +990,111 @@
 				"@jridgewell/sourcemap-codec": "^1.5.5"
 			}
 		},
+		"node_modules/memory-pager": {
+			"version": "1.5.0",
+			"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+			"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
+			"license": "MIT"
+		},
+		"node_modules/mongodb": {
+			"version": "7.5.0",
+			"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.5.0.tgz",
+			"integrity": "sha512-5FnrEDLnvp6ycUOGLNLLU33BfCx2qmp2mJjGPDwKLruYsVzXVSK5fsGpoDXvsXJwBfBsD7ebMRdawbDxC2814g==",
+			"license": "Apache-2.0",
+			"dependencies": {
+				"@mongodb-js/saslprep": "^1.4.11",
+				"bson": "^7.2.0",
+				"mongodb-connection-string-url": "^7.0.1"
+			},
+			"engines": {
+				"node": ">=20.19.0"
+			},
+			"peerDependencies": {
+				"@aws-sdk/credential-providers": "^3.806.0",
+				"@mongodb-js/zstd": "^7.0.0",
+				"gcp-metadata": "^7.0.1",
+				"kerberos": "^7.0.0",
+				"mongodb-client-encryption": "^7.2.0",
+				"snappy": "^7.3.2",
+				"socks": "^2.8.6"
+			},
+			"peerDependenciesMeta": {
+				"@aws-sdk/credential-providers": {
+					"optional": true
+				},
+				"@mongodb-js/zstd": {
+					"optional": true
+				},
+				"gcp-metadata": {
+					"optional": true
+				},
+				"kerberos": {
+					"optional": true
+				},
+				"mongodb-client-encryption": {
+					"optional": true
+				},
+				"snappy": {
+					"optional": true
+				},
+				"socks": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/mongodb-connection-string-url": {
+			"version": "7.0.2",
+			"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-7.0.2.tgz",
+			"integrity": "sha512-ZoS07RoFqpKYQwAk59qmrx8+jJHNHU30UjlU96QktiGn1ltvDr+vCznLX5DiUBLEpMAHatHNWV1nM/74ul66kA==",
+			"license": "Apache-2.0",
+			"dependencies": {
+				"@types/whatwg-url": "^13.0.0",
+				"whatwg-url": "^14.1.0"
+			},
+			"engines": {
+				"node": ">=20.19.0"
+			}
+		},
+		"node_modules/mongoose": {
+			"version": "9.9.4",
+			"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-9.9.4.tgz",
+			"integrity": "sha512-Gc7buf0ExrOZ3t8MD8tVzTek7Qr5d+tEwj4GRFmHCtTZvpaDb38EVsXgCkYacPL9ICAftgS+FGe+dQHLRLHhcw==",
+			"license": "MIT",
+			"dependencies": {
+				"@standard-schema/spec": "^1.1.0",
+				"kareem": "3.3.0",
+				"mongodb": "~7.5",
+				"mpath": "0.9.0",
+				"mquery": "6.0.0",
+				"ms": "2.1.3",
+				"sift": "17.1.3"
+			},
+			"engines": {
+				"node": ">=20.19.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/mongoose"
+			}
+		},
+		"node_modules/mpath": {
+			"version": "0.9.0",
+			"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz",
+			"integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=4.0.0"
+			}
+		},
+		"node_modules/mquery": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/mquery/-/mquery-6.0.0.tgz",
+			"integrity": "sha512-b2KQNsmgtkscfeDgkYMcWGn9vZI9YoXh802VDEwE6qc50zxBFQ0Oo8ROkawbPAsXCY1/Z1yp0MagqsZStPWJjw==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=20.19.0"
+			}
+		},
 		"node_modules/mrmime": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
@@ -940,6 +1105,12 @@
 				"node": ">=10"
 			}
 		},
+		"node_modules/ms": {
+			"version": "2.1.3",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+			"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+			"license": "MIT"
+		},
 		"node_modules/nanoid": {
 			"version": "3.3.18",
 			"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz",
@@ -959,6 +1130,26 @@
 				"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
 			}
 		},
+		"node_modules/node-addon-api": {
+			"version": "8.9.2",
+			"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.2.tgz",
+			"integrity": "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==",
+			"license": "MIT",
+			"engines": {
+				"node": "^18 || ^20 || >= 21"
+			}
+		},
+		"node_modules/node-gyp-build": {
+			"version": "4.8.4",
+			"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+			"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+			"license": "MIT",
+			"bin": {
+				"node-gyp-build": "bin.js",
+				"node-gyp-build-optional": "optional.js",
+				"node-gyp-build-test": "build-test.js"
+			}
+		},
 		"node_modules/obug": {
 			"version": "2.1.4",
 			"resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz",
@@ -1022,6 +1213,15 @@
 				"node": "^10 || ^12 || >=14"
 			}
 		},
+		"node_modules/punycode": {
+			"version": "2.3.1",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+			"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+			"license": "MIT",
+			"engines": {
+				"node": ">=6"
+			}
+		},
 		"node_modules/rolldown": {
 			"version": "1.2.6",
 			"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.6.tgz",
@@ -1063,6 +1263,12 @@
 			"dev": true,
 			"license": "MIT"
 		},
+		"node_modules/sift": {
+			"version": "17.1.3",
+			"resolved": "https://registry.npmjs.org/sift/-/sift-17.1.3.tgz",
+			"integrity": "sha512-Rtlj66/b0ICeFzYTuNvX/EF1igRbbnGSvEyT79McoZa/DeGhMyC5pWKOEsZKnpkqtSeovd5FL/bjHWC3CIIvCQ==",
+			"license": "MIT"
+		},
 		"node_modules/sirv": {
 			"version": "3.0.2",
 			"resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz",
@@ -1088,6 +1294,15 @@
 				"node": ">=0.10.0"
 			}
 		},
+		"node_modules/sparse-bitfield": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+			"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+			"license": "MIT",
+			"dependencies": {
+				"memory-pager": "^1.0.2"
+			}
+		},
 		"node_modules/svelte": {
 			"version": "5.56.10",
 			"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.10.tgz",
@@ -1143,6 +1358,27 @@
 				"node": ">=6"
 			}
 		},
+		"node_modules/tr46": {
+			"version": "5.1.1",
+			"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
+			"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
+			"license": "MIT",
+			"dependencies": {
+				"punycode": "^2.3.1"
+			},
+			"engines": {
+				"node": ">=18"
+			}
+		},
+		"node_modules/validator": {
+			"version": "13.15.35",
+			"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz",
+			"integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==",
+			"license": "MIT",
+			"engines": {
+				"node": ">= 0.10"
+			}
+		},
 		"node_modules/vite": {
 			"version": "8.2.2",
 			"resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz",
@@ -1241,6 +1477,28 @@
 				}
 			}
 		},
+		"node_modules/webidl-conversions": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+			"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+			"license": "BSD-2-Clause",
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/whatwg-url": {
+			"version": "14.2.0",
+			"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
+			"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
+			"license": "MIT",
+			"dependencies": {
+				"tr46": "^5.1.0",
+				"webidl-conversions": "^7.0.0"
+			},
+			"engines": {
+				"node": ">=18"
+			}
+		},
 		"node_modules/zimmerframe": {
 			"version": "1.1.4",
 			"resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz",

+ 5 - 0
package.json

@@ -15,5 +15,10 @@
 		"@sveltejs/vite-plugin-svelte": "^7.1.2",
 		"svelte": "^5.56.1",
 		"vite": "^8.0.16"
+	},
+	"dependencies": {
+		"bcrypt": "^6.0.0",
+		"mongoose": "^9.9.4",
+		"validator": "^13.15.35"
 	}
 }

+ 10 - 0
src/lib/server/db.js

@@ -0,0 +1,10 @@
+import mongoose from "mongoose";
+import {MONGODB_URI} from "$env/static/private";
+
+let isConnected = false;
+
+export async function connectDB() {
+    if(isConnected) return;
+    await mongoose.connect(MONGODB_URI);
+    isConnected = true;
+}

+ 18 - 0
src/lib/server/models/User.js

@@ -0,0 +1,18 @@
+import mongoose from "mongoose";
+
+const userSchema = new mongoose.Schema({
+    name: {
+        type: String,
+        required: true
+    },
+    email: {
+        type: String,
+        required: true
+    },
+    password: {
+        type: String,
+        required: true
+    }
+});
+
+export default mongoose.model("users", userSchema);

+ 7 - 0
src/routes/login/+page.server.js

@@ -0,0 +1,7 @@
+export const actions = {
+    default: async ({request})=>{
+        const data = await request.formData();
+        const name = data.get("name");
+        const email
+    }
+}

+ 35 - 0
src/routes/register/+page.server.js

@@ -0,0 +1,35 @@
+import {fail, redirect} from "@sveltejs/kit";
+import validator from "validator";
+import bcrypt from "bcrypt";
+import {connectDB} from "$lib/server/db";
+import User from "$lib/server/models/User.js";
+
+export const actions = {
+    default: async ({request})=>{
+        const data = await request.formData();
+        const name = data.get("name");
+        const email = data.get("email").toLowerCase();
+        const password = data.get("password");
+        const confirmPassword = data.get("confirmPassword");
+
+        if(!name) return fail(400, {message: "Name is required"});
+        if(!email) return fail(400, {message: "Email is required"});
+        if(!password || !confirmPassword) return fail(400, "Password is required");
+
+        if(!validator.isEmail(email)) return fail(400, "Invalid email");
+        if(password !== confirmPassword) return fail(400, "Passwords do not match");
+        if(password.length < 12) return fail(400, "Password must contain at least 12 characters");
+
+        await connectDB();
+
+        const user = new User({
+            name: name,
+            email: email,
+            password: await bcrypt.hash(password, 12)
+        });
+
+        user.save();
+
+        redirect(303, "/home");
+    }
+}

+ 8 - 1
src/routes/register/+page.svelte

@@ -1,5 +1,12 @@
 <script>
     import {enhance} from "$app/forms";
+    import {onMount} from "svelte";
+
+    let nameInput;
+
+    $effect(()=>{
+        nameInput?.focus();
+    });
 </script>
 
 <div class="container">
@@ -7,7 +14,7 @@
         <h1>Sign Up</h1>
 
         <label>Name
-            <input name="name" type="text" required>
+            <input name="name" type="text" bind:this={nameInput} required>
         </label>
 
         <label>Email