diff --git a/api/adminmonitor/admin_monitor.go b/api/adminmonitor/admin_monitor.go index e83dd47d5..43800dd8f 100644 --- a/api/adminmonitor/admin_monitor.go +++ b/api/adminmonitor/admin_monitor.go @@ -2,13 +2,14 @@ package adminmonitor import ( "context" + "embed" + "io/fs" "log" "net/http" "strings" "sync" "time" - httperror "github.com/portainer/libhttp/error" portainer "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/dataservices" ) @@ -26,7 +27,8 @@ type Monitor struct { adminInitDisabled bool } -// New creates a monitor that when started will wait for the timeout duration and then sends the timeout signal to disable the application +// New creates a monitor that when started will wait for an admin account being created for timeout duration +// if and admin account would still be missing, it'll disable the http traffic handling func New(timeout time.Duration, datastore dataservices.DataStore, shutdownCtx context.Context) *Monitor { return &Monitor{ timeout: timeout, @@ -98,16 +100,26 @@ func (m *Monitor) WasInstanceDisabled() bool { return m.adminInitDisabled } +//go:embed timeout +var timeoutFiles embed.FS + // WithRedirect checks whether administrator initialisation timeout. If so, it will return the error with redirect reason. // Otherwise, it will pass through the request to next func (m *Monitor) WithRedirect(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if m.WasInstanceDisabled() { - if strings.HasPrefix(r.RequestURI, "/api") && r.RequestURI != "/api/status" && r.RequestURI != "/api/settings/public" { - w.Header().Set("redirect-reason", RedirectReasonAdminInitTimeout) - httperror.WriteError(w, http.StatusSeeOther, "Administrator initialization timeout", nil) + if r.RequestURI == `/` || strings.HasPrefix(r.RequestURI, "/api") { + w.Header().Set("redirect-reason", `Administrator initialization timeout`) + http.Redirect(w, r, `/timeout.html`, http.StatusSeeOther) return } + + files, err := fs.Sub(timeoutFiles, "timeout") + if err != nil { + log.Printf("Error %s\n", err) + } + http.FileServer(http.FS(files)).ServeHTTP(w, r) + return } next.ServeHTTP(w, r) diff --git a/api/adminmonitor/timeout/assets/ico/apple-touch-icon.png b/api/adminmonitor/timeout/assets/ico/apple-touch-icon.png new file mode 100644 index 000000000..aeea31ce8 Binary files /dev/null and b/api/adminmonitor/timeout/assets/ico/apple-touch-icon.png differ diff --git a/api/adminmonitor/timeout/assets/ico/favicon-16x16.png b/api/adminmonitor/timeout/assets/ico/favicon-16x16.png new file mode 100644 index 000000000..f7a26b564 Binary files /dev/null and b/api/adminmonitor/timeout/assets/ico/favicon-16x16.png differ diff --git a/api/adminmonitor/timeout/assets/ico/favicon-32x32.png b/api/adminmonitor/timeout/assets/ico/favicon-32x32.png new file mode 100644 index 000000000..d1ccc9cea Binary files /dev/null and b/api/adminmonitor/timeout/assets/ico/favicon-32x32.png differ diff --git a/api/adminmonitor/timeout/assets/ico/favicon.ico b/api/adminmonitor/timeout/assets/ico/favicon.ico new file mode 100644 index 000000000..28ed661f9 Binary files /dev/null and b/api/adminmonitor/timeout/assets/ico/favicon.ico differ diff --git a/api/adminmonitor/timeout/assets/ico/safari-pinned-tab.svg b/api/adminmonitor/timeout/assets/ico/safari-pinned-tab.svg new file mode 100644 index 000000000..79ce7b6fa --- /dev/null +++ b/api/adminmonitor/timeout/assets/ico/safari-pinned-tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/api/adminmonitor/timeout/assets/images/logo_alt.svg b/api/adminmonitor/timeout/assets/images/logo_alt.svg new file mode 100644 index 000000000..90e164ca1 --- /dev/null +++ b/api/adminmonitor/timeout/assets/images/logo_alt.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/timeout.ejs b/api/adminmonitor/timeout/timeout.html similarity index 65% rename from app/timeout.ejs rename to api/adminmonitor/timeout/timeout.html index 656bf0335..119e94f22 100644 --- a/app/timeout.ejs +++ b/api/adminmonitor/timeout/timeout.html @@ -1,19 +1,18 @@ - + Portainer - - - - - - - + + + + + + @@ -24,8 +23,7 @@
- - +
diff --git a/api/http/handler/file/handler.go b/api/http/handler/file/handler.go index 137a87c52..72f8604e8 100644 --- a/api/http/handler/file/handler.go +++ b/api/http/handler/file/handler.go @@ -10,16 +10,14 @@ import ( // Handler represents an HTTP API handler for managing static files. type Handler struct { http.Handler - wasInstanceDisabled func() bool } // NewHandler creates a handler to serve static files. -func NewHandler(assetPublicPath string, wasInstanceDisabled func() bool) *Handler { +func NewHandler(assetPublicPath string) *Handler { h := &Handler{ Handler: handlers.CompressHandler( http.FileServer(http.Dir(assetPublicPath)), ), - wasInstanceDisabled: wasInstanceDisabled, } return h @@ -35,11 +33,6 @@ func isHTML(acceptContent []string) bool { } func (handler *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if handler.wasInstanceDisabled() && (r.RequestURI == "/" || r.RequestURI == "/index.html") { - http.Redirect(w, r, "/timeout.html", http.StatusTemporaryRedirect) - return - } - if !isHTML(r.Header["Accept"]) { w.Header().Set("Cache-Control", "max-age=31536000") } else { diff --git a/api/http/server.go b/api/http/server.go index ad07cafc4..994c591a7 100644 --- a/api/http/server.go +++ b/api/http/server.go @@ -176,7 +176,7 @@ func (server *Server) Start() error { var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.JWTService, server.KubeClusterAccessService, server.KubernetesClientFactory) - var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public"), adminMonitor.WasInstanceDisabled) + var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public")) var endpointHelmHandler = helm.NewHandler(requestBouncer, server.DataStore, server.JWTService, server.KubernetesDeployer, server.HelmPackageManager, server.KubeClusterAccessService) diff --git a/app/portainer/views/init/admin/initAdminController.js b/app/portainer/views/init/admin/initAdminController.js index 6ddcff217..6549ca71f 100644 --- a/app/portainer/views/init/admin/initAdminController.js +++ b/app/portainer/views/init/admin/initAdminController.js @@ -9,8 +9,7 @@ angular.module('portainer.app').controller('InitAdminController', [ 'EndpointService', 'BackupService', 'StatusService', - 'REDIRECT_REASON_TIMEOUT', - function ($scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, EndpointService, BackupService, StatusService, REDIRECT_REASON_TIMEOUT) { + function ($scope, $state, Notifications, Authentication, StateManager, SettingsService, UserService, EndpointService, BackupService, StatusService) { $scope.uploadBackup = uploadBackup; $scope.logo = StateManager.getState().application.logo; @@ -61,7 +60,6 @@ angular.module('portainer.app').controller('InitAdminController', [ } }) .catch(function error(err) { - handleError(err); Notifications.error('Failure', err, 'Unable to create administrator user'); }) .finally(function final() { @@ -69,15 +67,6 @@ angular.module('portainer.app').controller('InitAdminController', [ }); }; - function handleError(err) { - if (err.status === 303) { - const headers = err.headers(); - if (headers && headers['redirect-reason'] === REDIRECT_REASON_TIMEOUT) { - window.location.href = '/timeout.html'; - } - } - } - function createAdministratorFlow() { UserService.administratorExists() .then(function success(exists) { @@ -105,7 +94,6 @@ angular.module('portainer.app').controller('InitAdminController', [ try { await restoreAsyncFn(); } catch (err) { - handleError(err); Notifications.error('Failure', err, 'Unable to restore the backup'); $scope.state.backupInProgress = false; @@ -117,7 +105,6 @@ angular.module('portainer.app').controller('InitAdminController', [ Notifications.success('The backup has successfully been restored'); $state.go('portainer.auth'); } catch (err) { - handleError(err); Notifications.error('Failure', err, 'Unable to check for status'); await wait(2); location.reload(); diff --git a/webpack/webpack.common.js b/webpack/webpack.common.js index 9a1004473..c86d53374 100644 --- a/webpack/webpack.common.js +++ b/webpack/webpack.common.js @@ -108,14 +108,6 @@ module.exports = { }, manifest: './assets/ico/manifest.json', }), - new HtmlWebpackPlugin({ - template: './app/timeout.ejs', - filename: 'timeout.html', - templateParameters: { - name: pkg.name, - author: pkg.author, - }, - }), new WebpackBuildNotifierPlugin({ title: 'Portainer build', logo: path.resolve('./assets/favicon-32x32.png'),