mirror of
https://git.proxmox.com/git/pmg-gui
synced 2025-10-04 15:16:24 +00:00
login: add option to login with OIDC realm
By adding a viewModel with an oidc variable, the username & password fields are disabled/hidden when an OIDC realm is selected. Signed-off-by: Markus Frank <m.frank@proxmox.com>
This commit is contained in:
parent
693821d36b
commit
4a5079c806
149
js/LoginView.js
149
js/LoginView.js
@ -2,6 +2,21 @@ Ext.define('PMG.LoginView', {
|
|||||||
extend: 'Ext.container.Container',
|
extend: 'Ext.container.Container',
|
||||||
xtype: 'loginview',
|
xtype: 'loginview',
|
||||||
|
|
||||||
|
viewModel: {
|
||||||
|
data: {
|
||||||
|
oidc: false,
|
||||||
|
},
|
||||||
|
formulas: {
|
||||||
|
button_text: function(get) {
|
||||||
|
if (get("oidc") === true) {
|
||||||
|
return gettext("Login (OpenID Connect redirect)");
|
||||||
|
} else {
|
||||||
|
return gettext("Login");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
controller: {
|
controller: {
|
||||||
xclass: 'Ext.app.ViewController',
|
xclass: 'Ext.app.ViewController',
|
||||||
|
|
||||||
@ -46,19 +61,23 @@ Ext.define('PMG.LoginView', {
|
|||||||
|
|
||||||
submitForm: async function() {
|
submitForm: async function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
let view = me.getView();
|
|
||||||
let loginForm = me.lookupReference('loginForm');
|
|
||||||
var unField = me.lookupReference('usernameField');
|
|
||||||
var saveunField = me.lookupReference('saveunField');
|
|
||||||
|
|
||||||
if (loginForm.isValid()) {
|
let loginForm = this.lookupReference('loginForm');
|
||||||
|
let unField = this.lookupReference('usernameField');
|
||||||
|
let saveunField = this.lookupReference('saveunField');
|
||||||
|
let view = this.getView();
|
||||||
|
|
||||||
|
if (!loginForm.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (loginForm.isVisible()) {
|
if (loginForm.isVisible()) {
|
||||||
loginForm.mask(gettext('Please wait...'), 'x-mask-loading');
|
loginForm.mask(gettext('Please wait...'), 'x-mask-loading');
|
||||||
}
|
}
|
||||||
|
|
||||||
// set or clear username for admin view
|
// set or clear username for admin view
|
||||||
if (view.targetview !== 'quarantineview') {
|
if (view.targetview !== 'quarantineview') {
|
||||||
var sp = Ext.state.Manager.getProvider();
|
let sp = Ext.state.Manager.getProvider();
|
||||||
if (saveunField.getValue() === true) {
|
if (saveunField.getValue() === true) {
|
||||||
sp.set(unField.getStateId(), unField.getValue());
|
sp.set(unField.getStateId(), unField.getValue());
|
||||||
} else {
|
} else {
|
||||||
@ -69,6 +88,30 @@ Ext.define('PMG.LoginView', {
|
|||||||
|
|
||||||
let creds = loginForm.getValues();
|
let creds = loginForm.getValues();
|
||||||
|
|
||||||
|
if (this.getViewModel().data.oidc === true) {
|
||||||
|
const redirectURL = location.origin;
|
||||||
|
Proxmox.Utils.API2Request({
|
||||||
|
url: '/api2/extjs/access/oidc/auth-url',
|
||||||
|
params: {
|
||||||
|
realm: creds.realm,
|
||||||
|
"redirect-url": redirectURL,
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
success: function(resp, opts) {
|
||||||
|
window.location = resp.result.data;
|
||||||
|
},
|
||||||
|
failure: function(resp, opts) {
|
||||||
|
Proxmox.Utils.authClear();
|
||||||
|
loginForm.unmask();
|
||||||
|
Ext.MessageBox.alert(
|
||||||
|
gettext('Error'),
|
||||||
|
gettext('OpenID Connect redirect failed.') + `<br>${resp.htmlStatus}`,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let resp = await Proxmox.Async.api2({
|
let resp = await Proxmox.Async.api2({
|
||||||
url: '/api2/extjs/access/ticket',
|
url: '/api2/extjs/access/ticket',
|
||||||
@ -90,7 +133,6 @@ Ext.define('PMG.LoginView', {
|
|||||||
gettext('Login failed. Please try again'),
|
gettext('Login failed. Please try again'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
performTFAChallenge: async function(data) {
|
performTFAChallenge: async function(data) {
|
||||||
@ -115,6 +157,15 @@ Ext.define('PMG.LoginView', {
|
|||||||
return resp.result.data;
|
return resp.result.data;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
success: function(data) {
|
||||||
|
let me = this;
|
||||||
|
let view = me.getView();
|
||||||
|
let handler = view.handler || Ext.emptyFn;
|
||||||
|
handler.call(me, data);
|
||||||
|
PMG.Utils.updateLoginData(data);
|
||||||
|
PMG.app.changeView(view.targetview);
|
||||||
|
},
|
||||||
|
|
||||||
openQuarantineLinkWindow: function() {
|
openQuarantineLinkWindow: function() {
|
||||||
let me = this;
|
let me = this;
|
||||||
me.lookup('loginwindow').setVisible(false);
|
me.lookup('loginwindow').setVisible(false);
|
||||||
@ -150,6 +201,14 @@ Ext.define('PMG.LoginView', {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'field[name=realm]': {
|
||||||
|
change: function(f, value) {
|
||||||
|
let record = f.store.getById(value);
|
||||||
|
if (record === undefined) return;
|
||||||
|
let data = record.data;
|
||||||
|
this.getViewModel().set("oidc", data.type === "oidc");
|
||||||
|
},
|
||||||
|
},
|
||||||
'button[reference=quarantineButton]': {
|
'button[reference=quarantineButton]': {
|
||||||
click: 'openQuarantineLinkWindow',
|
click: 'openQuarantineLinkWindow',
|
||||||
},
|
},
|
||||||
@ -161,19 +220,54 @@ Ext.define('PMG.LoginView', {
|
|||||||
let me = this;
|
let me = this;
|
||||||
let view = me.getView();
|
let view = me.getView();
|
||||||
if (view.targetview !== 'quarantineview') {
|
if (view.targetview !== 'quarantineview') {
|
||||||
var sp = Ext.state.Manager.getProvider();
|
let sp = Ext.state.Manager.getProvider();
|
||||||
var checkboxField = this.lookupReference('saveunField');
|
let checkboxField = this.lookupReference('saveunField');
|
||||||
var unField = this.lookupReference('usernameField');
|
let unField = this.lookupReference('usernameField');
|
||||||
|
|
||||||
var checked = sp.get(checkboxField.getStateId());
|
let checked = sp.get(checkboxField.getStateId());
|
||||||
checkboxField.setValue(checked);
|
checkboxField.setValue(checked);
|
||||||
|
|
||||||
if (checked === true) {
|
if (checked === true) {
|
||||||
var username = sp.get(unField.getStateId());
|
let username = sp.get(unField.getStateId());
|
||||||
unField.setValue(username);
|
unField.setValue(username);
|
||||||
var pwField = this.lookupReference('passwordField');
|
let pwField = this.lookupReference('passwordField');
|
||||||
pwField.focus();
|
pwField.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let auth = Proxmox.Utils.getOpenIDRedirectionAuthorization();
|
||||||
|
if (auth !== undefined) {
|
||||||
|
Proxmox.Utils.authClear();
|
||||||
|
|
||||||
|
let loginForm = this.lookupReference('loginForm');
|
||||||
|
loginForm.mask(gettext('OpenID Connect login - please wait...'), 'x-mask-loading');
|
||||||
|
|
||||||
|
const redirectURL = location.origin;
|
||||||
|
|
||||||
|
Proxmox.Utils.API2Request({
|
||||||
|
url: '/api2/extjs/access/oidc/login',
|
||||||
|
params: {
|
||||||
|
state: auth.state,
|
||||||
|
code: auth.code,
|
||||||
|
"redirect-url": redirectURL,
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
failure: function(response) {
|
||||||
|
loginForm.unmask();
|
||||||
|
let error = response.htmlStatus;
|
||||||
|
Ext.MessageBox.alert(
|
||||||
|
gettext('Error'),
|
||||||
|
gettext('OpenID Connect login failed, please try again') + `<br>${error}`,
|
||||||
|
() => { window.location = redirectURL; },
|
||||||
|
);
|
||||||
|
},
|
||||||
|
success: function(response, options) {
|
||||||
|
loginForm.unmask();
|
||||||
|
let data = response.result.data;
|
||||||
|
history.replaceState(null, '', redirectURL);
|
||||||
|
me.success(data);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -250,6 +344,10 @@ Ext.define('PMG.LoginView', {
|
|||||||
reference: 'usernameField',
|
reference: 'usernameField',
|
||||||
stateId: 'login-username',
|
stateId: 'login-username',
|
||||||
inputAttrTpl: 'autocomplete=username',
|
inputAttrTpl: 'autocomplete=username',
|
||||||
|
bind: {
|
||||||
|
visible: "{!oidc}",
|
||||||
|
disabled: "{oidc}",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'textfield',
|
xtype: 'textfield',
|
||||||
@ -258,6 +356,17 @@ Ext.define('PMG.LoginView', {
|
|||||||
name: 'password',
|
name: 'password',
|
||||||
reference: 'passwordField',
|
reference: 'passwordField',
|
||||||
inputAttrTpl: 'autocomplete=current-password',
|
inputAttrTpl: 'autocomplete=current-password',
|
||||||
|
bind: {
|
||||||
|
visible: "{!oidc}",
|
||||||
|
disabled: "{oidc}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
xtype: 'pmxRealmComboBox',
|
||||||
|
reference: 'realmfield',
|
||||||
|
name: 'realm',
|
||||||
|
baseUrl: '/access/auth-realm',
|
||||||
|
value: 'pam',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
xtype: 'proxmoxLanguageSelector',
|
xtype: 'proxmoxLanguageSelector',
|
||||||
@ -266,12 +375,6 @@ Ext.define('PMG.LoginView', {
|
|||||||
name: 'lang',
|
name: 'lang',
|
||||||
submitValue: false,
|
submitValue: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
xtype: 'hiddenfield',
|
|
||||||
reference: 'realmfield',
|
|
||||||
name: 'realm',
|
|
||||||
value: 'pmg',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
{
|
{
|
||||||
@ -283,15 +386,19 @@ Ext.define('PMG.LoginView', {
|
|||||||
labelAlign: 'right',
|
labelAlign: 'right',
|
||||||
labelWidth: 150,
|
labelWidth: 150,
|
||||||
submitValue: false,
|
submitValue: false,
|
||||||
|
bind: {
|
||||||
|
visible: "{!oidc}",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: gettext('Request Quarantine Link'),
|
text: gettext('Request Quarantine Link'),
|
||||||
reference: 'quarantineButton',
|
reference: 'quarantineButton',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: gettext('Login'),
|
bind: {
|
||||||
|
text: "{button_text}",
|
||||||
|
},
|
||||||
reference: 'loginButton',
|
reference: 'loginButton',
|
||||||
formBind: true,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user