Custom Store
Implement a custom store backend for Warden.
You can implement a custom store by satisfying the store.Store interface.
Store Interface
The composite store interface embeds all subsystem stores:
import "github.com/xraph/warden/store"
type Store interface {
role.Store
permission.Store
assignment.Store
relation.Store
policy.Store
resourcetype.Store
checklog.Store
Migrate(ctx context.Context) error
Ping(ctx context.Context) error
Close() error
}Subsystem Interfaces
Each subsystem defines its own store interface. Here's an overview:
role.Store
type Store interface {
CreateRole(ctx context.Context, r *Role) error
GetRole(ctx context.Context, id id.RoleID) (*Role, error)
UpdateRole(ctx context.Context, r *Role) error
DeleteRole(ctx context.Context, id id.RoleID) error
ListRoles(ctx context.Context, filter *ListFilter) ([]*Role, error)
CountRoles(ctx context.Context, filter *ListFilter) (int, error)
AttachPermission(ctx context.Context, roleID id.RoleID, permID id.PermissionID) error
DetachPermission(ctx context.Context, roleID id.RoleID, permID id.PermissionID) error
ListPermissionsForRole(ctx context.Context, roleID id.RoleID) ([]id.PermissionID, error)
GetRoleBySlug(ctx context.Context, slug string) (*Role, error)
ListChildRoles(ctx context.Context, parentID id.RoleID) ([]*Role, error)
ListRolesForSubject(ctx context.Context, tenantID, subjectKind, subjectID string) ([]id.RoleID, error)
DeleteByTenant(ctx context.Context, tenantID string) error
}Other subsystem stores follow the same pattern:
permission.Store— CRUD + role attachment queriesassignment.Store— CRUD + subject/role lookupsrelation.Store— CRUD + graph traversal queriespolicy.Store— CRUD + active policy lookupsresourcetype.Store— CRUD + name lookupschecklog.Store— Append + query
Implementation Tips
- Start with the memory store as a reference:
store/memory/store.go - Use compile-time checks to ensure interface compliance:
var _ store.Store = (*MyStore)(nil) - Thread safety — Use appropriate locking for concurrent access
- Tenant isolation — All queries should filter by tenant ID from context
- Error mapping — Return
warden.ErrNotFoundfor missing entities,warden.ErrAlreadyExistsfor duplicates
Example Skeleton
package mystore
import (
"context"
"github.com/xraph/warden/store"
)
type MyStore struct {
// your database client
}
var _ store.Store = (*MyStore)(nil)
func (s *MyStore) Migrate(ctx context.Context) error {
// Run migrations
return nil
}
func (s *MyStore) Ping(ctx context.Context) error {
// Health check
return nil
}
func (s *MyStore) Close() error {
// Close connections
return nil
}
// Implement all subsystem store methods...