mirror of
https://github.com/mattermost/focalboard.git
synced 2024-12-03 08:45:40 +02:00
Added server changes to support private templates
This commit is contained in:
parent
22a92068b5
commit
d1b7e601c5
@ -76,6 +76,7 @@ func (a *API) RegisterRoutes(r *mux.Router) {
|
|||||||
apiv1.HandleFunc("/teams/{teamID}/boards", a.sessionRequired(a.handleGetBoards)).Methods("GET")
|
apiv1.HandleFunc("/teams/{teamID}/boards", a.sessionRequired(a.handleGetBoards)).Methods("GET")
|
||||||
apiv1.HandleFunc("/teams/{teamID}/boards/search", a.sessionRequired(a.handleSearchBoards)).Methods("GET")
|
apiv1.HandleFunc("/teams/{teamID}/boards/search", a.sessionRequired(a.handleSearchBoards)).Methods("GET")
|
||||||
apiv1.HandleFunc("/teams/{teamID}/templates", a.sessionRequired(a.handleGetTemplates)).Methods("GET")
|
apiv1.HandleFunc("/teams/{teamID}/templates", a.sessionRequired(a.handleGetTemplates)).Methods("GET")
|
||||||
|
apiv1.HandleFunc("/templates", a.sessionRequired(a.handleGetDefaultTemplates)).Methods("GET")
|
||||||
apiv1.HandleFunc("/boards", a.sessionRequired(a.handleCreateBoard)).Methods("POST")
|
apiv1.HandleFunc("/boards", a.sessionRequired(a.handleCreateBoard)).Methods("POST")
|
||||||
apiv1.HandleFunc("/boards/{boardID}", a.attachSession(a.handleGetBoard, false)).Methods("GET")
|
apiv1.HandleFunc("/boards/{boardID}", a.attachSession(a.handleGetBoard, false)).Methods("GET")
|
||||||
apiv1.HandleFunc("/boards/{boardID}", a.sessionRequired(a.handlePatchBoard)).Methods("PATCH")
|
apiv1.HandleFunc("/boards/{boardID}", a.sessionRequired(a.handlePatchBoard)).Methods("PATCH")
|
||||||
@ -2184,7 +2185,7 @@ func (a *API) handleGetTemplates(w http.ResponseWriter, r *http.Request) {
|
|||||||
auditRec.AddMeta("teamID", teamID)
|
auditRec.AddMeta("teamID", teamID)
|
||||||
|
|
||||||
// retrieve boards list
|
// retrieve boards list
|
||||||
boards, err := a.app.GetTemplateBoards(teamID)
|
boards, err := a.app.GetTemplateBoards(teamID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.errorResponse(w, r.URL.Path, http.StatusInternalServerError, "", err)
|
a.errorResponse(w, r.URL.Path, http.StatusInternalServerError, "", err)
|
||||||
return
|
return
|
||||||
@ -2208,6 +2209,62 @@ func (a *API) handleGetTemplates(w http.ResponseWriter, r *http.Request) {
|
|||||||
auditRec.Success()
|
auditRec.Success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) handleGetDefaultTemplates(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// swagger:operation GET /api/v1/templates getDefaultTemplates
|
||||||
|
//
|
||||||
|
// Returns default templates
|
||||||
|
//
|
||||||
|
// ---
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: teamID
|
||||||
|
// in: path
|
||||||
|
// description: Team ID
|
||||||
|
// required: true
|
||||||
|
// type: string
|
||||||
|
// security:
|
||||||
|
// - BearerAuth: []
|
||||||
|
// responses:
|
||||||
|
// '200':
|
||||||
|
// description: success
|
||||||
|
// schema:
|
||||||
|
// type: array
|
||||||
|
// items:
|
||||||
|
// items:
|
||||||
|
// "$ref": "#/definitions/Board"
|
||||||
|
// default:
|
||||||
|
// description: internal error
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/ErrorResponse"
|
||||||
|
|
||||||
|
auditRec := a.makeAuditRecord(r, "getDefaultTemplates", audit.Fail)
|
||||||
|
defer a.audit.LogRecord(audit.LevelRead, auditRec)
|
||||||
|
|
||||||
|
// retrieve boards list
|
||||||
|
boards, err := a.app.GetDefaultTemplates()
|
||||||
|
if err != nil {
|
||||||
|
a.errorResponse(w, r.URL.Path, http.StatusInternalServerError, "", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
a.logger.Debug("GetDefaultTemplates",
|
||||||
|
mlog.Int("boardsCount", len(boards)),
|
||||||
|
)
|
||||||
|
|
||||||
|
data, err := json.Marshal(boards)
|
||||||
|
if err != nil {
|
||||||
|
a.errorResponse(w, r.URL.Path, http.StatusInternalServerError, "", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// response
|
||||||
|
jsonBytesResponse(w, http.StatusOK, data)
|
||||||
|
|
||||||
|
auditRec.AddMeta("templatesCount", len(boards))
|
||||||
|
auditRec.Success()
|
||||||
|
}
|
||||||
|
|
||||||
// subscriptions
|
// subscriptions
|
||||||
|
|
||||||
func (a *API) handleCreateSubscription(w http.ResponseWriter, r *http.Request) {
|
func (a *API) handleCreateSubscription(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -49,8 +49,12 @@ func (a *App) GetBoardsForUserAndTeam(userID, teamID string) ([]*model.Board, er
|
|||||||
return a.store.GetBoardsForUserAndTeam(userID, teamID)
|
return a.store.GetBoardsForUserAndTeam(userID, teamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetTemplateBoards(teamID string) ([]*model.Board, error) {
|
func (a *App) GetTemplateBoards(teamID, userID string) ([]*model.Board, error) {
|
||||||
return a.store.GetTemplateBoards(teamID)
|
return a.store.GetTemplateBoards(teamID, userID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) GetDefaultTemplates() ([]*model.Board, error) {
|
||||||
|
return a.store.GetDefaultTemplates()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) CreateBoard(board *model.Board, userID string, addMember bool) (*model.Board, error) {
|
func (a *App) CreateBoard(board *model.Board, userID string, addMember bool) (*model.Board, error) {
|
||||||
|
@ -46,7 +46,7 @@ func (a *App) PrepareOnboardingTour(userID string, teamID string) (string, strin
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) getOnboardingBoardID() (string, error) {
|
func (a *App) getOnboardingBoardID() (string, error) {
|
||||||
boards, err := a.store.GetTemplateBoards(globalTeamID)
|
boards, err := a.store.GetDefaultTemplates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ func (a *App) InitTemplates() error {
|
|||||||
|
|
||||||
// initializeTemplates imports default templates if the boards table is empty.
|
// initializeTemplates imports default templates if the boards table is empty.
|
||||||
func (a *App) initializeTemplates() error {
|
func (a *App) initializeTemplates() error {
|
||||||
boards, err := a.store.GetTemplateBoards(globalTeamID)
|
boards, err := a.store.GetDefaultTemplates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot initialize templates: %w", err)
|
return fmt.Errorf("cannot initialize templates: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -535,6 +535,21 @@ func (mr *MockStoreMockRecorder) GetCategory(arg0 interface{}) *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCategory", reflect.TypeOf((*MockStore)(nil).GetCategory), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCategory", reflect.TypeOf((*MockStore)(nil).GetCategory), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetDefaultTemplates mocks base method.
|
||||||
|
func (m *MockStore) GetDefaultTemplates() ([]*model.Board, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "GetDefaultTemplates")
|
||||||
|
ret0, _ := ret[0].([]*model.Board)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDefaultTemplates indicates an expected call of GetDefaultTemplates.
|
||||||
|
func (mr *MockStoreMockRecorder) GetDefaultTemplates() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDefaultTemplates", reflect.TypeOf((*MockStore)(nil).GetDefaultTemplates))
|
||||||
|
}
|
||||||
|
|
||||||
// GetMemberForBoard mocks base method.
|
// GetMemberForBoard mocks base method.
|
||||||
func (m *MockStore) GetMemberForBoard(arg0, arg1 string) (*model.BoardMember, error) {
|
func (m *MockStore) GetMemberForBoard(arg0, arg1 string) (*model.BoardMember, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
@ -821,18 +836,18 @@ func (mr *MockStoreMockRecorder) GetTeamsForUser(arg0 interface{}) *gomock.Call
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTemplateBoards mocks base method.
|
// GetTemplateBoards mocks base method.
|
||||||
func (m *MockStore) GetTemplateBoards(arg0 string) ([]*model.Board, error) {
|
func (m *MockStore) GetTemplateBoards(arg0, arg1 string) ([]*model.Board, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetTemplateBoards", arg0)
|
ret := m.ctrl.Call(m, "GetTemplateBoards", arg0, arg1)
|
||||||
ret0, _ := ret[0].([]*model.Board)
|
ret0, _ := ret[0].([]*model.Board)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTemplateBoards indicates an expected call of GetTemplateBoards.
|
// GetTemplateBoards indicates an expected call of GetTemplateBoards.
|
||||||
func (mr *MockStoreMockRecorder) GetTemplateBoards(arg0 interface{}) *gomock.Call {
|
func (mr *MockStoreMockRecorder) GetTemplateBoards(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTemplateBoards", reflect.TypeOf((*MockStore)(nil).GetTemplateBoards), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTemplateBoards", reflect.TypeOf((*MockStore)(nil).GetTemplateBoards), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserByEmail mocks base method.
|
// GetUserByEmail mocks base method.
|
||||||
|
@ -367,12 +367,10 @@ INSERT INTO {{.prefix}}board_members (
|
|||||||
SELECT B.Id, CM.UserId, CM.Roles, (CM.UserId=B.created_by) OR CM.SchemeAdmin, CM.SchemeUser, FALSE, CM.SchemeGuest
|
SELECT B.Id, CM.UserId, CM.Roles, (CM.UserId=B.created_by) OR CM.SchemeAdmin, CM.SchemeUser, FALSE, CM.SchemeGuest
|
||||||
FROM {{.prefix}}boards AS B
|
FROM {{.prefix}}boards AS B
|
||||||
INNER JOIN ChannelMembers as CM ON CM.ChannelId=B.channel_id
|
INNER JOIN ChannelMembers as CM ON CM.ChannelId=B.channel_id
|
||||||
WHERE NOT B.is_template
|
|
||||||
);
|
);
|
||||||
{{else}}
|
{{else}}
|
||||||
{{- /* if we're in personal server or desktop, create memberships for everyone */ -}}
|
{{- /* if we're in personal server or desktop, create memberships for everyone */ -}}
|
||||||
INSERT INTO {{.prefix}}board_members
|
INSERT INTO {{.prefix}}board_members
|
||||||
SELECT B.id, U.id, '', B.created_by=U.id, TRUE, FALSE, FALSE
|
SELECT B.id, U.id, '', B.created_by=U.id, TRUE, FALSE, FALSE
|
||||||
FROM {{.prefix}}boards AS B, {{.prefix}}users AS U
|
FROM {{.prefix}}boards AS B, {{.prefix}}users AS U
|
||||||
WHERE NOT B.is_template;
|
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -319,6 +319,11 @@ func (s *SQLStore) GetCategory(id string) (*model.Category, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *SQLStore) GetDefaultTemplates() ([]*model.Board, error) {
|
||||||
|
return s.getDefaultTemplates(s.db)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (s *SQLStore) GetMemberForBoard(boardID string, userID string) (*model.BoardMember, error) {
|
func (s *SQLStore) GetMemberForBoard(boardID string, userID string) (*model.BoardMember, error) {
|
||||||
return s.getMemberForBoard(s.db, boardID, userID)
|
return s.getMemberForBoard(s.db, boardID, userID)
|
||||||
|
|
||||||
@ -414,8 +419,8 @@ func (s *SQLStore) GetTeamsForUser(userID string) ([]*model.Team, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SQLStore) GetTemplateBoards(teamID string) ([]*model.Board, error) {
|
func (s *SQLStore) GetTemplateBoards(teamID string, userID string) ([]*model.Board, error) {
|
||||||
return s.getTemplateBoards(s.db, teamID)
|
return s.getTemplateBoards(s.db, teamID, userID)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,11 +55,11 @@ func (s *SQLStore) removeDefaultTemplates(db sq.BaseRunner, boards []*model.Boar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getDefaultTemplateBoards fetches all template blocks .
|
// getDefaultTemplateBoards fetches all template blocks .
|
||||||
func (s *SQLStore) getTemplateBoards(db sq.BaseRunner, teamID string) ([]*model.Board, error) {
|
func (s *SQLStore) getDefaultTemplates(db sq.BaseRunner) ([]*model.Board, error) {
|
||||||
query := s.getQueryBuilder(db).
|
query := s.getQueryBuilder(db).
|
||||||
Select(boardFields("")...).
|
Select(boardFields("")...).
|
||||||
From(s.tablePrefix + "boards").
|
From(s.tablePrefix + "boards").
|
||||||
Where(sq.Eq{"coalesce(team_id, '0')": teamID}).
|
Where(sq.Eq{"team_id": "0"}).
|
||||||
Where(sq.Eq{"is_template": true})
|
Where(sq.Eq{"is_template": true})
|
||||||
|
|
||||||
rows, err := query.Query()
|
rows, err := query.Query()
|
||||||
@ -71,3 +71,27 @@ func (s *SQLStore) getTemplateBoards(db sq.BaseRunner, teamID string) ([]*model.
|
|||||||
|
|
||||||
return s.boardsFromRows(rows)
|
return s.boardsFromRows(rows)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDefaultTemplateBoards fetches all template blocks .
|
||||||
|
func (s *SQLStore) getTemplateBoards(db sq.BaseRunner, teamID, userID string) ([]*model.Board, error) {
|
||||||
|
query := s.getQueryBuilder(db).
|
||||||
|
Select(boardFields("")...).
|
||||||
|
From(s.tablePrefix+"boards as b").
|
||||||
|
Join(s.tablePrefix+"board_members as bm on b.id = bm.board_id and b.team_id = ? and bm.user_id = ?", teamID, userID).
|
||||||
|
Where(sq.Eq{"is_template": true})
|
||||||
|
|
||||||
|
rows, err := query.Query()
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Error(`getTemplateBoards ERROR`, mlog.Err(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.CloseRows(rows)
|
||||||
|
|
||||||
|
userTemplates, err := s.boardsFromRows(rows)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return userTemplates, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -124,8 +124,9 @@ type Store interface {
|
|||||||
GetNotificationHint(blockID string) (*model.NotificationHint, error)
|
GetNotificationHint(blockID string) (*model.NotificationHint, error)
|
||||||
GetNextNotificationHint(remove bool) (*model.NotificationHint, error)
|
GetNextNotificationHint(remove bool) (*model.NotificationHint, error)
|
||||||
|
|
||||||
|
GetDefaultTemplates() ([]*model.Board, error)
|
||||||
RemoveDefaultTemplates(boards []*model.Board) error
|
RemoveDefaultTemplates(boards []*model.Board) error
|
||||||
GetTemplateBoards(teamID string) ([]*model.Board, error)
|
GetTemplateBoards(teamID, userID string) ([]*model.Board, error)
|
||||||
|
|
||||||
DBType() string
|
DBType() string
|
||||||
|
|
||||||
|
@ -596,6 +596,15 @@ class OctoClient {
|
|||||||
return this.getBoardsWithPath(path)
|
return this.getBoardsWithPath(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getDefaultTemplates(): Promise<Board[]> {
|
||||||
|
const path = '/api/v1/templates'
|
||||||
|
const response = await fetch(this.getBaseURL() + path, {headers: this.headers()})
|
||||||
|
if (response.status !== 200) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return (await this.getJson(response, [])) as Board[]
|
||||||
|
}
|
||||||
|
|
||||||
// Boards
|
// Boards
|
||||||
// ToDo: .
|
// ToDo: .
|
||||||
// - goal? make the interface show boards & blocks for boards
|
// - goal? make the interface show boards & blocks for boards
|
||||||
|
@ -13,7 +13,7 @@ import {RootState} from './index'
|
|||||||
export const fetchGlobalTemplates = createAsyncThunk(
|
export const fetchGlobalTemplates = createAsyncThunk(
|
||||||
'globalTemplates/fetch',
|
'globalTemplates/fetch',
|
||||||
async () => {
|
async () => {
|
||||||
const templates = await client.getTeamTemplates('0')
|
const templates = await client.getDefaultTemplates()
|
||||||
return templates.sort((a, b) => a.title.localeCompare(b.title))
|
return templates.sort((a, b) => a.title.localeCompare(b.title))
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user