create target form

This commit is contained in:
Lena Emme 2024-08-12 22:16:01 +02:00
parent 27623035c8
commit 4ff69577cb
8 changed files with 148 additions and 48 deletions

View file

@ -13,6 +13,7 @@
"@types/js-cookie": "^3.0.6",
"axios": "^1.6.8",
"lucide-svelte": "^0.378.0",
"nanoid": "^5.0.7",
"sass": "^1.76.0"
},
"devDependencies": {
@ -1469,10 +1470,9 @@
"dev": true
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
"funding": [
{
"type": "github",
@ -1480,10 +1480,10 @@
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"node": "^18 || >=20"
}
},
"node_modules/normalize-path": {
@ -1579,6 +1579,24 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/prettier": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",

View file

@ -29,6 +29,7 @@
"@types/js-cookie": "^3.0.6",
"axios": "^1.6.8",
"lucide-svelte": "^0.378.0",
"nanoid": "^5.0.7",
"sass": "^1.76.0"
}
}
}

View file

@ -10,7 +10,7 @@
color: inherit;
border-radius: 8px;
border: 2px solid transparent;
padding: 8px 14px;
padding: 0.6rem 0.8rem;
background-color: var(--color-block-accent);
transition: border 0.2s;

View file

@ -1,7 +1,10 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import Button from "./Button.svelte";
import Input from "./Input.svelte";
import { ETargetStatus } from "./types";
import { ECaptchaProvider, ETargetStatus } from "./types";
import { nanoid } from "nanoid";
const dispatch = createEventDispatcher<{submit: typeof data}>();
const data = {
name: "",
@ -9,16 +12,16 @@
recipients: [""],
from: "",
status: ETargetStatus.ENABLED,
origin: "",
api_key: "",
allow_files: false,
allow_templates: false,
allow_custom_recipients: false,
subject_prefix: "",
ratelimit_timespan: 0,
ratelimit_requests: 0,
success_redirect: "",
error_redirect: "",
origin: undefined,
api_key: undefined,
allow_files: undefined,
allow_templates: undefined,
allow_custom_recipients: undefined,
subject_prefix: undefined,
ratelimit_timespan: undefined,
ratelimit_requests: undefined,
success_redirect: undefined,
error_redirect: undefined,
captcha_provider: undefined,
captcha_secret: undefined
}
@ -35,29 +38,42 @@
data.recipients = data.recipients;
}
}
function submit() {
// remove empty elements
data.recipients = data.recipients.filter(r => r);
dispatch("submit", data);
}
function generateKey() {
data.api_key = nanoid(32) as any;
}
</script>
<form>
<form on:submit|preventDefault={submit}>
<label>
Display name
<input placeholder="name" />
<input placeholder="name" required bind:value={data.name} />
</label>
<label>
SMTP Url
<input placeholder="smtp" />
<input placeholder="smtp" required bind:value={data.smtp} />
</label>
<label>
From (sender e-mail address)
<input placeholder="from email" />
<input placeholder="from email" required bind:value={data.from} />
</label>
<label>
Subject prefix
<input placeholder="prefix" />
<input placeholder="prefix" bind:value={data.subject_prefix} />
</label>
<hr />
<fieldset>
<legend>Recipients</legend>
@ -69,73 +85,102 @@
{/each}
</fieldset>
<hr />
<fieldset>
<legend>Permissions</legend>
<label class="inline">
Allow file attatchments
<input type="checkbox" />
<input type="checkbox" bind:checked={data.allow_files} />
</label>
<label class="inline">
Allow template usage
<input type="checkbox" />
<input type="checkbox" bind:checked={data.allow_templates} />
</label>
<label class="inline">
Allow custom recipients from target execution
<input type="checkbox" />
<input type="checkbox" bind:value={data.allow_custom_recipients} />
</label>
</fieldset>
<hr />
<fieldset>
<legend>Access restrictions</legend>
<label>
Origin
<input type="Origin URL" bind:value={data.origin} />
</label>
<label>
API Key
<input type="Custom api key" bind:value={data.api_key} />
</label>
<Button type="button" on:click={generateKey}>Generate API Key</Button>
</fieldset>
<hr />
<fieldset>
<legend>Rate Limits</legend>
<label>
Timespan
<input type="number" />
<input type="number" bind:value={data.ratelimit_timespan} />
</label>
<label>
Max number of request allowed in timespan
<input type="number" />
<input type="number" bind:value={data.ratelimit_requests} />
</label>
</fieldset>
<hr />
<fieldset>
<legend>Redirects</legend>
<label>
Success redirect
<input type="URL" />
<input type="URL" bind:value={data.success_redirect} />
</label>
<label>
Error redirect
<input type="URL" />
<input type="URL" bind:value={data.error_redirect} />
</label>
</fieldset>
<hr />
<fieldset>
<legend>Captcha</legend>
<label>
Provider
<select>
<option disabled selected>Select provider</option>
<option>Google ReCaptcha</option>
<option>hCaptcha</option>
<select bind:value={data.captcha_provider}>
<option disabled selected value={null}>Select provider</option>
<option value={ECaptchaProvider.RECAPTCHA}>Google ReCaptcha</option>
<option value={ECaptchaProvider.HCAPTCHA}>hCaptcha</option>
</select>
</label>
<label>
Secret
<input type="text" />
<input type="text" bind:value={data.captcha_secret} />
</label>
</fieldset>
<Button>Create</Button>
<br />
<Button type="submit">Create</Button>
</form>
<style lang="scss">
@ -148,10 +193,26 @@
flex-direction: column;
gap: 1rem;
hr {
margin: 0;
border: 0;
border-bottom: 2px solid var(--color-block-accent);
}
fieldset {
display: flex;
flex-direction: column;
gap: 1rem;
margin: 0;
border: 0;
padding: 0;
legend {
font-weight: bold;
font-size: 1.2rem;
margin-bottom: 0.4rem;
padding: 0;
}
}
}
</style>

View file

@ -12,9 +12,11 @@
<main>
{#if $authorizationKey}
<Sidebar />
<section>
<slot />
</section>
<div class="responsive-wrapper">
<section>
<slot />
</section>
</div>
{:else}
<section class="center">
<Login></Login>
@ -61,4 +63,14 @@
justify-content: center;
}
}
div.responsive-wrapper {
display: flex;
flex: 1;
justify-content: center;
section {
max-width: 840px;
}
}
</style>

View file

@ -1,15 +1,23 @@
<script lang="ts">
import PageTitle from "$lib/PageTitle.svelte";
import TargetForm from "$lib/TargetForm.svelte";
import axios from "axios";
import { pushToast } from "../../Toasts.svelte";
async function submit(data: CustomEvent) {
try {
axios.post("targets", data.detail);
} catch(e) {
pushToast("An error occured", "error");
}
}
</script>
<PageTitle>
Create a new mail target
Create new mail target
</PageTitle>
<TargetForm />
<TargetForm on:submit={submit} />
<style lang="scss">

View file

@ -1,8 +1,8 @@
:global(html) {
--color-bg: #1a1c1c;
--color-bg: #1b1c21;
--color-block: #262828;
--color-block-accent: #323535;
--color-block: #27282d;
--color-block-accent: #33343d;
--color-primary: #009489;
--color-primary-accent: #00867c;

View file

@ -17,7 +17,7 @@
color: inherit;
border-radius: 8px;
border: 2px solid transparent;
padding: 8px 14px;
padding: 0.4rem 0.8rem;
background-color: var(--color-block-accent);
transition: border 0.2s;