Multi Tenancy

1. Allgemeines

Mit der Intrexx-Mandantenfähigkeit wird eine weiche Datentrennung in großen, zusammenhängenden Unternehmensstrukturen ermöglicht. Bei mehreren Mandanten wird der Aufbau und die Bedienung (z.B. in Intranets) an vielen Stellen sehr vereinfacht. Auch für B2B und B2C bietet die Mandantenfähigkeit wertvolle Unterstützung. Da es sich um eine weiche Datentrennung handelt, ist eine isolierte Dateiablage und der Export eines Portals mit den Daten nur eines Mandanten nicht möglich.

2. Multi Tenancy im Modul Benutzer




Grundlage für die Mandantensteuerung sind die drei Objekte in der Benutzerverwaltung. Es können beliebige eigene neue Objekte definiert werden, die als Mandant wirken können.

2.1. Mandantenabhängigkeit erstellen




Mit der folgenden, sehr einfachen Struktur zeigen wir Ihnen, wie Sie Benutzerobjekte mit Mandanten verknüpfen können. Benutzer A wird dabei dem Mandanten "Organisationseinheit 1", Benutzer B dem Mandanten "Organisationseinheit 2" und Benutzer C beiden Mandanten zugeordnet. Die beiden Organisationseinheiten weisen keine Besonderheiten auf, sie sind mit der Basisklasse Organisationseinheit erstellt. Es muss also nicht zwingend das Objekt Mandant verwendet werden, um einen Mandanten zu erzeugen.



Im ersten Schritt wird das Benutzer-Objekt, das einem Mandanten zugewiesen werden soll, im Schemamanager bearbeitet. In unserem Beispiel sollen die Benutzer A, B und C einem Mandanten zugewiesen werden. Diese Benutzer basieren auf der Klasse Benutzer. Ist die Klasse im linken Bereich des Schemamanagers markiert, kann über das Menü "Bearbeiten / Neues Attribut" ein Attribut für diesen Zweck erstellt werden - in unserem Beispiel hier das Attribut "Organisationszuordnung". Werden einem Objekt mehrere Mandanten zugeordnet (1:n), sollte als Typ für das Datenfeld "Text" gewählt werden, damit eine Liste von Mandantenzugehörigkeiten gespeichert werden kann. Besteht nur eine 1:1 Zuordnung und wird zudem ein String-Feld als Referenzattribut bestimmt, kann auch ein String-Datenfeld verwendet werden.



Damit das Attribut "Organisationszuordnung" für das Speichern der Mandanten-ID verwendet wird, wird die Einstellung "Enthält Mandanten-ID" aktiviert. Mit Klick auf "Referenz bearbeiten" wird ein Dialog geöffnet, in dem die Referenz bearbeitet werden kann.



Für unser Beispiel wird hier die Klasse "Organisationseinheit" ausgewählt, weil "Organisationseinheit 1" und "Organisationseinheit 2" wie zu Beginn beschrieben auf Basis dieser Klasse erstellt wurden. ES kann ein beliebiges Referenz-Attribut bestimmt werden, d.h. nicht nur die LID oder GUID, sondern auch ein anderes Attribut, das einen eindeutigen Identifikationswert enthält (z.B. Organisationskürzel, Kostenstelle). Auch das Anzeigeattribut der referenzierten Klasse kann frei bestimmt werden. Hier wählen wir den Objektnamen aus. Damit Benutzer C beiden Mandanten zugeordnet werden kann, wird die Einstellung "Mehrfachreferenz zulassen" aktiviert.

Wenn alle Dialoge mit Klick auf "OK" geschlossen werden, ist die Mandantenabhängigkeit eingerichtet.

2.2. Mandantenzuordnung




In den Eigenschaften eines Benutzers kann der der Mandant nun auf dem Reiter Weitere Attribute zugordnet werden. Markieren Sie dazu das Attribut, das Sie für die Mandantenabhängigkeit erstellt haben und klicken Sie in der Spalte "Wert" auf "Wert bearbeiten". Für unser Beispiel wird Benutzer A der Organisationseinheit 1, Benutzer B der Organisationseinheit 2 und Benutzer C beiden Organisationseinheiten zugeordnet.

3. Multi Tenancy in Applikationen

3.1. Mandantensteuerung in Datengruppen




Eine strenge Mandantensteuerung erfolgt über den Mandantenfilter in den Datengruppen. Dort kann der Bezug der Mandantenmitgliedschaft des Benutzers zum Datensatz hergestellt werden. Es gibt eine n:1 Bindung direkt in der Datengruppe oder eine n:n Bindung über eine Kinddatengruppe, die pro Datensatz beliebige multiple Mandantenzuordnungen ermöglicht.

3.2. Mandantensteuerung in Filtern

Bei Tabellen, Auswahllisten, Mehrfachauswahl und Datapicker gibt es den neuen Operator "Ist enthalten in Mandanten". Wird mit der BenutzerID verglichen, werden nur die dem entsprechenden Mandanten zugeordneten Einträge angezeigt.

3.3. Mandantensteuerung in Verteilern

Im Element Mehrfachauswahl können mit der Einstellung Verteilerauswahl beliebige Objekte zur Definition eines Verteilers ausgewählt werden. Die Objekte können mit einem Filter belegt werden, z.B. um nur Benutzer oder Rollen anzubieten, die dem Mandanten des aktuellen Benutzers zugeordnet sind.

4. Groovy-API

Die API in Groovy ermöglicht Hier ein entsprechendes Skript-Beispiel:
// Erzeuge "Organisation"

def strTitle = g_record["GUID"].value /* datafield Titel <string> */
def strParentNode = g_record["GUID"].value /* datafield Mandant <string> */

def organization1 = g_om.createContainer ("ORGANIZATION", {
       container      = strParentNode
       NAME           = strTitle
       EXTERNALGUID   = "1235"
       PRIORITY       = 25
       DN             = "testDN"
       DISABLED       = false
       DESCRIPTION    = "Von Groovy um ${new Date()} angelegte Organisation"
       INTERNALUSN    = 2
       STATE          = "BW"
       POBOX          = "UP"
       STREET         = "UP-Allee"
       ISOCOUNTRYCODE = "DE"
       CITY           = "Freiburg"
       POSTALCODE     = "79098"
       COUNTRY        = "Deutschland"
})

// Erzeuge "Standard Rollen"
def role1 = g_om.createSet ("ROLE", {
	container      = organization1
	NAME           = strTitle + ": Mitarbeiter"
	DESCRIPTION    = "Von Groovy um ${new Date()} angelegte Rolle"
	memberOf       = ["Benutzer"]
})

// Erzeuge "Zusatzrollen"
def role2 = g_om.createSet ("ROLE", {
	container      = organization1
	NAME           = strTitle + ": Sammeluser"
	DESCRIPTION    = "Von Groovy um ${new Date()} angelegte Rolle"
	memberOf       = ["Benutzer"]
})

// Rollen löschen
g_om.deleteSet(role1.GUID)
 
// Container löschen (Alle enthalten Objekte werden auch gelöscht!)
g_om.deleteContainer(containerBase1.GUID)
Um die Mandantenmitgliedschaften eines angemeldeten Benutzers sowie die für die Session ausgewählten Mandantenobjekte zu ermitteln, steht im Groovy-Kontext der GroovyTenantHelper zur Verfügung. Bei der Definition eines GroovyTenantHelper-Objekts wird als Parameter die aktuelle Session mitgegeben. Darüber hinaus kann mit dem GroovyTenantHelper auch die Auswahl der aktiven Mandanten in der Session geändert werden. Die Varianten als Zeichenkettenliste (||) ermöglicht die direkte Verarbeitung von Verteiler- bzw. Mehrfachauswahl-Informationen aus Longtext-Feldern.
// Importieren der Klasse
import de.uplanet.lucy.server.usermanager.groovy.GroovyTenantHelper

// Definition eines neuen TenantHelper-Objekts
def thelper = new  GroovyTenantHelper(g_session)

//
thelper.getTenants():Set<String>
thelper.getSelectedTenants():Set<String>
thelper.getAllTenantValues():String getrennt durch ||
thelper.getSelectedTenantValues():String getrennt durch ||

// Einen aktiven Mandanten bestimmen
thelper.setSelectedTenant(String)

// Mehrere aktiven Mandanten bestimmen. Die Definition erfolgt durch eine Liste der Mandanten
thelper.setSelectedTenants(Set<String>)

// Mehrere aktiven Mandanten bestimmen. Die Definition der 
// Mandanten erfolgt in Form einer Liste als Zeichenkette mit || 
// Trennung (piped)
thelper.setSelectedTenants(String)
thelper.setSelectedTenants("MANDANT1_ID||MANDANT2_ID")

// Anzeige des Namens des ersten Mandanten
def tenantList = g_session.getTenants().get(0).getTitle()

// Prüfen ob erste Mandant ausgewählt ist
g_session.getTenants().tenantList.get(0).isSelected()

// ID des Mandanten
g_session.getTenants().tenantList.get(0).getValue()
import de.uplanet.lucy.server.ServerFeature

// Ermittelt die Einstellung im Portal, welche die Auswahl des aktiven 
// Mandanten auf Einen Mandanten beschränkt

ServerFeature.isSingleTenantMode()

5. Velocity-API

Die API in Velocity ermöglicht
## Prüfung auf Mandantenübereinstimmung (Benutzer – Datensatz)
#set($TenantMembersSelected = $Tenants.getAllTenantValues($Session))
#set($TenantMembersList = $TextUtil.stringToArray($TenantMembersSelected))
#set($TenantMembersSqlList = $TextUtil.arrayToString($TenantMembersList,",","'"))

#set($stmtTable = $PreparedQuery.prepare($DbConnection, 
"SELECT STR_TITEL FROM DATAGROUP('GUID') WHERE STR_MANDANT IN (?)"))
$stmtTable.setString(1, $TenantMembersSql)
#set($rsTable = $stmtTable.executeQuery())

#foreach($element in $rsTable)
	#set($Title = $element.getStringValue(1))
	$Title <br>
#end
$rsTable.close()
$stmtTable.close()

## Objekt-Information auslesen (Attribute)
#set($ObjectGuid = "8808E768D142663695576F533A27E5CAC2739552")
#set($stmtObject = $PreparedQuery.prepare($DbConnection, "SELECT STRIDENT FROM VDSTENANT WHERE STRGUID = ?"))
$stmtObject.setString(1, $ObjectGuid)
#set($ObjectIdent= $stmtObject.executeAndGetScalarStringValue(""))
$stmtObject.close()
Für die Mandanten werden mit dem $Tenants-Objekt die folgenden Methoden bereitgestellt:
## Liste aller Mandanten des aktuellen Benutzers
$Tenants.getTenants($Session)

## Liste aller ausgewählten Mandanten des aktuellen Benutzers/Session
$Tenants.getSelectedTenants($Session)

## Piped-Liste aller ausgewählten Mandanten des aktuellen Benutzers
$Tenants.getSelectedTenantValues ($Session)

## Anzahl der Mandanten des aktuellen Benutzers
$Tenants.getTenants($Session).size()

## Alle Mandanten des aktuellen Benutzers als Zeichenkettenliste 
## (mit || Trennung)
$Tenants.getAllTenantValues($Session)

## Anzahl der ausgewählten Mandanten
$Tenants.getSelectedCount($Session))
Auf die Liste der Tenant-Objekte (getTenants / getSelectedTenants) können folgende Methoden angewendet werden:
## Anzeige des Namens des ersten Mandanten
#set($TenantList = $Tenants.getTenants($Session))
$TenantList.get(0).getTitle()

## Prüfen ob erste Mandant ausgewählt ist
$TenantList.get(0).isSelected()

## ID des Mandanten
$TenantList.get(0).getValue()

6. Weitere Informationen

Parameter-Dialog
Velocity Docs
Groovy Docs