지난 시간에 비밀번호 찾기용 이메일 발송까지 되었고 메일로 발송된 변경 링크를 타고 온 회원에게 비밀번호를 변경할 수 있는 페이지를 제공하도록 할께요
먼저 ModifyPassword.vue 를 작성합니다.
<template>
<div class="d-flex justify-center align-center" style="height: 100%">
<v-card max-width="400" width="100%" elevation="10">
<v-card-subtitle>
변경하실 비밀번호를 입력하세요.
</v-card-subtitle>
<v-form @submit.prevent="save" ref="form" v-model="valid" lazy-validation>
<v-card-text>
<input-password
v-model="form.password"
label="비밀번호"
prepend-icon="mdi-lock"
:rules="rules.password()"
/>
<input-password
v-model="confirmPw"
label="비밀번호 확인"
prepend-icon="mdi-lock-check"
:rules="[rules.matchValue(form.password)]"
/>
</v-card-text>
<v-card-actions>
<v-btn type="submit" block color="primary" :loading="loading">
비밀번호 변경
</v-btn>
</v-card-actions>
</v-form>
<v-card-text class="mt-n4">
<v-btn to="/login" block >로그인</v-btn>
</v-card-text>
</v-card>
</div>
</template>
<script>
import { mapActions } from 'vuex';
import validateRules from '../../../util/validateRules';
import InputPassword from '../../components/InputForms/InputPassword.vue'
export default {
components: { InputPassword },
name : "ModifyPassword",
data() {
return {
valid : true,
form : {
password : "abcd1234",
hash : this.$route.params.hash
},
confirmPw : "abcd1234",
loading : false,
}
},
computed : {
rules : () => validateRules,
},
methods : {
...mapActions('user', ['modifyPassword']),
async save() {
this.$refs.form.validate();
await this.$nextTick();
if(!this.valid) return;
this.loading = true;
const data = await this.modifyPassword(this.form);
this.loading = false;
if(data) {
this.$toast.info('비밀번호가 변경되었습니다.');
this.$router.push('/login');
}
}
}
}
</script>
그리고 라우트에 규칙을 추가 하도록 합니다.
Error 규칙 위에 작성해 주세요.
// 생략...
{
path: '/modifyPassword/:hash',
name: 'NoAuthModifyPassword',
component: () => import(/* webpackChunkName: "modifyPassword" */ '../views/member/ModifyPassword.vue')
},
스토어 user.js에 modifyPassword 함수를 추가합니다.
// 생략...
export const actions = {
// 생략...
async modifyPassword(ctx, form) {
const {$axios} = Vue.prototype;
const data = await $axios.patch(`/api/member/modifyPassword`, form);
return data;
}
}
api/member.js에 라우터 를 추가합니다.
// 비밀번호 변경
router.patch('/modifyPassword', async (req, res) => {
const result = await modelCall(memberModel.modifyPassword, req.body);
res.json(result);
});
memberModel.js 에 modifyPassword 함수를 추가합니다.
async modifyPassword(data) {
// 유효시간이 경과된 거 삭제
const delQuery = `DELETE FROM ${TABLE.SEND_MAIL} WHERE sm_type=1 AND sm_expire_at < NOW()`;
await db.execute(delQuery);
// 유효시간 안에 해쉬로 검색
const sql = {
query: `SELECT sm_to FROM ${TABLE.SEND_MAIL} WHERE sm_type=? AND sm_hash=? AND sm_expire_at > NOW()`,
values: [1, data.hash],
};
const [[row]] = await db.execute(sql.query, sql.values);
// 없으면 에러
if (!row) {
throw new Error('시간이 만료되었거나 이미 처리되었습니다.');
}
// 있으면 비밀번호를 변경 하고
const mb_email = row.sm_to;
const mb_password = await jwt.generatePassword(data.password);
const upSql = sqlHelper.Update(TABLE.MEMBER, { mb_password }, { mb_email });
const [upRes] = await db.execute(upSql.query, upSql.values);
// 처리한거 삭제
const delSql = sqlHelper.DeleteSimple(TABLE.SEND_MAIL, {sm_hash : data.hash});
db.execute(delSql.query, delSql.values);
return upRes.affectedRows == 1;
},
SqlHeler.js에 DeleteSimple 함수를 추가합니다.
DeleteSimple(table, data) {
let query = `DELETE FROM ${table}`;
const where = [];
const values = [];
if (data) {
const keys = Object.keys(data);
for (key of keys) {
where.push(`${key}=?`);
values.push(data[key]);
}
query += ` WHERE ` + where.join(' AND ');
} else {
throw new Error('DELETE 구문에는 WHERE절이 있어야 합니다.');
}
return { query, values };
},
회원로그인 후 댓글을 작성하실 수 있습니다. 로그인