feat, fix : [FE] user Registration API add, refactoring connected ALL LOGIC

This commit is contained in:
minseokkang
2022-11-15 15:15:35 +09:00
parent 3e647a993b
commit 4a3e39c51e
11 changed files with 191 additions and 69 deletions

View File

@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"assert": "^2.0.0",
"axios": "^1.1.3",
"core-js": "^3.8.3",
"https-browserify": "^1.0.0",
"path": "^0.12.7",
@@ -3490,6 +3491,29 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"node_modules/axios": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
"integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-loader": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz",
@@ -6144,7 +6168,6 @@
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true,
"funding": [
{
"type": "individual",
@@ -9305,6 +9328,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -14564,6 +14592,28 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
},
"axios": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.1.3.tgz",
"integrity": "sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"babel-loader": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz",
@@ -16547,8 +16597,7 @@
"follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"dev": true
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"for-each": {
"version": "0.3.3",
@@ -18830,6 +18879,11 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",

View File

@@ -9,6 +9,7 @@
},
"dependencies": {
"assert": "^2.0.0",
"axios": "^1.1.3",
"core-js": "^3.8.3",
"https-browserify": "^1.0.0",
"path": "^0.12.7",

View File

@@ -29,7 +29,7 @@
<router-link to="/login" class="nav-link" active-class="active">Sign in</router-link>
</li>
<li class="nav-item">
<router-link to="/signup" class="nav-link" active-class="active">Sign up</router-link>
<router-link to="/register" class="nav-link" active-class="active">Sign up</router-link>
</li>
</ul>
</div>

View File

@@ -1,8 +1,9 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router";
import axios from 'axios';
const app = createApp(App);
app.use(router);
app.use(router,axios);
app.mount('#app');

View File

@@ -1,4 +1,4 @@
import { createWebHistory, createRouter } from "vue-router";
import { createWebHashHistory, createRouter } from "vue-router";
const routes = [
{
@@ -7,8 +7,8 @@ const routes = [
component: () => import(/* webpackChunkName "home" */ '@/views/TheHome.vue')
},
{
path: "/setting",
name: "Setting",
path: "/settings",
name: "Settings",
component: () => import(/* webpackChunkName "inputTag" */ '@/views/TheSetting.vue')
},
{
@@ -17,9 +17,9 @@ const routes = [
component: () => import(/* webpackChunkName "inputTag" */ '@/views/TheLogin.vue')
},
{
path: "/signup",
name: "SignUp",
component: () => import(/* webpackChunkName "inputTag" */ '@/views/TheSignUp.vue')
path: "/register",
name: "Register",
component: () => import(/* webpackChunkName "inputTag" */ '@/views/TheRegister.vue')
},
{
path: "/article",
@@ -29,7 +29,7 @@ const routes = [
];
const router = createRouter({
history: createWebHistory(),
history: createWebHashHistory(),
routes,
});

View File

@@ -0,0 +1,99 @@
<template>
<div class="auth-page">
<div class="container page">
<div class="row">
<div class="col-md-6 offset-md-3 col-xs-12">
<h1 class="text-xs-center">Sign up</h1>
<p class="text-xs-center">
<a href="">Have an account?</a>
</p>
<ul class="error-messages" v-if="emailDuplicate">
<li align="left">email has already been taken</li>
</ul>
<ul class="error-messages" v-if="usernameDuplicate">
<li align="left">username has already been taken</li>
</ul>
<form>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" placeholder="Your Name" v-model="username">
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" placeholder="Email" v-model="email">
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="password" placeholder="Password" v-model="password">
</fieldset>
<button @click = "signup" class="btn btn-lg btn-primary pull-xs-right">
Sign up
</button>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from "axios";
import router from "@/router";
export default {
name: "TheRegister.vue",
data() {
return {
emailDuplicate: false,
usernameDuplicate: false,
}
},
methods:{
showEmailUsernameError(){
this.emailDuplicate = true;
this.usernameDuplicate = true
},
showEmailError(){
this.emailDuplicate = true;
this.usernameDuplicate = false;
},
showUsernameError(){
this.usernameDuplicate = true;
this.emailDuplicate = false;
},
signup: function(){
axios.post('http://localhost:8080/api/users',{
user : {
username: this.username,
email: this.email,
password: this.password,
}
})
.then(response => {
window.localStorage.setItem("token",response.data.user.token);
this.emailDuplicate = false;
this.usernameDuplicate = false;
router.push("/");
})
.catch(error =>{
const code = error.response.data.errors.code;
if(code == "DUPLICATE_EMAIL_USERNAME"){
this.showEmailUsernameError();
}else if(code == "DUPLICATE_EMAIL"){
this.showEmailError();
}else if(code == "DUPLICATE_USERNAME"){
this.showUsernameError();
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -1,46 +0,0 @@
<template>
<div class="auth-page">
<div class="container page">
<div class="row">
<div class="col-md-6 offset-md-3 col-xs-12">
<h1 class="text-xs-center">Sign up</h1>
<p class="text-xs-center">
<a href="">Have an account?</a>
</p>
<ul class="error-messages">
<li>That email is already taken</li>
</ul>
<form>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" placeholder="Your Name">
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="text" placeholder="Email">
</fieldset>
<fieldset class="form-group">
<input class="form-control form-control-lg" type="password" placeholder="Password">
</fieldset>
<button class="btn btn-lg btn-primary pull-xs-right">
Sign up
</button>
</form>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "TheSignUp.vue"
}
</script>
<style scoped>
</style>

View File

@@ -13,6 +13,8 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Service
@RequiredArgsConstructor
@Log4j2
@@ -25,9 +27,17 @@ public class UserServiceImpl implements UserService {
private final JwtService jwtService;
public UserResponse signup(UserSignupRequest userSignupRequest) {
if (userRepository.findByEmail(userSignupRequest.getEmail()) != null) {
throw new CustomException(Error.DUPLICATE_USER);
} else {
User findEmail = userRepository.findByEmail(userSignupRequest.getEmail());
Optional<User> findUsername = userRepository.findByUsername(userSignupRequest.getUsername());
if ( findEmail != null && !findUsername.isEmpty()) {
throw new CustomException(Error.DUPLICATE_EMAIL_USERNAME);
}else if(findEmail != null){
throw new CustomException(Error.DUPLICATE_EMAIL);
}else if(!findUsername.isEmpty()){
throw new CustomException(Error.DUPLICATE_USERNAME);
}
else {
return convertUser(userRepository.save(User.builder().
username(userSignupRequest.getUsername()).
email(userSignupRequest.getEmail()).
@@ -67,7 +77,7 @@ public class UserServiceImpl implements UserService {
if(userUpdate.getEmail() != null){
userRepository.findAllByEmail(userUpdate.getEmail())
.stream().filter(found -> !found.getId().equals(userRepository.findById(user.getId())))
.findAny().ifPresent(found -> new CustomException(Error.DUPLICATE_USER));
.findAny().ifPresent(found -> new CustomException(Error.DUPLICATE_EMAIL));
user.changeEmail(userUpdate.getEmail());
}
userUpdate.setId(user.getId());

View File

@@ -5,7 +5,10 @@ import org.springframework.http.HttpStatus;
@Getter
public enum Error {
DUPLICATE_USER("duplicate user", HttpStatus.CONFLICT),
DUPLICATE_EMAIL_USERNAME("duplicate user email, username",HttpStatus.CONFLICT),
DUPLICATE_EMAIL("duplicate user email", HttpStatus.CONFLICT),
DUPLICATE_USERNAME("duplicate user username", HttpStatus.CONFLICT),
SIGNUP_NULL_DATA("request body include null",HttpStatus.BAD_REQUEST),
EMAIL_NULL_OR_INVALID("email is blank or invalid check plz",HttpStatus.BAD_REQUEST),
USER_NOT_FOUND("user not found check your info",HttpStatus.NOT_FOUND),

View File

@@ -75,7 +75,7 @@ class UsersControllerTest {
@MethodSource("validUsers")
@ParameterizedTest(name = "conroller:회원가입 중복 테스트")
void signupDuplicate(UserSignupRequest user) throws Exception {
when(userService.signup(any(UserSignupRequest.class))).thenThrow(new CustomException(Error.DUPLICATE_USER));
when(userService.signup(any(UserSignupRequest.class))).thenThrow(new CustomException(Error.DUPLICATE_EMAIL));
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
@@ -83,7 +83,7 @@ class UsersControllerTest {
.with(csrf())
)
.andExpect(MockMvcResultMatchers.status().isConflict())
.andExpect(MockMvcResultMatchers.jsonPath("$.errors.message", Matchers.equalTo(Error.DUPLICATE_USER.getMessage())));
.andExpect(MockMvcResultMatchers.jsonPath("$.errors.message", Matchers.equalTo(Error.DUPLICATE_EMAIL.getMessage())));
}
@WithMockUser

View File

@@ -87,7 +87,7 @@ class UserServiceImplTest {
.password(requestUser.getPassword())
.build();
when(userRepository.findByEmail(any(String.class))).thenReturn(null).thenThrow(new CustomException(Error.DUPLICATE_USER));
when(userRepository.findByEmail(any(String.class))).thenReturn(null).thenThrow(new CustomException(Error.DUPLICATE_EMAIL));
when(userRepository.save(any(User.class))).thenReturn(user);
userService.signup(requestUser);
}
@@ -178,12 +178,12 @@ class UserServiceImplTest {
when(userRepository.findById(AdditionalMatchers.not(eq(repoUser.getId())))).thenThrow(new CustomException(Error.USER_NOT_FOUND));
// case 2
if(userUpdate.getEmail() != null){
lenient().when(userRepository.findByEmail(eq(repoUser.getEmail()))).thenThrow(new CustomException(Error.DUPLICATE_USER));
lenient().when(userRepository.findByEmail(eq(repoUser.getEmail()))).thenThrow(new CustomException(Error.DUPLICATE_EMAIL));
try{
userService.updateUser(userUpdate,userAuth);
}catch(CustomException e){
assertThat(e.getError().equals(Error.DUPLICATE_USER));
assertThat(e.getError().getMessage().equals(Error.DUPLICATE_USER.getMessage()));
assertThat(e.getError().equals(Error.DUPLICATE_EMAIL));
assertThat(e.getError().getMessage().equals(Error.DUPLICATE_EMAIL.getMessage()));
}
}
// case 1