Bläddra i källkod

Multi-tenancy update access control api to dwan api
https://dev.wormwood.com.sg/zentao/task-view-424.html

vbea 1 år sedan
förälder
incheckning
690ff01b7e

+ 26 - 0
Strides-Admin/src/api/apiAccess.js

@@ -0,0 +1,26 @@
+import {get, post, put, del} from '../http/http'
+
+const prefix = "dawn/api/v1/"
+
+const apiAccess = {
+  getAccessPages(params) {
+    return post(prefix + 'access/user-pages', params)
+  },
+  getRoleOptions(params) {
+    return get(prefix + 'access/roles', params)
+  },
+  addAccessUser(params) {
+    return post(prefix + 'access/users', params)
+  },
+  infoAccessUser(userPk) {
+    return get(prefix + 'access/users/' + userPk)
+  },
+  updateAccessUser(params) {
+    return put(prefix + 'access/users', params)
+  },
+  deleteAccessUser(userPk) {
+    return del(prefix + 'access/users/' + userPk)
+  }
+}
+
+export default apiAccess;

+ 17 - 2
Strides-Admin/src/router/AccessRouter.js

@@ -1,6 +1,6 @@
 import Layout from '@/layout'
 import Layout from '@/layout'
 
 
-export default {
+export default [{
   path: '/access-control',
   path: '/access-control',
   component: Layout,
   component: Layout,
   children: [
   children: [
@@ -15,4 +15,19 @@ export default {
       }
       }
     }
     }
   ],
   ],
-}
+},{
+  path: '/access-control/index',
+  component: Layout,
+  children: [
+    {
+      path: '/access-control/index',
+      component: () => import('@/views/access/index2'),
+      name: 'access-control-v2',
+      meta: {
+        title: 'Access Control',
+        icon: 'access-control',
+        activeIcon: 'access-control-active',
+      }
+    }
+  ]
+}]

+ 1 - 1
Strides-Admin/src/router/index.js

@@ -89,7 +89,7 @@ const constantRoutes = [
   NotificationRouter,
   NotificationRouter,
   MarketingRouter,
   MarketingRouter,
   PartnershipRouter,
   PartnershipRouter,
-  AccessRouter,
+  ...AccessRouter,
   ...additionalRoute,
   ...additionalRoute,
   SettingsRouter
   SettingsRouter
 ]
 ]

+ 1 - 1
Strides-Admin/src/views/access/DialogDetail.vue

@@ -332,7 +332,7 @@ export default {
         userName: "",
         userName: "",
         email: "",
         email: "",
         phone: "",
         phone: "",
-        roleName: this.roleOptions[0].roleName,
+        roleName: this.roleOptions.length ? this.roleOptions[0].roleName : "",
         lastLogin: "",
         lastLogin: "",
         password: "",
         password: "",
         countryCode: settings.defaultCountry,
         countryCode: settings.defaultCountry,

+ 522 - 0
Strides-Admin/src/views/access/detail2.vue

@@ -0,0 +1,522 @@
+<template>
+  <el-dialog
+    class="dialog-access"
+    :visible="visible"
+    :before-close="e => hideDialog(false)"
+    :close-on-click-modal="false"
+    :title="isEdit ? 'Update User' : 'Add User'">
+    <el-form
+      ref="acsForm"
+      :model="form"
+      :rules="rules"
+      label-position="top"
+      v-loading="initial">
+      <div class="form-row">
+        <el-form-item
+          prop="userName"
+          class="form-item"
+          label="NAME:">
+          <el-input
+            v-model="form.userName"
+            class="flex-item"
+            maxlength="20"/>
+        </el-form-item>
+        <!--el-form-item
+          prop="phone"
+          class="form-item"
+          label="CONTACT NO.:">
+          <div class="flexc flex-item">
+            <el-select
+              style="min-width: 70px; max-width: 78px;margin-right: 10px;"
+              v-model="form.callingCode">
+              <el-option
+                v-for="(item,index) in callingOptions"
+                :key="index"
+                :label="'+' + item.callingCode"
+                :value="item.callingCode"
+              />
+            </el-select>
+            <el-input
+              v-model="form.phone"
+              class="flex1"
+              maxlength="12"
+            />
+          </div>
+        </el-form-item-->
+        <el-form-item
+          prop="email"
+          class="form-item"
+          label="EMAIL:">
+          <el-input
+            v-model="form.email"
+            class="flex-item"
+            maxlength="50"/>
+        </el-form-item>
+      </div>
+      <div class="form-row">
+        <el-form-item
+          label="Country:"
+          prop="countryCode"
+          class="form-item">
+          <el-select
+            v-model="form.countryCode"
+            class="flex-item">
+            <el-option
+              v-for="item in countryOptions"
+              :key="item.countryCode"
+              :label="item.countryName"
+              :value="item.countryCode" />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          class="form-item"
+          :class="{'is-required': !isEdit}"
+          label="SET PASSWORD:"
+          prop="password">
+          <el-input
+            v-model="form.password"
+            class="flex-item"
+            type="password"
+            maxlength="32"/>
+          <template slot="label">
+            <span>SET PASSWORD:</span>
+            <el-tooltip
+              v-if="showPasswordTip"
+              effect="dark"
+              :content="passwordTips"
+              placement="top"
+              popper-class="access-password-strength-tips">
+              <i class="el-icon-info"/>
+            </el-tooltip>
+          </template>
+        </el-form-item>
+      </div>
+      <div class="form-row">
+        <el-form-item
+          class="form-item"
+          label="ROLE:">
+          <el-select
+            v-model="form.roleName"
+            class="flex-item"
+            @change="changeRole"
+            v-if="roleOptions">
+            <el-option
+              v-for="(item, index) in roleOptions"
+              :key="index"
+              :label="item.roleDesc"
+              :value="item.roleName"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          class="form-item"
+          label="PROVIDER NAME:"
+          prop="providerPk"
+          v-if="form.roleName=='PROVIDER'">
+          <el-select
+            v-model="form.providerPk"
+            class="flex-item2">
+            <el-option
+              v-for="(item, index) in providerOptions"
+              :key="index"
+              :label="item.key"
+              :value="item.value"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          class="form-item"
+          label="GROUP NAME:"
+          prop="groupPk"
+          v-else-if="form.roleName=='GROUP'">
+          <el-select
+            v-model="form.groupPk"
+            class="flex-item2">
+            <el-option
+              v-for="(item, index) in groupOptions"
+              :key="index"
+              :label="item.key"
+              :value="item.value"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          class="form-item"
+          label="SITE ALLOCATION:"
+          prop="sitePks"
+          v-else-if="form.roleName=='SITE' || form.roleName=='STACK HOLDER'">
+          <el-select
+            v-model="form.sitePks"
+            class="flex-item"
+            filterable
+            multiple
+            placeholder="Select with search">
+            <el-option
+              v-for="(item, index) in siteOptions"
+              :key="index"
+              :label="item.siteName"
+              :value="item.sitePk"/>
+          </el-select>
+        </el-form-item>
+        <div class="form-item flex-item" v-else></div>
+      </div>
+      <div class="flexcc" style="margin-top: 10px;">
+        <el-button
+          class="button"
+          type="primary"
+          :loading="loading"
+          @click="onFormSave">
+          <span style="padding: 0 20px;">SAVE</span>
+        </el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import api from '@/api/apiAccess'
+import apiBase from '@/api/apiBase'
+import site from '@/http/api/site'
+import group from '@/http/api/group'
+import provider from '@/http/api/provider'
+import settings from '../../settings.js'
+import {getCountryList} from '../../utils/index.js'
+export default {
+  name: "DialogDetail",
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    isEdit: {
+      type: Boolean,
+      default: false
+    },
+    id: {
+      type: String|Number,
+      default: ''
+    },
+    roleOptions: {
+      type: Array,
+      default: () => []
+    }
+  },
+  data() {
+    return {
+      initial: false,
+      loading: false,
+      form: {
+        userPk: undefined,
+        userName: "",
+        email: "",
+        roleName: "",
+        lastLogin: "",
+        password: "",
+        countryCode: settings.defaultCountry,
+        callingCode: settings.defaultCalling,
+        providerPk: "",
+        groupPk: "",
+        sitePks: []
+      },
+      rules: {
+        userName: {
+          required: true,
+          message: "Username is required",
+          trigger: "blur"
+        },
+        phone: [{
+          required: true,
+          message: "Contact No. is required",
+          trigger: "blur"
+        }, {
+          pattern: /^\d{6,}$/,
+          trigger: 'blur',
+          message: 'Please type a correct phone'
+        }],
+        email: [{
+          message: "Email is required",
+          trigger: "blur",
+          required: true,
+        },{
+          pattern: /^[a-zA-Z0-9]+[\S]+@[a-zA-Z0-9_-]+[\.][\Sa-zA-Z]+$/,
+          trigger: 'blur',
+          message: 'Please type a correct email'
+        }],
+        countryCode: [{
+          required: true,
+          message: "Country is required",
+          trigger: "change"
+        }],
+        password: [{
+          required: false,
+          //message: "Passwrod is required",
+          trigger: "blur",
+          validator: (rule, value, callback) => {
+            if (value) {
+              if (settings.enablePassword12) {
+                var strength = 0;
+                if (value.length >= 12) {
+                  strength += 1;
+                }
+                if (/\d{1,}/.test(value)) {
+                  strength += 1;
+                }
+                if (/[a-z]{1,}/.test(value)) {
+                  strength += 1;
+                }
+                if (/[A-Z]{1,}/.test(value)) {
+                  strength += 1;
+                }
+                if (/\W{1,}/.test(value)) {
+                  strength += 1;
+                }
+                if (strength>=5) {
+                  callback()
+                } else {
+                  callback("The password is not strength")
+                }
+              } else {
+                if (value.length < 6) {
+                  callback("Password needs to be more than 6 characters")
+                } else {
+                  callback()
+                }
+              }
+            } else if (!this.isEdit) {
+              callback("Passwrod is required")
+            } else {
+              callback()
+            }
+          }
+        }],
+        providerPk: {
+          required: true,
+          message: "Provider is required",
+          trigger: "change"
+        },
+        groupPk: {
+          required: true,
+          message: "Group is required",
+          trigger: "change"
+        },
+        sitePks: {
+          required: true,
+          message: "Please select at least one site",
+          trigger: "change"
+        }
+      },
+      countryOptions: [],
+      siteOptions: [],
+      groupOptions: [],
+      callingOptions: [],
+      providerOptions: [],
+      showPasswordTip: settings.enablePassword12,
+      passwordTips: "Passwords must be at least 12 characters long and include a combination of uppercase and lowercase letters, numbers, and special characters (e.g., !, @, #, $)"
+    };
+  },
+  watch: {
+    id(n, o) {
+      if (this.visible && n) {
+        this.$nextTick(() => {
+          this.getUserInfo();
+        })
+      }
+    }
+  },
+  mounted() {
+    this.getOptions();
+  },
+  methods: {
+    hideDialog(success) {
+      this.init();
+      this.$emit("hide", success || false);
+    },
+    init() {
+      this.form = {
+        userPk: undefined,
+        userName: "",
+        email: "",
+        phone: "",
+        roleName: this.roleOptions.length ? this.roleOptions[0].roleName : "",
+        lastLogin: "",
+        password: "",
+        countryCode: settings.defaultCountry,
+        callingCode: settings.defaultCalling,
+        providerPk: "",
+        groupPk: "",
+        sitePks: []
+      }
+      this.loading = false;
+      this.$nextTick(() => {
+        if (this.$refs['acsForm']) {
+          this.$refs['acsForm'].clearValidate();
+        }
+      })
+    },
+    getOptions() {
+      /*getCountryList(list => {
+        this.callingOptions = list
+      });*/
+      apiBase.getCountryList().then(res => {
+        if (res.data) {
+          this.countryOptions = res.data
+        }
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+      apiBase.getProviderList().then(res => {
+        if (res.data) {
+          this.providerOptions = res.data
+        }
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+      apiBase.getUserGroupOptions().then(res => {
+        if (res.data) {
+          this.groupOptions = res.data
+        }
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+      this.getAllSite()
+    },
+    getAllSite(siteKeyword) {
+      site.getAllSiteList({siteName: siteKeyword || ""}).then(res => {
+        if (res.data && res.data.length > 0) {
+          this.siteOptions = res.data
+        } else {
+          this.siteOptions = []
+        }
+        this.init();
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+        this.siteOptions = []
+      });
+    },
+    getUserInfo() {
+      this.initial = true;
+      api.infoAccessUser(this.id).then(res => {
+        if (res.data) {
+          this.form = res.data
+        }
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      }).finally(() => {
+        this.initial = false;
+      })
+    },
+    changeRole() {
+      this.form.providerPk = ""
+      this.form.groupPk = ""
+      this.form.sitePks = []
+      this.$nextTick(() => {
+        this.$refs['acsForm'].clearValidate();
+      })
+    },
+    onFormSave() {
+      this.$refs['acsForm'].validate((valid) => {
+        if (valid) {
+          this.isEdit ? this.updateUser() : this.addUser();
+        }
+      })
+    },
+    addUser() {
+      this.loading = true;
+      api.addAccessUser(this.form).then(res => {
+        this.$message({
+          type: 'success',
+          message: "Add successfully"
+        });
+        this.hideDialog(true);
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+    },
+    updateUser() {
+      this.loading = true;
+      api.updateAccessUser(this.form).then(res => {
+        this.$message({
+          type: 'success',
+          message: "Update successfully"
+        });
+        this.hideDialog(true);
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+.dialog-access {
+  display: flex;
+  align-items: center;
+  flex-direction: column;
+  justify-content: center;
+}
+.dialog-access >>> .el-dialog {
+  width: 100%;
+  max-width: 620px;
+  margin-top: 0 !important;
+}
+.dialog-access >>> .el-dialog__body {
+  padding: 10px 20px 30px;
+}
+.dialog-access >>> .el-form {
+  padding-right: 10px;
+}
+.form-row {
+  display: flex;
+  flex-wrap: wrap;
+  padding-bottom: 5px;
+}
+.form-item {
+  flex: 1;
+  margin-left: 10px;
+  margin-bottom: 10px;
+}
+.form-item >>> label {
+  padding: 0;
+}
+.flex-item {
+  width: 100%;
+  min-width: 200px;
+  max-width: 270px;
+}
+.flex-item2 {
+  width: 100%;
+  min-width: 200px;
+}
+@media screen and (max-width: 500px) {
+  .flex-item {
+    width: 100%;
+    max-width: none;
+  }
+}
+</style>
+<style>
+.access-password-strength-tips {
+  max-width: 270px;
+}
+</style>

+ 2 - 0
Strides-Admin/src/views/access/index.vue

@@ -143,6 +143,8 @@ export default {
         if (res.data) {
         if (res.data) {
           this.dialogAction.roleOptions = res.data
           this.dialogAction.roleOptions = res.data
         }
         }
+      }).catch(err => {
+        //console.error("getRoleOptions", err);
       });
       });
     },
     },
     getTableData() {
     getTableData() {

+ 234 - 0
Strides-Admin/src/views/access/index2.vue

@@ -0,0 +1,234 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="filter-view">
+        <el-select
+          v-model="params.pageCriteria.roleName"
+          class="filter-view-item"
+          placeholder="Role"
+          @change="toSearch"
+          clearable>
+          <el-option
+            v-for="(item, index) in dialogAction.roleOptions"
+            :key="index"
+            :label="item.roleDesc"
+            :value="item.roleName"/>
+        </el-select>
+        <div class="flex1" style="max-width: 350px;">
+          <el-input
+            v-model="params.pageCriteria.criteria"
+            prefix-icon="el-icon-search"
+            placeholder="Search by Name"
+            @keyup.enter.native="toSearch"
+            @change="toSearch"
+            clearable/>
+        </div>
+        <div class="filter-flex-button">
+          <el-button
+            type="primary"
+            icon="el-icon-plus"
+            @click="addUser">
+            Add User
+          </el-button>
+        </div>
+      </div>
+    </div>
+    <el-table
+      v-loading="table.loading"
+      :data="table.list"
+      class="no-border"
+      fit>
+      <el-table-column
+        label="Name"
+        align="center"
+        min-width="100">
+          <template slot-scope="{row}">
+            <div class="link-type" @click="updateUser(row)">{{ row.userName }}</div>
+          </template>
+      </el-table-column>
+      <el-table-column
+        label="Email Address"
+        align="center"
+        prop="email"
+        min-width="120"/>
+      <el-table-column
+        label="Role"
+        align="center"
+        prop="roleName"
+        min-width="100"/>
+      <el-table-column
+        label="Description"
+        align="center"
+        prop="desc"
+        min-width="150">
+        <template slot-scope="{row}">
+          <div
+            v-for="item in row.desc"
+            v-if="row.desc"
+            :key="item">
+            {{item}}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="Last Login"
+        align="center"
+        prop="lastLogin"
+        min-width="120"/>
+      <el-table-column
+        label="Action"
+        align="center"
+        width="100">
+        <template slot-scope="{row}">
+          <el-dropdown
+            class="action-dropdown"
+            @command="(v) => handleCommand(v, row)">
+            <i class="el-icon-more icon-action"></i>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item
+                command="updateUser">
+                Edit
+              </el-dropdown-item>
+              <el-dropdown-item
+                command="deleteUser">
+                Delete
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+          <!-- <TableAction
+            @edit="updateUser(row)"
+            @delete="deleteUser(row)"/> -->
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="right">
+      <pagination
+        v-show="table.total > 0"
+        :total="table.total"
+        :page.sync="params.pageNum"
+        :limit.sync="params.pageSize"
+        @pagination="getTableData" />
+    </div>
+    <DialogDetail
+      v-bind="dialogAction"
+      @hide="hideDialog"/>
+  </div>
+</template>
+
+<script>
+import api from '@/api/apiAccess'
+import Pagination from '@/components/Pagination'
+import TableAction from '@/components/TableAction'
+import DialogDetail from './detail2'
+export default {
+  data() {
+    return {
+      params: {
+        pageNum: 1,
+        pageSize: 10,
+        pageCriteria: {
+          criteria: "",
+          roleName: ""
+        }
+      },
+      table: {
+        loading: false,
+        list: [],
+        total: 0
+      },
+      dialogAction: {
+        isEdit: false,
+        visible: false,
+        roleOptions: []
+      }
+    }
+  },
+  components: { Pagination,TableAction,DialogDetail },
+  created() {
+    this.getRoleOptions();
+    this.getTableData()
+  },
+  methods: {
+    toSearch() {
+      this.params.pageNum = 1;
+      this.getTableData();
+    },
+    getRoleOptions() {
+      api.getRoleOptions().then(res => {
+        if (res.data) {
+          this.dialogAction.roleOptions = res.data
+        }
+      });
+    },
+    getTableData() {
+      this.table.loading = true;
+      api.getAccessPages(this.params).then(res => {
+        if (res.data.records && res.data.totalRow) {
+          this.table.list = res.data.records;
+          this.table.total = res.data.totalRow;
+        } else {
+          this.table.total = 0;
+          this.table.list = [];
+        }
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+        this.table.total = 0;
+        this.table.list = [];
+      }).finally(() => {
+        this.table.loading = false
+      })
+    },
+    hideDialog(e) {
+      this.dialogAction.id = "";
+      this.dialogAction.visible = false;
+      if (e)
+        this.getTableData();
+    },
+    handleCommand(cb, item) {
+      this[cb](item)
+    },
+    addUser() {
+      this.dialogAction.id = "";
+      this.dialogAction.isEdit = false;
+      this.dialogAction.visible = true;
+    },
+    updateUser(row) {
+      this.dialogAction.id = row.userPk;
+      this.dialogAction.isEdit = true;
+      this.dialogAction.visible = true;
+    },
+    deleteUser(row) {
+      this.$confirm('Are you sure you want to delete this user?', 'Delete', {
+        confirmButtonText: 'Confirm',
+        cancelButtonText: 'Cancel',
+        type: 'warning'
+      }).then(res => {
+        this.onDeleteUser(row.userPk);
+      })
+    },
+    onDeleteUser(id) {
+      this.table.loading = true;
+      api.deleteAccessUser(id).then(res => {
+        this.$message({
+          type: 'success',
+          message: "Successfully deleted!"
+        })
+        this.getTableData()
+      }).catch(err => {
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      }).finally(() => {
+        this.table.loading = false
+      })
+    }
+  }
+}
+</script>
+
+<style>
+</style>