feat: enhanced dataset management and UI improvements
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m10s
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m10s
- Submitter/DatasetController.ts: improved validations for time_absolute, time_min, and time_max. - validators/dataset.ts: enhanced validations for time_absolute, time_min, and time_max. - Added new favicon.ico for better branding. - Improved password-meter.vue component with clearer hint messages. - Updated checkStrength.ts: enhanced checkStrength() method for password strength validation. - submitter/Dataset/Create.vue: added form controls for time_min, time_max, and/or time_absolute fields. - submitter/Dataset/Edit.vue: introduced a loading spinner during file upload for better UX.
This commit is contained in:
parent
f67b736a88
commit
d1480b1240
17 changed files with 2682 additions and 1446 deletions
|
@ -1,53 +1,54 @@
|
|||
import commonPasswords from '../data/commonPasswords';
|
||||
import Trie from './Trie';
|
||||
|
||||
|
||||
|
||||
const checkStrength = (pass: string) => {
|
||||
const score = scorePassword(pass);
|
||||
const scoreLabel = mapScoreToLabel(score);
|
||||
const scoreLabel = mapScoreToLabel(score);
|
||||
const hints = getImprovementHints(pass);
|
||||
return {
|
||||
score,
|
||||
scoreLabel
|
||||
}
|
||||
scoreLabel,
|
||||
hints,
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
if (password.length <= 8 || isCommonPassword(password)) return 0;
|
||||
|
||||
let score = 0;
|
||||
score += getLengthScore(password);
|
||||
score += getSpecialCharScore(password);
|
||||
score += getCaseMixScore(password);
|
||||
score += getNumberMixScore(password);
|
||||
score += getLengthScore(password); //3
|
||||
score += getSpecialCharScore(password); //1
|
||||
score += getCaseMixScore(password); //1
|
||||
score += getNumberMixScore(password); //1
|
||||
|
||||
return Math.min(score, 4); // Maximum score is 4
|
||||
return Math.min(score, 6); // Maximum score is 6
|
||||
};
|
||||
|
||||
// Initialize the Trie with common passwords
|
||||
const trie = new Trie();
|
||||
commonPasswords.forEach(password => trie.insert(password));
|
||||
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
|
||||
// Length-based scoring
|
||||
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);
|
||||
};
|
||||
|
||||
// const hasRepeatChars = (password: string): boolean => {
|
||||
// const repeatCharRegex = /(\w)(\1+\1+\1+\1+)/g;
|
||||
// return repeatCharRegex.test(password);
|
||||
// };
|
||||
// Check for repeated characters
|
||||
const hasRepeatChars = (password: string): boolean => /(\w)\1{3,}/.test(password);
|
||||
|
||||
// Function to get the score based on the presence of special characters
|
||||
const getSpecialCharScore = (password: string): number => {
|
||||
|
@ -71,23 +72,45 @@ const getNumberMixScore = (password: string): number => {
|
|||
|
||||
// Function to map the score to a corresponding label
|
||||
const mapScoreToLabel = (score: number): string => {
|
||||
const labels = ['risky', 'guessable', 'weak', 'safe', 'secure'];
|
||||
const labels = ['risky', 'guessable', 'weak', 'safe', 'secure', 'safe-secure', 'optimal'];
|
||||
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 '';
|
||||
// }
|
||||
// };
|
||||
// Function to get improvement hints
|
||||
const getImprovementHints = (password: string): string[] => {
|
||||
const hints = [];
|
||||
|
||||
if (password.length <= 8) {
|
||||
hints.push('Increase your password length to more than 8 characters for 1 scoring point.');
|
||||
} else {
|
||||
if (password.length > 8 && password.length <= 12) {
|
||||
hints.push('Increase your password length to more than 12 characters for additional scoring point.');
|
||||
} else if (password.length > 12 && password.length <= 20) {
|
||||
hints.push('Increase your password length to more than 20 characters for additional scoring point.');
|
||||
}
|
||||
|
||||
// Check for special character score
|
||||
if (!getSpecialCharScore(password)) {
|
||||
hints.push('Include at least one special character for 1 point.');
|
||||
}
|
||||
|
||||
// Check for case mix score
|
||||
if (!getCaseMixScore(password)) {
|
||||
hints.push('Mix uppercase and lowercase letters for 1 point.');
|
||||
}
|
||||
|
||||
// Check for number mix score
|
||||
if (!getNumberMixScore(password)) {
|
||||
hints.push('Add numbers to your password for 1 point.');
|
||||
}
|
||||
|
||||
if (hasRepeatChars(password) && password.length < 20) {
|
||||
hints.push('Remove repeated characters for 1 point.');
|
||||
}
|
||||
if (hasRepeatChars(password) && password.length > 20) {
|
||||
hints.push('Remove repeated characters for 2 points.');
|
||||
}
|
||||
}
|
||||
|
||||
return hints;
|
||||
};
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue