Added server changes to support private templates
This commit is contained in:
parent
22a92068b5
commit
d1b7e601c5
11 changed files with 130 additions and 17 deletions
|
@ -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/search", a.sessionRequired(a.handleSearchBoards)).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/{boardID}", a.attachSession(a.handleGetBoard, false)).Methods("GET")
|
||||
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)
|
||||
|
||||
// retrieve boards list
|
||||
boards, err := a.app.GetTemplateBoards(teamID)
|
||||
boards, err := a.app.GetTemplateBoards(teamID, userID)
|
||||
if err != nil {
|
||||
a.errorResponse(w, r.URL.Path, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
|
@ -2208,6 +2209,62 @@ func (a *API) handleGetTemplates(w http.ResponseWriter, r *http.Request) {
|
|||
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
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (a *App) GetTemplateBoards(teamID string) ([]*model.Board, error) {
|
||||
return a.store.GetTemplateBoards(teamID)
|
||||
func (a *App) GetTemplateBoards(teamID, userID string) ([]*model.Board, error) {
|
||||
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) {
|
||||
|
|
|
@ -46,7 +46,7 @@ func (a *App) PrepareOnboardingTour(userID string, teamID string) (string, strin
|
|||
}
|
||||
|
||||
func (a *App) getOnboardingBoardID() (string, error) {
|
||||
boards, err := a.store.GetTemplateBoards(globalTeamID)
|
||||
boards, err := a.store.GetDefaultTemplates()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ func (a *App) InitTemplates() error {
|
|||
|
||||
// initializeTemplates imports default templates if the boards table is empty.
|
||||
func (a *App) initializeTemplates() error {
|
||||
boards, err := a.store.GetTemplateBoards(globalTeamID)
|
||||
boards, err := a.store.GetDefaultTemplates()
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (m *MockStore) GetMemberForBoard(arg0, arg1 string) (*model.BoardMember, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -821,18 +836,18 @@ func (mr *MockStoreMockRecorder) GetTeamsForUser(arg0 interface{}) *gomock.Call
|
|||
}
|
||||
|
||||
// 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()
|
||||
ret := m.ctrl.Call(m, "GetTemplateBoards", arg0)
|
||||
ret := m.ctrl.Call(m, "GetTemplateBoards", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*model.Board)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// 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()
|
||||
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.
|
||||
|
|
|
@ -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
|
||||
FROM {{.prefix}}boards AS B
|
||||
INNER JOIN ChannelMembers as CM ON CM.ChannelId=B.channel_id
|
||||
WHERE NOT B.is_template
|
||||
);
|
||||
{{else}}
|
||||
{{- /* if we're in personal server or desktop, create memberships for everyone */ -}}
|
||||
INSERT INTO {{.prefix}}board_members
|
||||
SELECT B.id, U.id, '', B.created_by=U.id, TRUE, FALSE, FALSE
|
||||
FROM {{.prefix}}boards AS B, {{.prefix}}users AS U
|
||||
WHERE NOT B.is_template;
|
||||
{{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) {
|
||||
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) {
|
||||
return s.getTemplateBoards(s.db, teamID)
|
||||
func (s *SQLStore) GetTemplateBoards(teamID string, userID string) ([]*model.Board, error) {
|
||||
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 .
|
||||
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).
|
||||
Select(boardFields("")...).
|
||||
From(s.tablePrefix + "boards").
|
||||
Where(sq.Eq{"coalesce(team_id, '0')": teamID}).
|
||||
Where(sq.Eq{"team_id": "0"}).
|
||||
Where(sq.Eq{"is_template": true})
|
||||
|
||||
rows, err := query.Query()
|
||||
|
@ -71,3 +71,27 @@ func (s *SQLStore) getTemplateBoards(db sq.BaseRunner, teamID string) ([]*model.
|
|||
|
||||
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)
|
||||
GetNextNotificationHint(remove bool) (*model.NotificationHint, error)
|
||||
|
||||
GetDefaultTemplates() ([]*model.Board, error)
|
||||
RemoveDefaultTemplates(boards []*model.Board) error
|
||||
GetTemplateBoards(teamID string) ([]*model.Board, error)
|
||||
GetTemplateBoards(teamID, userID string) ([]*model.Board, error)
|
||||
|
||||
DBType() string
|
||||
|
||||
|
|
|
@ -596,6 +596,15 @@ class OctoClient {
|
|||
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
|
||||
// ToDo: .
|
||||
// - goal? make the interface show boards & blocks for boards
|
||||
|
|
|
@ -13,7 +13,7 @@ import {RootState} from './index'
|
|||
export const fetchGlobalTemplates = createAsyncThunk(
|
||||
'globalTemplates/fetch',
|
||||
async () => {
|
||||
const templates = await client.getTeamTemplates('0')
|
||||
const templates = await client.getDefaultTemplates()
|
||||
return templates.sort((a, b) => a.title.localeCompare(b.title))
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue