mirror of https://github.com/portainer/portainer
feat(global): add a --no-auth flag to disable authentication
parent
779fcf8e7f
commit
0f81ad5654
|
@ -29,6 +29,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
|
||||||
Assets: kingpin.Flag("assets", "Path to the assets").Default(defaultAssetsDirectory).Short('a').String(),
|
Assets: kingpin.Flag("assets", "Path to the assets").Default(defaultAssetsDirectory).Short('a').String(),
|
||||||
Data: kingpin.Flag("data", "Path to the folder where the data is stored").Default(defaultDataDirectory).Short('d').String(),
|
Data: kingpin.Flag("data", "Path to the folder where the data is stored").Default(defaultDataDirectory).Short('d').String(),
|
||||||
Templates: kingpin.Flag("templates", "URL to the templates (apps) definitions").Default(defaultTemplatesURL).Short('t').String(),
|
Templates: kingpin.Flag("templates", "URL to the templates (apps) definitions").Default(defaultTemplatesURL).Short('t').String(),
|
||||||
|
NoAuth: kingpin.Flag("no-auth", "Disable authentication").Default(defaultNoAuth).Bool(),
|
||||||
TLSVerify: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLSVerify).Bool(),
|
TLSVerify: kingpin.Flag("tlsverify", "TLS support").Default(defaultTLSVerify).Bool(),
|
||||||
TLSCacert: kingpin.Flag("tlscacert", "Path to the CA").Default(defaultTLSCACertPath).String(),
|
TLSCacert: kingpin.Flag("tlscacert", "Path to the CA").Default(defaultTLSCACertPath).String(),
|
||||||
TLSCert: kingpin.Flag("tlscert", "Path to the TLS certificate file").Default(defaultTLSCertPath).String(),
|
TLSCert: kingpin.Flag("tlscert", "Path to the TLS certificate file").Default(defaultTLSCertPath).String(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ const (
|
||||||
defaultDataDirectory = "/data"
|
defaultDataDirectory = "/data"
|
||||||
defaultAssetsDirectory = "."
|
defaultAssetsDirectory = "."
|
||||||
defaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
defaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
||||||
|
defaultNoAuth = "false"
|
||||||
defaultTLSVerify = "false"
|
defaultTLSVerify = "false"
|
||||||
defaultTLSCACertPath = "/certs/ca.pem"
|
defaultTLSCACertPath = "/certs/ca.pem"
|
||||||
defaultTLSCertPath = "/certs/cert.pem"
|
defaultTLSCertPath = "/certs/cert.pem"
|
||||||
|
|
|
@ -5,6 +5,7 @@ const (
|
||||||
defaultDataDirectory = "C:\\data"
|
defaultDataDirectory = "C:\\data"
|
||||||
defaultAssetsDirectory = "."
|
defaultAssetsDirectory = "."
|
||||||
defaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
defaultTemplatesURL = "https://raw.githubusercontent.com/portainer/templates/master/templates.json"
|
||||||
|
defaultNoAuth = "false"
|
||||||
defaultTLSVerify = "false"
|
defaultTLSVerify = "false"
|
||||||
defaultTLSCACertPath = "C:\\certs\\ca.pem"
|
defaultTLSCACertPath = "C:\\certs\\ca.pem"
|
||||||
defaultTLSCertPath = "C:\\certs\\cert.pem"
|
defaultTLSCertPath = "C:\\certs\\cert.pem"
|
||||||
|
|
|
@ -27,6 +27,7 @@ func main() {
|
||||||
settings := &portainer.Settings{
|
settings := &portainer.Settings{
|
||||||
HiddenLabels: *flags.Labels,
|
HiddenLabels: *flags.Labels,
|
||||||
Logo: *flags.Logo,
|
Logo: *flags.Logo,
|
||||||
|
Authentication: !*flags.NoAuth,
|
||||||
}
|
}
|
||||||
|
|
||||||
fileService, err := file.NewService(*flags.Data, "")
|
fileService, err := file.NewService(*flags.Data, "")
|
||||||
|
@ -41,10 +42,13 @@ func main() {
|
||||||
}
|
}
|
||||||
defer store.Close()
|
defer store.Close()
|
||||||
|
|
||||||
jwtService, err := jwt.NewService()
|
var jwtService portainer.JWTService
|
||||||
|
if !*flags.NoAuth {
|
||||||
|
jwtService, err = jwt.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var cryptoService portainer.CryptoService = &crypto.Service{}
|
var cryptoService portainer.CryptoService = &crypto.Service{}
|
||||||
|
|
||||||
|
@ -76,6 +80,7 @@ func main() {
|
||||||
AssetsPath: *flags.Assets,
|
AssetsPath: *flags.Assets,
|
||||||
Settings: settings,
|
Settings: settings,
|
||||||
TemplatesURL: *flags.Templates,
|
TemplatesURL: *flags.Templates,
|
||||||
|
AuthDisabled: *flags.NoAuth,
|
||||||
UserService: store.UserService,
|
UserService: store.UserService,
|
||||||
EndpointService: store.EndpointService,
|
EndpointService: store.EndpointService,
|
||||||
CryptoService: cryptoService,
|
CryptoService: cryptoService,
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
type AuthHandler struct {
|
type AuthHandler struct {
|
||||||
*mux.Router
|
*mux.Router
|
||||||
Logger *log.Logger
|
Logger *log.Logger
|
||||||
|
authDisabled bool
|
||||||
UserService portainer.UserService
|
UserService portainer.UserService
|
||||||
CryptoService portainer.CryptoService
|
CryptoService portainer.CryptoService
|
||||||
JWTService portainer.JWTService
|
JWTService portainer.JWTService
|
||||||
|
@ -26,6 +27,9 @@ const (
|
||||||
ErrInvalidCredentialsFormat = portainer.Error("Invalid credentials format")
|
ErrInvalidCredentialsFormat = portainer.Error("Invalid credentials format")
|
||||||
// ErrInvalidCredentials is an error raised when credentials for a user are invalid
|
// ErrInvalidCredentials is an error raised when credentials for a user are invalid
|
||||||
ErrInvalidCredentials = portainer.Error("Invalid credentials")
|
ErrInvalidCredentials = portainer.Error("Invalid credentials")
|
||||||
|
// ErrAuthDisabled is an error raised when trying to access the authentication endpoints
|
||||||
|
// when the server has been started with the --no-auth flag
|
||||||
|
ErrAuthDisabled = portainer.Error("Authentication is disabled")
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAuthHandler returns a new instance of AuthHandler.
|
// NewAuthHandler returns a new instance of AuthHandler.
|
||||||
|
@ -44,6 +48,11 @@ func (handler *AuthHandler) handlePostAuth(w http.ResponseWriter, r *http.Reques
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if handler.authDisabled {
|
||||||
|
Error(w, ErrAuthDisabled, http.StatusServiceUnavailable, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var req postAuthRequest
|
var req postAuthRequest
|
||||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||||
Error(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
Error(w, ErrInvalidJSON, http.StatusBadRequest, handler.Logger)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
// Service represents a service to manage HTTP middlewares
|
// Service represents a service to manage HTTP middlewares
|
||||||
type middleWareService struct {
|
type middleWareService struct {
|
||||||
jwtService portainer.JWTService
|
jwtService portainer.JWTService
|
||||||
|
authDisabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMiddleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
|
func addMiddleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
|
||||||
|
@ -37,6 +38,7 @@ func (*middleWareService) middleWareSecureHeaders(next http.Handler) http.Handle
|
||||||
// middleWareAuthenticate provides Authentication middleware for handlers
|
// middleWareAuthenticate provides Authentication middleware for handlers
|
||||||
func (service *middleWareService) middleWareAuthenticate(next http.Handler) http.Handler {
|
func (service *middleWareService) middleWareAuthenticate(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !service.authDisabled {
|
||||||
var token string
|
var token string
|
||||||
|
|
||||||
// Get token from the Authorization header
|
// Get token from the Authorization header
|
||||||
|
@ -56,6 +58,7 @@ func (service *middleWareService) middleWareAuthenticate(next http.Handler) http
|
||||||
Error(w, err, http.StatusUnauthorized, nil)
|
Error(w, err, http.StatusUnauthorized, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
type Server struct {
|
type Server struct {
|
||||||
BindAddress string
|
BindAddress string
|
||||||
AssetsPath string
|
AssetsPath string
|
||||||
|
AuthDisabled bool
|
||||||
UserService portainer.UserService
|
UserService portainer.UserService
|
||||||
EndpointService portainer.EndpointService
|
EndpointService portainer.EndpointService
|
||||||
CryptoService portainer.CryptoService
|
CryptoService portainer.CryptoService
|
||||||
|
@ -41,12 +42,14 @@ func (server *Server) updateActiveEndpoint(endpoint *portainer.Endpoint) error {
|
||||||
func (server *Server) Start() error {
|
func (server *Server) Start() error {
|
||||||
middleWareService := &middleWareService{
|
middleWareService := &middleWareService{
|
||||||
jwtService: server.JWTService,
|
jwtService: server.JWTService,
|
||||||
|
authDisabled: server.AuthDisabled,
|
||||||
}
|
}
|
||||||
|
|
||||||
var authHandler = NewAuthHandler()
|
var authHandler = NewAuthHandler()
|
||||||
authHandler.UserService = server.UserService
|
authHandler.UserService = server.UserService
|
||||||
authHandler.CryptoService = server.CryptoService
|
authHandler.CryptoService = server.CryptoService
|
||||||
authHandler.JWTService = server.JWTService
|
authHandler.JWTService = server.JWTService
|
||||||
|
authHandler.authDisabled = server.AuthDisabled
|
||||||
var userHandler = NewUserHandler(middleWareService)
|
var userHandler = NewUserHandler(middleWareService)
|
||||||
userHandler.UserService = server.UserService
|
userHandler.UserService = server.UserService
|
||||||
userHandler.CryptoService = server.CryptoService
|
userHandler.CryptoService = server.CryptoService
|
||||||
|
|
|
@ -20,6 +20,7 @@ type (
|
||||||
Labels *[]Pair
|
Labels *[]Pair
|
||||||
Logo *string
|
Logo *string
|
||||||
Templates *string
|
Templates *string
|
||||||
|
NoAuth *bool
|
||||||
TLSVerify *bool
|
TLSVerify *bool
|
||||||
TLSCacert *string
|
TLSCacert *string
|
||||||
TLSCert *string
|
TLSCert *string
|
||||||
|
@ -30,6 +31,7 @@ type (
|
||||||
Settings struct {
|
Settings struct {
|
||||||
HiddenLabels []Pair `json:"hiddenLabels"`
|
HiddenLabels []Pair `json:"hiddenLabels"`
|
||||||
Logo string `json:"logo"`
|
Logo string `json:"logo"`
|
||||||
|
Authentication bool `json:"authentication"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// User represent a user account.
|
// User represent a user account.
|
||||||
|
|
235
app/app.js
235
app/app.js
|
@ -67,124 +67,121 @@ angular.module('portainer', [
|
||||||
$urlRouterProvider.otherwise('/auth');
|
$urlRouterProvider.otherwise('/auth');
|
||||||
|
|
||||||
$stateProvider
|
$stateProvider
|
||||||
|
.state('root', {
|
||||||
|
abstract: true,
|
||||||
|
resolve: {
|
||||||
|
requiresLogin: ['StateManager', function (StateManager) {
|
||||||
|
var applicationState = StateManager.getState();
|
||||||
|
return applicationState.application.authentication;
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
.state('auth', {
|
.state('auth', {
|
||||||
|
parent: 'root',
|
||||||
url: '/auth',
|
url: '/auth',
|
||||||
params: {
|
params: {
|
||||||
logout: false,
|
logout: false,
|
||||||
error: ''
|
error: ''
|
||||||
},
|
},
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/auth/auth.html',
|
templateUrl: 'app/components/auth/auth.html',
|
||||||
controller: 'AuthenticationController'
|
controller: 'AuthenticationController'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
requiresLogin: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('containers', {
|
.state('containers', {
|
||||||
|
parent: 'root',
|
||||||
url: '/containers/',
|
url: '/containers/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/containers/containers.html',
|
templateUrl: 'app/components/containers/containers.html',
|
||||||
controller: 'ContainersController'
|
controller: 'ContainersController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('container', {
|
.state('container', {
|
||||||
url: "^/containers/:id",
|
url: "^/containers/:id",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/container/container.html',
|
templateUrl: 'app/components/container/container.html',
|
||||||
controller: 'ContainerController'
|
controller: 'ContainerController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('stats', {
|
.state('stats', {
|
||||||
url: "^/containers/:id/stats",
|
url: "^/containers/:id/stats",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/stats/stats.html',
|
templateUrl: 'app/components/stats/stats.html',
|
||||||
controller: 'StatsController'
|
controller: 'StatsController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('logs', {
|
.state('logs', {
|
||||||
url: "^/containers/:id/logs",
|
url: "^/containers/:id/logs",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/containerLogs/containerlogs.html',
|
templateUrl: 'app/components/containerLogs/containerlogs.html',
|
||||||
controller: 'ContainerLogsController'
|
controller: 'ContainerLogsController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('console', {
|
.state('console', {
|
||||||
url: "^/containers/:id/console",
|
url: "^/containers/:id/console",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/containerConsole/containerConsole.html',
|
templateUrl: 'app/components/containerConsole/containerConsole.html',
|
||||||
controller: 'ContainerConsoleController'
|
controller: 'ContainerConsoleController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('dashboard', {
|
.state('dashboard', {
|
||||||
|
parent: 'root',
|
||||||
url: '/dashboard',
|
url: '/dashboard',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/dashboard/dashboard.html',
|
templateUrl: 'app/components/dashboard/dashboard.html',
|
||||||
controller: 'DashboardController'
|
controller: 'DashboardController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('actions', {
|
.state('actions', {
|
||||||
abstract: true,
|
abstract: true,
|
||||||
url: "/actions",
|
url: "/actions",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
template: '<div ui-view="content"></div>'
|
template: '<div ui-view="content@"></div>'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
template: '<div ui-view="sidebar"></div>'
|
template: '<div ui-view="sidebar@"></div>'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -192,344 +189,281 @@ angular.module('portainer', [
|
||||||
abstract: true,
|
abstract: true,
|
||||||
url: "/create",
|
url: "/create",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
template: '<div ui-view="content"></div>'
|
template: '<div ui-view="content@"></div>'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
template: '<div ui-view="sidebar"></div>'
|
template: '<div ui-view="sidebar@"></div>'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('actions.create.container', {
|
.state('actions.create.container', {
|
||||||
url: "/container",
|
url: "/container",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/createContainer/createcontainer.html',
|
templateUrl: 'app/components/createContainer/createcontainer.html',
|
||||||
controller: 'CreateContainerController'
|
controller: 'CreateContainerController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('actions.create.network', {
|
.state('actions.create.network', {
|
||||||
url: "/network",
|
url: "/network",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/createNetwork/createnetwork.html',
|
templateUrl: 'app/components/createNetwork/createnetwork.html',
|
||||||
controller: 'CreateNetworkController'
|
controller: 'CreateNetworkController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('actions.create.service', {
|
.state('actions.create.service', {
|
||||||
url: "/service",
|
url: "/service",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/createService/createservice.html',
|
templateUrl: 'app/components/createService/createservice.html',
|
||||||
controller: 'CreateServiceController'
|
controller: 'CreateServiceController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('actions.create.volume', {
|
.state('actions.create.volume', {
|
||||||
url: "/volume",
|
url: "/volume",
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/createVolume/createvolume.html',
|
templateUrl: 'app/components/createVolume/createvolume.html',
|
||||||
controller: 'CreateVolumeController'
|
controller: 'CreateVolumeController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('docker', {
|
.state('docker', {
|
||||||
url: '/docker/',
|
url: '/docker/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/docker/docker.html',
|
templateUrl: 'app/components/docker/docker.html',
|
||||||
controller: 'DockerController'
|
controller: 'DockerController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('endpoints', {
|
.state('endpoints', {
|
||||||
url: '/endpoints/',
|
url: '/endpoints/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/endpoints/endpoints.html',
|
templateUrl: 'app/components/endpoints/endpoints.html',
|
||||||
controller: 'EndpointsController'
|
controller: 'EndpointsController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('endpoint', {
|
.state('endpoint', {
|
||||||
url: '^/endpoints/:id',
|
url: '^/endpoints/:id',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/endpoint/endpoint.html',
|
templateUrl: 'app/components/endpoint/endpoint.html',
|
||||||
controller: 'EndpointController'
|
controller: 'EndpointController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('endpointInit', {
|
.state('endpointInit', {
|
||||||
url: '/init/endpoint',
|
url: '/init/endpoint',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/endpointInit/endpointInit.html',
|
templateUrl: 'app/components/endpointInit/endpointInit.html',
|
||||||
controller: 'EndpointInitController'
|
controller: 'EndpointInitController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('events', {
|
.state('events', {
|
||||||
url: '/events/',
|
url: '/events/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/events/events.html',
|
templateUrl: 'app/components/events/events.html',
|
||||||
controller: 'EventsController'
|
controller: 'EventsController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('images', {
|
.state('images', {
|
||||||
url: '/images/',
|
url: '/images/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/images/images.html',
|
templateUrl: 'app/components/images/images.html',
|
||||||
controller: 'ImagesController'
|
controller: 'ImagesController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('image', {
|
.state('image', {
|
||||||
url: '^/images/:id/',
|
url: '^/images/:id/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/image/image.html',
|
templateUrl: 'app/components/image/image.html',
|
||||||
controller: 'ImageController'
|
controller: 'ImageController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('networks', {
|
.state('networks', {
|
||||||
url: '/networks/',
|
url: '/networks/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/networks/networks.html',
|
templateUrl: 'app/components/networks/networks.html',
|
||||||
controller: 'NetworksController'
|
controller: 'NetworksController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('network', {
|
.state('network', {
|
||||||
url: '^/networks/:id/',
|
url: '^/networks/:id/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/network/network.html',
|
templateUrl: 'app/components/network/network.html',
|
||||||
controller: 'NetworkController'
|
controller: 'NetworkController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('node', {
|
.state('node', {
|
||||||
url: '^/nodes/:id/',
|
url: '^/nodes/:id/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/node/node.html',
|
templateUrl: 'app/components/node/node.html',
|
||||||
controller: 'NodeController'
|
controller: 'NodeController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('services', {
|
.state('services', {
|
||||||
url: '/services/',
|
url: '/services/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/services/services.html',
|
templateUrl: 'app/components/services/services.html',
|
||||||
controller: 'ServicesController'
|
controller: 'ServicesController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('service', {
|
.state('service', {
|
||||||
url: '^/service/:id/',
|
url: '^/service/:id/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/service/service.html',
|
templateUrl: 'app/components/service/service.html',
|
||||||
controller: 'ServiceController'
|
controller: 'ServiceController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('settings', {
|
.state('settings', {
|
||||||
url: '/settings/',
|
url: '/settings/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/settings/settings.html',
|
templateUrl: 'app/components/settings/settings.html',
|
||||||
controller: 'SettingsController'
|
controller: 'SettingsController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('task', {
|
.state('task', {
|
||||||
url: '^/task/:id',
|
url: '^/task/:id',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/task/task.html',
|
templateUrl: 'app/components/task/task.html',
|
||||||
controller: 'TaskController'
|
controller: 'TaskController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('templates', {
|
.state('templates', {
|
||||||
url: '/templates/',
|
url: '/templates/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/templates/templates.html',
|
templateUrl: 'app/components/templates/templates.html',
|
||||||
controller: 'TemplatesController'
|
controller: 'TemplatesController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('volumes', {
|
.state('volumes', {
|
||||||
url: '/volumes/',
|
url: '/volumes/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/volumes/volumes.html',
|
templateUrl: 'app/components/volumes/volumes.html',
|
||||||
controller: 'VolumesController'
|
controller: 'VolumesController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.state('swarm', {
|
.state('swarm', {
|
||||||
url: '/swarm/',
|
url: '/swarm/',
|
||||||
views: {
|
views: {
|
||||||
"content": {
|
"content@": {
|
||||||
templateUrl: 'app/components/swarm/swarm.html',
|
templateUrl: 'app/components/swarm/swarm.html',
|
||||||
controller: 'SwarmController'
|
controller: 'SwarmController'
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar@": {
|
||||||
templateUrl: 'app/components/sidebar/sidebar.html',
|
templateUrl: 'app/components/sidebar/sidebar.html',
|
||||||
controller: 'SidebarController'
|
controller: 'SidebarController'
|
||||||
}
|
}
|
||||||
},
|
|
||||||
data: {
|
|
||||||
requiresLogin: true
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -550,18 +484,21 @@ angular.module('portainer', [
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}])
|
}])
|
||||||
.run(['$rootScope', '$state', 'Authentication', 'authManager', 'StateManager', function ($rootScope, $state, Authentication, authManager, StateManager) {
|
.run(['$rootScope', '$state', 'Authentication', 'authManager', 'StateManager', 'Messages', function ($rootScope, $state, Authentication, authManager, StateManager, Messages) {
|
||||||
|
StateManager.initialize().then(function success(state) {
|
||||||
|
if (state.application.authentication) {
|
||||||
authManager.checkAuthOnRefresh();
|
authManager.checkAuthOnRefresh();
|
||||||
authManager.redirectWhenUnauthenticated();
|
authManager.redirectWhenUnauthenticated();
|
||||||
|
|
||||||
Authentication.init();
|
Authentication.init();
|
||||||
StateManager.init();
|
|
||||||
|
|
||||||
$rootScope.$state = $state;
|
|
||||||
|
|
||||||
$rootScope.$on('tokenHasExpired', function($state) {
|
$rootScope.$on('tokenHasExpired', function($state) {
|
||||||
$state.go('auth', {error: 'Your session has expired'});
|
$state.go('auth', {error: 'Your session has expired'});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}, function error(err) {
|
||||||
|
Messages.error("Failure", err, 'Unable to retrieve application settings');
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$state = $state;
|
||||||
}])
|
}])
|
||||||
// This is your docker url that the api will use to make requests
|
// This is your docker url that the api will use to make requests
|
||||||
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
|
// You need to set this to the api endpoint without the port i.e. http://192.168.1.9
|
||||||
|
|
|
@ -13,6 +13,23 @@ function ($scope, $state, $stateParams, $window, $timeout, $sanitize, Config, Au
|
||||||
error: false
|
error: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!$scope.applicationState.application.authentication) {
|
||||||
|
EndpointService.getActive().then(function success(data) {
|
||||||
|
StateManager.updateEndpointState(true)
|
||||||
|
.then(function success() {
|
||||||
|
$state.go('dashboard');
|
||||||
|
}, function error(err) {
|
||||||
|
Messages.error("Failure", err, 'Unable to connect to the Docker endpoint');
|
||||||
|
});
|
||||||
|
}, function error(err) {
|
||||||
|
if (err.status === 404) {
|
||||||
|
$state.go('endpointInit');
|
||||||
|
} else {
|
||||||
|
Messages.error("Failure", err, 'Unable to verify Docker endpoint existence');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if ($stateParams.logout) {
|
if ($stateParams.logout) {
|
||||||
Authentication.logout();
|
Authentication.logout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
<a ui-sref="docker" ui-sref-active="active">Docker <span class="menu-icon fa fa-th"></span></a>
|
<a ui-sref="docker" ui-sref-active="active">Docker <span class="menu-icon fa fa-th"></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="sidebar-title"><span>Portainer settings</span></li>
|
<li class="sidebar-title"><span>Portainer settings</span></li>
|
||||||
<li class="sidebar-list">
|
<li class="sidebar-list" ng-if="applicationState.application.authentication">
|
||||||
<a ui-sref="settings" ui-sref-active="active">Password <span class="menu-icon fa fa-lock"></span></a>
|
<a ui-sref="settings" ui-sref-active="active">Password <span class="menu-icon fa fa-lock"></span></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="sidebar-list">
|
<li class="sidebar-list">
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
angular
|
angular
|
||||||
.module('portainer')
|
.module('portainer')
|
||||||
.directive('rdHeaderContent', function rdHeaderContent() {
|
.directive('rdHeaderContent', ['Authentication', function rdHeaderContent(Authentication) {
|
||||||
var directive = {
|
var directive = {
|
||||||
requires: '^rdHeader',
|
requires: '^rdHeader',
|
||||||
transclude: true,
|
transclude: true,
|
||||||
template: '<div class="breadcrumb-links"><div class="pull-left" ng-transclude></div><div class="pull-right"><a ui-sref="auth({logout: true})" class="text-danger" style="margin-right: 25px;"><u>log out <i class="fa fa-sign-out" aria-hidden="true"></i></u></a></div></div>',
|
link: function (scope, iElement, iAttrs) {
|
||||||
|
scope.username = Authentication.getCredentials().username;
|
||||||
|
},
|
||||||
|
template: '<div class="breadcrumb-links"><div class="pull-left" ng-transclude></div><div class="pull-right" ng-if="username"><a ui-sref="auth({logout: true})" class="text-danger" style="margin-right: 25px;"><u>log out <i class="fa fa-sign-out" aria-hidden="true"></i></u></a></div></div>',
|
||||||
restrict: 'E'
|
restrict: 'E'
|
||||||
};
|
};
|
||||||
return directive;
|
return directive;
|
||||||
});
|
}]);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
angular
|
angular
|
||||||
.module('portainer')
|
.module('portainer')
|
||||||
.directive('rdHeaderTitle', ['$rootScope', function rdHeaderTitle($rootScope) {
|
.directive('rdHeaderTitle', ['Authentication', function rdHeaderTitle(Authentication) {
|
||||||
var directive = {
|
var directive = {
|
||||||
requires: '^rdHeader',
|
requires: '^rdHeader',
|
||||||
scope: {
|
scope: {
|
||||||
title: '@'
|
title: '@'
|
||||||
},
|
},
|
||||||
link: function (scope, iElement, iAttrs) {
|
link: function (scope, iElement, iAttrs) {
|
||||||
scope.username = $rootScope.username;
|
scope.username = Authentication.getCredentials().username;
|
||||||
},
|
},
|
||||||
transclude: true,
|
transclude: true,
|
||||||
template: '<div class="page white-space-normal">{{title}}<span class="header_title_content" ng-transclude></span><span class="pull-right user-box"><i class="fa fa-user-circle-o" aria-hidden="true"></i> {{username}}</span></div>',
|
template: '<div class="page white-space-normal">{{title}}<span class="header_title_content" ng-transclude></span><span class="pull-right user-box" ng-if="username"><i class="fa fa-user-circle-o" aria-hidden="true"></i> {{username}}</span></div>',
|
||||||
restrict: 'E'
|
restrict: 'E'
|
||||||
};
|
};
|
||||||
return directive;
|
return directive;
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
angular.module('portainer.services')
|
angular.module('portainer.services')
|
||||||
.factory('Authentication', ['$q', '$rootScope', 'Auth', 'jwtHelper', 'LocalStorage', 'StateManager', function AuthenticationFactory($q, $rootScope, Auth, jwtHelper, LocalStorage, StateManager) {
|
.factory('Authentication', ['$q', 'Auth', 'jwtHelper', 'LocalStorage', 'StateManager', function AuthenticationFactory($q, Auth, jwtHelper, LocalStorage, StateManager) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var credentials = {};
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
var jwt = LocalStorage.getJWT();
|
var jwt = LocalStorage.getJWT();
|
||||||
if (jwt) {
|
if (jwt) {
|
||||||
var tokenPayload = jwtHelper.decodeToken(jwt);
|
var tokenPayload = jwtHelper.decodeToken(jwt);
|
||||||
$rootScope.username = tokenPayload.username;
|
credentials.username = tokenPayload.username;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
login: function(username, password) {
|
login: function(username, password) {
|
||||||
|
@ -14,7 +16,7 @@ angular.module('portainer.services')
|
||||||
Auth.login({username: username, password: password}).$promise
|
Auth.login({username: username, password: password}).$promise
|
||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
LocalStorage.storeJWT(data.jwt);
|
LocalStorage.storeJWT(data.jwt);
|
||||||
$rootScope.username = username;
|
credentials.username = username;
|
||||||
resolve();
|
resolve();
|
||||||
}, function() {
|
}, function() {
|
||||||
reject();
|
reject();
|
||||||
|
@ -28,6 +30,9 @@ angular.module('portainer.services')
|
||||||
isAuthenticated: function() {
|
isAuthenticated: function() {
|
||||||
var jwt = LocalStorage.getJWT();
|
var jwt = LocalStorage.getJWT();
|
||||||
return jwt && !jwtHelper.isTokenExpired(jwt);
|
return jwt && !jwtHelper.isTokenExpired(jwt);
|
||||||
|
},
|
||||||
|
getCredentials: function() {
|
||||||
|
return credentials;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -8,6 +8,12 @@ angular.module('portainer.services')
|
||||||
getEndpointState: function() {
|
getEndpointState: function() {
|
||||||
return localStorageService.get('ENDPOINT_STATE');
|
return localStorageService.get('ENDPOINT_STATE');
|
||||||
},
|
},
|
||||||
|
storeApplicationState: function(state) {
|
||||||
|
localStorageService.set('APPLICATION_STATE', state);
|
||||||
|
},
|
||||||
|
getApplicationState: function() {
|
||||||
|
return localStorageService.get('APPLICATION_STATE');
|
||||||
|
},
|
||||||
storeJWT: function(jwt) {
|
storeJWT: function(jwt) {
|
||||||
localStorageService.set('JWT', jwt);
|
localStorageService.set('JWT', jwt);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
angular.module('portainer.services')
|
angular.module('portainer.services')
|
||||||
.factory('StateManager', ['$q', 'Info', 'InfoHelper', 'Version', 'LocalStorage', function StateManagerFactory($q, Info, InfoHelper, Version, LocalStorage) {
|
.factory('StateManager', ['$q', 'Config', 'Info', 'InfoHelper', 'Version', 'LocalStorage', function StateManagerFactory($q, Config, Info, InfoHelper, Version, LocalStorage) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var state = {
|
var state = {
|
||||||
|
@ -9,12 +9,31 @@ angular.module('portainer.services')
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
initialize: function() {
|
||||||
var endpointState = LocalStorage.getEndpointState();
|
var endpointState = LocalStorage.getEndpointState();
|
||||||
if (endpointState) {
|
if (endpointState) {
|
||||||
state.endpoint = endpointState;
|
state.endpoint = endpointState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var deferred = $q.defer();
|
||||||
|
var applicationState = LocalStorage.getApplicationState();
|
||||||
|
if (applicationState) {
|
||||||
|
state.application = applicationState;
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
|
deferred.resolve(state);
|
||||||
|
} else {
|
||||||
|
Config.$promise.then(function success(data) {
|
||||||
|
state.application.authentication = data.authentication;
|
||||||
|
state.application.logo = data.logo;
|
||||||
|
LocalStorage.storeApplicationState(state.application);
|
||||||
|
state.loading = false;
|
||||||
|
deferred.resolve(state);
|
||||||
|
}, function error(err) {
|
||||||
|
state.loading = false;
|
||||||
|
deferred.reject({msg: 'Unable to retrieve server configuration', err: err});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return deferred.promise;
|
||||||
},
|
},
|
||||||
clean: function() {
|
clean: function() {
|
||||||
state.endpoint = {};
|
state.endpoint = {};
|
||||||
|
|
Loading…
Reference in New Issue