service

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 39 Imported by: 0

Documentation

Overview

Package service provides business logic services.

Index

Constants

View Source
const (
	// CtxKeyArticleID is the context key to pass the target article ID.
	CtxKeyArticleID ctxKey = "article_id"
	// CtxKeyUserID is the context key to pass the acting user ID.
	CtxKeyUserID ctxKey = "user_id"
)
View Source
const SysconfigSetupCompleted = "setup.assistant.completed"

SysconfigSetupCompleted is the sysconfig key that records whether the first-run setup wizard has been completed. Seeded to "false" by migration 000026.

Variables

This section is empty.

Functions

func ArticleIDFromContext

func ArticleIDFromContext(ctx context.Context) (int, bool)

ArticleIDFromContext retrieves article ID from context.

func GenerateOTRSStoragePath

func GenerateOTRSStoragePath(ticketID int, articleID int, filename string) string

GenerateOTRSStoragePath creates an OTRS-style path for storing files Format: var/article/{year}/{month}/{day}/{ticket_id}/{article_id}/{filename} Note: We do not add a timestamp suffix here as uniqueness is provided by article_id scoping.

func GetPlaceholderThumbnail

func GetPlaceholderThumbnail(contentType string) ([]byte, string)

GetPlaceholderThumbnail returns a placeholder image for non-image files.

func IsSupportedImageType

func IsSupportedImageType(contentType string) bool

IsSupportedImageType checks if a content type can be thumbnailed. With govips/libvips, we support many more formats than before.

func SuggestCustomerID added in v0.9.0

func SuggestCustomerID(name string) string

SuggestCustomerID derives a customer_id slug from a company name: uppercased, alphanumerics only, spaces/underscores/slashes collapsed to single hyphens, trimmed and capped at 50 chars. The admin may refine it before submitting.

func UserIDFromContext

func UserIDFromContext(ctx context.Context) (int, bool)

UserIDFromContext retrieves user ID from context.

func WithArticleID

func WithArticleID(ctx context.Context, articleID int) context.Context

WithArticleID attaches an article ID to context.

func WithUserID

func WithUserID(ctx context.Context, userID int) context.Context

WithUserID attaches a user ID to context.

Types

type APITokenService

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

APITokenService handles API token operations

func NewAPITokenService

func NewAPITokenService(db *sql.DB) *APITokenService

NewAPITokenService creates a new API token service

func (*APITokenService) GenerateToken

func (s *APITokenService) GenerateToken(ctx context.Context, req *models.APITokenCreateRequest, userID int, userType models.APITokenUserType, createdBy int) (*models.APITokenCreateResponse, error)

GenerateToken creates a new API token for a user

func (*APITokenService) GenerateTokenForUser

func (s *APITokenService) GenerateTokenForUser(ctx context.Context, req *models.APITokenCreateRequest, targetUserID int, userType models.APITokenUserType, tenantID int, adminID int) (*models.APITokenCreateResponse, error)

GenerateTokenForUser creates a token for a specific user (admin use) This is used when an admin creates a token on behalf of another user. The adminID is recorded as created_by for audit purposes.

func (*APITokenService) GetToken

func (s *APITokenService) GetToken(ctx context.Context, tokenID int64) (*models.APIToken, error)

GetToken returns a token by ID (for admin verification)

func (*APITokenService) ListAllTokens

func (s *APITokenService) ListAllTokens(ctx context.Context, includeRevoked bool) ([]*models.APIToken, error)

ListAllTokens returns all tokens (admin only)

func (*APITokenService) ListUserTokens

func (s *APITokenService) ListUserTokens(ctx context.Context, userID int, userType models.APITokenUserType) ([]*models.APITokenListItem, error)

ListUserTokens returns all tokens for a user

func (*APITokenService) RevokeToken

func (s *APITokenService) RevokeToken(ctx context.Context, tokenID int64, userID int, userType models.APITokenUserType, revokedBy int) error

RevokeToken revokes a token by ID

func (*APITokenService) RevokeTokenAdmin

func (s *APITokenService) RevokeTokenAdmin(ctx context.Context, tokenID int64, revokedBy int) error

RevokeTokenAdmin revokes any token (admin only)

func (*APITokenService) UpdateLastUsed

func (s *APITokenService) UpdateLastUsed(ctx context.Context, tokenID int64, ip string) error

UpdateLastUsed updates the last used timestamp

func (*APITokenService) VerifyToken

func (s *APITokenService) VerifyToken(ctx context.Context, rawToken string) (*models.APIToken, error)

VerifyToken verifies an API token and returns the token record if valid

type AccessibleQueue

type AccessibleQueue struct {
	QueueID   uint   `json:"queue_id"`
	QueueName string `json:"queue_name"`
	GroupID   uint   `json:"group_id"`
	GroupName string `json:"group_name"`
}

AccessibleQueue represents a queue the user can access.

type AgentInput added in v0.9.0

type AgentInput struct {
	Login     string `json:"login" form:"login"`
	FirstName string `json:"first_name" form:"first_name"`
	LastName  string `json:"last_name" form:"last_name"`
	Email     string `json:"email,omitempty" form:"email"`
	GroupIDs  []int  `json:"group_ids,omitempty" form:"group_ids"`
}

AgentInput defines an agent (system user) to create. GroupIDs follow the same resolution rule as QueueInput.GroupIDs.

type AgentInputWithGroupIDs added in v0.9.0

type AgentInputWithGroupIDs struct {
	Login     string `json:"login"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Email     string `json:"email"`
	GroupIDs  []int  `json:"group_ids"`
}

AgentInputWithGroupIDs extends AgentInput with ID and group assignments

type AuthLog

type AuthLog struct {
	Username  string    `json:"username"`
	Success   bool      `json:"success"`
	Error     string    `json:"error,omitempty"`
	IPAddress string    `json:"ip_address,omitempty"`
	UserAgent string    `json:"user_agent,omitempty"`
	Timestamp time.Time `json:"timestamp"`
}

AuthLog represents an authentication attempt log entry.

type BusinessHoursInput added in v0.9.0

type BusinessHoursInput struct {
	Name        string `json:"name" form:"name"`                   // Configuration name
	Timezone    string `json:"timezone,omitempty" form:"timezone"` // e.g., "America/New_York"
	Description string `json:"description,omitempty" form:"description"`
}

BusinessHoursInput defines working hours configuration for SLA calculations.

type CannedResponseService

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

CannedResponseService handles business logic for canned responses.

func NewCannedResponseService

func NewCannedResponseService(repo repository.CannedResponseRepository) *CannedResponseService

NewCannedResponseService creates a new canned response service.

func (*CannedResponseService) ApplyResponse

func (s *CannedResponseService) ApplyResponse(ctx context.Context, application *models.CannedResponseApplication, userID uint) (*models.AppliedResponse, error)

ApplyResponse applies a canned response to a ticket.

func (*CannedResponseService) ApplyResponseWithContext

func (s *CannedResponseService) ApplyResponseWithContext(ctx context.Context, application *models.CannedResponseApplication, userID uint, autoFillCtx *models.AutoFillContext) (*models.AppliedResponse, error)

ApplyResponseWithContext applies a response with auto-fill context.

func (*CannedResponseService) CreateResponse

func (s *CannedResponseService) CreateResponse(ctx context.Context, response *models.CannedResponse) error

CreateResponse creates a new canned response.

func (*CannedResponseService) DeleteResponse

func (s *CannedResponseService) DeleteResponse(ctx context.Context, id uint) error

DeleteResponse deletes a response.

func (*CannedResponseService) ExportResponses

func (s *CannedResponseService) ExportResponses(ctx context.Context) ([]byte, error)

ExportResponses exports all responses to JSON.

func (*CannedResponseService) GetActiveResponses

func (s *CannedResponseService) GetActiveResponses(ctx context.Context) ([]models.CannedResponse, error)

GetActiveResponses retrieves all active responses.

func (*CannedResponseService) GetCategories

GetCategories retrieves all response categories.

func (*CannedResponseService) GetPopularResponses

func (s *CannedResponseService) GetPopularResponses(ctx context.Context, limit int) ([]models.CannedResponse, error)

GetPopularResponses returns the most used responses.

func (*CannedResponseService) GetQuickResponses

func (s *CannedResponseService) GetQuickResponses(ctx context.Context) ([]models.CannedResponse, error)

GetQuickResponses retrieves responses with shortcuts for quick access.

func (*CannedResponseService) GetResponse

func (s *CannedResponseService) GetResponse(ctx context.Context, id uint) (*models.CannedResponse, error)

GetResponse retrieves a response by ID.

func (*CannedResponseService) GetResponseByShortcut

func (s *CannedResponseService) GetResponseByShortcut(ctx context.Context, shortcut string) (*models.CannedResponse, error)

GetResponseByShortcut retrieves a response by its shortcut.

func (*CannedResponseService) GetResponsesByCategory

func (s *CannedResponseService) GetResponsesByCategory(ctx context.Context, category string) ([]models.CannedResponse, error)

GetResponsesByCategory retrieves responses by category.

func (*CannedResponseService) GetResponsesForUser

func (s *CannedResponseService) GetResponsesForUser(ctx context.Context, userID uint) ([]models.CannedResponse, error)

GetResponsesForUser retrieves responses accessible to a specific user.

func (*CannedResponseService) ImportResponses

func (s *CannedResponseService) ImportResponses(ctx context.Context, data []byte) error

ImportResponses imports responses from JSON.

func (*CannedResponseService) SearchResponses

SearchResponses searches for responses.

func (*CannedResponseService) UpdateResponse

func (s *CannedResponseService) UpdateResponse(ctx context.Context, response *models.CannedResponse) error

UpdateResponse updates an existing response.

type CreateTicketInput

type CreateTicketInput struct {
	Title                         string
	QueueID                       int
	PriorityID                    int
	StateID                       int
	UserID                        int
	Body                          string // optional initial article body
	ArticleSubject                string
	ArticleSenderTypeID           int
	ArticleTypeID                 int
	ArticleIsVisibleForCustomer   *bool
	ArticleMimeType               string
	ArticleCharset                string
	ArticleCommunicationChannelID int
	PendingUntil                  int // unix seconds when pending should elapse; 0 = none
	TypeID                        int // optional ticket type to set on create (0 = none)
	CustomerID                    string
	CustomerUserID                string
}

type CreatedEntity added in v0.9.0

type CreatedEntity struct {
	Kind string `json:"kind"`
	Name string `json:"name"`
	ID   int    `json:"id,omitempty"`
}

CreatedEntity records one entity ExecuteWizard successfully created, so a partial failure still reports what succeeded.

type CustomerCompany added in v0.9.0

type CustomerCompany struct {
	Name     string `json:"name"`
	Street   string `json:"street"`
	Zip      string `json:"zip"`
	City     string `json:"city"`
	Country  string `json:"country"`
	Url      string `json:"url"`
	Comments string `json:"comments"`
}

CustomerCompany holds customer company details

type CustomerConfiguration added in v0.9.0

type CustomerConfiguration struct {
	Customer        *CustomerCompany         `json:"customer"`
	Groups          []GroupWithID            `json:"groups"`
	Queues          []QueueWithGroupIDs      `json:"queues"`
	Agents          []AgentInputWithGroupIDs `json:"agents"`
	MailAccounts    []MailAccountInput       `json:"mail_accounts"`
	Services        []string                 `json:"services"`
	SLAs            []SLAInput               `json:"slas"`
	PortalUsers     []PortalUserInfo         `json:"portal_users"`
	CannedResponses []string                 `json:"canned_responses"`
	BusinessHours   []BusinessHoursInput     `json:"business_hours"`
	EmailTransport  *EmailTransportInput     `json:"mail_transport"`
}

CustomerConfiguration holds all configuration for an existing customer

type CustomerInput added in v0.9.0

type CustomerInput struct {
	CustomerID string            `json:"customer_id" form:"customer_id"`
	Name       string            `json:"name" form:"name"`
	Fields     map[string]string `json:"fields,omitempty" form:"fields"`
}

CustomerInput defines a customer company to create.

type CustomerPreferencesService

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

CustomerPreferencesService handles customer preference operations. Note: customer_preferences uses string user_id (login) unlike user_preferences which uses numeric ID.

func NewCustomerPreferencesService

func NewCustomerPreferencesService(db *sql.DB) *CustomerPreferencesService

NewCustomerPreferencesService creates a new customer preferences service.

func (*CustomerPreferencesService) DeletePreference

func (s *CustomerPreferencesService) DeletePreference(userLogin string, key string) error

DeletePreference removes a customer preference.

func (*CustomerPreferencesService) GetAllPreferences

func (s *CustomerPreferencesService) GetAllPreferences(userLogin string) (map[string]string, error)

GetAllPreferences returns all preferences for a customer.

func (*CustomerPreferencesService) GetLanguage

func (s *CustomerPreferencesService) GetLanguage(userLogin string) string

GetLanguage returns the customer's preferred language. Returns empty string if no preference is set (use system detection).

func (*CustomerPreferencesService) GetPreference

func (s *CustomerPreferencesService) GetPreference(userLogin string, key string) (string, error)

GetPreference retrieves a customer preference by key.

func (*CustomerPreferencesService) GetSessionTimeout

func (s *CustomerPreferencesService) GetSessionTimeout(userLogin string) int

GetSessionTimeout returns the customer's preferred session timeout. Returns 0 if no preference is set (use system default).

func (*CustomerPreferencesService) GetTheme

func (s *CustomerPreferencesService) GetTheme(userLogin string) string

GetTheme returns the customer's preferred theme.

func (*CustomerPreferencesService) GetThemeMode

func (s *CustomerPreferencesService) GetThemeMode(userLogin string) string

GetThemeMode returns the customer's preferred theme mode (light/dark).

func (*CustomerPreferencesService) SetLanguage

func (s *CustomerPreferencesService) SetLanguage(userLogin string, lang string) error

SetLanguage sets the customer's preferred language.

func (*CustomerPreferencesService) SetPreference

func (s *CustomerPreferencesService) SetPreference(userLogin string, key string, value string) error

SetPreference sets a customer preference. Uses delete-then-insert within a transaction to avoid duplicates and ensure atomicity.

func (*CustomerPreferencesService) SetSessionTimeout

func (s *CustomerPreferencesService) SetSessionTimeout(userLogin string, timeout int) error

SetSessionTimeout sets the customer's preferred session timeout.

func (*CustomerPreferencesService) SetTheme

func (s *CustomerPreferencesService) SetTheme(userLogin string, theme string) error

SetTheme sets the customer's preferred theme.

func (*CustomerPreferencesService) SetThemeMode

func (s *CustomerPreferencesService) SetThemeMode(userLogin string, mode string) error

SetThemeMode sets the customer's preferred theme mode (light/dark).

type CustomerUserInput added in v0.9.0

type CustomerUserInput struct {
	Login     string `json:"login" form:"login"`
	Email     string `json:"email" form:"email"`
	FirstName string `json:"first_name" form:"first_name"`
	LastName  string `json:"last_name" form:"last_name"`
	Title     string `json:"title,omitempty" form:"title"`
	Phone     string `json:"phone,omitempty" form:"phone"`
	Mobile    string `json:"mobile,omitempty" form:"mobile"`
}

CustomerUserInput defines one portal user to provision during onboarding.

type DatabaseStorageService

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

DatabaseStorageService implements StorageService by storing attachment bytes in the DB.

func NewDatabaseStorageService

func NewDatabaseStorageService() (*DatabaseStorageService, error)

func (*DatabaseStorageService) Delete

func (s *DatabaseStorageService) Delete(ctx context.Context, path string) error

func (*DatabaseStorageService) Exists

func (s *DatabaseStorageService) Exists(ctx context.Context, path string) (bool, error)

func (*DatabaseStorageService) GetMetadata

func (s *DatabaseStorageService) GetMetadata(ctx context.Context, path string) (*FileMetadata, error)

func (*DatabaseStorageService) GetURL

func (s *DatabaseStorageService) GetURL(ctx context.Context, path string, expiry time.Duration) (string, error)

func (*DatabaseStorageService) Retrieve

func (s *DatabaseStorageService) Retrieve(ctx context.Context, path string) (io.ReadCloser, error)

func (*DatabaseStorageService) Store

Store reads the file and inserts into article_data_mime_attachment for the article_id found in ctx.

type EmailTransportInput added in v0.9.0

type EmailTransportInput struct {
	Host     string `json:"host" form:"host"`                     // SMTP server host (required)
	Port     int    `json:"port" form:"port"`                     // 25, 465, 587 etc.
	User     string `json:"user,omitempty" form:"user"`           // Username for auth
	Password string `json:"password,omitempty" form:"password"`   // Password (stored securely)
	AuthType string `json:"auth_type,omitempty" form:"auth_type"` // plain, login, crammd5
	TLS      bool   `json:"tls,omitempty" form:"tls"`             // Enable TLS
	TLSMode  string `json:"tls_mode,omitempty" form:"tls_mode"`   // none, starttls, smtps
	From     string `json:"from,omitempty" form:"from"`           // Default from address
	FromName string `json:"from_name,omitempty" form:"from_name"` // Display name for sender
}

EmailTransportInput configures outbound SMTP for the system.

type FileMetadata

type FileMetadata struct {
	ID           string    `json:"id"`
	OriginalName string    `json:"original_name"`
	StoragePath  string    `json:"storage_path"`
	ContentType  string    `json:"content_type"`
	Size         int64     `json:"size"`
	Checksum     string    `json:"checksum"`
	UploadedAt   time.Time `json:"uploaded_at"`
}

FileMetadata contains metadata about a stored file.

type GroupInput added in v0.9.0

type GroupInput struct {
	Name     string `json:"name" form:"name"`
	Comments string `json:"comments,omitempty" form:"comments"`
}

GroupInput defines a group to create.

type GroupPermissions

type GroupPermissions struct {
	Group       *models.Group
	Permissions map[string]bool
}

GroupPermissions represents permissions for a single group.

type GroupUserMatrix

type GroupUserMatrix struct {
	Group *models.Group
	Users []*UserPermissions
}

GroupUserMatrix represents permissions for all users in a group.

type GroupWithID added in v0.9.0

type GroupWithID struct {
	Name string `json:"name"`
	ID   int    `json:"id"`
}

GroupWithID holds group name with ID from DB

type InternalNoteService

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

InternalNoteService handles business logic for internal notes.

func NewInternalNoteService

func NewInternalNoteService(repo repository.InternalNoteRepository) *InternalNoteService

NewInternalNoteService creates a new internal note service.

func (*InternalNoteService) CreateNote

func (s *InternalNoteService) CreateNote(ctx context.Context, note *models.InternalNote) error

CreateNote creates a new internal note.

func (*InternalNoteService) CreateNoteFromTemplate

func (s *InternalNoteService) CreateNoteFromTemplate(ctx context.Context, ticketID uint, templateID uint, variables map[string]string, authorID uint) (*models.InternalNote, error)

CreateNoteFromTemplate creates a note from a template.

func (*InternalNoteService) CreateTemplate

func (s *InternalNoteService) CreateTemplate(ctx context.Context, template *models.NoteTemplate) error

CreateTemplate creates a note template.

func (*InternalNoteService) DeleteNote

func (s *InternalNoteService) DeleteNote(ctx context.Context, id uint, deletedBy uint) error

DeleteNote deletes a note.

func (*InternalNoteService) DeleteTemplate

func (s *InternalNoteService) DeleteTemplate(ctx context.Context, id uint) error

DeleteTemplate deletes a template.

func (*InternalNoteService) ExportNotes

func (s *InternalNoteService) ExportNotes(ctx context.Context, ticketID uint, format string, exportedBy string) ([]byte, error)

ExportNotes exports notes in various formats.

func (*InternalNoteService) GetCategories

func (s *InternalNoteService) GetCategories(ctx context.Context) ([]models.NoteCategory, error)

GetCategories retrieves all note categories.

func (*InternalNoteService) GetEditHistory

func (s *InternalNoteService) GetEditHistory(ctx context.Context, noteID uint) ([]models.NoteEdit, error)

GetEditHistory retrieves edit history for a note.

func (*InternalNoteService) GetImportantNotes

func (s *InternalNoteService) GetImportantNotes(ctx context.Context, ticketID uint) ([]models.InternalNote, error)

GetImportantNotes retrieves important notes for a ticket.

func (*InternalNoteService) GetNote

GetNote retrieves a note by ID.

func (*InternalNoteService) GetNotesByTicket

func (s *InternalNoteService) GetNotesByTicket(ctx context.Context, ticketID uint) ([]models.InternalNote, error)

GetNotesByTicket retrieves all notes for a ticket.

func (*InternalNoteService) GetPinnedNotes

func (s *InternalNoteService) GetPinnedNotes(ctx context.Context, ticketID uint) ([]models.InternalNote, error)

GetPinnedNotes retrieves pinned notes for a ticket.

func (*InternalNoteService) GetRecentActivity

func (s *InternalNoteService) GetRecentActivity(ctx context.Context, ticketID uint, limit int) ([]models.NoteActivity, error)

GetRecentActivity gets recent activity for a ticket.

func (*InternalNoteService) GetTemplates

func (s *InternalNoteService) GetTemplates(ctx context.Context) ([]models.NoteTemplate, error)

GetTemplates retrieves all templates.

func (*InternalNoteService) GetTicketNoteSummary

func (s *InternalNoteService) GetTicketNoteSummary(ctx context.Context, ticketID uint) (*models.NoteStatistics, error)

GetTicketNoteSummary gets statistics for a ticket's notes.

func (*InternalNoteService) GetUserMentions

func (s *InternalNoteService) GetUserMentions(ctx context.Context, userID uint) ([]models.NoteMention, error)

GetUserMentions gets mentions for a user.

func (*InternalNoteService) MarkImportant

func (s *InternalNoteService) MarkImportant(ctx context.Context, noteID uint, important bool, userID uint) error

MarkImportant marks or unmarks a note as important.

func (*InternalNoteService) MarkMentionRead

func (s *InternalNoteService) MarkMentionRead(ctx context.Context, mentionID uint) error

MarkMentionRead marks a mention as read.

func (*InternalNoteService) PinNote

func (s *InternalNoteService) PinNote(ctx context.Context, noteID uint, userID uint) error

PinNote pins or unpins a note.

func (*InternalNoteService) SearchNotes

func (s *InternalNoteService) SearchNotes(ctx context.Context, filter *models.NoteFilter) ([]models.InternalNote, error)

SearchNotes searches for notes.

func (*InternalNoteService) UpdateNote

func (s *InternalNoteService) UpdateNote(ctx context.Context, note *models.InternalNote, editReason string) error

UpdateNote updates an existing note.

func (*InternalNoteService) UpdateTemplate

func (s *InternalNoteService) UpdateTemplate(ctx context.Context, template *models.NoteTemplate) error

UpdateTemplate updates a template.

type LDAPAttributeMap

type LDAPAttributeMap struct {
	Username    string `json:"username"`     // sAMAccountName, uid
	Email       string `json:"email"`        // mail, userPrincipalName
	FirstName   string `json:"first_name"`   // givenName
	LastName    string `json:"last_name"`    // sn
	DisplayName string `json:"display_name"` // displayName, cn
	Phone       string `json:"phone"`        // telephoneNumber
	Department  string `json:"department"`   // department
	Title       string `json:"title"`        // title
	Manager     string `json:"manager"`      // manager
	Groups      string `json:"groups"`       // memberOf
	ObjectGUID  string `json:"object_guid"`  // objectGUID
	ObjectSID   string `json:"object_sid"`   // objectSid
}

LDAPAttributeMap maps LDAP attributes to GoatFlow user fields.

type LDAPConfig

type LDAPConfig struct {
	Host                 string           `json:"host"`
	Port                 int              `json:"port"`
	BaseDN               string           `json:"base_dn"`
	BindDN               string           `json:"bind_dn"`
	BindPassword         string           `json:"bind_password"`
	UserFilter           string           `json:"user_filter"`
	UserSearchBase       string           `json:"user_search_base,omitempty"`
	GroupFilter          string           `json:"group_filter,omitempty"`
	GroupSearchBase      string           `json:"group_search_base,omitempty"`
	UseTLS               bool             `json:"use_tls"`
	StartTLS             bool             `json:"start_tls"`
	InsecureSkipVerify   bool             `json:"insecure_skip_verify"`
	AttributeMap         LDAPAttributeMap `json:"attribute_map"`
	GroupMemberAttribute string           `json:"group_member_attribute"`
	AutoCreateUsers      bool             `json:"auto_create_users"`
	AutoUpdateUsers      bool             `json:"auto_update_users"`
	AutoCreateGroups     bool             `json:"auto_create_groups"`
	SyncInterval         time.Duration    `json:"sync_interval"`
	DefaultRole          string           `json:"default_role"`
	AdminGroups          []string         `json:"admin_groups,omitempty"`
	UserGroups           []string         `json:"user_groups,omitempty"`
}

LDAPConfig represents LDAP configuration.

type LDAPGroup

type LDAPGroup struct {
	DN          string   `json:"dn"`
	Name        string   `json:"name"`
	Description string   `json:"description"`
	Members     []string `json:"members"`
	ObjectGUID  string   `json:"object_guid"`
	ObjectSID   string   `json:"object_sid"`
}

LDAPGroup represents a group from LDAP.

type LDAPService

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

LDAPService handles LDAP/Active Directory integration.

func NewLDAPService

func NewLDAPService(userRepo *memory.UserRepository, roleRepo *memory.RoleRepository, groupRepo *memory.GroupRepository) *LDAPService

NewLDAPService creates a new LDAP service.

func (*LDAPService) AuthenticateUser

func (s *LDAPService) AuthenticateUser(username, password string) (*LDAPUser, error)

AuthenticateUser authenticates a user against LDAP.

func (*LDAPService) ConfigureLDAP

func (s *LDAPService) ConfigureLDAP(config *LDAPConfig) error

ConfigureLDAP configures LDAP integration.

func (*LDAPService) GetAuthLogs

func (s *LDAPService) GetAuthLogs(limit int) []AuthLog

GetAuthLogs returns authentication logs.

func (*LDAPService) GetConfig

func (s *LDAPService) GetConfig() *LDAPConfig

GetConfig returns the current LDAP configuration (without sensitive data).

func (*LDAPService) GetGroups

func (s *LDAPService) GetGroups() ([]*LDAPGroup, error)

GetGroups retrieves groups from LDAP.

func (*LDAPService) GetSyncStatus

func (s *LDAPService) GetSyncStatus() map[string]interface{}

GetSyncStatus returns the status of the last sync.

func (*LDAPService) GetUser

func (s *LDAPService) GetUser(username string) (*LDAPUser, error)

GetUser retrieves a user from LDAP.

func (*LDAPService) ImportUsers

func (s *LDAPService) ImportUsers(usernames []string, dryRun bool) (*LDAPSyncResult, error)

ImportUsers imports specific users from LDAP.

func (*LDAPService) Stop

func (s *LDAPService) Stop()

Stop stops the LDAP service.

func (*LDAPService) SyncUsers

func (s *LDAPService) SyncUsers() (*LDAPSyncResult, error)

SyncUsers synchronizes users from LDAP.

func (*LDAPService) TestConnection

func (s *LDAPService) TestConnection(config *LDAPConfig) error

TestConnection tests the LDAP connection.

type LDAPSyncResult

type LDAPSyncResult struct {
	UsersFound    int           `json:"users_found"`
	UsersCreated  int           `json:"users_created"`
	UsersUpdated  int           `json:"users_updated"`
	UsersDisabled int           `json:"users_disabled"`
	GroupsFound   int           `json:"groups_found"`
	GroupsCreated int           `json:"groups_created"`
	GroupsUpdated int           `json:"groups_updated"`
	Errors        []string      `json:"errors"`
	StartTime     time.Time     `json:"start_time"`
	EndTime       time.Time     `json:"end_time"`
	Duration      time.Duration `json:"duration"`
	DryRun        bool          `json:"dry_run"`
}

LDAPSyncResult represents the result of an LDAP sync operation.

type LDAPUser

type LDAPUser struct {
	DN          string            `json:"dn"`
	Username    string            `json:"username"`
	Email       string            `json:"email"`
	FirstName   string            `json:"first_name"`
	LastName    string            `json:"last_name"`
	DisplayName string            `json:"display_name"`
	Phone       string            `json:"phone"`
	Department  string            `json:"department"`
	Title       string            `json:"title"`
	Manager     string            `json:"manager"`
	Groups      []string          `json:"groups"`
	Attributes  map[string]string `json:"attributes"`
	ObjectGUID  string            `json:"object_guid"`
	ObjectSID   string            `json:"object_sid"`
	LastLogin   time.Time         `json:"last_login"`
	IsActive    bool              `json:"is_active"`
}

LDAPUser represents a user from LDAP.

type LocalStorageService

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

LocalStorageService implements StorageService for local file system.

func NewLocalStorageService

func NewLocalStorageService(basePath string) (*LocalStorageService, error)

NewLocalStorageService creates a new local storage service.

func (*LocalStorageService) Delete

func (s *LocalStorageService) Delete(ctx context.Context, path string) error

Delete removes a file from the local file system.

func (*LocalStorageService) Exists

func (s *LocalStorageService) Exists(ctx context.Context, path string) (bool, error)

Exists checks if a file exists in the local file system.

func (*LocalStorageService) GetMetadata

func (s *LocalStorageService) GetMetadata(ctx context.Context, path string) (*FileMetadata, error)

GetMetadata retrieves file metadata.

func (*LocalStorageService) GetURL

func (s *LocalStorageService) GetURL(ctx context.Context, path string, expiry time.Duration) (string, error)

GetURL returns the file path for local storage (no pre-signed URLs).

func (*LocalStorageService) Retrieve

func (s *LocalStorageService) Retrieve(ctx context.Context, path string) (io.ReadCloser, error)

Retrieve gets a file from the local file system.

func (*LocalStorageService) Store

Store saves a file to the local file system.

type LookupService

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

LookupService provides lookup data for forms and dropdowns.

func NewLookupService

func NewLookupService() *LookupService

NewLookupService creates a new lookup service.

func (*LookupService) GetPriorities

func (s *LookupService) GetPriorities() []models.LookupItem

GetPriorities returns available priorities.

func (*LookupService) GetPriorityByValue

func (s *LookupService) GetPriorityByValue(value string) (*models.LookupItem, bool)

GetPriorityByValue returns a priority by its value.

func (*LookupService) GetQueueByID

func (s *LookupService) GetQueueByID(id int) (*models.QueueInfo, bool)

GetQueueByID returns a specific queue by ID.

func (*LookupService) GetQueues

func (s *LookupService) GetQueues() []models.QueueInfo

GetQueues returns available queues.

func (*LookupService) GetStatusByValue

func (s *LookupService) GetStatusByValue(value string) (*models.LookupItem, bool)

GetStatusByValue returns a status by its value.

func (*LookupService) GetStatuses

func (s *LookupService) GetStatuses() []models.LookupItem

GetStatuses returns available ticket statuses.

func (*LookupService) GetTicketFormData

func (s *LookupService) GetTicketFormData() *models.TicketFormData

GetTicketFormData returns all data needed for ticket forms (defaults to English).

func (*LookupService) GetTicketFormDataWithLang

func (s *LookupService) GetTicketFormDataWithLang(lang string) *models.TicketFormData

GetTicketFormDataWithLang returns all data needed for ticket forms with translation.

func (*LookupService) GetTypeByID

func (s *LookupService) GetTypeByID(id int) (*models.LookupItem, bool)

GetTypeByID returns a ticket type by ID.

func (*LookupService) GetTypes

func (s *LookupService) GetTypes() []models.LookupItem

GetTypes returns available ticket types.

func (*LookupService) InvalidateCache

func (s *LookupService) InvalidateCache()

InvalidateCache forces a cache refresh on next request.

type MailAccountInput added in v0.9.0

type MailAccountInput struct {
	Login              string `json:"login" form:"login"`                                           // mailbox username / email
	Password           string `json:"password" form:"password"`                                     // mailbox password (stored as-is, matching existing admin UI)
	Host               string `json:"host" form:"host"`                                             // IMAP/POP3 host
	AccountType        string `json:"account_type" form:"account_type"`                             // IMAP, IMAPTLS, IMAPS, POP3, POP3S
	QueueID            int    `json:"queue_id" form:"queue_id"`                                     // existing queue fetched mail lands in
	CreateQueueName    string `json:"create_queue_name,omitempty" form:"create_queue_name"`         // if set + QueueID==0, create a new queue
	CreateQueueGroupID int    `json:"create_queue_group_id,omitempty" form:"create_queue_group_id"` // owning team for a created queue
	// CreateQueueUseNewTeam: own the created queue with the team created earlier
	// in this onboarding wizard (no id yet at request time).
	CreateQueueUseNewTeam bool   `json:"create_queue_use_new_team,omitempty" form:"create_queue_use_new_team"`
	IMAPFolder            string `json:"imap_folder,omitempty" form:"imap_folder"`
	Trusted               bool   `json:"trusted,omitempty" form:"trusted"`
	Comments              string `json:"comments,omitempty" form:"comments"`
}

MailAccountInput configures an inbound mailbox (OTRS mail_account) whose fetched messages land in a queue — used to wire up a customer's support email address during onboarding.

type MergeNode

type MergeNode struct {
	TicketID uint      `json:"ticket_id"`
	MergedAt time.Time `json:"merged_at"`
	MergedBy uint      `json:"merged_by"`
	Reason   string    `json:"reason"`
	IsActive bool      `json:"is_active"`
}

MergeNode represents a node in the merge tree.

type MergeRule

type MergeRule struct {
	Name       string `json:"name"`
	Condition  string `json:"condition"`
	TimeWindow int    `json:"time_window_hours"`
	MaxMerges  int    `json:"max_merges"`
	IsActive   bool   `json:"is_active"`
}

MergeRule defines a rule for automatic merging.

type MergeTree

type MergeTree struct {
	ParentID      uint        `json:"parent_id"`
	Children      []MergeNode `json:"children"`
	TotalChildren int         `json:"total_children"`
	Depth         int         `json:"depth"`
}

MergeTree represents a hierarchical view of merged tickets.

type OnboardCustomerRequest added in v0.9.0

type OnboardCustomerRequest struct {
	CustomerID string              `json:"customer_id" form:"customer_id"`
	Name       string              `json:"name" form:"name"`
	Street     string              `json:"street,omitempty" form:"street"`
	City       string              `json:"city,omitempty" form:"city"`
	ZIP        string              `json:"zip,omitempty" form:"zip"`
	Country    string              `json:"country,omitempty" form:"country"`
	URL        string              `json:"url,omitempty" form:"url"`
	Comments   string              `json:"comments,omitempty" form:"comments"`
	Users      []CustomerUserInput `json:"users,omitempty" form:"users"`
	// ManagingGroupIDs: agent teams granted read-write access to this company
	// (OTRS group_customer) — i.e. which teams manage this customer.
	ManagingGroupIDs []int `json:"managing_group_ids,omitempty" form:"managing_group_ids"`
	// CreateManagingGroupName: if set, create a new team with this name (e.g.
	// derived from the customer id) and add it to the managing teams.
	CreateManagingGroupName string `json:"create_managing_group_name,omitempty" form:"create_managing_group_name"`
	// Optional Service/SLA mapping (OTRS service → service_sla → service_customer_user).
	ServiceName string `json:"service_name,omitempty" form:"service_name"`
	SLAID       int    `json:"sla_id,omitempty" form:"sla_id"`
	// Optional inbound mailbox (OTRS mail_account) wired to a destination queue.
	MailAccount *MailAccountInput `json:"mail_account,omitempty" form:"mail_account"`
}

OnboardCustomerRequest is the full payload for the customer onboarding wizard: company identity + address + the initial portal users to provision.

type OnboardCustomerResult added in v0.9.0

type OnboardCustomerResult struct {
	Success          bool            `json:"success"`
	CustomerID       string          `json:"customer_id"`
	CompanyName      string          `json:"company_name"`
	UsersCreated     []OnboardedUser `json:"users_created"`
	ManagingGroupIDs []int           `json:"managing_group_ids,omitempty"`
	ServiceID        int             `json:"service_id,omitempty"`
	ServiceName      string          `json:"service_name,omitempty"`
	SLALinked        bool            `json:"sla_linked,omitempty"`
	CreatedGroupID   int             `json:"created_group_id,omitempty"`
	CreatedGroupName string          `json:"created_group_name,omitempty"`
	MailAccountID    int             `json:"mail_account_id,omitempty"`
	CreatedQueueID   int             `json:"created_queue_id,omitempty"`
	Error            string          `json:"error,omitempty"`
}

OnboardCustomerResult is the outcome of OnboardCustomer.

type OnboardedUser added in v0.9.0

type OnboardedUser struct {
	Login    string `json:"login"`
	Email    string `json:"email"`
	Password string `json:"password,omitempty"`
}

OnboardedUser records one provisioned portal user and its one-time password.

type PermissionMatrix

type PermissionMatrix struct {
	User   *models.User
	Groups []*GroupPermissions
}

PermissionMatrix represents a user's permissions across all groups.

type PermissionService

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

PermissionService handles business logic for permissions.

func NewPermissionService

func NewPermissionService(db *sql.DB) *PermissionService

NewPermissionService creates a new permission service.

func (*PermissionService) CloneUserPermissions

func (s *PermissionService) CloneUserPermissions(sourceUserID, targetUserID uint) error

CloneUserPermissions copies all permissions from one user to another.

func (*PermissionService) GetEffectivePermissions

func (s *PermissionService) GetEffectivePermissions(userID, groupID uint) (map[string]bool, error)

GetEffectivePermissions calculates effective permissions considering inheritance.

func (*PermissionService) GetGroupPermissionMatrix

func (s *PermissionService) GetGroupPermissionMatrix(groupID uint) (*GroupUserMatrix, error)

GetGroupPermissionMatrix gets all users and their permissions for a group.

func (*PermissionService) GetUserPermissionMatrix

func (s *PermissionService) GetUserPermissionMatrix(userID uint) (*PermissionMatrix, error)

GetUserPermissionMatrix gets complete permission matrix for a user.

func (*PermissionService) RemoveAllUserPermissions

func (s *PermissionService) RemoveAllUserPermissions(userID uint) error

RemoveAllUserPermissions removes all permissions for a user.

func (*PermissionService) UpdateUserPermissions

func (s *PermissionService) UpdateUserPermissions(userID uint, permissions map[uint]map[string]bool) error

UpdateUserPermissions updates all permissions for a user.

func (*PermissionService) ValidatePermissions

func (s *PermissionService) ValidatePermissions(userID, groupID uint, requiredPerms []string) (bool, error)

ValidatePermissions checks if a user has specific permissions for a group.

type PluginSetupTask added in v0.9.0

type PluginSetupTask struct {
	Plugin      string `json:"plugin"`
	ID          string `json:"id"`
	Title       string `json:"title"`
	Description string `json:"description,omitempty"`
	Icon        string `json:"icon,omitempty"`
	Category    string `json:"category"`
	Handler     string `json:"handler"`
}

PluginSetupTask is one entry in the setup task catalog. Core tasks use Plugin == "setup-assistant"; plugin-contributed tasks carry the plugin name.

type PortalUserInfo added in v0.9.0

type PortalUserInfo struct {
	Login     string `json:"login"`
	Email     string `json:"email"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Phone     string `json:"phone,omitempty"`
	Title     string `json:"title,omitempty"`
}

PortalUserInfo holds a customer portal user record for the config response.

type QueueAccessService

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

QueueAccessService handles queue permission checks for users. It resolves both direct permissions (via group_user) and role-based permissions (via role_user -> group_role) following OTRS compatibility.

func NewQueueAccessService

func NewQueueAccessService(db *sql.DB) *QueueAccessService

NewQueueAccessService creates a new queue access service.

func (*QueueAccessService) GetAccessibleQueueIDs

func (s *QueueAccessService) GetAccessibleQueueIDs(ctx context.Context, userID uint, permType string) ([]uint, error)

GetAccessibleQueueIDs returns all queue IDs the user can access with the specified permission type.

func (*QueueAccessService) GetAccessibleQueues

func (s *QueueAccessService) GetAccessibleQueues(ctx context.Context, userID uint, permType string) ([]AccessibleQueue, error)

GetAccessibleQueues returns full queue information for all queues the user can access with the specified permission type.

func (*QueueAccessService) GetQueueGroupID

func (s *QueueAccessService) GetQueueGroupID(ctx context.Context, queueID uint) (uint, error)

GetQueueGroupID returns the group ID for a specific queue.

func (*QueueAccessService) GetUserEffectiveGroupIDs

func (s *QueueAccessService) GetUserEffectiveGroupIDs(ctx context.Context, userID uint, permType string) ([]uint, error)

GetUserEffectiveGroupIDs returns all group IDs the user has access to with the specified permission type. This includes both direct permissions (from group_user) and role-based permissions (from role_user -> group_role). The 'rw' permission supersedes all others, so if checking for 'ro', users with 'rw' are also included.

func (*QueueAccessService) HasPermissionOnGroup

func (s *QueueAccessService) HasPermissionOnGroup(ctx context.Context, userID, groupID uint, permType string) (bool, error)

HasPermissionOnGroup checks if user has specific permission on a group.

func (*QueueAccessService) HasQueueAccess

func (s *QueueAccessService) HasQueueAccess(ctx context.Context, userID, queueID uint, permType string) (bool, error)

HasQueueAccess checks if the user has the specified permission type for a specific queue.

func (*QueueAccessService) IsAdmin

func (s *QueueAccessService) IsAdmin(ctx context.Context, userID uint) (bool, error)

IsAdmin checks if the user is in the admin group. Admin users bypass all queue permission checks.

type QueueInput added in v0.9.0

type QueueInput struct {
	Name     string `json:"name" form:"name"`
	GroupIDs []int  `json:"group_ids,omitempty" form:"group_ids"`
	Comments string `json:"comments,omitempty" form:"comments"`
}

QueueInput defines a queue to create. GroupIDs are 1-based indices into WizardRequest.Groups when submitted through the first-run wizard (the groups do not have database IDs yet); ExecuteWizard resolves them to real IDs. When CreateQueue is called directly (task handlers / API on an existing system), GroupIDs must be real database group IDs.

type QueueWithGroupIDs added in v0.9.0

type QueueWithGroupIDs struct {
	Name     string `json:"name"`
	GroupIDs []int  `json:"group_ids"`
}

QueueWithGroupIDs holds queue with group assignments

type ReindexStats

type ReindexStats struct {
	Total     int
	Indexed   int
	Failed    int
	StartTime time.Time
	EndTime   time.Time
	Duration  time.Duration
}

ReindexStats contains statistics for reindexing operation.

type ResponseTemplateInput added in v0.9.0

type ResponseTemplateInput struct {
	Name        string   `json:"name" form:"name"`                           // Display name (required)
	Shortcut    string   `json:"shortcut,omitempty" form:"shortcut"`         // Quick access code
	Category    string   `json:"category,omitempty" form:"category"`         // For organization
	Content     string   `json:"content" form:"content"`                     // Response body (required)
	ContentType string   `json:"content_type,omitempty" form:"content_type"` // text/plain or text/html
	Tags        []string `json:"tags,omitempty" form:"tags"`                 // Search tags
}

ResponseTemplateInput defines a canned response template for customer support.

type SLAInput added in v0.9.0

type SLAInput struct {
	Name              string `json:"name" form:"name"`
	FirstResponseTime int    `json:"first_response_time" form:"first_response_time"`
	SolutionTime      int    `json:"solution_time" form:"solution_time"`
}

SLAInput defines an SLA to create. Times are in minutes.

type SearchService

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

SearchService handles search operations for tickets.

func NewSearchService

func NewSearchService(client zinc.Client) *SearchService

NewSearchService creates a new search service.

func (*SearchService) BulkIndexTickets

func (s *SearchService) BulkIndexTickets(ctx context.Context, tickets []models.Ticket) error

BulkIndexTickets indexes multiple tickets at once.

func (*SearchService) DeleteTicketFromIndex

func (s *SearchService) DeleteTicketFromIndex(ctx context.Context, ticketNumber string) error

DeleteTicketFromIndex removes a ticket from the search index.

func (*SearchService) ExecuteSavedSearch

func (s *SearchService) ExecuteSavedSearch(ctx context.Context, id uint) (*models.SearchResult, error)

ExecuteSavedSearch runs a saved search.

func (*SearchService) GetSavedSearch

func (s *SearchService) GetSavedSearch(ctx context.Context, id uint) (*models.SavedSearch, error)

GetSavedSearch retrieves a saved search.

func (*SearchService) GetSavedSearches

func (s *SearchService) GetSavedSearches(ctx context.Context, userID uint) ([]models.SavedSearch, error)

GetSavedSearches retrieves all saved searches for a user.

func (*SearchService) GetSearchAnalytics

func (s *SearchService) GetSearchAnalytics(ctx context.Context, from, to time.Time) (*models.SearchAnalytics, error)

GetSearchAnalytics generates search analytics.

func (*SearchService) GetSearchHistory

func (s *SearchService) GetSearchHistory(ctx context.Context, userID uint, limit int) ([]models.SearchHistory, error)

GetSearchHistory retrieves search history for a user.

func (*SearchService) GetSearchSuggestions

func (s *SearchService) GetSearchSuggestions(ctx context.Context, text string) ([]string, error)

GetSearchSuggestions provides search suggestions.

func (*SearchService) IndexTicket

func (s *SearchService) IndexTicket(ctx context.Context, ticket *models.Ticket) error

IndexTicket indexes a single ticket.

func (*SearchService) RecordSearchHistory

func (s *SearchService) RecordSearchHistory(ctx context.Context, userID uint, request *models.SearchRequest, results *models.SearchResult) error

RecordSearchHistory records a search in history.

func (*SearchService) ReindexAllTickets

func (s *SearchService) ReindexAllTickets(ctx context.Context, fetcher func() ([]models.Ticket, error)) (*ReindexStats, error)

ReindexAllTickets reindexes all tickets.

func (*SearchService) SaveSearch

func (s *SearchService) SaveSearch(ctx context.Context, search *models.SavedSearch) error

SaveSearch saves a search query for later use.

func (*SearchService) SearchTickets

func (s *SearchService) SearchTickets(ctx context.Context, request *models.SearchRequest) (*models.SearchResult, error)

SearchTickets performs a ticket search.

func (*SearchService) SearchWithFilter

func (s *SearchService) SearchWithFilter(ctx context.Context, filter *models.SearchFilter) (*models.SearchResult, error)

SearchWithFilter performs an advanced search with filters.

func (*SearchService) UpdateTicketInIndex

func (s *SearchService) UpdateTicketInIndex(ctx context.Context, ticket *models.Ticket) error

UpdateTicketInIndex updates a ticket in the search index.

type SessionService

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

SessionService handles session management operations.

func NewSessionService

func NewSessionService(repo repository.SessionRepository) *SessionService

NewSessionService creates a new session service.

func (*SessionService) CleanupByMaxAge

func (s *SessionService) CleanupByMaxAge(maxAge time.Duration) (int, error)

CleanupByMaxAge removes sessions that were created more than maxAge ago. This enforces the maximum session lifetime regardless of activity. Returns the number of sessions cleaned up.

func (*SessionService) CleanupExpired

func (s *SessionService) CleanupExpired(maxAge time.Duration) (int, error)

CleanupExpired removes sessions that have been inactive for longer than maxAge. Returns the number of sessions cleaned up.

func (*SessionService) CreateSession

func (s *SessionService) CreateSession(userID int, userLogin, userType, remoteAddr, userAgent string) (string, error)

CreateSession creates a new session for a user. Returns the generated session ID.

func (*SessionService) CreateSessionWithDetails

func (s *SessionService) CreateSessionWithDetails(userID int, userLogin, userType, userTitle, userFullName, remoteAddr, userAgent string) (string, error)

CreateSessionWithDetails creates a new session with additional user details. Returns the generated session ID.

func (*SessionService) GetSession

func (s *SessionService) GetSession(sessionID string) (*models.Session, error)

GetSession retrieves a session by its ID.

func (*SessionService) GetUserSessions

func (s *SessionService) GetUserSessions(userID int) ([]*models.Session, error)

GetUserSessions retrieves all sessions for a specific user.

func (*SessionService) KillSession

func (s *SessionService) KillSession(sessionID string) error

KillSession terminates a specific session.

func (*SessionService) KillUserSessions

func (s *SessionService) KillUserSessions(userID int) (int, error)

KillUserSessions terminates all sessions for a specific user. Returns the number of sessions killed.

func (*SessionService) ListSessions

func (s *SessionService) ListSessions() ([]*models.Session, error)

ListSessions retrieves all active sessions.

func (*SessionService) TouchSession

func (s *SessionService) TouchSession(sessionID string) error

TouchSession updates the last request time for a session. Should be called on each authenticated request.

type SetupAssistantService added in v0.9.0

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

SetupAssistantService is the business-logic core shared by the HTML and JSON handlers. All entity creation goes through existing repositories; no SQL is built in handlers or templates.

func NewSetupAssistantService added in v0.9.0

func NewSetupAssistantService(db *sql.DB, mgr *pluginmgr.Manager) *SetupAssistantService

NewSetupAssistantService wires the service with its repositories and the plugin manager (nil mgr is allowed — plugin task discovery simply returns none).

func (*SetupAssistantService) AssignAgentToGroups added in v0.9.0

func (s *SetupAssistantService) AssignAgentToGroups(ctx context.Context, userID int, groupIDs []int, createBy int) error

AssignAgentToGroups grants an existing agent (user) rw membership in the given teams. Idempotent per (user, group): an existing 'rw' row is left untouched. Returns an error if the agent does not exist or is inactive.

func (*SetupAssistantService) AssignGroupsToCustomer added in v0.9.0

func (s *SetupAssistantService) AssignGroupsToCustomer(ctx context.Context, customerID string, groupIDs []int, createBy int) error

AssignGroupsToCustomer grants agent teams (groups) read-write access to a customer company via the OTRS `group_customer` table — i.e. which teams can see and manage this customer's tickets. Idempotent per (customer, group).

func (*SetupAssistantService) AssignQueueToGroup added in v0.9.0

func (s *SetupAssistantService) AssignQueueToGroup(ctx context.Context, queueID int, groupID int, createBy int) error

AssignQueueToGroup grants an existing team ownership/access of an existing queue. In the canonical GoatFlow schema a queue is owned by a single team via queue.group_id (users gain queue access by belonging to that team), so the first team supplied becomes the queue's owner. Idempotent.

func (*SetupAssistantService) AssignServiceToCustomerUser added in v0.9.0

func (s *SetupAssistantService) AssignServiceToCustomerUser(ctx context.Context, login string, serviceID, createBy int) error

AssignServiceToCustomerUser grants a service to a customer user by login via the OTRS `service_customer_user` table.

func (*SetupAssistantService) CallPluginTask added in v0.9.0

func (s *SetupAssistantService) CallPluginTask(ctx context.Context, pluginName, taskID string, args []byte) ([]byte, error)

CallPluginTask dispatches a plugin setup task by invoking its handler via the plugin manager. Returns the handler's raw JSON response.

func (*SetupAssistantService) CreateAgent added in v0.9.0

func (s *SetupAssistantService) CreateAgent(ctx context.Context, login, firstName, lastName, email string, groupIDs []int, createBy int) (int, error)

CreateAgent creates a system user and grants rw access to the given groups via group_user. groupIDs must be real database group IDs.

func (*SetupAssistantService) CreateBusinessHours added in v0.9.0

func (s *SetupAssistantService) CreateBusinessHours(ctx context.Context, cfg BusinessHoursInput, createBy int) error

CreateBusinessHours creates a business hours calendar for SLA calculations.

func (*SetupAssistantService) CreateCannedResponses added in v0.9.0

func (s *SetupAssistantService) CreateCannedResponses(ctx context.Context, templates []ResponseTemplateInput, createBy int) error

CreateCannedResponses creates multiple canned response templates for customer onboarding.

func (*SetupAssistantService) CreateCustomerCompany added in v0.9.0

func (s *SetupAssistantService) CreateCustomerCompany(ctx context.Context, customerID, name string, fields map[string]string, createBy int) error

CreateCustomerCompany inserts a customer_company row. Fields carries optional columns (street, zip, city, country, url, comments).

func (*SetupAssistantService) CreateEmailTransport added in v0.9.0

func (s *SetupAssistantService) CreateEmailTransport(ctx context.Context, cfg EmailTransportInput, createBy int) error

CreateEmailTransport configures outbound SMTP settings via sysconfig.

func (*SetupAssistantService) CreateGroup added in v0.9.0

func (s *SetupAssistantService) CreateGroup(ctx context.Context, name, comments string, createBy int) (int, error)

CreateGroup creates a group and returns its new ID.

func (*SetupAssistantService) CreateMailAccount added in v0.9.0

func (s *SetupAssistantService) CreateMailAccount(ctx context.Context, m MailAccountInput, createBy int) (int, error)

CreateMailAccount provisions an inbound mailbox via the existing EmailAccountRepository (no raw SQL in the service). Fetched messages land in the chosen queue. The password is stored as provided, matching the existing admin UI and the inbound poller (which reads `pw` directly).

func (*SetupAssistantService) CreateQueue added in v0.9.0

func (s *SetupAssistantService) CreateQueue(ctx context.Context, name string, groupIDs []int, comments string, createBy int) (int, error)

CreateQueue creates a queue and assigns it to the given groups. The first group becomes the queue's primary group_id (NOT NULL); all groups additionally receive queue_group access rows. groupIDs must be real database group IDs.

func (*SetupAssistantService) CreateSLA added in v0.9.0

func (s *SetupAssistantService) CreateSLA(ctx context.Context, name string, firstResponseTime, solutionTime int, createBy int) (int, error)

CreateSLA inserts an SLA row and returns its new ID. Times are in minutes.

func (*SetupAssistantService) CreateService added in v0.9.0

func (s *SetupAssistantService) CreateService(ctx context.Context, name string, createBy int) (int, error)

CreateService inserts an OTRS `service` row and returns its new id. Used by the onboarding flow to give a customer SLA coverage the OTRS way (service → service_sla → service_customer_user).

func (*SetupAssistantService) ExecuteWizard added in v0.9.0

func (s *SetupAssistantService) ExecuteWizard(ctx context.Context, req WizardRequest) *WizardResult

ExecuteWizard creates every entity in WizardRequest in dependency order: groups → queues (queue_group) → agents (group_user) → customers → SLAs. On any failure it returns a WizardResult describing what succeeded and what failed. It is not wrapped in a single transaction (entity creation spans several repositories); on a fresh system partial state is re-runnable.

func (*SetupAssistantService) GetAllTasks added in v0.9.0

func (s *SetupAssistantService) GetAllTasks() []PluginSetupTask

GetAllTasks returns the combined core + plugin task catalog, grouped in catalog order (core first, then plugins).

func (*SetupAssistantService) GetCoreTasks added in v0.9.0

func (s *SetupAssistantService) GetCoreTasks() []PluginSetupTask

GetCoreTasks returns the built-in setup task catalog. These dispatch to the core HTML/API task handlers, not to plugins.

func (*SetupAssistantService) GetPluginTasks added in v0.9.0

func (s *SetupAssistantService) GetPluginTasks() []PluginSetupTask

GetPluginTasks returns setup tasks contributed by registered plugins.

func (*SetupAssistantService) IsSetupComplete added in v0.9.0

func (s *SetupAssistantService) IsSetupComplete(ctx context.Context) bool

IsSetupComplete reads the setup.assistant.completed sysconfig flag.

func (*SetupAssistantService) LinkServiceSLA added in v0.9.0

func (s *SetupAssistantService) LinkServiceSLA(ctx context.Context, serviceID, slaID int) error

LinkServiceSLA links an SLA to a service via the OTRS `service_sla` table. Idempotent: a duplicate link is not an error (INSERT IGNORE / ON CONFLICT).

func (*SetupAssistantService) LoadExistingCustomer added in v0.9.0

func (s *SetupAssistantService) LoadExistingCustomer(ctx context.Context, customerID string) (*CustomerConfiguration, error)

LoadExistingCustomer loads an existing customer company and its associated configuration for review and modification in the wizard.

func (*SetupAssistantService) MarkSetupComplete added in v0.9.0

func (s *SetupAssistantService) MarkSetupComplete(ctx context.Context) error

MarkSetupComplete sets the setup.assistant.completed flag to "true". Uses an UPDATE-then-INSERT sequence that works on both MySQL and PostgreSQL without depending on a unique constraint.

func (*SetupAssistantService) OnboardCustomer added in v0.9.0

OnboardCustomer provisions a full customer setup in one shot: creates the company, then each initial portal user (with a generated temporary password the admin distributes). On any failure it reports what succeeded and stops. If CustomerID is empty it is derived from Name via SuggestCustomerID.

func (*SetupAssistantService) Recce added in v0.9.0

Recce returns the current system snapshot. Each count is independent and defaults to 0 on error (missing table / query failure) so a partial schema never breaks the wizard gating — mirrors handleAdminDashboard's pattern.

type SimpleAttachment

type SimpleAttachment struct {
	ID          uint      `json:"id"`
	MessageID   uint      `json:"message_id"`
	Filename    string    `json:"filename"`
	ContentType string    `json:"content_type"`
	Size        int64     `json:"size"`
	URL         string    `json:"url"` // Download URL for the attachment
	CreatedAt   time.Time `json:"created_at"`
}

SimpleAttachment is a simplified attachment model.

type SimpleTicketMessage

type SimpleTicketMessage struct {
	ID           uint                `json:"id"`
	TicketID     uint                `json:"ticket_id"`
	Body         string              `json:"body"`
	Subject      string              `json:"subject"`
	ContentType  string              `json:"content_type"`
	CreatedBy    uint                `json:"created_by"`
	AuthorName   string              `json:"author_name"`
	AuthorEmail  string              `json:"author_email"`
	AuthorType   string              `json:"author_type"` // "Customer", "Agent", "System"
	SenderTypeID int                 `json:"sender_type_id"`
	SenderColor  string              `json:"sender_color,omitempty"` // Hex color from article_color
	IsPublic     bool                `json:"is_public"`
	IsInternal   bool                `json:"is_internal"`
	CreatedAt    time.Time           `json:"created_at"`
	Attachments  []*SimpleAttachment `json:"attachments,omitempty"`
}

SimpleTicketMessage is a simplified message model.

type SimpleTicketService

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

This is for development/testing with in-memory repository.

func NewSimpleTicketService

func NewSimpleTicketService(repo repository.ITicketRepository) *SimpleTicketService

NewSimpleTicketService creates a new simple ticket service.

func (*SimpleTicketService) AddMessage

func (s *SimpleTicketService) AddMessage(ticketID uint, message *SimpleTicketMessage) error

AddMessage adds a message to a ticket.

func (*SimpleTicketService) CreateTicket

func (s *SimpleTicketService) CreateTicket(ticket *models.Ticket) error

CreateTicket creates a new ticket.

func (*SimpleTicketService) DeleteTicket

func (s *SimpleTicketService) DeleteTicket(ticketID uint) error

DeleteTicket deletes a ticket.

func (*SimpleTicketService) GetMessages

func (s *SimpleTicketService) GetMessages(ticketID uint) ([]*SimpleTicketMessage, error)

GetMessages retrieves all messages for a ticket.

func (*SimpleTicketService) GetTicket

func (s *SimpleTicketService) GetTicket(ticketID uint) (*models.Ticket, error)

GetTicket retrieves a ticket by ID.

func (*SimpleTicketService) ListTickets

ListTickets returns a paginated list of tickets.

func (*SimpleTicketService) UpdateTicket

func (s *SimpleTicketService) UpdateTicket(ticket *models.Ticket) error

UpdateTicket updates an existing ticket.

type StorageService

type StorageService interface {
	// Store saves a file and returns its metadata
	Store(ctx context.Context, file multipart.File, header *multipart.FileHeader, path string) (*FileMetadata, error)

	// Retrieve gets a file by its storage path
	Retrieve(ctx context.Context, path string) (io.ReadCloser, error)

	// Delete removes a file from storage
	Delete(ctx context.Context, path string) error

	// Exists checks if a file exists
	Exists(ctx context.Context, path string) (bool, error)

	// GetURL returns a URL for accessing the file (for S3 pre-signed URLs)
	GetURL(ctx context.Context, path string, expiry time.Duration) (string, error)

	// GetMetadata retrieves file metadata without downloading the file
	GetMetadata(ctx context.Context, path string) (*FileMetadata, error)
}

StorageService defines the interface for file storage operations.

type StorageType

type StorageType string

StorageType represents the type of storage backend.

const (
	StorageTypeLocal StorageType = "local"
	StorageTypeS3    StorageType = "s3"
)

type SystemSnapshot added in v0.9.0

type SystemSnapshot struct {
	Groups         int  `json:"groups"`
	Queues         int  `json:"queues"`
	Agents         int  `json:"agents"`
	Customers      int  `json:"customers"`
	SLAs           int  `json:"slas"`
	Roles          int  `json:"roles"`
	SetupCompleted bool `json:"setup_completed"`
}

SystemSnapshot is the "recce" result: live counts of each core entity plus whether first-run setup has been marked complete. Drives both wizard gating (Mode 1) and the assistant dashboard (Mode 2).

type ThumbnailOptions

type ThumbnailOptions struct {
	Width   int
	Height  int
	Quality int    // JPEG quality 1-100
	Format  string // "jpeg" or "png"
}

ThumbnailOptions defines options for thumbnail generation.

func DefaultThumbnailOptions

func DefaultThumbnailOptions() ThumbnailOptions

DefaultThumbnailOptions returns sensible defaults.

type ThumbnailService

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

func NewThumbnailService

func NewThumbnailService(redisClient *redis.Client) *ThumbnailService

NewThumbnailService creates a new thumbnail service with Redis caching.

func (*ThumbnailService) GenerateThumbnail

func (s *ThumbnailService) GenerateThumbnail(data []byte, contentType string, opts ThumbnailOptions) (thumbnailData []byte, outputFormat string, err error)

GenerateThumbnail generates a thumbnail from image data using libvips. Supports JPEG, PNG, GIF, WebP, AVIF, HEIC, TIFF, and more.

func (*ThumbnailService) GetOrCreateThumbnail

func (s *ThumbnailService) GetOrCreateThumbnail(ctx context.Context, attachmentID int, data []byte, contentType string, opts ThumbnailOptions) ([]byte, string, error)

GetOrCreateThumbnail gets a thumbnail from cache or generates it.

func (*ThumbnailService) InvalidateThumbnail

func (s *ThumbnailService) InvalidateThumbnail(ctx context.Context, attachmentID int) error

InvalidateThumbnail removes a thumbnail from cache.

type TicketMergeService

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

TicketMergeService handles ticket merging and splitting operations.

func NewTicketMergeService

func NewTicketMergeService(repo repository.TicketMergeRepository) *TicketMergeService

NewTicketMergeService creates a new ticket merge service.

func (*TicketMergeService) AutoMergeByRules

func (s *TicketMergeService) AutoMergeByRules(ctx context.Context, rules []MergeRule) (int, error)

AutoMergeByRules applies automatic merge rules.

func (*TicketMergeService) BulkUnmerge

func (s *TicketMergeService) BulkUnmerge(ctx context.Context, ticketIDs []uint, reason string, userID uint) (int, error)

BulkUnmerge unmerges multiple tickets at once.

func (*TicketMergeService) CreateTicketRelation

func (s *TicketMergeService) CreateTicketRelation(ctx context.Context, relation *models.TicketRelation) error

CreateTicketRelation creates a relation between two tickets.

func (*TicketMergeService) DeleteTicketRelation

func (s *TicketMergeService) DeleteTicketRelation(ctx context.Context, relationID uint) error

DeleteTicketRelation removes a ticket relation.

func (*TicketMergeService) FindDuplicates

func (s *TicketMergeService) FindDuplicates(ctx context.Context, ticketID uint) ([]uint, error)

FindDuplicates suggests potential duplicate tickets.

func (*TicketMergeService) GetChildTickets

func (s *TicketMergeService) GetChildTickets(ctx context.Context, parentID uint) ([]uint, error)

GetChildTickets returns all child ticket IDs for a parent.

func (*TicketMergeService) GetMergeHistory

func (s *TicketMergeService) GetMergeHistory(ctx context.Context, ticketID uint) ([]models.TicketMerge, error)

GetMergeHistory returns the merge history for a ticket.

func (*TicketMergeService) GetMergeStatistics

func (s *TicketMergeService) GetMergeStatistics(ctx context.Context, from, to time.Time) (*models.MergeStatistics, error)

GetMergeStatistics returns merge statistics for a time period.

func (*TicketMergeService) GetMergeTree

func (s *TicketMergeService) GetMergeTree(ctx context.Context, parentID uint) (*MergeTree, error)

GetMergeTree returns a hierarchical view of merged tickets.

func (*TicketMergeService) GetRelatedTickets

func (s *TicketMergeService) GetRelatedTickets(ctx context.Context, ticketID uint) (map[string][]uint, error)

GetRelatedTickets returns all tickets related to a given ticket.

func (*TicketMergeService) GetTicketRelations

func (s *TicketMergeService) GetTicketRelations(ctx context.Context, ticketID uint) ([]models.TicketRelation, error)

GetTicketRelations returns all relations for a ticket.

func (*TicketMergeService) IsTicketMerged

func (s *TicketMergeService) IsTicketMerged(ctx context.Context, ticketID uint) (bool, error)

IsTicketMerged checks if a ticket is currently merged.

func (*TicketMergeService) MergeTickets

func (s *TicketMergeService) MergeTickets(ctx context.Context, request *models.MergeRequest, userID uint) ([]uint, error)

MergeTickets merges multiple child tickets into a parent ticket.

func (*TicketMergeService) SplitTicket

func (s *TicketMergeService) SplitTicket(ctx context.Context, request *models.SplitRequest, userID uint) *models.SplitResult

SplitTicket splits messages from one ticket into a new ticket.

func (*TicketMergeService) UnmergeTicket

func (s *TicketMergeService) UnmergeTicket(ctx context.Context, request *models.UnmergeRequest, userID uint) error

UnmergeTicket unmerges a previously merged ticket.

func (*TicketMergeService) ValidateMerge

func (s *TicketMergeService) ValidateMerge(ctx context.Context, request *models.MergeRequest) (*models.MergeValidation, error)

ValidateMerge validates if tickets can be merged.

type TicketService

type TicketService interface {
	Create(ctx context.Context, req CreateTicketInput) (*models.Ticket, error)
}

type TicketServiceOption

type TicketServiceOption func(*ticketService)

func WithArticleRepository

func WithArticleRepository(repo *repository.ArticleRepository) TicketServiceOption

WithArticleRepository wires the optional article repository used for the initial article.

type TicketTemplateService

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

TicketTemplateService handles business logic for ticket templates.

func NewTicketTemplateService

func NewTicketTemplateService(repo repository.TicketTemplateRepository, ticketService *SimpleTicketService) *TicketTemplateService

NewTicketTemplateService creates a new ticket template service.

func (*TicketTemplateService) ApplyTemplate

func (s *TicketTemplateService) ApplyTemplate(ctx context.Context, application *models.TemplateApplication) (*models.Ticket, error)

ApplyTemplate creates a new ticket from a template.

func (*TicketTemplateService) CreateTemplate

func (s *TicketTemplateService) CreateTemplate(ctx context.Context, template *models.TicketTemplate) error

CreateTemplate creates a new ticket template.

func (*TicketTemplateService) DeleteTemplate

func (s *TicketTemplateService) DeleteTemplate(ctx context.Context, id uint) error

DeleteTemplate deletes a template.

func (*TicketTemplateService) GetActiveTemplates

func (s *TicketTemplateService) GetActiveTemplates(ctx context.Context) ([]models.TicketTemplate, error)

GetActiveTemplates retrieves all active templates.

func (*TicketTemplateService) GetCategories

GetCategories retrieves all template categories.

func (*TicketTemplateService) GetPopularTemplates

func (s *TicketTemplateService) GetPopularTemplates(ctx context.Context, limit int) ([]models.TicketTemplate, error)

GetPopularTemplates returns the most used templates.

func (*TicketTemplateService) GetTemplate

func (s *TicketTemplateService) GetTemplate(ctx context.Context, id uint) (*models.TicketTemplate, error)

GetTemplate retrieves a template by ID.

func (*TicketTemplateService) GetTemplatesByCategory

func (s *TicketTemplateService) GetTemplatesByCategory(ctx context.Context, category string) ([]models.TicketTemplate, error)

GetTemplatesByCategory retrieves templates by category.

func (*TicketTemplateService) SearchTemplates

func (s *TicketTemplateService) SearchTemplates(ctx context.Context, query string) ([]models.TicketTemplate, error)

SearchTemplates searches for templates.

func (*TicketTemplateService) UpdateTemplate

func (s *TicketTemplateService) UpdateTemplate(ctx context.Context, template *models.TicketTemplate) error

UpdateTemplate updates an existing template.

type UserPermissions

type UserPermissions struct {
	User        *models.User
	Permissions map[string]bool
}

UserPermissions represents a user's permissions in a group.

type WizardRequest added in v0.9.0

type WizardRequest struct {
	OrgType            string                  `json:"org_type" form:"org_type"`
	Groups             []GroupInput            `json:"groups" form:"groups"`
	Queues             []QueueInput            `json:"queues" form:"queues"`
	Agents             []AgentInput            `json:"agents" form:"agents"`
	CustomerCompanies  []CustomerInput         `json:"customer_companies" form:"customer_companies"`
	SLAs               []SLAInput              `json:"slas" form:"slas"`
	ResponseTemplates  []ResponseTemplateInput `json:"response_templates,omitempty" form:"response_templates"`
	BusinessHours      []BusinessHoursInput    `json:"business_hours,omitempty" form:"business_hours"`
	MailTransport      *EmailTransportInput    `json:"mail_transport,omitempty" form:"mail_transport"`
	ExistingCustomerID string                  `json:"existing_customer_id,omitempty" form:"existing_customer_id"`
	CreateBy           int                     `json:"-" form:"-"`
}

WizardRequest is the single structured payload the wizard (UI or LLM) submits. Submitting everything at once makes the flow idempotent and API-friendly.

type WizardResult added in v0.9.0

type WizardResult struct {
	Success bool            `json:"success"`
	Created []CreatedEntity `json:"created,omitempty"`
	Error   string          `json:"error,omitempty"`
}

WizardResult is the outcome of ExecuteWizard.

Directories

Path Synopsis
Package genericinterface provides the GenericInterface service for web service execution.
Package genericinterface provides the GenericInterface service for web service execution.
Package ticket_number provides ticket number generation strategies.
Package ticket_number provides ticket number generation strategies.

Jump to

Keyboard shortcuts

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