mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-11-30 22:45:46 +01:00
Compare commits
3 Commits
1231c8362f
...
v1.0.7
| Author | SHA1 | Date | |
|---|---|---|---|
| fbd0f03eb2 | |||
| 86166048e8 | |||
| 0363505126 |
@@ -9,10 +9,11 @@ export const validateLogin = [
|
||||
.normalizeEmail(),
|
||||
|
||||
body('password')
|
||||
.isLength({ min: 6 })
|
||||
.withMessage('Password must be at least 6 characters')
|
||||
.trim()
|
||||
.escape()
|
||||
.optional()
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('Password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/)
|
||||
.withMessage('Password must contain uppercase, lowercase, number and special character'),
|
||||
];
|
||||
|
||||
export const validateRegister = [
|
||||
@@ -29,10 +30,11 @@ export const validateRegister = [
|
||||
.escape(),
|
||||
|
||||
body('password')
|
||||
.optional()
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('Password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
|
||||
.withMessage('Password must contain uppercase, lowercase and number')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/)
|
||||
.withMessage('Password must contain uppercase, lowercase, number and special character'),
|
||||
];
|
||||
|
||||
// ===== EMPLOYEE VALIDATION =====
|
||||
@@ -53,8 +55,8 @@ export const validateEmployee = [
|
||||
.optional()
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('Password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
|
||||
.withMessage('Password must contain uppercase, lowercase and number'),
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/)
|
||||
.withMessage('Password must contain uppercase, lowercase, number and special character'),
|
||||
|
||||
body('employeeType')
|
||||
.isIn(['manager', 'personell', 'apprentice', 'guest'])
|
||||
@@ -145,14 +147,15 @@ export const validateEmployeeUpdate = [
|
||||
export const validateChangePassword = [
|
||||
body('currentPassword')
|
||||
.optional()
|
||||
.isLength({ min: 6 })
|
||||
.withMessage('Current password must be at least 6 characters'),
|
||||
|
||||
body('newPassword')
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('New password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
|
||||
.withMessage('New password must contain uppercase, lowercase and number')
|
||||
.withMessage('Current password must be at least 8 characters'),
|
||||
|
||||
body('password')
|
||||
.optional()
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('Password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/)
|
||||
.withMessage('Password must contain uppercase, lowercase, number and special character'),
|
||||
];
|
||||
|
||||
// ===== SHIFT PLAN VALIDATION =====
|
||||
@@ -284,7 +287,7 @@ export const validateCreateFromPreset = [
|
||||
body('presetName')
|
||||
.isLength({ min: 1 })
|
||||
.withMessage('Preset name is required')
|
||||
.isIn(['standardWeek', 'extendedWeek', 'weekendFocused', 'morningOnly', 'eveningOnly', 'ZEBRA_STANDARD'])
|
||||
.isIn(['GENERAL_STANDARD', 'ZEBRA_STANDARD'])
|
||||
.withMessage('Invalid preset name'),
|
||||
|
||||
body('name')
|
||||
@@ -340,10 +343,11 @@ export const validateSetupAdmin = [
|
||||
.escape(),
|
||||
|
||||
body('password')
|
||||
.optional()
|
||||
.isLength({ min: 8 })
|
||||
.withMessage('Password must be at least 8 characters')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
|
||||
.withMessage('Password must contain uppercase, lowercase and number')
|
||||
.matches(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?])/)
|
||||
.withMessage('Password must contain uppercase, lowercase, number and special character'),
|
||||
];
|
||||
|
||||
// ===== SCHEDULING VALIDATION =====
|
||||
|
||||
@@ -20,7 +20,7 @@ interface AuthContextType {
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||
const API_BASE_URL = process.env.REACT_APP_API_BASE_URL || '/api';
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api';
|
||||
|
||||
interface AuthProviderProps {
|
||||
children: ReactNode;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// frontend/src/services/authService.ts
|
||||
import { Employee } from '../models/Employee';
|
||||
const API_BASE = process.env.REACT_APP_API_BASE_URL || '/api';
|
||||
const API_BASE_URL = import.meta.env.VITE_API_URL || '/api';
|
||||
|
||||
export interface LoginRequest {
|
||||
email: string;
|
||||
@@ -24,7 +24,7 @@ class AuthService {
|
||||
private token: string | null = null;
|
||||
|
||||
async login(credentials: LoginRequest): Promise<AuthResponse> {
|
||||
const response = await fetch(`${API_BASE}/auth/login`, {
|
||||
const response = await fetch(`${API_BASE_URL}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(credentials)
|
||||
@@ -39,12 +39,11 @@ class AuthService {
|
||||
this.token = data.token;
|
||||
localStorage.setItem('token', data.token);
|
||||
localStorage.setItem('employee', JSON.stringify(data.employee));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async register(userData: RegisterRequest): Promise<AuthResponse> {
|
||||
const response = await fetch(`${API_BASE}/employees`, {
|
||||
const response = await fetch(`${API_BASE_URL}/employees`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(userData)
|
||||
@@ -73,7 +72,7 @@ class AuthService {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/auth/me`, {
|
||||
const response = await fetch(`${API_BASE_URL}/auth/me`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ export default defineConfig(({ mode }) => {
|
||||
NODE_ENV: mode,
|
||||
ENABLE_PRO: env.ENABLE_PRO || 'false',
|
||||
VITE_APP_TITLE: env.APP_TITLE || 'Shift Planning App',
|
||||
VITE_API_URL: isProduction ? '/api' : 'http://localhost:3002/api',
|
||||
VITE_API_URL: isProduction ? '/api' : '/api',
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
125
package-lock.json
generated
125
package-lock.json
generated
@@ -280,6 +280,7 @@
|
||||
"backend/node_modules/@types/node": {
|
||||
"version": "24.7.0",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.14.0"
|
||||
}
|
||||
@@ -349,17 +350,6 @@
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
},
|
||||
"backend/node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"backend/node_modules/acorn-walk": {
|
||||
"version": "8.3.4",
|
||||
"dev": true,
|
||||
@@ -2038,6 +2028,7 @@
|
||||
"frontend": {
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"date-fns": "4.1.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-router-dom": "^6.28.0"
|
||||
@@ -2048,7 +2039,9 @@
|
||||
"@types/react-dom": "^19.0.0",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@vitejs/plugin-react": "^4.3.3",
|
||||
"babel-plugin-transform-remove-console": "6.9.4",
|
||||
"esbuild": "^0.21.0",
|
||||
"terser": "5.44.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.0.7"
|
||||
}
|
||||
@@ -2078,6 +2071,7 @@
|
||||
"version": "7.28.5",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -2338,6 +2332,17 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/source-map": {
|
||||
"version": "0.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
|
||||
"integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.5",
|
||||
"@jridgewell/trace-mapping": "^0.3.25"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.5.5",
|
||||
"dev": true,
|
||||
@@ -2388,10 +2393,6 @@
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@schichtenplaner/premium": {
|
||||
"resolved": "premium",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@types/babel__core": {
|
||||
"version": "7.20.5",
|
||||
"dev": true,
|
||||
@@ -2443,6 +2444,7 @@
|
||||
"version": "20.19.23",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -2451,6 +2453,7 @@
|
||||
"version": "19.2.2",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -2514,12 +2517,32 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.15.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/babel-plugin-transform-remove-console": {
|
||||
"version": "6.9.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz",
|
||||
"integrity": "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/baseline-browser-mapping": {
|
||||
"version": "2.8.20",
|
||||
"dev": true,
|
||||
@@ -2585,6 +2608,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.19",
|
||||
"caniuse-lite": "^1.0.30001751",
|
||||
@@ -2599,6 +2623,13 @@
|
||||
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
|
||||
}
|
||||
},
|
||||
"node_modules/buffer-from": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
@@ -2656,6 +2687,13 @@
|
||||
],
|
||||
"license": "CC-BY-4.0"
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
@@ -2702,6 +2740,16 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"devOptional": true,
|
||||
@@ -3368,6 +3416,7 @@
|
||||
"version": "4.0.3",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -3457,6 +3506,7 @@
|
||||
"node_modules/react": {
|
||||
"version": "19.2.0",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -3464,6 +3514,7 @@
|
||||
"node_modules/react-dom": {
|
||||
"version": "19.2.0",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.27.0"
|
||||
},
|
||||
@@ -3730,6 +3781,16 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.2.1",
|
||||
"dev": true,
|
||||
@@ -3738,6 +3799,17 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-support": {
|
||||
"version": "0.5.21",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
|
||||
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"source-map": "^0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
@@ -3747,6 +3819,26 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/terser": {
|
||||
"version": "5.44.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz",
|
||||
"integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/source-map": "^0.3.3",
|
||||
"acorn": "^8.15.0",
|
||||
"commander": "^2.20.0",
|
||||
"source-map-support": "~0.5.20"
|
||||
},
|
||||
"bin": {
|
||||
"terser": "bin/terser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"dev": true,
|
||||
@@ -3788,6 +3880,7 @@
|
||||
"version": "5.9.3",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -3870,6 +3963,7 @@
|
||||
"version": "6.4.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
@@ -4002,6 +4096,7 @@
|
||||
"premium": {
|
||||
"name": "@schichtenplaner/premium",
|
||||
"version": "1.0.0",
|
||||
"extraneous": true,
|
||||
"workspaces": [
|
||||
"backendPRO",
|
||||
"frontendPRO"
|
||||
|
||||
Reference in New Issue
Block a user