Skip to content

Commit

Permalink
Merge branch 'generate-pw-button' into 'main'
Browse files Browse the repository at this point in the history
Add button to generate random password to password fields

See merge request reportcreator/reportcreator!804
  • Loading branch information
MWedl committed Dec 16, 2024
2 parents a39e0c4 + ac9d530 commit 348a06c
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Update and optimize designs: demo, HTB and OffSec designs
* Add design for HTB CAPE certification
* Warn about relative URLs in PDFs during rendering
* Add button to generate random password to password fields


## v2024.96 - 2024-12-04
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/components/LoginForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@
<v-card-text>
<s-password-field
v-model="formChangePassword.password"
confirm show-strength
confirm show-strength generate
label="New Password"
/>

Expand Down
1 change: 1 addition & 0 deletions packages/frontend/src/components/Notes/ShareInfoForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
:model-value="modelValue.password"
@update:model-value="updateProp('password', $event)"
label="Password (optional)"
generate
:disabled="props.disabled"
:error-messages="props.error?.password"
/>
Expand Down
12 changes: 3 additions & 9 deletions packages/frontend/src/pages/projects/[projectId]/publish.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
v-model="form.password"
:error-messages="(localSettings.encryptPdfEnabled && form.password.length === 0) ? ['Password required'] : []"
label="PDF password"
append-inner-icon="mdi-lock-reset" @click:append-inner="form.password = generateNewPassword()"
append-inner-icon="mdi-lock-reset" @click:append-inner="form.password = generateRandomPassword()"
spellcheck="false"
class="mt-4"
/>
Expand Down Expand Up @@ -106,8 +106,7 @@
</template>

<script setup lang="ts">
import { sampleSize } from "lodash-es"
import { fileDownload } from "@base/utils/helpers";
import { fileDownload, generateRandomPassword } from "@base/utils/helpers";
definePageMeta({
title: 'Publish',
Expand Down Expand Up @@ -142,13 +141,8 @@ const allMessages = computed(() => {
});
const hasErrors = computed(() => allMessages.value.some(m => m.level === MessageLevel.ERROR));
function generateNewPassword() {
// Charset does not contain similar-looking characters and numbers; removed: 0,O, 1,l,I
const charset = '23456789' + 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' + '!#%&+-_';
return sampleSize(charset, 20).join('');
}
const form = ref({
password: generateNewPassword(),
password: generateRandomPassword(),
filename: (project.value.name + '_report.pdf').replaceAll(/[\\/]/g, '').replaceAll(/\s+/g, ' '),
});
const rules = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
v-model="form.password"
label="New password"
:error-messages="serverErrors?.password || []"
confirm show-strength
confirm show-strength generate
:disabled="!canEdit"
/>

Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/pages/users/new.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<div v-if="apiSettings.isLocalUserAuthEnabled">
<s-password-field
v-model="userForm.password"
confirm show-strength
confirm show-strength generate
:error-messages="serverErrors?.password || []"
/>
<s-checkbox
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/pages/users/self/security.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
v-model="changePasswordWizard.password"
label="New Password"
:error-messages="changePasswordWizard.errors?.password"
confirm show-strength
confirm show-strength generate
/>
</v-card-text>
<v-card-actions>
Expand Down
45 changes: 32 additions & 13 deletions packages/nuxt-base-layer/src/components/S/PasswordField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,45 @@
:model-value="modelValue" @update:model-value="passwordChanged"
:type="showPassword ? 'text' : 'password'"
:label="label"
:disabled="disabled"
:disabled="props.disabled"
:append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append-inner="showPassword = !showPassword"
:loading="showStrength"
:loading="props.showStrength"
:variant="props.variant"
autocomplete="off"
spellcheck="false"
class="mt-4"
>
<template #loader>
<template #loader v-if="props.showStrength">
<v-progress-linear
v-model="passwordStrengthLevel"
:color="passwordStrengthColor"
height="7"
/>
</template>
<template #append v-if="props.generate">
<s-btn
@click="generateNewPassword"
icon
density="compact"
:disabled="props.disabled"
>
<v-icon icon="mdi-lock-reset" />
<s-tooltip activator="parent" text="Generate random password" />
</s-btn>
</template>
</s-text-field>
<s-text-field
v-if="confirm"
ref="confirmField"
v-model="passwordConfirmValue"
:type="showPassword ? 'text' : 'password'"
:label="label + ' (confirm)'"
:disabled="disabled"
:disabled="props.disabled"
:append-innner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
@click:append-inner="showPassword = !showPassword"
:rules="rules.confirmMatches"
:variant="props.variant"
autocomplete="off"
spellcheck="false"
class="mt-6"
Expand All @@ -42,47 +55,53 @@
import type { VForm } from "vuetify/lib/components/index.mjs";
import zxcvbn from 'zxcvbn';
const modelValue = defineModel<string|null>();
const props = withDefaults(defineProps<{
modelValue: string | null,
label?: string,
variant?: string,
disabled?: boolean,
confirm?: boolean,
showStrength?: boolean,
generate?: boolean,
}>(), {
label: 'Password',
variant: undefined,
disabled: false,
confirm: false,
showStrength: false,
});
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void,
}>();
const confirmField = ref<VForm|null>(null);
async function passwordChanged(val: string) {
if (props.confirm && confirmField.value) {
await confirmField.value.validate();
}
emit('update:modelValue', val);
modelValue.value = val;
}
const showPassword = ref(false);
const passwordConfirmValue = ref('');
const rules = {
confirmMatches: [(p: string) => p === props.modelValue || (!p && !props.modelValue) || 'Passwords do not match'],
confirmMatches: [(p: string) => p === modelValue.value || (!p && !modelValue.value) || 'Passwords do not match'],
};
const passwordStrengthCheckResult = computed(() => zxcvbn(props.modelValue || ''));
const passwordStrengthCheckResult = computed(() => zxcvbn(modelValue.value || ''));
const passwordStrengthLevel = computed(() => {
if (!props.modelValue) {
if (!modelValue.value) {
return 0;
}
return [10, 30, 50, 80, 100][passwordStrengthCheckResult.value.score];
});
const passwordStrengthColor = computed(() => {
if (!props.modelValue) {
if (!modelValue.value) {
return 'error';
}
return ['error', 'amber-darken-4', 'warning', 'lime-darken-1', 'success'][passwordStrengthCheckResult.value.score];
});
function generateNewPassword() {
modelValue.value = generateRandomPassword()
passwordConfirmValue.value = '';
showPassword.value = true;
}
</script>
8 changes: 7 additions & 1 deletion packages/nuxt-base-layer/src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { setWith, clone, cloneDeep } from "lodash-es";
import { setWith, clone, cloneDeep, sampleSize } from "lodash-es";
export { decode as base64decode, encode as base64encode } from 'base64-arraybuffer';
export { default as fileDownload } from 'js-file-download';
export { default as urlJoin } from 'url-join';
Expand Down Expand Up @@ -180,3 +180,9 @@ export function useAbortController<T>(performFetch: (fetchOptions: { signal: Abo
pending,
}
}

export function generateRandomPassword() {
// Charset does not contain similar-looking characters and numbers; removed: 0,O, 1,l,I
const charset = '23456789' + 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ' + '!#%&+-_';
return sampleSize(charset, 20).join('');
}

0 comments on commit 348a06c

Please sign in to comment.