From 3ad497dd765ded96ea9b3b0f3fb1228c8e08fd07 Mon Sep 17 00:00:00 2001 From: donpat1to Date: Fri, 31 Oct 2025 12:37:52 +0100 Subject: [PATCH] changed static password length statements 6 -> 8 --- backend/src/controllers/employeeController.ts | 2 +- backend/src/controllers/setupController.ts | 18 +- backend/src/middleware/Validation/Employee.md | 2 +- backend/src/models/helpers/employeeHelpers.ts | 26 +-- .../src/models/helpers/employeeHelpers.ts | 26 +-- frontend/src/pages/Settings/Settings.tsx | 10 +- frontend/src/pages/Setup/Setup.tsx | 162 +++++++++--------- 7 files changed, 123 insertions(+), 123 deletions(-) diff --git a/backend/src/controllers/employeeController.ts b/backend/src/controllers/employeeController.ts index 4c88e3e..ca883d3 100644 --- a/backend/src/controllers/employeeController.ts +++ b/backend/src/controllers/employeeController.ts @@ -766,7 +766,7 @@ export const changePassword = async (req: AuthRequest, res: Response): Promise => } // Password length validation - if (password.length < 6) { - res.status(400).json({ error: 'Das Passwort muss mindestens 6 Zeichen lang sein' }); + if (password.length < 8) { + res.status(400).json({ error: 'Das Passwort muss mindestens 8 Zeichen lang sein' }); return; } @@ -125,15 +125,15 @@ export const setupAdmin = async (req: Request, res: Response): Promise => } catch (dbError) { await db.run('ROLLBACK'); console.error('❌ Database error during admin creation:', dbError); - res.status(500).json({ + res.status(500).json({ error: 'Fehler beim Erstellen des Admin-Accounts' }); } } catch (error) { console.error('❌ Error in setup:', error); - + if (!res.headersSent) { - res.status(500).json({ + res.status(500).json({ error: 'Ein unerwarteter Fehler ist aufgetreten' }); } diff --git a/backend/src/middleware/Validation/Employee.md b/backend/src/middleware/Validation/Employee.md index bd5077b..b1e7742 100644 --- a/backend/src/middleware/Validation/Employee.md +++ b/backend/src/middleware/Validation/Employee.md @@ -23,7 +23,7 @@ ### \[CREATE\] Employee * `firstname` 1-100 characters and must not be empty * `lastname` 1-100 characters and must not be empty -* `password` must be at least 6 characters (in create mode) +* `password` must be at least 8 characters (in create mode) * `employeeType` must be `manager`, `personell`, `apprentice`, or `guest` * `canWorkAlone` optional boolean * `isTrainee` optional boolean diff --git a/backend/src/models/helpers/employeeHelpers.ts b/backend/src/models/helpers/employeeHelpers.ts index 63b4f45..0a1e197 100644 --- a/backend/src/models/helpers/employeeHelpers.ts +++ b/backend/src/models/helpers/employeeHelpers.ts @@ -14,7 +14,7 @@ function generateEmail(firstname: string, lastname: string): string { const cleanFirstname = convertUmlauts(firstname).replace(/[^a-z0-9]/g, ''); const cleanLastname = convertUmlauts(lastname).replace(/[^a-z0-9]/g, ''); - + return `${cleanFirstname}.${cleanLastname}@sp.de`; } @@ -22,8 +22,8 @@ function generateEmail(firstname: string, lastname: string): string { export function validateEmployeeData(employee: CreateEmployeeRequest): string[] { const errors: string[] = []; - if (employee.password?.length < 6) { - errors.push('Password must be at least 6 characters long'); + if (employee.password?.length < 8) { + errors.push('Password must be at least 8 characters long'); } if (!employee.firstname?.trim() || employee.firstname.trim().length < 2) { @@ -72,16 +72,16 @@ export function generateEmployeeEmail(firstname: string, lastname: string): stri } // UPDATED: Business logic helpers for new employee types -export const isManager = (employee: Employee): boolean => +export const isManager = (employee: Employee): boolean => employee.employeeType === 'manager'; -export const isPersonell = (employee: Employee): boolean => +export const isPersonell = (employee: Employee): boolean => employee.employeeType === 'personell'; -export const isApprentice = (employee: Employee): boolean => +export const isApprentice = (employee: Employee): boolean => employee.employeeType === 'apprentice'; -export const isGuest = (employee: Employee): boolean => +export const isGuest = (employee: Employee): boolean => employee.employeeType === 'guest'; export const isInternal = (employee: Employee): boolean => @@ -91,24 +91,24 @@ export const isExternal = (employee: Employee): boolean => employee.employeeType === 'guest'; // UPDATED: Trainee logic - now based on isTrainee field for personell type -export const isTrainee = (employee: Employee): boolean => +export const isTrainee = (employee: Employee): boolean => employee.employeeType === 'personell' && employee.isTrainee; -export const isExperienced = (employee: Employee): boolean => +export const isExperienced = (employee: Employee): boolean => employee.employeeType === 'personell' && !employee.isTrainee; // Role-based helpers -export const isAdmin = (employee: Employee): boolean => +export const isAdmin = (employee: Employee): boolean => employee.roles?.includes('admin') || false; -export const isMaintenance = (employee: Employee): boolean => +export const isMaintenance = (employee: Employee): boolean => employee.roles?.includes('maintenance') || false; -export const isUser = (employee: Employee): boolean => +export const isUser = (employee: Employee): boolean => employee.roles?.includes('user') || false; // UPDATED: Work alone permission - managers and experienced personell can work alone -export const canEmployeeWorkAlone = (employee: Employee): boolean => +export const canEmployeeWorkAlone = (employee: Employee): boolean => employee.canWorkAlone && (isManager(employee) || isExperienced(employee)); // Helper for full name display diff --git a/frontend/src/models/helpers/employeeHelpers.ts b/frontend/src/models/helpers/employeeHelpers.ts index 63b4f45..0a1e197 100644 --- a/frontend/src/models/helpers/employeeHelpers.ts +++ b/frontend/src/models/helpers/employeeHelpers.ts @@ -14,7 +14,7 @@ function generateEmail(firstname: string, lastname: string): string { const cleanFirstname = convertUmlauts(firstname).replace(/[^a-z0-9]/g, ''); const cleanLastname = convertUmlauts(lastname).replace(/[^a-z0-9]/g, ''); - + return `${cleanFirstname}.${cleanLastname}@sp.de`; } @@ -22,8 +22,8 @@ function generateEmail(firstname: string, lastname: string): string { export function validateEmployeeData(employee: CreateEmployeeRequest): string[] { const errors: string[] = []; - if (employee.password?.length < 6) { - errors.push('Password must be at least 6 characters long'); + if (employee.password?.length < 8) { + errors.push('Password must be at least 8 characters long'); } if (!employee.firstname?.trim() || employee.firstname.trim().length < 2) { @@ -72,16 +72,16 @@ export function generateEmployeeEmail(firstname: string, lastname: string): stri } // UPDATED: Business logic helpers for new employee types -export const isManager = (employee: Employee): boolean => +export const isManager = (employee: Employee): boolean => employee.employeeType === 'manager'; -export const isPersonell = (employee: Employee): boolean => +export const isPersonell = (employee: Employee): boolean => employee.employeeType === 'personell'; -export const isApprentice = (employee: Employee): boolean => +export const isApprentice = (employee: Employee): boolean => employee.employeeType === 'apprentice'; -export const isGuest = (employee: Employee): boolean => +export const isGuest = (employee: Employee): boolean => employee.employeeType === 'guest'; export const isInternal = (employee: Employee): boolean => @@ -91,24 +91,24 @@ export const isExternal = (employee: Employee): boolean => employee.employeeType === 'guest'; // UPDATED: Trainee logic - now based on isTrainee field for personell type -export const isTrainee = (employee: Employee): boolean => +export const isTrainee = (employee: Employee): boolean => employee.employeeType === 'personell' && employee.isTrainee; -export const isExperienced = (employee: Employee): boolean => +export const isExperienced = (employee: Employee): boolean => employee.employeeType === 'personell' && !employee.isTrainee; // Role-based helpers -export const isAdmin = (employee: Employee): boolean => +export const isAdmin = (employee: Employee): boolean => employee.roles?.includes('admin') || false; -export const isMaintenance = (employee: Employee): boolean => +export const isMaintenance = (employee: Employee): boolean => employee.roles?.includes('maintenance') || false; -export const isUser = (employee: Employee): boolean => +export const isUser = (employee: Employee): boolean => employee.roles?.includes('user') || false; // UPDATED: Work alone permission - managers and experienced personell can work alone -export const canEmployeeWorkAlone = (employee: Employee): boolean => +export const canEmployeeWorkAlone = (employee: Employee): boolean => employee.canWorkAlone && (isManager(employee) || isExperienced(employee)); // Helper for full name display diff --git a/frontend/src/pages/Settings/Settings.tsx b/frontend/src/pages/Settings/Settings.tsx index e85d7fd..d545ac7 100644 --- a/frontend/src/pages/Settings/Settings.tsx +++ b/frontend/src/pages/Settings/Settings.tsx @@ -203,11 +203,11 @@ const Settings: React.FC = () => { return; } - if (passwordForm.newPassword.length < 6) { + if (passwordForm.newPassword.length < 8) { showNotification({ type: 'error', title: 'Fehler', - message: 'Das neue Passwort muss mindestens 6 Zeichen lang sein' + message: 'Das neue Passwort muss mindestens 8 Zeichen lang sein' }); return; } @@ -600,9 +600,9 @@ const Settings: React.FC = () => { value={passwordForm.newPassword} onChange={handlePasswordChange} required - minLength={6} + minLength={8} style={styles.fieldInputWithIcon} - placeholder="Mindestens 6 Zeichen" + placeholder="Mindestens 8 Zeichen" onFocus={(e) => { e.target.style.borderColor = '#1a1325'; e.target.style.boxShadow = '0 0 0 3px rgba(26, 19, 37, 0.1)'; @@ -631,7 +631,7 @@ const Settings: React.FC = () => {
- Das Passwort muss mindestens 6 Zeichen lang sein. + Das Passwort muss mindestens 8 Zeichen lang sein.
diff --git a/frontend/src/pages/Setup/Setup.tsx b/frontend/src/pages/Setup/Setup.tsx index 1834636..b36d27e 100644 --- a/frontend/src/pages/Setup/Setup.tsx +++ b/frontend/src/pages/Setup/Setup.tsx @@ -32,7 +32,7 @@ const useSetup = () => { const steps: SetupStep[] = [ { - id: 'profile-setup', + id: 'profile-setup', title: 'Profilinformationen', subtitle: 'Geben Sie Ihre persönlichen Daten ein' }, @@ -62,8 +62,8 @@ const useSetup = () => { }; const validateStep2 = (): boolean => { - if (formData.password.length < 6) { - setError('Das Passwort muss mindestens 6 Zeichen lang sein.'); + if (formData.password.length < 8) { + setError('Das Passwort muss mindestens 8 Zeichen lang sein.'); return false; } if (formData.password !== formData.confirmPassword) { @@ -87,7 +87,7 @@ const useSetup = () => { // ===== NAVIGATIONS-FUNKTIONEN ===== const goToNextStep = async (): Promise => { setError(''); - + if (!validateCurrentStep(currentStep)) { return; } @@ -111,7 +111,7 @@ const useSetup = () => { const handleStepChange = (stepIndex: number): void => { setError(''); - + // Nur erlauben, zu bereits validierten Schritten zu springen // oder zum nächsten Schritt nach dem aktuellen if (stepIndex <= currentStep + 1) { @@ -163,7 +163,7 @@ const useSetup = () => { // Setup Status neu prüfen await checkSetupStatus(); - + } catch (err: any) { console.error('❌ Setup error:', err); setError(err.message || 'Ein unerwarteter Fehler ist aufgetreten'); @@ -177,7 +177,7 @@ const useSetup = () => { if (!formData.firstname.trim() || !formData.lastname.trim()) { return 'vorname.nachname@sp.de'; } - + const cleanFirstname = formData.firstname.toLowerCase().replace(/[^a-z0-9]/g, ''); const cleanLastname = formData.lastname.toLowerCase().replace(/[^a-z0-9]/g, ''); return `${cleanFirstname}.${cleanLastname}@sp.de`; @@ -186,8 +186,8 @@ const useSetup = () => { const isStepCompleted = (stepIndex: number): boolean => { switch (stepIndex) { case 0: - return formData.password.length >= 6 && - formData.password === formData.confirmPassword; + return formData.password.length >= 8 && + formData.password === formData.confirmPassword; case 1: return !!formData.firstname.trim() && !!formData.lastname.trim(); default: @@ -202,13 +202,13 @@ const useSetup = () => { loading, error, steps, - + // Actions goToNextStep, goToPrevStep, handleStepChange, handleInputChange, - + // Helpers getEmailPreview, isStepCompleted @@ -223,16 +223,16 @@ interface StepContentProps { currentStep: number; } -const Step1Content: React.FC = ({ - formData, +const Step1Content: React.FC = ({ + formData, onInputChange, - getEmailPreview + getEmailPreview }) => (
-
-
- -
= ({ }}> {getEmailPreview()}
-
@@ -315,15 +315,15 @@ const Step1Content: React.FC = ({ ); -const Step2Content: React.FC = ({ - formData, - onInputChange +const Step2Content: React.FC = ({ + formData, + onInputChange }) => (
-
- +
-
); -const Step3Content: React.FC = ({ +const Step3Content: React.FC = ({ formData, - getEmailPreview + getEmailPreview }) => (
-
-

Zusammenfassung

- +
E-Mail: @@ -413,15 +413,15 @@ const Step3Content: React.FC = ({
- -
- 💡 Wichtig: Nach dem Setup können Sie sich mit Ihrer + 💡 Wichtig: Nach dem Setup können Sie sich mit Ihrer automatisch generierten E-Mail anmelden.
@@ -464,7 +464,7 @@ const Setup: React.FC = () => { const getNextButtonText = (): string => { if (loading) return '⏳ Wird verarbeitet...'; - + switch (currentStep) { case 0: return 'Weiter →'; @@ -479,9 +479,9 @@ const Setup: React.FC = () => { // Inline Step Indicator Komponente const StepIndicator: React.FC = () => ( -
{ backgroundColor: '#e9ecef', zIndex: 1 }} /> - + {steps.map((step, index) => { const isCompleted = index < currentStep; const isCurrent = index === currentStep; const isClickable = index <= currentStep + 1; - + return ( -
{ > {index + 1} - +
-
@@ -555,8 +555,8 @@ const Setup: React.FC = () => { ); return ( -
{ border: '1px solid #e9ecef' }}>
-

🚀 Erstkonfiguration

-

{ {/* Aktueller Schritt Titel und Beschreibung */}

-

{steps[currentStep].title}

{steps[currentStep].subtitle && ( -

@@ -633,9 +633,9 @@ const Setup: React.FC = () => {

{/* Navigations-Buttons */} -
@@ -655,7 +655,7 @@ const Setup: React.FC = () => { > ← Zurück - +