diff --git a/.gitignore b/.gitignore index 68729d6..c69b04b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea/ -.DS_Store \ No newline at end of file +.DS_Store +package-lock.json \ No newline at end of file diff --git a/backend/controller/user.js b/backend/controller/user.js index 10c31ee..93f2224 100644 --- a/backend/controller/user.js +++ b/backend/controller/user.js @@ -1,5 +1,5 @@ const express = require("express"); -const { login, resetPassword, findUser, getUserList, createUser, getUserDetail, editUser, editMultipleUsers, getUserListByCourse, deleteUser } = require("../service/user"); +const { login, resetUser, findUser, getUserList, createUser, getUserDetail, getUserDetailWithAssets, editUser, editMultipleUsers, getUserListByCourse, deleteUser } = require("../service/user"); const jwt = require('jsonwebtoken'); const {promisify} = require('util'); const userController = express.Router(); @@ -61,10 +61,10 @@ userController.post("/login", } ); -// Reset the password by user id and new password +// Reset user information by user id and new password userController.post("/password", async (req, res) => { - const {user_id, password} = req.body; + const {user_id,firstName,lastName,email, password} = req.body; if (!user_id || !password.length) { res.status(400).send({message: "Invalid user or password."}); return; @@ -73,7 +73,7 @@ userController.post("/password", if(req.cookies.jwt) { res.clearCookie('jwt'); } - const results = await resetPassword(user_id, password); + const results = await resetUser(user_id, firstName, lastName, email, password); res.status(results.code || 200).json(results.data); }) @@ -127,6 +127,15 @@ userController.get("/detail/:userId", } ) +// Query user detailed information and asset list by user id +userController.get("/account/:userId", + async (req, res) => { + const {userId} = req.params; + const results = await getUserDetailWithAssets(userId); + res.status(results.code || 200).json(results.data); + } +) + // Edit user information by user id userController.put("/edit", async (req, res) => { diff --git a/backend/package-lock.json b/backend/package-lock.json index ee732b8..e4c30e5 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -132,6 +132,11 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "connect-multiparty": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/connect-multiparty/-/connect-multiparty-2.2.0.tgz", @@ -192,6 +197,11 @@ "vary": "^1" } }, + "cssfilter": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz", + "integrity": "sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=" + }, "dayjs": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz", @@ -1186,6 +1196,15 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" }, + "xss": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/xss/-/xss-1.0.9.tgz", + "integrity": "sha512-2t7FahYnGJys6DpHLhajusId7R0Pm2yTmuL0GV9+mV0ZlaLSnb2toBmppATfg5sWIhZQGlsTLoecSzya+l4EAQ==", + "requires": { + "commander": "^2.20.3", + "cssfilter": "0.0.10" + } + }, "yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/backend/package.json b/backend/package.json index 34d386f..9ee970b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,7 +21,7 @@ "jsonfile": "^5.0.0", "jsonwebtoken": "^8.5.1", "moment": "^2.29.1", - "mysql2": "^1.7.0", + "mysql2": "^2.3.0", "swagger-ui-express": "^4.1.4", "twilio": "^3.57.0", "util": "^0.12.3", diff --git a/backend/query/asset.js b/backend/query/asset.js index 817bb0d..75d9bfc 100644 --- a/backend/query/asset.js +++ b/backend/query/asset.js @@ -11,6 +11,12 @@ FROM KP_Asset WHERE creator_id = ? OR is_public = TRUE `; +const getUserAssetList = ` +SELECT * +FROM KP_Asset +WHERE creator_id = ? +`; + const getAssetDetail = ` SELECT a.asset_id, a.uuid, a.asset_name, a.description, a.creator_id, @@ -62,6 +68,7 @@ module.exports = { createSessionAsset, deleteSessionAssetBySessionId, deleteSessionAssetByAssetId, - deleteAssetQuery + deleteAssetQuery, + getUserAssetList }; diff --git a/backend/query/user.js b/backend/query/user.js index 8b399c7..07cffd8 100644 --- a/backend/query/user.js +++ b/backend/query/user.js @@ -8,10 +8,10 @@ WHERE email = ? AND password = ?; `; -const resetPassword = ` +const resetUser = ` UPDATE KP_User SET - password = ? + first_name = ?, last_name = ?, email = ?, password = ? WHERE user_id = ?; `; @@ -92,7 +92,7 @@ WHERE user_id = ?; `; module.exports = { login, - resetPassword, + resetUser, findUser, getUserList, createUser, diff --git a/backend/service/user.js b/backend/service/user.js index 23dba7e..36d46c7 100644 --- a/backend/service/user.js +++ b/backend/service/user.js @@ -1,6 +1,7 @@ const pool = require("./index"); const userQuery = require("../query/user"); const courseQuery = require("../query/course"); +const assetQuery = require("../query/asset"); /** * User Login @@ -29,8 +30,8 @@ const login = async (email, password) => { * @param {integer} user_id * @param {string} password */ -const resetPassword = async (user_id, password) => { - const results = await pool.execute(userQuery.resetPassword, [password, user_id]); +const resetUser = async (user_id, firstName, lastName, email, password) => { + const results = await pool.execute(userQuery.resetUser, [firstName, lastName, email, password, user_id]); const success = results[0]; if (!success.changedRows) { return { @@ -126,6 +127,21 @@ const getUserDetail = async userId => { } } +/** + * Get user detailed information and assets by user id + * @param {integer} userId + */ + const getUserDetailWithAssets = async userId => { + const results = await pool.execute(userQuery.getUserDetail, [userId]); + const user = results[0][0]; + const assetResults = await pool.execute(assetQuery.getUserAssetList, [userId]); + const assetList = assetResults[0]; + + return { + data: {...user, assetList} + } +} + /** * Edit user by user id * @param {string} lastName @@ -238,11 +254,12 @@ const deleteUser = async({userId}) => { } module.exports = { login, - resetPassword, + resetUser, findUser, getUserList, createUser, getUserDetail, + getUserDetailWithAssets, editUser, editMultipleUsers, getUserListByCourse, diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 13bda18..5ecef1c 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -17053,6 +17053,11 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "vee-validate": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-3.4.13.tgz", + "integrity": "sha512-ONnyRixpd0/JOGLuN8dlxFwLoT5FGq5ti1w4rx/zFZWaJZ1EefhfAbXkQvLwLhjU6izkfHyITXojW/7InOU3Tw==" + }, "vendors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 6366d92..59a94d3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "socket.io-client": "^2.3.0", "three": "^0.116.1", "uuid": "^7.0.2", + "vee-validate": "^3.4.13", "vue": "2.6.10", "vue-apexcharts": "^1.5.2", "vue-clickaway": "2.2.2", diff --git a/frontend/src/components/Layout/SideBar.vue b/frontend/src/components/Layout/SideBar.vue index 57d2735..e41b933 100644 --- a/frontend/src/components/Layout/SideBar.vue +++ b/frontend/src/components/Layout/SideBar.vue @@ -10,14 +10,8 @@ - + {{ `${user.firstName} ${user.lastName}` }} - - mdi-account-edit-outline - {{ user.email }} @@ -77,9 +71,9 @@ export default { this.showCourses = !this.showCourses; this.showSideBarCourseList = !this.showSideBarCourseList; }, - goToAccountPage() { + goToProfilePage() { this.$router.push({ - name: "Account" + name: "UserProfilePage" }); } } diff --git a/frontend/src/pages/Account/ResetPassword.vue b/frontend/src/pages/Account/ResetPassword.vue deleted file mode 100644 index 395ec3e..0000000 --- a/frontend/src/pages/Account/ResetPassword.vue +++ /dev/null @@ -1,102 +0,0 @@ - - - diff --git a/frontend/src/pages/Account/ResetUser.vue b/frontend/src/pages/Account/ResetUser.vue new file mode 100644 index 0000000..b8e1489 --- /dev/null +++ b/frontend/src/pages/Account/ResetUser.vue @@ -0,0 +1,185 @@ + + + diff --git a/frontend/src/pages/Landing/Landing.vue b/frontend/src/pages/Landing/Landing.vue index 3f3e32c..4b041b9 100644 --- a/frontend/src/pages/Landing/Landing.vue +++ b/frontend/src/pages/Landing/Landing.vue @@ -39,21 +39,6 @@ - - - - - diff --git a/frontend/src/pages/Landing/LandingCourseCard.vue b/frontend/src/pages/Landing/LandingCourseCard.vue index 3fb815c..6eeaf25 100644 --- a/frontend/src/pages/Landing/LandingCourseCard.vue +++ b/frontend/src/pages/Landing/LandingCourseCard.vue @@ -9,12 +9,6 @@
{{ course.department }}

