From 2ff10a6db8db755d3c379aa3c7d7d17543fa12c8 Mon Sep 17 00:00:00 2001 From: Ismail Halili Date: Tue, 7 May 2024 18:25:23 +0200 Subject: [PATCH] feat(web): implement user authentication and add on the fly migration to Strapi's authentication --- .env.example | 2 +- .../users-permissions/strapi-server.ts | 3 - scripts/user-migration/user-migration.js | 15 +- web/package-lock.json | 140 ++++++++++++++++++ web/package.json | 3 + web/src/app/api/auth/[...nextauth]/route.ts | 35 +++-- web/src/app/my-account/page.tsx | 71 +++++++++ web/src/app/registration/page.tsx | 11 +- .../Layout/Navigation/Navigation.tsx | 7 +- web/src/config/constants.ts | 4 + web/src/config/db.ts | 9 ++ web/src/lib/auth/legacy_web.ts | 42 ++++++ .../lib/{strapi/auth.ts => auth/strapi.ts} | 12 +- web/tsconfig.json | 2 +- web/types/next-auth.d.ts | 15 ++ 15 files changed, 325 insertions(+), 46 deletions(-) delete mode 100644 cms/src/extensions/users-permissions/strapi-server.ts create mode 100644 web/src/app/my-account/page.tsx create mode 100644 web/src/config/db.ts create mode 100644 web/src/lib/auth/legacy_web.ts rename web/src/lib/{strapi/auth.ts => auth/strapi.ts} (76%) create mode 100644 web/types/next-auth.d.ts diff --git a/.env.example b/.env.example index 53e4c22c..fd12addd 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ DATABASE_PASSWORD=super-secret DATABASE_PORT=3306 DATABASE_SSL=false -APP_DATABASE_NAME=vim +WEB_DATABASE_NAME=vim CMS_DATABASE_NAME=vim_cms CMS_PORT=1337 diff --git a/cms/src/extensions/users-permissions/strapi-server.ts b/cms/src/extensions/users-permissions/strapi-server.ts deleted file mode 100644 index 838c05ee..00000000 --- a/cms/src/extensions/users-permissions/strapi-server.ts +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = plugin => { - const x = -}; diff --git a/scripts/user-migration/user-migration.js b/scripts/user-migration/user-migration.js index c81e5fc1..0065b8c6 100644 --- a/scripts/user-migration/user-migration.js +++ b/scripts/user-migration/user-migration.js @@ -1,17 +1,11 @@ +// example migration const strapiUrl = "http://localhost:1337/api"; - const axios = require("axios"); async function getUsersFromStrapi() { try { - // Make a GET request to the Strapi API to fetch users const response = await axios.get(`${strapiUrl}/users`); - - // Extract user data from the response const users = response.data; - - // Output user data - console.log("Users:"); console.log(users); } catch (error) { console.error("Error fetching users:", error.message); @@ -43,9 +37,7 @@ async function createUser(username, email, password, old_password) { } } -// Get the client const mysql = require("mysql2"); -// Create the connection to database const connection = mysql.createConnection({ host: "localhost", user: "vim", @@ -53,9 +45,8 @@ const connection = mysql.createConnection({ password: "super-secret", }); -// A simple SELECT query connection.query("SELECT * FROM `vs_users`", function (err, results, fields) { - console.log(results); // results contains rows returned by server + console.log(results); results.forEach((user) => { createUser(user.user_name, user.email, "123gege321", "old_hash") @@ -67,5 +58,5 @@ connection.query("SELECT * FROM `vs_users`", function (err, results, fields) { }); }); - console.log(fields); // fields contains extra meta data about results, if available + console.log(fields); }); diff --git a/web/package-lock.json b/web/package-lock.json index 3c573b99..23d16a78 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -11,6 +11,8 @@ "@tabler/icons-react": "^2.45.0", "@tanstack/react-table": "^8.11.7", "axios": "^1.6.8", + "md5": "^2.3.0", + "mysql2": "^3.9.7", "next": "13.5.6", "next-auth": "^4.24.7", "qs": "^6.11.2", @@ -19,6 +21,7 @@ "swiper": "^11.0.5" }, "devDependencies": { + "@types/md5": "^2.3.5", "@types/node": "^20", "@types/qs": "^6.9.11", "@types/react": "^18", @@ -493,6 +496,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/md5": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.5.tgz", + "integrity": "sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw==", + "dev": true + }, "node_modules/@types/node": { "version": "20.8.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", @@ -1240,6 +1249,14 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1350,6 +1367,14 @@ "node": ">= 8" } }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "engines": { + "node": "*" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1435,6 +1460,14 @@ "node": ">=0.4.0" } }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2341,6 +2374,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, "node_modules/get-intrinsic": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", @@ -2578,6 +2619,17 @@ "node": ">= 0.4" } }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -2717,6 +2769,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -2858,6 +2915,11 @@ "node": ">=8" } }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -3151,6 +3213,11 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3173,6 +3240,16 @@ "node": ">=10" } }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3241,6 +3318,32 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mysql2": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.7.tgz", + "integrity": "sha512-KnJT8vYRcNAZv73uf9zpXqNbvBG7DJrs+1nACsjZP1HMJ1TgXEy8wnNilXAn/5i57JizXKtrUtwDB7HxT9DDpw==", + "dependencies": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "engines": { + "node": ">=16.14" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -3252,6 +3355,25 @@ "thenify-all": "^1.0.0" } }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -4132,6 +4254,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "node_modules/sass": { "version": "1.70.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz", @@ -4172,6 +4299,11 @@ "node": ">=10" } }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, "node_modules/set-function-length": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", @@ -4251,6 +4383,14 @@ "node": ">=0.10.0" } }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", diff --git a/web/package.json b/web/package.json index 44f3f3da..6dee6144 100644 --- a/web/package.json +++ b/web/package.json @@ -15,6 +15,8 @@ "@tabler/icons-react": "^2.45.0", "@tanstack/react-table": "^8.11.7", "axios": "^1.6.8", + "md5": "^2.3.0", + "mysql2": "^3.9.7", "next": "13.5.6", "next-auth": "^4.24.7", "qs": "^6.11.2", @@ -23,6 +25,7 @@ "swiper": "^11.0.5" }, "devDependencies": { + "@types/md5": "^2.3.5", "@types/node": "^20", "@types/qs": "^6.9.11", "@types/react": "^18", diff --git a/web/src/app/api/auth/[...nextauth]/route.ts b/web/src/app/api/auth/[...nextauth]/route.ts index b4de15f2..228b250d 100644 --- a/web/src/app/api/auth/[...nextauth]/route.ts +++ b/web/src/app/api/auth/[...nextauth]/route.ts @@ -1,6 +1,9 @@ import CredentialsProvider from "next-auth/providers/credentials"; import NextAuth from "next-auth/next"; -import { signIn } from "@/lib/strapi/auth"; +import { JWT } from "next-auth/jwt"; +import { Session, User } from "next-auth"; +import { signIn, signUp } from "@/lib/auth/strapi"; +import { findUserByEmail, verifyPassword } from "@/lib/auth/legacy_web"; import { StrapiSignInResponse } from "@/lib/types"; const authOptions = { @@ -13,13 +16,27 @@ const authOptions = { password: { label: "Password", type: "password" }, }, async authorize(credentials) { - console.log("heee"); try { if (credentials?.email == null || credentials.password == null) return null; const strapiResponse: StrapiSignInResponse = await signIn(credentials.email, credentials.password); - if (strapiResponse.error) { + if (strapiResponse === null || strapiResponse.error) { + // if strapi cannot authenticate + // look if user is to migrate + const potentialUserForMigration = await findUserByEmail(credentials.email); + const isToMigrate = potentialUserForMigration && verifyPassword(credentials.password, potentialUserForMigration.password); + + if (isToMigrate) { + const migrationResponse = await signUp(potentialUserForMigration.user_name, potentialUserForMigration.email, credentials.password, "internal"); + + return { + jwt: migrationResponse.jwt, + id: String(migrationResponse.user.id), + email: migrationResponse.user.email, + name: migrationResponse.user.username, + }; + } return null; } @@ -29,20 +46,20 @@ const authOptions = { email: strapiResponse.user.email, name: strapiResponse.user.username, }; - } catch (e) { - console.log(e); + } catch { return null; } }, }), ], callbacks: { - session: async ({ session, token }: { session: any; token: any }) => { - session.id = token.id; - session.jwt = token.jwt; + session: async ({ session, token }: { session: Session; token: JWT }) => { + session.id = token.id as string; + session.jwt = token.jwt as string; + return session; }, - jwt: async ({ token, user }: { token: any; user: any }) => { + jwt: async ({ token, user }: { token: JWT; user: User }) => { if (user) { token.id = user.id; token.jwt = user.jwt; diff --git a/web/src/app/my-account/page.tsx b/web/src/app/my-account/page.tsx new file mode 100644 index 00000000..68c750b3 --- /dev/null +++ b/web/src/app/my-account/page.tsx @@ -0,0 +1,71 @@ +"use client"; +import { ChangeEvent, FormEvent, useState } from "react"; +import { signIn, signOut, useSession } from "next-auth/react"; +import { getMailValidation } from "@/helpers/validators"; +import Input from "@/components/Inputs/TextInput"; + +type LoginFormData = { + email: string; + password: string; +}; + +export default function MyAccount() { + const { data: session } = useSession(); + const [formData, setFormData] = useState({ + email: "", + password: "", + }); + + const [errorMessage, setErrorMessage] = useState(""); + + const handleInputChange = (e: ChangeEvent) => { + const { name, value } = e.target; + setFormData(prevFormData => ({ ...prevFormData, [name]: value })); + }; + + return ( +
+

My Account

+
+ {session && } + {session?.user == null && ( +
) => { + e.preventDefault(); + try { + const res = await signIn("credentials", { email: formData.email, password: formData.password, redirect: false }); + if (res?.error) throw res.error; + else setErrorMessage(""); + } catch { + setErrorMessage("Invalid email or password"); + } + }} + > + getMailValidation(value)} + /> + + +
+ )} +
+ {errorMessage != "" &&

{errorMessage}

} +

Please note

+ {session?.user &&

{session.user.name}

} +

+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel est adipisci quas, aperiam voluptas, omnis tempora blanditiis quae fuga eum ullam + commodi a perspiciatis provident pariatur sunt excepturi doloremque! Commodi! +

+
+
+
+ ); +} diff --git a/web/src/app/registration/page.tsx b/web/src/app/registration/page.tsx index deeabb7b..91e2085d 100644 --- a/web/src/app/registration/page.tsx +++ b/web/src/app/registration/page.tsx @@ -1,9 +1,9 @@ "use client"; import { ChangeEvent, FormEvent, useState } from "react"; +import { signIn, useSession } from "next-auth/react"; +import { signUp } from "@/lib/auth/strapi"; import { getMailValidation } from "@/helpers/validators"; import Input from "@/components/Inputs/TextInput"; -import { signUp, signUpApi } from "@/lib/strapi/auth"; -import { signIn, useSession } from "next-auth/react"; type RegistrationFormData = { username: string; @@ -45,17 +45,12 @@ export default function Registration() { className="flex flex-col items-stretch gap-4" onSubmit={async (e: FormEvent) => { e.preventDefault(); - console.log("submit"); - console.log("err"); const registerresp = await signUp(formData.username, formData.email, formData.password); if (registerresp.error) { - console.log(registerresp.error.message); setErrorMessage(registerresp.error.message); return; } - console.log(registerresp); - const res = await signIn("credentials", { email: formData.email, password: formData.password, redirect: false }); - console.log(res); + await signIn("credentials", { email: formData.email, password: formData.password, redirect: false }); }} > diff --git a/web/src/components/Layout/Navigation/Navigation.tsx b/web/src/components/Layout/Navigation/Navigation.tsx index 77c0f8fd..dbee41f1 100644 --- a/web/src/components/Layout/Navigation/Navigation.tsx +++ b/web/src/components/Layout/Navigation/Navigation.tsx @@ -1,7 +1,7 @@ "use client"; import Link from "next/link"; import Image from "next/image"; -import { signIn, useSession, signOut } from "next-auth/react"; +import { useSession } from "next-auth/react"; import { IconUserCircle } from "@tabler/icons-react"; type NavigationProps = { @@ -44,10 +44,9 @@ export default function Navigation({ menu }: NavigationProps) {
- {session && } - signIn()}> + - My Account + {session?.user?.name ?

{session.user.name}

:

My Account

}
diff --git a/web/src/config/constants.ts b/web/src/config/constants.ts index fdece9e5..113d67b2 100644 --- a/web/src/config/constants.ts +++ b/web/src/config/constants.ts @@ -1,2 +1,6 @@ export const CMS_PUBLIC_API_URL = process.env.CMS_PUBLIC_API_URL ?? "http://localhost:1337/api"; export const CMS_INTERNAL_API_URL = process.env.CMS_INTERNAL_API_URL ?? "http://cms:1337/api"; +export const DATABASE_HOST = process.env.DATABASE_HOST ?? "db"; +export const DATABASE_USER = process.env.DATABASE_USER ?? "vim"; +export const DATABASE_NAME = process.env.DATABASE_NAME ?? "vim"; +export const DATABASE_PASSWORD = process.env.DATABASE_PASSWORD ?? "super-secret"; diff --git a/web/src/config/db.ts b/web/src/config/db.ts new file mode 100644 index 00000000..db2e00ce --- /dev/null +++ b/web/src/config/db.ts @@ -0,0 +1,9 @@ +import * as mysql from "mysql2"; +import { DATABASE_HOST, DATABASE_NAME, DATABASE_PASSWORD, DATABASE_USER } from "./constants"; + +export const dbConnection = mysql.createConnection({ + host: DATABASE_HOST, + user: DATABASE_USER, + database: DATABASE_NAME, + password: DATABASE_PASSWORD, +}); diff --git a/web/src/lib/auth/legacy_web.ts b/web/src/lib/auth/legacy_web.ts new file mode 100644 index 00000000..aa96da78 --- /dev/null +++ b/web/src/lib/auth/legacy_web.ts @@ -0,0 +1,42 @@ +import md5 from "md5"; +import { dbConnection } from "@/config/db"; +// MD5 Hash is stated to be not secure +// This code has to be deleted after majority of users +// migrated to a secure hashing algorithm +// this is fulfilled when users are registered in strapi + +type LegacyUser = { + user_id: number; + user_name: string; + password: string; + first_name: string; + last_name: string; + email: string; + access?: boolean; + homepage?: string; + sponsor_amount?: number; + sponsor_vote_amount?: number; + sponsor_vote_date?: string; + created: string; +}; + +export const findUserByEmail = (email: string): Promise => { + const sql = "SELECT * FROM `vs_users` WHERE email = ?"; + + return new Promise((resolve, reject) => { + dbConnection.query(sql, [email], function (err, results) { + if (err) { + reject(err); + return; + } + + if ((results as LegacyUser[]).length >= 1) { + resolve((results as LegacyUser[])[0]); + } else { + resolve(null); + } + }); + }); +}; + +export const verifyPassword = (givenPassword: string, legacyHashedPassword: string) => md5(givenPassword) === legacyHashedPassword; diff --git a/web/src/lib/strapi/auth.ts b/web/src/lib/auth/strapi.ts similarity index 76% rename from web/src/lib/strapi/auth.ts rename to web/src/lib/auth/strapi.ts index dccdb51f..161a2696 100644 --- a/web/src/lib/strapi/auth.ts +++ b/web/src/lib/auth/strapi.ts @@ -12,17 +12,16 @@ export const signIn = async (email: string, password: string) => { password: password, }), }); - console.log("signin"); return await response.json(); } catch (e) { - console.log(e); return null; } }; -export const signUp = async (username: string, email: string, password: string) => { +export const signUp = async (username: string, email: string, password: string, mode: "internal" | "public" = "public") => { + const strapiApiUrl = mode == "public" ? CMS_PUBLIC_API_URL : CMS_INTERNAL_API_URL; try { - const response = await fetch(`${CMS_PUBLIC_API_URL}/auth/local/register`, { + const response = await fetch(`${strapiApiUrl}/auth/local/register`, { method: "POST", headers: { "Content-Type": "application/json", @@ -34,12 +33,9 @@ export const signUp = async (username: string, email: string, password: string) password: password, }), }); - console.log(response); return await response.json(); - } catch (e) { - console.log("something went wrong"); - console.log(e); + } catch { return null; } }; diff --git a/web/tsconfig.json b/web/tsconfig.json index 1bf25398..d0797f33 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -22,6 +22,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "./types/next-auth.d.ts", "types/**/*"], "exclude": ["node_modules"] } diff --git a/web/types/next-auth.d.ts b/web/types/next-auth.d.ts new file mode 100644 index 00000000..d142d582 --- /dev/null +++ b/web/types/next-auth.d.ts @@ -0,0 +1,15 @@ +import "next-auth"; + +declare module "next-auth" { + interface User { + id: string; + email: string; + name: string; + jwt: JWT; + } + + interface Session extends DefaultSession { + id: string; + jwt: string; + } +}