mirror of
https://github.com/MizuchiLabs/mantrae.git
synced 2025-12-21 06:10:04 -06:00
small frontend fix
This commit is contained in:
@@ -25,10 +25,10 @@ var backupCron *cron.Cron
|
|||||||
// BackupData is the structure for the full manual backup
|
// BackupData is the structure for the full manual backup
|
||||||
type BackupData struct {
|
type BackupData struct {
|
||||||
Profiles []db.Profile `json:"profiles"`
|
Profiles []db.Profile `json:"profiles"`
|
||||||
Configs []*traefik.Dynamic `json:"configs"`
|
|
||||||
Providers []db.Provider `json:"providers"`
|
Providers []db.Provider `json:"providers"`
|
||||||
Settings []db.Setting `json:"settings"`
|
Settings []db.Setting `json:"settings"`
|
||||||
Users []db.User `json:"users"`
|
Users []db.User `json:"users"`
|
||||||
|
Configs []*traefik.Dynamic `json:"configs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func DumpBackup(ctx context.Context) (*BackupData, error) {
|
func DumpBackup(ctx context.Context) (*BackupData, error) {
|
||||||
@@ -44,12 +44,37 @@ func DumpBackup(ctx context.Context) (*BackupData, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to get configs: %w", err)
|
return nil, fmt.Errorf("failed to get configs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We're only interested in the our local provider
|
||||||
for _, config := range configs {
|
for _, config := range configs {
|
||||||
dynamic, err := traefik.DecodeConfig(config)
|
dynamic, err := traefik.DecodeConfig(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode config: %w", err)
|
return nil, fmt.Errorf("failed to decode config: %w", err)
|
||||||
}
|
}
|
||||||
data.Configs = append(data.Configs, dynamic)
|
|
||||||
|
newDynamic := &traefik.Dynamic{
|
||||||
|
ProfileID: config.ProfileID,
|
||||||
|
Routers: make(map[string]traefik.Router),
|
||||||
|
Services: make(map[string]traefik.Service),
|
||||||
|
Middlewares: make(map[string]traefik.Middleware),
|
||||||
|
}
|
||||||
|
for i, router := range dynamic.Routers {
|
||||||
|
if router.Provider == "http" {
|
||||||
|
newDynamic.Routers[i] = router
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, service := range dynamic.Services {
|
||||||
|
if service.Provider == "http" {
|
||||||
|
newDynamic.Services[i] = service
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i, middleware := range dynamic.Middlewares {
|
||||||
|
if middleware.Provider == "http" {
|
||||||
|
newDynamic.Middlewares[i] = middleware
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data.Configs = append(data.Configs, newDynamic)
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Providers, err = db.Query.ListProviders(ctx)
|
data.Providers, err = db.Query.ListProviders(ctx)
|
||||||
|
|||||||
@@ -450,7 +450,7 @@ func GetTraefikConfig() {
|
|||||||
|
|
||||||
// Sync periodically syncs the Traefik configuration
|
// Sync periodically syncs the Traefik configuration
|
||||||
func Sync(ctx context.Context) {
|
func Sync(ctx context.Context) {
|
||||||
ticker := time.NewTicker(time.Second * 60)
|
ticker := time.NewTicker(time.Second * 10)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
GetTraefikConfig()
|
GetTraefikConfig()
|
||||||
|
|||||||
@@ -127,7 +127,6 @@
|
|||||||
const validate = () => {
|
const validate = () => {
|
||||||
try {
|
try {
|
||||||
middleware.headers = headersSchema.parse(middleware.headers);
|
middleware.headers = headersSchema.parse(middleware.headers);
|
||||||
console.log(middleware.headers.stsSeconds);
|
|
||||||
errors = {};
|
errors = {};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof z.ZodError) {
|
if (err instanceof z.ZodError) {
|
||||||
|
|||||||
@@ -83,7 +83,6 @@
|
|||||||
$: isNameTaken = $middlewares.some((m) => m.name === middleware.name + '@' + middleware.provider);
|
$: isNameTaken = $middlewares.some((m) => m.name === middleware.name + '@' + middleware.provider);
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
console.log(middleware);
|
|
||||||
checkType();
|
checkType();
|
||||||
form = await LoadMiddlewareForm(middleware);
|
form = await LoadMiddlewareForm(middleware);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
toggleMiddleware,
|
toggleMiddleware,
|
||||||
toggleDNSProvider
|
toggleDNSProvider
|
||||||
} from '$lib/api';
|
} from '$lib/api';
|
||||||
import { newRouter, type Router } from '$lib/types/config';
|
import { type Router } from '$lib/types/config';
|
||||||
import RuleEditor from '../utils/ruleEditor.svelte';
|
import RuleEditor from '../utils/ruleEditor.svelte';
|
||||||
import ArrayInput from '../ui/array-input/array-input.svelte';
|
import ArrayInput from '../ui/array-input/array-input.svelte';
|
||||||
import logo from '$lib/images/logo.svg';
|
import logo from '$lib/images/logo.svg';
|
||||||
@@ -25,10 +25,11 @@
|
|||||||
export let router: Router;
|
export let router: Router;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z
|
||||||
name: z.string({ required_error: 'Name is required' }).min(1).max(255),
|
.object({
|
||||||
provider: z.string().optional(),
|
name: z.string().trim().min(1, 'Name is required').max(255),
|
||||||
status: z.string().optional(),
|
provider: z.string().trim().optional(),
|
||||||
|
status: z.string().trim().optional(),
|
||||||
routerType: z
|
routerType: z
|
||||||
.string()
|
.string()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
@@ -36,12 +37,27 @@
|
|||||||
dnsProvider: z.coerce.number().int().nonnegative().optional(),
|
dnsProvider: z.coerce.number().int().nonnegative().optional(),
|
||||||
entrypoints: z.array(z.string()).optional(),
|
entrypoints: z.array(z.string()).optional(),
|
||||||
middlewares: z.array(z.string()).optional(),
|
middlewares: z.array(z.string()).optional(),
|
||||||
rule: z.string({ required_error: 'Rule is required' }).min(1, { message: 'Rule is required' }),
|
rule: z.string().trim().optional(),
|
||||||
priority: z.coerce.number().int().nonnegative().optional(),
|
priority: z.coerce.number().int().nonnegative().optional(),
|
||||||
tls: z.object({
|
tls: z
|
||||||
|
.object({
|
||||||
certResolver: z.string().trim().optional()
|
certResolver: z.string().trim().optional()
|
||||||
})
|
})
|
||||||
});
|
.optional()
|
||||||
|
})
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
// Conditionally check if `rule` is required for `http` or `tcp`
|
||||||
|
if (['http', 'tcp'].includes(data.routerType) && !data.rule) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
message: 'Rule is required for HTTP and TCP routers',
|
||||||
|
path: ['rule'] // This points to the 'rule' field
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
let errors: Record<any, string[] | undefined> = {};
|
let errors: Record<any, string[] | undefined> = {};
|
||||||
export const validate = () => {
|
export const validate = () => {
|
||||||
@@ -298,6 +314,9 @@
|
|||||||
|
|
||||||
<!-- Rule -->
|
<!-- Rule -->
|
||||||
{#if router.routerType === 'http' || router.routerType === 'tcp'}
|
{#if router.routerType === 'http' || router.routerType === 'tcp'}
|
||||||
|
{#if errors.rule}
|
||||||
|
<div class="col-span-4 text-right text-sm text-red-500">{errors.rule}</div>
|
||||||
|
{/if}
|
||||||
<RuleEditor bind:rule={router.rule} bind:type={router.routerType} {disabled} />
|
<RuleEditor bind:rule={router.rule} bind:type={router.routerType} {disabled} />
|
||||||
{/if}
|
{/if}
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
|
|||||||
@@ -24,7 +24,19 @@
|
|||||||
.regex(/^(http|tcp|udp)$/),
|
.regex(/^(http|tcp|udp)$/),
|
||||||
serverStatus: z.record(z.string()).optional(),
|
serverStatus: z.record(z.string()).optional(),
|
||||||
loadBalancer: z.object({
|
loadBalancer: z.object({
|
||||||
servers: z.array(z.object({ url: z.string() }).or(z.object({ address: z.string() }))),
|
servers: z
|
||||||
|
.array(
|
||||||
|
z
|
||||||
|
.object({
|
||||||
|
url: z.string().trim().optional(),
|
||||||
|
address: z.string().trim().optional()
|
||||||
|
})
|
||||||
|
.refine((data) => data.url || data.address, {
|
||||||
|
message: 'At least one server is required',
|
||||||
|
path: ['servers'] // Points to the 'servers' array in case of error
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.nonempty('At least one server is required'),
|
||||||
passHostHeader: z.boolean().optional()
|
passHostHeader: z.boolean().optional()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@@ -33,7 +45,6 @@
|
|||||||
export const validate = () => {
|
export const validate = () => {
|
||||||
try {
|
try {
|
||||||
serviceSchema.parse({ ...service });
|
serviceSchema.parse({ ...service });
|
||||||
|
|
||||||
errors = {};
|
errors = {};
|
||||||
return true;
|
return true;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -45,7 +56,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const update = () => {
|
const update = () => {
|
||||||
validate();
|
|
||||||
if (service.loadBalancer === undefined) service.loadBalancer = { servers: [] };
|
if (service.loadBalancer === undefined) service.loadBalancer = { servers: [] };
|
||||||
|
|
||||||
service.loadBalancer.passHostHeader = passHostHeader;
|
service.loadBalancer.passHostHeader = passHostHeader;
|
||||||
|
|||||||
Reference in New Issue
Block a user