diff --git a/BackendFolder/SwitchRoom/build.gradle b/BackendFolder/SwitchRoom/build.gradle index 836672e13e795c70b9e74f64ed9616578613e3ce..a3f7dc73433ec197c4b74c675d611b87dc3530ce 100644 --- a/BackendFolder/SwitchRoom/build.gradle +++ b/BackendFolder/SwitchRoom/build.gradle @@ -20,10 +20,16 @@ repositories { dependencies { //implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' + implementation 'org.springframework:spring-context-support:5.3.23' implementation 'mysql:mysql-connector-java:8.0.30' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' implementation 'org.springframework.boot:spring-boot-starter-web' +// implementation 'org.springframework.boot:spring-boot-starter-security' +// implementation 'org.springframework.security:spring-security-test' +// implementation 'org.springframework.security:spring-security-core:5.7.3' +// implementation 'org.springframework.security.core.userdetails' + implementation 'org.springframework.boot:spring-boot-starter-mail:2.7.5' implementation 'io.jsonwebtoken:jjwt:0.9.1' implementation 'org.springframework.session:spring-session-core' annotationProcessor 'io.jsonwebtoken:jjwt:0.9.1' diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java index f6fb157f2391b6e0ecdaf7c7f02b5ea9b208bafc..3b6d2f02fc48768bcc2177cc5197a80ad6ba406f 100644 --- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java +++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/controllers/UserController.java @@ -4,15 +4,22 @@ import com.fasterxml.jackson.core.JsonProcessingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.repository.query.Param; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import vt.CS5934.SwitchRoom.models.ResponseModel; import vt.CS5934.SwitchRoom.models.UserModel; import vt.CS5934.SwitchRoom.services.Token; import vt.CS5934.SwitchRoom.services.UserService; +import vt.CS5934.SwitchRoom.utility.UsefulTools; +import javax.mail.MessagingException; import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.UnsupportedEncodingException; +import java.net.URI; import java.security.NoSuchAlgorithmException; /** @@ -150,4 +157,85 @@ public class UserController { response = userService.getProfile(userId); return response; } + + @PostMapping("/forgotPassword") + public ResponseModel processForgotPassword( + HttpServletRequest request, + @RequestBody String payload + ) throws MessagingException, UnsupportedEncodingException, JsonProcessingException { + ResponseModel response = new ResponseModel(); + boolean result = userService.updateResetPasswordToken(payload, request); + + if (result) { + response.setStatus(HttpStatus.OK); + response.setMessage("We have sent a reset password link to your email. Please check."); + } else { + response.setMessage("Couldn't find an account matching the email you entered"); + response.setStatus(HttpStatus.FORBIDDEN); + } + + return response; + } + + @GetMapping("/forgotPassword_verify") + public ResponseEntity<Void> showResetPasswordForm( + @Param(value = "token") String token, + HttpServletRequest request, + HttpServletResponse servletResponse + ) { + UserModel existUser = userService.getByResetPasswordToken(token); + String baseURL = UsefulTools.getSiteURL(request); + + // deployed +// if (existUser != null) { +// return ResponseEntity.status(HttpStatus.FOUND) +// .location(URI.create(baseURL + "/forgotPasswordForm")) +// .build(); +// } else { +// return ResponseEntity.status(HttpStatus.FOUND) +// .location(URI.create(baseURL)) +// .build(); +// } + + // development + if (existUser != null) { + Cookie theCookie = new Cookie("resetToken", token); + theCookie.setHttpOnly(false); + theCookie.setSecure(false); + theCookie.setPath("/"); + theCookie.setMaxAge(60*60); // 1 hour + servletResponse.addCookie(theCookie); + return ResponseEntity.status(HttpStatus.FOUND) + .location(URI.create("http://localhost:8080/forgotPasswordForm")) + .build(); + } else { + return ResponseEntity.status(HttpStatus.FOUND) + .location(URI.create("http://localhost:8080")) + .build(); + } + } + + @PostMapping("/forgotPasswordCreateNew") + public ResponseModel forgotPasswordCreateNew( + @CookieValue(value = "resetToken", required = false) String token, + @RequestBody String payload) throws JsonProcessingException, NoSuchAlgorithmException { + ResponseModel response = new ResponseModel(); + + if (token == null) { + response.setMessage("Login session expired or invalid"); + response.setStatus(HttpStatus.FORBIDDEN); + return response; + } + + boolean result = userService.forgotPasswordCreateNew(token, payload); + if (result) { + response.setMessage("Successfully reset your password"); + response.setStatus(HttpStatus.OK); + } else { + response.setMessage("Couldn't find an account matching your login session"); + response.setStatus(HttpStatus.FORBIDDEN); + } + + return response; + } } diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java index 1e95cfc1a8f165e633924379e09e09d4e01d0b5a..75910aa78c1d3323346f820d533c82aeb2c0e795 100644 --- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java +++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/models/UserModel.java @@ -39,9 +39,22 @@ public class UserModel { @Column(name="gender") private String gender; + + @Column(name="token") private String token; - public UserModel(String name, String password, String email, String firstname, String lastname, String gender, String token) { + @Column(name="reset_password_token") + private String resetPasswordToken; + + public UserModel( + String name, + String password, + String email, + String firstname, + String lastname, + String gender, + String token, + String resetPasswordToken) { this.username = name; this.password = password; this.email = email; @@ -49,6 +62,7 @@ public class UserModel { this.lastname = lastname; this.gender = gender; this.token = token; + this.resetPasswordToken = resetPasswordToken; } @Override @@ -62,6 +76,7 @@ public class UserModel { ", lastname='" + lastname + '\'' + ", gender='" + gender + '\'' + ", token='" + token + '\'' + + ", resetPasswordToken='" + resetPasswordToken + '\'' + '}'; } diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java index a57cb14b937ab5511d02dfa7c04891ea8206cdfd..84743b5a320fd86c6472a0965a5b3c2853273de4 100644 --- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java +++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/repositories/UserRepository.java @@ -24,6 +24,10 @@ public interface UserRepository extends JpaRepository<UserModel, Integer> { UserModel findByUsername(String username); + UserModel findByEmail(String email); + + UserModel findByResetPasswordToken(String token); + List<UserModel> findAll(); void deleteByUserId(Long userId); diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java index 50032ddb4efc8eced728087bffa8caf98b7e658c..a18e76906a062494723cc4a705d92c64f58ad03a 100644 --- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java +++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/services/UserService.java @@ -7,19 +7,30 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import vt.CS5934.SwitchRoom.hash.SHAModel; import vt.CS5934.SwitchRoom.models.ExampleModel; import vt.CS5934.SwitchRoom.models.ResponseModel; import vt.CS5934.SwitchRoom.models.UserModel; import vt.CS5934.SwitchRoom.repositories.UserRepository; +import vt.CS5934.SwitchRoom.utility.UsefulTools; +import javax.mail.MessagingException; +import javax.mail.internet.MimeMessage; +import javax.servlet.http.HttpServletRequest; import javax.transaction.Transactional; +import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.springframework.mail.javamail.JavaMailSender; +import vt.CS5934.SwitchRoom.utility.UsefulTools; + + @Service public class UserService { @@ -35,6 +46,8 @@ public class UserService { * It usually uses on Repository class, Service class, or some globe object in the class. */ @Autowired + private JavaMailSender mailSender; + @Autowired UserRepository userRepository; public UserService() throws NoSuchAlgorithmException { @@ -42,7 +55,7 @@ public class UserService { public UserModel addUserToDB(String username, String password, String email, String firstname, String lastname, String gender){ logger.info("Reached addNewExampleModelToDB()"); - UserModel newUser = new UserModel(username, password, email, firstname, lastname, gender, null); + UserModel newUser = new UserModel(username, password, email, firstname, lastname, gender, null, null); userRepository.save(newUser); return newUser; } @@ -138,4 +151,70 @@ public class UserService { return response; } + + public boolean updateResetPasswordToken(String payload, HttpServletRequest request) throws MessagingException, UnsupportedEncodingException, JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + String email = mapper.readTree(payload) + .get("email") + .asText(); + UserModel existUser = userRepository.findByEmail(email); + if (existUser != null) { + String token = Token.of(existUser.getUserId(), 10L, "secret").getToken(); + existUser.setResetPasswordToken(token); + userRepository.save(existUser); + String resetPasswordLink = UsefulTools.getSiteURL(request) + "/user/forgotPassword_verify?token=" + token; + sendEmail(email, resetPasswordLink, existUser.getUsername()); + return true; + } else { + logger.warn("checkLoginSession: FORBIDDEN (user not found)"); + return false; + } + } + + public void sendEmail(String recipientEmail, String link, String username) + throws MessagingException, UnsupportedEncodingException { + MimeMessage message = mailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(message); + + helper.setFrom("switchroomvt@gmail.com", "Switch Room Support"); + helper.setTo(recipientEmail); + + String subject = "(Switch Room Support) Here's the link to reset your password"; + + String content = "<p>Hello, " + username + "</p>" + + "<p>You have requested to reset your password.</p>" + + "<p>Click the link below to change your password:</p>" + + "<p><a href=\"" + link + "\">Change my password</a></p>" + + "<br>" + + "<p>Ignore this email if you do remember your password, " + + "or you have not made the request.</p>"; + + helper.setSubject(subject); + + helper.setText(content, true); + + mailSender.send(message); + } + + public UserModel getByResetPasswordToken(String token) { + return userRepository.findByResetPasswordToken(token); + } + + public boolean forgotPasswordCreateNew(String token, String payload) throws NoSuchAlgorithmException, JsonProcessingException { + UserModel existUser = getByResetPasswordToken(token); + if (existUser != null) { + ObjectMapper mapper = new ObjectMapper(); + String password = mapper.readTree(payload) + .get("password") + .asText(); + String encodedPassword = hashPassword(password); + existUser.setPassword(encodedPassword); + + existUser.setResetPasswordToken(null); + userRepository.save(existUser); + return true; + } else { + return false; + } + } } diff --git a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java index d1cba369c510c563e9b7d15fb95a3f2079a830d3..96b8a58d14b46d929cae91154df2d30d8d204158 100644 --- a/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java +++ b/BackendFolder/SwitchRoom/src/main/java/vt/CS5934/SwitchRoom/utility/UsefulTools.java @@ -1,7 +1,13 @@ package vt.CS5934.SwitchRoom.utility; +import javax.servlet.http.HttpServletRequest; import java.text.SimpleDateFormat; public class UsefulTools { public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + + public static String getSiteURL(HttpServletRequest request) { + String siteURL = request.getRequestURL().toString(); + return siteURL.replace(request.getServletPath(), ""); + } } diff --git a/BackendFolder/SwitchRoom/src/main/resources/application.properties b/BackendFolder/SwitchRoom/src/main/resources/application.properties index 45dc0326a2a696d0e43297d4b5fe74f10c457db9..66d7d7b9e0142b321aa2212ce2cdd08469b99bad 100644 --- a/BackendFolder/SwitchRoom/src/main/resources/application.properties +++ b/BackendFolder/SwitchRoom/src/main/resources/application.properties @@ -16,4 +16,14 @@ spring.task.scheduling.pool.size = 1 #SpringBoot Offer Wishlist matching job fields: offer.wishlist.job.gap.seconds = 60 -offer.wishlist.job.init.delay.seconds = 10 \ No newline at end of file +offer.wishlist.job.init.delay.seconds = 10 + +# spring mail +# zognlvyhizugupns +spring.mail.host=smtp.gmail.com +spring.mail.port=587 +spring.mail.username=switchroomvt@gmail.com +spring.mail.password=zognlvyhizugupns +spring.mail.properties.mail.smtp.auth=true +spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.smtp.starttls.required=true \ No newline at end of file diff --git a/FrontendFolder/switch-room/src/components/ForgotPasswordFormPage.vue b/FrontendFolder/switch-room/src/components/ForgotPasswordFormPage.vue new file mode 100644 index 0000000000000000000000000000000000000000..70b4ed4edbdb252762b8a1c3349fe1a45d79a8fe --- /dev/null +++ b/FrontendFolder/switch-room/src/components/ForgotPasswordFormPage.vue @@ -0,0 +1,146 @@ +<template> + <div class="form_wrapper"> + <div class="form_container"> + <div class="title_container"> + <h2>Reset Password</h2> + <div class="underline-title"></div> + </div> + <div class="row clearfix"> + <div class=""> + <form class="form"> + <label for="user-password" style="padding-top: 13px"> + Password + </label> + <input v-model="userInformation.password" id="user-password" class="form-content" type="password" + name="password" required /> + <div class="form-border"></div> + + <label for="user-retypePassword" style="padding-top: 13px"> + Re-type Password + </label> + <input v-model="userInformation.retypePassword" id="user-password" class="form-content" type="password" + name="retypePassword" required /> + <div class="form-border"></div> + + <button id="submit-btn" @click.prevent="onSubmit" type="submit" value="Submit"> + Submit + </button> + </form> + </div> + </div> + </div> + </div> +</template> + +<script setup lang="ts"> +import { ref, reactive } from "vue"; +import * as UserService from "../services/UserService"; +import { useRouter } from "vue-router"; +import { User } from "@/type/types"; +const router = useRouter(); +const userInformation = reactive({ + password: "", + retypePassword: "" +}); + +const onSubmit = async () => { + const userInfo = { + password: userInformation.password, + }; + + if (userInformation.password != userInformation.retypePassword) { + alert( + "Please check the password and retype password, they are not the same" + ); + } else { + const response = await UserService.forgotPasswordCreateNew( + JSON.stringify(userInfo) + ); + alert(response.message) + userInformation.password = "" + userInformation.retypePassword = "" + router.push("/"); + } +}; + +</script> + +<style scoped> +body { + font-family: Verdana, Geneva, sans-serif; + font-size: 14px; + background: #f2f2f2; +} + +.form_wrapper { + justify-content: center; + align-items: center; + display: flex; +} + +.form_container { + background: #fbfbfb; + border-radius: 8px; + box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.65); + height: auto; + width: 30%; + padding: 12px 44px; +} + +.title_container { + font-family: "Raleway Thin", sans-serif; + letter-spacing: 4px; + padding-bottom: 23px; + padding-top: 13px; + text-align: center; +} + +.form { + align-items: left; + display: flex; + flex-direction: column; +} + +.form-content { + background: #fbfbfb; + border: none; + outline: none; + padding-top: 14px; +} + +.form-border { + background: -webkit-linear-gradient(right, #a6f77b, #2ec06f); + height: 1px; + width: 100%; +} + +#submit-btn { + background: -webkit-linear-gradient(right, #a6f77b, #2dbd6e); + border: none; + border-radius: 21px; + box-shadow: 0px 1px 8px #24c64f; + cursor: pointer; + color: white; + font-family: "Raleway SemiBold", sans-serif; + height: 42.3px; + margin: 0 auto; + margin-top: 50px; + transition: 0.25s; + width: 153px; +} + +#submit-btn:hover { + box-shadow: 0px 1px 18px #24c64f; +} + +.underline-title { + background: -webkit-linear-gradient(right, #a6f77b, #2ec06f); + height: 2px; + margin: -1.1rem auto 0 auto; + width: 200px; +} + +.input_field radio_option { + margin-top: 10px; +} +</style> diff --git a/FrontendFolder/switch-room/src/components/ForgotPasswordPage.vue b/FrontendFolder/switch-room/src/components/ForgotPasswordPage.vue new file mode 100644 index 0000000000000000000000000000000000000000..e024a1c2b895f3a1671d4f44b6855ca756fc3b98 --- /dev/null +++ b/FrontendFolder/switch-room/src/components/ForgotPasswordPage.vue @@ -0,0 +1,135 @@ +<template> + <div class="form_wrapper"> + <div class="form_container"> + <div class="title_container"> + <h2>Forgot Password</h2> + <div class="underline-title"></div> + </div> + <div class="row clearfix"> + <div class=""> + <form class="form"> + <label for="user-email" style="padding-top: 13px"> + Email + </label> + <input + v-model="userInformation.email" + id="user-email" + class="form-content" + type="email" + name="email" + required + /> + <div class="form-border"></div> + + <button id="submit-btn" @click.prevent="onSubmit" type="submit" value="Submit"> + Submit + </button> + </form> + </div> + </div> + </div> + </div> +</template> + +<script setup lang="ts"> +import { ref, reactive } from "vue"; +import * as UserService from "../services/UserService"; +import { useRouter } from "vue-router"; +import { User } from "@/type/types"; +const router = useRouter(); +const userInformation = reactive({ + email: "", +}); + +const onSubmit = async () => { + const userInfo = { + email: userInformation.email, + }; + const response = await UserService.forgotPassword( + JSON.stringify(userInfo) + ); + alert(response.message) + userInformation.email = "" +}; + +</script> + +<style scoped> +body { + font-family: Verdana, Geneva, sans-serif; + font-size: 14px; + background: #f2f2f2; +} + +.form_wrapper { + justify-content: center; + align-items: center; + display: flex; +} + +.form_container { + background: #fbfbfb; + border-radius: 8px; + box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.65); + height: auto; + width: 30%; + padding: 12px 44px; +} + +.title_container { + font-family: "Raleway Thin", sans-serif; + letter-spacing: 4px; + padding-bottom: 23px; + padding-top: 13px; + text-align: center; +} + +.form { + align-items: left; + display: flex; + flex-direction: column; +} + +.form-content { + background: #fbfbfb; + border: none; + outline: none; + padding-top: 14px; +} + +.form-border { + background: -webkit-linear-gradient(right, #a6f77b, #2ec06f); + height: 1px; + width: 100%; +} + +#submit-btn { + background: -webkit-linear-gradient(right, #a6f77b, #2dbd6e); + border: none; + border-radius: 21px; + box-shadow: 0px 1px 8px #24c64f; + cursor: pointer; + color: white; + font-family: "Raleway SemiBold", sans-serif; + height: 42.3px; + margin: 0 auto; + margin-top: 50px; + transition: 0.25s; + width: 153px; +} + +#submit-btn:hover { + box-shadow: 0px 1px 18px #24c64f; +} + +.underline-title { + background: -webkit-linear-gradient(right, #a6f77b, #2ec06f); + height: 2px; + margin: -1.1rem auto 0 auto; + width: 200px; +} + +.input_field radio_option { + margin-top: 10px; +} +</style> diff --git a/FrontendFolder/switch-room/src/components/MainPage.vue b/FrontendFolder/switch-room/src/components/MainPage.vue index a105bd70bdb1b20945010f443c43fd66b4a10020..18546f3dc98f71ce2fc2d18caa413386008964b3 100644 --- a/FrontendFolder/switch-room/src/components/MainPage.vue +++ b/FrontendFolder/switch-room/src/components/MainPage.vue @@ -48,9 +48,9 @@ required /> <div class="form-border"></div> - <a href="#"> + <router-link to="/forgotPassword"> <legend id="forgot-pass">Forgot password?</legend> - </a> + </router-link> <button type="button" class="btn btn-primary" @click="handleLogin()"> LOGIN </button> diff --git a/FrontendFolder/switch-room/src/router/index.ts b/FrontendFolder/switch-room/src/router/index.ts index 4ac42f6213ea79c1a4d94c5ec29fe9e4d05ede12..06c70aaac8a32123ee0d4898ddb2236113712094 100644 --- a/FrontendFolder/switch-room/src/router/index.ts +++ b/FrontendFolder/switch-room/src/router/index.ts @@ -1,6 +1,8 @@ import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router"; import HomeView from "../views/HomeView.vue"; import RegisterView from "../views/RegisterView.vue"; +import ForgotPasswordView from "../views/ForgotPasswordView.vue"; +import ForgotPasswordFormView from "../views/ForgotPasswordFormView.vue"; import ResetPasswordView from "../views/ResetPasswordView.vue"; import ProfileView from "../views/ProfileView.vue"; import MatchedView from "../views/MatchedView.vue"; @@ -22,6 +24,23 @@ const routes: Array<RouteRecordRaw> = [ hideHeader: true, }, }, + { + path: "/forgotPassword", + name: "forgotPassword", + meta: { + hideHeader: true, + }, + component: ForgotPasswordView, + }, + { + path: "/forgotPasswordForm", + name: "forgotPasswordForm", + meta: { + requiresAuth: true, + hideHeader: true, + }, + component: ForgotPasswordFormView, + }, { path: "/resetPassword", name: "resetPassword", diff --git a/FrontendFolder/switch-room/src/services/UserService.ts b/FrontendFolder/switch-room/src/services/UserService.ts index 803612967dd6de200f8631a4b942e1c03bb0eb19..1d0d97acefd82c879d3d1b4a275b27e7743b9527 100644 --- a/FrontendFolder/switch-room/src/services/UserService.ts +++ b/FrontendFolder/switch-room/src/services/UserService.ts @@ -19,6 +19,14 @@ function resetPassword(userData: any) { const urlPath = "/resetPassword"; return serverHttpService.Post(baseUrl + urlPath, JSON.parse(userData)); } +function forgotPassword(userData: any) { + const urlPath = "/forgotPassword"; + return serverHttpService.Post(baseUrl + urlPath, JSON.parse(userData)); +} +function forgotPasswordCreateNew(userData: any) { + const urlPath = "/forgotPasswordCreateNew"; + return serverHttpService.Post(baseUrl + urlPath, JSON.parse(userData)); +} function getProfile() { const urlPath = "/profile"; return serverHttpService.Get(baseUrl + urlPath); @@ -29,5 +37,7 @@ export { loginUser, checkLoginSession, resetPassword, - getProfile, + forgotPassword, + forgotPasswordCreateNew, + getProfile }; diff --git a/FrontendFolder/switch-room/src/views/ForgotPasswordFormView.vue b/FrontendFolder/switch-room/src/views/ForgotPasswordFormView.vue new file mode 100644 index 0000000000000000000000000000000000000000..b2e7fb8243c44ffa884e47bf4910d5da5ae9dcfd --- /dev/null +++ b/FrontendFolder/switch-room/src/views/ForgotPasswordFormView.vue @@ -0,0 +1,7 @@ +<template> + <ForgotPasswordForm-Page></ForgotPasswordForm-Page> +</template> + +<script setup lang="ts"> +import ForgotPasswordFormPage from "@/components/ForgotPasswordFormPage.vue"; +</script> diff --git a/FrontendFolder/switch-room/src/views/ForgotPasswordView.vue b/FrontendFolder/switch-room/src/views/ForgotPasswordView.vue new file mode 100644 index 0000000000000000000000000000000000000000..470cbc70189b0e5e80c25308ba15a4b8a6a52d42 --- /dev/null +++ b/FrontendFolder/switch-room/src/views/ForgotPasswordView.vue @@ -0,0 +1,7 @@ +<template> + <ForgotPassword-Page></ForgotPassword-Page> +</template> + +<script setup lang="ts"> +import ForgotPasswordPage from "@/components/ForgotPasswordPage.vue"; +</script>