1
0
mirror of https://github.com/sismics/docs.git synced 2025-12-26 16:11:42 +00:00

LDAP support, courtesy of an anonymous donator

This commit is contained in:
bgamard
2020-08-28 18:09:54 +02:00
parent 6dc4f1b448
commit a9719feeec
20 changed files with 597 additions and 6 deletions

View File

@@ -14,6 +14,7 @@ import com.sismics.docs.core.model.jpa.File;
import com.sismics.docs.core.service.InboxService;
import com.sismics.docs.core.util.ConfigUtil;
import com.sismics.docs.core.util.DirectoryUtil;
import com.sismics.docs.core.util.authentication.LdapAuthenticationHandler;
import com.sismics.docs.core.util.jpa.PaginatedList;
import com.sismics.docs.core.util.jpa.PaginatedLists;
import com.sismics.docs.rest.constant.BaseFunction;
@@ -696,4 +697,138 @@ public class AppResource extends BaseResource {
.add("status", "ok");
return Response.ok().entity(response.build()).build();
}
/**
* Get the LDAP authentication configuration.
*
* @api {get} /app/config_ldap Get the LDAP authentication configuration
* @apiName GetAppConfigLdap
* @apiGroup App
* @apiSuccess {Boolean} enabled LDAP authentication enabled
* @apiSuccess {String} host LDAP server host
* @apiSuccess {Integer} port LDAP server port
* @apiSuccess {String} admin_dn Admin DN
* @apiSuccess {String} admin_password Admin password
* @apiSuccess {String} base_dn Base DN
* @apiSuccess {String} filter LDAP filter
* @apiSuccess {String} default_email LDAP default email
* @apiSuccess {Integer} default_storage LDAP default storage
* @apiError (client) ForbiddenError Access denied
* @apiPermission admin
* @apiVersion 1.9.0
*
* @return Response
*/
@GET
@Path("config_ldap")
public Response getConfigLdap() {
if (!authenticate()) {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
ConfigDao configDao = new ConfigDao();
Config enabled = configDao.getById(ConfigType.LDAP_ENABLED);
JsonObjectBuilder response = Json.createObjectBuilder();
if (enabled != null && Boolean.parseBoolean(enabled.getValue())) {
// LDAP enabled
response.add("enabled", true)
.add("host", ConfigUtil.getConfigStringValue(ConfigType.LDAP_HOST))
.add("port", ConfigUtil.getConfigIntegerValue(ConfigType.LDAP_PORT))
.add("admin_dn", ConfigUtil.getConfigStringValue(ConfigType.LDAP_ADMIN_DN))
.add("admin_password", ConfigUtil.getConfigStringValue(ConfigType.LDAP_ADMIN_PASSWORD))
.add("base_dn", ConfigUtil.getConfigStringValue(ConfigType.LDAP_BASE_DN))
.add("filter", ConfigUtil.getConfigStringValue(ConfigType.LDAP_FILTER))
.add("default_email", ConfigUtil.getConfigStringValue(ConfigType.LDAP_DEFAULT_EMAIL))
.add("default_storage", ConfigUtil.getConfigLongValue(ConfigType.LDAP_DEFAULT_STORAGE));
} else {
// LDAP disabled
response.add("enabled", false);
}
return Response.ok().entity(response.build()).build();
}
/**
* Configure the LDAP authentication.
*
* @api {post} /app/config_ldap Configure the LDAP authentication
* @apiName PostAppConfigLdap
* @apiGroup App
* @apiParam {Boolean} enabled LDAP authentication enabled
* @apiParam {String} host LDAP server host
* @apiParam {Integer} port LDAP server port
* @apiParam {String} admin_dn Admin DN
* @apiParam {String} admin_password Admin password
* @apiParam {String} base_dn Base DN
* @apiParam {String} filter LDAP filter
* @apiParam {String} default_email LDAP default email
* @apiParam {Integer} default_storage LDAP default storage
* @apiError (client) ForbiddenError Access denied
* @apiError (client) ValidationError Validation error
* @apiPermission admin
* @apiVersion 1.9.0
*
* @param enabled LDAP authentication enabled
* @param host LDAP server host
* @param portStr LDAP server port
* @param adminDn Admin DN
* @param adminPassword Admin password
* @param baseDn Base DN
* @param filter LDAP filter
* @param defaultEmail LDAP default email
* @param defaultStorageStr LDAP default storage
* @return Response
*/
@POST
@Path("config_ldap")
public Response configLdap(@FormParam("enabled") Boolean enabled,
@FormParam("host") String host,
@FormParam("port") String portStr,
@FormParam("admin_dn") String adminDn,
@FormParam("admin_password") String adminPassword,
@FormParam("base_dn") String baseDn,
@FormParam("filter") String filter,
@FormParam("default_email") String defaultEmail,
@FormParam("default_storage") String defaultStorageStr) {
if (!authenticate()) {
throw new ForbiddenClientException();
}
checkBaseFunction(BaseFunction.ADMIN);
ConfigDao configDao = new ConfigDao();
if (enabled != null && enabled) {
// LDAP enabled, validate everything
ValidationUtil.validateLength(host, "host", 1, 250);
ValidationUtil.validateInteger(portStr, "port");
ValidationUtil.validateLength(adminDn, "admin_dn", 1, 250);
ValidationUtil.validateLength(adminPassword, "admin_password", 1, 250);
ValidationUtil.validateLength(baseDn, "base_dn", 1, 250);
ValidationUtil.validateLength(filter, "filter", 1, 250);
if (!filter.contains("USERNAME")) {
throw new ClientException("ValidationError", "'filter' must contains 'USERNAME'");
}
ValidationUtil.validateLength(defaultEmail, "default_email", 1, 250);
ValidationUtil.validateLong(defaultStorageStr, "default_storage");
configDao.update(ConfigType.LDAP_ENABLED, Boolean.TRUE.toString());
configDao.update(ConfigType.LDAP_HOST, host);
configDao.update(ConfigType.LDAP_PORT, portStr);
configDao.update(ConfigType.LDAP_ADMIN_DN, adminDn);
configDao.update(ConfigType.LDAP_ADMIN_PASSWORD, adminPassword);
configDao.update(ConfigType.LDAP_BASE_DN, baseDn);
configDao.update(ConfigType.LDAP_FILTER, filter);
configDao.update(ConfigType.LDAP_DEFAULT_EMAIL, defaultEmail);
configDao.update(ConfigType.LDAP_DEFAULT_STORAGE, defaultStorageStr);
} else {
// LDAP disabled
configDao.update(ConfigType.LDAP_ENABLED, Boolean.FALSE.toString());
}
// Reset the LDAP pool to reconnect with the new configuration
LdapAuthenticationHandler.reset();
return Response.ok().build();
}
}

