package sqlstore import ( "database/sql" "fmt" sq "github.com/Masterminds/squirrel" "github.com/mattermost/focalboard/server/model" ) type BlockDoesntBelongToBoardsErr struct { blockID string } func (e BlockDoesntBelongToBoardsErr) Error() string { return fmt.Sprintf("block %s doesn't belong to any of the boards in the delete request", e.blockID) } func (s *SQLStore) createBoardsAndBlocksWithAdmin(db sq.BaseRunner, bab *model.BoardsAndBlocks, userID string) (*model.BoardsAndBlocks, []*model.BoardMember, error) { newBab, err := s.createBoardsAndBlocks(db, bab, userID) if err != nil { return nil, nil, err } members := []*model.BoardMember{} for _, board := range newBab.Boards { bm := &model.BoardMember{ BoardID: board.ID, UserID: board.CreatedBy, SchemeAdmin: true, SchemeEditor: true, } nbm, err := s.saveMember(db, bm) if err != nil { return nil, nil, err } members = append(members, nbm) } return newBab, members, nil } func (s *SQLStore) createBoardsAndBlocks(db sq.BaseRunner, bab *model.BoardsAndBlocks, userID string) (*model.BoardsAndBlocks, error) { boards := []*model.Board{} blocks := []model.Block{} for _, board := range bab.Boards { newBoard, err := s.insertBoard(db, board, userID) if err != nil { return nil, err } boards = append(boards, newBoard) } for _, block := range bab.Blocks { b := block err := s.insertBlock(db, &b, userID) if err != nil { return nil, err } blocks = append(blocks, block) } newBab := &model.BoardsAndBlocks{ Boards: boards, Blocks: blocks, } return newBab, nil } func (s *SQLStore) patchBoardsAndBlocks(db sq.BaseRunner, pbab *model.PatchBoardsAndBlocks, userID string) (*model.BoardsAndBlocks, error) { bab := &model.BoardsAndBlocks{} for i, boardID := range pbab.BoardIDs { board, err := s.patchBoard(db, boardID, pbab.BoardPatches[i], userID) if err != nil { return nil, err } bab.Boards = append(bab.Boards, board) } for i, blockID := range pbab.BlockIDs { if err := s.patchBlock(db, blockID, pbab.BlockPatches[i], userID); err != nil { return nil, err } block, err := s.getBlock(db, blockID) if err != nil { return nil, err } bab.Blocks = append(bab.Blocks, *block) } return bab, nil } // deleteBoardsAndBlocks deletes all the boards and blocks entities of // the DeleteBoardsAndBlocks struct, making sure that all the blocks // belong to the boards in the struct. func (s *SQLStore) deleteBoardsAndBlocks(db sq.BaseRunner, dbab *model.DeleteBoardsAndBlocks, userID string) error { boardIDMap := map[string]bool{} for _, boardID := range dbab.Boards { if err := s.deleteBoard(db, boardID, userID); err != nil { return err } boardIDMap[boardID] = true } for _, blockID := range dbab.Blocks { block, err := s.getBlock(db, blockID) if err != nil { return err } if block == nil { return sql.ErrNoRows } if _, ok := boardIDMap[block.BoardID]; !ok { return BlockDoesntBelongToBoardsErr{blockID} } if err := s.deleteBlock(db, blockID, userID); err != nil { return err } } return nil } func (s *SQLStore) duplicateBoard(db sq.BaseRunner, boardID string, userID string, toTeam string, asTemplate bool) (*model.BoardsAndBlocks, []*model.BoardMember, error) { bab := &model.BoardsAndBlocks{ Boards: []*model.Board{}, Blocks: []model.Block{}, } board, err := s.getBoard(db, boardID) if err != nil { return nil, nil, err } // todo: server localization if asTemplate == board.IsTemplate { // board -> board or template -> template board.Title += " copy" } else if asTemplate { // template from board board.Title = "New board template" } // make new board private board.Type = "P" board.IsTemplate = asTemplate board.CreatedBy = userID if toTeam != "" { board.TeamID = toTeam } bab.Boards = []*model.Board{board} blocks, err := s.getBlocksWithBoardID(db, boardID) if err != nil { return nil, nil, err } newBlocks := []model.Block{} for _, b := range blocks { if b.Type != model.TypeComment { newBlocks = append(newBlocks, b) } } bab.Blocks = newBlocks bab, err = model.GenerateBoardsAndBlocksIDs(bab, nil) if err != nil { return nil, nil, err } return s.createBoardsAndBlocksWithAdmin(db, bab, userID) }