force_delete/force_delete.ts

122 lines
3.3 KiB
TypeScript
Raw Normal View History

2024-10-03 00:09:46 +00:00
class ForceDeleteExtension {
2024-10-08 10:11:05 +00:00
private readonly LOOP_INTERVAL_TIME = 100
2024-10-03 00:09:46 +00:00
2024-10-03 23:30:15 +00:00
private readonly EXPLICIT_TARGET_SELECTORS = [
2024-10-03 00:09:46 +00:00
// S3 ---
'.delete-bucket-actions__input>input',
// VPC ---
2024-10-07 10:31:16 +00:00
'div[data-id="confirmation-modal-input"]>input',
// IAM ---
2024-11-14 01:06:17 +00:00
'div[data-testid="delete-user-input-test1"]>input',
2024-10-07 10:31:16 +00:00
'div[data-testid="roles-delete-modal-input"]>input',
2024-10-08 10:11:05 +00:00
'div[data-testid="policies-delete-modal-input"]>input',
'div[data-testid="policies-from-role-delete-modal-input"]>input',
// Firehose ---
2024-10-10 22:58:01 +00:00
'div[data-hook="DELETE_CONFIRMATION_INPUT"]>input',
2024-10-03 00:09:46 +00:00
2024-10-10 22:58:01 +00:00
// RDS ---
'div[data-testid="delete-protection-input"]>input'
]
private readonly OVERRIDDEN_TARGET_VALUES = [
{
target: 'div[data-testid="delete-protection-input"]>input',
value: 'delete me'
}
2024-10-03 00:09:46 +00:00
]
2024-10-03 23:30:15 +00:00
private readonly IMPLICIT_TARGET_PLACEHOLDERS = [
'delete',
'delete me',
2024-10-07 10:31:16 +00:00
'confirm',
'permanently delete'
2024-10-03 23:30:15 +00:00
]
2024-10-03 00:09:46 +00:00
public readonly startLoop = (): void => {
setInterval(
this.process.bind(this),
this.LOOP_INTERVAL_TIME)
}
2024-10-03 23:30:15 +00:00
private readonly process = (): void =>
2024-10-03 00:09:46 +00:00
this.applyDeleteMessages(this.findTargets())
//
// Target Element Finder ---
2024-10-03 23:30:15 +00:00
private readonly findTargets = (): HTMLInputElement[] => [
...this.findExplicitTargets(),
...this.findImplicitTargets()
]
2024-10-03 00:09:46 +00:00
2024-10-03 23:30:15 +00:00
private readonly findExplicitTargets = (): HTMLInputElement[] =>
this.EXPLICIT_TARGET_SELECTORS
2024-10-03 00:09:46 +00:00
.map(this.findTargetElements.bind(this))
.reduce((prev, curr) => ([...prev, ...curr]), [])
.filter((v) =>
v !== null &&
v instanceof HTMLInputElement
)
.filter((v) =>
!v.disabled &&
v.value.length < 1
)
2024-10-03 23:30:15 +00:00
private readonly findImplicitTargets = (): HTMLInputElement[] =>
this.findTargetElements('input')
.filter((v) =>
v !== null &&
v instanceof HTMLInputElement
)
.filter((v) =>
!v.disabled &&
v.value.length < 1 &&
this.IMPLICIT_TARGET_PLACEHOLDERS.includes(v.placeholder.toLowerCase())
)
2024-10-03 00:09:46 +00:00
private readonly findTargetElements = (targetSelector: string): Array<Element | null> =>
[...document.querySelectorAll(targetSelector)]
//
// Delete-safe Message Applier ---
private readonly applyDeleteMessages = (elements: HTMLInputElement[]): void =>
elements.forEach(this.applyDeleteMessage.bind(this))
private readonly applyDeleteMessage = (element: HTMLInputElement): void => {
2024-10-10 22:58:01 +00:00
element.classList.add('__force_deleted') // Play autocomplete animation
2024-10-08 10:11:05 +00:00
2024-10-10 22:58:01 +00:00
element.value = this.calculateValue(element)
2024-10-03 00:09:46 +00:00
element.dispatchEvent(new Event('input', {
bubbles: true
}))
}
2024-10-10 22:58:01 +00:00
//
// Value Calculator ---
private readonly calculateValue = (element: HTMLInputElement): string =>
this.findOverriddenValue(element) ??
this.findPlaceholderValue(element) ??
'delete'
private readonly findOverriddenValue = (element: HTMLElement): string | undefined =>
this.OVERRIDDEN_TARGET_VALUES
.find((v) => [...document.querySelectorAll(v.target)].includes(element))
?.value
private readonly findPlaceholderValue = (element: HTMLInputElement): string | undefined =>
element.placeholder.length > 0
? element.placeholder
: undefined
2024-10-03 00:09:46 +00:00
}
//
// Main ---
new ForceDeleteExtension()
.startLoop()