mirror of https://github.com/wg-easy/wg-easy
Browse Source
* separate route for onboarding * zse zod for validation * use argon2id * add build toolspull/1648/head
committed by
Bernd Storath
17 changed files with 104 additions and 126 deletions
@ -26,12 +26,12 @@ importers: |
|||||
apexcharts: |
apexcharts: |
||||
specifier: ^3.53.0 |
specifier: ^3.53.0 |
||||
version: 3.53.0 |
version: 3.53.0 |
||||
|
argon2: |
||||
|
specifier: ^0.41.1 |
||||
|
version: 0.41.1 |
||||
basic-auth: |
basic-auth: |
||||
specifier: ^2.0.1 |
specifier: ^2.0.1 |
||||
version: 2.0.1 |
version: 2.0.1 |
||||
bcryptjs: |
|
||||
specifier: ^2.4.3 |
|
||||
version: 2.4.3 |
|
||||
cidr-tools: |
cidr-tools: |
||||
specifier: ^11.0.2 |
specifier: ^11.0.2 |
||||
version: 11.0.2 |
version: 11.0.2 |
||||
@ -81,9 +81,6 @@ importers: |
|||||
'@nuxt/eslint-config': |
'@nuxt/eslint-config': |
||||
specifier: ^0.5.5 |
specifier: ^0.5.5 |
||||
version: 0.5.5([email protected]([email protected]))([email protected]) |
version: 0.5.5([email protected]([email protected]))([email protected]) |
||||
'@types/bcryptjs': |
|
||||
specifier: ^2.4.6 |
|
||||
version: 2.4.6 |
|
||||
'@types/debug': |
'@types/debug': |
||||
specifier: ^4.1.12 |
specifier: ^4.1.12 |
||||
version: 4.1.12 |
version: 4.1.12 |
||||
@ -1013,6 +1010,10 @@ packages: |
|||||
resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} |
resolution: {integrity: sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==} |
||||
engines: {node: '>= 10.0.0'} |
engines: {node: '>= 10.0.0'} |
||||
|
|
||||
|
'@phc/[email protected]': |
||||
|
resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} |
||||
|
engines: {node: '>=10'} |
||||
|
|
||||
'@pinia/[email protected]': |
'@pinia/[email protected]': |
||||
resolution: {integrity: sha512-nNEs2pq6+Ji5qIyRwmeD9LUdctL8aJ8QMVLTYxUc16cXEOcIIN+MSA8Xudsd0lVETYgEAROT5HiBHnOYRDY3yQ==} |
resolution: {integrity: sha512-nNEs2pq6+Ji5qIyRwmeD9LUdctL8aJ8QMVLTYxUc16cXEOcIIN+MSA8Xudsd0lVETYgEAROT5HiBHnOYRDY3yQ==} |
||||
|
|
||||
@ -1211,9 +1212,6 @@ packages: |
|||||
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} |
resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} |
||||
engines: {node: '>=10.13.0'} |
engines: {node: '>=10.13.0'} |
||||
|
|
||||
'@types/[email protected]': |
|
||||
resolution: {integrity: sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==} |
|
||||
|
|
||||
'@types/[email protected]': |
'@types/[email protected]': |
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} |
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} |
||||
|
|
||||
@ -1520,6 +1518,10 @@ packages: |
|||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} |
resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} |
||||
|
|
||||
|
[email protected]: |
||||
|
resolution: {integrity: sha512-dqCW8kJXke8Ik+McUcMDltrbuAWETPyU6iq+4AhxqKphWi7pChB/Zgd/Tp/o8xRLbg8ksMj46F/vph9wnxpTzQ==} |
||||
|
engines: {node: '>=16.17.0'} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} |
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} |
||||
|
|
||||
@ -1567,9 +1569,6 @@ packages: |
|||||
resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} |
resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} |
||||
engines: {node: '>= 0.8'} |
engines: {node: '>= 0.8'} |
||||
|
|
||||
[email protected]: |
|
||||
resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} |
|
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} |
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} |
||||
engines: {node: '>=8'} |
engines: {node: '>=8'} |
||||
@ -3031,6 +3030,10 @@ packages: |
|||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} |
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} |
||||
|
|
||||
|
[email protected]: |
||||
|
resolution: {integrity: sha512-yBY+qqWSv3dWKGODD6OGE6GnTX7Q2r+4+DfpqxHSHh8x0B4EKP9+wVGLS6U/AM1vxSNNmUEuIV5EGhYwPpfOwQ==} |
||||
|
engines: {node: ^18 || ^20 || >= 21} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} |
resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} |
||||
|
|
||||
@ -5484,6 +5487,8 @@ snapshots: |
|||||
'@parcel/watcher-win32-ia32': 2.4.1 |
'@parcel/watcher-win32-ia32': 2.4.1 |
||||
'@parcel/watcher-win32-x64': 2.4.1 |
'@parcel/watcher-win32-x64': 2.4.1 |
||||
|
|
||||
|
'@phc/[email protected]': {} |
||||
|
|
||||
'@pinia/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))': |
'@pinia/[email protected]([email protected])([email protected])([email protected])([email protected]([email protected]))': |
||||
dependencies: |
dependencies: |
||||
'@nuxt/kit': 3.13.0([email protected])([email protected]) |
'@nuxt/kit': 3.13.0([email protected])([email protected]) |
||||
@ -5651,8 +5656,6 @@ snapshots: |
|||||
|
|
||||
'@trysound/[email protected]': {} |
'@trysound/[email protected]': {} |
||||
|
|
||||
'@types/[email protected]': {} |
|
||||
|
|
||||
'@types/[email protected]': |
'@types/[email protected]': |
||||
dependencies: |
dependencies: |
||||
'@types/ms': 0.7.34 |
'@types/ms': 0.7.34 |
||||
@ -6082,6 +6085,12 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
|
[email protected]: |
||||
|
dependencies: |
||||
|
'@phc/format': 1.0.0 |
||||
|
node-addon-api: 8.1.0 |
||||
|
node-gyp-build: 4.8.2 |
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
@ -6127,8 +6136,6 @@ snapshots: |
|||||
dependencies: |
dependencies: |
||||
safe-buffer: 5.1.2 |
safe-buffer: 5.1.2 |
||||
|
|
||||
[email protected]: {} |
|
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
@ -7727,6 +7734,8 @@ snapshots: |
|||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
|
[email protected]: {} |
||||
|
|
||||
[email protected]: {} |
[email protected]: {} |
||||
|
|
||||
[email protected]: |
[email protected]: |
||||
|
@ -0,0 +1,8 @@ |
|||||
|
export default defineEventHandler(async (event) => { |
||||
|
const { username, password } = await readValidatedBody( |
||||
|
event, |
||||
|
validateZod(passwordType) |
||||
|
); |
||||
|
await Database.createUser(username, password); |
||||
|
return { success: true }; |
||||
|
}); |
@ -1,24 +0,0 @@ |
|||||
import { DatabaseError } from '~~/services/database/repositories/database'; |
|
||||
|
|
||||
export default defineEventHandler(async (event) => { |
|
||||
setHeader(event, 'Content-Type', 'application/json'); |
|
||||
try { |
|
||||
const { username, password } = await readValidatedBody( |
|
||||
event, |
|
||||
validateZod(passwordType) |
|
||||
); |
|
||||
await Database.newUserWithPassword(username, password); |
|
||||
return { success: true }; |
|
||||
} catch (error) { |
|
||||
if (error instanceof DatabaseError) { |
|
||||
const t = await useTranslation(event); |
|
||||
throw createError({ |
|
||||
statusCode: 400, |
|
||||
statusMessage: t(error.message), |
|
||||
message: error.message, |
|
||||
}); |
|
||||
} else { |
|
||||
throw createError('Something happened !'); |
|
||||
} |
|
||||
} |
|
||||
}); |
|
@ -0,0 +1,15 @@ |
|||||
|
export default defineEventHandler(async (event) => { |
||||
|
const { username, password } = await readValidatedBody( |
||||
|
event, |
||||
|
validateZod(passwordType) |
||||
|
); |
||||
|
const users = await Database.getUsers(); |
||||
|
if (users.length !== 0) { |
||||
|
throw createError({ |
||||
|
statusCode: 400, |
||||
|
statusMessage: 'Invalid state', |
||||
|
}); |
||||
|
} |
||||
|
await Database.createUser(username, password); |
||||
|
return { success: true }; |
||||
|
}); |
@ -1,47 +1,18 @@ |
|||||
import bcrypt from 'bcryptjs'; |
import argon2 from 'argon2'; |
||||
|
|
||||
/** |
/** |
||||
* Checks if `password` matches the user password. |
* Checks if `password` matches the hash. |
||||
* |
|
||||
* @param {string} password string to test |
|
||||
* @returns {boolean} `true` if matching user password, otherwise `false` |
|
||||
*/ |
*/ |
||||
export function isPasswordValid(password: string, hash: string): boolean { |
export function isPasswordValid( |
||||
return bcrypt.compareSync(password, hash); |
password: string, |
||||
} |
hash: string |
||||
|
): Promise<boolean> { |
||||
/** |
return argon2.verify(hash, password); |
||||
* Checks if a password is strong based on following criteria : |
|
||||
* |
|
||||
* - minimum length of 12 characters |
|
||||
* - contains at least one uppercase letter |
|
||||
* - contains at least one lowercase letter |
|
||||
* - contains at least one number |
|
||||
* - contains at least one special character (e.g., !@#$%^&*(),.?":{}|<>). |
|
||||
* |
|
||||
* @param {string} password - The password to validate |
|
||||
* @returns {boolean} `true` if the password is strong, otherwise `false` |
|
||||
*/ |
|
||||
|
|
||||
export function isPasswordStrong(password: string): boolean { |
|
||||
if (password.length < 12) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
const hasUpperCase = /[A-Z]/.test(password); |
|
||||
const hasLowerCase = /[a-z]/.test(password); |
|
||||
const hasNumber = /\d/.test(password); |
|
||||
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password); |
|
||||
|
|
||||
return hasUpperCase && hasLowerCase && hasNumber && hasSpecialChar; |
|
||||
} |
} |
||||
|
|
||||
/** |
/** |
||||
* Hashes a password. |
* Hashes a password. |
||||
* |
|
||||
* @param {string} password - The plaintext password to hash |
|
||||
* @returns {string} The hash of the password |
|
||||
*/ |
*/ |
||||
export function hashPassword(password: string): string { |
export async function hashPassword(password: string): Promise<string> { |
||||
return bcrypt.hashSync(password, 12); |
return argon2.hash(password); |
||||
} |
} |
||||
|
Loading…
Reference in new issue