{{ `Instructor: ${course.instructorName}` }}

- - - mdi-plus - New Lab - -
diff --git a/frontend/src/pages/UserProfile/UserProfile.vue b/frontend/src/pages/UserProfile/UserProfile.vue new file mode 100644 index 0000000..13837f5 --- /dev/null +++ b/frontend/src/pages/UserProfile/UserProfile.vue @@ -0,0 +1,139 @@ + + + \ No newline at end of file diff --git a/frontend/src/requests/auth.js b/frontend/src/requests/auth.js index 8f9475f..c25cb35 100644 --- a/frontend/src/requests/auth.js +++ b/frontend/src/requests/auth.js @@ -9,7 +9,7 @@ export const login = params => { }; // Reset the password -export const resetPassword = params => { +export const resetUser = params => { return baseRequest.post( "/users/password", params @@ -62,6 +62,14 @@ export const getUserDetail = params => { ) }; +// Get the user details and asset list by user id +export const getUserDetailWithAssets = params => { + const { userId } = params; + return baseRequest.get( + `/users/account/${userId}` + ) +}; + // Edit multiple users export const editMultipleUsers = params => { return baseRequest.put( diff --git a/frontend/src/routes/routes.js b/frontend/src/routes/routes.js index 462f20f..6d4b6f1 100644 --- a/frontend/src/routes/routes.js +++ b/frontend/src/routes/routes.js @@ -10,7 +10,7 @@ import LabEdit from "../pages/LabEdit/LabEdit"; import LabDetail from "../pages/LabDetail/LabDetail"; import Metric from "../pages/Metric/Metric"; import Assets from "../pages/Assets.vue"; -import ResetPassword from "../pages/Account/ResetPassword"; +import resetUser from "../pages/Account/ResetUser"; import About from "../pages/About.vue"; import Admin from "../pages/Admin/Admin.vue"; import UserCreate from "../pages/UserCreate/UserCreate.vue"; @@ -19,6 +19,7 @@ import MultipleUsersEdit from "../pages/MultipleUsersEdit/MultipleUsersEdit.vue" import CourseCreate from "../pages/CourseCreate/CourseCreate.vue"; import CourseEdit from "../pages/CourseEdit/CourseEdit.vue"; import MultipleCoursesEdit from "../pages/MultipleCoursesEdit/MultipleCoursesEdit.vue"; +import UserProfilePage from "../pages/UserProfile/UserProfile.vue"; const routes = [ // User login { @@ -203,13 +204,22 @@ const routes = [ // } // }, { - path: "account", + path: "/account/reset", name: "Account", - component: ResetPassword, + component: resetUser, + meta: { + requireLogin: true + }, + }, + // User Profile page + { + path: "/account", + name: "UserProfilePage", + component: UserProfilePage, meta: { requireLogin: true } - } + }, ] } ];