feat(config): add base url support EE-506 (#5999)
parent
335f951e6b
commit
4aea5690a8
|
@ -55,6 +55,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
|
||||||
Labels: pairs(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')),
|
Labels: pairs(kingpin.Flag("hide-label", "Hide containers with a specific label in the UI").Short('l')),
|
||||||
Logo: kingpin.Flag("logo", "URL for the logo displayed in the UI").String(),
|
Logo: kingpin.Flag("logo", "URL for the logo displayed in the UI").String(),
|
||||||
Templates: kingpin.Flag("templates", "URL to the templates definitions.").Short('t').String(),
|
Templates: kingpin.Flag("templates", "URL to the templates definitions.").Short('t').String(),
|
||||||
|
BaseURL: kingpin.Flag("base-url", "Base URL parameter such as portainer if running portainer as http://yourdomain.com/portainer/.").Short('b').Default(defaultBaseURL).String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
|
|
|
@ -19,4 +19,5 @@ const (
|
||||||
defaultSSLCertPath = "/certs/portainer.crt"
|
defaultSSLCertPath = "/certs/portainer.crt"
|
||||||
defaultSSLKeyPath = "/certs/portainer.key"
|
defaultSSLKeyPath = "/certs/portainer.key"
|
||||||
defaultSnapshotInterval = "5m"
|
defaultSnapshotInterval = "5m"
|
||||||
|
defaultBaseURL = "/"
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,4 +17,5 @@ const (
|
||||||
defaultSSLCertPath = "C:\\certs\\portainer.crt"
|
defaultSSLCertPath = "C:\\certs\\portainer.crt"
|
||||||
defaultSSLKeyPath = "C:\\certs\\portainer.key"
|
defaultSSLKeyPath = "C:\\certs\\portainer.key"
|
||||||
defaultSnapshotInterval = "5m"
|
defaultSnapshotInterval = "5m"
|
||||||
|
defaultBaseURL = "/"
|
||||||
)
|
)
|
||||||
|
|
|
@ -653,6 +653,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
|
||||||
ShutdownCtx: shutdownCtx,
|
ShutdownCtx: shutdownCtx,
|
||||||
ShutdownTrigger: shutdownTrigger,
|
ShutdownTrigger: shutdownTrigger,
|
||||||
StackDeployer: stackDeployer,
|
StackDeployer: stackDeployer,
|
||||||
|
BaseURL: *flags.BaseURL,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,15 +21,17 @@ type Handler struct {
|
||||||
kubernetesClientFactory *cli.ClientFactory
|
kubernetesClientFactory *cli.ClientFactory
|
||||||
authorizationService *authorization.Service
|
authorizationService *authorization.Service
|
||||||
JwtService portainer.JWTService
|
JwtService portainer.JWTService
|
||||||
|
BaseURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler creates a handler to process pre-proxied requests to external APIs.
|
// NewHandler creates a handler to process pre-proxied requests to external APIs.
|
||||||
func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore portainer.DataStore, kubernetesClientFactory *cli.ClientFactory) *Handler {
|
func NewHandler(bouncer *security.RequestBouncer, authorizationService *authorization.Service, dataStore portainer.DataStore, kubernetesClientFactory *cli.ClientFactory, baseURL string) *Handler {
|
||||||
h := &Handler{
|
h := &Handler{
|
||||||
Router: mux.NewRouter(),
|
Router: mux.NewRouter(),
|
||||||
dataStore: dataStore,
|
dataStore: dataStore,
|
||||||
kubernetesClientFactory: kubernetesClientFactory,
|
kubernetesClientFactory: kubernetesClientFactory,
|
||||||
authorizationService: authorizationService,
|
authorizationService: authorizationService,
|
||||||
|
BaseURL: baseURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeRouter := h.PathPrefix("/kubernetes").Subrouter()
|
kubeRouter := h.PathPrefix("/kubernetes").Subrouter()
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
clientV1 "k8s.io/client-go/tools/clientcmd/api/v1"
|
clientV1 "k8s.io/client-go/tools/clientcmd/api/v1"
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
|
||||||
return nil, &httperror.HandlerError{http.StatusInternalServerError, fmt.Sprintf("unable to find serviceaccount associated with user; username=%s", tokenData.Username), err}
|
return nil, &httperror.HandlerError{http.StatusInternalServerError, fmt.Sprintf("unable to find serviceaccount associated with user; username=%s", tokenData.Username), err}
|
||||||
}
|
}
|
||||||
|
|
||||||
configClusters[idx] = buildCluster(r, endpoint)
|
configClusters[idx] = buildCluster(r, handler.BaseURL, endpoint)
|
||||||
configContexts[idx] = buildContext(serviceAccount.Name, endpoint)
|
configContexts[idx] = buildContext(serviceAccount.Name, endpoint)
|
||||||
if !authInfosSet[serviceAccount.Name] {
|
if !authInfosSet[serviceAccount.Name] {
|
||||||
configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccount.Name, bearerToken))
|
configAuthInfos = append(configAuthInfos, buildAuthInfo(serviceAccount.Name, bearerToken))
|
||||||
|
@ -151,8 +152,11 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCluster(r *http.Request, endpoint portainer.Endpoint) clientV1.NamedCluster {
|
func buildCluster(r *http.Request, baseURL string, endpoint portainer.Endpoint) clientV1.NamedCluster {
|
||||||
proxyURL := fmt.Sprintf("https://%s/api/endpoints/%d/kubernetes", r.Host, endpoint.ID)
|
if baseURL != "/" {
|
||||||
|
baseURL = fmt.Sprintf("/%s/", strings.Trim(baseURL, "/"))
|
||||||
|
}
|
||||||
|
proxyURL := fmt.Sprintf("https://%s%sapi/endpoints/%d/kubernetes", r.Host, baseURL, endpoint.ID)
|
||||||
return clientV1.NamedCluster{
|
return clientV1.NamedCluster{
|
||||||
Name: buildClusterName(endpoint.Name),
|
Name: buildClusterName(endpoint.Name),
|
||||||
Cluster: clientV1.Cluster{
|
Cluster: clientV1.Cluster{
|
||||||
|
|
|
@ -96,6 +96,7 @@ type Server struct {
|
||||||
ShutdownCtx context.Context
|
ShutdownCtx context.Context
|
||||||
ShutdownTrigger context.CancelFunc
|
ShutdownTrigger context.CancelFunc
|
||||||
StackDeployer stackdeployer.StackDeployer
|
StackDeployer stackdeployer.StackDeployer
|
||||||
|
BaseURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the HTTP server
|
// Start starts the HTTP server
|
||||||
|
@ -172,7 +173,7 @@ func (server *Server) Start() error {
|
||||||
endpointProxyHandler.ProxyManager = server.ProxyManager
|
endpointProxyHandler.ProxyManager = server.ProxyManager
|
||||||
endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService
|
endpointProxyHandler.ReverseTunnelService = server.ReverseTunnelService
|
||||||
|
|
||||||
var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.KubernetesClientFactory)
|
var kubernetesHandler = kubehandler.NewHandler(requestBouncer, server.AuthorizationService, server.DataStore, server.KubernetesClientFactory, server.BaseURL)
|
||||||
kubernetesHandler.JwtService = server.JWTService
|
kubernetesHandler.JwtService = server.JWTService
|
||||||
|
|
||||||
var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public"))
|
var fileHandler = file.NewHandler(filepath.Join(server.AssetsPath, "public"))
|
||||||
|
|
|
@ -95,6 +95,7 @@ type (
|
||||||
SSLKey *string
|
SSLKey *string
|
||||||
Rollback *bool
|
Rollback *bool
|
||||||
SnapshotInterval *string
|
SnapshotInterval *string
|
||||||
|
BaseURL *string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomTemplate represents a custom template
|
// CustomTemplate represents a custom template
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from 'xterm';
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
angular.module('portainer.docker').controller('ContainerConsoleController', [
|
angular.module('portainer.docker').controller('ContainerConsoleController', [
|
||||||
'$scope',
|
'$scope',
|
||||||
|
@ -69,7 +70,8 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
||||||
};
|
};
|
||||||
|
|
||||||
var url =
|
var url =
|
||||||
window.location.href.split('#')[0] +
|
window.location.origin +
|
||||||
|
baseHref() +
|
||||||
'api/websocket/attach?' +
|
'api/websocket/attach?' +
|
||||||
Object.keys(params)
|
Object.keys(params)
|
||||||
.map((k) => k + '=' + params[k])
|
.map((k) => k + '=' + params[k])
|
||||||
|
@ -109,7 +111,8 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
||||||
};
|
};
|
||||||
|
|
||||||
var url =
|
var url =
|
||||||
window.location.href.split('#')[0] +
|
window.location.origin +
|
||||||
|
baseHref() +
|
||||||
'api/websocket/exec?' +
|
'api/websocket/exec?' +
|
||||||
Object.keys(params)
|
Object.keys(params)
|
||||||
.map((k) => k + '=' + params[k])
|
.map((k) => k + '=' + params[k])
|
||||||
|
|
|
@ -19,9 +19,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<button type="button" class="btn btn-sm btn-primary" ngf-select ngf-min-size="10" ng-model="formValues.UploadFile"
|
<button type="button" class="btn btn-sm btn-primary" ngf-select ngf-min-size="10" ng-model="formValues.UploadFile">Select file</button>
|
||||||
>Select file</button
|
|
||||||
>
|
|
||||||
<span style="margin-left: 5px;">
|
<span style="margin-left: 5px;">
|
||||||
{{ formValues.UploadFile.name }}
|
{{ formValues.UploadFile.name }}
|
||||||
<i class="fa fa-times red-icon" ng-if="!formValues.UploadFile" aria-hidden="true"></i>
|
<i class="fa fa-times red-icon" ng-if="!formValues.UploadFile" aria-hidden="true"></i>
|
||||||
|
@ -42,16 +40,16 @@
|
||||||
<rd-widget>
|
<rd-widget>
|
||||||
<rd-widget-header icon="fa-tag" title-text="Tag the image"></rd-widget-header>
|
<rd-widget-header icon="fa-tag" title-text="Tag the image"></rd-widget-header>
|
||||||
<rd-widget-body>
|
<rd-widget-body>
|
||||||
<!-- image-and-registry -->
|
<!-- image-and-registry -->
|
||||||
<por-image-registry
|
<por-image-registry
|
||||||
model="formValues.RegistryModel"
|
model="formValues.RegistryModel"
|
||||||
label-class="col-sm-1"
|
label-class="col-sm-1"
|
||||||
input-class="col-sm-11"
|
input-class="col-sm-11"
|
||||||
endpoint="endpoint"
|
endpoint="endpoint"
|
||||||
is-admin="isAdmin"
|
is-admin="isAdmin"
|
||||||
set-validity="setPullImageValidity"
|
set-validity="setPullImageValidity"
|
||||||
check-rate-limits="true"
|
check-rate-limits="true"
|
||||||
></por-image-registry>
|
></por-image-registry>
|
||||||
</rd-widget-body>
|
</rd-widget-body>
|
||||||
</rd-widget>
|
</rd-widget>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,6 +5,12 @@
|
||||||
<title>Portainer</title>
|
<title>Portainer</title>
|
||||||
<meta name="description" content="" />
|
<meta name="description" content="" />
|
||||||
<meta name="author" content="<%= author %>" />
|
<meta name="author" content="<%= author %>" />
|
||||||
|
<base id="base" />
|
||||||
|
<script>
|
||||||
|
var path = window.location.pathname.replace(/^\/+|\/+$/g, '');
|
||||||
|
var basePath = path ? '/' + path + '/' : '/';
|
||||||
|
document.getElementById('base').href = basePath;
|
||||||
|
</script>
|
||||||
|
|
||||||
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||||
<!--[if lt IE 9]>
|
<!--[if lt IE 9]>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from 'xterm';
|
||||||
import * as fit from 'xterm/lib/addons/fit/fit';
|
import * as fit from 'xterm/lib/addons/fit/fit';
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
export default class KubectlShellController {
|
export default class KubectlShellController {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
|
@ -91,7 +92,7 @@ export default class KubectlShellController {
|
||||||
};
|
};
|
||||||
|
|
||||||
const wsProtocol = this.$window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
const wsProtocol = this.$window.location.protocol === 'https:' ? 'wss://' : 'ws://';
|
||||||
const path = '/api/websocket/kubernetes-shell';
|
const path = baseHref() + 'api/websocket/kubernetes-shell';
|
||||||
const queryParams = Object.entries(params)
|
const queryParams = Object.entries(params)
|
||||||
.map(([k, v]) => `${k}=${v}`)
|
.map(([k, v]) => `${k}=${v}`)
|
||||||
.join('&');
|
.join('&');
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from 'xterm';
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
class KubernetesApplicationConsoleController {
|
class KubernetesApplicationConsoleController {
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
|
@ -59,7 +60,8 @@ class KubernetesApplicationConsoleController {
|
||||||
};
|
};
|
||||||
|
|
||||||
let url =
|
let url =
|
||||||
window.location.href.split('#')[0] +
|
window.location.origin +
|
||||||
|
baseHref() +
|
||||||
'api/websocket/pod?' +
|
'api/websocket/pod?' +
|
||||||
Object.keys(params)
|
Object.keys(params)
|
||||||
.map((k) => k + '=' + params[k])
|
.map((k) => k + '=' + params[k])
|
||||||
|
|
|
@ -11,9 +11,7 @@ interface InputGroupSubComponents {
|
||||||
NumberInput: typeof NumberInput;
|
NumberInput: typeof NumberInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputGroup: typeof MainComponent &
|
const InputGroup: typeof MainComponent & InputGroupSubComponents = MainComponent as typeof MainComponent & InputGroupSubComponents;
|
||||||
InputGroupSubComponents = MainComponent as typeof MainComponent &
|
|
||||||
InputGroupSubComponents;
|
|
||||||
|
|
||||||
InputGroup.Addon = InputGroupAddon;
|
InputGroup.Addon = InputGroupAddon;
|
||||||
InputGroup.ButtonWrapper = InputGroupButtonWrapper;
|
InputGroup.ButtonWrapper = InputGroupButtonWrapper;
|
||||||
|
|
|
@ -2,18 +2,7 @@ import { arrayMove } from './utils';
|
||||||
|
|
||||||
it('moves items in an array', () => {
|
it('moves items in an array', () => {
|
||||||
expect(arrayMove(['a', 'b', 'c'], 2, 0)).toEqual(['c', 'a', 'b']);
|
expect(arrayMove(['a', 'b', 'c'], 2, 0)).toEqual(['c', 'a', 'b']);
|
||||||
expect(
|
expect(arrayMove([{ name: 'Fred' }, { name: 'Barney' }, { name: 'Wilma' }, { name: 'Betty' }], 2, 1)).toEqual([
|
||||||
arrayMove(
|
|
||||||
[
|
|
||||||
{ name: 'Fred' },
|
|
||||||
{ name: 'Barney' },
|
|
||||||
{ name: 'Wilma' },
|
|
||||||
{ name: 'Betty' },
|
|
||||||
],
|
|
||||||
2,
|
|
||||||
1
|
|
||||||
)
|
|
||||||
).toEqual([
|
|
||||||
{ name: 'Fred' },
|
{ name: 'Fred' },
|
||||||
{ name: 'Wilma' },
|
{ name: 'Wilma' },
|
||||||
{ name: 'Barney' },
|
{ name: 'Barney' },
|
||||||
|
|
|
@ -10,23 +10,13 @@ export function arrayMove<T>(array: Array<T>, from: number, to: number) {
|
||||||
|
|
||||||
if (diff > 0) {
|
if (diff > 0) {
|
||||||
// move left
|
// move left
|
||||||
return [
|
return [...array.slice(0, to), item, ...array.slice(to, from), ...array.slice(from + 1, length)];
|
||||||
...array.slice(0, to),
|
|
||||||
item,
|
|
||||||
...array.slice(to, from),
|
|
||||||
...array.slice(from + 1, length),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
// move right
|
// move right
|
||||||
const targetIndex = to + 1;
|
const targetIndex = to + 1;
|
||||||
return [
|
return [...array.slice(0, from), ...array.slice(from + 1, targetIndex), item, ...array.slice(targetIndex, length)];
|
||||||
...array.slice(0, from),
|
|
||||||
...array.slice(from + 1, targetIndex),
|
|
||||||
item,
|
|
||||||
...array.slice(targetIndex, length),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...array];
|
return [...array];
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/**
|
||||||
|
* calculates baseHref
|
||||||
|
*
|
||||||
|
* return [string]
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export function baseHref() {
|
||||||
|
const base = document.getElementById('base');
|
||||||
|
return base ? base.getAttribute('href') : '/';
|
||||||
|
}
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
angular.module('portainer.app').factory('WebhookHelper', [
|
angular.module('portainer.app').factory('WebhookHelper', [
|
||||||
'$location',
|
'$location',
|
||||||
'API_ENDPOINT_WEBHOOKS',
|
'API_ENDPOINT_WEBHOOKS',
|
||||||
|
@ -11,11 +13,11 @@ angular.module('portainer.app').factory('WebhookHelper', [
|
||||||
const displayPort = (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443) ? '' : ':' + port;
|
const displayPort = (protocol === 'http' && port === 80) || (protocol === 'https' && port === 443) ? '' : ':' + port;
|
||||||
|
|
||||||
helper.returnWebhookUrl = function (token) {
|
helper.returnWebhookUrl = function (token) {
|
||||||
return `${protocol}://${$location.host()}${displayPort}/${API_ENDPOINT_WEBHOOKS}/${token}`;
|
return `${protocol}://${$location.host()}${displayPort}${baseHref()}${API_ENDPOINT_WEBHOOKS}/${token}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
helper.returnStackWebhookUrl = function (token) {
|
helper.returnStackWebhookUrl = function (token) {
|
||||||
return `${protocol}://${$location.host()}${displayPort}/${API_ENDPOINT_STACKS}/webhooks/${token}`;
|
return `${protocol}://${$location.host()}${displayPort}${baseHref()}${API_ENDPOINT_STACKS}/webhooks/${token}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return helper;
|
return helper;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { HIDE_INTERNAL_AUTH } from '@/portainer/feature-flags/feature-ids';
|
import { HIDE_INTERNAL_AUTH } from '@/portainer/feature-flags/feature-ids';
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
import providers, { getProviderByUrl } from './providers';
|
import providers, { getProviderByUrl } from './providers';
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ export default class OAuthSettingsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.settings.RedirectURI === '') {
|
if (this.settings.RedirectURI === '') {
|
||||||
this.settings.RedirectURI = window.location.origin;
|
this.settings.RedirectURI = window.location.origin + baseHref();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.settings.AuthorizationURI) {
|
if (this.settings.AuthorizationURI) {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
microsoft: {
|
microsoft: {
|
||||||
authUrl: 'https://login.microsoftonline.com/TENANT_ID/oauth2/authorize',
|
authUrl: 'https://login.microsoftonline.com/TENANT_ID/oauth2/authorize',
|
||||||
accessTokenUrl: 'https://login.microsoftonline.com/TENANT_ID/oauth2/token',
|
accessTokenUrl: 'https://login.microsoftonline.com/TENANT_ID/oauth2/token',
|
||||||
resourceUrl: 'https://graph.windows.net/TENANT_ID/me?api-version=2013-11-08',
|
resourceUrl: 'https://graph.windows.net/TENANT_ID/me?api-version=2013-11-08',
|
||||||
logoutUrl: `https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=${window.location.origin}/#!/auth`,
|
logoutUrl: `https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=${window.location.origin}${baseHref()}#!/auth`,
|
||||||
userIdentifier: 'userPrincipalName',
|
userIdentifier: 'userPrincipalName',
|
||||||
scopes: 'id,email,name',
|
scopes: 'id,email,name',
|
||||||
},
|
},
|
||||||
|
@ -11,7 +13,7 @@ export default {
|
||||||
authUrl: 'https://accounts.google.com/o/oauth2/auth',
|
authUrl: 'https://accounts.google.com/o/oauth2/auth',
|
||||||
accessTokenUrl: 'https://accounts.google.com/o/oauth2/token',
|
accessTokenUrl: 'https://accounts.google.com/o/oauth2/token',
|
||||||
resourceUrl: 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json',
|
resourceUrl: 'https://www.googleapis.com/oauth2/v1/userinfo?alt=json',
|
||||||
logoutUrl: `https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=${window.location.origin}/#!/auth`,
|
logoutUrl: `https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=${window.location.origin}${baseHref()}#!/auth`,
|
||||||
userIdentifier: 'email',
|
userIdentifier: 'email',
|
||||||
scopes: 'profile email',
|
scopes: 'profile email',
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { PortainerEndpointCreationTypes, PortainerEndpointTypes } from 'Portainer/models/endpoint/models';
|
import { PortainerEndpointCreationTypes, PortainerEndpointTypes } from 'Portainer/models/endpoint/models';
|
||||||
import { getAgentShortVersion } from 'Portainer/views/endpoints/helpers';
|
import { getAgentShortVersion } from 'Portainer/views/endpoints/helpers';
|
||||||
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
import { EndpointSecurityFormData } from '../../../components/endpointSecurity/porEndpointSecurityModel';
|
import { EndpointSecurityFormData } from '../../../components/endpointSecurity/porEndpointSecurityModel';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
|
@ -84,7 +85,8 @@ angular
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.setDefaultPortainerInstanceURL = function () {
|
$scope.setDefaultPortainerInstanceURL = function () {
|
||||||
$scope.formValues.URL = window.location.origin;
|
const baseHREF = baseHref();
|
||||||
|
$scope.formValues.URL = window.location.origin + (baseHREF !== '/' ? baseHREF : '');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.resetEndpointURL = function () {
|
$scope.resetEndpointURL = function () {
|
||||||
|
|
Loading…
Reference in New Issue