mirror of
https://github.com/speatzle/nfsense.git
synced 2025-05-12 19:28:20 +00:00
Compare commits
No commits in common. "cfb3d0a3b0d029a0ac16ac6395221bf91645230a" and "2c050ae61d9ff31280cc094318514c01c89f3c2c" have entirely different histories.
cfb3d0a3b0
...
2c050ae61d
13 changed files with 520 additions and 952 deletions
1247
Cargo.lock
generated
1247
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -22,9 +22,7 @@ tower-http = "0.4.4"
|
|||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.17"
|
||||
uuid = { version = "1.5.0", features = ["v4"] }
|
||||
validator = { version = "0.15", features = ["derive"] }
|
||||
tera = "1"
|
||||
lazy_static = "1.4.0"
|
||||
garde = { version = "0.20.0", features = ["full"] }
|
||||
once_cell = "1.19.0"
|
||||
regex = "1.10.5"
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script setup lang="ts">
|
||||
import { apiCall } from "../../api";
|
||||
import getPlugins from "../../plugins";
|
||||
import { apiCall } from '../../api';
|
||||
import getPlugins from '../../plugins';
|
||||
const p = getPlugins();
|
||||
|
||||
let peers = $ref({});
|
||||
|
@ -8,81 +8,65 @@ let loading = $ref(false);
|
|||
let selection = $ref([] as number[]);
|
||||
|
||||
const columns = [
|
||||
{ heading: "Name", path: "name" },
|
||||
{ heading: "Allowed IPs", path: "allowed_ips" },
|
||||
{ heading: "Endpoint", path: "endpoint" },
|
||||
{ heading: "Persistent Keepalive", path: "persistent_keepalive" },
|
||||
{ heading: "Comment", path: "comment" },
|
||||
{heading: 'Name', path: 'name'},
|
||||
{heading: 'Allowed IPs', path: 'allowed_ips'},
|
||||
{heading: 'Endpoint', path: 'endpoint'},
|
||||
{heading: 'Persistent Keepalive', path: 'persistent_keepalive'},
|
||||
{heading: 'Comment', path: 'comment'},
|
||||
];
|
||||
|
||||
const displayData = $computed(() => {
|
||||
let data: any;
|
||||
data = [];
|
||||
for (const index in peers) {
|
||||
data.push({
|
||||
name: peers[index].name,
|
||||
allowed_ips: peers[index].allowed_ips,
|
||||
endpoint: peers[index].endpoint,
|
||||
persistent_keepalive: peers[index].persistent_keepalive,
|
||||
comment: peers[index].comment,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
let data: any;
|
||||
data = [];
|
||||
for (const name in peers) {
|
||||
data.push({
|
||||
name,
|
||||
allowed_ips: peers[name].allowed_ips,
|
||||
endpoint: peers[name].endpoint,
|
||||
persistent_keepalive: peers[name].persistent_keepalive,
|
||||
comment: peers[name].comment,
|
||||
});
|
||||
}
|
||||
return data;
|
||||
});
|
||||
|
||||
async function load() {
|
||||
loading = true;
|
||||
let res = await apiCall("vpn.wireguard.peers.list", {});
|
||||
if (res.Error === null) {
|
||||
console.debug("peers", res.Data);
|
||||
peers = res.Data;
|
||||
} else {
|
||||
console.debug("error", res);
|
||||
}
|
||||
loading = false;
|
||||
async function load(){
|
||||
loading = true;
|
||||
let res = await apiCall('vpn.wireguard.peers.list', {});
|
||||
if (res.Error === null) {
|
||||
console.debug('peers', res.Data);
|
||||
peers = res.Data;
|
||||
} else {
|
||||
console.debug('error', res);
|
||||
}
|
||||
loading = false;
|
||||
}
|
||||
|
||||
async function deletePeer() {
|
||||
let res = await apiCall("vpn.wireguard.peers.delete", {
|
||||
name: displayData[selection[0]].name,
|
||||
});
|
||||
if (res.Error === null) {
|
||||
console.debug("deleted peer");
|
||||
} else {
|
||||
console.debug("error", res);
|
||||
}
|
||||
load();
|
||||
async function deletePeer(){
|
||||
let res = await apiCall('vpn.wireguard.peers.delete', {name: displayData[selection[0]].name});
|
||||
if (res.Error === null) {
|
||||
console.debug('deleted peer');
|
||||
} else {
|
||||
console.debug('error', res);
|
||||
}
|
||||
load();
|
||||
}
|
||||
|
||||
async function editPeer() {
|
||||
p.router.push(
|
||||
`/vpn/wireguard.peers/edit/${displayData[selection[0]].name}`,
|
||||
);
|
||||
p.router.push(`/vpn/wireguard.peers/edit/${ displayData[selection[0]].name}`);
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
load();
|
||||
onMounted(async() => {
|
||||
load();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TableView
|
||||
v-model:selection="selection"
|
||||
v-model:data="displayData"
|
||||
title="Peers"
|
||||
:columns="columns"
|
||||
:loading="loading"
|
||||
:table-props="{ sort: true, sortSelf: true }"
|
||||
>
|
||||
<button @click="load">Refresh</button>
|
||||
<router-link class="button" to="/vpn/wireguard.peers/edit"
|
||||
>Create</router-link
|
||||
>
|
||||
<button :disabled="selection.length != 1" @click="editPeer">
|
||||
Edit
|
||||
</button>
|
||||
<button :disabled="selection.length != 1" @click="deletePeer">
|
||||
Delete
|
||||
</button>
|
||||
</TableView>
|
||||
</template>
|
||||
<TableView v-model:selection="selection" v-model:data="displayData" title="Peers" :columns="columns" :loading="loading" :table-props="{sort:true, sortSelf: true}">
|
||||
<button @click="load">Refresh</button>
|
||||
<router-link class="button" to="/vpn/wireguard.peers/edit">Create</router-link>
|
||||
<button :disabled="selection.length != 1" @click="editPeer">Edit</button>
|
||||
<button :disabled="selection.length != 1" @click="deletePeer">Delete</button>
|
||||
</TableView>
|
||||
</template>
|
|
@ -1,11 +1,11 @@
|
|||
use super::definitions::config::Config;
|
||||
use garde::Validate;
|
||||
use pwhash::sha512_crypt;
|
||||
use serde::Serialize;
|
||||
use std::fs;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use thiserror::Error;
|
||||
use tracing::{error, info};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ConfigError {
|
||||
|
@ -13,7 +13,7 @@ pub enum ConfigError {
|
|||
SerdeError(#[from] serde_json::Error),
|
||||
|
||||
#[error("Validation Error")]
|
||||
ValidatonError(#[from] garde::Report),
|
||||
ValidatonError(#[from] validator::ValidationErrors),
|
||||
|
||||
#[error("Hash Error")]
|
||||
HashError(#[from] pwhash::error::Error),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use garde::Validate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
use super::firewall;
|
||||
use super::firewall::SNATType;
|
||||
|
@ -17,21 +17,13 @@ use super::vpn;
|
|||
use crate::macro_db;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Config {
|
||||
#[garde(skip)]
|
||||
pub config_version: u64,
|
||||
#[garde(dive)]
|
||||
pub network: network::Network,
|
||||
#[garde(dive)]
|
||||
pub object: object::Object,
|
||||
#[garde(dive)]
|
||||
pub system: system::System,
|
||||
#[garde(dive)]
|
||||
pub service: service::Service,
|
||||
#[garde(dive)]
|
||||
pub vpn: vpn::VPN,
|
||||
#[garde(dive)]
|
||||
pub firewall: firewall::Firewall,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,14 @@
|
|||
use super::config::Config;
|
||||
use garde::Validate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Firewall {
|
||||
#[garde(dive)]
|
||||
pub forward_rules: Vec<ForwardRule>,
|
||||
#[garde(dive)]
|
||||
pub destination_nat_rules: Vec<DestinationNATRule>,
|
||||
#[garde(dive)]
|
||||
pub source_nat_rules: Vec<SourceNATRule>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct ForwardRule {
|
||||
pub name: String,
|
||||
pub services: Vec<String>,
|
||||
|
@ -27,8 +20,6 @@ pub struct ForwardRule {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct DestinationNATRule {
|
||||
pub name: String,
|
||||
pub services: Vec<String>,
|
||||
|
@ -41,8 +32,6 @@ pub struct DestinationNATRule {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct SourceNATRule {
|
||||
pub name: String,
|
||||
pub services: Vec<String>,
|
||||
|
|
|
@ -1,23 +1,15 @@
|
|||
use super::config::Config;
|
||||
use crate::validation;
|
||||
use garde::Validate;
|
||||
use ipnet::IpNet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Network {
|
||||
#[garde(dive)]
|
||||
pub interfaces: Vec<NetworkInterface>,
|
||||
#[garde(dive)]
|
||||
pub static_routes: Vec<StaticRoute>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct NetworkInterface {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub alias: String,
|
||||
pub comment: String,
|
||||
|
@ -47,10 +39,7 @@ pub enum AddressingMode {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct StaticRoute {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub interface: String,
|
||||
pub gateway: String,
|
||||
|
@ -60,8 +49,6 @@ pub struct StaticRoute {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct Link {
|
||||
pub name: String,
|
||||
}
|
||||
|
|
|
@ -1,24 +1,16 @@
|
|||
use super::config::Config;
|
||||
use crate::validation;
|
||||
use garde::Validate;
|
||||
use ipnet::IpNet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::net::IpAddr;
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Object {
|
||||
#[garde(dive)]
|
||||
pub addresses: Vec<Address>,
|
||||
#[garde(dive)]
|
||||
pub services: Vec<Service>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct Address {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub address_type: AddressType,
|
||||
pub comment: String,
|
||||
|
@ -34,10 +26,7 @@ pub enum AddressType {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct Service {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub service_type: ServiceType,
|
||||
pub comment: String,
|
||||
|
|
|
@ -1,22 +1,15 @@
|
|||
use super::config::Config;
|
||||
use garde::Validate;
|
||||
use macaddr::MacAddr8;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Service {
|
||||
#[garde(dive)]
|
||||
pub dhcp_servers: Vec<DHCPServer>,
|
||||
#[garde(dive)]
|
||||
pub dns_servers: Vec<DNSServer>,
|
||||
#[garde(dive)]
|
||||
pub ntp_servers: Vec<NTPServer>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct DHCPServer {
|
||||
pub name: String,
|
||||
pub interface: String,
|
||||
|
@ -30,8 +23,6 @@ pub struct DHCPServer {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct DNSServer {
|
||||
pub name: String,
|
||||
pub interface: String,
|
||||
|
@ -39,8 +30,6 @@ pub struct DNSServer {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct NTPServer {
|
||||
pub name: String,
|
||||
pub interface: String,
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
use super::config::Config;
|
||||
use crate::validation;
|
||||
use garde::Validate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct System {
|
||||
#[garde(dive)]
|
||||
pub users: Vec<User>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct User {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub comment: String,
|
||||
pub hash: String,
|
||||
|
|
|
@ -1,29 +1,19 @@
|
|||
use super::config::Config;
|
||||
use crate::validation;
|
||||
use garde::Validate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use validator::Validate;
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct VPN {
|
||||
#[garde(dive)]
|
||||
pub wireguard: Wireguard,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Default, Debug)]
|
||||
#[garde(context(Config))]
|
||||
pub struct Wireguard {
|
||||
#[garde(dive)]
|
||||
pub interfaces: Vec<WireguardInterface>,
|
||||
#[garde(dive)]
|
||||
pub peers: Vec<WireguardPeer>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct WireguardInterface {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub public_key: String,
|
||||
pub private_key: String,
|
||||
|
@ -33,10 +23,7 @@ pub struct WireguardInterface {
|
|||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Validate, Debug)]
|
||||
#[garde(context(Config))]
|
||||
#[garde(allow_unvalidated)]
|
||||
pub struct WireguardPeer {
|
||||
#[garde(custom(validation::validate_name))]
|
||||
pub name: String,
|
||||
pub public_key: String,
|
||||
pub preshared_key: Option<String>,
|
||||
|
|
|
@ -25,7 +25,6 @@ mod config_manager;
|
|||
mod definitions;
|
||||
mod state;
|
||||
mod templates;
|
||||
mod validation;
|
||||
mod web;
|
||||
|
||||
#[tokio::main]
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
use {
|
||||
crate::definitions::config::Config, garde::rules::pattern::Matcher, once_cell::sync::Lazy,
|
||||
regex::Regex,
|
||||
};
|
||||
|
||||
pub fn validate_name(value: &str, _: &Config) -> garde::Result {
|
||||
if value.len() > 32 {
|
||||
return Err(garde::Error::new("name is longer than 32"));
|
||||
}
|
||||
|
||||
static RE: Lazy<Regex> = Lazy::new(|| Regex::new(r"/^[0-9A-Za-z_-]*$/g").unwrap());
|
||||
if !RE.is_match(value) {
|
||||
return Err(garde::Error::new("name must only contain 0-9A-Za-z_-"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
Loading…
Add table
Reference in a new issue