mirror of
https://github.com/Feuerhamster/mailform.git
synced 2025-06-02 10:42:08 +02:00
create target form
This commit is contained in:
parent
27623035c8
commit
4ff69577cb
8 changed files with 148 additions and 48 deletions
30
client/package-lock.json
generated
30
client/package-lock.json
generated
|
@ -13,6 +13,7 @@
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"lucide-svelte": "^0.378.0",
|
"lucide-svelte": "^0.378.0",
|
||||||
|
"nanoid": "^5.0.7",
|
||||||
"sass": "^1.76.0"
|
"sass": "^1.76.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -1469,10 +1470,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.7",
|
"version": "5.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
|
||||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
|
"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
|
@ -1480,10 +1480,10 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"nanoid": "bin/nanoid.cjs"
|
"nanoid": "bin/nanoid.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^18 || >=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/normalize-path": {
|
"node_modules/normalize-path": {
|
||||||
|
@ -1579,6 +1579,24 @@
|
||||||
"node": "^10 || ^12 || >=14"
|
"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": {
|
"node_modules/prettier": {
|
||||||
"version": "3.2.5",
|
"version": "3.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz",
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"axios": "^1.6.8",
|
"axios": "^1.6.8",
|
||||||
"lucide-svelte": "^0.378.0",
|
"lucide-svelte": "^0.378.0",
|
||||||
|
"nanoid": "^5.0.7",
|
||||||
"sass": "^1.76.0"
|
"sass": "^1.76.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
padding: 8px 14px;
|
padding: 0.6rem 0.8rem;
|
||||||
background-color: var(--color-block-accent);
|
background-color: var(--color-block-accent);
|
||||||
|
|
||||||
transition: border 0.2s;
|
transition: border 0.2s;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
import Button from "./Button.svelte";
|
import Button from "./Button.svelte";
|
||||||
import Input from "./Input.svelte";
|
import { ECaptchaProvider, ETargetStatus } from "./types";
|
||||||
import { ETargetStatus } from "./types";
|
import { nanoid } from "nanoid";
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher<{submit: typeof data}>();
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
name: "",
|
name: "",
|
||||||
|
@ -9,16 +12,16 @@
|
||||||
recipients: [""],
|
recipients: [""],
|
||||||
from: "",
|
from: "",
|
||||||
status: ETargetStatus.ENABLED,
|
status: ETargetStatus.ENABLED,
|
||||||
origin: "",
|
origin: undefined,
|
||||||
api_key: "",
|
api_key: undefined,
|
||||||
allow_files: false,
|
allow_files: undefined,
|
||||||
allow_templates: false,
|
allow_templates: undefined,
|
||||||
allow_custom_recipients: false,
|
allow_custom_recipients: undefined,
|
||||||
subject_prefix: "",
|
subject_prefix: undefined,
|
||||||
ratelimit_timespan: 0,
|
ratelimit_timespan: undefined,
|
||||||
ratelimit_requests: 0,
|
ratelimit_requests: undefined,
|
||||||
success_redirect: "",
|
success_redirect: undefined,
|
||||||
error_redirect: "",
|
error_redirect: undefined,
|
||||||
captcha_provider: undefined,
|
captcha_provider: undefined,
|
||||||
captcha_secret: undefined
|
captcha_secret: undefined
|
||||||
}
|
}
|
||||||
|
@ -35,29 +38,42 @@
|
||||||
data.recipients = data.recipients;
|
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>
|
</script>
|
||||||
|
|
||||||
<form>
|
<form on:submit|preventDefault={submit}>
|
||||||
<label>
|
<label>
|
||||||
Display name
|
Display name
|
||||||
<input placeholder="name" />
|
<input placeholder="name" required bind:value={data.name} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
SMTP Url
|
SMTP Url
|
||||||
<input placeholder="smtp" />
|
<input placeholder="smtp" required bind:value={data.smtp} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
From (sender e-mail address)
|
From (sender e-mail address)
|
||||||
<input placeholder="from email" />
|
<input placeholder="from email" required bind:value={data.from} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Subject prefix
|
Subject prefix
|
||||||
<input placeholder="prefix" />
|
<input placeholder="prefix" bind:value={data.subject_prefix} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Recipients</legend>
|
<legend>Recipients</legend>
|
||||||
|
|
||||||
|
@ -69,73 +85,102 @@
|
||||||
{/each}
|
{/each}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Permissions</legend>
|
<legend>Permissions</legend>
|
||||||
|
|
||||||
<label class="inline">
|
<label class="inline">
|
||||||
Allow file attatchments
|
Allow file attatchments
|
||||||
<input type="checkbox" />
|
<input type="checkbox" bind:checked={data.allow_files} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="inline">
|
<label class="inline">
|
||||||
Allow template usage
|
Allow template usage
|
||||||
<input type="checkbox" />
|
<input type="checkbox" bind:checked={data.allow_templates} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="inline">
|
<label class="inline">
|
||||||
Allow custom recipients from target execution
|
Allow custom recipients from target execution
|
||||||
<input type="checkbox" />
|
<input type="checkbox" bind:value={data.allow_custom_recipients} />
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</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>
|
<fieldset>
|
||||||
<legend>Rate Limits</legend>
|
<legend>Rate Limits</legend>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Timespan
|
Timespan
|
||||||
<input type="number" />
|
<input type="number" bind:value={data.ratelimit_timespan} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Max number of request allowed in timespan
|
Max number of request allowed in timespan
|
||||||
<input type="number" />
|
<input type="number" bind:value={data.ratelimit_requests} />
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Redirects</legend>
|
<legend>Redirects</legend>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Success redirect
|
Success redirect
|
||||||
<input type="URL" />
|
<input type="URL" bind:value={data.success_redirect} />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Error redirect
|
Error redirect
|
||||||
<input type="URL" />
|
<input type="URL" bind:value={data.error_redirect} />
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Captcha</legend>
|
<legend>Captcha</legend>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Provider
|
Provider
|
||||||
<select>
|
<select bind:value={data.captcha_provider}>
|
||||||
<option disabled selected>Select provider</option>
|
<option disabled selected value={null}>Select provider</option>
|
||||||
<option>Google ReCaptcha</option>
|
<option value={ECaptchaProvider.RECAPTCHA}>Google ReCaptcha</option>
|
||||||
<option>hCaptcha</option>
|
<option value={ECaptchaProvider.HCAPTCHA}>hCaptcha</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
Secret
|
Secret
|
||||||
<input type="text" />
|
<input type="text" bind:value={data.captcha_secret} />
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<Button>Create</Button>
|
<br />
|
||||||
|
|
||||||
|
<Button type="submit">Create</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -148,10 +193,26 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
|
hr {
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 2px solid var(--color-block-accent);
|
||||||
|
}
|
||||||
|
|
||||||
fieldset {
|
fieldset {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
legend {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
margin-bottom: 0.4rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -12,9 +12,11 @@
|
||||||
<main>
|
<main>
|
||||||
{#if $authorizationKey}
|
{#if $authorizationKey}
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
<section>
|
<div class="responsive-wrapper">
|
||||||
<slot />
|
<section>
|
||||||
</section>
|
<slot />
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<section class="center">
|
<section class="center">
|
||||||
<Login></Login>
|
<Login></Login>
|
||||||
|
@ -61,4 +63,14 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.responsive-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
section {
|
||||||
|
max-width: 840px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,15 +1,23 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import PageTitle from "$lib/PageTitle.svelte";
|
import PageTitle from "$lib/PageTitle.svelte";
|
||||||
import TargetForm from "$lib/TargetForm.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>
|
</script>
|
||||||
|
|
||||||
<PageTitle>
|
<PageTitle>
|
||||||
Create a new mail target
|
Create new mail target
|
||||||
</PageTitle>
|
</PageTitle>
|
||||||
|
|
||||||
<TargetForm />
|
<TargetForm on:submit={submit} />
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
:global(html) {
|
:global(html) {
|
||||||
--color-bg: #1a1c1c;
|
--color-bg: #1b1c21;
|
||||||
|
|
||||||
--color-block: #262828;
|
--color-block: #27282d;
|
||||||
--color-block-accent: #323535;
|
--color-block-accent: #33343d;
|
||||||
|
|
||||||
--color-primary: #009489;
|
--color-primary: #009489;
|
||||||
--color-primary-accent: #00867c;
|
--color-primary-accent: #00867c;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
padding: 8px 14px;
|
padding: 0.4rem 0.8rem;
|
||||||
background-color: var(--color-block-accent);
|
background-color: var(--color-block-accent);
|
||||||
|
|
||||||
transition: border 0.2s;
|
transition: border 0.2s;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue