Documentation
¶
Overview ¶
Package ds (Data Structure) All data models belonging to the app are stored here. Global functions should not be created here. Methods on types are welcome.
Index ¶
- Constants
- Variables
- type AuthToken
- type Book
- type BookAuthor
- type BooksFilter
- type ChangeEmailRequest
- type ChangeRequestsFilter
- type DataProvider
- type EmailConfirmation
- type EntitiesFilter
- type Entity
- func (e *Entity) CreateRules() z.Shape
- func (e *Entity) Data() map[string]any
- func (e *Entity) PropertyType(key string) prop.Type
- func (e *Entity) SetPublicID()
- func (e *Entity) UpdateRules() z.Shape
- func (e *Entity) ViewURL() string
- func (e *Entity) WithEntityData(data map[string]any) map[string]any
- type EntityChangeRequest
- type EntityChangeStatus
- type EntityStatus
- type EntityTopic
- type EntityType
- type EntityVisibility
- type EventLog
- type EventLogType
- type EventLogsFilter
- type File
- type FilePurpose
- type FilesFilter
- type FilterDT
- type FilterString
- type ID
- type OAuthUserAccount
- type Page
- type PasswordResetToken
- type Topic
- type TopicsFilter
- type User
- type UserSession
- type UsersFilter
Constants ¶
const ( // PerPageNoLimit disables pagination limits and returns all records. PerPageNoLimit = -1 // PerPageDefault defines the default number of records per page // when no explicit per-page value is provided. PerPageDefault = 25 // PerPageMax defines the maximum allowed number of records per page // to prevent excessive result sizes. PerPageMax = 100 )
const ( // DeleteTempFilesAfterDays defines how long temporary files // are kept before being eligible for deletion. DeleteTempFilesAfterDays = 5 // CleanupDeletedFilesAfterDays defines how long soft-deleted files // are kept before permanent cleanup. CleanupDeletedFilesAfterDays = 5 )
const ( // CleanupDeletedEntitiesAfterDays defines how long soft-deleted entities // are kept before permanent cleanup. CleanupDeletedEntitiesAfterDays = 10 )
const ( // CleanupDeletedUserAfter ... CleanupDeletedUserAfter = 30 * 24 * time.Hour )
Variables ¶
var EntityStatuses = []EntityStatus{ EntityStatusUnderReview, EntityStatusApproved, EntityStatusRejected, }
EntityStatuses defines the list of valid entity statuses.
var EntityTypes = []EntityType{ EntityTypeBook, EntityTypePage, }
EntityTypes lists all supported entity types.
var EntityVisibilities = []EntityVisibility{ EntityVisibilityPublic, EntityVisibilityPrivate, EntityVisibilityUnlisted, }
EntityVisibilities defines the list of all supported entity visibility values.
var ErrInvalidIDFormat = errors.New("invalid UUID format")
ErrInvalidIDFormat indicates that a provided ID string is not a valid UUID format.
var EventLogTypes = []EventLogType{ EventLogSystem, EventLogUserAccountCreated, EventLogUserEmailConfirmed, EventLogUserAccountActivated, EventLogUserRequestPasswordReset, EventLogUserPasswordChangedByResetRequest, EventLogUserPasswordChanged, EventLogUserEmailChangeRequested, EventLogUserEmailChanged, EventLogUserUsernameChanged, EventLogEntitySubmitted, EventLogEntityApproved, EventLogEntityRejected, EventLogEntityAdded, EventLogEntityUpdated, EventLogEntityRenamed, }
EventLogTypes lists all supported event log types.
var IDInputRules = z.CustomFunc(func(val *ID, _ z.Ctx) bool { if val == nil || *val == NilID { return false } return true }, z.Message("Invalid UUID"))
IDInputRules ...
var NilID = ID(uuid.Nil)
NilID is an empty UUID, all zeros.
var ReleaseDateLayouts = []string{
"2006",
"January 2006",
"January 2, 2006",
}
ReleaseDateLayouts defines the allowed date layouts for formatting book release dates.
Functions ¶
This section is empty.
Types ¶
type AuthToken ¶
type AuthToken struct {
ID ID
UserID int64
User *User
ClientName string
ClientIP string
UserAgent string
Token string
CreatedAt time.Time
ExpiresAt time.Time
}
AuthToken represents container for authentication-related data.
type Book ¶
type Book struct {
*Entity
DescriptionRaw string `json:"-"`
Description string `json:"description"`
CoverFileID ID `json:"cover_file_id"`
Authors []BookAuthor `json:"authors"`
Homepage string `json:"homepage"`
ReleaseDate string `json:"release_date"`
}
Book defines the data structure for a book.
func BookFromContext ¶
BookFromContext attempts to retrieve book object from the context.
func (*Book) CreateRules ¶
CreateRules provides the validation map used when saving a new book.
func (*Book) PropertyType ¶
PropertyType returns the property type for a given key.
func (*Book) UpdateRules ¶
UpdateRules provides the validation map used when editing an existing book.
type BookAuthor ¶
BookAuthor represents an author of a book.
type BooksFilter ¶
type BooksFilter struct {
EntitiesFilter
}
BooksFilter is used to filter and paginate user queries.
type ChangeEmailRequest ¶
type ChangeEmailRequest struct {
ID ID `json:"-"`
UserID ID `json:"-"`
NewEmail string `json:"-"`
Token string `json:"-"`
ExpiresAt time.Time `json:"-"`
CreatedAt time.Time `json:"-"`
}
ChangeEmailRequest represents a record in the change_email_requests table. It stores a single-use token for a user to confirm a change to their email address.
func (*ChangeEmailRequest) Invalid ¶
func (r *ChangeEmailRequest) Invalid() bool
Invalid returns true if token has expired.
type ChangeRequestsFilter ¶
type ChangeRequestsFilter struct {
Page int
PerPage int
Status EntityChangeStatus
WithCount bool
}
ChangeRequestsFilter is used to filter and paginate change requests.
type DataProvider ¶
DataProvider exposes entity data in a generic key-value form.
It is used to extract mutable fields of an entity for diffing, change requests, and edit workflows.
type EmailConfirmation ¶
type EmailConfirmation struct {
ID ID
UserID ID
Code string
CreatedAt time.Time
ExpiresAt time.Time
ConfirmedAt *time.Time
}
EmailConfirmation represents a record used to verify a user's email address after registration or a change request.
func (*EmailConfirmation) Invalid ¶
func (c *EmailConfirmation) Invalid() bool
Invalid checks if the confirmation record is expired. Returns true if the token is no longer valid, false otherwise.
type EntitiesFilter ¶
type EntitiesFilter struct {
Page int
PerPage int
WithCount bool
CreatedAt *FilterDT
DeletedAt *FilterDT
Deleted bool
Title *FilterString
Visibility []EntityVisibility
Status []EntityStatus
Topics []string
OrderBy string
OrderDirection string
}
EntitiesFilter is used to filter entities.
type Entity ¶
type Entity struct {
ID ID `json:"id"`
PublicID string `json:"public_id"`
OwnerID ID `json:"-"`
PreviewFileID ID `json:"preview_file_id"`
Type EntityType `json:"-"`
Title string `json:"title"`
SummaryRaw string `json:"-"`
Summary string `json:"summary"`
Status EntityStatus `json:"status"`
Visibility EntityVisibility `json:"visibility"`
PublishedAt *time.Time `json:"published_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
DeletedAt *time.Time `json:"-"`
Topics []Topic `json:"topics"`
Owner *string `db:"owner" json:"owner,omitempty"`
}
Entity represents the base metadata for any user-content in the system.
func (*Entity) CreateRules ¶
CreateRules returns the validation schema for creating a new entity.
func (*Entity) PropertyType ¶
PropertyType returns the property type for a given key.
func (*Entity) SetPublicID ¶
func (e *Entity) SetPublicID()
SetPublicID ensures that the entity has a non-empty, human-readable PublicID. If it cannot be derived from the Title, it falls back to "{type}_{shortuuid}".
func (*Entity) UpdateRules ¶
UpdateRules returns the validation schema for updating an existing entity.
type EntityChangeRequest ¶
type EntityChangeRequest struct {
ID ID `json:"id"`
EntityID ID `json:"entity_id,omitzero"`
UserID ID `json:"user_id,omitzero"`
Status EntityChangeStatus `json:"status"`
// Diff contains the proposed changes.
Diff map[string]any `json:"diff"`
Message string `json:"message,omitempty"`
Revision int `json:"revision"`
ReviewerID *ID `json:"reviewer_id,omitempty"`
ReviewedAt *time.Time `json:"reviewed_at,omitempty"`
ReviewNote string `json:"review_note,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
// props needed to be returned from filter action
Username string `json:"username"`
EntityType EntityType `json:"entity_type"`
EntityTitle string `json:"entity_title"`
EntityPublicID string `json:"entity_public_id"`
}
EntityChangeRequest describes a user's requested changes to an entity.
type EntityChangeStatus ¶
type EntityChangeStatus string
EntityChangeStatus represents the lifecycle state of an entity change request.
const ( // EntityChangePending indicates a change request awaiting review. EntityChangePending EntityChangeStatus = "pending" // EntityChangeCommitted indicates an approved and applied change request. EntityChangeCommitted EntityChangeStatus = "committed" // EntityChangeRejected indicates a change request that was reviewed and rejected. EntityChangeRejected EntityChangeStatus = "rejected" )
type EntityStatus ¶
type EntityStatus string
EntityStatus defines the moderation state of an entity.
const ( // EntityStatusUnderReview means the entity is awaiting moderation. EntityStatusUnderReview EntityStatus = "review" // EntityStatusApproved means the entity is live and approved. EntityStatusApproved EntityStatus = "approved" // EntityStatusRejected means the entity failed moderation. EntityStatusRejected EntityStatus = "rejected" )
func (EntityStatus) Is ¶
func (v EntityStatus) Is(v2 ...EntityStatus) bool
Is reports whether the status matches any of the provided values.
func (EntityStatus) Not ¶
func (v EntityStatus) Not(v2 ...EntityStatus) bool
Not reports whether the status does not match any of the provided values.
func (EntityStatus) Valid ¶
func (v EntityStatus) Valid() bool
Valid reports whether the status value is one of the supported entity statuses.
type EntityTopic ¶
EntityTopic links an entity to a topic (many-to-many).
type EntityType ¶
type EntityType string
EntityType defines the type of the entity content.
const ( EntityTypeBook EntityType = "book" EntityTypePage EntityType = "page" )
Supported entity types.
func (EntityType) Valid ¶
func (t EntityType) Valid() bool
Valid reports whether the entity type is supported.
type EntityVisibility ¶
type EntityVisibility string
EntityVisibility controls how the entity is accessed in listings and search results.
const ( // EntityVisibilityPublic means the entity is visible to everyone and indexed. EntityVisibilityPublic EntityVisibility = "public" // EntityVisibilityPrivate means the entity is restricted to the owner and collaborators. EntityVisibilityPrivate EntityVisibility = "private" // EntityVisibilityUnlisted means the entity is accessible only via direct link. EntityVisibilityUnlisted EntityVisibility = "unlisted" )
func (EntityVisibility) Is ¶
func (v EntityVisibility) Is(v2 ...EntityVisibility) bool
Is reports whether the visibility matches any of the provided values.
func (EntityVisibility) Not ¶
func (v EntityVisibility) Not(v2 ...EntityVisibility) bool
Not reports whether the visibility does not match any of the provided values.
func (EntityVisibility) Valid ¶
func (v EntityVisibility) Valid() bool
Valid reports whether the visibility value is one of the supported visibilities.
type EventLog ¶
type EventLog struct {
ID ID `json:"id"`
UserID *ID `json:"user_id"`
UserUsername *string `json:"-"`
Type EventLogType `json:"action_type"`
EntityID *ID `json:"entity_id"`
EntityType *EntityType `json:"-"`
EntityTitle *string `json:"-"`
EntityPublicID *string `json:"-"`
EntityChangeID *ID `json:"entity_change_id"`
// Message is an optional pre-rendered text for the event.
// When set, it takes precedence over automatically generated messages.
// This is primarily used for system events.
Message string `json:"message"`
// Meta holds custom data relevant to log
Meta map[string]any `json:"-"`
IsPublic bool `json:"is_public"`
CreatedAt time.Time `json:"created_at"`
}
EventLog represents a single event entry used for activity feeds, audits, and system transparency.
func (EventLog) RenderMessage ¶
RenderMessage builds a human-readable, public-facing description of the event.
The message format is {user} {verb} [{entityType} "{title}"] e.g.
- ognev.dev created book "Hello world"
- ognev.dev joined
If Message is explicitly set, it is returned as-is. This is primarily used for system events where the text cannot be reliably derived from structured data. Otherwise, the message is composed from User, Type, and Entity.
type EventLogType ¶
type EventLogType string
EventLogType defines a stable identifier of a system or user event.
const ( // EventLogSystem represents a system-level event that is not directly // initiated by a user action (e.g. deployment, maintenance, background jobs). EventLogSystem EventLogType = "system_event" // EventLogUserAccountCreated is recorded when a user account record // is created in the system (email/password or OAuth). EventLogUserAccountCreated EventLogType = "user_account_created" // EventLogUserEmailConfirmed is recorded when a user successfully // confirms ownership of their email address. EventLogUserEmailConfirmed EventLogType = "user_email_confirmed" // EventLogUserRequestPasswordReset is recorded when a user initiates // a password reset flow. EventLogUserRequestPasswordReset EventLogType = "user_request_password_reset" // EventLogUserPasswordChangedByResetRequest is recorded when a user // changes their password via a password reset request. EventLogUserPasswordChangedByResetRequest EventLogType = "user_password_changed_by_reset_request" // EventLogUserPasswordChanged is recorded when a user changes their // password while authenticated. EventLogUserPasswordChanged EventLogType = "user_password_changed" // EventLogUserEmailChangeRequested is recorded when a user initiates // an email address change flow. EventLogUserEmailChangeRequested EventLogType = "user_email_change_requested" // EventLogUserEmailChanged is recorded when a user's email address // has been successfully changed. EventLogUserEmailChanged EventLogType = "user_email_changed" // EventLogUserUsernameChanged is recorded when a user changes // their username. EventLogUserUsernameChanged EventLogType = "user_username_changed" // EventLogUserAccountActivated is recorded when a user account becomes // active and eligible to appear in public-facing activity feeds. EventLogUserAccountActivated EventLogType = "user_account_activated" // EventLogEntitySubmitted is recorded when an entity is submitted // for moderation or review. EventLogEntitySubmitted EventLogType = "entity_submitted" // EventLogEntityApproved is recorded when an entity is approved // by a moderator or administrator. EventLogEntityApproved EventLogType = "entity_approved" // EventLogEntityRejected is recorded when an entity submission // is rejected during moderation. EventLogEntityRejected EventLogType = "entity_rejected" // EventLogEntityAdded is recorded when an entity becomes visible // and available to other users (published/accepted). EventLogEntityAdded EventLogType = "entity_added" // EventLogEntityUpdated is recorded when an existing entity // is updated. EventLogEntityUpdated EventLogType = "entity_updated" // EventLogEntityRenamed is recorded when an entity is only renamed. EventLogEntityRenamed EventLogType = "entity_renamed" )
func (EventLogType) Verb ¶
func (t EventLogType) Verb() string
Verb returns a short, human-readable verb describing the event.
type EventLogsFilter ¶
EventLogsFilter is used to filter and paginate event logs.
type File ¶
type File struct {
ID ID `json:"id"`
OwnerID ID `json:"owner_id"`
Name string `json:"name"`
Path string `json:"-"`
PreviewPath string `json:"-"`
Hash string `json:"-"`
Type file.Type `json:"type"`
MimeType string `json:"mime_type"`
Purpose FilePurpose `json:"purpose"`
Size int64 `json:"size"`
CreatedAt time.Time `json:"created_at"`
DeletedAt *time.Time `json:"-"`
Temp bool `json:"-"`
}
File represents a file uploaded to the system along with its metadata. Some fields are internal-only and intentionally excluded from JSON output.
func (*File) CreateRules ¶
CreateRules returns the validation schema for creating a new File.
func (*File) IsBookCover ¶
IsBookCover reports whether the file is an image intended to be used as a book cover.
type FilePurpose ¶
type FilePurpose string
FilePurpose describes the semantic purpose of a file in the system.
const ( // FilePurposeBookCover marks a file used as a book cover image. FilePurposeBookCover FilePurpose = "book-cover" )
type FilesFilter ¶
type FilesFilter struct {
Page int
PerPage int
WithCount bool
CreatedAt *FilterDT
DeletedAt *FilterDT
Deleted bool
OrderBy string
OrderDirection string
}
FilesFilter is used to filter, sort, and paginate file queries.
type FilterString ¶
type FilterString struct {
NotNull *bool
NotEmpty *bool
ExactMatch *string
Contains *string
NotContains *string
StartsWith *string
EndsWith *string
}
FilterString defines options for filtering string-type data.
type ID ¶
ID is a domain-specific UUID (v7). Add `json:",omitzero"` to JSON payloads where ID is optional, or zero ID will happily serialize itself as "00000000-0000-0000-0000-000000000000".
func NewID ¶
func NewID() ID
NewID generates a new UUID v7. It panics if the system clock is severely misconfigured.
func (ID) MarshalJSON ¶
MarshalJSON uses the built-in MarshalText from google/uuid.
func (*ID) UnmarshalJSON ¶
UnmarshalJSON decodes ID from JSON. It treats null and empty string ("") as zero (empty) ID.
func (*ID) UnmarshalYAML ¶
UnmarshalYAML implements the yaml.Unmarshaler interface.
type OAuthUserAccount ¶
type OAuthUserAccount struct {
ID ID `json:"id"`
UserID ID `json:"user_id"`
Provider provider.Type `json:"provider"`
ProviderUserID string `json:"provider_user_id"`
CreatedAt time.Time `json:"created_at"`
}
OAuthUserAccount links a local user to their external identity provider credentials.
type Page ¶
Page defines the data structure for a page.
func PageFromContext ¶
PageFromContext attempts to retrieve page object from the context.
func (*Page) CreateRules ¶
CreateRules provides the validation map used when saving a new book.
func (*Page) PropertyType ¶
PropertyType returns the property type for a given key.
func (*Page) UpdateRules ¶
UpdateRules provides the validation map used when editing an existing book.
type PasswordResetToken ¶
type PasswordResetToken struct {
ID ID `json:"-"`
UserID ID `json:"-"`
Token string `json:"-"`
ExpiresAt time.Time `json:"-"`
CreatedAt time.Time `json:"-"`
}
PasswordResetToken represents a record in the password_reset_tokens table. It stores a single-use token for a user to reset their password.
func (*PasswordResetToken) Invalid ¶
func (t *PasswordResetToken) Invalid() bool
Invalid returns true if the password reset token has expired.
type Topic ¶
type Topic struct {
ID ID `json:"id,omitzero"`
Type EntityType `json:"entity_type,omitempty"`
PublicID string `json:"public_id,omitempty"`
Name string `json:"name"`
Description string `json:"description,omitzero"`
CreatedAt time.Time `json:"created_at,omitzero"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
DeletedAt *time.Time `json:"deleted_at,omitempty"`
}
Topic represents a topic scoped to a specific entity type (e.g. "book"). Topics are linked to entities through the entity_topics pivot table.
type TopicsFilter ¶
type TopicsFilter struct {
Page int
PerPage int
Type EntityType
PublicIDs []string
WithCount bool
OrderBy string
OrderDirection string
}
TopicsFilter is used to filter and paginate user queries.
type User ¶
type User struct {
ID ID `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
EmailConfirmed bool `json:"-"`
Password string `json:"-"`
CreatedAt time.Time `json:"-"`
UpdatedAt *time.Time `json:"-"`
DeletedAt *time.Time `json:"-"`
// IsAdmin is true if the user ID is listed in "admins" key in config file.
// This field is set by the auth middleware.
// Until proper RBAC/ACL is implemented, we trust authority generously granted by the devs themselves.
IsAdmin bool `json:"-"`
}
User ...
func UserFromContext ¶
UserFromContext attempts to retrieve user object from the context.
type UserSession ¶
type UserSession struct {
ID ID `json:"id"`
UserID ID `json:"user_id"`
CreatedAt time.Time `json:"-"`
UpdatedAt *time.Time `json:"-"`
ExpiresAt time.Time `json:"-"`
}
UserSession represents an active session for a logged-in user.
func UserSessionFromContext ¶
func UserSessionFromContext(ctx context.Context) *UserSession
UserSessionFromContext attempts to retrieve the user session object from the context.