Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Changelog
All notable changes to this project will be documented in this file.

## 5.0.0
### Changed
- store configurations in a separate database table, not appconfig

### Added
- occ commands for modifying SAML configurations

### Removed
- Ability to change SAML configuration with occ app-config, use the new occ commands instead

## 4.1.0
### Added
- Nextcloud 22 support
Expand Down
13 changes: 2 additions & 11 deletions appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,8 @@
\OC::$server->getLogger()->logException($e);
return;
}
$samlSettings = new \OCA\User_SAML\SAMLSettings(
$urlGenerator,
$config,
$request,
$session
);

$samlSettings = \OC::$server->query(\OCA\User_SAML\SAMLSettings::class);

$userData = new \OCA\User_SAML\UserData(
new \OCA\User_SAML\UserResolver(\OC::$server->getUserManager()),
Expand Down Expand Up @@ -72,11 +68,6 @@
$type = '';
switch ($config->getAppValue('user_saml', 'type')) {
case 'saml':
try {
$oneLoginSettings = new \OneLogin\Saml2\Settings($samlSettings->getOneLoginSettingsArray(1));
} catch (\OneLogin\SAML2\Error $e) {
$returnScript = true;
}
$type = 'saml';
break;
case 'environment-variable':
Expand Down
6 changes: 5 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The following providers are supported and tested at the moment:
* Any other provider that authenticates using the environment variable

While theoretically any other authentication provider implementing either one of those standards is compatible, we like to note that they are not part of any internal test matrix.]]></description>
<version>4.3.0</version>
<version>5.0.0</version>
<licence>agpl</licence>
<author>Lukas Reschke</author>
<namespace>User_SAML</namespace>
Expand All @@ -36,6 +36,10 @@ While theoretically any other authentication provider implementing either one of
<nextcloud min-version="21" max-version="24" />
</dependencies>
<commands>
<command>OCA\User_SAML\Command\ConfigCreate</command>
<command>OCA\User_SAML\Command\ConfigDelete</command>
<command>OCA\User_SAML\Command\ConfigGet</command>
<command>OCA\User_SAML\Command\ConfigSet</command>
<command>OCA\User_SAML\Command\GetMetadata</command>
</commands>
<settings>
Expand Down
31 changes: 29 additions & 2 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,47 @@
'url' => '/saml/selectUserBackEnd',
'verb' => 'GET',
],
[
'name' => 'Settings#getSamlProviderIds',
'url' => '/settings/providers',
'verb' => 'GET',
],
[
'name' => 'Settings#getSamlProviderSettings',
'url' => '/settings/providerSettings/{providerId}',
'verb' => 'GET',
'defaults' => [
'providerId' => '1'
'providerId' => 1
],
'requirements' => [
'providerId' => '\d+'
]
],
[
'name' => 'Settings#setProviderSetting',
'url' => '/settings/providerSettings/{providerId}',
'verb' => 'PUT',
'defaults' => [
'providerId' => 1
],
'requirements' => [
'providerId' => '\d+'
]
],
[
'name' => 'Settings#newSamlProviderSettingsId',
'url' => '/settings/providerSettings',
'verb' => 'POST',
],
[
'name' => 'Settings#deleteSamlProviderSettings',
'url' => '/settings/providerSettings/{providerId}',
'verb' => 'DELETE',
'defaults' => [
'providerId' => '1'
'providerId' => 1
],
'requirements' => [
'providerId' => '\d+'
]
],
[
Expand Down
178 changes: 113 additions & 65 deletions js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,30 @@
currentConfig: '1',
providerIds: '1',

_getAppConfig: function (key) {
return $.ajax({
type: 'GET',
url: OC.linkToOCS('apps/provisioning_api/api/v1', 2) + 'config/apps' + '/user_saml/' + key + '?format=json'
});
},
init: function(callback) {
this._getAppConfig('providerIds').done(function (data){
if (data.ocs.data.data !== '') {
OCA.User_SAML.Admin.providerIds = data.ocs.data.data;
OCA.User_SAML.Admin.currentConfig = OCA.User_SAML.Admin.providerIds.split(',').sort()[0];
var xhr = new XMLHttpRequest();
xhr.open('GET', OC.generateUrl('/apps/user_saml/settings/providers'));
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('requesttoken', OC.requestToken);

xhr.onload = function () {
var response = JSON.parse(xhr.response);
if (xhr.status >= 200 && xhr.status < 300) {
if (response.providerIds !== "") {
OCA.User_SAML.Admin.providerIds += ',' + response.providerIds;
OCA.User_SAML.Admin.currentConfig = OCA.User_SAML.Admin.providerIds.split(',')[0];
}
callback();
} else {
console.error("Could not fetch new provider ID");
}
callback();
});
};
xhr.onerror = function () {
console.error("Could not fetch new provider ID");
}


xhr.send();
},
chooseEnv: function() {
if (OC.PasswordConfirmation.requiresPasswordConfirmation()) {
Expand Down Expand Up @@ -60,23 +70,49 @@

/**
* Add a new provider
* @returns {number} id of the provider
*/
addProvider: function(callback) {
var providerIds = OCA.User_SAML.Admin.providerIds.split(',');
var nextId = 1;
if (providerIds.indexOf('1') >= 0) {
nextId = 2;
while ($.inArray('' + nextId, providerIds) >= 0) {
nextId++;
addProvider: function (callback) {
var xhr = new XMLHttpRequest();
xhr.open('POST', OC.generateUrl('/apps/user_saml/settings/providerSettings'));
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.setRequestHeader('requesttoken', OC.requestToken)

xhr.onload = function () {
var response = JSON.parse(xhr.response)
if (xhr.status >= 200 && xhr.status < 300) {
OCA.User_SAML.Admin.providerIds += ',' + response.id;
callback(response.id)
} else {
console.error("Could not fetch new provider ID")
}
}
OCP.AppConfig.setValue('user_saml', 'providerIds', OCA.User_SAML.Admin.providerIds + ',' + nextId, {
success: function () {
OCA.User_SAML.Admin.providerIds += ',' + nextId;
callback(nextId)
};
xhr.onerror = function () {
console.error("Could not fetch new provider ID");
};

xhr.send();
},

updateProvider: function (configKey, configValue, successCb, errorCb) {
var xhr = new XMLHttpRequest();
xhr.open('PUT', OC.generateUrl('/apps/user_saml/settings/providerSettings/' + this.currentConfig));
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('requesttoken', OC.requestToken);

xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
successCb();
} else {
console.error("Could not update config");
errorCb();
}
});
};
xhr.onerror = function () {
console.error("Could not update config");
errorCb();
};

xhr.send(JSON.stringify({configKey: configKey, configValue: configValue.trim()}));
},

removeProvider: function(callback) {
Expand All @@ -86,17 +122,8 @@
if (index > -1) {
providerIds.splice(index, 1);
}
var config = this.currentConfig;
$.ajax({ url: OC.generateUrl('/apps/user_saml/settings/providerSettings/' + this.currentConfig), type: 'DELETE'})
.done(function(data) {
OCP.AppConfig.setValue('user_saml', 'providerIds', providerIds.join(','), {
success: function () {
OCA.User_SAML.Admin.providerIds = providerIds.join(',');
callback(config);
}
});
});

.done(callback(this.currentConfig));
}
},

Expand All @@ -105,14 +132,22 @@
OC.PasswordConfirmation.requirePasswordConfirmation(_.bind(this.setSamlConfigValue, this, category, setting, value));
return;
}
// store global config flags without idp prefix
var configIdentifier = this.getConfigIdentifier();
if (global === true) {
configIdentifier = '';
}
OC.msg.startSaving('#user-saml-save-indicator');
OCP.AppConfig.setValue('user_saml', configIdentifier + category + '-' + setting, value.trim());
OC.msg.finishedSaving('#user-saml-save-indicator', {status: 'success', data: {message: t('user_saml', 'Saved')}});

var callbacks = {
success: function () {
OC.msg.finishedSaving('#user-saml-save-indicator', {status: 'success', data: {message: t('user_saml', 'Saved')}});
},
error: function() {
OC.msg.finishedSaving('#user-saml-save-indicator', {status: 'error', data: {message: t('user_saml', 'Could not save')}});
}
};

if (global) {
OCP.AppConfig.setValue('user_saml', category + '-' + setting, value, callbacks);
return;
}
this.updateProvider(category + '-' + setting, value, callbacks.success, callbacks.error);
}
}
})(OCA);
Expand Down Expand Up @@ -175,35 +210,48 @@ $(function() {
$('.account-list li[data-id="' + providerId + '"]').addClass('active');
OCA.User_SAML.Admin.currentConfig = '' + providerId;
$.get(OC.generateUrl('/apps/user_saml/settings/providerSettings/' + providerId)).done(function(data) {
Object.keys(data).forEach(function(category, index){
document.querySelectorAll('#user-saml-settings input[type="text"], #user-saml-settings textarea').forEach(function (inputNode) {
inputNode.value = '';
});
document.querySelectorAll('#user-saml-settings input[type="checkbox"]').forEach(function (inputNode) {
inputNode.checked = false;
inputNode.setAttribute('value', '0');
});
document.querySelectorAll('#user-saml-settings select option').forEach(function (inputNode) {
inputNode.selected = false;
});

Object.keys(data).forEach(function(category){
var entries = data[category];
Object.keys(entries).forEach(function (configKey) {
var element = $('#user-saml-settings *[data-key="' + configKey + '"]');
if ($('#user-saml-settings #user-saml-' + category + ' #user-saml-' + configKey).length) {
element = $('#user-saml-' + category + ' #user-saml-' + configKey);
}
if ($('#user-saml-settings #user-saml-' + category + ' [name="' + configKey + '"]').length) {
element = $('#user-saml-' + category + ' [name="' + configKey + '"]');
}
if(element.is('input') && element.prop('type') === 'text') {
element.val(entries[configKey])
}
else if(element.is('textarea')) {
element.val(entries[configKey]);
var htmlElement = document.querySelector('#user-saml-settings *[data-key="' + configKey + '"]')
|| document.querySelector('#user-saml-' + category + ' #user-saml-' + configKey)
|| document.querySelector('#user-saml-' + category + ' [name="' + configKey + '"]');

if (!htmlElement) {
console.log("could not find element for " + configKey);
return;
}
else if(element.prop('type') === 'checkbox') {
var value = entries[configKey] === '1' ? '1' : '0';
element.val(value);

if ((htmlElement.tagName === 'INPUT' && htmlElement.getAttribute('type') === 'text')
|| htmlElement.tagName === 'TEXTAREA'
) {
htmlElement.nodeValue = entries[configKey];
htmlElement.value = entries[configKey];
} else if (htmlElement.tagName === 'INPUT' && htmlElement.getAttribute('type') === 'checkbox') {
htmlElement.checked = entries[configKey] === '1';
htmlElement.value = entries[configKey] === '1' ? '1' : '0';
} else if (htmlElement.tagName === 'SELECT') {
htmlElement.querySelector('[value="' + entries[configKey] + '"]').selected = true;
} else {
console.log('unable to find element for ' + configKey);
console.error("Could not handle " + configKey + " Tag is " + htmlElement.tagName + " and type is " + htmlElement.getAttribute("type"));
}
});
});
$('input:checkbox[value="1"]').attr('checked', true);
$('input:checkbox[value="0"]').attr('checked', false);
var xmlDownloadButton = $('#get-metadata');
var url = xmlDownloadButton.data('base') + '?idp=' + providerId;
xmlDownloadButton.attr('href', url);

var xmlDownloadButton = document.getElementById('get-metadata');
var url = xmlDownloadButton.dataset.base + '?idp=' + providerId;
xmlDownloadButton.setAttribute('href', url);
});
};

Expand Down
4 changes: 3 additions & 1 deletion lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

use OCA\User_SAML\DavPlugin;
use OCA\User_SAML\Middleware\OnlyLoggedInMiddleware;
use OCA\User_SAML\SAMLSettings;
use OCP\AppFramework\App;
use OCP\AppFramework\IAppContainer;
use OCP\SabrePluginEvent;
Expand All @@ -48,7 +49,8 @@ public function __construct(array $urlParams = []) {
return new DavPlugin(
$server->getSession(),
$server->getConfig(),
$_SERVER
$_SERVER,
$server->get(SAMLSettings::class)
);
});

Expand Down
Loading