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 @@
-
+
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'),