mirror of
https://github.com/ansible/awx.git
synced 2026-03-27 13:55:04 -02:30
Merge pull request #4032 from ghjm/configurable_login_3.6.2
[3.6.2] Configurable login redirect
This commit is contained in:
@@ -62,3 +62,14 @@ register(
|
|||||||
category=_('Authentication'),
|
category=_('Authentication'),
|
||||||
category_slug='authentication',
|
category_slug='authentication',
|
||||||
)
|
)
|
||||||
|
register(
|
||||||
|
'LOGIN_REDIRECT_OVERRIDE',
|
||||||
|
field_class=fields.CharField,
|
||||||
|
allow_blank=True,
|
||||||
|
required=False,
|
||||||
|
label=_('Login redirect override URL'),
|
||||||
|
help_text=_('URL to which unauthorized users will be redirected to log in. '
|
||||||
|
'If blank, users will be sent to the Tower login page.'),
|
||||||
|
category=_('Authentication'),
|
||||||
|
category_slug='authentication',
|
||||||
|
)
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class ApiRootView(APIView):
|
|||||||
data['oauth2'] = drf_reverse('api:oauth_authorization_root_view')
|
data['oauth2'] = drf_reverse('api:oauth_authorization_root_view')
|
||||||
data['custom_logo'] = settings.CUSTOM_LOGO
|
data['custom_logo'] = settings.CUSTOM_LOGO
|
||||||
data['custom_login_info'] = settings.CUSTOM_LOGIN_INFO
|
data['custom_login_info'] = settings.CUSTOM_LOGIN_INFO
|
||||||
|
data['login_redirect_override'] = settings.LOGIN_REDIRECT_OVERRIDE
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
@@ -97,3 +97,7 @@ def handle_csp_violation(request):
|
|||||||
logger = logging.getLogger('awx')
|
logger = logging.getLogger('awx')
|
||||||
logger.error(json.loads(request.body))
|
logger.error(json.loads(request.body))
|
||||||
return HttpResponse(content=None)
|
return HttpResponse(content=None)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_login_redirect(request):
|
||||||
|
return HttpResponseRedirect("/#/login")
|
||||||
|
|||||||
@@ -379,6 +379,10 @@ TACACSPLUS_AUTH_PROTOCOL = 'ascii'
|
|||||||
# Note: This setting may be overridden by database settings.
|
# Note: This setting may be overridden by database settings.
|
||||||
AUTH_BASIC_ENABLED = True
|
AUTH_BASIC_ENABLED = True
|
||||||
|
|
||||||
|
# If set, specifies a URL that unauthenticated users will be redirected to
|
||||||
|
# when trying to access a UI page that requries authentication.
|
||||||
|
LOGIN_REDIRECT_OVERRIDE = None
|
||||||
|
|
||||||
# If set, serve only minified JS for UI.
|
# If set, serve only minified JS for UI.
|
||||||
USE_MINIFIED_JS = False
|
USE_MINIFIED_JS = False
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ global.$AnsibleConfig = null;
|
|||||||
// Provided via Webpack DefinePlugin in webpack.config.js
|
// Provided via Webpack DefinePlugin in webpack.config.js
|
||||||
global.$ENV = {};
|
global.$ENV = {};
|
||||||
|
|
||||||
|
global.$ConfigResponse = {};
|
||||||
|
|
||||||
var urlPrefix;
|
var urlPrefix;
|
||||||
|
|
||||||
if ($basePath) {
|
if ($basePath) {
|
||||||
@@ -383,7 +385,11 @@ angular
|
|||||||
var stime = timestammp[lastUser.id].time,
|
var stime = timestammp[lastUser.id].time,
|
||||||
now = new Date().getTime();
|
now = new Date().getTime();
|
||||||
if ((stime - now) <= 0) {
|
if ((stime - now) <= 0) {
|
||||||
$location.path('/login');
|
if (global.$AnsibleConfig.login_redirect_override) {
|
||||||
|
window.location.replace(global.$AnsibleConfig.login_redirect_override);
|
||||||
|
} else {
|
||||||
|
$location.path('/login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If browser refresh, set the user_is_superuser value
|
// If browser refresh, set the user_is_superuser value
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ function bootstrap (callback) {
|
|||||||
angular.module('I18N').constant('LOCALE', locale);
|
angular.module('I18N').constant('LOCALE', locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
angular.element(document).ready(() => callback());
|
fetchConfig(() => {
|
||||||
|
angular.element(document).ready(() => callback());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +51,25 @@ function fetchLocaleStrings (callback) {
|
|||||||
request.fail(() => callback({ code: DEFAULT_LOCALE }));
|
request.fail(() => callback({ code: DEFAULT_LOCALE }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fetchConfig (callback) {
|
||||||
|
const request = $.ajax('/api/');
|
||||||
|
|
||||||
|
request.done(res => {
|
||||||
|
global.$ConfigResponse = res;
|
||||||
|
if (res.login_redirect_override) {
|
||||||
|
if (!document.cookie.split(';').filter((item) => item.includes('userLoggedIn=true')).length && !window.location.href.includes('/#/login')) {
|
||||||
|
window.location.replace(res.login_redirect_override);
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
request.fail(() => callback());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Grabs the language off of navigator for browser compatibility.
|
* Grabs the language off of navigator for browser compatibility.
|
||||||
* If the language isn't set, then it falls back to the DEFAULT_LOCALE. The
|
* If the language isn't set, then it falls back to the DEFAULT_LOCALE. The
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ export default ['i18n', function(i18n) {
|
|||||||
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: {
|
ALLOW_OAUTH2_FOR_EXTERNAL_USERS: {
|
||||||
type: 'toggleSwitch',
|
type: 'toggleSwitch',
|
||||||
},
|
},
|
||||||
|
LOGIN_REDIRECT_OVERRIDE: {
|
||||||
|
type: 'text',
|
||||||
|
reset: 'LOGIN_REDIRECT_OVERRIDE'
|
||||||
|
},
|
||||||
ACCESS_TOKEN_EXPIRE_SECONDS: {
|
ACCESS_TOKEN_EXPIRE_SECONDS: {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
reset: 'ACCESS_TOKEN_EXPIRE_SECONDS'
|
reset: 'ACCESS_TOKEN_EXPIRE_SECONDS'
|
||||||
|
|||||||
@@ -1,55 +1,40 @@
|
|||||||
export default
|
export default
|
||||||
function LoadConfig($log, $rootScope, $http, Store) {
|
function LoadConfig($rootScope, Store) {
|
||||||
return function() {
|
return function() {
|
||||||
|
|
||||||
|
|
||||||
var configSettings = {};
|
var configSettings = {};
|
||||||
|
|
||||||
var configInit = function() {
|
if(global.$ConfigResponse.custom_logo) {
|
||||||
// Auto-resolving what used to be found when attempting to load local_setting.json
|
configSettings.custom_logo = true;
|
||||||
if ($rootScope.loginConfig) {
|
$rootScope.custom_logo = global.$ConfigResponse.custom_logo;
|
||||||
$rootScope.loginConfig.resolve('config loaded');
|
} else {
|
||||||
}
|
configSettings.custom_logo = false;
|
||||||
$rootScope.$emit('ConfigReady');
|
}
|
||||||
|
|
||||||
// Load new hardcoded settings from above
|
if(global.$ConfigResponse.custom_login_info) {
|
||||||
|
configSettings.custom_login_info = global.$ConfigResponse.custom_login_info;
|
||||||
|
$rootScope.custom_login_info = global.$ConfigResponse.custom_login_info;
|
||||||
|
} else {
|
||||||
|
configSettings.custom_login_info = false;
|
||||||
|
}
|
||||||
|
|
||||||
global.$AnsibleConfig = configSettings;
|
if (global.$ConfigResponse.login_redirect_override) {
|
||||||
Store('AnsibleConfig', global.$AnsibleConfig);
|
configSettings.login_redirect_override = global.$ConfigResponse.login_redirect_override;
|
||||||
$rootScope.$emit('LoadConfig');
|
}
|
||||||
};
|
|
||||||
|
|
||||||
// Retrieve the custom logo information - update configSettings from above
|
// Auto-resolving what used to be found when attempting to load local_setting.json
|
||||||
$http({
|
if ($rootScope.loginConfig) {
|
||||||
method: 'GET',
|
$rootScope.loginConfig.resolve('config loaded');
|
||||||
url: '/api/',
|
}
|
||||||
})
|
global.$AnsibleConfig = configSettings;
|
||||||
.then(function({data}) {
|
Store('AnsibleConfig', global.$AnsibleConfig);
|
||||||
if(data.custom_logo) {
|
$rootScope.$emit('ConfigReady');
|
||||||
configSettings.custom_logo = true;
|
|
||||||
$rootScope.custom_logo = data.custom_logo;
|
|
||||||
} else {
|
|
||||||
configSettings.custom_logo = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data.custom_login_info) {
|
// Load new hardcoded settings from above
|
||||||
configSettings.custom_login_info = data.custom_login_info;
|
$rootScope.$emit('LoadConfig');
|
||||||
$rootScope.custom_login_info = data.custom_login_info;
|
|
||||||
} else {
|
|
||||||
configSettings.custom_login_info = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
configInit();
|
|
||||||
|
|
||||||
}).catch(({error}) => {
|
|
||||||
$log.debug(error);
|
|
||||||
configInit();
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadConfig.$inject =
|
LoadConfig.$inject =
|
||||||
[ '$log', '$rootScope', '$http',
|
[ '$rootScope', 'Store' ];
|
||||||
'Store'
|
|
||||||
];
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from awx.main.views import (
|
|||||||
handle_404,
|
handle_404,
|
||||||
handle_500,
|
handle_500,
|
||||||
handle_csp_violation,
|
handle_csp_violation,
|
||||||
|
handle_login_redirect,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ urlpatterns = [
|
|||||||
url(r'^(?:api/)?404.html$', handle_404),
|
url(r'^(?:api/)?404.html$', handle_404),
|
||||||
url(r'^(?:api/)?500.html$', handle_500),
|
url(r'^(?:api/)?500.html$', handle_500),
|
||||||
url(r'^csp-violation/', handle_csp_violation),
|
url(r'^csp-violation/', handle_csp_violation),
|
||||||
|
url(r'^login/', handle_login_redirect),
|
||||||
]
|
]
|
||||||
|
|
||||||
if settings.SETTINGS_MODULE == 'awx.settings.development':
|
if settings.SETTINGS_MODULE == 'awx.settings.development':
|
||||||
|
|||||||
Reference in New Issue
Block a user