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()
|