Bedrud uses GORM as its ORM, supporting both SQLite and PostgreSQL.

Supported Databases

  • SQLite: Used by default for easy development and small installations. The database is stored in a file (usually bedrud.db).
  • PostgreSQL: Recommended for production environments with many users.

You can configure the database type and connection details in the config.yaml file under the database: section.

Core Models

The models are located in internal/models/. Here are the most important ones:

User (user.go)

Stores account information including credentials and roles.

Room (room.go)

Represents a meeting session. It uses GORM’s Embedded Structs to organize settings. Instead of a separate table or a JSON blob, the RoomSettings fields (like allow_chat, allow_video) are stored directly in the rooms table with a settings_ prefix (e.g., settings_allow_chat). This provides a clean model in Go while maintaining a flat, performant database structure.

Passkey (passkey.go)

Stores FIDO2/WebAuthn public keys for passwordless login.

Custom Types: StringArray

Standard SQL databases handle arrays differently (PostgreSQL has native arrays, SQLite does not). To maintain compatibility, Bedrud defines a StringArray type in internal/models/user.go.

  • It implements sql.Scanner and driver.Valuer.
  • In PostgreSQL, it uses the native text[] type.
  • In SQLite, it serializes the array into a string (e.g., {admin,user}) for storage.

Foreign Key Management

GORM’s AutoMigrate does not handle composite primary keys (e.g., room_participants).

In internal/database/migrations.go, Bedrud manually executes ALTER TABLE statements to ensure foreign key constraints (like ON DELETE CASCADE) are correctly applied in production (PostgreSQL).

Repository Pattern

The backend uses the Repository Pattern for database access. Handlers do not call GORM directly - they use a repository.

Example:

// In handler:
user, err := h.userRepo.GetByEmail(email)
 
// In repository:
func (r *UserRepository) GetByEmail(email string) (*models.User, error) {
    var user models.User
    err := r.db.Where("email = ?", email).First(&user).Error
    return &user, err
}

Automatic Migrations

When the server starts, it automatically runs “AutoMigrate”. This creates or updates database tables based on the Go structures in internal/models. No manual CREATE TABLE statements are required for simple schema changes.