Help us shape the future of Go! Take the 2026 Go Developer Survey

database

package module
v2.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2026 License: MIT Imports: 8 Imported by: 0

README

Database Module

This module stores device sessions for the auth-middleware project in PostgreSQL. User accounts are owned by your application; this module only references them by email.

Requirements

  • PostgreSQL 14+
  • An existing users table whose email column is a PRIMARY KEY or has a UNIQUE constraint, so a foreign key can reference it

Installation

go get github.com/lucap9056/auth-middleware/database/v2

Usage

import "github.com/lucap9056/auth-middleware/database/v2"

userRef, err := database.WithUserEmailReference("users(email)")
if err != nil {
	return err
}

db, err := database.NewDatabase(dsn,
	database.WithAutoCreateSchema(true),
	userRef,
)
if err != nil {
	return err
}
defer db.Close()

Options

Option Default Description
WithMaxOpenConns(n) 20 Maximum number of open connections
WithMaxIdleConns(n) 15 Maximum number of idle connections
WithConnMaxLifetime(d) 5m Maximum lifetime of a connection
WithConnMaxIdleTime(d) 2m Maximum idle time of a connection
WithCleanupInterval(d) 24h Interval for deleting devices not updated in the last 7 days; 0 disables cleanup
WithAutoCreateSchema(bool) false Create the auth_user_devices table and its indexes on startup
WithUserEmailReference(ref) users(email) Users table and email column referenced by the foreign key
User Email Reference

Format: [<schema>.]<table>(<column>)[:<type>]

Example Meaning
users(email) users.email, type text
users(email):citext users.email, type citext
auth.members(mail):varchar(255) auth.members.mail, type varchar(255)

The reference is case-insensitive and normalized to lowercase. <type> must match the type of the referenced column.

Auto Create Schema

When enabled, NewDatabase creates the schema, which requires DDL privileges. When disabled, create the schema yourself using schema.Generate, or with the SQL below.

Schema

CREATE TABLE IF NOT EXISTS auth_user_devices (
    device_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    device_name TEXT NOT NULL,
    user_email TEXT NOT NULL,
    secret TEXT NOT NULL,
    generation INT NOT NULL DEFAULT 1,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
    CONSTRAINT fk_auth_user_devices FOREIGN KEY (user_email)
        REFERENCES users (email)
        ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE INDEX IF NOT EXISTS idx_auth_user_devices_user_email ON auth_user_devices(user_email);
CREATE INDEX IF NOT EXISTS idx_auth_user_devices_updated_at ON auth_user_devices(updated_at);

API

Method Description
SaveDeviceSecret(userEmail, deviceName, secret) Creates a device and returns its device_id. Returns ErrUserNotFound if the email does not exist in the users table
GetDeviceSecret(deviceID) Returns the device's secret and current generation
UpdateDeviceSecret(deviceID) Increments the device's generation, refreshes updated_at, and returns the new generation
DeleteDevice(userEmail, deviceID) Deletes one device belonging to the user
DeleteAllDevices(userEmail) Deletes all devices of the user
DeleteAllDevicesReturningIDs(userEmail) Deletes all devices of the user and returns their IDs
Close() Stops the cleanup worker and closes the connection pool

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupportedDriver = errors.New("database requires a *sql.DB backed by the pgx stdlib driver")
View Source
var ErrUserNotFound = errors.New("user not found")

Functions

This section is empty.

Types

type Database

type Database struct {
	// contains filtered or unexported fields
}

func New added in v2.1.0

func New(db *sql.DB, opts ...Option) (*Database, error)

func NewDatabase

func NewDatabase(dsn string, opts ...Option) (*Database, error)

func (*Database) Close

func (d *Database) Close() error

func (*Database) DeleteAllDevices

func (d *Database) DeleteAllDevices(userEmail string) error

func (*Database) DeleteAllDevicesReturningIDs

func (d *Database) DeleteAllDevicesReturningIDs(userEmail string) ([]string, error)

func (*Database) DeleteDevice

func (d *Database) DeleteDevice(userEmail, deviceID string) error

func (*Database) GetDeviceSecret

func (d *Database) GetDeviceSecret(deviceID string) (string, int, error)

func (*Database) SaveDeviceSecret

func (d *Database) SaveDeviceSecret(userEmail, deviceName, secret string) (string, error)

func (*Database) UpdateDeviceSecret

func (d *Database) UpdateDeviceSecret(deviceID string) (int, error)

type Option

type Option func(*options)

func WithAutoCreateSchema

func WithAutoCreateSchema(enabled bool) Option

func WithCleanupInterval

func WithCleanupInterval(d time.Duration) Option

func WithConnMaxIdleTime

func WithConnMaxIdleTime(d time.Duration) Option

func WithConnMaxLifetime

func WithConnMaxLifetime(d time.Duration) Option

func WithMaxIdleConns

func WithMaxIdleConns(n int) Option

func WithMaxOpenConns

func WithMaxOpenConns(n int) Option

func WithUserEmailReference

func WithUserEmailReference(reference string) (Option, error)

type UserDevice

type UserDevice struct {
	UserEmail  string `json:"user_email"`
	DeviceID   string `json:"device_id"`
	DeviceName string `json:"device_name"`
	Secret     string `json:"secret,omitempty"`
	UpdatedAt  string `json:"updated_at,omitempty"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL