Compare commits

..

18 Commits

Author SHA1 Message Date
miloschwartz
ed95f10fcc openapi and swagger ui improvements and cleanup 2026-03-02 21:59:41 -08:00
Owen
64bae5b142 Merge branch 'main' into dev 2026-03-02 18:52:20 -08:00
Owen
19f9dda490 Add comment about not needing exit node 2026-03-02 16:28:01 -08:00
Owen Schwartz
cdf79edb00 Merge pull request #2570 from Fizza-Mukhtar/fix/mixed-target-failover-2448
fix: local targets ignored when newt site is unhealthy (mixed target failover)
2026-03-01 15:58:25 -08:00
Milo Schwartz
280cbb6e22 Merge pull request #2553 from LaurenceJJones/explore/static-org-dropdown
enhance(sidebar): make mobile org selector sticky
2026-03-01 11:14:16 -08:00
miloschwartz
c20babcb53 fix org selector spacing on mobile 2026-03-01 11:13:49 -08:00
Owen Schwartz
768eebe2cd Merge pull request #2432 from ChanningHe/feat-integration-api-domain-crud
feat(integration): add domain CRUD endpoints to integration API
2026-03-01 11:12:05 -08:00
Owen Schwartz
44e3eedffa Merge pull request #2567 from marcschaeferger/fix-kubernetes-install
feat(kubernetes): enable newtInstances by default and update installation instructions
2026-03-01 10:56:18 -08:00
Marc Schäfer
bb189874cb fix(newt-install): conditionally display Kubernetes installation info
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 10:55:58 -08:00
Marc Schäfer
34dadd0e16 feat(kubernetes): enable newtInstances by default and update installation instructions
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 10:55:58 -08:00
Owen Schwartz
87b5cd9988 Merge pull request #2573 from Fizza-Mukhtar/fix/container-search-excludes-labels-2228
fix: exclude labels from container search to prevent false positives
2026-03-01 10:52:50 -08:00
Marc Schäfer
6a537a23e8 fix(newt-install): conditionally display Kubernetes installation info
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-03-01 18:17:45 +01:00
Fizza-Mukhtar
e63a6e9b77 fix: treat local and wireguard sites as online for failover 2026-03-01 07:56:47 -08:00
Fizza-Mukhtar
7ce589c4f2 fix: exclude labels from container search to prevent false positives 2026-03-01 06:50:03 -08:00
Fizza-Mukhtar
f36cf06e26 fix: fallback to local targets when newt targets are unhealthy 2026-03-01 01:43:15 -08:00
Marc Schäfer
375211f184 feat(kubernetes): enable newtInstances by default and update installation instructions
Signed-off-by: Marc Schäfer <git@marcschaeferger.de>
2026-02-28 23:56:28 +01:00
Laurence
81c1a1da9c enhance(sidebar): make mobile org selector sticky
Make org selector sticky on mobile sidebar

  Move OrgSelector outside the scrollable container so it stays fixed
  at the top while menu items scroll, matching the desktop sidebar
  behavior introduced in 9b2c0d0b.
2026-02-26 15:45:41 +00:00
ChanningHe
52f26396ac feat(integration): add domain CRUD endpoints to integration API 2026-02-26 08:44:55 +09:00
127 changed files with 481 additions and 308 deletions

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Получаване на потребител",
"actionGetOrgUser": "Вземете потребител на организация",
"actionListOrgDomains": "Изброяване на домейни на организация",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Създаване на сайт",
"actionDeleteSite": "Изтриване на сайта",
"actionGetSite": "Вземете сайт",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Потребителят може да изпълнява само определени команди с sudo.",
"sshSudo": "Разреши sudo",
"sshSudoCommands": "Sudo команди",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Списък с команди, които потребителят е разрешено да изпълнява с sudo.",
"sshCreateHomeDir": "Създай начална директория",
"sshUnixGroups": "Unix групи",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix групи, в които да добавите потребителя на целевия хост.",
"retryAttempts": "Опити за повторно",
"expectedResponseCodes": "Очаквани кодове за отговор",
"expectedResponseCodesDescription": "HTTP статус код, указващ здравословно състояние. Ако бъде оставено празно, между 200-300 се счита за здравословно.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Získat uživatele",
"actionGetOrgUser": "Získat uživatele organizace",
"actionListOrgDomains": "Seznam domén organizace",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Vytvořit lokalitu",
"actionDeleteSite": "Odstranění lokality",
"actionGetSite": "Získat web",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Uživatel může spustit pouze zadané příkazy s sudo.",
"sshSudo": "Povolit sudo",
"sshSudoCommands": "Sudo příkazy",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Seznam příkazů, které může uživatel spouštět s sudo.",
"sshCreateHomeDir": "Vytvořit domovský adresář",
"sshUnixGroups": "Unixové skupiny",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix skupiny přidají uživatele do cílového hostitele.",
"retryAttempts": "Opakovat pokusy",
"expectedResponseCodes": "Očekávané kódy odezvy",
"expectedResponseCodesDescription": "HTTP kód stavu, který označuje zdravý stav. Ponecháte-li prázdné, 200-300 je považováno za zdravé.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Benutzer abrufen",
"actionGetOrgUser": "Organisationsbenutzer abrufen",
"actionListOrgDomains": "Organisationsdomains auflisten",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Standort erstellen",
"actionDeleteSite": "Standort löschen",
"actionGetSite": "Standort abrufen",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Benutzer kann nur die angegebenen Befehle mit sudo ausführen.",
"sshSudo": "sudo erlauben",
"sshSudoCommands": "Sudo-Befehle",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Liste der Befehle, die der Benutzer mit sudo ausführen darf.",
"sshCreateHomeDir": "Home-Verzeichnis erstellen",
"sshUnixGroups": "Unix-Gruppen",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix-Gruppen, zu denen der Benutzer auf dem Ziel-Host hinzugefügt wird.",
"retryAttempts": "Wiederholungsversuche",
"expectedResponseCodes": "Erwartete Antwortcodes",
"expectedResponseCodesDescription": "HTTP-Statuscode, der einen gesunden Zustand anzeigt. Wenn leer gelassen, wird 200-300 als gesund angesehen.",

View File

@@ -1102,6 +1102,12 @@
"actionGetUser": "Get User",
"actionGetOrgUser": "Get Organization User",
"actionListOrgDomains": "List Organization Domains",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Create Site",
"actionDeleteSite": "Delete Site",
"actionGetSite": "Get Site",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Obtener usuario",
"actionGetOrgUser": "Obtener usuario de la organización",
"actionListOrgDomains": "Listar dominios de la organización",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Crear sitio",
"actionDeleteSite": "Eliminar sitio",
"actionGetSite": "Obtener sitio",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "El usuario sólo puede ejecutar los comandos especificados con sudo.",
"sshSudo": "Permitir sudo",
"sshSudoCommands": "Comandos Sudo",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Lista de comandos que el usuario puede ejecutar con sudo.",
"sshCreateHomeDir": "Crear directorio principal",
"sshUnixGroups": "Grupos Unix",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Grupos Unix para agregar el usuario en el host de destino.",
"retryAttempts": "Intentos de Reintento",
"expectedResponseCodes": "Códigos de respuesta esperados",
"expectedResponseCodesDescription": "Código de estado HTTP que indica un estado saludable. Si se deja en blanco, se considera saludable de 200 a 300.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Obtenir l'utilisateur",
"actionGetOrgUser": "Obtenir l'utilisateur de l'organisation",
"actionListOrgDomains": "Lister les domaines de l'organisation",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Créer un site",
"actionDeleteSite": "Supprimer un site",
"actionGetSite": "Obtenir un site",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "L'utilisateur ne peut exécuter que les commandes spécifiées avec sudo.",
"sshSudo": "Autoriser sudo",
"sshSudoCommands": "Commandes Sudo",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Liste des commandes que l'utilisateur est autorisé à exécuter avec sudo.",
"sshCreateHomeDir": "Créer un répertoire personnel",
"sshUnixGroups": "Groupes Unix",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Groupes Unix à ajouter à l'utilisateur sur l'hôte cible.",
"retryAttempts": "Tentatives de réessai",
"expectedResponseCodes": "Codes de réponse attendus",
"expectedResponseCodesDescription": "Code de statut HTTP indiquant un état de santé satisfaisant. Si non renseigné, 200-300 est considéré comme satisfaisant.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Ottieni Utente",
"actionGetOrgUser": "Ottieni Utente Organizzazione",
"actionListOrgDomains": "Elenca Domini Organizzazione",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Crea Sito",
"actionDeleteSite": "Elimina Sito",
"actionGetSite": "Ottieni Sito",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "L'utente può eseguire solo i comandi specificati con sudo.",
"sshSudo": "Consenti sudo",
"sshSudoCommands": "Comandi Sudo",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Elenco di comandi che l'utente può eseguire con sudo.",
"sshCreateHomeDir": "Crea Cartella Home",
"sshUnixGroups": "Gruppi Unix",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Gruppi Unix su cui aggiungere l'utente sull'host di destinazione.",
"retryAttempts": "Tentativi di Riprova",
"expectedResponseCodes": "Codici di Risposta Attesi",
"expectedResponseCodesDescription": "Codice di stato HTTP che indica lo stato di salute. Se lasciato vuoto, considerato sano è compreso tra 200-300.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "사용자 조회",
"actionGetOrgUser": "조직 사용자 가져오기",
"actionListOrgDomains": "조직 도메인 목록",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "사이트 생성",
"actionDeleteSite": "사이트 삭제",
"actionGetSite": "사이트 가져오기",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "사용자는 sudo로 지정된 명령만 실행할 수 있습니다.",
"sshSudo": "Sudo 허용",
"sshSudoCommands": "Sudo 명령",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "사용자가 sudo로 실행할 수 있도록 허용된 명령 목록입니다.",
"sshCreateHomeDir": "홈 디렉터리 생성",
"sshUnixGroups": "유닉스 그룹",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "대상 호스트에서 사용자를 추가할 유닉스 그룹입니다.",
"retryAttempts": "재시도 횟수",
"expectedResponseCodes": "예상 응답 코드",
"expectedResponseCodesDescription": "정상 상태를 나타내는 HTTP 상태 코드입니다. 비워 두면 200-300이 정상으로 간주됩니다.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Hent bruker",
"actionGetOrgUser": "Hent organisasjonsbruker",
"actionListOrgDomains": "List opp organisasjonsdomener",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Opprett område",
"actionDeleteSite": "Slett område",
"actionGetSite": "Hent område",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Brukeren kan bare kjøre de angitte kommandoene med sudo.",
"sshSudo": "Tillat sudo",
"sshSudoCommands": "Sudo kommandoer",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Liste av kommandoer brukeren har lov til å kjøre med sudo.",
"sshCreateHomeDir": "Opprett hjemmappe",
"sshUnixGroups": "Unix grupper",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix grupper for å legge til brukeren til målverten.",
"retryAttempts": "Forsøk på nytt",
"expectedResponseCodes": "Forventede svarkoder",
"expectedResponseCodesDescription": "HTTP-statuskode som indikerer sunn status. Hvis den blir stående tom, regnes 200-300 som sunn.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Gebruiker ophalen",
"actionGetOrgUser": "Krijg organisatie-gebruiker",
"actionListOrgDomains": "Lijst organisatie domeinen",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Site aanmaken",
"actionDeleteSite": "Site verwijderen",
"actionGetSite": "Site ophalen",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Gebruiker kan alleen de opgegeven commando's uitvoeren met de sudo.",
"sshSudo": "sudo toestaan",
"sshSudoCommands": "Sudo Commando's",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Lijst van commando's die de gebruiker mag uitvoeren met een sudo.",
"sshCreateHomeDir": "Maak Home Directory",
"sshUnixGroups": "Unix groepen",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix groepen om de gebruiker toe te voegen aan de doel host.",
"retryAttempts": "Herhaal Pogingen",
"expectedResponseCodes": "Verwachte Reactiecodes",
"expectedResponseCodesDescription": "HTTP-statuscode die gezonde status aangeeft. Indien leeg wordt 200-300 als gezond beschouwd.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Pobierz użytkownika",
"actionGetOrgUser": "Pobierz użytkownika organizacji",
"actionListOrgDomains": "Lista domen organizacji",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Utwórz witrynę",
"actionDeleteSite": "Usuń witrynę",
"actionGetSite": "Pobierz witrynę",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Użytkownik może uruchamiać tylko określone polecenia z sudo.",
"sshSudo": "Zezwól na sudo",
"sshSudoCommands": "Komendy Sudo",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Lista poleceń, które użytkownik może uruchamiać z sudo.",
"sshCreateHomeDir": "Utwórz katalog domowy",
"sshUnixGroups": "Grupy Unix",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Grupy Unix do dodania użytkownika do docelowego hosta.",
"retryAttempts": "Próby Ponowienia",
"expectedResponseCodes": "Oczekiwane Kody Odpowiedzi",
"expectedResponseCodesDescription": "Kod statusu HTTP, który wskazuje zdrowy status. Jeśli pozostanie pusty, uznaje się 200-300 za zdrowy.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Obter Usuário",
"actionGetOrgUser": "Obter Utilizador da Organização",
"actionListOrgDomains": "Listar Domínios da Organização",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Criar Site",
"actionDeleteSite": "Eliminar Site",
"actionGetSite": "Obter Site",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Usuário só pode executar os comandos especificados com sudo.",
"sshSudo": "Permitir sudo",
"sshSudoCommands": "Comandos Sudo",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Lista de comandos com permissão de executar com o sudo.",
"sshCreateHomeDir": "Criar Diretório Inicial",
"sshUnixGroups": "Grupos Unix",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Grupos Unix para adicionar o usuário no host de destino.",
"retryAttempts": "Tentativas de Repetição",
"expectedResponseCodes": "Códigos de Resposta Esperados",
"expectedResponseCodesDescription": "Código de status HTTP que indica estado saudável. Se deixado em branco, 200-300 é considerado saudável.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Получить пользователя",
"actionGetOrgUser": "Получить пользователя организации",
"actionListOrgDomains": "Список доменов организации",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Создать сайт",
"actionDeleteSite": "Удалить сайт",
"actionGetSite": "Получить сайт",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Пользователь может запускать только указанные команды с помощью sudo.",
"sshSudo": "Разрешить sudo",
"sshSudoCommands": "Sudo Команды",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Список команд, которые пользователю разрешено запускать с помощью sudo.",
"sshCreateHomeDir": "Создать домашний каталог",
"sshUnixGroups": "Unix группы",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Unix группы для добавления пользователя на целевой хост.",
"retryAttempts": "Количество попыток повторного запроса",
"expectedResponseCodes": "Ожидаемые коды ответов",
"expectedResponseCodesDescription": "HTTP-код состояния, указывающий на здоровое состояние. Если оставить пустым, 200-300 считается здоровым.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "Kullanıcıyı Getir",
"actionGetOrgUser": "Kuruluş Kullanıcısını Al",
"actionListOrgDomains": "Kuruluş Alan Adlarını Listele",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "Site Oluştur",
"actionDeleteSite": "Siteyi Sil",
"actionGetSite": "Siteyi Al",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "Kullanıcı sadece belirtilen komutları sudo ile çalıştırabilir.",
"sshSudo": "Sudo'ya izin ver",
"sshSudoCommands": "Sudo Komutları",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "Kullanıcının sudo ile çalıştırmasına izin verilen komutların listesi.",
"sshCreateHomeDir": "Ev Dizini Oluştur",
"sshUnixGroups": "Unix Grupları",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "Hedef ana bilgisayarda kullanıcıya eklemek için Unix grupları.",
"retryAttempts": "Tekrar Deneme Girişimleri",
"expectedResponseCodes": "Beklenen Yanıt Kodları",
"expectedResponseCodesDescription": "Sağlıklı durumu gösteren HTTP durum kodu. Boş bırakılırsa, 200-300 arası sağlıklı kabul edilir.",

View File

@@ -1101,12 +1101,6 @@
"actionGetUser": "获取用户",
"actionGetOrgUser": "获取组织用户",
"actionListOrgDomains": "列出组织域",
"actionGetDomain": "Get Domain",
"actionCreateOrgDomain": "Create Domain",
"actionUpdateOrgDomain": "Update Domain",
"actionDeleteOrgDomain": "Delete Domain",
"actionGetDNSRecords": "Get DNS Records",
"actionRestartOrgDomain": "Restart Domain",
"actionCreateSite": "创建站点",
"actionDeleteSite": "删除站点",
"actionGetSite": "获取站点",
@@ -1675,10 +1669,10 @@
"sshSudoModeCommandsDescription": "用户只能用 sudo 运行指定的命令。",
"sshSudo": "允许Sudo",
"sshSudoCommands": "Sudo 命令",
"sshSudoCommandsDescription": "Comma separated list of commands the user is allowed to run with sudo.",
"sshSudoCommandsDescription": "允许用户使用 sudo 运行的命令列表。",
"sshCreateHomeDir": "创建主目录",
"sshUnixGroups": "Unix 组",
"sshUnixGroupsDescription": "Comma separated Unix groups to add the user to on the target host.",
"sshUnixGroupsDescription": "将用户添加到目标主机的Unix组。",
"retryAttempts": "重试次数",
"expectedResponseCodes": "期望响应代码",
"expectedResponseCodesDescription": "HTTP 状态码表示健康状态。如留空200-300 被视为健康。",

