본문 바로가기
Programming/Vue

[실습] 뷰(Vue)로 임시 비밀번호 발급 기능 구현하기 - UI 및 기능 개발

by 돌방로그 2023. 3. 8.


오늘의 실습 목표는 "임시 비밀번호 발급 기능 만들어보기!" 입니다.
본 게시글에서 다루는 사항은 임시 비밀번호 발급 기능을 구현하는 과정입니다.

 


임시 비밀번호 발급 기능 구현하기 - UI 및 기능 개발

사전 준비

아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.

 


결과 이미지

구현하기에 앞서 본 글을 따라하시면 아래와 같이 화면의 레이아웃을 구성하실 수 있습니다.

좌: 관리자 포털 사용자 관리 화면 우: 관리자 포털 특정 사용자 임시 비밀번호 발급 버튼 클릭 후

 


소스 코드

src\components\admin-web\users\AdminUsersMain.vue

관리자 포털의 사용자 관리 화면의 주요 기능이 담겨있는 컴포넌트 파일입니다.

전체 코드를 확인하실 분들은 아래 더보기를 클릭해주세요.

더보기
<template>
  <v-container>
    <div class="text-h5 font-weight-medium ma-2">Users (Admin Web)</div>

    <v-divider></v-divider>

    <v-row>
      <v-col class="align-self-center" :cols="4">
        <div>
          <v-switch
            inset
            color="indigo darken-3"
            v-model="readAll"
            :label="`${readAll ? 'All' : 'Available'}`"
            @change="changeReadStatus"
          ></v-switch>
        </div>
      </v-col>
      <v-col class="align-self-center" :cols="8">
        <div class="d-flex justify-end">
          <v-dialog persistent max-width="1000px" v-model="dialogRegister">
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                text
                outlined
                class="mx-md-1 elevation-2"
                v-bind="attrs"
                v-on="on"
                >REGISTER
              </v-btn>
            </template>
            <v-card>
              <Form
                :mode="'Register'"
                v-on:finishProcess="finishProcess"
              ></Form>
            </v-card>
          </v-dialog>

          <v-dialog persistent max-width="1000px" v-model="dialogModify">
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                text
                outlined
                class="mx-md-1 elevation-2"
                v-bind="attrs"
                v-on="on"
                :disabled="!hasSelectedRow()"
                >MODIFY
              </v-btn>
            </template>
            <v-card>
              <Form
                :mode="'Modify'"
                :employee="this.selectedRow[0]"
                v-on:finishProcess="finishProcess"
              ></Form>
            </v-card>
          </v-dialog>

          <v-dialog v-model="dialogDelete" persistent max-width="300">
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                text
                outlined
                class="mx-md-1 elevation-2"
                :disabled="!checkDeleteStatus()"
                v-bind="attrs"
                v-on="on"
                >DELETE
              </v-btn>
            </template>
            <v-card>
              <v-card-title class="text-h5">
                Are you sure you want to delete the user?
              </v-card-title>
              <v-card-text
                >Deleted user cannot be restored, and are immediately reflected
                on the admin portal after deletion.
              </v-card-text>
              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn color="blue darken-1" text @click="dialogDelete = false">
                  Cancel
                </v-btn>
                <v-btn color="blue darken-1" text @click="deleteUser">
                  Confirm
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>

          <v-dialog v-model="dialogCreatePassword" persistent max-width="450">
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                text
                outlined
                class="mx-md-1 elevation-2"
                :disabled="!hasSelectedRow()"
                v-bind="attrs"
                v-on="on"
                >CREATE PASSWORD
              </v-btn>
            </template>
            <v-card>
              <v-card-title class="text-h5">
                Are you sure you want to create temporary password for the user?
              </v-card-title>
              <v-card-text
                >Previous password cannot be restored, and are immediately
                reflected on the admin portal after creation temporary password.
              </v-card-text>
              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn
                  color="blue darken-1"
                  text
                  @click="dialogCreatePassword = false"
                >
                  Cancel
                </v-btn>
                <v-btn color="blue darken-1" text @click="createPassword">
                  Confirm
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </div>
      </v-col>
    </v-row>

    <div>
      <v-card-title>
        Admin Users
        <v-spacer></v-spacer>
        <v-text-field
          single-line
          hide-details
          v-model="search"
          append-icon="mdi-magnify"
          label="Search"
        ></v-text-field>
      </v-card-title>
      <v-data-table
        single-select
        show-select
        item-key="employeeNo"
        show-expand
        class="mt-md-2 elevation-5"
        v-model="selectedRow"
        :search="search"
        :headers="headers"
        :items="users"
        :items-per-page="10"
      >
        <template v-slot:expanded-item="{ headers, item }">
          <td class="pa-5" :colspan="headers.length">
            {{ "- Division: " + item.division }} <br />{{
              "- Team: " + item.team
            }}
            <br />{{ "- Name (Eng): " + item.nameEng }} <br />{{
              "- Email: " + item.email
            }}
            <br />{{ "- Phone: " + item.phone }}
          </td>
        </template>
      </v-data-table>
    </div>
  </v-container>
</template>

<script>
import Form from "./../../../components/admin-web/users/AdminUsersDetail.vue";

export default {
  components: {
    Form,
  },
  data() {
    return {
      today: new Date(Date.now() - new Date().getTimezoneOffset() * 60000)
        .toISOString()
        .substring(0, 10)
        .replaceAll("-", ""),
      readAll: false,
      dialogRegister: false,
      dialogModify: false,
      dialogDelete: false,
      dialogCreatePassword: false,
      selectedRow: [],
      search: "",
      headers: [
        {
          text: "Company",
          value: "employeeCompany",
        },
        {
          text: "Employee No.",
          value: "employeeNo",
        },
        {
          text: "Name (Kor)",
          value: "employeeName",
        },
        {
          text: "Position",
          value: "employeePosition",
        },
      ],
      users: [],
    };
  },
  created: function () {
    this.getAdminUsers();
  },
  methods: {
    hasSelectedRow: function () {
      return this.selectedRow.length > 0;
    },
    checkDeleteStatus: function () {
      let isAvailable = false;

      if (this.hasSelectedRow() === true) {
        isAvailable = this.selectedRow[0].usageExpDate > this.today;
      }
      return isAvailable;
    },
    finishProcess: function () {
      this.dialogRegister = false;
      this.dialogModify = false;

      window.location.reload();
    },
    changeReadStatus: function () {
      this.getAdminUsers();
    },
    deleteUser: function () {
      this.dialogDelete = false;

      this.$axios
        .put("/api/admin-web/user/delete/" + this.selectedRow[0].employeeNo, {
          employeeNo: this.selectedRow[0].employeeNo,
          // TODO: EmployeeNo는 로그인한 유저의 사번으로 변경
          updateEmployeeNo: "000000",
          usageExpDate: this.today,
        })
        .catch(function (error) {
          console.log("[ERR/DEL]" + error);
        });
    },
    createPassword: function () {
      this.dialogCreatePassword = false;

      // Generate random string
      let temporaryPassword = Math.random().toString(36).substring(2, 11);
      console.log(temporaryPassword);

      let path = "/api/admin-web/user/update";
      let jsonData = {
        employeeNo: this.selectedRow[0].employeeNo,
        employeePw: temporaryPassword,
        registerEmployeeNo: "000000",
        updateEmployeeNo: "000000",
        pwTrialState: "0",
        temporaryPwState: "Y",
      };

      this.$axios
        .put(path, jsonData)
        .then((response) => {
          if (response.statusText == "OK") {
            alert(
              "Have to notice this temporary password(" +
                temporaryPassword +
                ") to the user(" +
                this.selectedRow[0].employeeNo +
                "/" +
                this.selectedRow[0].employeeName +
                ")."
            );
          }
        })
        .catch(function (error) {
          console.log("[ERR/CREATEPASSWORD]" + error);
        });
    },
    getAdminUsers: function () {
      let path = "/api/admin-web/user/";
      path += this.readAll ? "all" : "available";

      this.$axios
        .get(path)
        .then((response) => {
          this.users = [];

          for (let idx in response.data) {
            let user = {
              employeeCompany: response.data[idx].employeeCompany,
              employeeNo: response.data[idx].employeeNo,
              employeeName: response.data[idx].employeeName,
              employeePosition: response.data[idx].employeePosition,
              employeeDivision: response.data[idx].employeeDivision,
              employeePw: response.data[idx].employeePw,
              employeeTeam: response.data[idx].employeeTeam,
              employeeEmail: response.data[idx].employeeEmail,
              employeePhone: response.data[idx].employeePhone,
              employeeNameEng: response.data[idx].employeeNameEng,
              usageExpDate: response.data[idx].usageExpDate,
            };
            this.users.push(user);
          }
        })
        .catch(function (error) {
          console.log("[ERR/GET]" + error);
        });
    },
  },
};
</script>

