diff --git a/frontend/src/lib/components/RadioOption.svelte b/frontend/src/lib/components/RadioOption.svelte new file mode 100644 index 0000000..49f6ee3 --- /dev/null +++ b/frontend/src/lib/components/RadioOption.svelte @@ -0,0 +1,25 @@ + + + diff --git a/frontend/src/lib/components/SettingsCard.svelte b/frontend/src/lib/components/SettingsCard.svelte new file mode 100644 index 0000000..c7a11cc --- /dev/null +++ b/frontend/src/lib/components/SettingsCard.svelte @@ -0,0 +1,23 @@ + + +
+

+ {title} +

+
+ +
+ {#if $$slots.footer} +
+ +
+ {/if} +
diff --git a/frontend/src/lib/components/SettingsLoading.svelte b/frontend/src/lib/components/SettingsLoading.svelte new file mode 100644 index 0000000..e5c2893 --- /dev/null +++ b/frontend/src/lib/components/SettingsLoading.svelte @@ -0,0 +1,10 @@ + + +
+
+ Loading... +
diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index ac0e982..1a18ce4 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -1,1653 +1,65 @@
Settings - {#if isInitiallyLoaded} -
- -
- -
-

- Single Sign-On -

-
-
- {#if isSSOEnabled} -

- - Enabled -

- {:else} -

- - Disabled -

- {/if} -
-
- {#if isSSOEnabled} - - {:else} - - {/if} -
-
-
- -
-

- Auto-Prune Recipients -

-
-
-

- Automatically delete orphaned recipients (not in any group) on a hourly schedule. -

-
- - -
- -
-
-
- - -
-

- General Settings -

-
-
-
- Upload max file size (MB) - Repeat Offender Memory (Months) - -
-
- Save Changes -
-
-
-
- - -
-

- Logging -

-
-
-
- Application log level - - Database log level -
-
-
-
- - -
-

- Import -

-
-
- onSetImportFile(e)}> - Select ZIP file to import - - - {#if importForCompany} -
- Company Import:
Pages and emails will be imported for this company. - Assets will be imported as global/shared resources. -
- {:else} -
- Global Import: All templates and assets will be imported as shared - resources. -
- {/if} - -
-
- - {#if isImportSubmitting} - Importing... - {:else} - Import File - {/if} - -
-
-
- -
-

- Display Mode -

-
-
-

- Select which features are available -

-
- - -

- Read about the difference between phishing simulation and red team phishing -

-
- -
-
-
- - -
-

- Backup -

-
-
-

- Create a backup of database, assets, attachments and certificates. -

- - {#if availableBackups.length > 0} -
-

- Available: -

-
- {#each availableBackups as backup} -
-
- - {new Date(backup.createdAt).toLocaleString()} - - - {(backup.size / 1024 / 1024).toFixed(1)} MB - -
- -
- {/each} -
-
- {:else if !isLoadingBackups} -
- No backups available yet. -
- {/if} -
-
- -
-
-
- - - -
-

- Obfuscation Template -

-
-
-

- Customize the template used when obfuscation is enabled to. -

-
-

- Internal obfuscation variable: -

-

- {'{{.Script}}'} -

-
-
-
- -
-
-
-
- - - {#if !isCompanyContext} -
-

- Report Template -

-
-
-

- Default HTML template used when generating campaign PDF reports. Companies without their own template fall back to this. -

-
-
- -
-
-
- {/if} - - -
-

- PDF Reports -

-
-
-

- Generate PDF reports for campaigns. Requires Chromium and system dependencies. -

-

- {isReportPDFEnabled ? 'Enabled' : 'Disabled'} -

-
-
- -
-
-
- - -
-

- Browser Cache -

-
-
-

- Chromium is downloaded and cached for PDF reports and remote browser sessions. Wipe to force a fresh download. -

-
-
- -
-
-
-
-
- - {#if isImportResultModalVisible && importResult} - -
{}} - bind:this={importModalContent} - > -
- -
- -
-

- Assets (Global/Shared) -

-
    -
  • Created: {importResult.assets_created}
  • -
  • Skipped: {importResult.assets_skipped}
  • -
  • Errors: {importResult.assets_errors}
  • -
-

- Assets are always imported as global resources -

-
- - -
-

- Pages -

-
    -
  • Created: {importResult.pages_created}
  • -
  • Updated: {importResult.pages_updated}
  • -
  • Skipped: {importResult.pages_skipped}
  • -
  • Errors: {importResult.pages_errors}
  • -
-
- - -
-

- Emails -

-
    -
  • Created: {importResult.emails_created}
  • -
  • Updated: {importResult.emails_updated}
  • -
  • Skipped: {importResult.emails_skipped}
  • -
  • Errors: {importResult.emails_errors}
  • -
-
-
- - -
-
- - {#if importResult.assets_skipped_list?.length > 0} -
-

Assets (Global/Shared)

-

- All assets are imported as global resources regardless of import context -

-
- {#if importResult.assets_skipped_list?.length > 0} -
-

Skipped:

-
    - {#each importResult.assets_skipped_list || [] as asset} -
  • {asset}
  • - {/each} -
-
- {/if} -
-
- {/if} - {#if importResult.assets_errors_list?.length > 0} -
-

Errors:

-
    - {#each importResult.assets_errors_list as err} -
  • - {err.type}: - {err.name} — {err.message} -
  • - {/each} -
-
- {/if} - - - {#if importResult.pages_created_list?.length > 0 || importResult.pages_updated_list?.length > 0 || importResult.pages_skipped_list?.length > 0 || importResult.pages_errors_list?.length > 0} -
-

Pages

-
- {#if importResult.pages_created_list?.length > 0} -
-

Created:

-
    - {#each importResult.pages_created_list || [] as page} -
  • {page}
  • - {/each} -
-
- {/if} - {#if importResult.pages_updated_list?.length > 0} -
-

Updated:

-
    - {#each importResult.pages_updated_list || [] as page} -
  • {page}
  • - {/each} -
-
- {/if} - {#if importResult.pages_skipped_list?.length > 0} -
-

Skipped:

-
    - {#each importResult.pages_skipped_list || [] as page} -
  • {page}
  • - {/each} -
-
- {/if} - {#if importResult.pages_errors_list?.length > 0} -
-

Errors:

-
    - {#each importResult.pages_errors_list as err} -
  • - {err.type}: - {err.name} — {err.message} -
  • - {/each} -
-
- {/if} -
-
- {/if} - - - {#if importResult.emails_created_list?.length > 0 || importResult.emails_updated_list?.length > 0 || importResult.emails_errors_list?.length > 0 || importResult.emails_skipped_list?.length > 0} -
-

Emails

-
- {#if importResult.emails_created_list?.length > 0} -
-

Created:

-
    - {#each importResult.emails_created_list || [] as email} -
  • {email}
  • - {/each} -
-
- {/if} - {#if importResult.emails_updated_list?.length > 0} -
-

Updated:

-
    - {#each importResult.emails_updated_list || [] as email} -
  • {email}
  • - {/each} -
-
- {/if} - {#if importResult.emails_errors_list?.length > 0} -
-

Errors:

-
    - {#each importResult.emails_errors_list as err} -
  • - {err.type}: - {err.name} — {err.message} -
  • - {/each} -
-
- {/if} -
-
- {/if} -
-
-
- {#if importResult.errors && importResult.errors.length > 0} -
-

Errors:

-
    - {#each importResult.errors as err} -
  • - {err.type}: - {err.name} — {err.message} -
  • - {/each} -
-
- {/if} -
- -
-
-
- {/if} - - -
-
+
- {/if} - {#if isSSOModalVisible} - -
- -
-

Microsoft SSO Setup

-

- Configure Single Sign-On with Microsoft Azure AD. -

-
+ - -
-

Important:

-

- Accounts that login with SSO will no longer be able to use password login. -

-
-
- - - - - Client ID - Tenant ID - - - Redirect URL - - Client Secret - - - - - -
- {/if} - - {#if isSSODeleteAlertVisible} - onClickDisableSSO()} - bind:isVisible={isSSODeleteAlertVisible} - > - {/if} - - {#if isSSODeleteAlertVisible} - onClickDisableSSO()} - bind:isVisible={isSSODeleteAlertVisible} - /> - {/if} - - {#if isBackupModalVisible} - - - - -
-

This will create a backup file that can be downloaded from the settings page.

-

- Note: This is not a substitute for having proper automated and tested - backup and recovery plans at the operating system level. -

-
-

- What will be backed up: -

-
    -
  • • SQLite database (including WAL files)
  • -
  • • Asset files
  • -
  • • Attachment files
  • -
  • • Certificate files
  • -
-
- -
-

Important:

-
    -
  • • Large databases may take significant time to backup
  • -
  • • Operations may be affected during the backup process
  • -
  • • Ensure you have sufficient disk space
  • -
  • - • Only the 3 most recent backups are kept (older ones are automatically deleted) -
  • -
  • • The backup does not include config.json or the application binary
  • -
-
-
-
-
- -
-
- {/if} - - {#if isObfuscationTemplateModalVisible} - - -
- -

- Example {"eval(atob('{{base64 .Script}}'))"} -

- -
- -
-
- {/if} - - {#if isReportTemplateModalVisible} - - -
- - -
- -
-
- {/if} - {#if isReportPDFEnableModalVisible} - -
-

PDF report generation requires Chromium and additional system dependencies that are not part of the standard installation.

-

Before enabling, ensure the host has the required libraries and any AppArmor restrictions on unprivileged user namespaces have been addressed.

-

See the setup guide for dependency installation and AppArmor configuration.

-
-
- {/if} +
+ +
diff --git a/frontend/src/routes/settings/panels/Access.svelte b/frontend/src/routes/settings/panels/Access.svelte new file mode 100644 index 0000000..455648a --- /dev/null +++ b/frontend/src/routes/settings/panels/Access.svelte @@ -0,0 +1,213 @@ + + +{#if !loaded} + +{:else} +
+ +
+ {#if isSSOEnabled} +

+ + Enabled +

+ {:else} +

+ + Disabled +

+ {/if} +
+ + {#if isSSOEnabled} + + {:else} + + {/if} + +
+
+{/if} + +{#if isSSOModalVisible} + +
+
+

Microsoft SSO Setup

+

+ Configure Single Sign-On with Microsoft Azure AD. +

+
+ +
+

Important:

+

+ Accounts that login with SSO will no longer be able to use password login. +

+
+
+ + + + Client ID + Tenant ID + + + Redirect URL + + Client Secret + + + + + +
+{/if} + +{#if isSSODeleteAlertVisible} + onClickDisableSSO()} + bind:isVisible={isSSODeleteAlertVisible} + /> +{/if} diff --git a/frontend/src/routes/settings/panels/Data.svelte b/frontend/src/routes/settings/panels/Data.svelte new file mode 100644 index 0000000..766c883 --- /dev/null +++ b/frontend/src/routes/settings/panels/Data.svelte @@ -0,0 +1,588 @@ + + +{#if !loaded} + +{:else} +
+ +
+ onSetImportFile(e)}> + Select ZIP file to import + + + {#if importForCompany} +
+ Company Import:
Pages and emails will be imported for this company. Assets + will be imported as global/shared resources. +
+ {:else} +
+ Global Import: All templates and assets will be imported as shared resources. +
+ {/if} + +
+ + + {#if isImportSubmitting} + Importing... + {:else} + Import File + {/if} + + +
+ + +
+

+ Create a backup of database, assets, attachments and certificates. +

+ + {#if availableBackups.length > 0} +
+

+ Available: +

+
+ {#each availableBackups as backup} +
+
+ + {new Date(backup.createdAt).toLocaleString()} + + + {(backup.size / 1024 / 1024).toFixed(1)} MB + +
+ +
+ {/each} +
+
+ {:else if !isLoadingBackups} +
+ No backups available yet. +
+ {/if} +
+ + + +
+ + +
+

+ Automatically delete orphaned recipients (not in any group) on a hourly schedule. +

+
+ setAutoPruneValue(true)} + /> + setAutoPruneValue(false)} + /> +
+ +
+
+
+{/if} + +{#if isImportResultModalVisible && importResult} + +
+
+
+
+

+ Assets (Global/Shared) +

+
    +
  • Created: {importResult.assets_created}
  • +
  • Skipped: {importResult.assets_skipped}
  • +
  • Errors: {importResult.assets_errors}
  • +
+

+ Assets are always imported as global resources +

+
+ +
+

+ Pages +

+
    +
  • Created: {importResult.pages_created}
  • +
  • Updated: {importResult.pages_updated}
  • +
  • Skipped: {importResult.pages_skipped}
  • +
  • Errors: {importResult.pages_errors}
  • +
+
+ +
+

+ Emails +

+
    +
  • Created: {importResult.emails_created}
  • +
  • Updated: {importResult.emails_updated}
  • +
  • Skipped: {importResult.emails_skipped}
  • +
  • Errors: {importResult.emails_errors}
  • +
+
+
+ +
+
+ {#if importResult.assets_skipped_list?.length > 0} +
+

Assets (Global/Shared)

+

+ All assets are imported as global resources regardless of import context +

+
+ {#if importResult.assets_skipped_list?.length > 0} +
+

Skipped:

+
    + {#each importResult.assets_skipped_list || [] as asset} +
  • {asset}
  • + {/each} +
+
+ {/if} +
+
+ {/if} + {#if importResult.assets_errors_list?.length > 0} +
+

Errors:

+
    + {#each importResult.assets_errors_list as err} +
  • + {err.type}: + {err.name} — {err.message} +
  • + {/each} +
+
+ {/if} + + {#if importResult.pages_created_list?.length > 0 || importResult.pages_updated_list?.length > 0 || importResult.pages_skipped_list?.length > 0 || importResult.pages_errors_list?.length > 0} +
+

Pages

+
+ {#if importResult.pages_created_list?.length > 0} +
+

Created:

+
    + {#each importResult.pages_created_list || [] as page} +
  • {page}
  • + {/each} +
+
+ {/if} + {#if importResult.pages_updated_list?.length > 0} +
+

Updated:

+
    + {#each importResult.pages_updated_list || [] as page} +
  • {page}
  • + {/each} +
+
+ {/if} + {#if importResult.pages_skipped_list?.length > 0} +
+

Skipped:

+
    + {#each importResult.pages_skipped_list || [] as page} +
  • {page}
  • + {/each} +
+
+ {/if} + {#if importResult.pages_errors_list?.length > 0} +
+

Errors:

+
    + {#each importResult.pages_errors_list as err} +
  • + {err.type}: + {err.name} — {err.message} +
  • + {/each} +
+
+ {/if} +
+
+ {/if} + + {#if importResult.emails_created_list?.length > 0 || importResult.emails_updated_list?.length > 0 || importResult.emails_errors_list?.length > 0 || importResult.emails_skipped_list?.length > 0} +
+

Emails

+
+ {#if importResult.emails_created_list?.length > 0} +
+

Created:

+
    + {#each importResult.emails_created_list || [] as email} +
  • {email}
  • + {/each} +
+
+ {/if} + {#if importResult.emails_updated_list?.length > 0} +
+

Updated:

+
    + {#each importResult.emails_updated_list || [] as email} +
  • {email}
  • + {/each} +
+
+ {/if} + {#if importResult.emails_errors_list?.length > 0} +
+

Errors:

+
    + {#each importResult.emails_errors_list as err} +
  • + {err.type}: + {err.name} — {err.message} +
  • + {/each} +
+
+ {/if} +
+
+ {/if} +
+
+
+ {#if importResult.errors && importResult.errors.length > 0} +
+

Errors:

+
    + {#each importResult.errors as err} +
  • + {err.type}: + {err.name} — {err.message} +
  • + {/each} +
+
+ {/if} +
+ +
+
+
+{/if} + +{#if isBackupModalVisible} + + + + +
+

This will create a backup file that can be downloaded from the settings page.

+

+ Note: This is not a substitute for having proper automated and tested backup + and recovery plans at the operating system level. +

+
+

What will be backed up:

+
    +
  • • SQLite database (including WAL files)
  • +
  • • Asset files
  • +
  • • Attachment files
  • +
  • • Certificate files
  • +
+
+ +
+

Important:

+
    +
  • • Large databases may take significant time to backup
  • +
  • • Operations may be affected during the backup process
  • +
  • • Ensure you have sufficient disk space
  • +
  • + • Only the 3 most recent backups are kept (older ones are automatically deleted) +
  • +
  • • The backup does not include config.json or the application binary
  • +
+
+
+
+
+ +
+
+{/if} diff --git a/frontend/src/routes/settings/panels/General.svelte b/frontend/src/routes/settings/panels/General.svelte new file mode 100644 index 0000000..1a2f8f7 --- /dev/null +++ b/frontend/src/routes/settings/panels/General.svelte @@ -0,0 +1,162 @@ + + +{#if !loaded} + +{:else} +
+ +
+

+ Select which features are available +

+
+ setDisplayMode(DISPLAY_MODE.WHITEBOX)} + /> + setDisplayMode(DISPLAY_MODE.BLACKBOX)} + /> +

+ Read about the difference between phishing simulation and red team phishing +

+
+ +
+
+ + +
+ Upload max file size (MB) + Repeat Offender Memory (Months) + +
+ Save Changes +
+ +
+
+{/if} diff --git a/frontend/src/routes/settings/panels/RedTeam.svelte b/frontend/src/routes/settings/panels/RedTeam.svelte new file mode 100644 index 0000000..0266864 --- /dev/null +++ b/frontend/src/routes/settings/panels/RedTeam.svelte @@ -0,0 +1,124 @@ + + +
+ +
+

+ Customize the template used when obfuscation is enabled to. +

+
+

+ Internal obfuscation variable: +

+

+ {'{{.Script}}'} +

+
+
+ + + +
+
+ +{#if isObfuscationTemplateModalVisible} + + +
+ +

+ Example {"eval(atob('{{base64 .Script}}'))"} +

+ +
+ +
+
+{/if} diff --git a/frontend/src/routes/settings/panels/Reports.svelte b/frontend/src/routes/settings/panels/Reports.svelte new file mode 100644 index 0000000..d9c1085 --- /dev/null +++ b/frontend/src/routes/settings/panels/Reports.svelte @@ -0,0 +1,241 @@ + + +{#if !loaded} + +{:else} +
+ +
+

+ Generate PDF reports for campaigns. Requires Chromium and system dependencies. +

+

+ {isReportPDFEnabled ? 'Enabled' : 'Disabled'} +

+
+ + + +
+ + {#if !isCompanyContext} + +

+ Default HTML template used when generating campaign PDF reports. Companies without their own + template fall back to this. +

+ + + +
+ {/if} +
+{/if} + +{#if isReportTemplateModalVisible} + + +
+ + +
+ +
+
+{/if} + +{#if isReportPDFEnableModalVisible} + +
+

+ PDF report generation requires Chromium and additional system dependencies that are not part + of the standard installation. +

+

+ Before enabling, ensure the host has the required libraries and any AppArmor restrictions on + unprivileged user namespaces have been addressed. +

+

+ See the setup guide for dependency installation and AppArmor configuration. +

+
+
+{/if} diff --git a/frontend/src/routes/settings/panels/System.svelte b/frontend/src/routes/settings/panels/System.svelte new file mode 100644 index 0000000..da9fcec --- /dev/null +++ b/frontend/src/routes/settings/panels/System.svelte @@ -0,0 +1,205 @@ + + +{#if !loaded} + +{:else} +
+ +
+ Application log level + + Database log level +
+
+ + +

+ Chromium is downloaded and cached for PDF reports and remote browser sessions. Wipe to force a + fresh download. +

+ + + +
+ + +
+
+ Version + +
+
+ Status + {#if updateAvailable} + Update available + {:else} + Up to date + {/if} +
+
+ Licenses + View licenses +
+
+ + + +
+
+{/if}