diff --git a/apis/installer.go b/apis/installer.go index d8b1a218..16401c9e 100644 --- a/apis/installer.go +++ b/apis/installer.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "runtime" + "strings" "time" "github.com/fatih/color" @@ -16,9 +17,8 @@ import ( "github.com/pocketbase/pocketbase/tools/security" ) -const installerHookId = "__pbinstallerHook" - -func loadInstaller(app core.App, hostURL string) error { +// @todo consider combining with the installer specific hooks after refactoring cmd +func loadInstaller(app core.App, dashboardURL string) error { if !needInstallerSuperuser(app) { return nil } @@ -34,11 +34,11 @@ func loadInstaller(app core.App, hostURL string) error { } // launch url (ignore errors and always print a help text as fallback) - url := fmt.Sprintf("%s/_/#/pbinstal/%s", hostURL, token) + url := fmt.Sprintf("%s/#/pbinstal/%s", strings.TrimRight(dashboardURL, "/"), token) _ = launchURL(url) color.Magenta("\n(!) Launch the URL below in the browser if it hasn't been open already to create your first superuser account:") color.New(color.Bold).Add(color.FgCyan).Println(url) - color.New(color.FgHiBlack, color.Italic).Printf("(you can also create your first superuser account by running '%s superuser upsert test@example.com yourpass' and restart the server)\n", os.Args[0]) + color.New(color.FgHiBlack, color.Italic).Printf("(you can also create your first superuser account by running '%s superuser upsert test@example.com yourpass')\n", os.Args[0]) return nil } @@ -47,6 +47,7 @@ func needInstallerSuperuser(app core.App) bool { total, err := app.CountRecords(core.CollectionNameSuperusers, dbx.Not(dbx.HashExp{ "email": core.DefaultInstallerEmail, })) + return err == nil && total == 0 } diff --git a/apis/serve.go b/apis/serve.go index ff47f32a..7e490d59 100644 --- a/apis/serve.go +++ b/apis/serve.go @@ -27,10 +27,9 @@ type ServeConfig struct { // ShowStartBanner indicates whether to show or hide the server start console message. ShowStartBanner bool - // DashboardPath specifies the route path to the superusers dashboard interface - // (default to "/_/{path...}"). + // DashboardPath specifies the route path to the superusers dashboard (default to "_"). // - // Note: Must include the "{path...}" wildcard parameter. + // Currently it is limited to a single path segment (this is because the UI is not extendable at the moment). DashboardPath string // HttpAddr is the TCP address to listen for the HTTP server (eg. "127.0.0.1:80"). @@ -68,9 +67,12 @@ func Serve(app core.App, config ServeConfig) error { } if config.DashboardPath == "" { - config.DashboardPath = "/_/{path...}" - } else if !strings.HasSuffix(config.DashboardPath, "{path...}") { - return errors.New("invalid dashboard path - missing {path...} wildcard") + config.DashboardPath = "_" + } else { + config.DashboardPath = strings.Trim(config.DashboardPath, "/") + if strings.Contains(config.DashboardPath, "/") { + return errors.New("the dashboard path must be single path segment: _, admin, etc.") + } } // ensure that the latest migrations are applied before starting the server @@ -89,7 +91,7 @@ func Serve(app core.App, config ServeConfig) error { AllowMethods: []string{http.MethodGet, http.MethodHead, http.MethodPut, http.MethodPatch, http.MethodPost, http.MethodDelete}, })) - pbRouter.GET(config.DashboardPath, Static(ui.DistDirFS, false)). + pbRouter.GET("/"+config.DashboardPath+"/{path...}", Static(ui.DistDirFS, false)). BindFunc(func(e *core.RequestEvent) error { // ingore root path if e.Request.PathValue(StaticWildcardParam) != "" { @@ -252,7 +254,8 @@ func Serve(app core.App, config ServeConfig) error { addr = config.CertificateDomains[0] } } - fullAddr := fmt.Sprintf("%s://%s", schema, addr) + baseURL := fmt.Sprintf("%s://%s", schema, addr) + dashboardURL := fmt.Sprintf("%s/%s", baseURL, config.DashboardPath) if config.ShowStartBanner { date := new(strings.Builder) @@ -262,16 +265,16 @@ func Serve(app core.App, config ServeConfig) error { bold.Printf( "%s Server started at %s\n", strings.TrimSpace(date.String()), - color.CyanString("%s", fullAddr), + color.CyanString("%s", baseURL), ) regular := color.New() - regular.Printf("├─ REST API: %s\n", color.CyanString("%s/api/", fullAddr)) - regular.Printf("└─ Dashboard: %s\n", color.CyanString("%s/_/", fullAddr)) + regular.Printf("├─ REST API: %s\n", color.CyanString("%s/api/", baseURL)) + regular.Printf("└─ Dashboard: %s\n", color.CyanString("%s/", dashboardURL)) } go func() { - installerErr := loadInstaller(app, fullAddr) + installerErr := loadInstaller(app, dashboardURL) if installerErr != nil { app.Logger().Warn("Failed to initialize installer", "error", installerErr) } diff --git a/cmd/serve.go b/cmd/serve.go index 8ebc45b3..3cc0b4f3 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -78,8 +78,8 @@ func NewServeCommand(app core.App, showStartBanner bool) *cobra.Command { command.PersistentFlags().StringVar( &dashboardPath, "dashboard", - "/_/{path...}", - "The route path to the superusers dashboard; must include the '{path...}' wildcard parameter", + "_", + "The route path to the superusers dashboard (currently limited to a single path segment)", ) return command diff --git a/cmd/superuser.go b/cmd/superuser.go index 6c8d8e1b..398da7cd 100644 --- a/cmd/superuser.go +++ b/cmd/superuser.go @@ -11,7 +11,7 @@ import ( ) // NewSuperuserCommand creates and returns new command for managing -// superuser accounts (create, update, delete). +// superuser accounts (create, update, upsert, delete). func NewSuperuserCommand(app core.App) *cobra.Command { command := &cobra.Command{ Use: "superuser", diff --git a/pocketbase.go b/pocketbase.go index f1d497cf..d6a2c746 100644 --- a/pocketbase.go +++ b/pocketbase.go @@ -141,7 +141,7 @@ func NewWithConfig(config Config) *PocketBase { } // Start starts the application, aka. registers the default system -// commands (serve, migrate, version) and executes pb.RootCmd. +// commands (serve, superuser, version) and executes pb.RootCmd. func (pb *PocketBase) Start() error { // register system commands pb.RootCmd.AddCommand(cmd.NewSuperuserCommand(pb))