mirror of
https://github.com/fosrl/pangolin.git
synced 2026-02-18 02:46:37 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f9f3fdede | ||
|
|
a778109214 | ||
|
|
cb7fa9375b | ||
|
|
515ecb09e7 | ||
|
|
a12a620697 | ||
|
|
0c3b2bc2f5 | ||
|
|
78ba27dc63 | ||
|
|
dc20b863ed | ||
|
|
c9a211d5cf | ||
|
|
95f94cffd2 | ||
|
|
0da95cbdb8 | ||
|
|
dadd1e3101 | ||
|
|
d523ae3ffa | ||
|
|
9a41cac6e1 | ||
|
|
5d3c5ab7cc | ||
|
|
e94ded920b | ||
|
|
c882fbd59a | ||
|
|
46b50a042e | ||
|
|
fda9e95786 | ||
|
|
ea1ad23bff | ||
|
|
7ffc5e0212 | ||
|
|
acba9444f4 | ||
|
|
f7e3671801 | ||
|
|
a1b2e36a5d | ||
|
|
44e96942b3 | ||
|
|
f2efa760ff | ||
|
|
256df9042b | ||
|
|
6d7091fb5c | ||
|
|
0d1f88a368 | ||
|
|
2ae601717d | ||
|
|
c7c8b463b4 | ||
|
|
282f839211 | ||
|
|
b2eb846b69 |
@@ -8,10 +8,10 @@ import base64
|
|||||||
YAML_FILE_PATH = 'blueprint.yaml'
|
YAML_FILE_PATH = 'blueprint.yaml'
|
||||||
|
|
||||||
# The API endpoint and headers from the curl request
|
# The API endpoint and headers from the curl request
|
||||||
API_URL = 'http://localhost:3004/v1/org/test/blueprint'
|
API_URL = 'http://api.pangolin.fossorial.io/v1/org/test/blueprint'
|
||||||
HEADERS = {
|
HEADERS = {
|
||||||
'accept': '*/*',
|
'accept': '*/*',
|
||||||
'Authorization': 'Bearer v7ix7xha1bmq2on.tzsden374mtmkeczm3tx44uzxsljnrst7nmg7ccr',
|
'Authorization': 'Bearer <your_token_here>',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !config.HybridMode && checkIsPangolinInstalledWithHybrid() {
|
if !config.HybridMode {
|
||||||
// Setup Token Section
|
// Setup Token Section
|
||||||
fmt.Println("\n=== Setup Token ===")
|
fmt.Println("\n=== Setup Token ===")
|
||||||
|
|
||||||
|
|||||||
@@ -454,7 +454,7 @@
|
|||||||
"accessRoleErrorAddDescription": "Beim Hinzufügen des Benutzers zur Rolle ist ein Fehler aufgetreten.",
|
"accessRoleErrorAddDescription": "Beim Hinzufügen des Benutzers zur Rolle ist ein Fehler aufgetreten.",
|
||||||
"userSaved": "Benutzer gespeichert",
|
"userSaved": "Benutzer gespeichert",
|
||||||
"userSavedDescription": "Der Benutzer wurde aktualisiert.",
|
"userSavedDescription": "Der Benutzer wurde aktualisiert.",
|
||||||
"autoProvisioned": "Automatisch vorgesehen",
|
"autoProvisioned": "Automatisch bereitgestellt",
|
||||||
"autoProvisionedDescription": "Erlaube diesem Benutzer die automatische Verwaltung durch Identitätsanbieter",
|
"autoProvisionedDescription": "Erlaube diesem Benutzer die automatische Verwaltung durch Identitätsanbieter",
|
||||||
"accessControlsDescription": "Verwalten Sie, worauf dieser Benutzer in der Organisation zugreifen und was er tun kann",
|
"accessControlsDescription": "Verwalten Sie, worauf dieser Benutzer in der Organisation zugreifen und was er tun kann",
|
||||||
"accessControlsSubmit": "Zugriffskontrollen speichern",
|
"accessControlsSubmit": "Zugriffskontrollen speichern",
|
||||||
@@ -513,7 +513,7 @@
|
|||||||
"ipAddressErrorInvalidFormat": "Ungültiges IP-Adressformat",
|
"ipAddressErrorInvalidFormat": "Ungültiges IP-Adressformat",
|
||||||
"ipAddressErrorInvalidOctet": "Ungültiges IP-Adress-Oktett",
|
"ipAddressErrorInvalidOctet": "Ungültiges IP-Adress-Oktett",
|
||||||
"path": "Pfad",
|
"path": "Pfad",
|
||||||
"matchPath": "Spielpfad",
|
"matchPath": "Unterverzeichnis",
|
||||||
"ipAddressRange": "IP-Bereich",
|
"ipAddressRange": "IP-Bereich",
|
||||||
"rulesErrorFetch": "Fehler beim Abrufen der Regeln",
|
"rulesErrorFetch": "Fehler beim Abrufen der Regeln",
|
||||||
"rulesErrorFetchDescription": "Beim Abrufen der Regeln ist ein Fehler aufgetreten",
|
"rulesErrorFetchDescription": "Beim Abrufen der Regeln ist ein Fehler aufgetreten",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
"setupErrorIdentifier": "L'ID de l'organisation est déjà pris. Veuillez en choisir un autre.",
|
"setupErrorIdentifier": "L'ID de l'organisation est déjà pris. Veuillez en choisir un autre.",
|
||||||
"componentsErrorNoMemberCreate": "Vous n'êtes actuellement membre d'aucune organisation. Créez une organisation pour commencer.",
|
"componentsErrorNoMemberCreate": "Vous n'êtes actuellement membre d'aucune organisation. Créez une organisation pour commencer.",
|
||||||
"componentsErrorNoMember": "Vous n'êtes actuellement membre d'aucune organisation.",
|
"componentsErrorNoMember": "Vous n'êtes actuellement membre d'aucune organisation.",
|
||||||
"welcome": "Bienvenue à Pangolin",
|
"welcome": "Bienvenue sur Pangolin",
|
||||||
"welcomeTo": "Bienvenue chez",
|
"welcomeTo": "Bienvenue chez",
|
||||||
"componentsCreateOrg": "Créer une organisation",
|
"componentsCreateOrg": "Créer une organisation",
|
||||||
"componentsMember": "Vous êtes membre de {count, plural, =0 {aucune organisation} one {une organisation} other {# organisations}}.",
|
"componentsMember": "Vous êtes membre de {count, plural, =0 {aucune organisation} one {une organisation} other {# organisations}}.",
|
||||||
@@ -34,13 +34,13 @@
|
|||||||
"confirmPassword": "Confirmer le mot de passe",
|
"confirmPassword": "Confirmer le mot de passe",
|
||||||
"createAccount": "Créer un compte",
|
"createAccount": "Créer un compte",
|
||||||
"viewSettings": "Afficher les paramètres",
|
"viewSettings": "Afficher les paramètres",
|
||||||
"delete": "Supprimez",
|
"delete": "Supprimer",
|
||||||
"name": "Nom",
|
"name": "Nom",
|
||||||
"online": "En ligne",
|
"online": "En ligne",
|
||||||
"offline": "Hors ligne",
|
"offline": "Hors ligne",
|
||||||
"site": "Site",
|
"site": "Site",
|
||||||
"dataIn": "Données dans",
|
"dataIn": "Données reçues",
|
||||||
"dataOut": "Données épuisées",
|
"dataOut": "Données envoyées",
|
||||||
"connectionType": "Type de connexion",
|
"connectionType": "Type de connexion",
|
||||||
"tunnelType": "Type de tunnel",
|
"tunnelType": "Type de tunnel",
|
||||||
"local": "Locale",
|
"local": "Locale",
|
||||||
@@ -175,7 +175,7 @@
|
|||||||
"resourceHTTPSSettingsDescription": "Configurer comment votre ressource sera accédée via HTTPS",
|
"resourceHTTPSSettingsDescription": "Configurer comment votre ressource sera accédée via HTTPS",
|
||||||
"domainType": "Type de domaine",
|
"domainType": "Type de domaine",
|
||||||
"subdomain": "Sous-domaine",
|
"subdomain": "Sous-domaine",
|
||||||
"baseDomain": "Domaine de base",
|
"baseDomain": "Domaine racine",
|
||||||
"subdomnainDescription": "Le sous-domaine où votre ressource sera accessible.",
|
"subdomnainDescription": "Le sous-domaine où votre ressource sera accessible.",
|
||||||
"resourceRawSettings": "Paramètres TCP/UDP",
|
"resourceRawSettings": "Paramètres TCP/UDP",
|
||||||
"resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP",
|
"resourceRawSettingsDescription": "Configurer comment votre ressource sera accédée via TCP/UDP",
|
||||||
@@ -309,7 +309,7 @@
|
|||||||
"numberOfSites": "Nombre de sites",
|
"numberOfSites": "Nombre de sites",
|
||||||
"licenseKeySearch": "Rechercher des clés de licence...",
|
"licenseKeySearch": "Rechercher des clés de licence...",
|
||||||
"licenseKeyAdd": "Ajouter une clé de licence",
|
"licenseKeyAdd": "Ajouter une clé de licence",
|
||||||
"type": "Type de texte",
|
"type": "Type",
|
||||||
"licenseKeyRequired": "La clé de licence est requise",
|
"licenseKeyRequired": "La clé de licence est requise",
|
||||||
"licenseTermsAgree": "Vous devez accepter les conditions de licence",
|
"licenseTermsAgree": "Vous devez accepter les conditions de licence",
|
||||||
"licenseErrorKeyLoad": "Impossible de charger les clés de licence",
|
"licenseErrorKeyLoad": "Impossible de charger les clés de licence",
|
||||||
@@ -598,7 +598,7 @@
|
|||||||
"newtId": "ID Newt",
|
"newtId": "ID Newt",
|
||||||
"newtSecretKey": "Clé secrète Newt",
|
"newtSecretKey": "Clé secrète Newt",
|
||||||
"architecture": "Architecture",
|
"architecture": "Architecture",
|
||||||
"sites": "Espaces",
|
"sites": "Sites",
|
||||||
"siteWgAnyClients": "Utilisez n'importe quel client WireGuard pour vous connecter. Vous devrez adresser vos ressources internes en utilisant l'IP du pair.",
|
"siteWgAnyClients": "Utilisez n'importe quel client WireGuard pour vous connecter. Vous devrez adresser vos ressources internes en utilisant l'IP du pair.",
|
||||||
"siteWgCompatibleAllClients": "Compatible avec tous les clients WireGuard",
|
"siteWgCompatibleAllClients": "Compatible avec tous les clients WireGuard",
|
||||||
"siteWgManualConfigurationRequired": "Configuration manuelle requise",
|
"siteWgManualConfigurationRequired": "Configuration manuelle requise",
|
||||||
@@ -1128,7 +1128,7 @@
|
|||||||
"sidebarOverview": "Aperçu",
|
"sidebarOverview": "Aperçu",
|
||||||
"sidebarHome": "Domicile",
|
"sidebarHome": "Domicile",
|
||||||
"sidebarSites": "Espaces",
|
"sidebarSites": "Espaces",
|
||||||
"sidebarResources": "Ressource",
|
"sidebarResources": "Ressources",
|
||||||
"sidebarAccessControl": "Contrôle d'accès",
|
"sidebarAccessControl": "Contrôle d'accès",
|
||||||
"sidebarUsers": "Utilisateurs",
|
"sidebarUsers": "Utilisateurs",
|
||||||
"sidebarInvitations": "Invitations",
|
"sidebarInvitations": "Invitations",
|
||||||
|
|||||||
@@ -38,12 +38,12 @@
|
|||||||
"name": "naam",
|
"name": "naam",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
"site": "Website",
|
"site": "Referentie",
|
||||||
"dataIn": "Gegevens in",
|
"dataIn": "Dataverbruik inkomend",
|
||||||
"dataOut": "Data Uit",
|
"dataOut": "Dataverbruik uitgaand",
|
||||||
"connectionType": "Type verbinding",
|
"connectionType": "Type verbinding",
|
||||||
"tunnelType": "Tunnel type",
|
"tunnelType": "Tunnel type",
|
||||||
"local": "lokaal",
|
"local": "Lokaal",
|
||||||
"edit": "Bewerken",
|
"edit": "Bewerken",
|
||||||
"siteConfirmDelete": "Verwijderen van site bevestigen",
|
"siteConfirmDelete": "Verwijderen van site bevestigen",
|
||||||
"siteDelete": "Site verwijderen",
|
"siteDelete": "Site verwijderen",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
"siteCreate": "Site maken",
|
"siteCreate": "Site maken",
|
||||||
"siteCreateDescription2": "Volg de onderstaande stappen om een nieuwe site aan te maken en te verbinden",
|
"siteCreateDescription2": "Volg de onderstaande stappen om een nieuwe site aan te maken en te verbinden",
|
||||||
"siteCreateDescription": "Maak een nieuwe site aan om verbinding te maken met uw bronnen",
|
"siteCreateDescription": "Maak een nieuwe site aan om verbinding te maken met uw bronnen",
|
||||||
"close": "Afsluiten",
|
"close": "Sluiten",
|
||||||
"siteErrorCreate": "Fout bij maken site",
|
"siteErrorCreate": "Fout bij maken site",
|
||||||
"siteErrorCreateKeyPair": "Key pair of site standaard niet gevonden",
|
"siteErrorCreateKeyPair": "Key pair of site standaard niet gevonden",
|
||||||
"siteErrorCreateDefaults": "Standaardinstellingen niet gevonden",
|
"siteErrorCreateDefaults": "Standaardinstellingen niet gevonden",
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
"siteGeneralDescription": "Algemene instellingen voor deze site configureren",
|
"siteGeneralDescription": "Algemene instellingen voor deze site configureren",
|
||||||
"siteSettingDescription": "Configureer de instellingen op uw site",
|
"siteSettingDescription": "Configureer de instellingen op uw site",
|
||||||
"siteSetting": "{siteName} instellingen",
|
"siteSetting": "{siteName} instellingen",
|
||||||
"siteNewtTunnel": "Nieuwstunnel (Aanbevolen)",
|
"siteNewtTunnel": "Newttunnel (Aanbevolen)",
|
||||||
"siteNewtTunnelDescription": "Gemakkelijkste manier om een ingangspunt in uw netwerk te maken. Geen extra opzet.",
|
"siteNewtTunnelDescription": "Gemakkelijkste manier om een ingangspunt in uw netwerk te maken. Geen extra opzet.",
|
||||||
"siteWg": "Basis WireGuard",
|
"siteWg": "Basis WireGuard",
|
||||||
"siteWgDescription": "Gebruik een WireGuard client om een tunnel te bouwen. Handmatige NAT installatie vereist.",
|
"siteWgDescription": "Gebruik een WireGuard client om een tunnel te bouwen. Handmatige NAT installatie vereist.",
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
"siteCredentialsSave": "Uw referenties opslaan",
|
"siteCredentialsSave": "Uw referenties opslaan",
|
||||||
"siteCredentialsSaveDescription": "Je kunt dit slechts één keer zien. Kopieer het naar een beveiligde plek.",
|
"siteCredentialsSaveDescription": "Je kunt dit slechts één keer zien. Kopieer het naar een beveiligde plek.",
|
||||||
"siteInfo": "Site informatie",
|
"siteInfo": "Site informatie",
|
||||||
"status": "status",
|
"status": "Status",
|
||||||
"shareTitle": "Beheer deellinks",
|
"shareTitle": "Beheer deellinks",
|
||||||
"shareDescription": "Maak deelbare links aan om tijdelijke of permanente toegang tot uw bronnen te verlenen",
|
"shareDescription": "Maak deelbare links aan om tijdelijke of permanente toegang tot uw bronnen te verlenen",
|
||||||
"shareSearch": "Zoek share links...",
|
"shareSearch": "Zoek share links...",
|
||||||
@@ -146,19 +146,19 @@
|
|||||||
"never": "Nooit",
|
"never": "Nooit",
|
||||||
"shareErrorSelectResource": "Selecteer een bron",
|
"shareErrorSelectResource": "Selecteer een bron",
|
||||||
"resourceTitle": "Bronnen beheren",
|
"resourceTitle": "Bronnen beheren",
|
||||||
"resourceDescription": "Veilige proxy's voor uw privé applicaties maken",
|
"resourceDescription": "Veilige proxy's voor uw privé applicaties aanmaken",
|
||||||
"resourcesSearch": "Zoek bronnen...",
|
"resourcesSearch": "Zoek bronnen...",
|
||||||
"resourceAdd": "Bron toevoegen",
|
"resourceAdd": "Bron toevoegen",
|
||||||
"resourceErrorDelte": "Fout bij verwijderen document",
|
"resourceErrorDelte": "Fout bij verwijderen document",
|
||||||
"authentication": "Authenticatie",
|
"authentication": "Authenticatie",
|
||||||
"protected": "Beschermd",
|
"protected": "Beveiligd",
|
||||||
"notProtected": "Niet beschermd",
|
"notProtected": "Niet beveiligd",
|
||||||
"resourceMessageRemove": "Eenmaal verwijderd, zal het bestand niet langer toegankelijk zijn. Alle doelen die gekoppeld zijn aan het hulpbron, zullen ook verwijderd worden.",
|
"resourceMessageRemove": "Eenmaal verwijderd, zal het bestand niet langer toegankelijk zijn. Alle doelen die gekoppeld zijn aan het hulpbron, zullen ook verwijderd worden.",
|
||||||
"resourceMessageConfirm": "Om te bevestigen, typ de naam van de bron hieronder.",
|
"resourceMessageConfirm": "Om te bevestigen, typ de naam van de bron hieronder.",
|
||||||
"resourceQuestionRemove": "Weet u zeker dat u de resource {selectedResource} uit de organisatie wilt verwijderen?",
|
"resourceQuestionRemove": "Weet u zeker dat u de resource {selectedResource} uit de organisatie wilt verwijderen?",
|
||||||
"resourceHTTP": "HTTPS bron",
|
"resourceHTTP": "HTTPS bron",
|
||||||
"resourceHTTPDescription": "Proxy verzoeken aan uw app via HTTPS via een subdomein of basisdomein.",
|
"resourceHTTPDescription": "Proxy verzoeken aan uw app via HTTPS via een subdomein of basisdomein.",
|
||||||
"resourceRaw": "Ruwe TCP/UDP bron",
|
"resourceRaw": "TCP/UDP bron",
|
||||||
"resourceRawDescription": "Proxy verzoeken naar je app via TCP/UDP met behulp van een poortnummer.",
|
"resourceRawDescription": "Proxy verzoeken naar je app via TCP/UDP met behulp van een poortnummer.",
|
||||||
"resourceCreate": "Bron maken",
|
"resourceCreate": "Bron maken",
|
||||||
"resourceCreateDescription": "Volg de onderstaande stappen om een nieuwe bron te maken",
|
"resourceCreateDescription": "Volg de onderstaande stappen om een nieuwe bron te maken",
|
||||||
@@ -183,7 +183,7 @@
|
|||||||
"protocolSelect": "Selecteer een protocol",
|
"protocolSelect": "Selecteer een protocol",
|
||||||
"resourcePortNumber": "Nummer van poort",
|
"resourcePortNumber": "Nummer van poort",
|
||||||
"resourcePortNumberDescription": "Het externe poortnummer naar proxyverzoeken.",
|
"resourcePortNumberDescription": "Het externe poortnummer naar proxyverzoeken.",
|
||||||
"cancel": "annuleren",
|
"cancel": "Annuleren",
|
||||||
"resourceConfig": "Configuratie tekstbouwstenen",
|
"resourceConfig": "Configuratie tekstbouwstenen",
|
||||||
"resourceConfigDescription": "Kopieer en plak deze configuratie-snippets om je TCP/UDP-bron in te stellen",
|
"resourceConfigDescription": "Kopieer en plak deze configuratie-snippets om je TCP/UDP-bron in te stellen",
|
||||||
"resourceAddEntrypoints": "Traefik: Entrypoints toevoegen",
|
"resourceAddEntrypoints": "Traefik: Entrypoints toevoegen",
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
"saveGeneralSettings": "Algemene instellingen opslaan",
|
"saveGeneralSettings": "Algemene instellingen opslaan",
|
||||||
"saveSettings": "Instellingen opslaan",
|
"saveSettings": "Instellingen opslaan",
|
||||||
"orgDangerZone": "Gevaarlijke zone",
|
"orgDangerZone": "Gevaarlijke zone",
|
||||||
"orgDangerZoneDescription": "Als u deze instantie verwijdert, is er geen weg terug. Wees het alstublieft zeker.",
|
"orgDangerZoneDescription": "Deze instantie verwijderen is onomkeerbaar. Bevestig alstublieft dat u wilt doorgaan.",
|
||||||
"orgDelete": "Verwijder organisatie",
|
"orgDelete": "Verwijder organisatie",
|
||||||
"orgDeleteConfirm": "Bevestig Verwijderen Organisatie",
|
"orgDeleteConfirm": "Bevestig Verwijderen Organisatie",
|
||||||
"orgMessageRemove": "Deze actie is onomkeerbaar en zal alle bijbehorende gegevens verwijderen.",
|
"orgMessageRemove": "Deze actie is onomkeerbaar en zal alle bijbehorende gegevens verwijderen.",
|
||||||
@@ -501,8 +501,8 @@
|
|||||||
"targetStickySessionsDescription": "Behoud verbindingen op hetzelfde backend doel voor hun hele sessie.",
|
"targetStickySessionsDescription": "Behoud verbindingen op hetzelfde backend doel voor hun hele sessie.",
|
||||||
"methodSelect": "Selecteer methode",
|
"methodSelect": "Selecteer methode",
|
||||||
"targetSubmit": "Doelwit toevoegen",
|
"targetSubmit": "Doelwit toevoegen",
|
||||||
"targetNoOne": "Geen doelwitten. Voeg een doel toe via het formulier.",
|
"targetNoOne": "Geen doel toegevoegd. Voeg deze toe via dit formulier.",
|
||||||
"targetNoOneDescription": "Het toevoegen van meer dan één doel hierboven zal de load balancering mogelijk maken.",
|
"targetNoOneDescription": "Het toevoegen van meer dan één doel hierboven zal load balancering mogelijk maken.",
|
||||||
"targetsSubmit": "Doelstellingen opslaan",
|
"targetsSubmit": "Doelstellingen opslaan",
|
||||||
"proxyAdditional": "Extra Proxy-instellingen",
|
"proxyAdditional": "Extra Proxy-instellingen",
|
||||||
"proxyAdditionalDescription": "Configureer hoe de proxy-instellingen van uw bron worden afgehandeld",
|
"proxyAdditionalDescription": "Configureer hoe de proxy-instellingen van uw bron worden afgehandeld",
|
||||||
@@ -598,7 +598,7 @@
|
|||||||
"newtId": "Newt-ID",
|
"newtId": "Newt-ID",
|
||||||
"newtSecretKey": "Nieuwe geheime sleutel",
|
"newtSecretKey": "Nieuwe geheime sleutel",
|
||||||
"architecture": "Architectuur",
|
"architecture": "Architectuur",
|
||||||
"sites": "Werkruimtes",
|
"sites": "Verbindingen",
|
||||||
"siteWgAnyClients": "Gebruik een willekeurige WireGuard client om verbinding te maken. Je moet je interne bronnen aanspreken met behulp van de peer IP.",
|
"siteWgAnyClients": "Gebruik een willekeurige WireGuard client om verbinding te maken. Je moet je interne bronnen aanspreken met behulp van de peer IP.",
|
||||||
"siteWgCompatibleAllClients": "Compatibel met alle WireGuard clients",
|
"siteWgCompatibleAllClients": "Compatibel met alle WireGuard clients",
|
||||||
"siteWgManualConfigurationRequired": "Handmatige configuratie vereist",
|
"siteWgManualConfigurationRequired": "Handmatige configuratie vereist",
|
||||||
@@ -729,7 +729,7 @@
|
|||||||
"idpMessageConfirm": "Om dit te bevestigen, typt u de naam van onderstaande identiteitsprovider.",
|
"idpMessageConfirm": "Om dit te bevestigen, typt u de naam van onderstaande identiteitsprovider.",
|
||||||
"idpConfirmDelete": "Bevestig verwijderen Identity Provider",
|
"idpConfirmDelete": "Bevestig verwijderen Identity Provider",
|
||||||
"idpDelete": "Identity Provider verwijderen",
|
"idpDelete": "Identity Provider verwijderen",
|
||||||
"idp": "Identiteit aanbieders",
|
"idp": "Identiteitsaanbieders",
|
||||||
"idpSearch": "Identiteitsaanbieders zoeken...",
|
"idpSearch": "Identiteitsaanbieders zoeken...",
|
||||||
"idpAdd": "Identity Provider toevoegen",
|
"idpAdd": "Identity Provider toevoegen",
|
||||||
"idpClientIdRequired": "Client-ID is vereist.",
|
"idpClientIdRequired": "Client-ID is vereist.",
|
||||||
@@ -801,7 +801,7 @@
|
|||||||
"defaultMappingsOrgDescription": "Deze expressie moet de org-ID teruggeven of waar om de gebruiker toegang te geven tot de organisatie.",
|
"defaultMappingsOrgDescription": "Deze expressie moet de org-ID teruggeven of waar om de gebruiker toegang te geven tot de organisatie.",
|
||||||
"defaultMappingsSubmit": "Standaard toewijzingen opslaan",
|
"defaultMappingsSubmit": "Standaard toewijzingen opslaan",
|
||||||
"orgPoliciesEdit": "Organisatie beleid bewerken",
|
"orgPoliciesEdit": "Organisatie beleid bewerken",
|
||||||
"org": "Rekening",
|
"org": "Organisatie",
|
||||||
"orgSelect": "Selecteer organisatie",
|
"orgSelect": "Selecteer organisatie",
|
||||||
"orgSearch": "Zoek in org",
|
"orgSearch": "Zoek in org",
|
||||||
"orgNotFound": "Geen org gevonden.",
|
"orgNotFound": "Geen org gevonden.",
|
||||||
@@ -976,10 +976,10 @@
|
|||||||
"supportKeyEnterDescription": "Ontmoet je eigen huisdier Pangolin!",
|
"supportKeyEnterDescription": "Ontmoet je eigen huisdier Pangolin!",
|
||||||
"githubUsername": "GitHub-gebruikersnaam",
|
"githubUsername": "GitHub-gebruikersnaam",
|
||||||
"supportKeyInput": "Supporter Sleutel",
|
"supportKeyInput": "Supporter Sleutel",
|
||||||
"supportKeyBuy": "Koop Supportersleutel",
|
"supportKeyBuy": "Koop supportersleutel",
|
||||||
"logoutError": "Fout bij uitloggen",
|
"logoutError": "Fout bij uitloggen",
|
||||||
"signingAs": "Ingelogd als",
|
"signingAs": "Ingelogd als",
|
||||||
"serverAdmin": "Server Beheerder",
|
"serverAdmin": "Server beheer",
|
||||||
"managedSelfhosted": "Beheerde Self-Hosted",
|
"managedSelfhosted": "Beheerde Self-Hosted",
|
||||||
"otpEnable": "Twee-factor inschakelen",
|
"otpEnable": "Twee-factor inschakelen",
|
||||||
"otpDisable": "Tweestapsverificatie uitschakelen",
|
"otpDisable": "Tweestapsverificatie uitschakelen",
|
||||||
@@ -1128,7 +1128,7 @@
|
|||||||
"sidebarOverview": "Overzicht.",
|
"sidebarOverview": "Overzicht.",
|
||||||
"sidebarHome": "Startpagina",
|
"sidebarHome": "Startpagina",
|
||||||
"sidebarSites": "Werkruimtes",
|
"sidebarSites": "Werkruimtes",
|
||||||
"sidebarResources": "Hulpmiddelen",
|
"sidebarResources": "Bronnen",
|
||||||
"sidebarAccessControl": "Toegangs controle",
|
"sidebarAccessControl": "Toegangs controle",
|
||||||
"sidebarUsers": "Gebruikers",
|
"sidebarUsers": "Gebruikers",
|
||||||
"sidebarInvitations": "Uitnodigingen",
|
"sidebarInvitations": "Uitnodigingen",
|
||||||
@@ -1147,7 +1147,7 @@
|
|||||||
"viewDockerContainers": "Bekijk Docker containers",
|
"viewDockerContainers": "Bekijk Docker containers",
|
||||||
"containersIn": "Containers in {siteName}",
|
"containersIn": "Containers in {siteName}",
|
||||||
"selectContainerDescription": "Selecteer een container om als hostnaam voor dit doel te gebruiken. Klik op een poort om een poort te gebruiken.",
|
"selectContainerDescription": "Selecteer een container om als hostnaam voor dit doel te gebruiken. Klik op een poort om een poort te gebruiken.",
|
||||||
"containerName": "naam",
|
"containerName": "Naam",
|
||||||
"containerImage": "Afbeelding",
|
"containerImage": "Afbeelding",
|
||||||
"containerState": "Provincie",
|
"containerState": "Provincie",
|
||||||
"containerNetworks": "Netwerken",
|
"containerNetworks": "Netwerken",
|
||||||
@@ -1349,7 +1349,7 @@
|
|||||||
"olmId": "Olm ID",
|
"olmId": "Olm ID",
|
||||||
"olmSecretKey": "Olm Geheime Sleutel",
|
"olmSecretKey": "Olm Geheime Sleutel",
|
||||||
"clientCredentialsSave": "Uw referenties opslaan",
|
"clientCredentialsSave": "Uw referenties opslaan",
|
||||||
"clientCredentialsSaveDescription": "Je kunt dit slechts één keer zien. Kopieer het naar een beveiligde plek.",
|
"clientCredentialsSaveDescription": "Je kunt dit slechts één keer zien. Kopieer deze naar een veilige plek.",
|
||||||
"generalSettingsDescription": "Configureer de algemene instellingen voor deze client",
|
"generalSettingsDescription": "Configureer de algemene instellingen voor deze client",
|
||||||
"clientUpdated": "Klant bijgewerkt ",
|
"clientUpdated": "Klant bijgewerkt ",
|
||||||
"clientUpdatedDescription": "De client is bijgewerkt.",
|
"clientUpdatedDescription": "De client is bijgewerkt.",
|
||||||
|
|||||||
224
package-lock.json
generated
224
package-lock.json
generated
@@ -109,7 +109,7 @@
|
|||||||
"@types/jmespath": "^0.15.2",
|
"@types/jmespath": "^0.15.2",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/node": "24.5.0",
|
"@types/node": "24.5.2",
|
||||||
"@types/nodemailer": "7.0.1",
|
"@types/nodemailer": "7.0.1",
|
||||||
"@types/pg": "8.15.5",
|
"@types/pg": "8.15.5",
|
||||||
"@types/react": "19.1.13",
|
"@types/react": "19.1.13",
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@types/yargs": "17.0.33",
|
"@types/yargs": "17.0.33",
|
||||||
"drizzle-kit": "0.31.4",
|
"drizzle-kit": "0.31.4",
|
||||||
"esbuild": "0.25.9",
|
"esbuild": "0.25.10",
|
||||||
"esbuild-node-externals": "1.18.0",
|
"esbuild-node-externals": "1.18.0",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"react-email": "4.2.11",
|
"react-email": "4.2.11",
|
||||||
@@ -1556,9 +1556,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz",
|
||||||
"integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
|
"integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1573,9 +1573,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm": {
|
"node_modules/@esbuild/android-arm": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz",
|
||||||
"integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
|
"integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1590,9 +1590,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-arm64": {
|
"node_modules/@esbuild/android-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
|
"integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1607,9 +1607,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/android-x64": {
|
"node_modules/@esbuild/android-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
|
"integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1624,9 +1624,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-arm64": {
|
"node_modules/@esbuild/darwin-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
|
"integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1641,9 +1641,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/darwin-x64": {
|
"node_modules/@esbuild/darwin-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
|
"integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1658,9 +1658,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-arm64": {
|
"node_modules/@esbuild/freebsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
|
"integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1675,9 +1675,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/freebsd-x64": {
|
"node_modules/@esbuild/freebsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
|
"integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1692,9 +1692,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm": {
|
"node_modules/@esbuild/linux-arm": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz",
|
||||||
"integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
|
"integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
@@ -1709,9 +1709,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-arm64": {
|
"node_modules/@esbuild/linux-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
|
"integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1726,9 +1726,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ia32": {
|
"node_modules/@esbuild/linux-ia32": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz",
|
||||||
"integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
|
"integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1743,9 +1743,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-loong64": {
|
"node_modules/@esbuild/linux-loong64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz",
|
||||||
"integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
|
"integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
@@ -1760,9 +1760,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-mips64el": {
|
"node_modules/@esbuild/linux-mips64el": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz",
|
||||||
"integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
|
"integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
@@ -1777,9 +1777,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-ppc64": {
|
"node_modules/@esbuild/linux-ppc64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz",
|
||||||
"integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
|
"integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
@@ -1794,9 +1794,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-riscv64": {
|
"node_modules/@esbuild/linux-riscv64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz",
|
||||||
"integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
|
"integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
@@ -1811,9 +1811,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-s390x": {
|
"node_modules/@esbuild/linux-s390x": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz",
|
||||||
"integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
|
"integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
@@ -1828,9 +1828,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/linux-x64": {
|
"node_modules/@esbuild/linux-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
|
"integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1845,9 +1845,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-arm64": {
|
"node_modules/@esbuild/netbsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
|
"integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1862,9 +1862,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/netbsd-x64": {
|
"node_modules/@esbuild/netbsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
|
"integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1879,9 +1879,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-arm64": {
|
"node_modules/@esbuild/openbsd-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
|
"integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1896,9 +1896,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openbsd-x64": {
|
"node_modules/@esbuild/openbsd-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
|
"integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1913,9 +1913,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/openharmony-arm64": {
|
"node_modules/@esbuild/openharmony-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
|
"integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1930,9 +1930,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/sunos-x64": {
|
"node_modules/@esbuild/sunos-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
|
"integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -1947,9 +1947,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-arm64": {
|
"node_modules/@esbuild/win32-arm64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz",
|
||||||
"integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
|
"integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
@@ -1964,9 +1964,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-ia32": {
|
"node_modules/@esbuild/win32-ia32": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz",
|
||||||
"integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
|
"integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
@@ -1981,9 +1981,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@esbuild/win32-x64": {
|
"node_modules/@esbuild/win32-x64": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz",
|
||||||
"integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
|
"integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
@@ -6342,9 +6342,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "24.5.0",
|
"version": "24.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.2.tgz",
|
||||||
"integrity": "sha512-y1dMvuvJspJiPSDZUQ+WMBvF7dpnEqN4x9DDC9ie5Fs/HUZJA3wFp7EhHoVaKX/iI0cRoECV8X2jL8zi0xrHCg==",
|
"integrity": "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==",
|
||||||
"devOptional": true,
|
"devOptional": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -9005,9 +9005,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.25.9",
|
"version": "0.25.10",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz",
|
||||||
"integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
|
"integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -9018,32 +9018,32 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@esbuild/aix-ppc64": "0.25.9",
|
"@esbuild/aix-ppc64": "0.25.10",
|
||||||
"@esbuild/android-arm": "0.25.9",
|
"@esbuild/android-arm": "0.25.10",
|
||||||
"@esbuild/android-arm64": "0.25.9",
|
"@esbuild/android-arm64": "0.25.10",
|
||||||
"@esbuild/android-x64": "0.25.9",
|
"@esbuild/android-x64": "0.25.10",
|
||||||
"@esbuild/darwin-arm64": "0.25.9",
|
"@esbuild/darwin-arm64": "0.25.10",
|
||||||
"@esbuild/darwin-x64": "0.25.9",
|
"@esbuild/darwin-x64": "0.25.10",
|
||||||
"@esbuild/freebsd-arm64": "0.25.9",
|
"@esbuild/freebsd-arm64": "0.25.10",
|
||||||
"@esbuild/freebsd-x64": "0.25.9",
|
"@esbuild/freebsd-x64": "0.25.10",
|
||||||
"@esbuild/linux-arm": "0.25.9",
|
"@esbuild/linux-arm": "0.25.10",
|
||||||
"@esbuild/linux-arm64": "0.25.9",
|
"@esbuild/linux-arm64": "0.25.10",
|
||||||
"@esbuild/linux-ia32": "0.25.9",
|
"@esbuild/linux-ia32": "0.25.10",
|
||||||
"@esbuild/linux-loong64": "0.25.9",
|
"@esbuild/linux-loong64": "0.25.10",
|
||||||
"@esbuild/linux-mips64el": "0.25.9",
|
"@esbuild/linux-mips64el": "0.25.10",
|
||||||
"@esbuild/linux-ppc64": "0.25.9",
|
"@esbuild/linux-ppc64": "0.25.10",
|
||||||
"@esbuild/linux-riscv64": "0.25.9",
|
"@esbuild/linux-riscv64": "0.25.10",
|
||||||
"@esbuild/linux-s390x": "0.25.9",
|
"@esbuild/linux-s390x": "0.25.10",
|
||||||
"@esbuild/linux-x64": "0.25.9",
|
"@esbuild/linux-x64": "0.25.10",
|
||||||
"@esbuild/netbsd-arm64": "0.25.9",
|
"@esbuild/netbsd-arm64": "0.25.10",
|
||||||
"@esbuild/netbsd-x64": "0.25.9",
|
"@esbuild/netbsd-x64": "0.25.10",
|
||||||
"@esbuild/openbsd-arm64": "0.25.9",
|
"@esbuild/openbsd-arm64": "0.25.10",
|
||||||
"@esbuild/openbsd-x64": "0.25.9",
|
"@esbuild/openbsd-x64": "0.25.10",
|
||||||
"@esbuild/openharmony-arm64": "0.25.9",
|
"@esbuild/openharmony-arm64": "0.25.10",
|
||||||
"@esbuild/sunos-x64": "0.25.9",
|
"@esbuild/sunos-x64": "0.25.10",
|
||||||
"@esbuild/win32-arm64": "0.25.9",
|
"@esbuild/win32-arm64": "0.25.10",
|
||||||
"@esbuild/win32-ia32": "0.25.9",
|
"@esbuild/win32-ia32": "0.25.10",
|
||||||
"@esbuild/win32-x64": "0.25.9"
|
"@esbuild/win32-x64": "0.25.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/esbuild-node-externals": {
|
"node_modules/esbuild-node-externals": {
|
||||||
|
|||||||
@@ -126,7 +126,7 @@
|
|||||||
"@types/jmespath": "^0.15.2",
|
"@types/jmespath": "^0.15.2",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/node": "24.5.0",
|
"@types/node": "24.5.2",
|
||||||
"@types/nodemailer": "7.0.1",
|
"@types/nodemailer": "7.0.1",
|
||||||
"@types/pg": "8.15.5",
|
"@types/pg": "8.15.5",
|
||||||
"@types/react": "19.1.13",
|
"@types/react": "19.1.13",
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
"@types/yargs": "17.0.33",
|
"@types/yargs": "17.0.33",
|
||||||
"drizzle-kit": "0.31.4",
|
"drizzle-kit": "0.31.4",
|
||||||
"esbuild": "0.25.9",
|
"esbuild": "0.25.10",
|
||||||
"esbuild-node-externals": "1.18.0",
|
"esbuild-node-externals": "1.18.0",
|
||||||
"postcss": "^8",
|
"postcss": "^8",
|
||||||
"react-email": "4.2.11",
|
"react-email": "4.2.11",
|
||||||
|
|||||||
@@ -138,12 +138,8 @@ export async function updateProxyResources(
|
|||||||
? true
|
? true
|
||||||
: resourceData.ssl;
|
: resourceData.ssl;
|
||||||
let headers = "";
|
let headers = "";
|
||||||
for (const header of resourceData.headers || []) {
|
if (resourceData.headers) {
|
||||||
headers += `${header.name}: ${header.value},`;
|
headers = JSON.stringify(resourceData.headers);
|
||||||
}
|
|
||||||
// if there are headers, remove the trailing comma
|
|
||||||
if (headers.endsWith(",")) {
|
|
||||||
headers = headers.slice(0, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (existingResource) {
|
if (existingResource) {
|
||||||
@@ -169,7 +165,7 @@ export async function updateProxyResources(
|
|||||||
.update(resources)
|
.update(resources)
|
||||||
.set({
|
.set({
|
||||||
name: resourceData.name || "Unnamed Resource",
|
name: resourceData.name || "Unnamed Resource",
|
||||||
protocol: protocol || "http",
|
protocol: protocol || "tcp",
|
||||||
http: http,
|
http: http,
|
||||||
proxyPort: http ? null : resourceData["proxy-port"],
|
proxyPort: http ? null : resourceData["proxy-port"],
|
||||||
fullDomain: http ? resourceData["full-domain"] : null,
|
fullDomain: http ? resourceData["full-domain"] : null,
|
||||||
@@ -461,7 +457,7 @@ export async function updateProxyResources(
|
|||||||
orgId,
|
orgId,
|
||||||
niceId: resourceNiceId,
|
niceId: resourceNiceId,
|
||||||
name: resourceData.name || "Unnamed Resource",
|
name: resourceData.name || "Unnamed Resource",
|
||||||
protocol: resourceData.protocol || "http",
|
protocol: protocol || "tcp",
|
||||||
http: http,
|
http: http,
|
||||||
proxyPort: http ? null : resourceData["proxy-port"],
|
proxyPort: http ? null : resourceData["proxy-port"],
|
||||||
fullDomain: http ? resourceData["full-domain"] : null,
|
fullDomain: http ? resourceData["full-domain"] : null,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import path from "path";
|
|||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
// This is a placeholder value replaced by the build process
|
// This is a placeholder value replaced by the build process
|
||||||
export const APP_VERSION = "1.10.0";
|
export const APP_VERSION = "1.10.2";
|
||||||
|
|
||||||
export const __FILENAME = fileURLToPath(import.meta.url);
|
export const __FILENAME = fileURLToPath(import.meta.url);
|
||||||
export const __DIRNAME = path.dirname(__FILENAME);
|
export const __DIRNAME = path.dirname(__FILENAME);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export async function addTargets(
|
|||||||
}:${target.port}`;
|
}:${target.port}`;
|
||||||
});
|
});
|
||||||
|
|
||||||
sendToClient(newtId, {
|
await sendToClient(newtId, {
|
||||||
type: `newt/${protocol}/add`,
|
type: `newt/${protocol}/add`,
|
||||||
data: {
|
data: {
|
||||||
targets: payloadTargets
|
targets: payloadTargets
|
||||||
|
|||||||
@@ -319,26 +319,6 @@ async function createRawResource(
|
|||||||
|
|
||||||
const { name, http, protocol, proxyPort } = parsedBody.data;
|
const { name, http, protocol, proxyPort } = parsedBody.data;
|
||||||
|
|
||||||
// if http is false check to see if there is already a resource with the same port and protocol
|
|
||||||
const existingResource = await db
|
|
||||||
.select()
|
|
||||||
.from(resources)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(resources.protocol, protocol),
|
|
||||||
eq(resources.proxyPort, proxyPort!)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingResource.length > 0) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.CONFLICT,
|
|
||||||
"Resource with that protocol and port already exists"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let resource: Resource | undefined;
|
let resource: Resource | undefined;
|
||||||
|
|
||||||
const niceId = await getUniqueResourceName(orgId);
|
const niceId = await getUniqueResourceName(orgId);
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ async function query(resourceId?: number, niceId?: string, orgId?: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GetResourceResponse = NonNullable<Awaited<ReturnType<typeof query>>>;
|
export type GetResourceResponse = Omit<NonNullable<Awaited<ReturnType<typeof query>>>, 'headers'> & {
|
||||||
|
headers: { name: string; value: string }[] | null;
|
||||||
|
};
|
||||||
|
|
||||||
registry.registerPath({
|
registry.registerPath({
|
||||||
method: "get",
|
method: "get",
|
||||||
@@ -99,7 +101,10 @@ export async function getResource(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return response<GetResourceResponse>(res, {
|
return response<GetResourceResponse>(res, {
|
||||||
data: resource,
|
data: {
|
||||||
|
...resource,
|
||||||
|
headers: resource.headers ? JSON.parse(resource.headers) : resource.headers
|
||||||
|
},
|
||||||
success: true,
|
success: true,
|
||||||
error: false,
|
error: false,
|
||||||
message: "Resource retrieved successfully",
|
message: "Resource retrieved successfully",
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const updateHttpResourceBodySchema = z
|
|||||||
tlsServerName: z.string().nullable().optional(),
|
tlsServerName: z.string().nullable().optional(),
|
||||||
setHostHeader: z.string().nullable().optional(),
|
setHostHeader: z.string().nullable().optional(),
|
||||||
skipToIdpId: z.number().int().positive().nullable().optional(),
|
skipToIdpId: z.number().int().positive().nullable().optional(),
|
||||||
headers: z.string().nullable().optional()
|
headers: z.array(z.object({ name: z.string(), value: z.string() })).optional(),
|
||||||
})
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.refine((data) => Object.keys(data).length > 0, {
|
.refine((data) => Object.keys(data).length > 0, {
|
||||||
@@ -85,18 +85,6 @@ const updateHttpResourceBodySchema = z
|
|||||||
message:
|
message:
|
||||||
"Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header."
|
"Invalid custom Host Header value. Use domain name format, or save empty to unset custom Host Header."
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.refine(
|
|
||||||
(data) => {
|
|
||||||
if (data.headers) {
|
|
||||||
return validateHeaders(data.headers);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
message:
|
|
||||||
"Invalid headers format. Use comma-separated format: 'Header-Name: value, Another-Header: another-value'. Header values cannot contain colons."
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export type UpdateResourceResponse = Resource;
|
export type UpdateResourceResponse = Resource;
|
||||||
@@ -292,9 +280,14 @@ async function updateHttpResource(
|
|||||||
updateData.subdomain = finalSubdomain;
|
updateData.subdomain = finalSubdomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let headers = null;
|
||||||
|
if (updateData.headers) {
|
||||||
|
headers = JSON.stringify(updateData.headers);
|
||||||
|
}
|
||||||
|
|
||||||
const updatedResource = await db
|
const updatedResource = await db
|
||||||
.update(resources)
|
.update(resources)
|
||||||
.set({ ...updateData })
|
.set({ ...updateData, headers })
|
||||||
.where(eq(resources.resourceId, resource.resourceId))
|
.where(eq(resources.resourceId, resource.resourceId))
|
||||||
.returning();
|
.returning();
|
||||||
|
|
||||||
@@ -342,31 +335,6 @@ async function updateRawResource(
|
|||||||
|
|
||||||
const updateData = parsedBody.data;
|
const updateData = parsedBody.data;
|
||||||
|
|
||||||
if (updateData.proxyPort) {
|
|
||||||
const proxyPort = updateData.proxyPort;
|
|
||||||
const existingResource = await db
|
|
||||||
.select()
|
|
||||||
.from(resources)
|
|
||||||
.where(
|
|
||||||
and(
|
|
||||||
eq(resources.protocol, resource.protocol),
|
|
||||||
eq(resources.proxyPort, proxyPort!)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
existingResource.length > 0 &&
|
|
||||||
existingResource[0].resourceId !== resource.resourceId
|
|
||||||
) {
|
|
||||||
return next(
|
|
||||||
createHttpError(
|
|
||||||
HttpCode.CONFLICT,
|
|
||||||
"Resource with that protocol and port already exists"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedResource = await db
|
const updatedResource = await db
|
||||||
.update(resources)
|
.update(resources)
|
||||||
.set(updateData)
|
.set(updateData)
|
||||||
|
|||||||
@@ -306,17 +306,25 @@ export async function getTraefikConfig(
|
|||||||
...additionalMiddlewares
|
...additionalMiddlewares
|
||||||
];
|
];
|
||||||
|
|
||||||
if (resource.headers && resource.headers.length > 0) {
|
if (resource.headers || resource.setHostHeader) {
|
||||||
// if there are headers, parse them into an object
|
// if there are headers, parse them into an object
|
||||||
const headersObj: { [key: string]: string } = {};
|
const headersObj: { [key: string]: string } = {};
|
||||||
const headersArr = resource.headers.split(",");
|
if (resource.headers) {
|
||||||
for (const header of headersArr) {
|
let headersArr: { name: string; value: string }[] = [];
|
||||||
const [key, value] = header
|
try {
|
||||||
.split(":")
|
headersArr = JSON.parse(resource.headers) as {
|
||||||
.map((s: string) => s.trim());
|
name: string;
|
||||||
if (key && value) {
|
value: string;
|
||||||
headersObj[key] = value;
|
}[];
|
||||||
|
} catch (e) {
|
||||||
|
logger.warn(
|
||||||
|
`Failed to parse headers for resource ${resource.resourceId}: ${e}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
headersArr.forEach((header) => {
|
||||||
|
headersObj[header.name] = header.value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resource.setHostHeader) {
|
if (resource.setHostHeader) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import m2 from "./scriptsPg/1.7.0";
|
|||||||
import m3 from "./scriptsPg/1.8.0";
|
import m3 from "./scriptsPg/1.8.0";
|
||||||
import m4 from "./scriptsPg/1.9.0";
|
import m4 from "./scriptsPg/1.9.0";
|
||||||
import m5 from "./scriptsPg/1.10.0";
|
import m5 from "./scriptsPg/1.10.0";
|
||||||
|
import m6 from "./scriptsPg/1.10.2";
|
||||||
|
|
||||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||||
@@ -21,6 +22,7 @@ const migrations = [
|
|||||||
{ version: "1.8.0", run: m3 },
|
{ version: "1.8.0", run: m3 },
|
||||||
{ version: "1.9.0", run: m4 },
|
{ version: "1.9.0", run: m4 },
|
||||||
{ version: "1.10.0", run: m5 },
|
{ version: "1.10.0", run: m5 },
|
||||||
|
{ version: "1.10.2", run: m6 },
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as {
|
] as {
|
||||||
version: string;
|
version: string;
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import m22 from "./scriptsSqlite/1.7.0";
|
|||||||
import m23 from "./scriptsSqlite/1.8.0";
|
import m23 from "./scriptsSqlite/1.8.0";
|
||||||
import m24 from "./scriptsSqlite/1.9.0";
|
import m24 from "./scriptsSqlite/1.9.0";
|
||||||
import m25 from "./scriptsSqlite/1.10.0";
|
import m25 from "./scriptsSqlite/1.10.0";
|
||||||
|
import m26 from "./scriptsSqlite/1.10.1";
|
||||||
|
import m27 from "./scriptsSqlite/1.10.2";
|
||||||
|
|
||||||
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
// THIS CANNOT IMPORT ANYTHING FROM THE SERVER
|
||||||
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
// EXCEPT FOR THE DATABASE AND THE SCHEMA
|
||||||
@@ -53,6 +55,8 @@ const migrations = [
|
|||||||
{ version: "1.8.0", run: m23 },
|
{ version: "1.8.0", run: m23 },
|
||||||
{ version: "1.9.0", run: m24 },
|
{ version: "1.9.0", run: m24 },
|
||||||
{ version: "1.10.0", run: m25 },
|
{ version: "1.10.0", run: m25 },
|
||||||
|
{ version: "1.10.1", run: m26 },
|
||||||
|
{ version: "1.10.2", run: m27 },
|
||||||
// Add new migrations here as they are created
|
// Add new migrations here as they are created
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
|||||||
47
server/setup/scriptsPg/1.10.2.ts
Normal file
47
server/setup/scriptsPg/1.10.2.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { db } from "@server/db/pg/driver";
|
||||||
|
import { sql } from "drizzle-orm";
|
||||||
|
import { __DIRNAME, APP_PATH } from "@server/lib/consts";
|
||||||
|
|
||||||
|
const version = "1.10.2";
|
||||||
|
|
||||||
|
export default async function migration() {
|
||||||
|
console.log(`Running setup script ${version}...`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resources = await db.execute(sql`
|
||||||
|
SELECT * FROM "resources"
|
||||||
|
`);
|
||||||
|
|
||||||
|
await db.execute(sql`BEGIN`);
|
||||||
|
|
||||||
|
for (const resource of resources.rows) {
|
||||||
|
const headers = resource.headers as string | null;
|
||||||
|
if (headers && headers !== "") {
|
||||||
|
// lets convert it to json
|
||||||
|
// fist split at commas
|
||||||
|
const headersArray = headers
|
||||||
|
.split(",")
|
||||||
|
.map((header: string) => {
|
||||||
|
const [name, ...valueParts] = header.split(":");
|
||||||
|
const value = valueParts.join(":").trim();
|
||||||
|
return { name: name.trim(), value };
|
||||||
|
});
|
||||||
|
|
||||||
|
await db.execute(sql`
|
||||||
|
UPDATE "resources" SET "headers" = ${JSON.stringify(headersArray)} WHERE "resourceId" = ${resource.resourceId}
|
||||||
|
`);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Updated resource ${resource.resourceId} headers to JSON format`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.execute(sql`COMMIT`);
|
||||||
|
console.log(`Migrated database`);
|
||||||
|
} catch (e) {
|
||||||
|
await db.execute(sql`ROLLBACK`);
|
||||||
|
console.log("Failed to migrate db:", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
69
server/setup/scriptsSqlite/1.10.1.ts
Normal file
69
server/setup/scriptsSqlite/1.10.1.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { APP_PATH } from "@server/lib/consts";
|
||||||
|
import Database from "better-sqlite3";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const version = "1.10.1";
|
||||||
|
|
||||||
|
export default async function migration() {
|
||||||
|
console.log(`Running setup script ${version}...`);
|
||||||
|
|
||||||
|
const location = path.join(APP_PATH, "db", "db.sqlite");
|
||||||
|
const db = new Database(location);
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.pragma("foreign_keys = OFF");
|
||||||
|
|
||||||
|
db.transaction(() => {
|
||||||
|
db.exec(`ALTER TABLE "targets" RENAME TO "targets_old";
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "targets" (
|
||||||
|
"targetId" INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"resourceId" INTEGER NOT NULL,
|
||||||
|
"siteId" INTEGER NOT NULL,
|
||||||
|
"ip" TEXT NOT NULL,
|
||||||
|
"method" TEXT,
|
||||||
|
"port" INTEGER NOT NULL,
|
||||||
|
"internalPort" INTEGER,
|
||||||
|
"enabled" INTEGER NOT NULL DEFAULT 1,
|
||||||
|
"path" TEXT,
|
||||||
|
"pathMatchType" TEXT,
|
||||||
|
FOREIGN KEY ("resourceId") REFERENCES "resources"("resourceId") ON UPDATE no action ON DELETE cascade,
|
||||||
|
FOREIGN KEY ("siteId") REFERENCES "sites"("siteId") ON UPDATE no action ON DELETE cascade
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
INSERT INTO "targets" (
|
||||||
|
"targetId",
|
||||||
|
"resourceId",
|
||||||
|
"siteId",
|
||||||
|
"ip",
|
||||||
|
"method",
|
||||||
|
"port",
|
||||||
|
"internalPort",
|
||||||
|
"enabled",
|
||||||
|
"path",
|
||||||
|
"pathMatchType"
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
targetId,
|
||||||
|
resourceId,
|
||||||
|
siteId,
|
||||||
|
ip,
|
||||||
|
method,
|
||||||
|
port,
|
||||||
|
internalPort,
|
||||||
|
enabled,
|
||||||
|
path,
|
||||||
|
pathMatchType
|
||||||
|
FROM "targets_old";
|
||||||
|
--> statement-breakpoint
|
||||||
|
DROP TABLE "targets_old";`);
|
||||||
|
})();
|
||||||
|
|
||||||
|
db.pragma("foreign_keys = ON");
|
||||||
|
|
||||||
|
console.log(`Migrated database`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to migrate db:", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
server/setup/scriptsSqlite/1.10.2.ts
Normal file
54
server/setup/scriptsSqlite/1.10.2.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { APP_PATH } from "@server/lib/consts";
|
||||||
|
import Database from "better-sqlite3";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const version = "1.10.2";
|
||||||
|
|
||||||
|
export default async function migration() {
|
||||||
|
console.log(`Running setup script ${version}...`);
|
||||||
|
|
||||||
|
const location = path.join(APP_PATH, "db", "db.sqlite");
|
||||||
|
const db = new Database(location);
|
||||||
|
|
||||||
|
const resources = db.prepare("SELECT * FROM resources").all() as Array<{
|
||||||
|
resourceId: number;
|
||||||
|
headers: string | null;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
try {
|
||||||
|
db.pragma("foreign_keys = OFF");
|
||||||
|
|
||||||
|
db.transaction(() => {
|
||||||
|
for (const resource of resources) {
|
||||||
|
const headers = resource.headers;
|
||||||
|
if (headers && headers !== "") {
|
||||||
|
// lets convert it to json
|
||||||
|
// fist split at commas
|
||||||
|
const headersArray = headers
|
||||||
|
.split(",")
|
||||||
|
.map((header: string) => {
|
||||||
|
const [name, ...valueParts] = header.split(":");
|
||||||
|
const value = valueParts.join(":").trim();
|
||||||
|
return { name: name.trim(), value };
|
||||||
|
});
|
||||||
|
|
||||||
|
db.prepare(
|
||||||
|
`
|
||||||
|
UPDATE "resources" SET "headers" = ? WHERE "resourceId" = ?`
|
||||||
|
).run(JSON.stringify(headersArray), resource.resourceId);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Updated resource ${resource.resourceId} headers to JSON format`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
db.pragma("foreign_keys = ON");
|
||||||
|
|
||||||
|
console.log(`Migrated database`);
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to migrate db:", e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -227,7 +227,7 @@ export default function ReverseProxyTargets(props: {
|
|||||||
message: t("proxyErrorInvalidHeader")
|
message: t("proxyErrorInvalidHeader")
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
headers: z.string().optional()
|
headers: z.array(z.object({ name: z.string(), value: z.string() })).nullable()
|
||||||
});
|
});
|
||||||
|
|
||||||
const tlsSettingsSchema = z.object({
|
const tlsSettingsSchema = z.object({
|
||||||
@@ -286,7 +286,7 @@ export default function ReverseProxyTargets(props: {
|
|||||||
resolver: zodResolver(proxySettingsSchema),
|
resolver: zodResolver(proxySettingsSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
setHostHeader: resource.setHostHeader || "",
|
setHostHeader: resource.setHostHeader || "",
|
||||||
headers: resource.headers || ""
|
headers: resource.headers
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1479,7 +1479,7 @@ export default function ReverseProxyTargets(props: {
|
|||||||
<FormControl>
|
<FormControl>
|
||||||
<HeadersInput
|
<HeadersInput
|
||||||
value={
|
value={
|
||||||
field.value || ""
|
field.value
|
||||||
}
|
}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
field.onChange(
|
field.onChange(
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
|
||||||
|
|
||||||
interface HeadersInputProps {
|
interface HeadersInputProps {
|
||||||
value?: string;
|
value?: { name: string, value: string }[] | null;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: { name: string, value: string }[] | null) => void;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
rows?: number;
|
rows?: number;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function HeadersInput({
|
export function HeadersInput({
|
||||||
value = "",
|
value = [],
|
||||||
onChange,
|
onChange,
|
||||||
placeholder = `X-Example-Header: example-value
|
placeholder = `X-Example-Header: example-value
|
||||||
X-Another-Header: another-value`,
|
X-Another-Header: another-value`,
|
||||||
@@ -20,47 +21,98 @@ X-Another-Header: another-value`,
|
|||||||
className
|
className
|
||||||
}: HeadersInputProps) {
|
}: HeadersInputProps) {
|
||||||
const [internalValue, setInternalValue] = useState("");
|
const [internalValue, setInternalValue] = useState("");
|
||||||
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
|
const isUserEditingRef = useRef(false);
|
||||||
|
|
||||||
// Convert comma-separated to newline-separated for display
|
// Convert header objects array to newline-separated string for display
|
||||||
const convertToNewlineSeparated = (commaSeparated: string): string => {
|
const convertToNewlineSeparated = (headers: { name: string, value: string }[] | null): string => {
|
||||||
if (!commaSeparated || commaSeparated.trim() === "") return "";
|
if (!headers || headers.length === 0) return "";
|
||||||
|
|
||||||
return commaSeparated
|
return headers
|
||||||
.split(',')
|
.map(header => `${header.name}: ${header.value}`)
|
||||||
.map(header => header.trim())
|
|
||||||
.filter(header => header.length > 0)
|
|
||||||
.join('\n');
|
.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Convert newline-separated to comma-separated for output
|
// Convert newline-separated string to header objects array
|
||||||
const convertToCommaSeparated = (newlineSeparated: string): string => {
|
const convertToHeadersArray = (newlineSeparated: string): { name: string, value: string }[] | null => {
|
||||||
if (!newlineSeparated || newlineSeparated.trim() === "") return "";
|
if (!newlineSeparated || newlineSeparated.trim() === "") return [];
|
||||||
|
|
||||||
return newlineSeparated
|
return newlineSeparated
|
||||||
.split('\n')
|
.split('\n')
|
||||||
.map(header => header.trim())
|
.map(line => line.trim())
|
||||||
.filter(header => header.length > 0)
|
.filter(line => line.length > 0 && line.includes(':'))
|
||||||
.join(', ');
|
.map(line => {
|
||||||
|
const colonIndex = line.indexOf(':');
|
||||||
|
const name = line.substring(0, colonIndex).trim();
|
||||||
|
const value = line.substring(colonIndex + 1).trim();
|
||||||
|
|
||||||
|
// Ensure header name conforms to HTTP header requirements
|
||||||
|
// Header names should be case-insensitive, contain only ASCII letters, digits, and hyphens
|
||||||
|
const normalizedName = name.replace(/[^a-zA-Z0-9\-]/g, '').toLowerCase();
|
||||||
|
|
||||||
|
return { name: normalizedName, value };
|
||||||
|
})
|
||||||
|
.filter(header => header.name.length > 0); // Filter out headers with invalid names
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update internal value when external value changes
|
// Update internal value when external value changes
|
||||||
|
// But only if the user is not currently editing (textarea not focused)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setInternalValue(convertToNewlineSeparated(value));
|
if (!isUserEditingRef.current) {
|
||||||
|
setInternalValue(convertToNewlineSeparated(value));
|
||||||
|
}
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
const newValue = e.target.value;
|
const newValue = e.target.value;
|
||||||
setInternalValue(newValue);
|
setInternalValue(newValue);
|
||||||
|
|
||||||
// Convert back to comma-separated format for the parent
|
// Mark that user is actively editing
|
||||||
const commaSeparatedValue = convertToCommaSeparated(newValue);
|
isUserEditingRef.current = true;
|
||||||
onChange(commaSeparatedValue);
|
|
||||||
|
// Only update parent if the input is in a valid state
|
||||||
|
// Valid states: empty/whitespace only, or contains properly formatted headers
|
||||||
|
|
||||||
|
if (newValue.trim() === "") {
|
||||||
|
// Empty input is valid - represents no headers
|
||||||
|
onChange([]);
|
||||||
|
} else {
|
||||||
|
// Check if all non-empty lines are properly formatted (contain ':')
|
||||||
|
const lines = newValue.split('\n');
|
||||||
|
const nonEmptyLines = lines
|
||||||
|
.map(line => line.trim())
|
||||||
|
.filter(line => line.length > 0);
|
||||||
|
|
||||||
|
// If there are no non-empty lines, or all non-empty lines contain ':', it's valid
|
||||||
|
const isValid = nonEmptyLines.length === 0 || nonEmptyLines.every(line => line.includes(':'));
|
||||||
|
|
||||||
|
if (isValid) {
|
||||||
|
// Safe to convert and update parent
|
||||||
|
const headersArray = convertToHeadersArray(newValue);
|
||||||
|
onChange(headersArray);
|
||||||
|
}
|
||||||
|
// If not valid, don't call onChange - let user continue typing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFocus = () => {
|
||||||
|
isUserEditingRef.current = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
// Small delay to allow any final change events to process
|
||||||
|
setTimeout(() => {
|
||||||
|
isUserEditingRef.current = false;
|
||||||
|
}, 100);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Textarea
|
<Textarea
|
||||||
|
ref={textareaRef}
|
||||||
value={internalValue}
|
value={internalValue}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onBlur={handleBlur}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
className={className}
|
className={className}
|
||||||
|
|||||||
Reference in New Issue
Block a user