Commit 3bb0dfeb authored by Jochen Kressin's avatar Jochen Kressin
Browse files

make global and private tenant optiona, closes...

make global and private tenant optiona, closes floragunncom/search-guard-module-kibana-multitenancy#1
parent d2755a5d
......@@ -36,7 +36,11 @@ export default function (kibana) {
}).default(),
}).default(),
multitenancy: Joi.object().keys({
enabled: Joi.boolean().default(false)
enabled: Joi.boolean().default(false),
tenants: Joi.object().keys({
enable_private: Joi.boolean().default(true),
enable_global: Joi.boolean().default(true),
}).default(),
}).default()
}).default();
return obj;
......
......@@ -16,6 +16,7 @@
import Boom from 'boom';
import Joi from 'joi';
import { isEmpty } from 'lodash';
module.exports = function (pluginRoot, server, kbnServer, APP_ROOT, API_ROOT) {
......@@ -57,7 +58,8 @@ module.exports = function (pluginRoot, server, kbnServer, APP_ROOT, API_ROOT) {
}
request.auth.session.set(session);
return reply({
username: user.username
username: user.username,
tenants: user.tenants
});
} catch (error) {
if (error instanceof AuthenticationError) {
......
......@@ -33,6 +33,13 @@ export default class User {
return this._roles;
}
/**
* @property {Array} tenants - The user tenants.
*/
get tenants() {
return this._tenants;
}
/**
* @property {object} credentials - The credentials that were used to authenticate the user.
*/
......@@ -48,11 +55,12 @@ export default class User {
return this._proxyCredentials;
}
constructor(username, credentials, proxyCredentials, roles) {
constructor(username, credentials, proxyCredentials, roles, tenants) {
this._username = username;
this._credentials = credentials;
this._proxyCredentials = proxyCredentials;
this._roles = roles;
this._tenants = tenants;
}
}
......@@ -39,7 +39,7 @@ export default class SearchGuardBackend {
authorization: `Basic ${authHeader}`
}
});
return new User(credentials.username, credentials, credentials, response.sg_roles);
return new User(credentials.username, credentials, credentials, response.sg_roles, response.sg_tenants);
} catch(error) {
if (error.status == 401) {
throw new AuthenticationError();
......
......@@ -45,7 +45,30 @@ export default function LoginController($scope, $http, $window) {
$http.post(`${API_ROOT}/login`, this.credentials)
.then(
(response) => {
$window.location.href = `${ROOT}/`;
// validate the tenant settings if multi tenancy is enabled
// if MT is disabled, or the GLOBAL tenant is enabled,
// no further checks are necessary. In the first case MT does not
// matter, in the latter case we always have a tenant as fallback if
// user has no tenants configured and PRIVATE is disabled
if (!chrome.getInjected("multitenancy.enabled") || chrome.getInjected("multitenancy.tenants.enable_global")) {
$window.location.href = `${ROOT}/`;
} else {
// GLOBAL is disabled, check if we have at least one tenant to choose from
var allTenants = response.data.tenants;
// if private tenant is disabled, remove it
if(allTenants != null && !chrome.getInjected("multitenancy.tenants.enable_private")) {
delete allTenants[response.data.username];
}
// check that we have at least one tenant to fall back to
if (allTenants == null || allTenants.length == 0 || _.isEmpty(allTenants)) {
this.errorMessage = 'No tenant available for this user, please contact your system administrator.';
} else {
// todo: choose default tenant based on user preferences and available tenants
$window.location.href = `${ROOT}/`;
}
}
},
(error) => {
if (error.status && error.status === 401) {
......
......@@ -3,37 +3,34 @@
<div class="col-12-sm">
<h1 class="text-center">Available tenants</h1>
<p class="error-message" ng-if="ctrl.errorMessage">{{ ctrl.errorMessage }}</p>
<h3 class="text-center" ng-bind="ctrl.tenantLabel"></h3>
<h4 class="text-center" ng-bind="ctrl.tenantLabel" style="margin-bottom:15px;"></h4>
<table class="table">
<thead>
<tr>
<th class="col-xs-4 col-sm-4">Name</th>
<th class="col-xs-4 col-sm-4">Permissions</th>
<th class="col-xs-4 col-sm-4">Comment</th>
<th class="col-xs-4 col-sm-4">Action</th>
<th>Name</th>
<th>Permissions</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-class="{'active': ctrl.currentTenant == ''}">
<tr ng-class="{'active': ctrl.currentTenant == ''}" ng-show="ctrl.globalEnabled">
<td>
{{ctrl.GLOBAL_USER_LABEL}}
</td>
<td>
<div>read/write</div>
</td>
<td>Shared with all users</td>
<td class="actions">
<button class="btn-primary" ng-disabled="ctrl.currentTenant == ''" ng-show="ctrl.currentTenant != ctrl.GLOBAL_USER_VALUE" ng-click="ctrl.selectTenant(ctrl.GLOBAL_USER_LABEL, ctrl.GLOBAL_USER_VALUE)">Choose</button>
</td>
</tr>
<tr ng-class="{'active': ctrl.currentTenant == ctrl.PRIVATE_USER_VALUE}">
<tr ng-class="{'active': ctrl.currentTenant == ctrl.PRIVATE_USER_VALUE}" ng-show="ctrl.privateEnabled">
<td>
{{ctrl.PRIVATE_USER_LABEL}}
</td>
<td>
<div>read/write</div>
</td>
<td>Your private space, shared with no one</td>
<td class="actions">
<button class="btn-primary" ng-disabled="ctrl.currentTenant == ctrl.PRIVATE_USER_VALUE" ng-click="ctrl.selectTenant(ctrl.PRIVATE_USER_LABEL, ctrl.PRIVATE_USER_VALUE)">Choose</button>
</td>
......@@ -47,7 +44,6 @@
<div ng-if="ctrl.alltenants[tenantkey] == 'rw'">read/write</div>
<div ng-if="ctrl.alltenants[tenantkey] == 'ro'">read only</div>
</td>
<td></td>
<td class="actions">
<button class="btn-primary" ng-disabled="ctrl.currentTenant == tenantkey" ng-click="ctrl.selectTenant(tenantkey, tenantkey)">Choose</button>
</td>
......
......@@ -38,6 +38,9 @@ uiModules
var APP_ROOT = `${chrome.getBasePath()}/searchguard`;
var API_ROOT = `${APP_ROOT}/api/v1`;
this.privateEnabled = chrome.getInjected("multitenancy.tenants.enable_private");
this.globalEnabled = chrome.getInjected("multitenancy.tenants.enable_global");
this.GLOBAL_USER_LABEL = "Global";
this.GLOBAL_USER_VALUE = null;
this.PRIVATE_USER_LABEL = "Private";
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment