forked from geolba/tethys.backend
- add password strength meter for creating or editing user passwords
- add public opensearch api host
This commit is contained in:
parent
f4854d70b9
commit
010bead723
|
@ -14,7 +14,7 @@ import env from '#start/env';
|
|||
// import { default as Dataset } from '#models/dataset';
|
||||
|
||||
const opensearchNode = env.get('OPENSEARCH_HOST', 'localhost');
|
||||
const client = new Client({ node: `http://${opensearchNode}` }); // replace with your OpenSearch endpoint
|
||||
const client = new Client({ node: `${opensearchNode}` }); // replace with your OpenSearch endpoint
|
||||
|
||||
export default class IndexDatasets extends BaseCommand {
|
||||
static commandName = 'index:datasets';
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
"assets/resources_js_Pages_Admin_Role_Show_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Role_Show_vue.js",
|
||||
"assets/resources_js_Pages_Admin_Settings_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_Settings_vue.js",
|
||||
"assets/resources_js_Pages_Admin_User_Create_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Create_vue.js",
|
||||
"assets/resources_js_Pages_Admin_User_Edit_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Edit_vue.js",
|
||||
"assets/resources_js_Pages_Admin_User_Edit_vue-resources_js_Components_SimplePasswordMeter_password-m-6dc207.css": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Edit_vue-resources_js_Components_SimplePasswordMeter_password-m-6dc207.css",
|
||||
"assets/resources_js_Pages_Admin_User_Edit_vue-resources_js_Components_SimplePasswordMeter_password-m-6dc207.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Edit_vue-resources_js_Components_SimplePasswordMeter_password-m-6dc207.js",
|
||||
"assets/resources_js_Pages_Admin_User_Index_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Index_vue.js",
|
||||
"assets/resources_js_Pages_Admin_User_Show_vue.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Show_vue.js",
|
||||
"assets/resources_js_Pages_App_vue.js": "http://localhost:8080/assets/resources_js_Pages_App_vue.js",
|
||||
"assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css.css": "http://localhost:8080/assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css.css",
|
||||
"assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css.js": "http://localhost:8080/assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css.js",
|
||||
"assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css-resources_js_Components_-06c7b5.css": "http://localhost:8080/assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css-resources_js_Components_-06c7b5.css",
|
||||
"assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css-resources_js_Components_-06c7b5.js": "http://localhost:8080/assets/resources_js_Pages_Auth_AccountInfo_vue-resources_js_utils_toast_css-resources_js_Components_-06c7b5.js",
|
||||
"assets/resources_js_Pages_Auth_Login_vue.js": "http://localhost:8080/assets/resources_js_Pages_Auth_Login_vue.js",
|
||||
"assets/resources_js_Pages_Auth_Register_vue.js": "http://localhost:8080/assets/resources_js_Pages_Auth_Register_vue.js",
|
||||
"assets/resources_js_Pages_Dashboard_vue.js": "http://localhost:8080/assets/resources_js_Pages_Dashboard_vue.js",
|
||||
|
@ -49,9 +50,9 @@
|
|||
"assets/vendors-node_modules_mdi_js_mdi_js-node_modules_vue-loader_dist_exportHelper_js.js": "http://localhost:8080/assets/vendors-node_modules_mdi_js_mdi_js-node_modules_vue-loader_dist_exportHelper_js.js",
|
||||
"assets/vendors-node_modules_focus-trap_dist_focus-trap_esm_js-node_modules_notiwind_dist_index_esm_js.js": "http://localhost:8080/assets/vendors-node_modules_focus-trap_dist_focus-trap_esm_js-node_modules_notiwind_dist_index_esm_js.js",
|
||||
"assets/vendors-node_modules_vue-facing-decorator_dist_esm_utils_js.js": "http://localhost:8080/assets/vendors-node_modules_vue-facing-decorator_dist_esm_utils_js.js",
|
||||
"assets/vendors-node_modules_leaflet_dist_leaflet-src_js-node_modules_leaflet_src_control_Control_Att-4ee9a6.js": "http://localhost:8080/assets/vendors-node_modules_leaflet_dist_leaflet-src_js-node_modules_leaflet_src_control_Control_Att-4ee9a6.js",
|
||||
"assets/vendors-node_modules_leaflet_dist_leaflet-src_js-node_modules_leaflet_src_control_Control_Att-adabdc.js": "http://localhost:8080/assets/vendors-node_modules_leaflet_dist_leaflet-src_js-node_modules_leaflet_src_control_Control_Att-adabdc.js",
|
||||
"assets/vendors-node_modules_toastify-js_src_toastify_js.js": "http://localhost:8080/assets/vendors-node_modules_toastify-js_src_toastify_js.js",
|
||||
"assets/vendors-node_modules_buffer_index_js-node_modules_leaflet_src_layer_tile_TileLayer_WMS_js-nod-e7bc71.js": "http://localhost:8080/assets/vendors-node_modules_buffer_index_js-node_modules_leaflet_src_layer_tile_TileLayer_WMS_js-nod-e7bc71.js",
|
||||
"assets/vendors-node_modules_buffer_index_js-node_modules_vuedraggable_dist_vuedraggable_umd_js.js": "http://localhost:8080/assets/vendors-node_modules_buffer_index_js-node_modules_vuedraggable_dist_vuedraggable_umd_js.js",
|
||||
"assets/vendors-node_modules_numeral_numeral_js-node_modules_chart_js_dist_chart_js.js": "http://localhost:8080/assets/vendors-node_modules_numeral_numeral_js-node_modules_chart_js_dist_chart_js.js",
|
||||
"assets/resources_js_Components_BaseButton_vue.js": "http://localhost:8080/assets/resources_js_Components_BaseButton_vue.js",
|
||||
"assets/resources_js_Stores_main_ts-resources_js_Components_BaseDivider_vue-resources_js_Components_C-b45805.js": "http://localhost:8080/assets/resources_js_Stores_main_ts-resources_js_Components_BaseDivider_vue-resources_js_Components_C-b45805.js",
|
||||
|
@ -64,6 +65,7 @@
|
|||
"assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js": "http://localhost:8080/assets/resources_js_Components_Admin_Sort_vue-resources_js_Components_SectionTitleLineWithButton_vue.js",
|
||||
"assets/resources_js_Components_CardBoxModal_vue.js": "http://localhost:8080/assets/resources_js_Components_CardBoxModal_vue.js",
|
||||
"assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-bdf2f9.js": "http://localhost:8080/assets/resources_js_Components_FileUpload_vue-resources_js_Components_FormCheckRadioGroup_vue-resour-bdf2f9.js",
|
||||
"assets/resources_js_Components_SectionTitleLineWithButton_vue-resources_js_Components_SimplePassword-945989.js": "http://localhost:8080/assets/resources_js_Components_SectionTitleLineWithButton_vue-resources_js_Components_SimplePassword-945989.js",
|
||||
"assets/fonts/inter-latin-ext-400-normal.woff": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.40b3b0d5.woff",
|
||||
"assets/fonts/inter-latin-ext-400-normal.woff2": "http://localhost:8080/assets/fonts/inter-latin-ext-400-normal.0f9e8d4e.woff2",
|
||||
"assets/fonts/inter-latin-400-normal.woff": "http://localhost:8080/assets/fonts/inter-latin-400-normal.08a02fd2.woff",
|
||||
|
@ -85,5 +87,8 @@
|
|||
"assets/images/marker-icon.png": "http://localhost:8080/assets/images/marker-icon.2b3e1faf.png",
|
||||
"assets/images/layers-2x.png": "http://localhost:8080/assets/images/layers-2x.8f2c4d11.png",
|
||||
"assets/images/layers.png": "http://localhost:8080/assets/images/layers.416d9136.png",
|
||||
"assets/images/Close.svg": "http://localhost:8080/assets/images/Close.e4887675.svg"
|
||||
"assets/images/Close.svg": "http://localhost:8080/assets/images/Close.e4887675.svg",
|
||||
"assets/vendors-node_modules_vue-facing-decorator_dist_esm_index_js-node_modules_vue-facing-decorator-818045.js": "http://localhost:8080/assets/vendors-node_modules_vue-facing-decorator_dist_esm_index_js-node_modules_vue-facing-decorator-818045.js",
|
||||
"assets/resources_js_Pages_Admin_User_Create_vue-resources_js_Components_SimplePasswordMeter_password-f3312a.css": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Create_vue-resources_js_Components_SimplePasswordMeter_password-f3312a.css",
|
||||
"assets/resources_js_Pages_Admin_User_Create_vue-resources_js_Components_SimplePasswordMeter_password-f3312a.js": "http://localhost:8080/assets/resources_js_Pages_Admin_User_Create_vue-resources_js_Components_SimplePasswordMeter_password-f3312a.js"
|
||||
}
|
|
@ -7,7 +7,7 @@ import { canvas } from 'leaflet/src/layer/vector/Canvas';
|
|||
import { svg } from 'leaflet/src/layer/vector/SVG';
|
||||
import axios from 'axios';
|
||||
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
|
||||
// import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
|
||||
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
|
||||
import { TileLayer } from 'leaflet/src/layer/tile/TileLayer';
|
||||
import { Attribution } from 'leaflet/src/control/Control.Attribution';
|
||||
import DrawControlComponent from '@/Components/Map/draw.component.vue';
|
||||
|
@ -60,7 +60,7 @@ Map.include({
|
|||
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
|
||||
const DEFAULT_BASE_LAYER_ATTRIBUTION = '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
||||
// const OPENSEARCH_HOST = 'http://localhost:9200';
|
||||
const OPENSEARCH_HOST = 'http://192.168.21.18';
|
||||
const OPENSEARCH_HOST = `${process.env.OPENSEARCH_HOST}`;
|
||||
// const OPENSEARCH_HOST = `http://${process.env.OPENSEARCH_PUBLIC_HOST}`;
|
||||
let map: Map;
|
||||
|
||||
|
@ -134,21 +134,21 @@ const initMap = async () => {
|
|||
const attributionControl = new Attribution().addTo(map);
|
||||
attributionControl.setPrefix(false);
|
||||
|
||||
// let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
|
||||
// format: 'image/png',
|
||||
// attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
||||
// layers: 'OSM-WMS',
|
||||
// });
|
||||
|
||||
let baseAt = new TileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
|
||||
subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
|
||||
let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
|
||||
format: 'image/png',
|
||||
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
||||
layers: 'OSM-WMS',
|
||||
});
|
||||
|
||||
// let baseAt = new TileLayer('https://{s}.wien.gv.at/basemap/bmapgrau/normal/google3857/{z}/{y}/{x}.png', {
|
||||
// subdomains: ['maps', 'maps1', 'maps2', 'maps3', 'maps4'],
|
||||
// attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
|
||||
// });
|
||||
|
||||
let layerOptions = {
|
||||
label: DEFAULT_BASE_LAYER_NAME,
|
||||
visible: true,
|
||||
layer: baseAt,
|
||||
layer: osmGgray,
|
||||
};
|
||||
layerOptions.layer.addTo(map);
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// common passwords as an array of strings
|
||||
|
||||
const commonPasswords = [
|
||||
'123456',
|
||||
'qwerty',
|
||||
'password',
|
||||
'111111',
|
||||
'Abc123',
|
||||
'123456789',
|
||||
'12345678',
|
||||
'123123',
|
||||
'1234567890',
|
||||
'12345',
|
||||
'1234567',
|
||||
'qwertyuiop',
|
||||
'qwerty123',
|
||||
'1q2w3e',
|
||||
'password1',
|
||||
'123321',
|
||||
'Iloveyou',
|
||||
'12345',
|
||||
'test',
|
||||
'test007'
|
||||
];
|
||||
|
||||
export default commonPasswords;
|
|
@ -0,0 +1,9 @@
|
|||
export default class TrieNode {
|
||||
children: { [key: string]: TrieNode };
|
||||
isEndOfWord: boolean;
|
||||
|
||||
constructor() {
|
||||
this.children = {};
|
||||
this.isEndOfWord = false;
|
||||
}
|
||||
}
|
30
resources/js/Components/SimplePasswordMeter/logic/Trie.ts
Normal file
30
resources/js/Components/SimplePasswordMeter/logic/Trie.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
import TrieNode from './TieNode';
|
||||
|
||||
export default class Trie {
|
||||
private root: TrieNode;
|
||||
constructor() {
|
||||
this.root = new TrieNode();
|
||||
}
|
||||
|
||||
insert(word: string) {
|
||||
let node: TrieNode = this.root;
|
||||
for (let char of word) {
|
||||
if (!node.children[char]) {
|
||||
node.children[char] = new TrieNode();
|
||||
}
|
||||
node = node.children[char];
|
||||
}
|
||||
node.isEndOfWord = true;
|
||||
}
|
||||
|
||||
search(word: string) {
|
||||
let node = this.root;
|
||||
for (let char of word) {
|
||||
if (!node.children[char]) {
|
||||
return false;
|
||||
}
|
||||
node = node.children[char];
|
||||
}
|
||||
return node.isEndOfWord;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
import commonPasswords from '../data/commonPasswords';
|
||||
import Trie from './Trie';
|
||||
|
||||
|
||||
|
||||
const checkStrength = (pass: string) => {
|
||||
const score = scorePassword(pass);
|
||||
const scoreLabel = mapScoreToLabel(score);
|
||||
return {
|
||||
score,
|
||||
scoreLabel
|
||||
}
|
||||
};
|
||||
|
||||
export default checkStrength;
|
||||
|
||||
// Function to score the password based on different criteria
|
||||
const scorePassword = (password: string): number => {
|
||||
if (password.length <= 6) return 0;
|
||||
if (isCommonPassword(password)) return 0;
|
||||
|
||||
let score = 0;
|
||||
score += getLengthScore(password);
|
||||
score += getSpecialCharScore(password);
|
||||
score += getCaseMixScore(password);
|
||||
score += getNumberMixScore(password);
|
||||
|
||||
return Math.min(score, 4); // Maximum score is 4
|
||||
};
|
||||
|
||||
// Initialize the Trie with common passwords
|
||||
const trie = new Trie();
|
||||
commonPasswords.forEach(password => trie.insert(password));
|
||||
const isCommonPassword = (password: string): boolean => {
|
||||
// return commonPasswords.includes(password);
|
||||
return trie.search(password);
|
||||
};
|
||||
|
||||
// Function to get the score based on password length
|
||||
const getLengthScore = (password: string): number => {
|
||||
if (password.length > 20 && !hasRepeatChars(password)) return 3;
|
||||
if (password.length > 12 && !hasRepeatChars(password)) return 2;
|
||||
if (password.length > 8) return 1;
|
||||
return 0;
|
||||
};
|
||||
// Function to check if the password contains repeated characters
|
||||
const hasRepeatChars = (password: string): boolean => {
|
||||
const repeatCharRegex = /(\w)(\1+\1+\1+\1+)/g;
|
||||
return repeatCharRegex.test(password);
|
||||
};
|
||||
|
||||
// Function to get the score based on the presence of special characters
|
||||
const getSpecialCharScore = (password: string): number => {
|
||||
const specialCharRegex = /[^A-Za-z0-9]/g;
|
||||
return specialCharRegex.test(password) ? 1 : 0;
|
||||
};
|
||||
|
||||
// Function to get the score based on the mix of uppercase and lowercase letters
|
||||
const getCaseMixScore = (password: string): number => {
|
||||
const hasUpperCase = /[A-Z]/.test(password);
|
||||
const hasLowerCase = /[a-z]/.test(password);
|
||||
return hasUpperCase && hasLowerCase ? 1 : 0;
|
||||
};
|
||||
|
||||
// Function to get the score based on the mix of letters and numbers
|
||||
const getNumberMixScore = (password: string): number => {
|
||||
const hasLetter = /[A-Za-z]/.test(password);
|
||||
const hasNumber = /[0-9]/.test(password);
|
||||
return hasLetter && hasNumber ? 1 : 0;
|
||||
};
|
||||
|
||||
// Function to map the score to a corresponding label
|
||||
const mapScoreToLabel = (score: number): string => {
|
||||
const labels = ['risky', 'guessable', 'weak', 'safe', 'secure'];
|
||||
return labels[score] || '';
|
||||
};
|
||||
|
||||
// const nameScore = (score: number): string => {
|
||||
// switch (score) {
|
||||
// case 0:
|
||||
// return 'risky';
|
||||
// case 1:
|
||||
// return 'guessable';
|
||||
// case 2:
|
||||
// return 'weak';
|
||||
// case 3:
|
||||
// return 'safe';
|
||||
// case 4:
|
||||
// return 'secure';
|
||||
// default:
|
||||
// return '';
|
||||
// }
|
||||
// };
|
|
@ -0,0 +1,5 @@
|
|||
// import scorePassword from './scorePassword'
|
||||
// import nameScore from './nameScore'
|
||||
import checkStrength from './checkStrength'
|
||||
|
||||
export { checkStrength }
|
|
@ -0,0 +1,66 @@
|
|||
// import { isCommonPassword } from "./isCommonPassword"
|
||||
import commonPasswords from '../data/commonPasswords';
|
||||
|
||||
const scorePassword = (pass: string): number => {
|
||||
let score = 0;
|
||||
let length = 0;
|
||||
let specialChar = 0;
|
||||
let caseMix = 0;
|
||||
let numCharMix = 0;
|
||||
|
||||
const specialCharRegex = /[^A-Za-z0-9]/g;
|
||||
const lowercaseRegex = /(.*[a-z].*)/g;
|
||||
const uppercaseRegex = /(.*[A-Z].*)/g;
|
||||
const numberRegex = /(.*[0-9].*)/g;
|
||||
const repeatCharRegex = /(\w)(\1+\1+\1+\1+)/g;
|
||||
|
||||
const hasSpecialChar = specialCharRegex.test(pass);
|
||||
const hasLowerCase = lowercaseRegex.test(pass);
|
||||
const hasUpperCase = uppercaseRegex.test(pass);
|
||||
const hasNumber = numberRegex.test(pass);
|
||||
const hasRepeatChars = repeatCharRegex.test(pass);
|
||||
|
||||
if (pass.length > 4) {
|
||||
if (isCommonPassword(pass)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((hasLowerCase || hasUpperCase) && hasNumber) {
|
||||
numCharMix = 1;
|
||||
}
|
||||
|
||||
if (hasUpperCase && hasLowerCase) {
|
||||
caseMix = 1;
|
||||
}
|
||||
|
||||
if ((hasLowerCase || hasUpperCase || hasNumber) && hasSpecialChar) {
|
||||
specialChar = 1;
|
||||
}
|
||||
|
||||
if (pass.length > 8) {
|
||||
length = 1;
|
||||
}
|
||||
|
||||
if (pass.length > 12 && !hasRepeatChars) {
|
||||
length = 2;
|
||||
}
|
||||
|
||||
if (pass.length > 20 && !hasRepeatChars) {
|
||||
length = 3;
|
||||
}
|
||||
|
||||
score = length + specialChar + caseMix + numCharMix;
|
||||
|
||||
if (score > 4) {
|
||||
score = 4;
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
};
|
||||
|
||||
export default scorePassword;
|
||||
|
||||
const isCommonPassword = (password: string): boolean => {
|
||||
return commonPasswords.includes(password);
|
||||
};
|
|
@ -0,0 +1,95 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { checkStrength } from './logic/index';
|
||||
|
||||
// Define props
|
||||
const props = defineProps<{
|
||||
password: string;
|
||||
}>();
|
||||
|
||||
// Define emits
|
||||
// const emit = defineEmits<{
|
||||
// (event: 'score', payload: { score: number; strength: string }): void;
|
||||
// }>();
|
||||
|
||||
const emit = defineEmits(['score']);
|
||||
|
||||
// const score = (event) => {
|
||||
// emit('score', event, payload: { score; strength: string });
|
||||
// };
|
||||
|
||||
// Computed property for password class
|
||||
const passwordClass = computed(() => {
|
||||
if (!props.password) {
|
||||
return null;
|
||||
}
|
||||
// const scoreLabel = checkStrength(props.password);
|
||||
// const score = scorePassword(props.password);
|
||||
const { score, scoreLabel } = checkStrength(props.password);
|
||||
emit('score', score);
|
||||
return {
|
||||
[scoreLabel]: true,
|
||||
// scored: true,
|
||||
};
|
||||
});
|
||||
|
||||
// export default {
|
||||
// name: 'PasswordMeter',
|
||||
// props: {
|
||||
// password: String,
|
||||
// },
|
||||
// emits: ['score'],
|
||||
// computed: {
|
||||
// passwordClass(): object | null {
|
||||
// if (!this.password) {
|
||||
// return null;
|
||||
// }
|
||||
// const strength = checkStrength(this.password);
|
||||
// const score = scorePassword(this.password);
|
||||
// this.$emit('score', { score, strength });
|
||||
// return {
|
||||
// [strength]: true,
|
||||
// scored: true,
|
||||
// };
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="po-password-strength-bar" :class="passwordClass" />
|
||||
</template>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.po-password-strength-bar {
|
||||
border-radius: 2px;
|
||||
transition: all 0.2s linear;
|
||||
height: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.po-password-strength-bar.risky {
|
||||
background-color: #f95e68;
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.po-password-strength-bar.guessable {
|
||||
background-color: #fb964d;
|
||||
width: 32.5%;
|
||||
}
|
||||
|
||||
.po-password-strength-bar.weak {
|
||||
background-color: #fdd244;
|
||||
width: 55%;
|
||||
}
|
||||
|
||||
.po-password-strength-bar.safe {
|
||||
background-color: #b0dc53;
|
||||
width: 77.5%;
|
||||
}
|
||||
|
||||
.po-password-strength-bar.secure {
|
||||
background-color: #35cc62;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Head, useForm, router } from '@inertiajs/vue3';
|
||||
import { mdiAccountKey, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||
|
@ -13,6 +14,16 @@ import BaseButton from '@/Components/BaseButton.vue';
|
|||
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
// import { Inertia } from '@inertiajs/inertia';
|
||||
import passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
|
||||
const enabled = ref(false);
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
roles: {
|
||||
|
@ -80,6 +91,7 @@ const submit = async () => {
|
|||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<password-meter :password="form.password" @score="handleScore" />
|
||||
|
||||
<FormField label="Password Confirmation" :class="{ 'text-red-400': errors.password_confirmation }">
|
||||
<FormControl
|
||||
|
@ -114,8 +126,8 @@ const submit = async () => {
|
|||
type="submit"
|
||||
color="info"
|
||||
label="Submit"
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing"
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing == true || enabled == false"
|
||||
/>
|
||||
</BaseButtons>
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { Head, useForm, router } from '@inertiajs/vue3';
|
||||
import { mdiAccountKey, mdiArrowLeftBoldOutline } from '@mdi/js';
|
||||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||
|
@ -13,7 +14,9 @@ import BaseButton from '@/Components/BaseButton.vue';
|
|||
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
// import { Inertia } from '@inertiajs/inertia';
|
||||
import passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
|
||||
const enabled = ref(false);
|
||||
const props = defineProps({
|
||||
user: {
|
||||
type: Object,
|
||||
|
@ -46,6 +49,15 @@ const submit = async () => {
|
|||
// await Inertia.post(stardust.route('user.store'), form);
|
||||
await router.put(stardust.route('settings.user.update', [props.user.id]), form);
|
||||
};
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
}
|
||||
// strengthLabel.value = scoreLabel;
|
||||
// score.value = scoreValue;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -88,6 +100,8 @@ const submit = async () => {
|
|||
</FormControl>
|
||||
</FormField>
|
||||
|
||||
<password-meter :password="form.password" @score="handleScore" />
|
||||
|
||||
<FormField label="Password Confirmation" :class="{ 'text-red-400': errors.password_confirmation }">
|
||||
<FormControl
|
||||
v-model="form.password_confirmation"
|
||||
|
@ -121,7 +135,7 @@ const submit = async () => {
|
|||
color="info"
|
||||
label="Submit"
|
||||
:class="{ 'opacity-25': form.processing }"
|
||||
:disabled="form.processing"
|
||||
:disabled="form.processing == true || enabled == false"
|
||||
/>
|
||||
</BaseButtons>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
// import { Head, Link, useForm } from '@inertiajs/inertia-vue3';
|
||||
import { ref } from 'vue';
|
||||
import { useForm } from '@inertiajs/vue3';
|
||||
// import { ref } from 'vue';
|
||||
// import { reactive } from 'vue';
|
||||
|
@ -24,7 +25,7 @@ import NotificationBar from '@/Components/NotificationBar.vue';
|
|||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
// import { Inertia } from '@inertiajs/inertia';
|
||||
import passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
import { computed, Ref } from 'vue';
|
||||
import { usePage } from '@inertiajs/vue3';
|
||||
import FormValidationErrors from '@/Components/FormValidationErrors.vue';
|
||||
|
@ -35,6 +36,17 @@ import PersonalTotpSettings from '@/Components/PersonalTotpSettings.vue';
|
|||
|
||||
const emit = defineEmits(['confirm', 'update:confirmation'])
|
||||
|
||||
const enabled = ref(false);
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
}
|
||||
// strengthLabel.value = scoreLabel;
|
||||
// score.value = scoreValue;
|
||||
};
|
||||
|
||||
defineProps({
|
||||
// user will be returned from controller action
|
||||
user: {
|
||||
|
@ -183,6 +195,8 @@ const flash: Ref<any> = computed(() => {
|
|||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<password-meter :password="passwordForm.new_password" @score="handleScore" />
|
||||
|
||||
|
||||
<FormField label="Confirm password" help="Required. New password one more time"
|
||||
:class="{ 'text-red-400': passwordForm.errors.confirm_password }">
|
||||
|
@ -205,7 +219,7 @@ const flash: Ref<any> = computed(() => {
|
|||
|
||||
<template #footer>
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Change password" />
|
||||
<BaseButton type="submit" color="info" label="Change password" :disabled="passwordForm.processing == true || enabled == false" />
|
||||
</BaseButtons>
|
||||
</template>
|
||||
</CardBox>
|
||||
|
|
Loading…
Reference in New Issue
Block a user