mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-11 21:39:00 +00:00
81847c7f4e
Not backported to main due to extensive i18n refactoring changes in this branch.
179 lines
6.0 KiB
Go
179 lines
6.0 KiB
Go
// Package template manages templates including creation, retrieval and rendering.
|
|
package template
|
|
|
|
import (
|
|
"database/sql"
|
|
"embed"
|
|
"errors"
|
|
"fmt"
|
|
"html/template"
|
|
"sync"
|
|
|
|
"github.com/abhinavxd/libredesk/internal/dbutil"
|
|
"github.com/abhinavxd/libredesk/internal/envelope"
|
|
"github.com/abhinavxd/libredesk/internal/template/models"
|
|
"github.com/jmoiron/sqlx"
|
|
"github.com/knadh/go-i18n"
|
|
"github.com/zerodha/logf"
|
|
)
|
|
|
|
var (
|
|
//go:embed queries.sql
|
|
efs embed.FS
|
|
ErrTemplateNotFound = errors.New("template not found")
|
|
TypeEmailOutgoing = "email_outgoing"
|
|
TypeEmailNotification = "email_notification"
|
|
)
|
|
|
|
// Manager handles template-related operations.
|
|
type Manager struct {
|
|
mutex sync.RWMutex
|
|
tpls *template.Template
|
|
webTpls *template.Template
|
|
funcMap template.FuncMap
|
|
q queries
|
|
lo *logf.Logger
|
|
i18n *i18n.I18n
|
|
}
|
|
|
|
// queries contains prepared SQL queries.
|
|
type queries struct {
|
|
InsertTemplate *sqlx.Stmt `query:"insert"`
|
|
UpdateTemplate *sqlx.Stmt `query:"update"`
|
|
DeleteTemplate *sqlx.Stmt `query:"delete"`
|
|
GetDefaultTemplate *sqlx.Stmt `query:"get-default"`
|
|
GetAllTemplates *sqlx.Stmt `query:"get-all"`
|
|
GetTemplate *sqlx.Stmt `query:"get-template"`
|
|
GetByName *sqlx.Stmt `query:"get-by-name"`
|
|
IsBuiltIn *sqlx.Stmt `query:"is-builtin"`
|
|
}
|
|
|
|
// New creates and returns a new instance of the Manager.
|
|
func New(lo *logf.Logger, db *sqlx.DB, webTpls *template.Template, tpls *template.Template, funcMap template.FuncMap, i18n *i18n.I18n) (*Manager, error) {
|
|
var q queries
|
|
if err := dbutil.ScanSQLFile("queries.sql", &q, db, efs); err != nil {
|
|
return nil, err
|
|
}
|
|
return &Manager{
|
|
mutex: sync.RWMutex{},
|
|
tpls: tpls,
|
|
webTpls: webTpls,
|
|
funcMap: funcMap,
|
|
q: q,
|
|
lo: lo,
|
|
i18n: i18n,
|
|
}, nil
|
|
}
|
|
|
|
// Update updates a new template with the given name, and body.
|
|
func (m *Manager) Update(id int, t models.Template) (models.Template, error) {
|
|
var result models.Template
|
|
if err := m.q.UpdateTemplate.Get(&result, id, t.Name, t.Body, t.IsDefault, t.Subject, t.Type); err != nil {
|
|
m.lo.Error("error updating template", "error", err)
|
|
return models.Template{}, envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// Create creates a template.
|
|
func (m *Manager) Create(t models.Template) (models.Template, error) {
|
|
if t.IsDefault {
|
|
t.Type = TypeEmailOutgoing
|
|
}
|
|
var result models.Template
|
|
if err := m.q.InsertTemplate.Get(&result, t.Name, t.Body, t.IsDefault, t.Subject, t.Type); err != nil {
|
|
if dbutil.IsUniqueViolationError(err) && t.IsDefault {
|
|
return models.Template{}, envelope.NewError(envelope.GeneralError, m.i18n.T("template.defaultTemplateAlreadyExists"), nil)
|
|
}
|
|
m.lo.Error("error inserting template", "error", err)
|
|
return models.Template{}, envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
// GetAll returns all templates by type.
|
|
func (m *Manager) GetAll(typ string) ([]models.Template, error) {
|
|
var templates = make([]models.Template, 0)
|
|
if err := m.q.GetAllTemplates.Select(&templates, typ); err != nil {
|
|
m.lo.Error("error fetching templates", "error", err)
|
|
return templates, envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
return templates, nil
|
|
}
|
|
|
|
// Get returns a template by id.
|
|
func (m *Manager) Get(id int) (models.Template, error) {
|
|
var templates = models.Template{}
|
|
if err := m.q.GetTemplate.Get(&templates, id); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return templates, envelope.NewError(envelope.NotFoundError, m.i18n.T("validation.notFoundTemplate"), nil)
|
|
}
|
|
m.lo.Error("error fetching template", "error", err)
|
|
return templates, envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
return templates, nil
|
|
}
|
|
|
|
// Delete deletes a template by id.
|
|
func (m *Manager) Delete(id int) error {
|
|
// Do not allow deletion of built-in templates.
|
|
isBuiltIn, err := m.isBuiltIn(id)
|
|
if err != nil {
|
|
return envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
if isBuiltIn {
|
|
return envelope.NewError(envelope.PermissionError, m.i18n.T("template.cannotDeleteBuiltInTemplate"), nil)
|
|
}
|
|
if _, err := m.q.DeleteTemplate.Exec(id); err != nil {
|
|
m.lo.Error("error deleting template", "error", err)
|
|
return envelope.NewError(envelope.GeneralError, m.i18n.T("globals.messages.somethingWentWrong"), nil)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// isBuiltIn returns true if the template is built-in.
|
|
func (m *Manager) isBuiltIn(id int) (bool, error) {
|
|
var isBuiltIn bool
|
|
if err := m.q.IsBuiltIn.Get(&isBuiltIn, id); err != nil {
|
|
m.lo.Error("error fetching template", "error", err)
|
|
return false, fmt.Errorf("error fetching template(%d) by id: %w", id, err)
|
|
}
|
|
return isBuiltIn, nil
|
|
}
|
|
|
|
// getDefaultOutgoingEmailTemplate returns the default outgoing email template.
|
|
func (m *Manager) getDefaultOutgoingEmailTemplate() (models.Template, error) {
|
|
var template models.Template
|
|
if err := m.q.GetDefaultTemplate.Get(&template); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return template, ErrTemplateNotFound
|
|
}
|
|
m.lo.Error("error fetching default template", "error", err)
|
|
return template, fmt.Errorf("error fetching default template: %w", err)
|
|
}
|
|
return template, nil
|
|
}
|
|
|
|
// getByName returns a template by name.
|
|
func (m *Manager) getByName(name string) (models.Template, error) {
|
|
var template models.Template
|
|
if err := m.q.GetByName.Get(&template, name); err != nil {
|
|
if err == sql.ErrNoRows {
|
|
return template, ErrTemplateNotFound
|
|
}
|
|
m.lo.Error("error fetching default template", "error", err)
|
|
return template, fmt.Errorf("error fetching template(%s) by name: %w", name, err)
|
|
}
|
|
return template, nil
|
|
}
|
|
|
|
// Reload reloads the templates and function map.
|
|
func (m *Manager) Reload(webTpls, tpls *template.Template, funcMap template.FuncMap) error {
|
|
m.mutex.Lock()
|
|
defer m.mutex.Unlock()
|
|
m.webTpls = webTpls
|
|
m.tpls = tpls
|
|
m.funcMap = funcMap
|
|
return nil
|
|
}
|