View File

@@ -17,6 +17,7 @@ import fs from "fs";
import path from "path";
import { APP_PATH } from "./lib/consts";
import yaml from "js-yaml";
import { z } from "zod";
const dev = process.env.ENVIRONMENT !== "prod";
const externalPort = config.getRawConfig().server.integration_port;
@@ -38,12 +39,24 @@ export function createIntegrationApiServer() {
apiServer.use(cookieParser());
apiServer.use(express.json());
const openApiDocumentation = getOpenApiDocumentation();
apiServer.use(
"/v1/docs",
swaggerUi.serve,
swaggerUi.setup(getOpenApiDocumentation())
swaggerUi.setup(openApiDocumentation)
);
// Unauthenticated OpenAPI spec endpoints
apiServer.get("/v1/openapi.json", (_req, res) => {
res.json(openApiDocumentation);
});
apiServer.get("/v1/openapi.yaml", (_req, res) => {
const yamlOutput = yaml.dump(openApiDocumentation);
res.type("application/yaml").send(yamlOutput);
});
// API routes
const prefix = `/v1`;
apiServer.use(logIncomingMiddleware);
@@ -75,16 +88,6 @@ function getOpenApiDocumentation() {
}
);
for (const def of registry.definitions) {
if (def.type === "route") {
def.route.security = [
{
[bearerAuth.name]: []
}
];
}
}
registry.registerPath({
method: "get",
path: "/",
@@ -94,6 +97,74 @@ function getOpenApiDocumentation() {
responses: {}
});
registry.registerPath({
method: "get",
path: "/openapi.json",
description: "Get OpenAPI specification as JSON",
tags: [],
request: {},
responses: {
"200": {
description: "OpenAPI specification as JSON",
content: {
"application/json": {
schema: {
type: "object"
}
}
}
}
}
});
registry.registerPath({
method: "get",
path: "/openapi.yaml",
description: "Get OpenAPI specification as YAML",
tags: [],
request: {},
responses: {
"200": {
description: "OpenAPI specification as YAML",
content: {
"application/yaml": {
schema: {
type: "string"
}
}
}
}
}
});
for (const def of registry.definitions) {
if (def.type === "route") {
def.route.security = [
{
[bearerAuth.name]: []
}
];
// Ensure every route has a generic JSON response schema so Swagger UI can render responses
const existingResponses = def.route.responses;
const hasExistingResponses =
existingResponses && Object.keys(existingResponses).length > 0;
if (!hasExistingResponses) {
def.route.responses = {
"*": {
description: "",
content: {
"application/json": {
schema: z.object({})
}
}
}
};
}
}
}
const generator = new OpenApiGeneratorV3(registry.definitions);
const generated = generator.generateDocument({

View File

@@ -477,7 +477,10 @@ export async function getTraefikConfig(
// TODO: HOW TO HANDLE ^^^^^^ BETTER
const anySitesOnline = targets.some(
(target) => target.site.online
(target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
);
return (
@@ -490,7 +493,7 @@ export async function getTraefikConfig(
if (target.health == "unhealthy") {
return false;
}
// If any sites are online, exclude offline sites
if (anySitesOnline && !target.site.online) {
return false;
@@ -605,7 +608,10 @@ export async function getTraefikConfig(
servers: (() => {
// Check if any sites are online
const anySitesOnline = targets.some(
(target) => target.site.online
(target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
);
return targets
@@ -613,7 +619,7 @@ export async function getTraefikConfig(
if (!target.enabled) {
return false;
}
// If any sites are online, exclude offline sites
if (anySitesOnline && !target.site.online) {
return false;

View File

@@ -14,3 +14,4 @@ export * from "./verifyApiKeyApiKeyAccess";
export * from "./verifyApiKeyClientAccess";
export * from "./verifyApiKeySiteResourceAccess";
export * from "./verifyApiKeyIdpAccess";
export * from "./verifyApiKeyDomainAccess";

View File

@@ -0,0 +1,90 @@
import { Request, Response, NextFunction } from "express";
import { db, domains, orgDomains, apiKeyOrg } from "@server/db";
import { and, eq } from "drizzle-orm";
import createHttpError from "http-errors";
import HttpCode from "@server/types/HttpCode";
export async function verifyApiKeyDomainAccess(
req: Request,
res: Response,
next: NextFunction
) {
try {
const apiKey = req.apiKey;
const domainId =
req.params.domainId || req.body.domainId || req.query.domainId;
const orgId = req.params.orgId;
if (!apiKey) {
return next(
createHttpError(HttpCode.UNAUTHORIZED, "Key not authenticated")
);
}
if (!domainId) {
return next(
createHttpError(HttpCode.BAD_REQUEST, "Invalid domain ID")
);
}
if (apiKey.isRoot) {
// Root keys can access any domain in any org
return next();
}
// Verify domain exists and belongs to the organization
const [domain] = await db
.select()
.from(domains)
.innerJoin(orgDomains, eq(orgDomains.domainId, domains.domainId))
.where(
and(
eq(orgDomains.domainId, domainId),
eq(orgDomains.orgId, orgId)
)
)
.limit(1);
if (!domain) {
return next(
createHttpError(
HttpCode.NOT_FOUND,
`Domain with ID ${domainId} not found in organization ${orgId}`
)
);
}
// Verify the API key has access to this organization
if (!req.apiKeyOrg) {
const apiKeyOrgRes = await db
.select()
.from(apiKeyOrg)
.where(
and(
eq(apiKeyOrg.apiKeyId, apiKey.apiKeyId),
eq(apiKeyOrg.orgId, orgId)
)
)
.limit(1);
req.apiKeyOrg = apiKeyOrgRes[0];
}
if (!req.apiKeyOrg) {
return next(
createHttpError(
HttpCode.FORBIDDEN,
"Key does not have access to this organization"
)
);
}
return next();
} catch (error) {
return next(
createHttpError(
HttpCode.INTERNAL_SERVER_ERROR,
"Error verifying domain access"
)
);
}
}

View File

@@ -5,17 +5,20 @@ export const registry = new OpenAPIRegistry();
export enum OpenAPITags {
Site = "Site",
Org = "Organization",
Resource = "Resource",
PublicResource = "Public Resource",
PrivateResource = "Private Resource",
Role = "Role",
User = "User",
Invitation = "Invitation",
Target = "Target",
Invitation = "User Invitation",
Target = "Resource Target",
Rule = "Rule",
AccessToken = "Access Token",
Idp = "Identity Provider",
GlobalIdp = "Identity Provider (Global)",
OrgIdp = "Identity Provider (Organization Only)",
Client = "Client",
ApiKey = "API Key",
Domain = "Domain",
Blueprint = "Blueprint",
Ssh = "SSH"
Ssh = "SSH",
Logs = "Logs"
}

View File

@@ -665,7 +665,10 @@ export async function getTraefikConfig(
// TODO: HOW TO HANDLE ^^^^^^ BETTER
const anySitesOnline = targets.some(
(target) => target.site.online
(target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
);
return (
@@ -793,7 +796,10 @@ export async function getTraefikConfig(
servers: (() => {
// Check if any sites are online
const anySitesOnline = targets.some(
(target) => target.site.online
(target) =>
target.site.online ||
target.site.type === "local" ||
target.site.type === "wireguard"
);
return targets

View File

@@ -32,7 +32,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/access/export",
description: "Export the access audit log for an organization as CSV",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryAccessAuditLogsQuery,
params: queryAccessAuditLogsParams

View File

@@ -32,7 +32,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/action/export",
description: "Export the action audit log for an organization as CSV",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryActionAuditLogsQuery,
params: queryActionAuditLogsParams

View File

@@ -249,7 +249,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/access",
description: "Query the access audit log for an organization",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryAccessAuditLogsQuery,
params: queryAccessAuditLogsParams

View File

@@ -160,7 +160,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/action",
description: "Query the action audit log for an organization",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryActionAuditLogsQuery,
params: queryActionAuditLogsParams

View File

@@ -31,16 +31,16 @@ const getOrgSchema = z.strictObject({
orgId: z.string()
});
registry.registerPath({
method: "get",
path: "/org/{orgId}/billing/usage",
description: "Get an organization's billing usage",
tags: [OpenAPITags.Org],
request: {
params: getOrgSchema
},
responses: {}
});
// registry.registerPath({
// method: "get",
// path: "/org/{orgId}/billing/usage",
// description: "Get an organization's billing usage",
// tags: [OpenAPITags.Org],
// request: {
// params: getOrgSchema
// },
// responses: {}
// });
export async function getOrgUsage(
req: Request,

View File

@@ -52,7 +52,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/idp/oidc",
description: "Create an OIDC IdP for a specific organization.",
tags: [OpenAPITags.Idp, OpenAPITags.Org],
tags: [OpenAPITags.OrgIdp],
request: {
params: paramsSchema,
body: {

View File

@@ -35,7 +35,7 @@ registry.registerPath({
method: "delete",
path: "/org/{orgId}/idp/{idpId}",
description: "Delete IDP for a specific organization.",
tags: [OpenAPITags.Idp, OpenAPITags.Org],
tags: [OpenAPITags.OrgIdp],
request: {
params: paramsSchema
},

View File

@@ -50,9 +50,9 @@ async function query(idpId: number, orgId: string) {
registry.registerPath({
method: "get",
path: "/org/:orgId/idp/:idpId",
path: "/org/{orgId}/idp/{idpId}",
description: "Get an IDP by its IDP ID for a specific organization.",
tags: [OpenAPITags.Idp, OpenAPITags.Org],
tags: [OpenAPITags.OrgIdp],
request: {
params: paramsSchema
},

View File

@@ -67,7 +67,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/idp",
description: "List all IDP for a specific organization.",
tags: [OpenAPITags.Idp, OpenAPITags.Org],
tags: [OpenAPITags.OrgIdp],
request: {
query: querySchema,
params: paramsSchema

View File

@@ -59,7 +59,7 @@ registry.registerPath({
method: "post",
path: "/org/{orgId}/idp/{idpId}/oidc",
description: "Update an OIDC IdP for a specific organization.",
tags: [OpenAPITags.Idp, OpenAPITags.Org],
tags: [OpenAPITags.OrgIdp],
request: {
params: paramsSchema,
body: {

View File

@@ -52,7 +52,7 @@ registry.registerPath({
method: "get",
path: "/maintenance/info",
description: "Get maintenance information for a resource by domain.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
query: z.object({
fullDomain: z.string()

View File

@@ -43,7 +43,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/access-token",
description: "Generate a new access token for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.AccessToken],
tags: [OpenAPITags.PublicResource, OpenAPITags.AccessToken],
request: {
params: generateAccssTokenParamsSchema,
body: {

View File

@@ -122,7 +122,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/access-tokens",
description: "List all access tokens in an organization.",
tags: [OpenAPITags.Org, OpenAPITags.AccessToken],
tags: [OpenAPITags.AccessToken],
request: {
params: z.object({
orgId: z.string()
@@ -135,8 +135,8 @@ registry.registerPath({
registry.registerPath({
method: "get",
path: "/resource/{resourceId}/access-tokens",
description: "List all access tokens in an organization.",
tags: [OpenAPITags.Resource, OpenAPITags.AccessToken],
description: "List all access tokens for a resource.",
tags: [OpenAPITags.PublicResource, OpenAPITags.AccessToken],
request: {
params: z.object({
resourceId: z.number()

View File

@@ -37,7 +37,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/api-key",
description: "Create a new API key scoped to the organization.",
tags: [OpenAPITags.Org, OpenAPITags.ApiKey],
tags: [OpenAPITags.ApiKey],
request: {
params: paramsSchema,
body: {

View File

@@ -18,7 +18,7 @@ registry.registerPath({
method: "delete",
path: "/org/{orgId}/api-key/{apiKeyId}",
description: "Delete an API key.",
tags: [OpenAPITags.Org, OpenAPITags.ApiKey],
tags: [OpenAPITags.ApiKey],
request: {
params: paramsSchema
},

View File

@@ -48,7 +48,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/api-key/{apiKeyId}/actions",
description: "List all actions set for an API key.",
tags: [OpenAPITags.Org, OpenAPITags.ApiKey],
tags: [OpenAPITags.ApiKey],
request: {
params: paramsSchema,
query: querySchema

View File

@@ -52,7 +52,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/api-keys",
description: "List all API keys for an organization",
tags: [OpenAPITags.Org, OpenAPITags.ApiKey],
tags: [OpenAPITags.ApiKey],
request: {
params: paramsSchema,
query: querySchema

View File

@@ -25,7 +25,7 @@ registry.registerPath({
path: "/org/{orgId}/api-key/{apiKeyId}/actions",
description:
"Set actions for an API key. This will replace any existing actions.",
tags: [OpenAPITags.Org, OpenAPITags.ApiKey],
tags: [OpenAPITags.ApiKey],
request: {
params: paramsSchema,
body: {

View File

@@ -20,7 +20,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/request",
description: "Query the request audit log for an organization",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryAccessAuditLogsQuery.omit({
limit: true,

View File

@@ -151,7 +151,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/analytics",
description: "Query the request audit analytics for an organization",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryAccessAuditLogsQuery,
params: queryRequestAuditLogsParams

View File

@@ -182,7 +182,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/logs/request",
description: "Query the request audit log for an organization",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Logs],
request: {
query: queryAccessAuditLogsQuery,
params: queryRequestAuditLogsParams

View File

@@ -20,7 +20,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/blueprint",
description: "Apply a base64 encoded JSON blueprint to an organization",
tags: [OpenAPITags.Org, OpenAPITags.Blueprint],
tags: [OpenAPITags.Blueprint],
request: {
params: applyBlueprintParamsSchema,
body: {

View File

@@ -43,7 +43,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/blueprint",
description: "Create and apply a YAML blueprint to an organization",
tags: [OpenAPITags.Org, OpenAPITags.Blueprint],
tags: [OpenAPITags.Blueprint],
request: {
params: applyBlueprintParamsSchema,
body: {

View File

@@ -53,7 +53,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/blueprint/{blueprintId}",
description: "Get a blueprint by its blueprint ID.",
tags: [OpenAPITags.Org, OpenAPITags.Blueprint],
tags: [OpenAPITags.Blueprint],
request: {
params: getBlueprintSchema
},

View File

@@ -67,7 +67,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/blueprints",
description: "List all blueprints for a organization.",
tags: [OpenAPITags.Org, OpenAPITags.Blueprint],
tags: [OpenAPITags.Blueprint],
request: {
params: z.object({
orgId: z.string()

View File

@@ -48,7 +48,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/client",
description: "Create a new client for an organization.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.Client],
request: {
params: createClientParamsSchema,
body: {

View File

@@ -49,7 +49,7 @@ registry.registerPath({
path: "/org/{orgId}/user/{userId}/client",
description:
"Create a new client for a user and associate it with an existing olm.",
tags: [OpenAPITags.Client, OpenAPITags.Org, OpenAPITags.User],
tags: [OpenAPITags.Client],
request: {
params: paramsSchema,
body: {

View File

@@ -243,7 +243,7 @@ registry.registerPath({
path: "/org/{orgId}/client/{niceId}",
description:
"Get a client by orgId and niceId. NiceId is a readable ID for the site and unique on a per org basis.",
tags: [OpenAPITags.Org, OpenAPITags.Site],
tags: [OpenAPITags.Site],
request: {
params: z.object({
orgId: z.string(),

View File

@@ -237,7 +237,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/clients",
description: "List all clients for an organization.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.Client],
request: {
query: listClientsSchema,
params: listClientsParamsSchema

View File

@@ -256,7 +256,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/user-devices",
description: "List all user devices for an organization.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.Client],
request: {
query: listUserDevicesSchema,
params: listUserDevicesParamsSchema

View File

@@ -23,7 +23,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/pick-client-defaults",
description: "Return pre-requisite data for creating a client.",
tags: [OpenAPITags.Client, OpenAPITags.Site],
tags: [OpenAPITags.Client],
request: {
params: pickClientDefaultsSchema
},

View File

@@ -59,7 +59,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/domains",
description: "List all domains for a organization.",
tags: [OpenAPITags.Org],
tags: [OpenAPITags.Domain],
request: {
params: z.object({
orgId: z.string()

View File

@@ -27,7 +27,7 @@ registry.registerPath({
method: "put",
path: "/idp/{idpId}/org/{orgId}",
description: "Create an IDP policy for an existing IDP on an organization.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema,
body: {

View File

@@ -37,7 +37,7 @@ registry.registerPath({
method: "put",
path: "/idp/oidc",
description: "Create an OIDC IdP.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
body: {
content: {

View File

@@ -21,7 +21,7 @@ registry.registerPath({
method: "delete",
path: "/idp/{idpId}",
description: "Delete IDP.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema
},

View File

@@ -19,7 +19,7 @@ registry.registerPath({
method: "delete",
path: "/idp/{idpId}/org/{orgId}",
description: "Create an OIDC IdP for an organization.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema
},

View File

@@ -34,7 +34,7 @@ registry.registerPath({
method: "get",
path: "/idp/{idpId}",
description: "Get an IDP by its IDP ID.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema
},

View File

@@ -48,7 +48,7 @@ registry.registerPath({
method: "get",
path: "/idp/{idpId}/org",
description: "List all org policies on an IDP.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema,
query: querySchema

View File

@@ -58,7 +58,7 @@ registry.registerPath({
method: "get",
path: "/idp",
description: "List all IDP in the system.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
query: querySchema
},

View File

@@ -26,7 +26,7 @@ registry.registerPath({
method: "post",
path: "/idp/{idpId}/org/{orgId}",
description: "Update an IDP org policy.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema,
body: {

View File

@@ -42,7 +42,7 @@ registry.registerPath({
method: "post",
path: "/idp/{idpId}/oidc",
description: "Update an OIDC IdP.",
tags: [OpenAPITags.Idp],
tags: [OpenAPITags.GlobalIdp],
request: {
params: paramsSchema,
body: {

View File

@@ -27,7 +27,8 @@ import {
verifyApiKeyClientAccess,
verifyApiKeySiteResourceAccess,
verifyApiKeySetResourceClients,
verifyLimits
verifyLimits,
verifyApiKeyDomainAccess
} from "@server/middlewares";
import HttpCode from "@server/types/HttpCode";
import { Router } from "express";
@@ -347,6 +348,56 @@ authenticated.get(
domain.listDomains
);
authenticated.get(
"/org/:orgId/domain/:domainId",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.getDomain),
domain.getDomain
);
authenticated.put(
"/org/:orgId/domain",
verifyApiKeyOrgAccess,
verifyApiKeyHasAction(ActionsEnum.createOrgDomain),
logActionAudit(ActionsEnum.createOrgDomain),
domain.createOrgDomain
);
authenticated.patch(
"/org/:orgId/domain/:domainId",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.updateOrgDomain),
domain.updateOrgDomain
);
authenticated.delete(
"/org/:orgId/domain/:domainId",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.deleteOrgDomain),
logActionAudit(ActionsEnum.deleteOrgDomain),
domain.deleteAccountDomain
);
authenticated.get(
"/org/:orgId/domain/:domainId/dns-records",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.getDNSRecords),
domain.getDNSRecords
);
authenticated.post(
"/org/:orgId/domain/:domainId/restart",
verifyApiKeyOrgAccess,
verifyApiKeyDomainAccess,
verifyApiKeyHasAction(ActionsEnum.restartOrgDomain),
logActionAudit(ActionsEnum.restartOrgDomain),
domain.restartOrgDomain
);
authenticated.get(
"/org/:orgId/invitations",
verifyApiKeyOrgAccess,

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist/add",
description: "Add a single email to the resource whitelist.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: addEmailToResourceWhitelistParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles/add",
description: "Add a single role to a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: addRoleToResourceParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users/add",
description: "Add a single user to a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: addUserToResourceParamsSchema,
body: {

View File

@@ -79,7 +79,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/resource",
description: "Create a resource.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: createResourceParamsSchema,
body: {

View File

@@ -31,7 +31,7 @@ registry.registerPath({
method: "put",
path: "/resource/{resourceId}/rule",
description: "Create a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: createResourceRuleParamsSchema,
body: {

View File

@@ -22,7 +22,7 @@ registry.registerPath({
method: "delete",
path: "/resource/{resourceId}",
description: "Delete a resource.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: deleteResourceSchema
},

View File

@@ -19,7 +19,7 @@ registry.registerPath({
method: "delete",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Delete a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: deleteResourceRuleSchema
},

View File

@@ -54,7 +54,7 @@ registry.registerPath({
path: "/org/{orgId}/resource/{niceId}",
description:
"Get a resource by orgId and niceId. NiceId is a readable ID for the resource and unique on a per org basis.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string(),
@@ -68,7 +68,7 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}",
description: "Get a resource by resourceId.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
resourceId: z.number()

View File

@@ -31,7 +31,7 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/whitelist",
description: "Get the whitelist of emails for a specific resource.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: getResourceWhitelistSchema
},

View File

@@ -33,7 +33,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/resources-names",
description: "List all resource names for an organization.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string()

View File

@@ -35,7 +35,7 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/roles",
description: "List all roles for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: listResourceRolesSchema
},

View File

@@ -56,7 +56,7 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/rules",
description: "List rules for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: listResourceRulesParamsSchema,
query: listResourceRulesSchema

View File

@@ -38,7 +38,7 @@ registry.registerPath({
method: "get",
path: "/resource/{resourceId}/users",
description: "List all users for a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: listResourceUsersSchema
},

View File

@@ -225,7 +225,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/resources",
description: "List resources for an organization.",
tags: [OpenAPITags.Org, OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: z.object({
orgId: z.string()

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/whitelist/remove",
description: "Remove a single email from the resource whitelist.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: removeEmailFromResourceWhitelistParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/roles/remove",
description: "Remove a single role from a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: removeRoleFromResourceParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/users/remove",
description: "Remove a single user from a resource.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: removeUserFromResourceParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
path: "/resource/{resourceId}/header-auth",
description:
"Set or update the header authentication for a resource. If user and password is not provided, it will remove the header authentication.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {

View File

@@ -25,7 +25,7 @@ registry.registerPath({
path: "/resource/{resourceId}/password",
description:
"Set the password for a resource. Setting the password to null will remove it.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {

View File

@@ -29,7 +29,7 @@ registry.registerPath({
path: "/resource/{resourceId}/pincode",
description:
"Set the PIN code for a resource. Setting the PIN code to null will remove it.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceAuthMethodsParamsSchema,
body: {

View File

@@ -23,7 +23,7 @@ registry.registerPath({
path: "/resource/{resourceId}/roles",
description:
"Set roles for a resource. This will replace all existing roles.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
tags: [OpenAPITags.PublicResource, OpenAPITags.Role],
request: {
params: setResourceRolesParamsSchema,
body: {

View File

@@ -23,7 +23,7 @@ registry.registerPath({
path: "/resource/{resourceId}/users",
description:
"Set users for a resource. This will replace all existing users.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
tags: [OpenAPITags.PublicResource, OpenAPITags.User],
request: {
params: setUserResourcesParamsSchema,
body: {

View File

@@ -32,7 +32,7 @@ registry.registerPath({
path: "/resource/{resourceId}/whitelist",
description:
"Set email whitelist for a resource. This will replace all existing emails.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: setResourceWhitelistParamsSchema,
body: {

View File

@@ -136,7 +136,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}",
description: "Update a resource.",
tags: [OpenAPITags.Resource],
tags: [OpenAPITags.PublicResource],
request: {
params: updateResourceParamsSchema,
body: {

View File

@@ -38,7 +38,7 @@ registry.registerPath({
method: "post",
path: "/resource/{resourceId}/rule/{ruleId}",
description: "Update a resource rule.",
tags: [OpenAPITags.Resource, OpenAPITags.Rule],
tags: [OpenAPITags.PublicResource, OpenAPITags.Rule],
request: {
params: updateResourceRuleParamsSchema,
body: {

View File

@@ -45,7 +45,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/role",
description: "Create a role.",
tags: [OpenAPITags.Org, OpenAPITags.Role],
tags: [OpenAPITags.Role],
request: {
params: createRoleParamsSchema,
body: {

View File

@@ -7,7 +7,7 @@ import { and, eq, inArray, sql } from "drizzle-orm";
import { ActionsEnum } from "@server/auth/actions";
import { NextFunction, Request, Response } from "express";
import createHttpError from "http-errors";
import { z } from "zod";
import { object, z } from "zod";
import { fromError } from "zod-validation-error";
const listRolesParamsSchema = z.strictObject({
@@ -64,7 +64,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/roles",
description: "List roles.",
tags: [OpenAPITags.Org, OpenAPITags.Role],
tags: [OpenAPITags.Role],
request: {
params: listRolesParamsSchema,
query: listRolesSchema

View File

@@ -58,7 +58,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/site",
description: "Create a new site.",
tags: [OpenAPITags.Site, OpenAPITags.Org],
tags: [OpenAPITags.Site],
request: {
params: createSiteParamsSchema,
body: {
@@ -292,7 +292,7 @@ export async function createSite(
if (type == "newt") {
[newSite] = await trx
.insert(sites)
.values({
.values({ // NOTE: NO SUBNET OR EXIT NODE ID PASSED IN HERE BECAUSE ITS NOW CHOSEN ON CONNECT
orgId,
name,
niceId,

View File

@@ -51,7 +51,7 @@ registry.registerPath({
path: "/org/{orgId}/site/{niceId}",
description:
"Get a site by orgId and niceId. NiceId is a readable ID for the site and unique on a per org basis.",
tags: [OpenAPITags.Org, OpenAPITags.Site],
tags: [OpenAPITags.Site],
request: {
params: z.object({
orgId: z.string(),

View File

@@ -180,7 +180,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/sites",
description: "List all sites in an organization",
tags: [OpenAPITags.Org, OpenAPITags.Site],
tags: [OpenAPITags.Site],
request: {
params: listSitesParamsSchema,
query: listSitesSchema

View File

@@ -35,7 +35,7 @@ registry.registerPath({
path: "/org/{orgId}/pick-site-defaults",
description:
"Return pre-requisite data for creating a site, such as the exit node, subnet, Newt credentials, etc.",
tags: [OpenAPITags.Org, OpenAPITags.Site],
tags: [OpenAPITags.Site],
request: {
params: z.object({
orgId: z.string()

View File

@@ -30,7 +30,7 @@ registry.registerPath({
path: "/site-resource/{siteResourceId}/clients/add",
description:
"Add a single client to a site resource. Clients with a userId cannot be added.",
tags: [OpenAPITags.Resource, OpenAPITags.Client],
tags: [OpenAPITags.PrivateResource, OpenAPITags.Client],
request: {
params: addClientToSiteResourceParamsSchema,
body: {

View File

@@ -30,7 +30,7 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/roles/add",
description: "Add a single role to a site resource.",
tags: [OpenAPITags.Resource, OpenAPITags.Role],
tags: [OpenAPITags.PrivateResource, OpenAPITags.Role],
request: {
params: addRoleToSiteResourceParamsSchema,
body: {

View File

@@ -30,7 +30,7 @@ registry.registerPath({
method: "post",
path: "/site-resource/{siteResourceId}/users/add",
description: "Add a single user to a site resource.",
tags: [OpenAPITags.Resource, OpenAPITags.User],
tags: [OpenAPITags.PrivateResource, OpenAPITags.User],
request: {
params: addUserToSiteResourceParamsSchema,
body: {

View File

@@ -114,7 +114,7 @@ registry.registerPath({
method: "put",
path: "/org/{orgId}/site-resource",
description: "Create a new site resource.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.PrivateResource],
request: {
params: createSiteResourceParamsSchema,
body: {

View File

@@ -23,7 +23,7 @@ registry.registerPath({
method: "delete",
path: "/site-resource/{siteResourceId}",
description: "Delete a site resource.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.PrivateResource],
request: {
params: deleteSiteResourceParamsSchema
},

View File

@@ -65,7 +65,7 @@ registry.registerPath({
method: "get",
path: "/site-resource/{siteResourceId}",
description: "Get a specific site resource by siteResourceId.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.PrivateResource],
request: {
params: z.object({
siteResourceId: z.number(),
@@ -80,7 +80,7 @@ registry.registerPath({
method: "get",
path: "/org/{orgId}/site/{siteId}/resource/nice/{niceId}",
description: "Get a specific site resource by niceId.",
tags: [OpenAPITags.Client, OpenAPITags.Org],
tags: [OpenAPITags.PrivateResource],
request: {
params: z.object({
niceId: z.string(),

Some files were not shown because too many files have changed in this diff Show More