View File

@@ -244,6 +244,15 @@ angular.module('docs',
}
}
})
.state('settings.ldap', {
url: '/ldap',
views: {
'settings': {
templateUrl: 'partial/docs/settings.ldap.html',
controller: 'SettingsLdap'
}
}
})
.state('document', {
url: '/document',
abstract: true,

View File

@@ -0,0 +1,33 @@
'use strict';
/**
* Settings LDAP page controller.
*/
angular.module('docs').controller('SettingsLdap', function($scope, Restangular, $translate, $timeout) {
$scope.ldap = {
enabled: false
};
// Get the LDAP configuration
Restangular.one('app/config_ldap').get().then(function (data) {
$scope.ldap = data;
if ($scope.ldap.default_storage) {
$scope.ldap.default_storage /= 1000000;
}
});
// Edit SMTP config
$scope.saveResult = undefined;
$scope.save = function () {
var ldap = angular.copy($scope.ldap);
if (ldap.default_storage) {
ldap.default_storage *= 1000000;
}
Restangular.one('app').post('config_ldap', ldap).then(function () {
$scope.saveResult = $translate.instant('settings.ldap.saved');
$timeout(function() {
$scope.saveResult = undefined;
}, 5000);
});
};
});

View File

@@ -94,6 +94,7 @@
<script src="app/docs/controller/settings/SettingsGroupEdit.js" type="text/javascript"></script>
<script src="app/docs/controller/settings/SettingsVocabulary.js" type="text/javascript"></script>
<script src="app/docs/controller/settings/SettingsMetadata.js" type="text/javascript"></script>
<script src="app/docs/controller/settings/SettingsLdap.js" type="text/javascript"></script>
<script src="app/docs/controller/usergroup/UserGroup.js" type="text/javascript"></script>
<script src="app/docs/controller/usergroup/UserProfile.js" type="text/javascript"></script>
<script src="app/docs/controller/usergroup/GroupProfile.js" type="text/javascript"></script>

View File

@@ -278,8 +278,22 @@
"menu_vocabularies": "Vocabularies",
"menu_configuration": "Configuration",
"menu_inbox": "Inbox scanning",
"menu_ldap": "LDAP authentication",
"menu_metadata": "Custom metadata",
"menu_monitoring": "Monitoring",
"ldap": {
"title": "LDAP authentication",
"enabled": "Enable LDAP authentication",
"host": "LDAP hostname",
"port": "LDAP port (389 by default)",
"admin_dn": "Admin DN",
"admin_password": "Admin password",
"base_dn": "Base search DN",
"filter": "Search filter (must contains USERNAME, eg. \"(uid=USERNAME)\")",
"default_email": "Default email for LDAP user",
"default_storage": "Default storage for LDAP user",
"saved": "LDAP configuration saved successfully"
},
"user": {
"title": "Users management",
"add_user": "Add a user",

View File

@@ -278,7 +278,21 @@
"menu_vocabularies": "Vocabulaires",
"menu_configuration": "Configuration",
"menu_inbox": "Scanning de boîte de réception",
"menu_ldap": "Authentification LDAP",
"menu_monitoring": "Monitoring",
"ldap": {
"title": "Authentification LDAP",
"enabled": "Activer l'authentication LDAP",
"host": "Hôte LDAP",
"port": "Port LDAP (389 par défaut)",
"admin_dn": "DN administrateur",
"admin_password": "Mot de passe administrateur",
"base_dn": "DN de recherche",
"filter": "Filtre de recherche (doit contenir USERNAME, cf. \"(uid=USERNAME)\")",
"default_email": "Email par défaut pour les utilisateurs LDAP",
"default_storage": "Stockage par défaut pour les utilisateurs LDAP",
"saved": "Configuration IMAP sauvegardée avec succès"
},
"user": {
"title": "Gestion des utilisateurs",
"add_user": "Ajouter un utilisateur",

View File

@@ -20,6 +20,7 @@
<a class="list-group-item" ui-sref-active="{ active: 'settings.config.**' }" href="#/settings/config">{{ 'settings.menu_configuration' | translate }}</a>
<a class="list-group-item" ui-sref-active="{ active: 'settings.metadata.**' }" href="#/settings/metadata">{{ 'settings.menu_metadata' | translate }}</a>
<a class="list-group-item" ui-sref-active="{ active: 'settings.inbox.**' }" href="#/settings/inbox">{{ 'settings.menu_inbox' | translate }}</a>
<a class="list-group-item" ui-sref-active="{ active: 'settings.ldap.**' }" href="#/settings/ldap">{{ 'settings.menu_ldap' | translate }}</a>
<a class="list-group-item" ui-sref-active="{ active: 'settings.monitoring.**' }" href="#/settings/monitoring">{{ 'settings.menu_monitoring' | translate }}</a>
</ul>
</div>

View File

@@ -0,0 +1,88 @@
<h2 translate="settings.ldap.title"></h2>
<form class="form-horizontal" name="form" novalidate>
<div class="form-group">
<label class="col-sm-2 control-label" for="ldapEnabled">{{ 'settings.ldap.enabled' | translate }}</label>
<div class="col-sm-7">
<input name="enabled" type="checkbox" id="ldapEnabled" ng-model="ldap.enabled" />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.hostname.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapHost">{{ 'settings.ldap.host' | translate }}</label>
<div class="col-sm-7">
<input name="hostname" type="text" class="form-control" id="ldapHost" ng-model="ldap.host" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.port.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapPort">{{ 'settings.ldap.port' | translate }}</label>
<div class="col-sm-7">
<input name="port" type="number" class="form-control" id="ldapPort" ng-model="ldap.port" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.adminDn.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapAdminDn">{{ 'settings.ldap.admin_dn' | translate }}</label>
<div class="col-sm-7">
<input name="adminDn" type="text" class="form-control" id="ldapAdminDn" ng-model="ldap.admin_dn" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.adminPassword.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapAdminPassword">{{ 'settings.ldap.admin_password' | translate }}</label>
<div class="col-sm-7">
<input name="adminPassword" type="password" class="form-control" id="ldapAdminPassword" ng-model="ldap.admin_password" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.baseDn.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapBaseDn">{{ 'settings.ldap.base_dn' | translate }}</label>
<div class="col-sm-7">
<input name="baseDn" type="text" class="form-control" id="ldapBaseDn" ng-model="ldap.base_dn" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.filter.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapFilter">{{ 'settings.ldap.filter' | translate }}</label>
<div class="col-sm-7">
<input name="filter" type="text" class="form-control" id="ldapFilter"
ng-pattern="/(USERNAME)+/"
ng-model="ldap.filter" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.defaultEmail.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapDefaultEmail">{{ 'settings.ldap.default_email' | translate }}</label>
<div class="col-sm-7">
<input name="defaultEmail" type="text" class="form-control" id="ldapDefaultEmail" ng-model="ldap.default_email" ng-maxlength="250" required />
</div>
</div>
<div ng-if="ldap.enabled" class="form-group" ng-class="{ 'has-error': !form.defaultStorage.$valid && form.$dirty }">
<label class="col-sm-2 control-label" for="ldapDefaultStorage">{{ 'settings.ldap.default_storage' | translate }}</label>
<div class="col-sm-7">
<div class="input-group">
<input name="defaultStorage" type="number" id="ldapDefaultStorage" required class="form-control"
ng-pattern="/[0-9]*/" ng-model="ldap.default_storage"/>
<div class="input-group-addon">{{ 'filter.filesize.mb' | translate }}</div>
</div>
</div>
<div class="col-sm-3">
<span class="help-block" ng-show="form.default_storage.$error.pattern && form.$dirty">{{ 'validation.number' | translate }}</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-primary" ng-click="save()" ng-disabled="!form.$valid">
<span class="fas fa-pencil-alt"></span> {{ 'save' | translate }}
</button>
</div>
</div>
</form>
<div class="alert col-sm-9 alert-success"
ng-show="saveResult">
{{ saveResult }}
</div>