1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Fixes #11623: obfuscate Wi-Fi PSKs (#12244)

* Fixes #11623: obfuscate Wi-Fi PSKs

* yarn linting fixes

* include static files
This commit is contained in:
Austin de Coup-Crank
2023-04-24 11:13:28 -05:00
committed by GitHub
parent b693123f6e
commit adb9673f09
8 changed files with 110 additions and 10 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,7 @@ import { initReslug } from './reslug';
import { initSelectAll } from './selectAll'; import { initSelectAll } from './selectAll';
import { initSelectMultiple } from './selectMultiple'; import { initSelectMultiple } from './selectMultiple';
import { initMarkdownPreviews } from './markdownPreview'; import { initMarkdownPreviews } from './markdownPreview';
import { initSecretToggle } from './secretToggle';
export function initButtons(): void { export function initButtons(): void {
for (const func of [ for (const func of [
@ -15,6 +16,7 @@ export function initButtons(): void {
initSelectMultiple, initSelectMultiple,
initMoveButtons, initMoveButtons,
initMarkdownPreviews, initMarkdownPreviews,
initSecretToggle,
]) { ]) {
func(); func();
} }

View File

@ -0,0 +1,77 @@
import { secretState } from '../stores';
import { getElement, getElements, isTruthy } from '../util';
import type { StateManager } from '../state';
type SecretState = { hidden: boolean };
/**
* Change toggle button's text and attribute to reflect the current state.
*
* @param hidden `true` if the current state is hidden, `false` otherwise.
* @param button Toggle element.
*/
function toggleSecretButton(hidden: boolean, button: HTMLButtonElement): void {
button.setAttribute('data-secret-visibility', hidden ? 'hidden' : 'shown');
button.innerText = hidden ? 'Show Secret' : 'Hide Secret';
}
/**
* Show secret.
*/
function showSecret(): void {
const secret = getElement('secret');
if (isTruthy(secret)) {
const value = secret.getAttribute('data-secret');
if (isTruthy(value)) {
secret.innerText = value;
}
}
}
/**
* Hide secret.
*/
function hideSecret(): void {
const secret = getElement('secret');
if (isTruthy(secret)) {
const value = secret.getAttribute('data-secret');
if (isTruthy(value)) {
secret.innerText = '••••••••';
}
}
}
/**
* Update secret state and visualization when the button is clicked.
*
* @param state State instance.
* @param button Toggle element.
*/
function handleSecretToggle(state: StateManager<SecretState>, button: HTMLButtonElement): void {
state.set('hidden', !state.get('hidden'));
const hidden = state.get('hidden');
if (hidden) {
hideSecret();
} else {
showSecret();
}
toggleSecretButton(hidden, button);
}
/**
* Initialize secret toggle button.
*/
export function initSecretToggle(): void {
hideSecret();
for (const button of getElements<HTMLButtonElement>('button.toggle-secret')) {
button.addEventListener(
'click',
event => {
handleSecretToggle(secretState, event.currentTarget as HTMLButtonElement);
},
false,
);
}
}

View File

@ -1,3 +1,4 @@
export * from './objectDepth'; export * from './objectDepth';
export * from './rackImages'; export * from './rackImages';
export * from './previousPkCheck'; export * from './previousPkCheck';
export * from './secret';

View File

@ -0,0 +1,6 @@
import { createState } from '../state';
export const secretState = createState<{ hidden: boolean }>(
{ hidden: true },
{ persist: true, key: 'netbox-secret' },
);

View File

@ -14,7 +14,12 @@
</tr> </tr>
<tr> <tr>
<th scope="row">PSK</th> <th scope="row">PSK</th>
<td class="font-monospace">{{ object.auth_psk|placeholder }}</td> <td>
<span id="secret" class="font-monospace" data-secret="{{ object.auth_psk }}">{{ object.auth_psk|placeholder }}</span>
{% if object.auth_psk %}
<button type="button" class="btn btn-sm btn-primary toggle-secret float-end" data-bs-toggle="button">Show Secret</button>
{% endif %}
</td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@ -1,3 +1,4 @@
from django.forms import PasswordInput
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from dcim.models import Device, Interface, Location, Region, Site, SiteGroup from dcim.models import Device, Interface, Location, Region, Site, SiteGroup
from ipam.models import VLAN, VLANGroup from ipam.models import VLAN, VLANGroup
@ -101,6 +102,10 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
'status': StaticSelect, 'status': StaticSelect,
'auth_type': StaticSelect, 'auth_type': StaticSelect,
'auth_cipher': StaticSelect, 'auth_cipher': StaticSelect,
'auth_psk': PasswordInput(
render_value=True,
attrs={'data-toggle': 'password'}
),
} }
@ -206,6 +211,10 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'status': StaticSelect, 'status': StaticSelect,
'auth_type': StaticSelect, 'auth_type': StaticSelect,
'auth_cipher': StaticSelect, 'auth_cipher': StaticSelect,
'auth_psk': PasswordInput(
render_value=True,
attrs={'data-toggle': 'password'}
),
} }
labels = { labels = {
'auth_type': 'Type', 'auth_type': 'Type',