<style scoped></style>

 

본 코드에서 아래 사항에 대해만 일부 수정하였습니다.

<template>

<template>
  ... 
    <v-row>
      ...
        <v-col class="align-self-center" :cols="8">
        <div class="d-flex justify-end">
          ...
          <v-dialog v-model="dialogCreatePassword" persistent max-width="450">
            <template v-slot:activator="{ on, attrs }">
              <v-btn
                text
                outlined
                class="mx-md-1 elevation-2"
                :disabled="!hasSelectedRow()"
                v-bind="attrs"
                v-on="on"
                >CREATE PASSWORD
              </v-btn>
            </template>
            <v-card>
              <v-card-title class="text-h5">
                Are you sure you want to create temporary password for the user?
              </v-card-title>
              <v-card-text
                >Previous password cannot be restored, and are immediately
                reflected on the admin portal after creation temporary password.
              </v-card-text>
              <v-card-actions>
                <v-spacer></v-spacer>
                <v-btn
                  color="blue darken-1"
                  text
                  @click="dialogCreatePassword = false"
                >
                  Cancel
                </v-btn>
                <v-btn color="blue darken-1" text @click="createPassword">
                  Confirm
                </v-btn>
              </v-card-actions>
            </v-card>
          </v-dialog>
        </div>
      </v-col>
    </v-row>
  ...
</template>

 

<script>

<script>
...
export default {
  ...
  data() {
    return {
      ...
      dialogDelete: false,
      dialogCreatePassword: false,
      ...
    };
  },
  methods: {
    ...
    createPassword: function () {
      this.dialogCreatePassword = false;

      // Generate random string
      let temporaryPassword = Math.random().toString(36).substring(2, 11);
      console.log(temporaryPassword);

      let path = "/api/admin-web/user/update";
      let jsonData = {
        employeeNo: this.selectedRow[0].employeeNo,
        employeePw: temporaryPassword,
        registerEmployeeNo: "000000",
        updateEmployeeNo: "000000",
        pwTrialState: "0",
        temporaryPwState: "Y",
      };

      this.$axios
        .put(path, jsonData)
        .then((response) => {
          if (response.statusText == "OK") {
            alert(
              "Have to notice this temporary password(" +
                temporaryPassword +
                ") to the user(" +
                this.selectedRow[0].employeeNo +
                "/" +
                this.selectedRow[0].employeeName +
                ")."
            );
          }
        })
        .catch(function (error) {
          console.log("[ERR/CREATEPASSWORD]" + error);
        });
    },
    ...
</script>
  • Math API의 난수 생성 기능을 통해 임시 비밀번호 발급
  • 발급된 임시 비밀번호를 DB에 비밀번호 변경 로직을 수행하도록 REST API 연동

 

 


댓글