From 6c2a04ff95ad902220bba4908715c4473d14fa15 Mon Sep 17 00:00:00 2001 From: Gregory Croisdale Date: Fri, 27 Sep 2024 12:24:43 -0400 Subject: [PATCH] word update --- package.json | 1 + pnpm-lock.yaml | 15 ++++++++ src/utils/password.tsx | 81 +++++++++++++++++++++++++----------------- 3 files changed, 65 insertions(+), 32 deletions(-) diff --git a/package.json b/package.json index efc4d7c..1a57094 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "astro": "^2.5.5", "qrcode.react": "^4.0.1", "randexp": "^0.5.3", + "random-words": "^2.0.1", "react": "^19.0.0-beta", "react-dom": "^19.0.0-beta", "sanitize-filename": "^1.6.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d0bb064..7b3f11c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: randexp: specifier: ^0.5.3 version: 0.5.3 + random-words: + specifier: ^2.0.1 + version: 2.0.1 react: specifier: ^19.0.0-beta version: 19.0.0-rc-fb9a90fa48-20240614 @@ -1514,6 +1517,9 @@ packages: resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==} engines: {node: '>=4'} + random-words@2.0.1: + resolution: {integrity: sha512-nZNJAmgcFmtJMTDDIUCm/iK4R6RydC6NvALvWhYItXQrgYGk1F7Gww416LpVROFQtfVd5TaLEf4WuSsko03N7w==} + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -1632,6 +1638,9 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + seedrandom@3.0.5: + resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3665,6 +3674,10 @@ snapshots: drange: 1.1.1 ret: 0.2.2 + random-words@2.0.1: + dependencies: + seedrandom: 3.0.5 + rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -3828,6 +3841,8 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + seedrandom@3.0.5: {} + semver@6.3.1: {} semver@7.6.3: {} diff --git a/src/utils/password.tsx b/src/utils/password.tsx index e5ce95b..7eb8e92 100644 --- a/src/utils/password.tsx +++ b/src/utils/password.tsx @@ -1,42 +1,59 @@ import React, { useState } from 'react'; import RandExp from 'randexp'; +import { generate } from 'random-words'; + +const regexOptions = [ + { + value: 'strong', + regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=.{12,})[A-Za-z\\d@#$%^&+=!]{12,32}$', + label: 'Strong Password', + description: 'At least 12 characters, max 32. Includes uppercase, lowercase, number, and special character.' + }, + { + value: 'very-strong', + regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=.{16,})[A-Za-z\\d@#$%^&+=!]{16,64}$', + label: 'Very Strong Password', + description: 'At least 16 characters, max 64. Includes uppercase, lowercase, number, and special character.' + }, + { + value: 'memorable', + regex: '^($word){3}\\d{2,4}[@#$%^&+=!]{1,2}$', // Use custom $word token here + label: 'Memorable Password', + description: '3 random words, followed by 2-4 digits and 1-2 special characters.' + }, + { + value: 'pin', + regex: '\\d{6}', + label: 'PIN', + description: '6-digit PIN number.' + }, +]; + +// Function to replace custom tokens after the base password is generated +const transformCustomTokens = (generatedString: string): string => { + // Replace each occurrence of $word with a random capitalized word + return generatedString.replace(/word/g, () => { + const word = generate({ exactly: 1, maxLength: 12 })[0]; + return word.charAt(0).toUpperCase() + word.slice(1); + }); +}; const PasswordGenerator = () => { const [password, setPassword] = useState(''); - const [currentRegex, setCurrentRegex] = useState('^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=.{12,})[A-Za-z\\d@#$%^&+=!]{12,64}$'); + const [currentRegex, setCurrentRegex] = useState(regexOptions[0].regex); const [selectedOption, setSelectedOption] = useState('strong'); - const regexOptions = [ - { - value: 'strong', - regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=.{12,})[A-Za-z\\d@#$%^&+=!]{12,64}$', - label: 'Strong Password', - description: 'At least 12 characters, max 64. Includes uppercase, lowercase, number, and special character.' - }, - { - value: 'very-strong', - regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@#$%^&+=!])(?=.{16,})[A-Za-z\\d@#$%^&+=!]{16,128}$', - label: 'Very Strong Password', - description: 'At least 16 characters, max 128. Includes uppercase, lowercase, number, and special character.' - }, - { - value: 'memorable', - regex: '^([A-Z][a-z]{6,12}){3}\\d{2,4}[@#$%^&+=!]{1,2}$', - label: 'Memorable Password', - description: '3 capitalized words (6-12 chars each), followed by 2-4 digits and 1-2 special characters.' - }, - { - value: 'pin', - regex: '\\d{6}', - label: 'PIN', - description: '6-digit PIN number.' - }, - ]; - const generatePassword = () => { try { + // Generate the base string using RandExp const randexp = new RandExp(new RegExp(currentRegex)); - setPassword(randexp.gen()); + let basePassword = randexp.gen(); + + // Apply custom transformations to the generated base string + const transformedPassword = transformCustomTokens(basePassword); + + // Set the final password + setPassword(transformedPassword); } catch (error) { setPassword('Invalid regex pattern'); } @@ -49,8 +66,8 @@ const PasswordGenerator = () => { const handleOptionChange = (e) => { const selected = regexOptions.find(option => option.value === e.target.value); - setSelectedOption(selected.value); - setCurrentRegex(selected.regex); + setSelectedOption(selected?.value || 'custom'); + setCurrentRegex(selected?.regex || ''); }; return ( @@ -112,4 +129,4 @@ const PasswordGenerator = () => { ); }; -export default PasswordGenerator; \ No newline at end of file +export default PasswordGenerator;