## VKC mit Anbindung an eine Datenbank

Version 1.1: 24.07.2002
Version 1.2: 30.07.2002
Version 1.3: 31.07.2002
Version 1.4: 07.08.2002
Version 1.5: 09.08.2002

- Zum Geleit
- Einführung
- Funktionalitäten
- Entitäten
- Funktionale Abhängigkeiten
- Datenbankschema (konzeptionell und physikalisch)
- Tabellen
- Szenarien
- Was ein Admin darf (implzite Rechte)
- Offene Punkte
- Dies und das

dokumente mit einer aclid verbinden...

### Zum Geleit

Programmers don't comment! What was hard to write, should be hard to read !

### Einführung

In einer vergangen VKC-KR wurde die Anbindung von VKC an eine Datenbank beschlossen.Um eine große Flexibilität bzgl. der DatenbankManagementSystem zu erreichen, soll der Zugriff auf die Daten mittels JDBC erfolgen!

Die Benutzung einer Datenbank bietet folgende Vorteile:

- Focussierung auf das Anwendungsdesign (Art&Weise der Speicherung interessieren nicht mehr)
- Universal (Verschiedene Datenbanken sind verwendbar), Zugriff mittels z.B. JDBC
- Änderung von Daten auch durch DB-GUI möglich
- Konsistente Erweiterung der Daten einfach und schnell zu bewerkstelligen
- Abhängigkeit der Daten untereinander ist klar und transparent (vorgegeben durch das relationale Schema)
- Auswertungen / Statistiken realtiv leicht zu handbaben
- Durch Verwendung von IDs eindeutige und einfache Zuordnung von Entitäten möglich (Document / Category / ...)
  gerade bei Referenzierung durch WebPages
- Datenbank hat i.d.R. Transaktionsmechanimus: Konsistenz von Daten ist gewährleistet
- Falls Datenbank Triggermechanismus besitzt, können über das Einfügen/Ändern/Löschen bestimmte Aktionen angestossen werden

Dem stehen diese Nachteile gegenüber:

- Hierarchische Strukturen sind u.U. schwierig darzustellen
- evt Performance-Probleme
- DB ist zwingend erforderlich (Kosten !)
- Umgang mit IDs erhöht u.U. nicht Lesbarkeit (z.B. ID=20, ja welche Category ist das denn ?)

### Funktionalitäten

Das in diesem Dokument vorgestellte Datenbank-Schema bietet folgende Funktionalitäten:

- Verwaltung von Categorie-Daten
- Verwaltung von Dokumenten-Daten
- Verwaltung von User-Daten und User-Gruppen
- Verwaltung der Zugriffsrechte auf Categorien und Dokumente
- Mögliche Erweiterung: Verwaltung von Konfigurationsdaten für das VKC-System
- Verwaltung von Start- und Laufzeit-Parameter

Die Zugriffsrechte werden über Zugriffslisten (AccessControlLists ACL) realisiert.

Eine ACL ist beispielhaft:

Categorie | AccessorType | Accessor | Rechte | Beschreibung
Für `"TestCategorie"` haben implizit User/Gruppen mit AdminBerechtigung ALLE Rechte
`"TestCategorie"` | "USER" | <id des owners> | `RWCc` | Für den Owner werden (automatisch) alle Rechte angelegt ! Dadurch ist gewährleistet, dass a) der Owner alle Rechte hat (inclusive das Recht, die ACL zu verändern (c) b) der Administrator dem Owner aber Rechte entziehen kann c) es gibt kein A-Recht mehr, welches nicht disjunkt zu den anderen REchten wäre
d) es der Owner jetzt in der Hand hat, wem er an der Categorie /dem Dokument/Gruppe noch weitereichendere Rechte zugesteht.
`"TestCategorie"` | "USER" | `User1` | `RWC-` | User1 darf TestCategorie Lesen(R), Schreiben(W) und Verändern(C)
`"TestCategorie"` | "USER" | `User2` | `R---` | User1 darf TestCategorie Lesen(R)
`"TestCategorie"` | "GROUP" | `Group1` | `R---` | Gruppe1 darf TestCategorie Lesen(R)
`"TestCategorie"` | "ANYOTHER" | null | `R---` | Ein nicht authentisierter Benutzer darf diese Categorie lesen (Public-Access)
`"TestCategorie"` | "MASK" | null | `-W--` | Maskierung der resultierenden Rechte mit XOR Dient z.B. dafür, das man temporär ein Recht ausschalten kann (Beispiel): User hat nominell `"RW--"`. Ein XOR mit `"-W--"` ergibt ein effektives Recht mit `"R---"` !!! Dem User wurde das R-Recht entzogen und zwar solange, bis der Mask-Eintrag geändert bzw. gelöscht wird.

Dieser Eintrag sollte nur einmal pro ACL vorkommen !!!

Die Definition der Rechte (bzw. der Token wie R/U/...) sind (global) frei wählbar. Die Semantik ergibt sich aus dem Kontext der Anwendung.

I.d.R. wird vom Benutzer eine Aktion angestossen, die ein bestimmtes Recht erfordert. Vom System muß dann geprüft werden, ob der Benutzer dieses Recht hat. Ein andere Fragestellung ist, welche Rechte ein Benutzer an einem gegebenen Objekt überhaupt hat.

Die Datenbank realisiert somit die Autorisierung ("hat Benutzer XYZ das Recht a?"). Die Authenisierung ("Ist Benutzer XYZ auch wirklich der, der er vorgibt zu sein" (Realiserung mit User/Password-Tupel) wird NICHT durch die Datenbank implementiert. Dies muß durch andere Komponenten des VKC-Systems erfolgen.

*** Wichtige Änderung zum Vorgängerdokument ***
Besondere Beachtung verdienen User/Gruppen mit AdminBerechtigung: Sie haben implizit alle Rechte. Dies gilt global für jedwelchen rechtlich geschützen Zugriff. Für den Eigentümer der Categorie/des Dokumentes wird beim Anlegen ein Datensatz in den ACLs angelegt, der diesem "Owener"-User alle Rechte zuordnet.
Dadurch ist gewährleistet, dass
a) der Owner alle Rechte hat (inclusive das Recht, die ACL zu verändern (c)
b) der Administrator dem Owner aber Rechte entziehen kann (Admin hat ja implizit alle Rechte)
c) es gibt kein A-Recht mehr, welches nicht disjunkt zu den anderen Rechten wäre
d) es der Owner jetzt in der Hand hat, wem er an der Categorie noch weitereichende Rechte zugesteht.

Um bestimmten Benutzern einen zeitlich beschränken Zugriff auf das System zu ermöglichen, kann bei jedem User- oder Gruppen-Account vermerkt werden, von wann bis wann der derselbe gültig ist (Feld "ValidFrom/ValidUntil", nur User/Gruppen mit Admin-Berechtigung sollten das setzten können): Ist das Feld "NULL" liegt keine Zeitbeschränkung vor, ansonsten gibt es das Datum des letzten möglichen Zugriffs vor (Zugriff solange AccountValidUntil >= today).

Für Gästezugriffe (auch Public-Zugriffe genannt), soll heißen Benutzer, die dem System (namentlich) nicht bekannt sind, gibt es die Möglichkeit, in den ACLs für die jeweilige Categorie / Dokuments einen Eintrag vom Typ "ANYOTHER" (ohne Angabe einer UserID) zu hinterlegen.

Um bestimmte Rechte temporär ausschalten zu können (z.B. aus Gründen der Wartung des Systems) gibt es die Möglichkeit, einen Eintrag vom Typ "MASK" anzulegen. Falls dieser Eintrag vorliegt, wird jeder Zugriffsprüfung (ausgenommen AdminUser/Groups, NICHT OWNER !!!) nochmals mit dem Eintrag unter MASK "XOR(Exclusiv oder)" verknüpft. Damit kann man gezielt Rechte ausblenden und dem Anwender für eine gewisse Zeit entziehen. Und zwar solange, wie der entsprechende MASK-Eintrag existiert bzw. nicht verändert wird.

Die ACLs beschreiben Zugriffsmöglichkeiten für gegebene Dokumente bzw. Kategorien. Um festzulegen, wer überhaupt Categorien initial anlegen darf bzw. Gruppen anlegen darf, wurde eine weitere Tabelle (UserPermissions) geschaffen, die festlegt, welchem User soetwas zugebilligt wird. Ebenfalls gibt es eine ACL bzgl der Gruppen, die bestimmt, wer aus der entsprechenden Gruppe Mitglieder löschen oder neu hinzufügen darf (GroupACL).

Eine Weiterführung des ACL-Konzeptes wäre die Einführung einer ObjectACL. Mit dieser ACL könnten beliebige Objekte /Resourcen geschützt werden (z.B. User, Systemeinstellungen, Prozesse etc.). Bei Zugriff auf ein so beschriebenes Object kann in gewohnter Weise die Rechte dafür abgefragt werden.
Um dieses zu implementieren müssten zwei weitere Tabellen angelegt werden: Object (Beschreibung des Objectes und Vergabe einer ID) sowie ObjectACL (Verwaltung der Rechte mit Bezug auf die Object-Tabelle)

*** Wichtige Änderung zum Vorgänger-Dokument ***
Früher wurden beliebige ACL-Einträge einem Dokument zugeordnet. Da jetzt bei den Dokumenten eine Versionierung (mit Verweis auf das Vorgänger-Dokument erfolgen kann, hatte das den Nachteil, das die ACL-Einträge für das neue Dokument anhand derer des alten "geclont werden" mussten. Daher wurde jetzt eine Änderung vorgenommen: Jedem Dokument ist jetzt eine ACL zugeordnet, die aus mehreren Einträgen besteht. Bei Neuanlage eines Dokumentes braucht nur noch dann die entsprechende ACL-ID übernommen werden.

Wie im weiteren Verlauf dieses Dokumentes ersichtlich ,erfolgt die Überprüfung der Rechte in der Datenbank, die auch die Informationen für die Categorien, Dokumente. Das hat den Vorteil, dass dieses System sich als abgeschlossenes präsentiert. Es ist somit möglich, sämtliche Daten auf ein anderes System zu portieren ohne das darauf geachtet werden muss, andere "Datenquellen" mit zu verschieben.

Als mögliche Erweiterung des Rechtesystem kann noch eine weitere Tabelle eingeführt werden, die die Namen der (JAVA-) Funktion verwaltet und deren benötigten Rechte. Somit kann bei Aufruf einer Funktion dieselbe nachschauen, welches Recht benötigt, um sie ausführen zu können.

Eventuell kann das hier vorgestellte Rechtesystem mittels der Klassen von "java.security.acl" aufgebaut werden !!!

Viele Tabellen weisen auch als Bearbeitungsmerker einen Zeitstempel auf (LastChanged/LastChangedUserID). Das ist zwar ein erhöhter Aufwand, hat aber den Vorteil, das somit Zuständigkeiten vermerkt werden, auf die im Falle eines Konfliktes ("Bei mir funktionerts nicht mehr! Ich habe nichts gemacht" oder "Wer hat mir denn das Recht entzogen?") verwiesen werden kann.

Mittels der Tabelle SysParameters können Parameter für den Systemstart bzw. Laufzeitparameter für das System hinterlegt werden.

*** Wichtige Änderungen zum Vorgänger-Dokument ***

- Das vorhandene System erlaubt eine Versionierung von Dokumenten und zwar derart, dass bei jedem Dokument die ID seines Vorgängers vermerkt ist. Dadurch ist es möglich, verkettete Strukturen zu schaffen
- Wenn ein Dokument in einer bestimmten Version in ein anderes Format überführt wird, wird dieses ebenfalls vermerkt: Es gilt das Prinzip: Wenn für eine bestimmte Version (Documents) ein zusätzliches Dokument erstellt wird, wird das entsprechend vermerkt (AdditionalDocumentFormats)
- Ein User erhält noch ein zusätzliches Attribut, das bestimmt, ob er Benutzergruppen anlegen darf
- GroupACLs: Rechte bzgl. Gruppen (Member anlegen, löschen, ACL ändern, Gruppe löschen): Wie bei den Cat/DocACLs bekommt der Owner einen Eintrag (unter "USER", der ihm alle Rechte zubilligt.
- Die Attribute "Path" wurden aus den Entities Document und Category entfernt. Diese Eigenschaft kann sich (u.U. durch wiederholtes oder rekursives Aufrufen) "zusammengebaut werden
- Dynamische Attribute: Um gegenüber möglichen Erweiterung gewappnet u sein, wurde die Tabelle "DynAttributes" angelegt. Diese Tabelle pflegt alle möglichen zusätzlichen Attribute. Die einzelen Entitäten (User, Docuemts, Cartegories) können sich über Zwischentabellen (UserDynAttributes,...) daztu verlinken

WICHTIG: Aufgrund des Datenbankschemas ist es notwendig, das Datenbanken benutzt werden, die einen Transaktionsmechanismus implementiert haben. Viele Aktionen (siehe Szenarien) bestehen aus den verschiedensten Prozess-Schritten. Kann eine Aktion nicht korrekt ausgeführt werden, so müssen die vorherigen Aktionen wieder zurückgesetzt werden, um die Datenintegrität zu gewährleisten. Dieses kann am besten (und ohne zusäzlichen Aufwand) mit einem Transaktionsmechanismus sichergestellt werden.

### Entitäten

Folgende grundlegende Entitäten wurden für VKC indentifiziert

Entity | Description
--- | ---
Document | Dokumente (PDF; EXE; XLS; MDB, TXT, DOC, HTML,...)
Category | Verzeichnis
Keyword | Schlüsselwörter
Lexicon | Lexikon
User | Benutzer
Group | Benutzergruppe
Acl | Access Control List (Zugriffsliste)
Permission | Zugriffsrechte
SearchEngine | Suchmaschinen
SysParameter | System Parameter (Parameter für den Systemstart/Laufzeit von VKC)
DynAttributes | Dynamische Attribute
Synonyms | Synonyme für bestehende Schlüsselwörter

### Funktionale Abhängigkeiten

Entity | Relation | Entity | Description
--- | --- | --- | ---
Document | n:m | DocumentKeywords | Dokument beinhaltet N Keywords, 1 Keyword kann in M Documenten vorkommen
Category | n:m | Document | Category beinhaltet N Dokumente, 1 Dokument kann in M Categorien vorkommen
Category | n:m | CategoryKeywords | Category beinhaltet N Keywords, 1 Keyword kann in M Categorien vorkommen
Category | 1:n | Category | Category beinhaltet N SubCategories, 1 Subcategory gehört zu einer Category Ein Category ist zu sich selbstbezüglich !!!
User | n:m | Group | User ist in N Groups, 1 Group beinhaltet M User
User | n:m | UserRegisteredKeywords | User hat sich auf N Keywords registriert, 1 Keyword kann zu M User gehören
User | n:m | UserRegisteredCategory | User hat sich auf mehrere Categorien registriert, 1 Category kann zu M Usern gehören
Group | n:m | User | Group beinhaltet N User, 1 User kann zu M Groups gehören
CategoryAcl | 1:1 | Category | Einer Category ist eine ACL (mit mehreren Einträgen zugeordnet)
DocumentAcl | 1:1 | Document | Einem Dokument ist eine ACL (mit mehreren Einträgen zugeordnet)
DynAttibute | n:m | Category | 1 Category kann N DynAttribute enthalten, 1 DynAttribute gehört zu N Categorien
DynAttibute | n:m | User | 1 User kann N DynAttribute enthalten, 1 DynAttribute gehört zu N Usern
DynAttibute | n:m | Document | 1 Document kann N DynAttribute enthalten, 1 DynAttribute gehört zu N Documenten
Keyword | n:m | Synonym | 1 Keyword kann zu mehrere Synonyme umfassen, 1 Synonym gehört zu mehreren Synonymen
Document | 1:n | AddDocumentFormats | 1 Dokuemnt kann mehrere assoziierte Dokumente umfassen, 1 assoziiertes Document gehört zu einem Dokument (inclusive Versionierung)

### Datenbankschema (konzeptionell und physikalisch)

### Tabellen

Bitte beachten: Die Tabellen basieren auf numerischen ID (serialIDs): fortlaufende, in der jeweiligen Tabelle einmal vorkommende Zahlen.
Das hat den Vorteil, das die Tabellen entsprechend schnell verknüpft werden können und Datensätze anhand der ID recht schnell ausgewählt werden können.
Dadurch ist u.a. das Ändern (z.B. der Name von einem Dokument kann gändert werden, ohne das die Referenz zu anderen Tabellen verloren geht) und Löschen schnell zu realisieren (ohne viele, die Eindeutigkeit des Datensatzes betreffende Parameter anführen zu müssen).
Nachteil: Die serialIDs verbergen in der ersten Stufe den konkreten Datensatz, d.h., man muss immer ein SELECT durchführen, um entsprechend aussagekräftige Daten (wie z.B. Name, Pfad, etc) zu bekommen.

was sind mit assoziationen und lexika.../dokument versionen und types

TableName | Table description (bold = primary key, red = unique index) | Description
--- | --- | ---
AclTypes |

Field | Description
AclTypeID | serial
Name | char
Rank | Dient der hierarchischen Abhängigkeiten: 0 hat stärkere Rechte als 1 usw.
Description | char

AclTypen: z.B.

- "User" : 0 : "Benutzer"
- "Group" : 1 : "Gruppe"
- "Anyother": 2 :"Alle Anderen"
- "Mask" : 3 : XOR-Maske" (wer darf die Anlegen der mit dem "c"-Recht)

CategoryAcls |

Field | Description
CatEntryAclID | serial
AclNumber | Verknüpfungspunkt für die Categorie
AclTypeID | Verweis auf den AclTyp
AccessorID | Verweis auf GroupID oder UserID
PermissionID | Verweis auf die Permission
Created | Datum
CreatorID |
LastChange | Datum
LastChangerID |

AccessContolList (ACL) für eine Category (Beispiel):

- "TestCategory" : "USER" : "<id des Creators>" : "RWIDc"
- "TestCategory" : "USER" : "testuser1" : "R----"
- "TestCategory" : "USER" : "testuser2" : "RW---"
- "TestCategory" : "GROUP" : testgroup" : "--ID-"

AllowedDocumentTypes |

Field | Description
CatAllDocTypeID | serial
CategoryID |
DocumentTypeID |

Welche Dokumententypen in der Category erlaubt sind
Categories |

Field | Description
CategoryID | serial
ParentCategoryID | ID der übergeordneten Categorie
IsInitialCategory |
Name |
Title |
Description |
ShowDescription | yes/no
AssignedTemplate |
AclID | Verweis auf die ACL
Created | Datum der Anlegung dieses Datensatzes
CreatorID | User, der diesen Datensatz angelegt hat (OWNER)
LastChanged | Datum der letzten Änderung
LastChangerID | User der letzte Änderung durchgeführt hat
LastAccessed | Datum
LastAcessorID |
AccessCounter |

Die Tabelle Categories ist bezüglich auf sich selbst !!!

per definitionem hat die ROOT-Categorie die ParentCategoryID=0 !!!

CategoryDocuments |

Field | Description
CatDocID | serial
CategoryID |
DocumentID |
IsInitialCat | yes/no

Welche Document sind in welchem Verzeichnis vorhanden

Diese Tabelle realisiert einen Link:
Ein Dokument kann in verschiedenen Categorien vorkommen !!!

Das Attribut "IsInitialCat" legt fest, ob die Category, in der das Dokument eingefügt wurde, die Category ist, die dem Dokument zuerst zugeordnet wurde (YES). Ist der Wert des Attributes "NO" so handelt es sich um einen Softlink: Diese Dokument sind initial einer anderen Categorie zugeordnet !!!

CategoryKeywords |

Field | Description
CatKeyID | serial
CategoryID |
KeywordID |
Weight | Gewichtung

Welche Keywords gehören zu welcher Category
DocumentKeywords |

Field | Description
DocKeyID | serial
DocumentID |
KeywordID |
Weight | Gewichtung

Welche Keywords gehören zu welchem Dokument
DocumentAcls |

Field | Description
DocAclEntryID | serial
AclID | Verknüfungspunkt für das Dokument
AclTypeID | Verweis auf den AclTyp
AccessorID | Verweis auf Gruppen oder UserID
PermissionID | Verweis auf die Permission
Created | Datum
CreatorID |
LastChanged | Datum
LastChangerID |

AccessContolList (ACL) für ein Dokument (Beispiel):

- "TestDokument" : "USER" : "<id des Authors>" : "RWIDc"
- "TestDokument" : "USER" : "testuser1" : "R----"
- "TestDokument" : "USER" : "testuser2" : "RW---"
- "TestDokument" : "GROUP" : testgroup" : "--ID-"

Documents |

Field | Description
DocumentID | serial
PredDocID | id des Vorgänger Dokumentes
Name |
Title |
Description |
TypeID | Verweis auf DocumentTypes
ArchiveID | Verweis auf die ID des Dokumentes im Archiv
Summary |
AclID | Verweis auf die ACL
Status | Verweis auf DocumentStatus
Expiration | Datum des Verfalls des Documentes
Published | Datum der Veröffentlichung
AuthorID | Author des Dokumentes (OWNER)
LastChanged | Datum der letzten Änderung
LastChangerID | User, der letzte Änderung durchgeführt hat
LastAccessed | Datum
LastAccessorID |
AccessCounter |

Beachten: Die Dokumente werden nicht in der DB selbst gespeichert, sondern "nur" die Verwaltungsdaten. Das einzelne Dokument wird in einem FileSystem abgelegt.

Wird eines neues Dokument abgelegt und ist die Version nicht in den Daten enthalten, so wird ein neue Dokument angelegt. Dabei ist zu berücksichtigen, ob dann auch evt links zu diesem Dokument angepasst werden !!!

AdditionalDocumentFormats |

Field | Description
DocFormatID | serial
DocID | Verweis auf das (initiale) OriginalDocument
TypeID |
ArchiveID |

DocumentFlags |

Field | Description
Flag | Numerische Flag Werte
Description |

z.B.:

- 0: Document angelegt
- 1: Document verfallen, in TMP-Ordner abgelegt, Owner bekommt Nachricht
- 2: Document endgültig ungültig, aus TMP-Ordner entfernt
- ...

DocumentTypes |

Field | Description
DocTypeID | serial
Type | DokumentenTyp
Description |

z.B.:

- "XLS" : "Excel-Dokument"
- "PDF": "Adobe Portable Document Format"
- "DOC" : Microsoft WinWord Document
- ...

Groups |

Field | Description
GroupID | serial
Name |
Description |
AdminPrivileges | yes/no
AclID | Verweis auf ACL
ValidFrom | Datum
ValidUntil | Datum
Created | Datum
CreatorID | = Owner
LastChanged | Datum
LastChangerID |

GroupACLs |

Field | Description
GroupAclEntryID | serial
AclID |
UserID |
PermissionID |

Keywords |

Field | Description
KeywordID | serial
Keyword |

Permissions |

Field | Description
PermissionID | serial
Token | char
Value | int
PrintString | string
Context | string
Description |

Beispiele für Token/PrintString:

- "R": "Read"
- "W": "Write"
- "U": "Upload"
- "D": "Delete"

Categorien und Dokumente können andere Rechte eingestellt werden
(Wird unterscheidbar gemacht durch den Context)
(z.B. Category unterstützt ein Upload-Recht, ein Dokument braucht das nicht, Category beinhaltet das Recht einen Link zu erstellen, ...)

evt noch anlegen, ob das ein default für den entsprechen context ist

CategoryPermission | DocumentPermissions | GroupACL | User Group Permissions

- U: Upload oder W: Write
- R: Read
- L: CreateLink
- F: FollowLink
- C: CreateSubCat
- c: ChangeACL
- M:MoveCategory
- D:Delete

- R: Read
- W:Write
- c:ChangeACL
- M:MoveDocument
- D:Delete

- D:DeleteGroup
- A: AddMember
- D: DeleteMember
- c:ChangeACL

- C:CreateGroup
- A:AdminPrivileges

UserGroups |

Field | Description
UserGroupID | serial
GroupID |
UserID |

Zuordnung User zu Gruppen
UserRegisteredCategories |

Field | Description
UserRegCatID | serial
CategoryID |
UserID |

Zuordung, für welche Categorien ein User sich registriert hat
UserRegisteredKeywords |

Field | Description
UserRegKeyID | serial
UserID |
KeywordID |

Zuordnung, für welche Keywords sich ein User registriert hat
Users |

Field | Description |
UserID | serial |
UserName |  |
FirstName |  |
LastName |  |
Password |  |
PasswordChanged | yes/no |
EMail |  |
Company |  |
Department |  |
Zip |  |
City |  |
Street |  |
Phone |  |
Fax |  |
Mobile |  |
HomepageURL |  |
ContactURL |  |
PictureArchiveID |  |
ShowEMailAdress | yes/no |
AdminPrivileges | yes/no | darf nur von einem anderm Admin gesetzt werden
CreateGroups | yes/no | "
EnableMessaging | yes/no |
MessagingTimePeriod | double |
ValidFrom | Datum |
ValidUntil | Datum |
Remarks | string |
LanguageID |  |
Created | Datum |
CreatorID |  |
LastChanged | Datum |
LastChangerID |  |

Languages |

Field | Description
LanguageID | serial
Name | string
Code | string

SearchEngines |

Field | Description
SEID | serial
URL | string
Parameters | string
Description | string

List of SearchEngines to be used
SysParameters |

Field | Description
SysParamID | serial
Name | string
Value | string
Description | string

System Parameter
DynAttributes |

Field | Description
DynAttrID | serial
Name | string
Description | string

Dynamische Attribute
UserDynAttributes |

Field | Description
UserDynAttrID | serial
UserID |
DynAttrID |
Value | string

Verknüpfung User und DynAttributes
CatDynAttributes |

Field | Description
CatDynAttrID | serial
CategoryID |
DynAttrID |
Value | string

Verknüpfung Category und DynAttributes
DocDynAttributes |

Field | Description
DocDynAttrID | serial
DocumentID |
DynAttrID |
Value | string

Verknüpfung Documents und DynAttributes
Synonyms |

Field | Description
SynonymID | serial
Name | string

Associations |

Field | Description
AssocID | serial
KeywordID |
SynonymID |

###
Szenarien

Anhand dieser Tabelle werden die wichtigsten Szenarien beschrieben, die beim Betrieb von VKC auftauchen. Es zeigt auf, aus welchen Schritten (unter besonderer Berücksichtigung der Datenbank-Aktivitäten) die Prozess-Kette besteht.

Process / Activity | How to
Allgemeines Muster der Rechte-Überprüfung |
    Der Ablauf der Access-Funktion:

    parameter user, requiredPerm

    if user == known
    then
       begin
           if ((user has adminPrivilege) OR (user in group with adminprivilege))
           then
               ==> grant access
           else
               // wether user is owner or not
               // normally there is an entry "USER" : <id of owner> : "<all permissions>"
               if (requiredPerm in (getAllPermissionsOfUser() XOR getMask()))
                  then
                       ==> grant access
                  else
                       ==> deny access
                  end if
              end if
           end if
       end
    else
        // user unknown
        begin
          if exists (entry==ANYOTHER)
          then
              if (requiredPerm in (getAllPermissionsOfUser() XOR getMask()))
              then
                  ==> grant access
              else
                  ==> deny access
              end if
          else
              ==> deny
          end if
       end
    end if
Auflisten der Inhalte einer Category gegeben:

- UserName
- CategoryID
- ...
- Permission "R:READ"

1. | Überprüfen der Benutzerrechte |

| Check: Ist User überhaupt bekannt? | // Anzahl // 0 => nein // 1 => ja `SELECT Count(*) FROM users
WHERE username = "<username>"`

| Check: Existiert ein Mask-Eintrag für "R" ? | // Anzahl, wie oft MASK mit Recht "R" auftaucht !!! // 0 => keinmal (keine Maskierung) // 1 => einmal (Maskierung) `SELECT Count(*) FROM categoryAcls
WHERE categoryAcls.categoryID = <catID>
AND categoryAcls.aclTypeID = "MASK"
AND categoryAcls.permission = "R"`

1. | Check: UserAccount noch gültig? | // Anzahl // 0 => nein // 1 => ja `SELECT Count(*) FROM users
WHERE userName = "<userName>"
AND (AccountValidUntil IS NULL
OR AccountValidUntil >= today)`
2. | Check: User ist Admin? | // Anzahl // 0 => nein, hat keine AdminRechte // 1 => ja, hat AdminRechte `SELECT Count(*) FROM users
WHERE userName = "<userName>"
AND HasAdminPrivileges = TRUE`
3. | Check: User in AdminGroup? | // Anzahl der Gruppen, in denen der User ist, die AdminRechte haben // 0 => Zugriff verweigert // !=0 => Zugriff erlaubt `SELECT Count(*) FROM groups, usergroups, users
WHERE users.userName = "<userName>"
AND users.userID = usergroups.userID
AND usergroups.groupID = groups.groupID
AND groups.HasAdminPrivileges = true`
`AND (groups.AccountValidUntil IS NULL
OR groups.AccountValidUntil >= today)`

4. | Check: User is Owner | // Anzahl // 0 => nein, ist nicht Owner // 1 => ja, ist Owner `SELECT Count(*) FROM categories, users
WHERE categorieID = <catID>
AND SetupUserID = users.userID
AND users.userName = "<userName>"`
5. | Check: Hat User das Recht bzw Recht A? | // Anzahl, wie oft User mit Recht "R" auftaucht !!! // 0 => Zugriff verweigert // !=0 => Zugriff erlaubt `SELECT Count(*) FROM users, categoryAcls
WHERE users.userName = "<userName>"
AND categoryAcls.categoryID = <catID>
AND categoryAcls.aclTypeID = "USER"
AND categoryAcls.accessorID = users.userID
AND categoryAcls.permission = "R"`

6. | Check: Hat eine Gruppe, in der User ist, Recht | // Anzahl der Gruppen, in denen User ist, die das Recht // "R" haben // 0 => Zugriff verweigert // !=0 => Zugriff erlaubt `SELECT Count(*)
FROM users, usergroups, groups, categoryAcls
WHERE categoryAcls.categoryID = <catID>
AND category.aclTypeID = "GROUP"
AND categoryAcls.accessorID = groups.groupID
AND usergroups.groupID = groups.groupID
AND usergroups.userID = users.userID
AND users.userName = <userName>
AND categoryAcls.permission = "R"`
`AND (groups.AccountValidUntil IS NULL
OR groups.AccountValidUntil >= today)`

7. | Check: Haben Gäste (nicht authentisierte User Typ: ANYOTHER) Rechte | // Anzahl, wie oft User mit Recht "R" auftaucht !!! // 0 => Zugriff verweigert // !=0 => Zugriff erlaubt `SELECT Count(*) FROM categoryAcls
WHERE categoryAcls.categoryID = <catID>
AND categoryAcls.aclTypeID = "ANYOTHER"
AND categoryAcls.permission = "R"`

2. | Liste aller SubCategorien | `SELECT categoryID FROM categories WHERE ParentCategoryID = <catID>`
3. | Liste aller Links | // liste aller links auf categorien `SELECT linkedID FROM categorylinks WHERE parentcategoryID = <catID>` // liste aller links auf dokumente
`SELECT linkedID
FROM documentlinks
WHERE parentcategoryID = <catID>`

4. | Liste aller Dokumente | `SELECT documentID FROM categorydocuments WHERE categoryID = <catID>`

Anlegen einer neuen Categorie gegeben:

- ParentCategoryID
- CategoryName
- ...
- Permission "C:CreateCategory"

1. | Überprüfen der Benutzerrechte |
2. | Eintragen der neuen Categorie |

1. | Einfügen in Categorie-Tabelle | `INSERT INTO categories`
2. | Category-Keywords eintragen | `INSERT INTO categorykeywords WHERE categoryID = <newCatID>`

Einfügen eines Dokumentes in eine Categorie gegeben:

- ParentCategoryID
- DokumentenName
- DokumentenTyp
- ...
- Permission "W:Write"

1. | Überprüfen der Benutzerrechte |
2. | Überprüfen, ob Dokumententypen passen | // Anzahl // 0 : Documenttyp in dieser Categorie NICHT erlaubt // !=0 : Documenttyp in dieser Categorie erlaubt `SELECT Count(*) FROM CategorieAllowedDocumentTypes, DocumentTypes
WHERE DocumentTypes.Type = "<docType>"
AND CategorieAllowedDocumentTypes.CategoryID = <parentCatID>
AND CategorieAllowedDocumentTypes.DocumentTypeID = DocumentTypes.DocumentTypeID`

3. | Überprüfung, ob Categorie beschreibbar ist | evt obsolet, da recht W abgefragt wird // Anzahl // 0 : kein Upload erlaubt // 1: Upload erlaubt `SELECT Count(*)
FROM categories
WHERE categoryID = <parentCatID>
AND AllowUpload = true`

oder:
`SELECT AllowUpdate
FROM categories
WHERE categoryID = <parentCatID>`

4. | Eintragen des Dokumentes |

1. | Extraktion der Keyword/Description | ==> keyword1, keyword2,...,keywordN
| Eintragen der kewords in die Keyword-Tabelle | INSERT keyword SET keyword = keyword1 INTO keywords
2. | Eintragen des Dokumentes in Tabelle | `INSERT INTO documents`
3. | Eintragen neuer Keywords | `INSERT documentID, keywordID VALUES <newDocID, keyID> INTO DocumentKeywords`

5. | Bei Keywords registrierten Usern eine Mail schicken | `SELECT users.EMail FROM userRegisteredKeywords, users WHERE (userRegisteredKeyword.keywordID = keyword1 OR userRegisteredKeyword.keywordID = keyword2 OR ...)
AND userRegisteredKeywords.userID = users.UserID`
6. | Bei Category registrierten Usern eine Mail schicken | `SELECT users.EMail FROM usersRegisteredCategories, users WHERE userRegisteredCategories.categoryID = <catID> AND userRegisteredCategories.userID = users.userID`

Löschen eines Dokumentes aus einer Categorie gegeben:

- ParentCategoryID
- DocumentID
- ...
- Permission "D:DELETE"

1. | Überprüfen der Benutzerrechte |
2. | Löschen des Dokumentes | `DELETE FROM Categories WHERE documentID = <docID>`
3. | Setzten des Flags des Dokuments | `UPDATE Documents SET flag = 2 WHERE documentID = <docID`
4. | Nachschauen, ob Link auf dieses Dokument zeigt, ggf löschen | `DELETE FROM DocumentLinks WHERE LinkedID = <docID>`

Anlegen eines Links in der Categorie gegeben:

- ParentCategoryID
- CategoryID
- ...
- Permission "L:Link"

1. | Überprüfen der Benutzerrechte |
2. | Einfügen des Verweises | `INSERT parentCategoryID, categoryID VALUES <parentCatID, categoryID> INTO CategoryLinks`

Löschen eines Links aus der Categorie gegeben:

- ParentCategoryID
- CatLinkID
- ...
- Permission "L:Link"

1. | Überprüfen der Benutzerrechte |
2. | Löschen des Verweises | `DELETE FROM CategoryLinkID WHERE CatLinkID = <catLinkID>`

Ein Categorie löschen gegeben:

- CategoryID
- ...
- Permission "D:Delete"

1. | Überprüfen der Benutzerrechte |
2. | Categorie löschen | `DELETE FROM Categories WHERE ParentCategoryID = <catID>`
3. | DokumentenFlag auf "gelöscht" setzen | `UPDATE Documents SET flag = 2 WHERE DocumentID IN(SELECT DocumentID FROM CategoryDocuments WHERE CategoryID= <catID>)`
4. | Bezug Categorie und Dokumente löschen | `DELETE FROM CategoryDocuments WHERE CategoryID = <catID>`
5. | Categorie Links löschen | `DELETE FROM CategoryLinks WHERE CategoryID = <catID>`
6. | Document Links löschen | `DELETE FROM DocumentLinks WHERE CategoryID = <catID>`
7. | Links, die auf diese Category zeigen, löschen | `DELETE FROM CategoryLinks WHERE LinkedID = <catID>`
8. | Registrierte Benutzer für diese Category austragen | `DELETE FROM UserRegisteredCategories WHERE CategoryID = <catID>`

Ein Dokument wird ungültig |

1. | Herausfinden, welche Dokumente ungültig sind | `SELECT documentID FROM documents WHERE expiration < today`
2. | Dokument auf ungültig setzten | `UPDATE documents SET flag = 1 WHERE documentID = <documentID>`
3. | Owner eine Mail senden | `SELECT users.EMail FROM documents, users WHERE documents.documentID = <documentID> AND documents.AuthorID = users.userID`

Document verschieben gegeben:

- ParentCategoryID
- DestinationCategoryID
- DocumentID
- ...
- Permission "M:Move"

1. | Überprüfen der Benutzerrechte |
2. | Categorie für dieses Dokument ändern | `UPDATE CategoryDocuments SET categoryID = <destCatID> WHERE documentID = <docID> AND categoryID = <parentCatID>`
3. | Anpassen der Links auf dieses Dokument | `UPDATE DocumentLinks SET categoryID = <destCatID> WHERE documentID = <docID> AND categoryID = <parentCatID>`

User einfügen gegeben:

- UserDaten

1. | Überprüfen der Benutzerrechte |
2. | Einfügen des Datensatzes | `INSERT INTO Users VALUES (UserName, FirstName, ...)`

User ändern gegeben:

- UserID

1. | Überprüfen der Benutzerrechte |
2. | Ändern des Datensatzes | `UPDATE USERS SET FirstName = <firstname>, ... WHERE UserID = <userid>`

User löschen: gegeben:

- UserID

1. | Überprüfen der Benutzerrechte |
2. | Löschen des Datensatzes | `DELETE FROM Users WHERE UserID = <userid>`

### Was ein Admin darf (implizite Rechte)

- User anlegen
- Gruppen anlegen
- Rechte vergeben, Gruppe oder User anzulegen (UserPermissions)
  - wenn User, der U-Recht hat, einen neuen User anlegt, darf der das Attribut "HasAdminPrivileges" nicht setzen
    (anders ausgedrückt: wenn ein User das "HasAdminPrivilege" hat, darf der das setzen/entziehen, kein anderer !!!)
  - wenn User, der G-Recht hat, eine neue Gruppe anlegt, darf der das Attribut "HasAdminPrivileges" nicht setzen
- User / Gruppe mit AdminRecht ausstatten (Flag "HasAdminPrivileges" bei User/Gruppe)
- Categorien anlegen (besonders ROOT) / löschen / verschieben

### Offene Punkte, die der Klärung bedürfen

1. Ist die Struktur von DokumentACL/CategoryACL db-technisch ok ?
   Es ist ein Flag (AclType) eingebaut, welches anzeigt, das für Views oder etc evt verschiedene Tabellen verknüpft werden muss.
   Der JOIN ist abhängig vom Flag: OK
2. Die vergebenen Rechte sind nicht disjunkt, d.h., hat ein User z.B. bei Categories das "A"-Recht, hat er automatisch alle! Änderungen siehe aktuelles Dokument
3. Ist die Tabelle UserPermissions ok (Rechte für Anlegen von Gruppen, initiales Anlegen von Categorien) ok, oder sollen solche Rechte in die Tabelle des Users (als weitere Attribute) gehängt werden: Rechte dafür werden als Attribute dem User zugeordnet
4. Hierarchisierung in der Tabellen-Darstellung von Gruppen und/oder Categorien notwendig ? Nein, erstmal nicht
5. Es gibt einen AdminUser, der alles darf. der kann weitere Rechte an die User verteilen (über ACL bzw UserPermissions)
6. Aufteilung CreateGroup in UserPerm und DeleteGroup in GroupACLs ok ? nein, User bekommt Attribut CreateGroups
7. Wie groß ist die MessagingTimePeriod ? Minuten
8. Path (in Category) mit oder ohne Endpunkt ? ohne, wird rekursiv ermittelt

### Dies und das

Nur für den Autor als Gedankenstütze...

- die Sache mit den Admins Admins implizit, oder über ContainerACL oder über DefaultTabelle
- links (mit zähler?) dann müßten die verknüpfungen anders werden (category=> wie oft verlinkt wird auf dieselbe, categoryID und Linkedcategory, in der auf cat1 verlinkt wird (anzahl dann mit count(*))
- REFERENCE MONITOR (jeder geschützte zugriff auf ein funktion des systems muss über den RM laufen)
- evt alles nur links? (vorteil, einfacher bei rechteverwaltung ???)
- registeredcategories: url? unterbäume
- acls: gastprivilegien(foreign_user), maske, admin, owner
- wie erfaßt man rechte, die anlegen/ändern von benutzer, maileinträgen etc dürfen
- evt neues struktursstem schaffen, knoten und kanten mit db...
- Wie stellt an fest, wer OWNER ist oder nicht (anhand der ACL-Einträge) ohen Qualifizierer "OWNER"
- neues acl-system:
  - was ist mit guestusern/foreign_user/anyother... eigentlich abgedeckt über "ANYOTHER"
  - rechte ein (OR) oder ausblende (XOR) (global und lokal)
  - wie kann ich im allgemeinen objekte schützen (ACL) ObjectACL
  - java.security packages anschauen !!!