mirror of
http://git.mhez-qa.uplus.co.kr/hubez/hubez-admin.git
synced 2025-12-07 02:59:22 +09:00
리스크관리 / 유치채널현황 관리 / 채널관리 추가
This commit is contained in:
@@ -37,241 +37,268 @@
|
||||
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
<common-modal ref="commmonModal"></common-modal>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
import api from '../service/api';
|
||||
import tokenSvc from '@/common/token-service';
|
||||
import LoginPopup from '@/components/LoginPopup.vue'
|
||||
//import * as utils from '@/common/utils';
|
||||
import { mapGetters } from 'vuex';
|
||||
import api from '../service/api';
|
||||
import tokenSvc from '@/common/token-service';
|
||||
import LoginPopup from '@/components/LoginPopup.vue'
|
||||
import commonModal from "@/components/modal/commonModal";
|
||||
|
||||
export default {
|
||||
name: 'Params',
|
||||
props: {
|
||||
userId: {
|
||||
type: String,
|
||||
default : ''
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
errors: [],
|
||||
mdn: '01012341234',
|
||||
confirmNum: '',
|
||||
userId: '',
|
||||
isAuthNum: false,
|
||||
isLogin: true,
|
||||
pwd: '',
|
||||
text: '',
|
||||
number: '',
|
||||
timer: null,
|
||||
timeCounter: 180,
|
||||
timerStr: "03:00"
|
||||
};
|
||||
},
|
||||
components: {
|
||||
LoginPopup : LoginPopup
|
||||
},
|
||||
created() {
|
||||
if(!!tokenSvc.getToken()){
|
||||
this.$store.commit("login/isLogin", true);
|
||||
this.$store.commit("login/isAuthChk", true);
|
||||
this.$router.push({ path: '/' });
|
||||
}else{
|
||||
if(!this.getLogin){
|
||||
this.$router.push({ path: '/login' });
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.hubwebUserId) {
|
||||
this.userId = localStorage.hubwebUserId;
|
||||
export default {
|
||||
name: 'Params',
|
||||
props: {
|
||||
userId: {
|
||||
type: String,
|
||||
default : ''
|
||||
}
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
row:{},
|
||||
errors: [],
|
||||
mdn: '',
|
||||
confirmNum: '',
|
||||
userId: '',
|
||||
isAuthNum: false,
|
||||
isLogin: true,
|
||||
pwd: '',
|
||||
text: '',
|
||||
number: '',
|
||||
timer: null,
|
||||
timeCounter: 180,
|
||||
timerStr: "03:00"
|
||||
};
|
||||
},
|
||||
components: {
|
||||
LoginPopup : LoginPopup
|
||||
,commonModal
|
||||
},
|
||||
created() {
|
||||
if(!!tokenSvc.getToken()){
|
||||
this.$store.commit("login/isLogin", true);
|
||||
this.$store.commit("login/isAuthChk", true);
|
||||
this.$router.push({ path: '/' });
|
||||
}else{
|
||||
if(!this.getLogin){
|
||||
this.$router.push({ path: '/login' });
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.hubwebUserId) {
|
||||
this.userId = localStorage.hubwebUserId;
|
||||
}
|
||||
this.isLogin = this.getLogin;
|
||||
this.pwd = this.getPwd;
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
getLogin: 'login/isLogin',
|
||||
getErrorPage: 'login/isErrorPage',
|
||||
getAuthChk: 'login/isAuthChk',
|
||||
getPwd: 'login/getPwd'
|
||||
}),
|
||||
},
|
||||
watch: {
|
||||
getLogin(data) {
|
||||
if (data != null && data != '' && data == true) {
|
||||
this.isLogin = true;
|
||||
} else {
|
||||
this.isLogin = false;
|
||||
}
|
||||
this.isLogin = this.getLogin;
|
||||
this.pwd = this.getPwd;
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
getLogin: 'login/isLogin',
|
||||
getErrorPage: 'login/isErrorPage',
|
||||
getAuthChk: 'login/isAuthChk',
|
||||
getPwd: 'login/getPwd'
|
||||
}),
|
||||
},
|
||||
watch: {
|
||||
getLogin(data) {
|
||||
if (data != null && data != '' && data == true) {
|
||||
this.isLogin = true;
|
||||
} else {
|
||||
this.isLogin = false;
|
||||
}
|
||||
getPwd(data) {
|
||||
if(data != null && data != ''){
|
||||
this.pwd = data;
|
||||
}
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
let cont = document.querySelector(".wrap");
|
||||
cont.classList.remove("bg-wrap");
|
||||
},
|
||||
methods: {
|
||||
// 2차 인증번호 요청
|
||||
async authNum(){
|
||||
var vm = this;
|
||||
let userId = vm.$route.params.userId;
|
||||
if(!this.isLogin){
|
||||
vm.$store.commit("login/isLogin", false);
|
||||
vm.$store.commit("login/isAuthChk", false);
|
||||
vm.$router.push({ path: '/'});
|
||||
return;
|
||||
}
|
||||
if (vm.mdn == null || vm.mdn.trim() == "" || vm.mdn.length < 11 || !vm.mdn){
|
||||
// vm.ModalOpen('modal06');
|
||||
this.row.title = '휴대폰번호 확인';
|
||||
this.row.msg1 = '휴대폰번호를 확인해 주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
return false;
|
||||
}
|
||||
var params = {
|
||||
"oprtrId": userId,
|
||||
"hpNo": this.mdn,
|
||||
"isLogin" : this.isLogin
|
||||
}
|
||||
try {
|
||||
const response = await api.authNum(params)
|
||||
console.log(response);
|
||||
var rsp = response.data;
|
||||
if(rsp.retCode == '0000'){
|
||||
this.timerStop(this.timer);
|
||||
this.timer = this.timerStart();
|
||||
this.row.title = '인증번호 발송';
|
||||
this.row.msg1 = '인증번호를 발송하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal07');
|
||||
// console.log('시간 3:00 카운트 하기');
|
||||
this.isAuthNum = true;
|
||||
}else if (!this.timer) {
|
||||
this.timerStop(this.timer);
|
||||
this.timer = null;
|
||||
this.row.title = '인증번호 발송';
|
||||
this.row.msg1 = '인증번호를 발송하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal06');
|
||||
// 실패 -> 실패 코드에 따라 실패 팝업 보여주기
|
||||
//인증시간 초과 후 “시간초과!” 문구로 변경
|
||||
}
|
||||
} catch(err) {
|
||||
this.row.title = '로그인';
|
||||
this.row.msg1 = '실패 하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}
|
||||
},
|
||||
getPwd(data) {
|
||||
if(data != null && data != ''){
|
||||
this.pwd = data;
|
||||
|
||||
// 2차 인증 확인
|
||||
async ajaxAuth(){
|
||||
var vm = this;
|
||||
let userId = vm.$route.params.userId;
|
||||
if (!vm.formCheck()){
|
||||
alert(vm.errors[0]);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
let cont = document.querySelector(".wrap");
|
||||
cont.classList.remove("bg-wrap");
|
||||
},
|
||||
methods: {
|
||||
// 2차 인증번호 요청
|
||||
authNum(){
|
||||
var vm = this;
|
||||
let userId = vm.$route.params.userId;
|
||||
if(!this.isLogin){
|
||||
|
||||
if(this.timeCounter == 0){
|
||||
this.ModalOpen('modal10');
|
||||
return false;
|
||||
}
|
||||
var params = {
|
||||
"oprtrId": userId,
|
||||
"hpNo": this.mdn,
|
||||
"chrVal": this.confirmNum,
|
||||
"isLogin": this.isLogin,
|
||||
"oprtrPw": this.pwd
|
||||
}
|
||||
|
||||
//인증번호 확인
|
||||
try {
|
||||
const response = await api.confirmNum(params)
|
||||
const rsp = response.data;
|
||||
console.log("RESULT_CODE : "+rsp.retCode);
|
||||
if(rsp.retCode == '0000'){
|
||||
vm.$store.commit("login/isLogin", true);
|
||||
//var nextUrl = rsp.data.nextUrl;
|
||||
//vm.$router.push({ path: nextUrl});
|
||||
vm.$router.push({ path: '/'});
|
||||
}else if (rsp.retCode == '4008'){
|
||||
this.row.title = '휴대폰번호 확인';
|
||||
this.row.msg1 = '휴대폰번호를 확인해주세요.';
|
||||
this.row.msg2 = '아이디에 등록된 휴대폰번호로만 인증이 가능합니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}else if (rsp.retCode == '4009'){
|
||||
this.row.title = '인증실패';
|
||||
this.row.msg1 = '인증시간 초과되었습니다.';
|
||||
this.row.msg2 = '다시 휴대폰번호를 입력해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}else if (rsp.retCode == '4010'){
|
||||
this.row.title = '인증실패';
|
||||
this.row.msg1 = '잘못된 인증번호입니다.';
|
||||
this.row.msg2 = '5회 실패 시 로그아웃됩니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}else if (rsp.retCode == '4011'){
|
||||
this.row.title = '인증실패';
|
||||
this.row.msg1 = '인증번호 5회 실패하였습니다.';
|
||||
this.row.msg2 = '로그아웃되어 다시 로그인해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
vm.$store.commit("login/isLogin", false);
|
||||
vm.$store.commit("login/isAuthChk", false);
|
||||
vm.$router.push({ path: '/'});
|
||||
return;
|
||||
}
|
||||
if (vm.mdn == null || vm.mdn.trim() == "" || vm.mdn.length < 11 || !vm.mdn){
|
||||
vm.ModalOpen('modal06');
|
||||
return false;
|
||||
}
|
||||
var params = {
|
||||
"oprtrId": userId,
|
||||
"hpNo": this.mdn,
|
||||
"isLogin" : this.isLogin
|
||||
}
|
||||
api.authNum(params).then(response => {
|
||||
console.log(response);
|
||||
var rsp = response.data;
|
||||
if(rsp.retCode == '0000'){
|
||||
this.timerStop(this.timer);
|
||||
this.timer = this.timerStart();
|
||||
vm.ModalOpen('modal07');
|
||||
// console.log('시간 3:00 카운트 하기');
|
||||
this.isAuthNum = true;
|
||||
}else if (!this.timer) {
|
||||
this.timerStop(this.timer);
|
||||
this.timer = null;
|
||||
vm.ModalOpen('modal06');
|
||||
// 실패 -> 실패 코드에 따라 실패 팝업 보여주기
|
||||
//인증시간 초과 후 “시간초과!” 문구로 변경
|
||||
}
|
||||
}).catch(response =>{
|
||||
|
||||
console.log(response);
|
||||
});
|
||||
},
|
||||
} catch(err) {
|
||||
//alert("실패 하였습니다.");
|
||||
this.row.title = '인증번호';
|
||||
this.row.msg1 = '실패 하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}
|
||||
},
|
||||
formCheck: function() {
|
||||
this.errors = [];
|
||||
if(!this.mdn){
|
||||
this.row.title = '휴대폰번호 확인';
|
||||
this.row.msg1 = '휴대폰번호를 확인해 주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else if(!this.isAuthNum){
|
||||
this.row.title = '인증번호 입력';
|
||||
this.row.msg1 = '인증요청을 먼저 해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}else if(!this.confirmNum){
|
||||
this.row.title = '인증번호 입력';
|
||||
this.row.msg1 = '인증번호를 입력하세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}
|
||||
return this.errors.length == 0;
|
||||
},
|
||||
|
||||
// 2차 인증 확인
|
||||
ajaxAuth: function(){
|
||||
var vm = this;
|
||||
let userId = vm.$route.params.userId;
|
||||
if (!vm.formCheck()){
|
||||
alert(vm.errors[0]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.timeCounter == 0){
|
||||
this.ModalOpen('modal10');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var params = {
|
||||
"oprtrId": userId,
|
||||
"hpNo": this.mdn,
|
||||
"chrVal": this.confirmNum,
|
||||
"isLogin": this.isLogin,
|
||||
"oprtrPw": this.pwd
|
||||
}
|
||||
|
||||
//인증번호 확인
|
||||
api.confirmNum(params).then(function(response){
|
||||
var rsp = response.data;
|
||||
console.log("RESULT_CODE : "+rsp.retCode);
|
||||
if(rsp.retCode == '0000'){
|
||||
vm.$store.commit("login/isLogin", true);
|
||||
//var nextUrl = rsp.data.nextUrl;
|
||||
//vm.$router.push({ path: nextUrl});
|
||||
vm.$router.push({ path: '/'});
|
||||
}else if(rsp.retCode == '4008') { //휴대폰번호 확인
|
||||
vm.ModalOpen('modal06');
|
||||
|
||||
}
|
||||
// else if(rsp.retCode == '4009') { //인증실패: 시간초과
|
||||
// vm.ModalOpen('modal10');
|
||||
// }
|
||||
else{
|
||||
if(rsp.retCode == '4010') { //인증실패: 인증번호
|
||||
vm.ModalOpen('modal09');
|
||||
}
|
||||
else if(rsp.retCode == '4011') { //인증실패: 5회
|
||||
vm.ModalOpen('modal11');
|
||||
// vm.$router.go(-1)
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
// else{
|
||||
// }
|
||||
});
|
||||
},
|
||||
formCheck: function() {
|
||||
this.errors = [];
|
||||
if(!this.mdn){
|
||||
this.ModalOpen('modal06');
|
||||
} else if(!this.isAuthNum){
|
||||
this.errors.push('인증요청을 먼저 해주세요.');
|
||||
}else if(!this.confirmNum){
|
||||
this.ModalOpen('modal08');
|
||||
}
|
||||
|
||||
return this.errors.length == 0;
|
||||
},
|
||||
|
||||
clickMenu(link){
|
||||
this.$router.push({
|
||||
path: link
|
||||
});
|
||||
},
|
||||
|
||||
ModalOpen: function(target){
|
||||
this.$refs.LoginPopup.ModalOpen(target);
|
||||
},
|
||||
timerStart: function() {
|
||||
// 1초에 한번씩 start 호출
|
||||
this.timeCounter = 180;
|
||||
var interval = setInterval(() => {
|
||||
this.timeCounter--;
|
||||
//1초씩 감소
|
||||
this.timerStr = this.prettyTime();
|
||||
if (this.timeCounter <= 0)
|
||||
{
|
||||
this.timerStop(interval);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return interval;
|
||||
},
|
||||
|
||||
timerStop: function(Timer)
|
||||
{
|
||||
clearInterval(Timer);
|
||||
this.timeCounter = 0;
|
||||
},
|
||||
|
||||
prettyTime: function() {
|
||||
// 시간 형식으로 변환 리턴
|
||||
let time = this.timeCounter / 60;
|
||||
let minutes = parseInt(time);
|
||||
let secondes = Math.round((time - minutes) * 60);
|
||||
|
||||
return (
|
||||
minutes.toString().padStart(2, "0") +
|
||||
":"
|
||||
+ secondes.toString().padStart(2, "0")
|
||||
);
|
||||
},
|
||||
clickMenu(link){
|
||||
this.$router.push({
|
||||
path: link
|
||||
});
|
||||
},
|
||||
|
||||
ModalOpen: function(target){
|
||||
this.$refs.LoginPopup.ModalOpen(target);
|
||||
},
|
||||
timerStart: function() {
|
||||
// 1초에 한번씩 start 호출
|
||||
this.timeCounter = 180;
|
||||
var interval = setInterval(() => {
|
||||
this.timeCounter--;
|
||||
//1초씩 감소
|
||||
this.timerStr = this.prettyTime();
|
||||
if (this.timeCounter <= 0)
|
||||
{
|
||||
this.timerStop(interval);
|
||||
}
|
||||
};
|
||||
}, 1000);
|
||||
|
||||
return interval;
|
||||
},
|
||||
|
||||
timerStop: function(Timer)
|
||||
{
|
||||
clearInterval(Timer);
|
||||
this.timeCounter = 0;
|
||||
},
|
||||
|
||||
prettyTime: function() {
|
||||
// 시간 형식으로 변환 리턴
|
||||
let time = this.timeCounter / 60;
|
||||
let minutes = parseInt(time);
|
||||
let secondes = Math.round((time - minutes) * 60);
|
||||
|
||||
return (
|
||||
minutes.toString().padStart(2, "0") +
|
||||
":"
|
||||
+ secondes.toString().padStart(2, "0")
|
||||
);
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,142 +1,167 @@
|
||||
<template>
|
||||
<div class="wrap bg-wrap">
|
||||
<div class="login-box adm-login">
|
||||
<div class="wbox">
|
||||
<div class="logo"></div>
|
||||
<h3 class="title">관리자 로그인</h3>
|
||||
<!-- <form action=""> -->
|
||||
<div class="login-form">
|
||||
<li><input type="text" placeholder="아이디" v-model="userId"></li>
|
||||
<li><input type="password" placeholder="비밀번호" v-model="userPwd" @keyup.enter="ajaxlogin"></li>
|
||||
<li>
|
||||
<span class="lcont"><input type="checkbox" id="id-remember" ref="chkSaveId" checked><label for="id-remember">아이디 저장</label></span>
|
||||
<span class="rcont"><button class="btn-pwreset" @click="clickMenu('/view/login/resetPassword')">비밀번호 초기화</button></span>
|
||||
</li>
|
||||
<li><button class="btn-pcolor" v-on:click="ajaxlogin">로그인</button></li>
|
||||
</div>
|
||||
<!-- </form> -->
|
||||
<div class="login-notice">
|
||||
<div>
|
||||
<li>비밀번호 분실 시 비밀번호 초기화를 이용해주세요.</li>
|
||||
<li>비밀번호는 90일이내 변경하여 안전히 관리해주세요.</li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
</div>
|
||||
<div class="wrap bg-wrap">
|
||||
<div class="login-box adm-login">
|
||||
<div class="wbox">
|
||||
<div class="logo"></div>
|
||||
<h3 class="title">관리자 로그인</h3>
|
||||
<!-- <form action=""> -->
|
||||
<div class="login-form">
|
||||
<li><input type="text" placeholder="아이디" v-model="userId"></li>
|
||||
<li><input type="password" placeholder="비밀번호" v-model="userPwd" @keyup.enter="ajaxlogin"></li>
|
||||
<li>
|
||||
<span class="lcont"><input type="checkbox" id="id-remember" ref="chkSaveId" checked><label for="id-remember">아이디 저장</label></span>
|
||||
<span class="rcont"><button class="btn-pwreset" @click="clickMenu('/view/login/resetPassword')">비밀번호 초기화</button></span>
|
||||
</li>
|
||||
<li><button class="btn-pcolor" @click="ajaxlogin">로그인</button></li>
|
||||
</div>
|
||||
<!-- </form> -->
|
||||
<div class="login-notice">
|
||||
<div>
|
||||
<li>비밀번호 분실 시 비밀번호 초기화를 이용해주세요.</li>
|
||||
<li>비밀번호는 90일이내 변경하여 안전히 관리해주세요.</li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
<common-modal ref="commmonModal"></common-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../service/api';
|
||||
import LoginPopup from '@/components/LoginPopup.vue';
|
||||
import tokenSvc from '@/common/token-service';
|
||||
//import * as utils from '@/common/utils';
|
||||
import api from '../service/api';
|
||||
import LoginPopup from '@/components/LoginPopup.vue';
|
||||
import tokenSvc from '@/common/token-service';
|
||||
import commonModal from "@/components/modal/commonModal";
|
||||
|
||||
export default {
|
||||
data: function() {
|
||||
return {
|
||||
errors: [],
|
||||
corpId: '',
|
||||
userId: '',
|
||||
userPwd: ''
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 로그인 페이지 진입시
|
||||
if(!!tokenSvc.getToken()){
|
||||
this.$store.commit("login/isLogin", true);
|
||||
this.$store.commit("login/isAuthChk", true);
|
||||
this.$router.push({ path: '/' });
|
||||
}else{
|
||||
this.$store.commit("login/isLogin", false);
|
||||
this.$store.commit("login/isAuthChk", false);
|
||||
this.$store.commit("login/isErrorPage", false);
|
||||
export default {
|
||||
data: function() {
|
||||
return {
|
||||
row:{},
|
||||
errors: [],
|
||||
corpId: '',
|
||||
userId: '',
|
||||
userPwd: ''
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 로그인 페이지 진입시
|
||||
if(!!tokenSvc.getToken()){
|
||||
this.$store.commit("login/isLogin", true);
|
||||
this.$store.commit("login/isAuthChk", true);
|
||||
this.$router.push({ path: '/' });
|
||||
}else{
|
||||
this.$store.commit("login/isLogin", false);
|
||||
this.$store.commit("login/isAuthChk", false);
|
||||
this.$store.commit("login/isErrorPage", false);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.chkSaveId.checked = true;
|
||||
|
||||
if (localStorage.hubwebUserId) {
|
||||
this.userId = localStorage.hubwebUserId;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
let cont = document.querySelector(".wrap");
|
||||
cont.classList.remove("login-wrap");
|
||||
},
|
||||
components: {
|
||||
LoginPopup : LoginPopup,
|
||||
commonModal,
|
||||
},
|
||||
methods: {
|
||||
chgChkUserId() {
|
||||
if (this.$refs.chkSaveId.checked == true) {
|
||||
localStorage.hubwebUserId = this.userId;
|
||||
} else {
|
||||
delete localStorage.hubwebUserId;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.chkSaveId.checked = true;
|
||||
|
||||
if (localStorage.hubwebUserId) {
|
||||
this.userId = localStorage.hubwebUserId;
|
||||
toRegister(){
|
||||
this.$router.push({ name: 'register'});
|
||||
},
|
||||
async ajaxlogin() {
|
||||
|
||||
var vm = this;
|
||||
vm.errmsg = null;
|
||||
// if (!vm.formCheck()) return false;
|
||||
console.log(this.userId)
|
||||
if (!this.userId){
|
||||
this.row.title = '로그인 실패';
|
||||
this.row.msg1 = '아이디,비밀번호를 확인해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
return false;
|
||||
}
|
||||
if (!this.userPwd){
|
||||
this.row.title = '비밀번호 오류';
|
||||
this.row.msg1 = '비밀번호를 확인해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
let cont = document.querySelector(".wrap");
|
||||
cont.classList.remove("login-wrap");
|
||||
},
|
||||
components: {
|
||||
LoginPopup : LoginPopup
|
||||
},
|
||||
methods: {
|
||||
chgChkUserId() {
|
||||
if (this.$refs.chkSaveId.checked == true) {
|
||||
localStorage.hubwebUserId = this.userId;
|
||||
} else {
|
||||
delete localStorage.hubwebUserId;
|
||||
}
|
||||
},
|
||||
toRegister(){
|
||||
this.$router.push({ name: 'register'});
|
||||
},
|
||||
formCheck: function() {
|
||||
this.errors = [];
|
||||
|
||||
|
||||
if (!this.userId) this.errors.push('아이디를 입력해 주세요.');
|
||||
if (!this.userPwd) this.errors.push('비밀번호를 입력해 주세요.');
|
||||
let oprtrId = this.userId;
|
||||
let oprtrPw = this.userPwd;
|
||||
|
||||
return this.errors.length == 0;
|
||||
},
|
||||
ajaxlogin: function() {
|
||||
|
||||
var vm = this;
|
||||
vm.errmsg = null;
|
||||
|
||||
if (!vm.formCheck()) return false;
|
||||
|
||||
let oprtrId = this.userId;
|
||||
let oprtrPw = this.userPwd;
|
||||
|
||||
// FormData 객체를 파라미터로 넘기면 Content-Type: multipart/form-data; 요청을 한다.
|
||||
// 일반 Object를 파라미터로 넘기면 Content-Type: application/json;charset=UTF-8 요청을 한다.
|
||||
var params = {
|
||||
"oprtrId": this.userId,
|
||||
"oprtrPw": this.userPwd,
|
||||
}
|
||||
// FormData 객체를 파라미터로 넘기면 Content-Type: multipart/form-data; 요청을 한다.
|
||||
// 일반 Object를 파라미터로 넘기면 Content-Type: application/json;charset=UTF-8 요청을 한다.
|
||||
var params = {
|
||||
"oprtrId": this.userId,
|
||||
"oprtrPw": this.userPwd,
|
||||
}
|
||||
//로그인버튼을 누를시 상황
|
||||
api.login(params).then(function(response) {
|
||||
|
||||
var rsp = response.data;
|
||||
try {
|
||||
const response = await api.login(params)
|
||||
const rsp = response.data;
|
||||
console.log(rsp);
|
||||
|
||||
if(rsp.retCode == '0000'){
|
||||
var path = rsp.data.nextUrl;
|
||||
console.log(path);
|
||||
vm.chgChkUserId();
|
||||
vm.$store.commit("login/isLogin", true);
|
||||
vm.$store.commit("login/savePwd", oprtrPw);
|
||||
vm.$router.push({ name: 'loginAuth',params: {userId : oprtrId}});
|
||||
} else if(rsp.retCode == '4004') { // ID/PWD 불일치
|
||||
vm.errors.push('로그인 실패하였습니다. (5회 실패 시 계정 잠김)');
|
||||
vm.ModalOpen('modal01');
|
||||
} else if(rsp.retCode == '4005') { // ID/PWD 불일치 횟수초과로 계정 잠김
|
||||
// msg = '5회 이상 로그인 실패하여 해당 아이디에 대한 계정이 잠금처리되었습니다.\n관리자에게 문의하세요.';
|
||||
vm.ModalOpen('modal02');
|
||||
} else if(rsp.retCode == '4006') {
|
||||
// msg = '비밀번호를 변경하신지 90일이 지났습니다.\n비밀번호 변경 화면으로 이동합니다.';
|
||||
vm.chgChkUserId();
|
||||
vm.ModalOpen('modal04');
|
||||
} else if(rsp.retCode == '4007') {
|
||||
// msg = '관리자 승인 후 이용할 수 있습니다.';
|
||||
vm.ModalOpen('modal03');
|
||||
} else {
|
||||
vm.$store.commit("login/isLogin", false);
|
||||
return;
|
||||
}
|
||||
});
|
||||
if(rsp.retCode == '0000'){
|
||||
var path = rsp.data.nextUrl;
|
||||
console.log(path);
|
||||
vm.chgChkUserId();
|
||||
vm.$store.commit("login/isLogin", true);
|
||||
vm.$store.commit("login/savePwd", oprtrPw);
|
||||
vm.$router.push({ name: 'loginAuth',params: {userId : oprtrId}});
|
||||
} else if(rsp.retCode == '4003') { // ID 조회 없음.
|
||||
this.row.title = '로그인 실패';
|
||||
this.row.msg1 = '등록되지 않은 아이디입니다.';
|
||||
this.row.msg2 = '아이디를 다시 확인하세요';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else if(rsp.retCode == '4004') { // ID/PWD 불일치
|
||||
this.row.title = '비밀번호 오류';
|
||||
this.row.msg1 = '비밀번호를 확인해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else if(rsp.retCode == '4005') { // ID/PWD 불일치 횟수초과로 계정 잠김 4005
|
||||
this.row.title = '로그인 실패';
|
||||
this.row.msg1 = '로그인 5회 실패하였습니다.';
|
||||
this.row.msg2 = '비밀번호 초기화 후 비밀번호를 변경해 주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else if(rsp.retCode == '4006') {
|
||||
// msg = '비밀번호를 변경하신지 90일이 지났습니다.\n비밀번호 변경 화면으로 이동합니다.';
|
||||
this.row.title = '로그인 실패';
|
||||
this.row.msg1 = '비밀번호를 변경하지 않은지 90일이';
|
||||
this.row.msg2 = '지났습니다. 비밀번호를 변경하여';
|
||||
this.row.msg3 = '이용 부탁드립니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else if(rsp.retCode == '4007') {
|
||||
this.row.title = '로그인 실패';
|
||||
this.row.msg1 = '아이디 상태를 확인해 주세요.';
|
||||
this.row.msg2 = '(사용중인 상태만 로그인 가능합니다.)';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
} else {
|
||||
vm.$store.commit("login/isLogin", false);
|
||||
return;
|
||||
}
|
||||
} catch(err) {
|
||||
//alert("실패 하였습니다.");
|
||||
this.row.title = '로그인';
|
||||
this.row.msg1 = '실패 하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
clickMenu(link){
|
||||
|
||||
@@ -1,115 +1,124 @@
|
||||
<template>
|
||||
|
||||
<div class="wrap bg-wrap">
|
||||
<div class="wrap bg-wrap">
|
||||
|
||||
<!-- s: 패스워드초기화 -->
|
||||
<div class="login-box pw-reset">
|
||||
<div class="logo"></div>
|
||||
<div class="wbox">
|
||||
<h3 class="title">비밀번호 초기화</h3>
|
||||
<!-- <form action=""> -->
|
||||
<div class="login-form">
|
||||
<div>
|
||||
|
||||
<input type="text" placeholder="아이디를 입력하세요" v-model="userId"></div>
|
||||
<div class="button_group">
|
||||
<button class="btn-pcolor" @click="ajaxReset">비밀번호 초기화 문자 발송하기</button>
|
||||
<button class="btn-default" @click="clickMenu('/login')">취소</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- </form> -->
|
||||
<div class="login-notice">
|
||||
<div>
|
||||
<li>초기화된 비밀번호는 등록된 휴대폰 문자메시지로 발송됩니다.</li>
|
||||
<li>휴대폰 번호 변경 시 관리자로 문의해주세요.</li>
|
||||
</div>
|
||||
|
||||
<!-- s: 패스워드초기화 -->
|
||||
<div class="login-box pw-reset">
|
||||
<div class="logo"></div>
|
||||
<div class="wbox">
|
||||
<h3 class="title">비밀번호 초기화</h3>
|
||||
<!-- <form action=""> -->
|
||||
<div class="login-form">
|
||||
<div>
|
||||
<input type="text" placeholder="아이디를 입력하세요" v-model="userId"></div>
|
||||
<div class="button_group">
|
||||
<button class="btn-pcolor" @click="ajaxReset">비밀번호 초기화 문자 발송하기</button>
|
||||
<button class="btn-default" @click="clickMenu('/login')">취소</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
|
||||
</div>
|
||||
<!-- </form> -->
|
||||
<div class="login-notice">
|
||||
<div>
|
||||
<li>초기화된 비밀번호는 등록된 휴대폰 문자메시지로 발송됩니다.</li>
|
||||
<li>휴대폰 번호 변경 시 관리자로 문의해주세요.</li>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
<common-modal ref="commmonModal"></common-modal>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import api from '../service/api';
|
||||
import LoginPopup from '@/components/LoginPopup.vue';
|
||||
import commonModal from "@/components/modal/commonModal";
|
||||
|
||||
export default {
|
||||
name: 'resetPassword',
|
||||
data: function() {
|
||||
return {
|
||||
errors: [],
|
||||
userId: '',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.commit("login/isLogin", false);
|
||||
this.$store.commit("login/isAuthChk", false);
|
||||
},
|
||||
components: {
|
||||
LoginPopup
|
||||
},
|
||||
methods: {
|
||||
formCheck: function()
|
||||
name: 'resetPassword',
|
||||
data: function() {
|
||||
return {
|
||||
errors: [],
|
||||
userId: '',
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.commit("login/isLogin", false);
|
||||
this.$store.commit("login/isAuthChk", false);
|
||||
},
|
||||
components: {
|
||||
LoginPopup,
|
||||
commonModal,
|
||||
},
|
||||
methods: {
|
||||
formCheck: function()
|
||||
{
|
||||
this.errors = [];
|
||||
if (!this.userId) {
|
||||
this.row.title = '아이디 오류';
|
||||
this.row.msg1 = '아이디를 입력해 주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// this.errors.push('아이디를 입력해 주세요.');
|
||||
}
|
||||
|
||||
return this.errors.length == 0;
|
||||
},
|
||||
|
||||
async ajaxReset(){
|
||||
var vm = this;
|
||||
//vm.errmsg = null;
|
||||
if (!vm.formCheck()) return false;
|
||||
|
||||
var params =
|
||||
{
|
||||
this.errors = [];
|
||||
if (!this.userId) {
|
||||
this.errors.push('아이디를 입력해 주세요.');
|
||||
}
|
||||
|
||||
return this.errors.length == 0;
|
||||
},
|
||||
|
||||
ajaxReset: function(){
|
||||
var vm = this;
|
||||
//vm.errmsg = null;
|
||||
if (!vm.formCheck()) return false;
|
||||
|
||||
var params =
|
||||
{
|
||||
"userId": this.userId,
|
||||
//"userPwd": this.userPwd,
|
||||
}
|
||||
api.resetPassword(params).then(function(response){
|
||||
var rsp = response.data;
|
||||
console.log("RESULT_CODE : "+rsp.retCode);
|
||||
|
||||
if(rsp.retCode == '0000'){
|
||||
// vm.$store.commit("login/isLogin", true);
|
||||
//vm.$store.commit("login/isAuthChk", true);
|
||||
|
||||
vm.ModalOpen('modal12');
|
||||
//vm.$router.push({ path : 'view/login'});
|
||||
|
||||
} else if(rsp.retCode == '4003') {
|
||||
vm.ModalOpen('modal13');
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
document.getElementsByClassName('modal12')[0].getElementsByClassName('btn-pcolor')[0].addEventListener('click',() => {
|
||||
vm.$router.push({path: '/login'});
|
||||
});
|
||||
});
|
||||
}
|
||||
,
|
||||
clickMenu(link) {
|
||||
|
||||
this
|
||||
.$router
|
||||
.push({path: link});
|
||||
},
|
||||
|
||||
ModalOpen: function(target){
|
||||
this.$refs.LoginPopup.ModalOpen(target);
|
||||
},
|
||||
"userId": this.userId,
|
||||
//"userPwd": this.userPwd,
|
||||
}
|
||||
try {
|
||||
const response = await api.resetPassword(params)
|
||||
const rsp = response.data;
|
||||
console.log("RESULT_CODE : "+rsp.retCode);
|
||||
|
||||
if(rsp.retCode == '0000'){
|
||||
// vm.$store.commit("login/isLogin", true);
|
||||
//vm.$store.commit("login/isAuthChk", true);
|
||||
this.row.title = '비밀번호 초기화';
|
||||
this.row.msg1 = '해당 아이디에 저장되어 있는 핸드폰번호로';
|
||||
this.row.msg2 = '비밀번호 초기화 문자가 발송되었습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal12');
|
||||
//vm.$router.push({ path : 'view/login'});
|
||||
|
||||
} else if(rsp.retCode == '4003') {
|
||||
this.row.title = '비밀번호 초기화';
|
||||
this.row.msg1 = '등록되지 않은 아이디입니다.';
|
||||
this.row.msg2 = '아이디를 다시 확인하세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal13');
|
||||
}
|
||||
// document.getElementsByClassName('modal12')[0].getElementsByClassName('btn-pcolor')[0].addEventListener('click',() => {
|
||||
// vm.$router.push({path: '/login'});
|
||||
} catch(err) {
|
||||
//alert("실패 하였습니다.");
|
||||
this.row.title = '비밀번호 초기화';
|
||||
this.row.msg1 = '실패 하였습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
,
|
||||
clickMenu(link) {
|
||||
this.$router.push({path: link});
|
||||
},
|
||||
|
||||
ModalOpen: function(target){
|
||||
this.$refs.LoginPopup.ModalOpen(target);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
<template>
|
||||
<div class="wrap bg-wrap">
|
||||
<!-- s: 비밀번호변경 -->
|
||||
<div id="cpf" class="login-box pw-change">
|
||||
<div class="logo"></div>
|
||||
<div class="wbox">
|
||||
<h3 class="title">비밀번호 변경</h3>
|
||||
<p class="desc">임시비밀번호로 로그인할 경우 비밀번호를 변경 후<br>서비스 이용이 가능합니다.</p>
|
||||
<form @submit.prevent="changedPwd">
|
||||
<ul class="pw-form">
|
||||
<div><input id="oldPw" type="password" placeholder="기존 비밀번호를 입력하세요" v-model="oldPw" ref="oldPw"></div>
|
||||
<div>
|
||||
<input id="newPw" type="password" placeholder="새로운 비밀번호를 입력하세요" required minlength="8" maxlength="16" v-model.trim="newPw" ref="_newPw">
|
||||
</div>
|
||||
<div><input type="password" placeholder="새로운 비밀번호를 다시 한 번 입력하세요" required minlength="8" maxlength="16" v-model.trim="newPw2" ref="_newPw2"></div>
|
||||
<div><button class="btn-pcolor" @click="changedPwd()">비밀번호 변경하기</button></div>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
<div id="cpf" class="login-box pw-change">
|
||||
<div class="logo"></div>
|
||||
<div class="wbox">
|
||||
<h3 class="title">비밀번호 변경</h3>
|
||||
<p class="desc">임시비밀번호로 로그인할 경우 비밀번호를 변경 후<br>서비스 이용이 가능합니다.</p>
|
||||
<form @submit.prevent="changedPwd">
|
||||
<ul class="pw-form">
|
||||
<div><input id="oldPw" type="password" placeholder="기존 비밀번호를 입력하세요" v-model="oldPw" ref="oldPw"></div>
|
||||
<div>
|
||||
<input id="newPw" type="password" placeholder="새로운 비밀번호를 입력하세요" required minlength="8" maxlength="16" v-model.trim="newPw" ref="_newPw">
|
||||
</div>
|
||||
<div><input type="password" placeholder="새로운 비밀번호를 다시 한 번 입력하세요" required minlength="8" maxlength="16" v-model.trim="newPw2" ref="_newPw2"></div>
|
||||
<div><button class="btn-pcolor" @click="changedPwd()">비밀번호 변경하기</button></div>
|
||||
</ul>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<login-popup ref="LoginPopup"> </login-popup>
|
||||
<common-modal ref="commmonModal"></common-modal>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
@@ -31,8 +32,8 @@ import { mapGetters } from 'vuex';
|
||||
import LoginPopup from '@/components/LoginPopup.vue';
|
||||
import tokenSvc from '@/common/token-service';
|
||||
import { commonPwdView, validation } from '../service/mixins';
|
||||
// import { chkPattern } from '@/common/vue-mixins';
|
||||
// import * as utils from '@/common/utils';
|
||||
import commonModal from "@/components/modal/commonModal";
|
||||
|
||||
export default {
|
||||
mixins: [commonPwdView, validation],
|
||||
data: function() {
|
||||
@@ -89,7 +90,8 @@ export default {
|
||||
},
|
||||
|
||||
components: {
|
||||
LoginPopup : LoginPopup
|
||||
LoginPopup : LoginPopup,
|
||||
commonModal,
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -108,20 +110,26 @@ export default {
|
||||
},
|
||||
|
||||
doPwdValidate(){
|
||||
debugger;
|
||||
//debugger;
|
||||
if(lodash.isNil(this.newPw)){
|
||||
alert("비밀번호 확인을 입력해 주세요.");
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호 확인을 입력해 주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
this.$refs._newPw2.focus();
|
||||
return false;
|
||||
}
|
||||
if(!lodash.isEqual(this.newPw, this.newPw2)){
|
||||
alert("비밀번호가 일치하지 않습니다.");
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호가 일치하지 않습니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
this.$refs._newPw2.focus();
|
||||
return false;
|
||||
}
|
||||
const pwdLen = this.bytes(this.newPw);
|
||||
if(!(pwdLen >= 8 && pwdLen <= 16)){
|
||||
alert("비밀번호는 8~16자의 영문, 숫자, 특수문자(!,@, $, %, ^, &, *) 조합이 필요합니다.");
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호는 8~16자의 영문, 숫자, 특수문자(!,@, $, %, ^, &, *) 조합이 필요합니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
this.$refs._newPw2.focus();
|
||||
return false;
|
||||
}
|
||||
@@ -129,7 +137,9 @@ export default {
|
||||
const pNum = /[0-9]/g; // 숫자
|
||||
const pSpc = /[!@$%^&*]/g; // 특수문자
|
||||
if(!(pEng.test(this.newPw) && pNum.test(this.newPw) && pSpc.test(this.newPw))) {
|
||||
alert("비밀번호는 8~16자의 영문, 숫자, 특수문자(!,@, $, %, ^, &, *) 조합이 필요합니다.");
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호는 8~16자의 영문, 숫자, 특수문자(!,@, $, %, ^, &, *) 조합이 필요합니다.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
this.$refs._newPw2.focus();
|
||||
return;
|
||||
}
|
||||
@@ -155,26 +165,31 @@ export default {
|
||||
|
||||
if(rsp.retCode == '0000') {
|
||||
// vm.chgChkUserId();
|
||||
|
||||
if(vm.ModalOpen('modal16')){
|
||||
vm.$router.push({ path: '/login' });
|
||||
}
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호가 정상적으로 변경되었습니다.';
|
||||
this.row.msg2 = '변경된 비밀번호로 다시 로그인 해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// if(vm.ModalOpen('modal16')){
|
||||
vm.$router.push({ path: '/login' });
|
||||
// }
|
||||
} else if(rsp.retCode == '4016') {
|
||||
vm.ModalOpen('modal14')
|
||||
this.row.title = '비밀번호 변경';
|
||||
this.row.msg1 = '비밀번호를 확인해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal14')
|
||||
} else if(rsp.retCode == '4017') {
|
||||
vm.ModalOpen('modal15')
|
||||
this.row.title = '비밀번호 오류';
|
||||
this.row.msg1 = '비밀번호를 사용할 수 없습니다.';
|
||||
this.row.msg2 = '비밀번호는 영문/숫자/특수기호를 혼합하여';
|
||||
this.row.msg3 = '8~16자리로 설정해주세요.';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
// vm.ModalOpen('modal15')
|
||||
} else if(rsp.retCode == '4003') {
|
||||
if(vm.ModalOpen('modal14')) {
|
||||
//수정사항 : 모달오픈 -> 기존비밀번호 포커스
|
||||
alert('1');
|
||||
}
|
||||
|
||||
// //this.$refs.oldPw.focus();
|
||||
// alert('비밀번호 유효성체크');
|
||||
// vm.$refs.oldPw.focus();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
this.row.title = '아이디 오류';
|
||||
this.row.msg1 = '등록되지 않은 아이디입니다.';
|
||||
this.row.msg1 = '아이디를 다시 확인하세요';
|
||||
this.$refs.commmonModal.alertModalOpen(this.row);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user