mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-08-30 22:20:45 +02:00
cleanup from old proxy page test
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
@@ -1314,15 +1314,13 @@ export class API {
|
||||
* @param {string} name
|
||||
* @param {string} content
|
||||
* @param {string} companyID
|
||||
* @param {object} additionalFields - Optional additional fields for Proxy pages
|
||||
* @returns {Promise<ApiResponse>}
|
||||
*/
|
||||
create: async (name, content, companyID, additionalFields = {}) => {
|
||||
create: async (name, content, companyID) => {
|
||||
const payload = {
|
||||
name: name,
|
||||
content: content,
|
||||
companyID: companyID,
|
||||
...additionalFields
|
||||
companyID: companyID
|
||||
};
|
||||
return await postJSON(this.getPath('/page'), payload);
|
||||
},
|
||||
|
||||
@@ -388,11 +388,19 @@
|
||||
isDetailsVisible = true;
|
||||
}}
|
||||
type="button"
|
||||
class="h-8 border-2 border-gray-300 dark:border-gray-600 rounded-md w-36 text-center cursor-pointer hover:opacity-80 flex items-center justify-center gap-2 mb-2 text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-700 transition-colors duration-200"
|
||||
class="h-8 border-2 rounded-md w-36 text-center cursor-pointer hover:opacity-80 flex items-center justify-center gap-2 mb-2 transition-colors duration-200"
|
||||
class:font-bold={isDetailsVisible}
|
||||
class:bg-cta-blue={isDetailsVisible}
|
||||
class:dark:bg-indigo-600={isDetailsVisible}
|
||||
class:bg-blue-600={isDetailsVisible}
|
||||
class:dark:bg-blue-500={isDetailsVisible}
|
||||
class:text-white={isDetailsVisible}
|
||||
class:border-blue-600={isDetailsVisible}
|
||||
class:dark:border-blue-500={isDetailsVisible}
|
||||
class:text-gray-700={!isDetailsVisible}
|
||||
class:dark:text-gray-200={!isDetailsVisible}
|
||||
class:bg-white={!isDetailsVisible}
|
||||
class:dark:bg-gray-700={!isDetailsVisible}
|
||||
class:border-gray-300={!isDetailsVisible}
|
||||
class:dark:border-gray-600={!isDetailsVisible}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -414,11 +422,19 @@
|
||||
isDetailsVisible = false;
|
||||
}}
|
||||
type="button"
|
||||
class="h-8 border-2 border-gray-300 dark:border-gray-600 rounded-md w-36 text-center cursor-pointer hover:opacity-80 ml-1 flex items-center justify-center gap-2 text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-700 transition-colors duration-200"
|
||||
class="h-8 border-2 rounded-md w-36 text-center cursor-pointer hover:opacity-80 ml-1 flex items-center justify-center gap-2 transition-colors duration-200"
|
||||
class:font-bold={!isDetailsVisible}
|
||||
class:bg-cta-blue={!isDetailsVisible}
|
||||
class:dark:bg-indigo-600={!isDetailsVisible}
|
||||
class:bg-blue-600={!isDetailsVisible}
|
||||
class:dark:bg-blue-500={!isDetailsVisible}
|
||||
class:text-white={!isDetailsVisible}
|
||||
class:border-blue-600={!isDetailsVisible}
|
||||
class:dark:border-blue-500={!isDetailsVisible}
|
||||
class:text-gray-700={isDetailsVisible}
|
||||
class:dark:text-gray-200={isDetailsVisible}
|
||||
class:bg-white={isDetailsVisible}
|
||||
class:dark:bg-gray-700={isDetailsVisible}
|
||||
class:border-gray-300={isDetailsVisible}
|
||||
class:dark:border-gray-600={isDetailsVisible}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
import TableCellAction from '$lib/components/table/TableCellAction.svelte';
|
||||
import Modal from '$lib/components/Modal.svelte';
|
||||
import FormGrid from '$lib/components/FormGrid.svelte';
|
||||
import ProxySvgIcon from '$lib/components/ProxySvgIcon.svelte';
|
||||
|
||||
import BigButton from '$lib/components/BigButton.svelte';
|
||||
import FormColumns from '$lib/components/FormColumns.svelte';
|
||||
import FormColumn from '$lib/components/FormColumn.svelte';
|
||||
@@ -34,7 +34,6 @@
|
||||
import { fetchAllRows } from '$lib/utils/api-utils';
|
||||
import { BiMap } from '$lib/utils/maps';
|
||||
import AutoRefresh from '$lib/components/AutoRefresh.svelte';
|
||||
import SimpleCodeEditor from '$lib/components/editor/SimpleCodeEditor.svelte';
|
||||
|
||||
// services
|
||||
const appStateService = AppStateService.instance;
|
||||
@@ -44,10 +43,7 @@
|
||||
let formValues = {
|
||||
id: null,
|
||||
name: null,
|
||||
content: null,
|
||||
type: 'regular',
|
||||
targetURL: null,
|
||||
proxyConfig: null
|
||||
content: null
|
||||
};
|
||||
let isSubmitting = false;
|
||||
|
||||
@@ -68,54 +64,6 @@
|
||||
name: null
|
||||
};
|
||||
|
||||
// proxy example configuration - simplified to only capture and replacement rules
|
||||
const proxyExample = `capture:
|
||||
- name: 'login credentials'
|
||||
method: 'POST' # optional, default GET
|
||||
path: '/login' # regex path pattern - matches /login exactly
|
||||
find: 'username=([^&]+)&password=([^&]+)' # REQUIRED - regex pattern to capture data
|
||||
from: 'request_body' # where to capture from: request_body, request_header, response_body, response_header, any
|
||||
# required: true # default - all captures are required unless explicitly set to false
|
||||
|
||||
- name: 'has completed login'
|
||||
method: 'GET'
|
||||
path: '/secure' # navigation tracking - just checks if user visited this path
|
||||
# no find pattern needed for path-based navigation tracking
|
||||
# required: true # default - user must visit /secure before campaign progresses
|
||||
|
||||
- name: 'form submission'
|
||||
method: 'POST'
|
||||
path: '/submit-data' # tracks POST requests to this endpoint
|
||||
# no find pattern needed - just tracking that the form was submitted
|
||||
|
||||
- name: 'profile update'
|
||||
method: 'PUT'
|
||||
path: '/api/profile' # tracks PUT requests for profile updates
|
||||
# navigation tracking works with any HTTP method
|
||||
|
||||
- name: 'api tokens'
|
||||
path: '/api/v\\d+/auth.*' # regex - matches /api/v1/auth, /api/v2/auth/token, etc.
|
||||
find: 'token=([a-zA-Z0-9]+)' # REQUIRED - all captures must have a find pattern
|
||||
from: 'response_body'
|
||||
|
||||
- name: 'optional tracking data'
|
||||
path: '^/dashboard' # regex - matches paths starting with /dashboard
|
||||
find: 'session_id=([a-f0-9]+)' # REQUIRED - find pattern is mandatory
|
||||
from: 'response_header'
|
||||
required: false # explicitly mark as optional - campaign will progress without this
|
||||
|
||||
replace:
|
||||
- name: 'replace logo'
|
||||
find: 'https://target\\.example\\.com/logo\\.png'
|
||||
replace: 'https://evil.domain.com/assets/logo.png'
|
||||
|
||||
- name: 'replace links'
|
||||
find: 'href="([^"]*target\\.example\\.com[^"]*)"'
|
||||
replace: 'href="https://evil.domain.com$1"'`;
|
||||
|
||||
$: isRegularPage = formValues.type === 'regular';
|
||||
$: isProxyPage = formValues.type === 'proxy';
|
||||
|
||||
$: {
|
||||
modalText = getModalText('page', modalMode);
|
||||
}
|
||||
@@ -209,20 +157,7 @@ replace:
|
||||
|
||||
const create = async () => {
|
||||
try {
|
||||
const pageData = {
|
||||
name: formValues.name,
|
||||
type: formValues.type,
|
||||
content: isRegularPage ? formValues.content : null,
|
||||
targetURL: isProxyPage ? formValues.targetURL : null,
|
||||
proxyConfig: isProxyPage ? formValues.proxyConfig : null
|
||||
};
|
||||
|
||||
const res = await api.page.create(
|
||||
pageData.name,
|
||||
pageData.content,
|
||||
contextCompanyID,
|
||||
pageData
|
||||
);
|
||||
const res = await api.page.create(formValues.name, formValues.content, contextCompanyID);
|
||||
if (!res.success) {
|
||||
formError = res.error;
|
||||
return;
|
||||
@@ -240,10 +175,7 @@ replace:
|
||||
try {
|
||||
const updateData = {
|
||||
name: formValues.name,
|
||||
type: formValues.type,
|
||||
content: isRegularPage ? formValues.content : null,
|
||||
targetURL: isProxyPage ? formValues.targetURL : null,
|
||||
proxyConfig: isProxyPage ? formValues.proxyConfig : null
|
||||
content: formValues.content
|
||||
};
|
||||
|
||||
const res = await api.page.update(formValues.id, updateData);
|
||||
@@ -288,9 +220,6 @@ replace:
|
||||
formValues.content = '';
|
||||
formValues.name = '';
|
||||
formValues.id = '';
|
||||
formValues.type = 'regular';
|
||||
formValues.targetURL = '';
|
||||
formValues.proxyConfig = '';
|
||||
form.reset();
|
||||
formError = '';
|
||||
};
|
||||
@@ -305,10 +234,7 @@ replace:
|
||||
formValues = {
|
||||
id: null,
|
||||
name: null,
|
||||
content: null,
|
||||
type: 'regular',
|
||||
targetURL: null,
|
||||
proxyConfig: null
|
||||
content: null
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -337,10 +263,7 @@ replace:
|
||||
formValues = {
|
||||
id: null,
|
||||
name: null,
|
||||
content: null,
|
||||
type: 'regular',
|
||||
targetURL: null,
|
||||
proxyConfig: null
|
||||
content: null
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -366,9 +289,6 @@ replace:
|
||||
formValues.id = page.id;
|
||||
formValues.name = page.name;
|
||||
formValues.content = page.content || '';
|
||||
formValues.type = page.type && page.type.trim() !== '' ? page.type : 'regular';
|
||||
formValues.targetURL = page.targetURL || '';
|
||||
formValues.proxyConfig = page.proxyConfig || '';
|
||||
};
|
||||
|
||||
/** @param {*} event */
|
||||
@@ -440,115 +360,18 @@ replace:
|
||||
</Table>
|
||||
<Modal headerText={modalText} visible={isModalVisible} onClose={closeModal} {isSubmitting}>
|
||||
<FormGrid on:submit={onSubmit} bind:bindTo={form} {isSubmitting}>
|
||||
<div class="col-span-3 w-full overflow-y-auto px-6 py-4 space-y-8">
|
||||
<!-- Basic Information Section -->
|
||||
<div class="w-full">
|
||||
<h3 class="text-base font-medium text-pc-darkblue dark:text-white mb-3">
|
||||
Basic Information
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<TextField
|
||||
required
|
||||
minLength={1}
|
||||
maxLength={64}
|
||||
bind:value={formValues.name}
|
||||
placeholder="Intranet login">Name</TextField
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<div class="w-full">
|
||||
<div class="flex flex-col py-2">
|
||||
<div class="flex items-center">
|
||||
<p
|
||||
class="font-semibold text-slate-600 dark:text-gray-300 py-2 transition-colors duration-200"
|
||||
>
|
||||
Type
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex space-x-4">
|
||||
<label
|
||||
class="flex items-center space-x-2 px-3 py-2 border rounded-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
|
||||
class:bg-blue-50={formValues.type === 'regular'}
|
||||
class:border-blue-300={formValues.type === 'regular'}
|
||||
class:dark:bg-blue-900={formValues.type === 'regular'}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={formValues.type}
|
||||
value="regular"
|
||||
class="text-blue-600"
|
||||
/>
|
||||
<span class="text-sm text-slate-600 dark:text-gray-300">📄 Regular</span>
|
||||
</label>
|
||||
<label
|
||||
class="flex items-center space-x-2 px-3 py-2 border rounded-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-200"
|
||||
class:bg-blue-50={formValues.type === 'proxy'}
|
||||
class:border-blue-300={formValues.type === 'proxy'}
|
||||
class:dark:bg-blue-900={formValues.type === 'proxy'}
|
||||
>
|
||||
<input
|
||||
type="radio"
|
||||
bind:group={formValues.type}
|
||||
value="proxy"
|
||||
class="text-blue-600"
|
||||
/>
|
||||
<span
|
||||
class="text-sm text-slate-600 dark:text-gray-300 flex items-center gap-1"
|
||||
>
|
||||
<ProxySvgIcon size="w-4 h-4" />
|
||||
Proxy
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Editor contentType="page" {domainMap} bind:value={formValues.content}>
|
||||
<div class="pl-4">
|
||||
<TextField
|
||||
minLength={1}
|
||||
maxLength={64}
|
||||
required
|
||||
bind:value={formValues.name}
|
||||
placeholder="Intranet login">Name</TextField
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Content Configuration Section -->
|
||||
<div class="w-full">
|
||||
<h3 class="text-base font-medium text-pc-darkblue dark:text-white mb-3">
|
||||
{#if isProxyPage}
|
||||
Proxy Configuration
|
||||
{:else}
|
||||
Page Content
|
||||
{/if}
|
||||
</h3>
|
||||
|
||||
{#if isRegularPage}
|
||||
<Editor contentType="page" {domainMap} bind:value={formValues.content} />
|
||||
{/if}
|
||||
|
||||
{#if isProxyPage}
|
||||
<div class="space-y-6">
|
||||
<div class="flex flex-col py-2 w-full">
|
||||
<div class="flex items-center">
|
||||
<p class="font-bold text-slate-600 dark:text-gray-300 py-2">
|
||||
Proxy Capture & Replacement Rules (YAML)
|
||||
</p>
|
||||
<div class="ml-2 text-xs text-gray-500">
|
||||
Data captures require a 'find' pattern. Path-based navigation tracking (any
|
||||
method) doesn't need 'find'. All captures are required by default.
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-80vw">
|
||||
<SimpleCodeEditor
|
||||
bind:value={formValues.proxyConfig}
|
||||
height="medium"
|
||||
language="yaml"
|
||||
placeholder={proxyExample}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<FormError message={formError} />
|
||||
</div>
|
||||
|
||||
</Editor>
|
||||
<FormError message={formError} />
|
||||
<FormFooter {closeModal} {isSubmitting} />
|
||||
</FormGrid>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user