Multi Tenancy

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.

Multi Tenancy im Modul "Benutzer"

Grundlage für die Mandantensteuerung sind die drei Objekte

  • Land

  • Mandant

  • Ort

im Modul "Benutzer". Im Schemamanager können beliebige eigene neue Objekte definiert werden, die als Mandant wirken können.

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.

Mandantenzuordnung

In den Eigenschaften eines Benutzers kann der Mandant nun auf dem Reiter "Weitere Attribute" zugeordnet 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.

Multi Tenancy in Applikationen

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.

Mandantensteuerung in Filtern

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

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.

Groovy-API

Die API in Groovy ermöglicht

  • Die Anlage von Objekten zur Definition von Mandanten und Organisationsstrukturen

  • Die Anlage von Gruppen, Rollen, Verteilern und deren Mitgliedschaft in anderen Objekten

  • Das Bearbeiten aller Objekte

  • Das Löschen aller Objekte

Hier ein entsprechendes Skript-Beispiel:

// Create "Organisation"

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

def organization1 = g_om.createContainer ("ORGANIZATION", {
       container      = strParentNode
       NAME           = strTitle
       EXTERNALGUID   = "1235"
       PRIORITY       = 25
       DN             = "testDN"
       DISABLED       = false
       DESCRIPTION    = "Organization created by Groovy around ${new Date()}"
       INTERNALUSN    = 2
       STATE          = "BW"
       POBOX          = "UP"
       STREET         = "UP-Alley"
       ISOCOUNTRYCODE = "DE"
       CITY           = "Freiburg"
       POSTALCODE     = "79098"
       COUNTRY        = "Germany"
})

// Create "default roles"
def role1 = g_om.createSet ("ROLE", {
	container      = organization1
	NAME           = strTitle + ": Employee"
	DESCRIPTION    = "Role created by Groovy on ${new Date()}"
	memberOf       = ["Users"]
})

// Create "additional roles"
def role2 = g_om.createSet ("ROLE", {
	container      = organization1
	NAME           = strTitle + ": User"
	DESCRIPTION    = "Role created by Groovy on ${new Date()}"
	memberOf       = ["Users"]
})

// Delete roles
g_om.deleteSet(role1.GUID)
 
// Delete container (All included objects will also be deleted!)
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.

// Import of class
import de.uplanet.lucy.server.usermanager.groovy.GroovyTenantHelper

// Definition of a new TenantHelper object
def thelper = new  GroovyTenantHelper(g_session)

//
thelper.getTenants():Set<String>thelper.getSelectedTenants():Set<String>thelper.getAllTenantValues():String seperated by ||
thelper.getSelectedTenantValues():String seperated by ||

// Define an active tenant
thelper.setSelectedTenant(String)

// Define multiple active tenants - the definition is made by a list of tenants
thelper.setSelectedTenants(Set<String>)

//Define multiple active tenants - the definition
// of tenants is made in the form of a list as a string seperated by || 

thelper.setSelectedTenants(String)
thelper.setSelectedTenants("TENANT1_ID||TENANT2_ID")
import de.uplanet.lucy.server.ServerFeature

// Determines the setting in the portal that determines the selection of the active 
// tenants limited to one tenant

ServerFeature.isSingleTenantMode()

Velocity-API

Die API in Velocity ermöglicht

  • die Prüfung der Mandanten-Mitgliedschaft (Benutzerobjekt gegen Mandatenobjekt)

  • die Ermittlung von Attributen eines Objekts (Mandant, Organisation, Organisationseinheit, Rolle, Gruppe)

## Check for tenant match (user - record)
#set($TenantMembersSelected = $Tenants.getAllTenantValues($Session))
#set($TenantMembersSqlList = $TenantMembersSelected.replace("||", "','") )

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

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

## Read object information (attributes)
#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:

## List of all tenants of the current user
$Tenants.getTenants($Session)

## List of all selected tenants of the current user/session
$Tenants.getSelectedTenants($Session)

## Piped-List of all selected tenants of the current user
$Tenants.getSelectedTenantValues ($Session)

## Number of tenants of the current user
$Tenants.getTenants($Session).size()

## All tenants of the current user as string list 
## (seperated by ||)
$Tenants.getAllTenantValues($Session)

## Number of selected tenants
$Tenants.getSelectedCount($Session))

Auf die Liste der Tenant-Objekte (getTenants / getSelectedTenants) können folgende Methoden angewendet werden:

## Display of the name of the first tenant
#set($TenantList = $Tenants.getTenants($Session))
$TenantList.get(0).getTitle()

## Check if first tenant is selected
$TenantList.get(0).isSelected()

## ID of the tenant
$TenantList.get(0).getValue()

Weitere Informationen

Parameter-Dialog

Velocity Docs

Groovy Docs