diff --git a/internal/cmd/server.go b/internal/cmd/server.go index b08dea28ce..1f56162114 100644 --- a/internal/cmd/server.go +++ b/internal/cmd/server.go @@ -91,7 +91,7 @@ func defaultServerOptions(infraDir string) server.Options { SessionDuration: 24 * time.Hour * 30, // 30 days SessionExtensionDeadline: 24 * time.Hour * 3, // 3 days EnableSignup: false, - BaseDomain: "example.com", + BaseDomain: "", Addr: server.ListenerOptions{ HTTP: ":80", diff --git a/internal/cmd/server_test.go b/internal/cmd/server_test.go index 2c483585ae..41f473f2cb 100644 --- a/internal/cmd/server_test.go +++ b/internal/cmd/server_test.go @@ -301,6 +301,7 @@ users: expected.SessionDuration = 3 * time.Minute expected.SessionExtensionDeadline = 1 * time.Minute expected.EnableSignup = false + expected.BaseDomain = "" return expected }, }, diff --git a/internal/server/middleware_test.go b/internal/server/middleware_test.go index 0c8c75b8cd..06ccd01fee 100644 --- a/internal/server/middleware_test.go +++ b/internal/server/middleware_test.go @@ -554,6 +554,7 @@ func TestAuthenticateRequest(t *testing.T) { func TestValidateRequestOrganization(t *testing.T) { srv := setupServer(t, withAdminUser) srv.options.EnableSignup = true // multi-tenant environment + srv.options.BaseDomain = "example.com" routes := srv.GenerateRoutes() org := &models.Organization{ diff --git a/internal/server/server.go b/internal/server/server.go index 058ff1932e..21e81b1ad6 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -124,6 +124,10 @@ func newServer(options Options) *Server { // New creates a Server, and initializes it. The returned Server is ready to run. func New(options Options) (*Server, error) { + if options.EnableSignup && options.BaseDomain == "" { + return nil, errors.New("cannot enable signup without setting base domain") + } + server := newServer(options) if err := importSecrets(options.Secrets, server.secrets); err != nil { diff --git a/internal/server/server_test.go b/internal/server/server_test.go index 8e9691da49..2b10187e1c 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -206,6 +206,7 @@ func TestServer_Run_UIProxy(t *testing.T) { DBEncryptionKey: filepath.Join(dir, "sqlite3.db.key"), TLSCache: filepath.Join(dir, "tlscache"), EnableSignup: true, + BaseDomain: "example.com", TLS: TLSOptions{ CA: types.StringOrFile(golden.Get(t, "pki/ca.crt")), CAPrivateKey: string(golden.Get(t, "pki/ca.key")), @@ -321,6 +322,7 @@ func TestServer_GenerateRoutes_NoRoute(t *testing.T) { func TestServer_PersistSignupUser(t *testing.T) { s := setupServer(t, func(_ *testing.T, opts *Options) { opts.EnableSignup = true + opts.BaseDomain = "example.com" opts.SessionDuration = time.Minute opts.SessionExtensionDeadline = time.Minute }) diff --git a/ui/package-lock.json b/ui/package-lock.json index 6d7c4b225b..bdcc496610 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -9,6 +9,7 @@ "@heroicons/react": "^1.0.6", "copy-to-clipboard": "^3.3.2", "dayjs": "^1.11.5", + "js-yaml": "^4.1.0", "next": "^12.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -2233,8 +2234,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/aria-query": { "version": "4.2.2", @@ -5906,7 +5906,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -9938,8 +9937,7 @@ "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "aria-query": { "version": "4.2.2", @@ -12657,7 +12655,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, "requires": { "argparse": "^2.0.1" } diff --git a/ui/package.json b/ui/package.json index 2836564ee9..824709a297 100644 --- a/ui/package.json +++ b/ui/package.json @@ -16,6 +16,7 @@ "@heroicons/react": "^1.0.6", "copy-to-clipboard": "^3.3.2", "dayjs": "^1.11.5", + "js-yaml": "^4.1.0", "next": "^12.2.5", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/ui/pages/destinations/add.js b/ui/pages/destinations/add.js index 86b6676e5a..9aa9651c46 100644 --- a/ui/pages/destinations/add.js +++ b/ui/pages/destinations/add.js @@ -2,8 +2,23 @@ import Head from 'next/head' import Link from 'next/link' import { useState, useEffect } from 'react' import copy from 'copy-to-clipboard' +import yaml from 'js-yaml' import Fullscreen from '../../components/layouts/fullscreen' +import { useServerConfig } from '../../lib/serverconfig' + +function download(values) { + const blob = new Blob([values], { type: 'application/yaml' }) + const href = URL.createObjectURL(blob) + const link = document.createElement('a') + + link.href = href + link.setAttribute('download', 'values.yaml') + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + URL.revokeObjectURL(href) +} export default function DestinationsAdd() { const [name, setName] = useState('') @@ -11,7 +26,10 @@ export default function DestinationsAdd() { const [submitted, setSubmitted] = useState(false) const [accessKey, setAccessKey] = useState('') const [connected, setConnected] = useState(false) - const [copied, setCopied] = useState(false) + const [valuesDownloaded, setValuesDownloaded] = useState(false) + const [valuesCopied, setValuesCopied] = useState(false) + const [commandCopied, setCommandCopied] = useState(false) + const { baseDomain } = useServerConfig() useEffect(() => { const interval = setInterval(async () => { @@ -66,17 +84,23 @@ export default function DestinationsAdd() { setSubmitted(true) } - const server = window.location.host - let command = `helm install infra-connector infrahq/infra \\ - --set connector.config.accessKey=${accessKey} \\ - --set connector.config.server=${server} \\ - --set connector.config.name=${name}` + const server = baseDomain ? `api.${baseDomain}` : window.location.host + const values = { + connector: { + config: { + server: server, + name: name, + }, + }, + } if (window.location.protocol !== 'https:') { - command += ` \\ - --set connector.config.skipTLSVerify=true` + values.connector.config.skipTLSVerify = true } + const valuesYaml = yaml.dump(values) + const command = `helm upgrade --install infra-connector infrahq/infra --values values.yaml --set connector.config.accessKey=${accessKey}` + return (