Wiki.js Rust-Datenmodell

Aus Dokument
Version vom 12. August 2026, 02:44 Uhr von Thorsten (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „ Dieses Dokument beschreibt ein reines Rust-Datenmodell (Structs/Enums, ohne externe Crates wie <code>serde</code>, <code>sqlx</code> oder <code>chrono</code>) für das PostgreSQL-Schema von [https://github.com/requarks/wiki Wiki.js] (<code>server/models/*.js</code> + Knex-Migrationen). Der vollständige Quelltext liegt in <code>wikijs_models.rs</code>. __TOC__ == Überblick == * Keine Abhängigkeiten — reine <code>std</code>. * JSONB-Spalten werden…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

Dieses Dokument beschreibt ein reines Rust-Datenmodell (Structs/Enums, ohne externe Crates wie serde, sqlx oder chrono) für das PostgreSQL-Schema von Wiki.js (server/models/*.js + Knex-Migrationen). Der vollständige Quelltext liegt in wikijs_models.rs.

Überblick

  • Keine Abhängigkeiten — reine std.
  • JSONB-Spalten werden als roher JSON-Text (String) abgebildet — kein eigener JSON-Typ.
  • Zeitstempel werden über den ebenfalls selbstgebauten Typ Timestamp (Unix-Zeit in Sekunden) abgebildet (siehe #Timestamp).
  • Enums bilden die in Wiki.js als String/Int gespeicherten "closed sets" ab (z. B. contentType, action, kind, permissions).

Cargo.toml

[dependencies]

Timestamp

Einfacher Zeitstempel ohne externe Crates.

Feld Typ Beschreibung
0 (Tupelfeld) i64 Unix-Zeit in Sekunden seit 1970-01-01 UTC

Pages

Page

Entspricht der Tabelle pages — Kerntabelle für Wiki-Seiten.

Feld Typ Beschreibung
id i32 Primärschlüssel
path String Seitenpfad
hash String Hash des Pfads (für Lookups)
title String Titel
description String Kurzbeschreibung
is_private bool private Sichtbarkeit
is_published bool veröffentlicht?
private_ns Option<String> private Namespace-Kennung
publish_start_date Option<Timestamp> Start des Veröffentlichungsfensters
publish_end_date Option<Timestamp> Ende des Veröffentlichungsfensters
content String Rohinhalt (Quelltext)
content_type #ContentType Editor-/Renderformat
render Option<String> gerenderter HTML-Output
toc Option<String> Inhaltsverzeichnis-Baum als roher JSON-Text
extra Option<String> beliebige Zusatzdaten als roher JSON-Text
editor_key String genutzter Editor
locale_code String Sprachcode
creator_id i32 erstellender Benutzer
author_id i32 letzter Bearbeiter
owner_id i32 Eigentümer
css Option<String> seitenspezifisches CSS
script_css Option<String> zusätzliches CSS (Skript-Editor)
script_js Option<String> zusätzliches JS (Skript-Editor)
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

ContentType

Editor/Rendering-Format einer Seite (pages.contentType, pageHistory.contentType).

  • Markdown
  • Html
  • Asciidoc — nicht mehr aktiv genutzt, aber historisch im Schema möglich

PageHistory

Entspricht der Tabelle pageHistory — Versionsverlauf, gleiche Spalten wie #Page plus action/version_date.

Feld Typ Beschreibung
id i32 Primärschlüssel
page_id i32 zugehörige Seite
path String Seitenpfad zum Zeitpunkt der Version
hash String Hash des Pfads
title String Titel zum Zeitpunkt der Version
description String Kurzbeschreibung
is_private bool private Sichtbarkeit
content String Rohinhalt dieser Version
content_type #ContentType Editor-/Renderformat
render Option<String> gerenderter HTML-Output
toc Option<String> Inhaltsverzeichnis-Baum als roher JSON-Text
editor_key String genutzter Editor
locale_code String Sprachcode
action #PageHistoryAction Art der Änderung
version_date Timestamp Zeitpunkt der Version
author_id i32 Bearbeiter dieser Version

PageHistoryAction

Art der historisierten Änderung (pageHistory.action).

  • Initial
  • Edit
  • Delete
  • Move
  • Restore

Entspricht der Tabelle pageLinks — extrahierte Verlinkungen zwischen Seiten (für Broken-Link-Check).

Feld Typ Beschreibung
id i32 Primärschlüssel
path String Ziel-Pfad des Links
locale_code String Sprachcode des Ziels
page_id i32 Quellseite des Links

Tags

Tag

Entspricht der Tabelle tags.

Feld Typ Beschreibung
id i32 Primärschlüssel
tag String Tag-Slug
title Option<String> Anzeigename
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

PageTag

Join-Tabelle pageTags (n:m zwischen #Page und #Tag).

Feld Typ Beschreibung
page_id i32 FK auf #Page
tag_id i32 FK auf #Tag

Users

User

Entspricht der Tabelle users.

Feld Typ Beschreibung
id i32 Primärschlüssel
email String E-Mail-Adresse
name String Anzeigename
provider String Modul-ID des Auth-Providers (z. B. "local", "ldap", "google", "azure")
provider_id Option<String> externe Provider-ID
provider_key Option<String> Provider-Schlüssel
password Option<String> bcrypt-Hash, nur bei provider == "local"
tfa_is_active bool Zwei-Faktor-Auth aktiv?
tfa_secret Option<String> 2FA-Secret
job_title Option<String> Berufsbezeichnung
location Option<String> Standort
picture_url Option<String> Profilbild-URL
timezone String Zeitzone
date_format String bevorzugtes Datumsformat
appearance String UI-Theme-Einstellung
is_system bool Systembenutzer?
is_active bool Konto aktiv?
is_verified bool E-Mail verifiziert?
meta Option<String> beliebige Provider-spezifische Zusatzdaten als roher JSON-Text
last_login_at Option<Timestamp> letzter Login
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

UserKeyKind

Zweck eines temporären Tokens (userKeys.kind).

  • Validation
  • ResetPwd
  • ChangeEmail
  • Api

UserKey

Entspricht der Tabelle userKeys.

Feld Typ Beschreibung
id i32 Primärschlüssel
kind #UserKeyKind Zweck des Tokens
token String Token-Wert
user_id i32 FK auf #User
expiration Timestamp Ablaufzeitpunkt
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

Groups

Group

Entspricht der Tabelle groups — Rechte- und Gruppenverwaltung.

Feld Typ Beschreibung
id i32 Primärschlüssel
name String Gruppenname
is_system bool Systemgruppe?
permissions Vec<#Permission> globale Rechte, z. B. [ReadPages, WritePages]
page_rules Vec<#PageRule> pfadbasierte Zugriffsregeln
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

UserGroup

Join-Tabelle userGroups (n:m zwischen #User und #Group).

Feld Typ Beschreibung
user_id i32 FK auf #User
group_id i32 FK auf #Group

Permission

Bekannte globale Rechte, in groups.permissions als String-Array (JSON) gespeichert.

  • ManageSystem
  • ManageGroups
  • ManageNavigation
  • ManageTheme
  • ManageApi
  • ManageUsers
  • ManagePages
  • ReadPages
  • ReadAssets
  • ReadComments
  • WritePages
  • WriteAssets
  • WriteComments
  • ManageComments
  • DeletePages
  • DeleteAssets
  • DeleteComments

PageRule

Ein Eintrag aus groups.pageRules (JSONB-Array).

Feld Typ Beschreibung
id String Regel-ID
deny bool Regel verweigert (statt erlaubt)?
roles Vec<#Permission> betroffene Rechte
match (r#match) #PageRuleMatch Art des Pfad-Matchings
path String Pfad-Muster
locales Vec<String> betroffene Sprachcodes

PageRuleMatch

  • Start
  • End
  • Regex
  • Exact
  • Tag

Comments

Comment

Entspricht der Tabelle comments.

Feld Typ Beschreibung
id i32 Primärschlüssel
content String Rohinhalt des Kommentars
render String gerenderter HTML-Output
name String angezeigter Name
email String E-Mail des Verfassers
ip String IP-Adresse des Verfassers
page_id i32 FK auf #Page
author_id i32 FK auf #User
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

Assets

Asset

Entspricht der Tabelle assets.

Feld Typ Beschreibung
id i32 Primärschlüssel
filename String Dateiname
ext String Dateiendung
kind #AssetKind Art der Datei
mime String MIME-Type
file_size i64 Dateigröße in Bytes
metadata Option<String> Zusatzmetadaten als roher JSON-Text
folder_id Option<i32> FK auf #AssetFolder
author_id i32 FK auf #User
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

AssetKind

  • Image
  • Binary

AssetFolder

Entspricht der Tabelle assetFolders.

Feld Typ Beschreibung
id i32 Primärschlüssel
slug String URL-Slug
name String Anzeigename
parent_id Option<i32> übergeordneter Ordner (rekursiv)

AssetData

Binärdaten getrennt von den Metadaten gehalten (1:1 zu #Asset).

Feld Typ Beschreibung
id i32 FK/PK auf #Asset
data Vec<u8> Binärinhalt

Storage

StorageTarget

Sync-Status der konfigurierten Storage-Targets (Git, S3, ...), Tabelle storage.

Feld Typ Beschreibung
id i32 Primärschlüssel
key String Target-Kennung (z. B. "git", "s3")
is_enabled bool aktiviert?
mode #StorageMode Sync-Richtung
config String provider-spezifische Konfiguration (als roher JSON-Text) (Repo-URL, Credentials-Ref, ...)
state Option<String> letzter bekannter Sync-Zustand (als roher JSON-Text)
sync_interval Option<String> Sync-Intervall

StorageMode

  • Push
  • Pull
  • Sync

Seitenbaum pro Locale, Tabelle navigation (eine Zeile je Locale-Code).

Feld Typ Beschreibung
id String Locale-Code, z. B. "en" oder "de"
config Vec<#NavigationItem> Navigationseinträge
Feld Typ Beschreibung
id String Eintrags-ID
kind #NavigationItemKind Art des Eintrags
label Option<String> Anzeigetext
icon Option<String> Icon-Kennung
target_type Option<#NavigationTargetType> Ziel-Art
target Option<String> Ziel (Pfad/URL)
visibility_rules Option<Vec<String>> Sichtbarkeitsregeln
  • Link
  • Header
  • Divider
  • Internal
  • External

Locales

Locale

Entspricht der Tabelle locales — installierte Sprachpakete.

Feld Typ Beschreibung
code String Sprachcode (Primärschlüssel)
strings String Übersetzungs-Strings (als roher JSON-Text)
is_rtl bool rechts-nach-links-Schrift?
name String englischer Name
native_name String einheimischer Name
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

API Keys

ApiKey

Entspricht der Tabelle apiKeys.

Feld Typ Beschreibung
id i32 Primärschlüssel
name String Bezeichnung
key String Schlüsselwert
expiration Timestamp Ablaufzeitpunkt
is_revoked bool widerrufen?
created_at Timestamp Erstellungszeitpunkt
updated_at Timestamp letzte Änderung

Settings

Setting

Generischer Key/Value-Store für Sitekonfiguration, Tabelle settings.

Feld Typ Beschreibung
key String Einstellungsschlüssel (Primärschlüssel)
value String Wert (als roher JSON-Text)
updated_at Timestamp letzte Änderung

Vollständiger Quelltext

/// Einfacher Zeitstempel ohne externe Crates: Unix-Zeit in Sekunden seit
/// 1970-01-01 UTC.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Timestamp(pub i64);

#[derive(Debug, Clone)]
pub struct Page {
    pub id: i32,
    pub path: String,
    pub hash: String,
    pub title: String,
    pub description: String,
    pub is_private: bool,
    pub is_published: bool,
    pub private_ns: Option<String>,
    pub publish_start_date: Option<Timestamp>,
    pub publish_end_date: Option<Timestamp>,
    pub content: String,
    pub content_type: ContentType,
    pub render: Option<String>,
    pub toc: Option<String>,
    pub extra: Option<String>,
    pub editor_key: String,
    pub locale_code: String,
    pub creator_id: i32,
    pub author_id: i32,
    pub owner_id: i32,
    pub css: Option<String>,
    pub script_css: Option<String>,
    pub script_js: Option<String>,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContentType {
    Markdown,
    Html,
    Asciidoc,
}

#[derive(Debug, Clone)]
pub struct PageHistory {
    pub id: i32,
    pub page_id: i32,
    pub path: String,
    pub hash: String,
    pub title: String,
    pub description: String,
    pub is_private: bool,
    pub content: String,
    pub content_type: ContentType,
    pub render: Option<String>,
    pub toc: Option<String>,
    pub editor_key: String,
    pub locale_code: String,
    pub action: PageHistoryAction,
    pub version_date: Timestamp,
    pub author_id: i32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageHistoryAction {
    Initial,
    Edit,
    Delete,
    Move,
    Restore,
}

#[derive(Debug, Clone)]
pub struct PageLink {
    pub id: i32,
    pub path: String,
    pub locale_code: String,
    pub page_id: i32,
}

#[derive(Debug, Clone)]
pub struct Tag {
    pub id: i32,
    pub tag: String,
    pub title: Option<String>,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct PageTag {
    pub page_id: i32,
    pub tag_id: i32,
}

#[derive(Debug, Clone)]
pub struct User {
    pub id: i32,
    pub email: String,
    pub name: String,
    pub provider: String,
    pub provider_id: Option<String>,
    pub provider_key: Option<String>,
    pub password: Option<String>,
    pub tfa_is_active: bool,
    pub tfa_secret: Option<String>,
    pub job_title: Option<String>,
    pub location: Option<String>,
    pub picture_url: Option<String>,
    pub timezone: String,
    pub date_format: String,
    pub appearance: String,
    pub is_system: bool,
    pub is_active: bool,
    pub is_verified: bool,
    pub meta: Option<String>,
    pub last_login_at: Option<Timestamp>,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum UserKeyKind {
    Validation,
    ResetPwd,
    ChangeEmail,
    Api,
}

#[derive(Debug, Clone)]
pub struct UserKey {
    pub id: i32,
    pub kind: UserKeyKind,
    pub token: String,
    pub user_id: i32,
    pub expiration: Timestamp,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct Group {
    pub id: i32,
    pub name: String,
    pub is_system: bool,
    pub permissions: Vec<Permission>,
    pub page_rules: Vec<PageRule>,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct UserGroup {
    pub user_id: i32,
    pub group_id: i32,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Permission {
    ManageSystem,
    ManageGroups,
    ManageNavigation,
    ManageTheme,
    ManageApi,
    ManageUsers,
    ManagePages,
    ReadPages,
    ReadAssets,
    ReadComments,
    WritePages,
    WriteAssets,
    WriteComments,
    ManageComments,
    DeletePages,
    DeleteAssets,
    DeleteComments,
}

#[derive(Debug, Clone)]
pub struct PageRule {
    pub id: String,
    pub deny: bool,
    pub roles: Vec<Permission>,
    pub r#match: PageRuleMatch,
    pub path: String,
    pub locales: Vec<String>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageRuleMatch {
    Start,
    End,
    Regex,
    Exact,
    Tag,
}

#[derive(Debug, Clone)]
pub struct Comment {
    pub id: i32,
    pub content: String,
    pub render: String,
    pub name: String,
    pub email: String,
    pub ip: String,
    pub page_id: i32,
    pub author_id: i32,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct Asset {
    pub id: i32,
    pub filename: String,
    pub ext: String,
    pub kind: AssetKind,
    pub mime: String,
    pub file_size: i64,
    pub metadata: Option<String>,
    pub folder_id: Option<i32>,
    pub author_id: i32,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AssetKind {
    Image,
    Binary,
}

#[derive(Debug, Clone)]
pub struct AssetFolder {
    pub id: i32,
    pub slug: String,
    pub name: String,
    pub parent_id: Option<i32>,
}

#[derive(Debug, Clone)]
pub struct AssetData {
    pub id: i32,
    pub data: Vec<u8>,
}

#[derive(Debug, Clone)]
pub struct StorageTarget {
    pub id: i32,
    pub key: String,
    pub is_enabled: bool,
    pub mode: StorageMode,
    pub config: String,
    pub state: Option<String>,
    pub sync_interval: Option<String>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StorageMode {
    Push,
    Pull,
    Sync,
}

#[derive(Debug, Clone)]
pub struct NavigationTree {
    pub id: String,
    pub config: Vec<NavigationItem>,
}

#[derive(Debug, Clone)]
pub struct NavigationItem {
    pub id: String,
    pub kind: NavigationItemKind,
    pub label: Option<String>,
    pub icon: Option<String>,
    pub target_type: Option<NavigationTargetType>,
    pub target: Option<String>,
    pub visibility_rules: Option<Vec<String>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NavigationItemKind {
    Link,
    Header,
    Divider,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NavigationTargetType {
    Internal,
    External,
}

#[derive(Debug, Clone)]
pub struct Locale {
    pub code: String,
    pub strings: String,
    pub is_rtl: bool,
    pub name: String,
    pub native_name: String,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct ApiKey {
    pub id: i32,
    pub name: String,
    pub key: String,
    pub expiration: Timestamp,
    pub is_revoked: bool,
    pub created_at: Timestamp,
    pub updated_at: Timestamp,
}

#[derive(Debug, Clone)]
pub struct Setting {
    pub key: String,
    pub value: String,
    pub updated_at: Timestamp,
}