focalboard/server/app/templates.go
Harshil Sharma 9e3e3b5ef7
Added constant template IDs for tracking template usage (#3238)
* Added template ID to templates

* Removed debug log statements

* Removed debug log statements

* Fixed tests

* Generated template tracking ID on runtime

* MD5 is okay

* Fixed webapp tests

* Fixed webapp tests

* Fixed a big and tracked only in-built templates

* Fixed test
2022-06-29 19:47:54 +05:30

112 lines
3.2 KiB
Go

package app
import (
"bytes"
"fmt"
"strings"
"github.com/mattermost/focalboard/server/assets"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
const (
defaultTemplateVersion = 4
)
func (a *App) InitTemplates() error {
_, err := a.initializeTemplates()
return err
}
// initializeTemplates imports default templates if the boards table is empty.
func (a *App) initializeTemplates() (bool, error) {
boards, err := a.store.GetTemplateBoards(model.GlobalTeamID, "")
if err != nil {
return false, fmt.Errorf("cannot initialize templates: %w", err)
}
a.logger.Debug("Fetched template boards", mlog.Int("count", len(boards)))
isNeeded, reason := a.isInitializationNeeded(boards)
if !isNeeded {
a.logger.Debug("Template import not needed, skipping")
return false, nil
}
a.logger.Debug("Importing new default templates",
mlog.String("reason", reason),
mlog.Int("size", len(assets.DefaultTemplatesArchive)),
)
// Remove in case of newer Templates
if err = a.store.RemoveDefaultTemplates(boards); err != nil {
return false, fmt.Errorf("cannot remove old template boards: %w", err)
}
r := bytes.NewReader(assets.DefaultTemplatesArchive)
opt := model.ImportArchiveOptions{
TeamID: model.GlobalTeamID,
ModifiedBy: model.SystemUserID,
BlockModifier: fixTemplateBlock,
BoardModifier: fixTemplateBoard,
}
if err = a.ImportArchive(r, opt); err != nil {
return false, fmt.Errorf("cannot initialize global templates for team %s: %w", model.GlobalTeamID, err)
}
return true, nil
}
// isInitializationNeeded returns true if the blocks table contains no default templates,
// or contains at least one default template with an old version number.
func (a *App) isInitializationNeeded(boards []*model.Board) (bool, string) {
if len(boards) == 0 {
return true, "no default templates found"
}
// look for any built-in template boards with the wrong version number (or no version #).
for _, board := range boards {
// if not built-in board...skip
if board.CreatedBy != model.SystemUserID {
continue
}
if board.TemplateVersion < defaultTemplateVersion {
return true, "template_version too old"
}
}
return false, ""
}
// fixTemplateBlock fixes a block to be inserted as part of a template.
func fixTemplateBlock(block *model.Block, cache map[string]interface{}) bool {
// cache contains ids of skipped boards. Ensure their children are skipped as well.
if _, ok := cache[block.BoardID]; ok {
cache[block.ID] = struct{}{}
return false
}
if _, ok := cache[block.ParentID]; ok {
cache[block.ID] = struct{}{}
return false
}
return true
}
// fixTemplateBoard fixes a board to be inserted as part of a template.
func fixTemplateBoard(board *model.Board, cache map[string]interface{}) bool {
// filter out template blocks; we only want the non-template
// blocks which we will turn into default template blocks.
if board.IsTemplate {
cache[board.ID] = struct{}{}
return false
}
// remove '(NEW)' from title & force template flag
board.Title = strings.ReplaceAll(board.Title, "(NEW)", "")
board.IsTemplate = true
board.TemplateVersion = defaultTemplateVersion
board.Type = model.BoardTypeOpen
return true
}