From ff89cbfceabad47178531956cfd2cead48a6c39f Mon Sep 17 00:00:00 2001 From: latakshsariyapatidar Date: Tue, 12 May 2026 01:52:36 +0530 Subject: [PATCH 1/2] fix(auth): standardize login field to email and fix VITE_API_BASE_URL config --- RestroHub-FrontEnd/package-lock.json | 351 ++++++++++++++++++ RestroHub-FrontEnd/src/pages/public/Login.jsx | 18 +- RestroHub-FrontEnd/src/services/common/api.js | 2 +- .../auth/controller/AuthController.java | 8 +- .../qrmenu/auth/dto/AuthResponse.java | 4 +- .../qrmenu/auth/dto/LoginRequest.java | 8 +- .../qrmenu/auth/service/AuthServiceImpl.java | 14 +- .../security/CustomUserDetailsService.java | 12 +- 8 files changed, 384 insertions(+), 33 deletions(-) diff --git a/RestroHub-FrontEnd/package-lock.json b/RestroHub-FrontEnd/package-lock.json index 9664855f..2e3e30a5 100644 --- a/RestroHub-FrontEnd/package-lock.json +++ b/RestroHub-FrontEnd/package-lock.json @@ -37,6 +37,7 @@ "eslint-plugin-react": "^7.32.0", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.0", + "gh-pages": "^6.3.0", "postcss": "^8.5.6", "tailwindcss": "^3.4.19", "vite": "^7.3.1" @@ -2281,6 +2282,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -2379,6 +2390,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -2801,6 +2819,13 @@ "node": ">= 6" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3153,6 +3178,19 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -3186,6 +3224,13 @@ "dev": true, "license": "ISC" }, + "node_modules/email-addresses": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", + "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-abstract": { "version": "1.24.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", @@ -3793,6 +3838,34 @@ "node": ">=16.0.0" } }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", + "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.1", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -3806,6 +3879,24 @@ "node": ">=8" } }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -3961,6 +4052,21 @@ } } }, + "node_modules/fs-extra": { + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -4091,6 +4197,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gh-pages": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", + "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^3.2.4", + "commander": "^13.0.0", + "email-addresses": "^5.0.0", + "filenamify": "^4.3.0", + "find-cache-dir": "^3.3.1", + "fs-extra": "^11.1.1", + "globby": "^11.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gh-pages/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4134,6 +4273,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glsl-noise": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz", @@ -4160,6 +4320,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -4913,6 +5080,19 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -5081,6 +5261,22 @@ "three": ">=0.134.0" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5444,6 +5640,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5483,6 +5689,16 @@ "dev": true, "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5523,6 +5739,75 @@ "node": ">= 6" } }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -6468,6 +6753,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6626,6 +6921,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/sucrase": { "version": "3.35.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", @@ -6860,6 +7178,29 @@ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", "license": "MIT" }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/trim-repeated/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/troika-three-text": { "version": "0.52.4", "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz", @@ -7057,6 +7398,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", diff --git a/RestroHub-FrontEnd/src/pages/public/Login.jsx b/RestroHub-FrontEnd/src/pages/public/Login.jsx index 9190a44c..7fa7f379 100644 --- a/RestroHub-FrontEnd/src/pages/public/Login.jsx +++ b/RestroHub-FrontEnd/src/pages/public/Login.jsx @@ -12,7 +12,7 @@ const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || "http://localhost:5000/api"; const validationSchema = Yup.object({ - username: Yup.string().required("Email or username is required"), + email: Yup.string().email("Invalid email address").required("Email is required"), password: Yup.string() .min(6, "Password must be at least 6 characters") .required("Password is required"), @@ -179,7 +179,7 @@ const Login = () => { } } catch (err) { toast.error( - err.response?.data?.message || "Invalid username or password" + err.response?.data?.message || "Invalid email or password" ); } finally { setIsLoading(false); @@ -253,15 +253,15 @@ const Login = () => { Email
- diff --git a/RestroHub-FrontEnd/src/services/common/api.js b/RestroHub-FrontEnd/src/services/common/api.js index ee4c9f77..a23e6e3a 100644 --- a/RestroHub-FrontEnd/src/services/common/api.js +++ b/RestroHub-FrontEnd/src/services/common/api.js @@ -1,7 +1,7 @@ import axios from "axios"; const api = axios.create({ - baseURL: import.meta.env.API_BASE_URL || "http://localhost:8181/restroly", + baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:8181/restroly", }); // Add interceptor diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/auth/controller/AuthController.java b/RestroHub/src/main/java/com/restroly/qrmenu/auth/controller/AuthController.java index fe7bacd1..3bcf1c1d 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/auth/controller/AuthController.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/auth/controller/AuthController.java @@ -56,7 +56,7 @@ public class AuthController { "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "tokenType": "Bearer", "expiresIn": 86400, - "username": "admin", + "email": "admin@restroly.com", "roles": ["ROLE_ADMIN"] }, "timestamp": "2024-01-15T10:30:00" @@ -82,7 +82,7 @@ public class AuthController { { "status": 401, "error": "UNAUTHORIZED", - "message": "Invalid username or password", + "message": "Invalid email or password", "path": "/api/v1/auth/login", "timestamp": "2024-01-15T10:30:00", "traceId": "abc123" @@ -99,7 +99,7 @@ public class AuthController { schema = @Schema(implementation = LoginRequest.class), examples = @ExampleObject(value = """ { - "username": "admin", + "email": "admin@restroly.com", "password": "admin123" } """) @@ -108,7 +108,7 @@ public class AuthController { public ResponseEntity> login( @Valid @RequestBody LoginRequest loginRequest) { - log.info("Login request received for user: {}", loginRequest.getUsername()); + log.info("Login request received for user: {}", loginRequest.getEmail()); AuthResponse authResponse = authService.login(loginRequest); diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/AuthResponse.java b/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/AuthResponse.java index cc13d913..aa77b5db 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/AuthResponse.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/AuthResponse.java @@ -28,8 +28,8 @@ public class AuthResponse { @Schema(description = "Token expiration time in seconds", example = "86400") private Long expiresIn; - @Schema(description = "Username of authenticated user", example = "admin") - private String username; + @Schema(description = "Email of authenticated user", example = "admin@restroly.com") + private String email; @Schema(description = "User roles", example = "[\"ROLE_ADMIN\"]") private List roles; diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/LoginRequest.java b/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/LoginRequest.java index f5f902c7..a4c52f38 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/LoginRequest.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/auth/dto/LoginRequest.java @@ -12,10 +12,10 @@ @Schema(description = "Login request payload") public class LoginRequest { - @NotBlank(message = "Username is required") - @Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters") - @Schema(description = "Username", example = "admin", requiredMode = Schema.RequiredMode.REQUIRED) - private String username; + @NotBlank(message = "Email is required") + @jakarta.validation.constraints.Email(message = "Invalid email format") + @Schema(description = "Email", example = "admin@restroly.com", requiredMode = Schema.RequiredMode.REQUIRED) + private String email; @NotBlank(message = "Password is required") @Size(min = 6, max = 100, message = "Password must be between 6 and 100 characters") diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/auth/service/AuthServiceImpl.java b/RestroHub/src/main/java/com/restroly/qrmenu/auth/service/AuthServiceImpl.java index 4928eafa..215492c0 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/auth/service/AuthServiceImpl.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/auth/service/AuthServiceImpl.java @@ -32,12 +32,12 @@ public class AuthServiceImpl implements AuthService { @Override public AuthResponse login(LoginRequest loginRequest) { - log.info("Login attempt for user: {}", loginRequest.getUsername()); + log.info("Login attempt for user: {}", loginRequest.getEmail()); try { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( - loginRequest.getUsername(), + loginRequest.getEmail(), loginRequest.getPassword() ) ); @@ -52,22 +52,22 @@ public AuthResponse login(LoginRequest loginRequest) { .map(GrantedAuthority::getAuthority) .collect(Collectors.toList()); - log.info("User {} logged in successfully", loginRequest.getUsername()); + log.info("User {} logged in successfully", loginRequest.getEmail()); return AuthResponse.builder() .accessToken(accessToken) .refreshToken(refreshToken) .tokenType("Bearer") .expiresIn(jwtTokenProvider.getExpirationInSeconds()) - .username(userDetails.getUsername()) + .email(userDetails.getUsername()) .roles(roles) .build(); } catch (BadCredentialsException ex) { - log.warn("Failed login attempt for user: {}", loginRequest.getUsername()); + log.warn("Failed login attempt for user: {}", loginRequest.getEmail()); throw new BadCredentialsException("Invalid username or password"); } catch (AuthenticationException ex) { - log.error("Authentication error for user {}: {}", loginRequest.getUsername(), ex.getMessage()); + log.error("Authentication error for user {}: {}", loginRequest.getEmail(), ex.getMessage()); throw new BusinessException("Authentication failed: " + ex.getMessage()); } } @@ -102,7 +102,7 @@ public AuthResponse refreshToken(RefreshTokenRequest refreshTokenRequest) { .refreshToken(newRefreshToken) .tokenType("Bearer") .expiresIn(jwtTokenProvider.getExpirationInSeconds()) - .username(username) + .email(username) .roles(roles) .build(); } diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java b/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java index 64bcdc71..cd3936ee 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java @@ -28,8 +28,8 @@ public class CustomUserDetailsService implements UserDetailsService { public void init() { // Create sample users for testing // Password: admin123 - users.put("admin", User.builder() - .username("admin") + users.put("admin@restroly.com", User.builder() + .username("admin@restroly.com") .password(passwordEncoder.encode("admin123")) .authorities(List.of( new SimpleGrantedAuthority("ROLE_ADMIN"), @@ -38,8 +38,8 @@ public void init() { .build()); // Password: owner123 - users.put("restaurant_owner", User.builder() - .username("restaurant_owner") + users.put("owner@restroly.com", User.builder() + .username("owner@restroly.com") .password(passwordEncoder.encode("owner123")) .authorities(List.of( new SimpleGrantedAuthority("ROLE_RESTAURANT_OWNER"), @@ -48,8 +48,8 @@ public void init() { .build()); // Password: user123 - users.put("user", User.builder() - .username("user") + users.put("user@restroly.com", User.builder() + .username("user@restroly.com") .password(passwordEncoder.encode("user123")) .authorities(List.of( new SimpleGrantedAuthority("ROLE_USER") From 889de50d725589f6d74fda04b81159e327cbf9d0 Mon Sep 17 00:00:00 2001 From: latakshsariyapatidar Date: Tue, 12 May 2026 13:05:18 +0530 Subject: [PATCH 2/2] fix(auth): verify CustomUserDetailsService loads credentials dynamically from DB --- .../src/services/public/ApiService.js | 2 +- .../qrmenu/config/DataInitializer.java | 69 ++++++++++++++++ .../security/CustomUserDetailsService.java | 80 ++++++------------- 3 files changed, 95 insertions(+), 56 deletions(-) create mode 100644 RestroHub/src/main/java/com/restroly/qrmenu/config/DataInitializer.java diff --git a/RestroHub-FrontEnd/src/services/public/ApiService.js b/RestroHub-FrontEnd/src/services/public/ApiService.js index a09f061e..09787c45 100644 --- a/RestroHub-FrontEnd/src/services/public/ApiService.js +++ b/RestroHub-FrontEnd/src/services/public/ApiService.js @@ -3,7 +3,7 @@ // Handles all API calls for the application // ============================================ -const API_BASE_URL = 'http://localhost:8181/restroly'; +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8181/restroly'; // Helper function for making API requests const apiRequest = async (endpoint, options = {}) => { diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/config/DataInitializer.java b/RestroHub/src/main/java/com/restroly/qrmenu/config/DataInitializer.java new file mode 100644 index 00000000..26054886 --- /dev/null +++ b/RestroHub/src/main/java/com/restroly/qrmenu/config/DataInitializer.java @@ -0,0 +1,69 @@ +package com.restroly.qrmenu.config; + +import com.restroly.qrmenu.user.entity.Role; +import com.restroly.qrmenu.user.entity.User; +import com.restroly.qrmenu.user.repository.RoleRepository; +import com.restroly.qrmenu.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; + +@Component +@RequiredArgsConstructor +@Slf4j +public class DataInitializer implements CommandLineRunner { + + private final UserRepository userRepository; + private final RoleRepository roleRepository; + private final PasswordEncoder passwordEncoder; + + @Override + @Transactional + public void run(String... args) { + log.info("Initializing default roles and users..."); + + // Initialize Roles + Role adminRole = createRoleIfNotFound("ROLE_ADMIN", "Administrator role"); + Role userRole = createRoleIfNotFound("ROLE_USER", "Standard user role"); + Role ownerRole = createRoleIfNotFound("ROLE_RESTAURANT_OWNER", "Restaurant owner role"); + + // Initialize Users + createUserIfNotFound("admin@restroly.com", "admin123", "System Admin", Arrays.asList(adminRole, userRole)); + createUserIfNotFound("owner@restroly.com", "owner123", "Restaurant Owner", Arrays.asList(ownerRole, userRole)); + createUserIfNotFound("user@restroly.com", "user123", "Normal User", Arrays.asList(userRole)); + + log.info("Data initialization completed."); + } + + private Role createRoleIfNotFound(String name, String description) { + return roleRepository.findByName(name) + .orElseGet(() -> { + Role role = Role.builder() + .name(name) + .description(description) + .isActive(true) + .build(); + return roleRepository.save(role); + }); + } + + private void createUserIfNotFound(String email, String password, String name, List roles) { + if (!userRepository.existsByEmail(email)) { + User user = User.builder() + .email(email) + .password(passwordEncoder.encode(password)) + .name(name) + .roles(roles) + .isActive(true) + .build(); + userRepository.save(user); + log.info("Created default user: {}", email); + } + } +} diff --git a/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java b/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java index cd3936ee..4b3c6c8e 100644 --- a/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java +++ b/RestroHub/src/main/java/com/restroly/qrmenu/security/CustomUserDetailsService.java @@ -1,77 +1,47 @@ package com.restroly.qrmenu.security; -import jakarta.annotation.PostConstruct; +import com.restroly.qrmenu.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import java.util.stream.Collectors; @Service @Slf4j @RequiredArgsConstructor public class CustomUserDetailsService implements UserDetailsService { - // In-memory user store for demo purposes - // TODO: Replace with actual database-backed implementation - private final Map users = new HashMap<>(); - private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - @PostConstruct - public void init() { - // Create sample users for testing - // Password: admin123 - users.put("admin@restroly.com", User.builder() - .username("admin@restroly.com") - .password(passwordEncoder.encode("admin123")) - .authorities(List.of( - new SimpleGrantedAuthority("ROLE_ADMIN"), - new SimpleGrantedAuthority("ROLE_USER") - )) - .build()); - - // Password: owner123 - users.put("owner@restroly.com", User.builder() - .username("owner@restroly.com") - .password(passwordEncoder.encode("owner123")) - .authorities(List.of( - new SimpleGrantedAuthority("ROLE_RESTAURANT_OWNER"), - new SimpleGrantedAuthority("ROLE_USER") - )) - .build()); - - // Password: user123 - users.put("user@restroly.com", User.builder() - .username("user@restroly.com") - .password(passwordEncoder.encode("user123")) - .authorities(List.of( - new SimpleGrantedAuthority("ROLE_USER") - )) - .build()); - - log.info("Initialized {} sample users for authentication", users.size()); - } + private final UserRepository userRepository; @Override - public UserDetails loadUserByUsername(String username) + public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { - log.debug("Loading user by username: {}", username); - - UserDetails userDetails = users.get(username); - - if (userDetails == null) { - log.warn("User not found: {}", username); - throw new UsernameNotFoundException("User not found: " + username); - } - - log.debug("User found: {} with roles: {}", username, userDetails.getAuthorities()); - return userDetails; + log.debug("Loading user by email: {}", email); + + com.restroly.qrmenu.user.entity.User user = userRepository.findByEmailWithRoles(email) + .orElseThrow(() -> { + log.warn("User not found with email: {}", email); + return new UsernameNotFoundException("User not found with email: " + email); + }); + + List authorities = user.getRoles().stream() + .map(role -> new SimpleGrantedAuthority(role.getName())) + .collect(Collectors.toList()); + + log.debug("User found: {} with roles: {}", email, authorities); + + return org.springframework.security.core.userdetails.User.builder() + .username(user.getEmail()) + .password(user.getPassword()) + .authorities(authorities) + .disabled(!user.isActive()) + .accountLocked(user.isLocked()) + .build(); } }