mirror of
https://github.com/mattermost/focalboard.git
synced 2025-02-10 19:41:29 +02:00
Workspace backend support
This commit is contained in:
parent
65be22fa15
commit
725971784b
@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@ -15,6 +16,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/mattermost/focalboard/server/app"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/utils"
|
||||
)
|
||||
|
||||
@ -23,18 +25,30 @@ const (
|
||||
HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
|
||||
)
|
||||
|
||||
const (
|
||||
ERROR_NO_WORKSPACE_CODE = 1000
|
||||
ERROR_NO_WORKSPACE_MESSAGE = "No workspace"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
// REST APIs
|
||||
|
||||
type API struct {
|
||||
appBuilder func() *app.App
|
||||
singleUserToken string
|
||||
type WorkspaceAuthenticator interface {
|
||||
DoesUserHaveWorkspaceAccess(session *model.Session, workspaceID string) bool
|
||||
}
|
||||
|
||||
func NewAPI(appBuilder func() *app.App, singleUserToken string) *API {
|
||||
type API struct {
|
||||
appBuilder func() *app.App
|
||||
authService string
|
||||
singleUserToken string
|
||||
WorkspaceAuthenticator WorkspaceAuthenticator
|
||||
}
|
||||
|
||||
func NewAPI(appBuilder func() *app.App, singleUserToken string, authService string) *API {
|
||||
return &API{
|
||||
appBuilder: appBuilder,
|
||||
singleUserToken: singleUserToken,
|
||||
authService: authService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,11 +60,21 @@ func (a *API) RegisterRoutes(r *mux.Router) {
|
||||
apiv1 := r.PathPrefix("/api/v1").Subrouter()
|
||||
apiv1.Use(a.requireCSRFToken)
|
||||
|
||||
apiv1.HandleFunc("/blocks", a.sessionRequired(a.handleGetBlocks)).Methods("GET")
|
||||
apiv1.HandleFunc("/blocks", a.sessionRequired(a.handlePostBlocks)).Methods("POST")
|
||||
apiv1.HandleFunc("/blocks/{blockID}", a.sessionRequired(a.handleDeleteBlock)).Methods("DELETE")
|
||||
apiv1.HandleFunc("/blocks/{blockID}/subtree", a.attachSession(a.handleGetSubTree, false)).Methods("GET")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks", a.sessionRequired(a.handleGetBlocks)).Methods("GET")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks", a.sessionRequired(a.handlePostBlocks)).Methods("POST")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks/{blockID}", a.sessionRequired(a.handleDeleteBlock)).Methods("DELETE")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks/{blockID}/subtree", a.attachSession(a.handleGetSubTree, false)).Methods("GET")
|
||||
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks/export", a.sessionRequired(a.handleExport)).Methods("GET")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/blocks/import", a.sessionRequired(a.handleImport)).Methods("POST")
|
||||
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/sharing/{rootID}", a.sessionRequired(a.handlePostSharing)).Methods("POST")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/sharing/{rootID}", a.sessionRequired(a.handleGetSharing)).Methods("GET")
|
||||
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}", a.sessionRequired(a.handleGetWorkspace)).Methods("GET")
|
||||
apiv1.HandleFunc("/workspaces/{workspaceID}/regenerate_signup_token", a.sessionRequired(a.handlePostWorkspaceRegenerateSignupToken)).Methods("POST")
|
||||
|
||||
// User APIs
|
||||
apiv1.HandleFunc("/users/me", a.sessionRequired(a.handleGetMe)).Methods("GET")
|
||||
apiv1.HandleFunc("/users/{userID}", a.sessionRequired(a.handleGetUser)).Methods("GET")
|
||||
apiv1.HandleFunc("/users/{userID}/changepassword", a.sessionRequired(a.handleChangePassword)).Methods("POST")
|
||||
@ -60,15 +84,6 @@ func (a *API) RegisterRoutes(r *mux.Router) {
|
||||
|
||||
apiv1.HandleFunc("/files", a.sessionRequired(a.handleUploadFile)).Methods("POST")
|
||||
|
||||
apiv1.HandleFunc("/blocks/export", a.sessionRequired(a.handleExport)).Methods("GET")
|
||||
apiv1.HandleFunc("/blocks/import", a.sessionRequired(a.handleImport)).Methods("POST")
|
||||
|
||||
apiv1.HandleFunc("/sharing/{rootID}", a.sessionRequired(a.handlePostSharing)).Methods("POST")
|
||||
apiv1.HandleFunc("/sharing/{rootID}", a.sessionRequired(a.handleGetSharing)).Methods("GET")
|
||||
|
||||
apiv1.HandleFunc("/workspace", a.sessionRequired(a.handleGetWorkspace)).Methods("GET")
|
||||
apiv1.HandleFunc("/workspace/regenerate_signup_token", a.sessionRequired(a.handlePostWorkspaceRegenerateSignupToken)).Methods("POST")
|
||||
|
||||
// Get Files API
|
||||
|
||||
files := r.PathPrefix("/files").Subrouter()
|
||||
@ -101,8 +116,38 @@ func (a *API) checkCSRFToken(r *http.Request) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *API) getContainer(r *http.Request) (*store.Container, error) {
|
||||
if a.WorkspaceAuthenticator == nil {
|
||||
// Native auth: always use root workspace
|
||||
container := store.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
return &container, nil
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
workspaceID := vars["workspaceID"]
|
||||
|
||||
if workspaceID == "" || workspaceID == "0" {
|
||||
// When authenticating, a workspace is required
|
||||
return nil, errors.New("No workspace specified")
|
||||
}
|
||||
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
if !a.WorkspaceAuthenticator.DoesUserHaveWorkspaceAccess(session, workspaceID) {
|
||||
return nil, errors.New("Access denied to workspace")
|
||||
}
|
||||
|
||||
container := store.Container{
|
||||
WorkspaceID: workspaceID,
|
||||
}
|
||||
|
||||
return &container, nil
|
||||
}
|
||||
|
||||
func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks getBlocks
|
||||
// swagger:operation GET /api/v1/workspaces/{workspaceID}/blocks getBlocks
|
||||
//
|
||||
// Returns blocks
|
||||
//
|
||||
@ -110,6 +155,11 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: parent_id
|
||||
// in: query
|
||||
// description: ID of parent block, omit to specify all blocks
|
||||
@ -137,8 +187,13 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
parentID := query.Get("parent_id")
|
||||
blockType := query.Get("type")
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
blocks, err := a.app().GetBlocks(parentID, blockType)
|
||||
blocks, err := a.app().GetBlocks(*container, parentID, blockType)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -169,7 +224,7 @@ func stampModifiedByUser(r *http.Request, blocks []model.Block) {
|
||||
}
|
||||
|
||||
func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/blocks updateBlocks
|
||||
// swagger:operation POST /api/v1/workspaces/{workspaceID}/blocks updateBlocks
|
||||
//
|
||||
// Insert or update blocks
|
||||
//
|
||||
@ -177,6 +232,11 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: Body
|
||||
// in: body
|
||||
// description: array of blocks to insert or update
|
||||
@ -195,6 +255,12 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
@ -232,7 +298,7 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
stampModifiedByUser(r, blocks)
|
||||
|
||||
err = a.app().InsertBlocks(blocks)
|
||||
err = a.app().InsertBlocks(*container, blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -338,7 +404,7 @@ func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation DELETE /api/v1/blocks/{blockID} deleteBlock
|
||||
// swagger:operation DELETE /api/v1/workspaces/{workspaceID}/blocks/{blockID} deleteBlock
|
||||
//
|
||||
// Deletes a block
|
||||
//
|
||||
@ -346,6 +412,11 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: blockID
|
||||
// in: path
|
||||
// description: ID of block to delete
|
||||
@ -368,7 +439,13 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
blockID := vars["blockID"]
|
||||
|
||||
err := a.app().DeleteBlock(blockID, userID)
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.app().DeleteBlock(*container, blockID, userID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
|
||||
@ -380,7 +457,7 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks/{blockID}/subtree getSubTree
|
||||
// swagger:operation GET /api/v1/workspaces/{workspaceID}/blocks/{blockID}/subtree getSubTree
|
||||
//
|
||||
// Returns the blocks of a subtree
|
||||
//
|
||||
@ -388,6 +465,11 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: blockID
|
||||
// in: path
|
||||
// description: The ID of the root block of the subtree
|
||||
@ -417,6 +499,12 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
blockID := vars["blockID"]
|
||||
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// If not authenticated (no session), check that block is publicly shared
|
||||
ctx := r.Context()
|
||||
session, _ := ctx.Value("session").(*model.Session)
|
||||
@ -430,7 +518,7 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
isValid, err := a.app().IsValidReadToken(blockID, readToken)
|
||||
isValid, err := a.app().IsValidReadToken(*container, blockID, readToken)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -454,7 +542,7 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
blocks, err := a.app().GetSubTree(blockID, int(levels))
|
||||
blocks, err := a.app().GetSubTree(*container, blockID, int(levels))
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -471,13 +559,19 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/blocks/export exportBlocks
|
||||
// swagger:operation GET /api/v1/workspaces/{workspaceID}/blocks/export exportBlocks
|
||||
//
|
||||
// Returns all blocks
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
@ -492,7 +586,13 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
blocks, err := a.app().GetAllBlocks()
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
blocks, err := a.app().GetAllBlocks(*container)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -556,7 +656,7 @@ func arrayContainsBlockWithID(array []model.Block, blockID string) bool {
|
||||
}
|
||||
|
||||
func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/blocks/import importBlocks
|
||||
// swagger:operation POST /api/v1/workspaces/{workspaceID}/blocks/import importBlocks
|
||||
//
|
||||
// Import blocks
|
||||
//
|
||||
@ -564,6 +664,11 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: Body
|
||||
// in: body
|
||||
// description: array of blocks to import
|
||||
@ -582,6 +687,12 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
@ -598,7 +709,7 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
stampModifiedByUser(r, blocks)
|
||||
|
||||
err = a.app().InsertBlocks(blocks)
|
||||
err = a.app().InsertBlocks(*container, blocks)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -611,7 +722,7 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// Sharing
|
||||
|
||||
func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/sharing/{rootID} getSharing
|
||||
// swagger:operation GET /api/v1/workspaces/{workspaceID}/sharing/{rootID} getSharing
|
||||
//
|
||||
// Returns sharing information for a root block
|
||||
//
|
||||
@ -619,6 +730,11 @@ func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: rootID
|
||||
// in: path
|
||||
// description: ID of the root block
|
||||
@ -639,7 +755,13 @@ func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
rootID := vars["rootID"]
|
||||
|
||||
sharing, err := a.app().GetSharing(rootID)
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
sharing, err := a.app().GetSharing(*container, rootID)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -656,7 +778,7 @@ func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/sharing/{rootID} postSharing
|
||||
// swagger:operation POST /api/v1/workspaces/{workspaceID}/sharing/{rootID} postSharing
|
||||
//
|
||||
// Sets sharing information for a root block
|
||||
//
|
||||
@ -664,6 +786,11 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// - name: rootID
|
||||
// in: path
|
||||
// description: ID of the root block
|
||||
@ -685,6 +812,12 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
container, err := a.getContainer(r)
|
||||
if err != nil {
|
||||
noContainerErrorResponse(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
@ -708,7 +841,7 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
sharing.ModifiedBy = userID
|
||||
|
||||
err = a.app().UpsertSharing(sharing)
|
||||
err = a.app().UpsertSharing(*container, sharing)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -721,13 +854,19 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
// Workspace
|
||||
|
||||
func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation GET /api/v1/workspace getWorkspace
|
||||
// swagger:operation GET /api/v1/workspaces/{workspaceID} getWorkspace
|
||||
//
|
||||
// Returns information of the root workspace
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
@ -740,10 +879,28 @@ func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
|
||||
// schema:
|
||||
// "$ref": "#/definitions/ErrorResponse"
|
||||
|
||||
workspace, err := a.app().GetRootWorkspace()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
var workspace *model.Workspace
|
||||
var err error
|
||||
|
||||
if a.WorkspaceAuthenticator != nil {
|
||||
vars := mux.Vars(r)
|
||||
workspaceID := vars["workspaceID"]
|
||||
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
if !a.WorkspaceAuthenticator.DoesUserHaveWorkspaceAccess(session, workspaceID) {
|
||||
errorResponse(w, http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
workspace = &model.Workspace{
|
||||
ID: workspaceID,
|
||||
}
|
||||
} else {
|
||||
workspace, err = a.app().GetRootWorkspace()
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
workspaceData, err := json.Marshal(workspace)
|
||||
@ -756,13 +913,19 @@ func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/workspace/regenerate_signup_token regenerateSignupToken
|
||||
// swagger:operation POST /api/v1/workspaces/{workspaceID}/regenerate_signup_token regenerateSignupToken
|
||||
//
|
||||
// Regenerates the signup token for the root workspace
|
||||
//
|
||||
// ---
|
||||
// produces:
|
||||
// - application/json
|
||||
// parameters:
|
||||
// - name: workspaceID
|
||||
// in: path
|
||||
// description: Workspace ID
|
||||
// required: true
|
||||
// type: string
|
||||
// security:
|
||||
// - BearerAuth: []
|
||||
// responses:
|
||||
@ -910,7 +1073,7 @@ func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) {
|
||||
func errorResponse(w http.ResponseWriter, code int, message string, sourceError error) {
|
||||
log.Printf("API ERROR %d, err: %v\n", code, sourceError)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
data, err := json.Marshal(model.ErrorResponse{Error: message})
|
||||
data, err := json.Marshal(model.ErrorResponse{Error: message, ErrorCode: code})
|
||||
if err != nil {
|
||||
data = []byte("{}")
|
||||
}
|
||||
@ -918,6 +1081,21 @@ func errorResponse(w http.ResponseWriter, code int, message string, sourceError
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
func errorResponseWithCode(w http.ResponseWriter, statusCode int, errorCode int, message string, sourceError error) {
|
||||
log.Printf("API ERROR status %d, errorCode: %d, err: %v\n", statusCode, errorCode, sourceError)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
data, err := json.Marshal(model.ErrorResponse{Error: message, ErrorCode: errorCode})
|
||||
if err != nil {
|
||||
data = []byte("{}")
|
||||
}
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
func noContainerErrorResponse(w http.ResponseWriter, sourceError error) {
|
||||
errorResponseWithCode(w, http.StatusBadRequest, ERROR_NO_WORKSPACE_CODE, ERROR_NO_WORKSPACE_MESSAGE, sourceError)
|
||||
}
|
||||
|
||||
func addUserID(rw http.ResponseWriter, req *http.Request, next http.Handler) {
|
||||
ctx := context.WithValue(req.Context(), "userid", req.Header.Get("userid"))
|
||||
req = req.WithContext(ctx)
|
||||
|
@ -358,11 +358,13 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
now := time.Now().Unix()
|
||||
session := &model.Session{
|
||||
ID: "single-user",
|
||||
Token: token,
|
||||
UserID: "single-user",
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
ID: "single-user",
|
||||
Token: token,
|
||||
UserID: "single-user",
|
||||
AuthService: a.authService,
|
||||
Props: map[string]interface{}{},
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
}
|
||||
ctx := context.WithValue(r.Context(), "session", session)
|
||||
handler(w, r.WithContext(ctx))
|
||||
@ -379,6 +381,14 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
|
||||
handler(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
authService := session.AuthService
|
||||
if authService != a.authService {
|
||||
log.Printf(`Session '%s' authService mismatch '%s' instead of '%s'`, session.ID, authService, a.authService)
|
||||
errorResponse(w, http.StatusUnauthorized, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.WithValue(r.Context(), "session", session)
|
||||
handler(w, r.WithContext(ctx))
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/auth"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@ -16,8 +17,8 @@ func (a *App) GetSession(token string) (*model.Session, error) {
|
||||
}
|
||||
|
||||
// IsValidReadToken validates the read token for a block
|
||||
func (a *App) IsValidReadToken(blockID, readToken string) (bool, error) {
|
||||
return a.auth.IsValidReadToken(blockID, readToken)
|
||||
func (a *App) IsValidReadToken(c store.Container, blockID string, readToken string) (bool, error) {
|
||||
return a.auth.IsValidReadToken(c, blockID, readToken)
|
||||
}
|
||||
|
||||
// GetRegisteredUserCount returns the number of registered users
|
||||
@ -83,11 +84,17 @@ func (a *App) Login(username, email, password, mfaToken string) (string, error)
|
||||
return "", errors.New("invalid username or password")
|
||||
}
|
||||
|
||||
authService := user.AuthService
|
||||
if authService == "" {
|
||||
authService = "native"
|
||||
}
|
||||
|
||||
session := model.Session{
|
||||
ID: uuid.New().String(),
|
||||
Token: uuid.New().String(),
|
||||
UserID: user.ID,
|
||||
Props: map[string]interface{}{},
|
||||
ID: uuid.New().String(),
|
||||
Token: uuid.New().String(),
|
||||
UserID: user.ID,
|
||||
AuthService: authService,
|
||||
Props: map[string]interface{}{},
|
||||
}
|
||||
err := a.store.CreateSession(&session)
|
||||
if err != nil {
|
||||
@ -133,7 +140,7 @@ func (a *App) RegisterUser(username, email, password string) error {
|
||||
Email: email,
|
||||
Password: auth.HashPassword(password),
|
||||
MfaSecret: "",
|
||||
AuthService: "",
|
||||
AuthService: a.config.AuthMode,
|
||||
AuthData: "",
|
||||
Props: map[string]interface{}{},
|
||||
})
|
||||
|
@ -2,33 +2,34 @@ package app
|
||||
|
||||
import (
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
)
|
||||
|
||||
func (a *App) GetBlocks(parentID, blockType string) ([]model.Block, error) {
|
||||
func (a *App) GetBlocks(c store.Container, parentID string, blockType string) ([]model.Block, error) {
|
||||
if len(blockType) > 0 && len(parentID) > 0 {
|
||||
return a.store.GetBlocksWithParentAndType(parentID, blockType)
|
||||
return a.store.GetBlocksWithParentAndType(c, parentID, blockType)
|
||||
}
|
||||
|
||||
if len(blockType) > 0 {
|
||||
return a.store.GetBlocksWithType(blockType)
|
||||
return a.store.GetBlocksWithType(c, blockType)
|
||||
}
|
||||
|
||||
return a.store.GetBlocksWithParent(parentID)
|
||||
return a.store.GetBlocksWithParent(c, parentID)
|
||||
}
|
||||
|
||||
func (a *App) GetRootID(blockID string) (string, error) {
|
||||
return a.store.GetRootID(blockID)
|
||||
func (a *App) GetRootID(c store.Container, blockID string) (string, error) {
|
||||
return a.store.GetRootID(c, blockID)
|
||||
}
|
||||
|
||||
func (a *App) GetParentID(blockID string) (string, error) {
|
||||
return a.store.GetParentID(blockID)
|
||||
func (a *App) GetParentID(c store.Container, blockID string) (string, error) {
|
||||
return a.store.GetParentID(c, blockID)
|
||||
}
|
||||
|
||||
func (a *App) InsertBlock(block model.Block) error {
|
||||
return a.store.InsertBlock(block)
|
||||
func (a *App) InsertBlock(c store.Container, block model.Block) error {
|
||||
return a.store.InsertBlock(c, block)
|
||||
}
|
||||
|
||||
func (a *App) InsertBlocks(blocks []model.Block) error {
|
||||
func (a *App) InsertBlocks(c store.Container, blocks []model.Block) error {
|
||||
blockIDsToNotify := []string{}
|
||||
|
||||
uniqueBlockIDs := make(map[string]bool)
|
||||
@ -43,7 +44,7 @@ func (a *App) InsertBlocks(blocks []model.Block) error {
|
||||
blockIDsToNotify = append(blockIDsToNotify, block.ParentID)
|
||||
}
|
||||
|
||||
err := a.store.InsertBlock(block)
|
||||
err := a.store.InsertBlock(c, block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -55,21 +56,21 @@ func (a *App) InsertBlocks(blocks []model.Block) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) GetSubTree(blockID string, levels int) ([]model.Block, error) {
|
||||
func (a *App) GetSubTree(c store.Container, blockID string, levels int) ([]model.Block, error) {
|
||||
// Only 2 or 3 levels are supported for now
|
||||
if levels >= 3 {
|
||||
return a.store.GetSubTree3(blockID)
|
||||
return a.store.GetSubTree3(c, blockID)
|
||||
}
|
||||
return a.store.GetSubTree2(blockID)
|
||||
return a.store.GetSubTree2(c, blockID)
|
||||
}
|
||||
|
||||
func (a *App) GetAllBlocks() ([]model.Block, error) {
|
||||
return a.store.GetAllBlocks()
|
||||
func (a *App) GetAllBlocks(c store.Container) ([]model.Block, error) {
|
||||
return a.store.GetAllBlocks(c)
|
||||
}
|
||||
|
||||
func (a *App) DeleteBlock(blockID, modifiedBy string) error {
|
||||
func (a *App) DeleteBlock(c store.Container, blockID string, modifiedBy string) error {
|
||||
blockIDsToNotify := []string{blockID}
|
||||
parentID, err := a.GetParentID(blockID)
|
||||
parentID, err := a.GetParentID(c, blockID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -78,7 +79,7 @@ func (a *App) DeleteBlock(blockID, modifiedBy string) error {
|
||||
blockIDsToNotify = append(blockIDsToNotify, parentID)
|
||||
}
|
||||
|
||||
err = a.store.DeleteBlock(blockID, modifiedBy)
|
||||
err = a.store.DeleteBlock(c, blockID, modifiedBy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/mattermost/focalboard/server/auth"
|
||||
"github.com/mattermost/focalboard/server/services/config"
|
||||
st "github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/services/store/mockstore"
|
||||
"github.com/mattermost/focalboard/server/services/webhook"
|
||||
"github.com/mattermost/focalboard/server/ws"
|
||||
@ -25,16 +26,19 @@ func TestGetParentID(t *testing.T) {
|
||||
webhook := webhook.NewClient(&cfg)
|
||||
app := New(&cfg, store, auth, wsserver, &mocks.FileBackend{}, webhook)
|
||||
|
||||
container := st.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
t.Run("success query", func(t *testing.T) {
|
||||
store.EXPECT().GetParentID(gomock.Eq("test-id")).Return("test-parent-id", nil)
|
||||
result, err := app.GetParentID("test-id")
|
||||
store.EXPECT().GetParentID(gomock.Eq(container), gomock.Eq("test-id")).Return("test-parent-id", nil)
|
||||
result, err := app.GetParentID(container, "test-id")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "test-parent-id", result)
|
||||
})
|
||||
|
||||
t.Run("fail query", func(t *testing.T) {
|
||||
store.EXPECT().GetParentID(gomock.Eq("test-id")).Return("", errors.New("block-not-found"))
|
||||
_, err := app.GetParentID("test-id")
|
||||
store.EXPECT().GetParentID(gomock.Eq(container), gomock.Eq("test-id")).Return("", errors.New("block-not-found"))
|
||||
_, err := app.GetParentID(container, "test-id")
|
||||
require.Error(t, err)
|
||||
require.Equal(t, "block-not-found", err.Error())
|
||||
})
|
||||
|
@ -4,10 +4,11 @@ import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
)
|
||||
|
||||
func (a *App) GetSharing(rootID string) (*model.Sharing, error) {
|
||||
sharing, err := a.store.GetSharing(rootID)
|
||||
func (a *App) GetSharing(c store.Container, rootID string) (*model.Sharing, error) {
|
||||
sharing, err := a.store.GetSharing(c, rootID)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
@ -17,6 +18,6 @@ func (a *App) GetSharing(rootID string) (*model.Sharing, error) {
|
||||
return sharing, nil
|
||||
}
|
||||
|
||||
func (a *App) UpsertSharing(sharing model.Sharing) error {
|
||||
return a.store.UpsertSharing(sharing)
|
||||
func (a *App) UpsertSharing(c store.Container, sharing model.Sharing) error {
|
||||
return a.store.UpsertSharing(c, sharing)
|
||||
}
|
||||
|
@ -38,13 +38,13 @@ func (a *Auth) GetSession(token string) (*model.Session, error) {
|
||||
}
|
||||
|
||||
// IsValidReadToken validates the read token for a block
|
||||
func (a *Auth) IsValidReadToken(blockID, readToken string) (bool, error) {
|
||||
rootID, err := a.store.GetRootID(blockID)
|
||||
func (a *Auth) IsValidReadToken(c store.Container, blockID string, readToken string) (bool, error) {
|
||||
rootID, err := a.store.GetRootID(c, blockID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
sharing, err := a.store.GetSharing(rootID)
|
||||
sharing, err := a.store.GetSharing(c, rootID)
|
||||
if err == sql.ErrNoRows {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ func (c *Client) doApiRequestReader(method, url string, data io.Reader, etag str
|
||||
}
|
||||
|
||||
func (c *Client) GetBlocksRoute() string {
|
||||
return "/blocks"
|
||||
return "/workspaces/0/blocks"
|
||||
}
|
||||
|
||||
func (c *Client) GetBlockRoute(id string) string {
|
||||
@ -192,7 +192,7 @@ func (c *Client) GetSubtree(blockID string) ([]model.Block, *Response) {
|
||||
// Sharing
|
||||
|
||||
func (c *Client) GetSharingRoute(rootID string) string {
|
||||
return fmt.Sprintf("/sharing/%s", rootID)
|
||||
return fmt.Sprintf("/workspaces/0/sharing/%s", rootID)
|
||||
}
|
||||
|
||||
func (c *Client) GetSharing(rootID string) (*model.Sharing, *Response) {
|
||||
|
@ -17,6 +17,7 @@ cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZ
|
||||
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||
cloud.google.com/go v0.63.0/go.mod h1:GmezbQc7T2snqkEXWfZ0sy0VfkB/ivI2DdtJL2DEmlg=
|
||||
cloud.google.com/go v0.64.0/go.mod h1:xfORb36jGvE+6EexW71nMEtL025s3x6xvuYUKM4JLv4=
|
||||
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
@ -1171,7 +1172,10 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84 h1:duBc5zuJsmJXYOVVE/6PxejI+N3AaCqKjtsoLn1Je5Q=
|
||||
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -1364,6 +1368,7 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
|
@ -3,6 +3,6 @@ module github.com/mattermost/focalboard/server
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/golang/mock v1.5.0
|
||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible // indirect
|
||||
)
|
||||
|
@ -1,11 +1,24 @@
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible h1:91Uy4d9SYVr1kyTJ15wJsog+esAZZl7JmEfTkwmhJts=
|
||||
github.com/jteeuwen/go-bindata v3.0.7+incompatible/go.mod h1:JVvhzYOiGBnFSYRyV00iY8q7/0PThjIYav1p9h5dmKs=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262 h1:qsl9y/CJx34tuA7QCPNp86JNJe4spst6Ff8MjvPUdPg=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -6,4 +6,8 @@ type ErrorResponse struct {
|
||||
// The error message
|
||||
// required: false
|
||||
Error string `json:"error"`
|
||||
|
||||
// The error code
|
||||
// required: false
|
||||
ErrorCode int `json:"errorCode"`
|
||||
}
|
||||
|
@ -45,10 +45,11 @@ type User struct {
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
ID string `json:"id"`
|
||||
Token string `json:"token"`
|
||||
UserID string `json:"user_id"`
|
||||
Props map[string]interface{} `json:"props"`
|
||||
CreateAt int64 `json:"create_at,omitempty"`
|
||||
UpdateAt int64 `json:"update_at,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Token string `json:"token"`
|
||||
UserID string `json:"user_id"`
|
||||
AuthService string `json:"authService"`
|
||||
Props map[string]interface{} `json:"props"`
|
||||
CreateAt int64 `json:"create_at,omitempty"`
|
||||
UpdateAt int64 `json:"update_at,omitempty"`
|
||||
}
|
||||
|
5
server/server/initHandlers.go
Normal file
5
server/server/initHandlers.go
Normal file
@ -0,0 +1,5 @@
|
||||
package server
|
||||
|
||||
func (s *Server) initHandlers() {
|
||||
// Additional init handlers go here
|
||||
}
|
@ -43,6 +43,8 @@ type Server struct {
|
||||
|
||||
localRouter *mux.Router
|
||||
localModeServer *http.Server
|
||||
api *api.API
|
||||
appBuilder func() *app.App
|
||||
}
|
||||
|
||||
func New(cfg *config.Configuration, singleUserToken string) (*Server, error) {
|
||||
@ -74,7 +76,7 @@ func New(cfg *config.Configuration, singleUserToken string) (*Server, error) {
|
||||
webhookClient := webhook.NewClient(cfg)
|
||||
|
||||
appBuilder := func() *app.App { return app.New(cfg, store, auth, wsServer, filesBackend, webhookClient) }
|
||||
api := api.NewAPI(appBuilder, singleUserToken)
|
||||
api := api.NewAPI(appBuilder, singleUserToken, cfg.AuthMode)
|
||||
|
||||
// Local router for admin APIs
|
||||
localRouter := mux.NewRouter()
|
||||
@ -150,7 +152,7 @@ func New(cfg *config.Configuration, singleUserToken string) (*Server, error) {
|
||||
}
|
||||
})
|
||||
|
||||
return &Server{
|
||||
server := Server{
|
||||
config: cfg,
|
||||
wsServer: wsServer,
|
||||
webServer: webServer,
|
||||
@ -159,7 +161,13 @@ func New(cfg *config.Configuration, singleUserToken string) (*Server, error) {
|
||||
telemetry: telemetryService,
|
||||
logger: logger,
|
||||
localRouter: localRouter,
|
||||
}, nil
|
||||
api: api,
|
||||
appBuilder: appBuilder,
|
||||
}
|
||||
|
||||
server.initHandlers()
|
||||
|
||||
return &server, nil
|
||||
}
|
||||
|
||||
func (s *Server) Start() error {
|
||||
|
@ -18,6 +18,7 @@ type Configuration struct {
|
||||
DBType string `json:"dbtype" mapstructure:"dbtype"`
|
||||
DBConfigString string `json:"dbconfig" mapstructure:"dbconfig"`
|
||||
UseSSL bool `json:"useSSL" mapstructure:"useSSL"`
|
||||
SecureCookie bool `json:"secureCookie" mapstructure:"secureCookie"`
|
||||
WebPath string `json:"webpath" mapstructure:"webpath"`
|
||||
FilesPath string `json:"filespath" mapstructure:"filespath"`
|
||||
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
|
||||
@ -28,6 +29,11 @@ type Configuration struct {
|
||||
LocalOnly bool `json:"localonly" mapstructure:"localonly"`
|
||||
EnableLocalMode bool `json:"enableLocalMode" mapstructure:"enableLocalMode"`
|
||||
LocalModeSocketLocation string `json:"localModeSocketLocation" mapstructure:"localModeSocketLocation"`
|
||||
|
||||
AuthMode string `json:"authMode" mapstructure:"authMode"`
|
||||
MattermostURL string `json:"mattermostURL" mapstructure:"mattermostURL"`
|
||||
MattermostClientID string `json:"mattermostClientID" mapstructure:"mattermostClientID"`
|
||||
MattermostClientSecret string `json:"mattermostClientSecret" mapstructure:"mattermostClientSecret"`
|
||||
}
|
||||
|
||||
// ReadConfigFile read the configuration from the filesystem.
|
||||
@ -39,6 +45,7 @@ func ReadConfigFile() (*Configuration, error) {
|
||||
viper.SetDefault("Port", DefaultPort)
|
||||
viper.SetDefault("DBType", "sqlite3")
|
||||
viper.SetDefault("DBConfigString", "./octo.db")
|
||||
viper.SetDefault("SecureCookie", false)
|
||||
viper.SetDefault("WebPath", "./pack")
|
||||
viper.SetDefault("FilesPath", "./files")
|
||||
viper.SetDefault("Telemetry", true)
|
||||
@ -49,6 +56,8 @@ func ReadConfigFile() (*Configuration, error) {
|
||||
viper.SetDefault("EnableLocalMode", false)
|
||||
viper.SetDefault("LocalModeSocketLocation", "/var/tmp/focalboard_local.socket")
|
||||
|
||||
viper.SetDefault("AuthMode", "native")
|
||||
|
||||
err := viper.ReadInConfig() // Find and read the config file
|
||||
if err != nil { // Handle errors reading the config file
|
||||
return nil, err
|
||||
@ -62,7 +71,16 @@ func ReadConfigFile() (*Configuration, error) {
|
||||
}
|
||||
|
||||
log.Println("readConfigFile")
|
||||
log.Printf("%+v", configuration)
|
||||
log.Printf("%+v", removeSecurityData(configuration))
|
||||
|
||||
return &configuration, nil
|
||||
}
|
||||
|
||||
func removeSecurityData(config Configuration) Configuration {
|
||||
clean := config
|
||||
clean.Secret = "hidden"
|
||||
clean.MattermostClientID = "hidden"
|
||||
clean.MattermostClientSecret = "hidden"
|
||||
|
||||
return clean
|
||||
}
|
||||
|
@ -5,35 +5,37 @@
|
||||
package mockstore
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
model "github.com/mattermost/focalboard/server/model"
|
||||
reflect "reflect"
|
||||
store "github.com/mattermost/focalboard/server/services/store"
|
||||
)
|
||||
|
||||
// MockStore is a mock of Store interface
|
||||
// MockStore is a mock of Store interface.
|
||||
type MockStore struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockStoreMockRecorder
|
||||
}
|
||||
|
||||
// MockStoreMockRecorder is the mock recorder for MockStore
|
||||
// MockStoreMockRecorder is the mock recorder for MockStore.
|
||||
type MockStoreMockRecorder struct {
|
||||
mock *MockStore
|
||||
}
|
||||
|
||||
// NewMockStore creates a new mock instance
|
||||
// NewMockStore creates a new mock instance.
|
||||
func NewMockStore(ctrl *gomock.Controller) *MockStore {
|
||||
mock := &MockStore{ctrl: ctrl}
|
||||
mock.recorder = &MockStoreMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockStore) EXPECT() *MockStoreMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// CleanUpSessions mocks base method
|
||||
// CleanUpSessions mocks base method.
|
||||
func (m *MockStore) CleanUpSessions(arg0 int64) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CleanUpSessions", arg0)
|
||||
@ -41,13 +43,13 @@ func (m *MockStore) CleanUpSessions(arg0 int64) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CleanUpSessions indicates an expected call of CleanUpSessions
|
||||
// CleanUpSessions indicates an expected call of CleanUpSessions.
|
||||
func (mr *MockStoreMockRecorder) CleanUpSessions(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanUpSessions", reflect.TypeOf((*MockStore)(nil).CleanUpSessions), arg0)
|
||||
}
|
||||
|
||||
// CreateSession mocks base method
|
||||
// CreateSession mocks base method.
|
||||
func (m *MockStore) CreateSession(arg0 *model.Session) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateSession", arg0)
|
||||
@ -55,13 +57,13 @@ func (m *MockStore) CreateSession(arg0 *model.Session) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreateSession indicates an expected call of CreateSession
|
||||
// CreateSession indicates an expected call of CreateSession.
|
||||
func (mr *MockStoreMockRecorder) CreateSession(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSession", reflect.TypeOf((*MockStore)(nil).CreateSession), arg0)
|
||||
}
|
||||
|
||||
// CreateUser mocks base method
|
||||
// CreateUser mocks base method.
|
||||
func (m *MockStore) CreateUser(arg0 *model.User) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "CreateUser", arg0)
|
||||
@ -69,27 +71,27 @@ func (m *MockStore) CreateUser(arg0 *model.User) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// CreateUser indicates an expected call of CreateUser
|
||||
// CreateUser indicates an expected call of CreateUser.
|
||||
func (mr *MockStoreMockRecorder) CreateUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockStore)(nil).CreateUser), arg0)
|
||||
}
|
||||
|
||||
// DeleteBlock mocks base method
|
||||
func (m *MockStore) DeleteBlock(arg0, arg1 string) error {
|
||||
// DeleteBlock mocks base method.
|
||||
func (m *MockStore) DeleteBlock(arg0 store.Container, arg1, arg2 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteBlock", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "DeleteBlock", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteBlock indicates an expected call of DeleteBlock
|
||||
func (mr *MockStoreMockRecorder) DeleteBlock(arg0, arg1 interface{}) *gomock.Call {
|
||||
// DeleteBlock indicates an expected call of DeleteBlock.
|
||||
func (mr *MockStoreMockRecorder) DeleteBlock(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBlock", reflect.TypeOf((*MockStore)(nil).DeleteBlock), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBlock", reflect.TypeOf((*MockStore)(nil).DeleteBlock), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// DeleteSession mocks base method
|
||||
// DeleteSession mocks base method.
|
||||
func (m *MockStore) DeleteSession(arg0 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "DeleteSession", arg0)
|
||||
@ -97,13 +99,13 @@ func (m *MockStore) DeleteSession(arg0 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// DeleteSession indicates an expected call of DeleteSession
|
||||
// DeleteSession indicates an expected call of DeleteSession.
|
||||
func (mr *MockStoreMockRecorder) DeleteSession(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSession", reflect.TypeOf((*MockStore)(nil).DeleteSession), arg0)
|
||||
}
|
||||
|
||||
// GetActiveUserCount mocks base method
|
||||
// GetActiveUserCount mocks base method.
|
||||
func (m *MockStore) GetActiveUserCount(arg0 int64) (int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetActiveUserCount", arg0)
|
||||
@ -112,88 +114,88 @@ func (m *MockStore) GetActiveUserCount(arg0 int64) (int, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetActiveUserCount indicates an expected call of GetActiveUserCount
|
||||
// GetActiveUserCount indicates an expected call of GetActiveUserCount.
|
||||
func (mr *MockStoreMockRecorder) GetActiveUserCount(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveUserCount", reflect.TypeOf((*MockStore)(nil).GetActiveUserCount), arg0)
|
||||
}
|
||||
|
||||
// GetAllBlocks mocks base method
|
||||
func (m *MockStore) GetAllBlocks() ([]model.Block, error) {
|
||||
// GetAllBlocks mocks base method.
|
||||
func (m *MockStore) GetAllBlocks(arg0 store.Container) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetAllBlocks")
|
||||
ret := m.ctrl.Call(m, "GetAllBlocks", arg0)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetAllBlocks indicates an expected call of GetAllBlocks
|
||||
func (mr *MockStoreMockRecorder) GetAllBlocks() *gomock.Call {
|
||||
// GetAllBlocks indicates an expected call of GetAllBlocks.
|
||||
func (mr *MockStoreMockRecorder) GetAllBlocks(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBlocks", reflect.TypeOf((*MockStore)(nil).GetAllBlocks))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAllBlocks", reflect.TypeOf((*MockStore)(nil).GetAllBlocks), arg0)
|
||||
}
|
||||
|
||||
// GetBlocksWithParent mocks base method
|
||||
func (m *MockStore) GetBlocksWithParent(arg0 string) ([]model.Block, error) {
|
||||
// GetBlocksWithParent mocks base method.
|
||||
func (m *MockStore) GetBlocksWithParent(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithParent", arg0)
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithParent", arg0, arg1)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetBlocksWithParent indicates an expected call of GetBlocksWithParent
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithParent(arg0 interface{}) *gomock.Call {
|
||||
// GetBlocksWithParent indicates an expected call of GetBlocksWithParent.
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithParent(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParent", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParent), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParent", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParent), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetBlocksWithParentAndType mocks base method
|
||||
func (m *MockStore) GetBlocksWithParentAndType(arg0, arg1 string) ([]model.Block, error) {
|
||||
// GetBlocksWithParentAndType mocks base method.
|
||||
func (m *MockStore) GetBlocksWithParentAndType(arg0 store.Container, arg1, arg2 string) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithParentAndType", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithParentAndType", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetBlocksWithParentAndType indicates an expected call of GetBlocksWithParentAndType
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithParentAndType(arg0, arg1 interface{}) *gomock.Call {
|
||||
// GetBlocksWithParentAndType indicates an expected call of GetBlocksWithParentAndType.
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithParentAndType(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParentAndType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParentAndType), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithParentAndType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithParentAndType), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// GetBlocksWithType mocks base method
|
||||
func (m *MockStore) GetBlocksWithType(arg0 string) ([]model.Block, error) {
|
||||
// GetBlocksWithType mocks base method.
|
||||
func (m *MockStore) GetBlocksWithType(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithType", arg0)
|
||||
ret := m.ctrl.Call(m, "GetBlocksWithType", arg0, arg1)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetBlocksWithType indicates an expected call of GetBlocksWithType
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithType(arg0 interface{}) *gomock.Call {
|
||||
// GetBlocksWithType indicates an expected call of GetBlocksWithType.
|
||||
func (mr *MockStoreMockRecorder) GetBlocksWithType(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithType), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocksWithType", reflect.TypeOf((*MockStore)(nil).GetBlocksWithType), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetParentID mocks base method
|
||||
func (m *MockStore) GetParentID(arg0 string) (string, error) {
|
||||
// GetParentID mocks base method.
|
||||
func (m *MockStore) GetParentID(arg0 store.Container, arg1 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetParentID", arg0)
|
||||
ret := m.ctrl.Call(m, "GetParentID", arg0, arg1)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetParentID indicates an expected call of GetParentID
|
||||
func (mr *MockStoreMockRecorder) GetParentID(arg0 interface{}) *gomock.Call {
|
||||
// GetParentID indicates an expected call of GetParentID.
|
||||
func (mr *MockStoreMockRecorder) GetParentID(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParentID", reflect.TypeOf((*MockStore)(nil).GetParentID), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetParentID", reflect.TypeOf((*MockStore)(nil).GetParentID), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetRegisteredUserCount mocks base method
|
||||
// GetRegisteredUserCount mocks base method.
|
||||
func (m *MockStore) GetRegisteredUserCount() (int, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetRegisteredUserCount")
|
||||
@ -202,28 +204,28 @@ func (m *MockStore) GetRegisteredUserCount() (int, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetRegisteredUserCount indicates an expected call of GetRegisteredUserCount
|
||||
// GetRegisteredUserCount indicates an expected call of GetRegisteredUserCount.
|
||||
func (mr *MockStoreMockRecorder) GetRegisteredUserCount() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRegisteredUserCount", reflect.TypeOf((*MockStore)(nil).GetRegisteredUserCount))
|
||||
}
|
||||
|
||||
// GetRootID mocks base method
|
||||
func (m *MockStore) GetRootID(arg0 string) (string, error) {
|
||||
// GetRootID mocks base method.
|
||||
func (m *MockStore) GetRootID(arg0 store.Container, arg1 string) (string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetRootID", arg0)
|
||||
ret := m.ctrl.Call(m, "GetRootID", arg0, arg1)
|
||||
ret0, _ := ret[0].(string)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetRootID indicates an expected call of GetRootID
|
||||
func (mr *MockStoreMockRecorder) GetRootID(arg0 interface{}) *gomock.Call {
|
||||
// GetRootID indicates an expected call of GetRootID.
|
||||
func (mr *MockStoreMockRecorder) GetRootID(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootID", reflect.TypeOf((*MockStore)(nil).GetRootID), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRootID", reflect.TypeOf((*MockStore)(nil).GetRootID), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSession mocks base method
|
||||
// GetSession mocks base method.
|
||||
func (m *MockStore) GetSession(arg0 string, arg1 int64) (*model.Session, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSession", arg0, arg1)
|
||||
@ -232,58 +234,58 @@ func (m *MockStore) GetSession(arg0 string, arg1 int64) (*model.Session, error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSession indicates an expected call of GetSession
|
||||
// GetSession indicates an expected call of GetSession.
|
||||
func (mr *MockStoreMockRecorder) GetSession(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSession", reflect.TypeOf((*MockStore)(nil).GetSession), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSharing mocks base method
|
||||
func (m *MockStore) GetSharing(arg0 string) (*model.Sharing, error) {
|
||||
// GetSharing mocks base method.
|
||||
func (m *MockStore) GetSharing(arg0 store.Container, arg1 string) (*model.Sharing, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSharing", arg0)
|
||||
ret := m.ctrl.Call(m, "GetSharing", arg0, arg1)
|
||||
ret0, _ := ret[0].(*model.Sharing)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSharing indicates an expected call of GetSharing
|
||||
func (mr *MockStoreMockRecorder) GetSharing(arg0 interface{}) *gomock.Call {
|
||||
// GetSharing indicates an expected call of GetSharing.
|
||||
func (mr *MockStoreMockRecorder) GetSharing(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSharing", reflect.TypeOf((*MockStore)(nil).GetSharing), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSharing", reflect.TypeOf((*MockStore)(nil).GetSharing), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSubTree2 mocks base method
|
||||
func (m *MockStore) GetSubTree2(arg0 string) ([]model.Block, error) {
|
||||
// GetSubTree2 mocks base method.
|
||||
func (m *MockStore) GetSubTree2(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSubTree2", arg0)
|
||||
ret := m.ctrl.Call(m, "GetSubTree2", arg0, arg1)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSubTree2 indicates an expected call of GetSubTree2
|
||||
func (mr *MockStoreMockRecorder) GetSubTree2(arg0 interface{}) *gomock.Call {
|
||||
// GetSubTree2 indicates an expected call of GetSubTree2.
|
||||
func (mr *MockStoreMockRecorder) GetSubTree2(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree2", reflect.TypeOf((*MockStore)(nil).GetSubTree2), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree2", reflect.TypeOf((*MockStore)(nil).GetSubTree2), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSubTree3 mocks base method
|
||||
func (m *MockStore) GetSubTree3(arg0 string) ([]model.Block, error) {
|
||||
// GetSubTree3 mocks base method.
|
||||
func (m *MockStore) GetSubTree3(arg0 store.Container, arg1 string) ([]model.Block, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSubTree3", arg0)
|
||||
ret := m.ctrl.Call(m, "GetSubTree3", arg0, arg1)
|
||||
ret0, _ := ret[0].([]model.Block)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSubTree3 indicates an expected call of GetSubTree3
|
||||
func (mr *MockStoreMockRecorder) GetSubTree3(arg0 interface{}) *gomock.Call {
|
||||
// GetSubTree3 indicates an expected call of GetSubTree3.
|
||||
func (mr *MockStoreMockRecorder) GetSubTree3(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree3", reflect.TypeOf((*MockStore)(nil).GetSubTree3), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubTree3", reflect.TypeOf((*MockStore)(nil).GetSubTree3), arg0, arg1)
|
||||
}
|
||||
|
||||
// GetSystemSettings mocks base method
|
||||
// GetSystemSettings mocks base method.
|
||||
func (m *MockStore) GetSystemSettings() (map[string]string, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSystemSettings")
|
||||
@ -292,13 +294,13 @@ func (m *MockStore) GetSystemSettings() (map[string]string, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSystemSettings indicates an expected call of GetSystemSettings
|
||||
// GetSystemSettings indicates an expected call of GetSystemSettings.
|
||||
func (mr *MockStoreMockRecorder) GetSystemSettings() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSystemSettings", reflect.TypeOf((*MockStore)(nil).GetSystemSettings))
|
||||
}
|
||||
|
||||
// GetUserByEmail mocks base method
|
||||
// GetUserByEmail mocks base method.
|
||||
func (m *MockStore) GetUserByEmail(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserByEmail", arg0)
|
||||
@ -307,13 +309,13 @@ func (m *MockStore) GetUserByEmail(arg0 string) (*model.User, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserByEmail indicates an expected call of GetUserByEmail
|
||||
// GetUserByEmail indicates an expected call of GetUserByEmail.
|
||||
func (mr *MockStoreMockRecorder) GetUserByEmail(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByEmail", reflect.TypeOf((*MockStore)(nil).GetUserByEmail), arg0)
|
||||
}
|
||||
|
||||
// GetUserById mocks base method
|
||||
// GetUserById mocks base method.
|
||||
func (m *MockStore) GetUserById(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserById", arg0)
|
||||
@ -322,13 +324,13 @@ func (m *MockStore) GetUserById(arg0 string) (*model.User, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserById indicates an expected call of GetUserById
|
||||
// GetUserById indicates an expected call of GetUserById.
|
||||
func (mr *MockStoreMockRecorder) GetUserById(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserById", reflect.TypeOf((*MockStore)(nil).GetUserById), arg0)
|
||||
}
|
||||
|
||||
// GetUserByUsername mocks base method
|
||||
// GetUserByUsername mocks base method.
|
||||
func (m *MockStore) GetUserByUsername(arg0 string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserByUsername", arg0)
|
||||
@ -337,13 +339,13 @@ func (m *MockStore) GetUserByUsername(arg0 string) (*model.User, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserByUsername indicates an expected call of GetUserByUsername
|
||||
// GetUserByUsername indicates an expected call of GetUserByUsername.
|
||||
func (mr *MockStoreMockRecorder) GetUserByUsername(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByUsername", reflect.TypeOf((*MockStore)(nil).GetUserByUsername), arg0)
|
||||
}
|
||||
|
||||
// GetWorkspace mocks base method
|
||||
// GetWorkspace mocks base method.
|
||||
func (m *MockStore) GetWorkspace(arg0 string) (*model.Workspace, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetWorkspace", arg0)
|
||||
@ -352,27 +354,27 @@ func (m *MockStore) GetWorkspace(arg0 string) (*model.Workspace, error) {
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetWorkspace indicates an expected call of GetWorkspace
|
||||
// GetWorkspace indicates an expected call of GetWorkspace.
|
||||
func (mr *MockStoreMockRecorder) GetWorkspace(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetWorkspace", reflect.TypeOf((*MockStore)(nil).GetWorkspace), arg0)
|
||||
}
|
||||
|
||||
// InsertBlock mocks base method
|
||||
func (m *MockStore) InsertBlock(arg0 model.Block) error {
|
||||
// InsertBlock mocks base method.
|
||||
func (m *MockStore) InsertBlock(arg0 store.Container, arg1 model.Block) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "InsertBlock", arg0)
|
||||
ret := m.ctrl.Call(m, "InsertBlock", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// InsertBlock indicates an expected call of InsertBlock
|
||||
func (mr *MockStoreMockRecorder) InsertBlock(arg0 interface{}) *gomock.Call {
|
||||
// InsertBlock indicates an expected call of InsertBlock.
|
||||
func (mr *MockStoreMockRecorder) InsertBlock(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertBlock", reflect.TypeOf((*MockStore)(nil).InsertBlock), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertBlock", reflect.TypeOf((*MockStore)(nil).InsertBlock), arg0, arg1)
|
||||
}
|
||||
|
||||
// RefreshSession mocks base method
|
||||
// RefreshSession mocks base method.
|
||||
func (m *MockStore) RefreshSession(arg0 *model.Session) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "RefreshSession", arg0)
|
||||
@ -380,13 +382,13 @@ func (m *MockStore) RefreshSession(arg0 *model.Session) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// RefreshSession indicates an expected call of RefreshSession
|
||||
// RefreshSession indicates an expected call of RefreshSession.
|
||||
func (mr *MockStoreMockRecorder) RefreshSession(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RefreshSession", reflect.TypeOf((*MockStore)(nil).RefreshSession), arg0)
|
||||
}
|
||||
|
||||
// SetSystemSetting mocks base method
|
||||
// SetSystemSetting mocks base method.
|
||||
func (m *MockStore) SetSystemSetting(arg0, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SetSystemSetting", arg0, arg1)
|
||||
@ -394,13 +396,13 @@ func (m *MockStore) SetSystemSetting(arg0, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// SetSystemSetting indicates an expected call of SetSystemSetting
|
||||
// SetSystemSetting indicates an expected call of SetSystemSetting.
|
||||
func (mr *MockStoreMockRecorder) SetSystemSetting(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSystemSetting", reflect.TypeOf((*MockStore)(nil).SetSystemSetting), arg0, arg1)
|
||||
}
|
||||
|
||||
// Shutdown mocks base method
|
||||
// Shutdown mocks base method.
|
||||
func (m *MockStore) Shutdown() error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Shutdown")
|
||||
@ -408,13 +410,13 @@ func (m *MockStore) Shutdown() error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Shutdown indicates an expected call of Shutdown
|
||||
// Shutdown indicates an expected call of Shutdown.
|
||||
func (mr *MockStoreMockRecorder) Shutdown() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Shutdown", reflect.TypeOf((*MockStore)(nil).Shutdown))
|
||||
}
|
||||
|
||||
// UpdateSession mocks base method
|
||||
// UpdateSession mocks base method.
|
||||
func (m *MockStore) UpdateSession(arg0 *model.Session) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateSession", arg0)
|
||||
@ -422,13 +424,13 @@ func (m *MockStore) UpdateSession(arg0 *model.Session) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateSession indicates an expected call of UpdateSession
|
||||
// UpdateSession indicates an expected call of UpdateSession.
|
||||
func (mr *MockStoreMockRecorder) UpdateSession(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSession", reflect.TypeOf((*MockStore)(nil).UpdateSession), arg0)
|
||||
}
|
||||
|
||||
// UpdateUser mocks base method
|
||||
// UpdateUser mocks base method.
|
||||
func (m *MockStore) UpdateUser(arg0 *model.User) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUser", arg0)
|
||||
@ -436,13 +438,13 @@ func (m *MockStore) UpdateUser(arg0 *model.User) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateUser indicates an expected call of UpdateUser
|
||||
// UpdateUser indicates an expected call of UpdateUser.
|
||||
func (mr *MockStoreMockRecorder) UpdateUser(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUser", reflect.TypeOf((*MockStore)(nil).UpdateUser), arg0)
|
||||
}
|
||||
|
||||
// UpdateUserPassword mocks base method
|
||||
// UpdateUserPassword mocks base method.
|
||||
func (m *MockStore) UpdateUserPassword(arg0, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUserPassword", arg0, arg1)
|
||||
@ -450,13 +452,13 @@ func (m *MockStore) UpdateUserPassword(arg0, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateUserPassword indicates an expected call of UpdateUserPassword
|
||||
// UpdateUserPassword indicates an expected call of UpdateUserPassword.
|
||||
func (mr *MockStoreMockRecorder) UpdateUserPassword(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPassword", reflect.TypeOf((*MockStore)(nil).UpdateUserPassword), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpdateUserPasswordByID mocks base method
|
||||
// UpdateUserPasswordByID mocks base method.
|
||||
func (m *MockStore) UpdateUserPasswordByID(arg0, arg1 string) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpdateUserPasswordByID", arg0, arg1)
|
||||
@ -464,27 +466,27 @@ func (m *MockStore) UpdateUserPasswordByID(arg0, arg1 string) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpdateUserPasswordByID indicates an expected call of UpdateUserPasswordByID
|
||||
// UpdateUserPasswordByID indicates an expected call of UpdateUserPasswordByID.
|
||||
func (mr *MockStoreMockRecorder) UpdateUserPasswordByID(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateUserPasswordByID", reflect.TypeOf((*MockStore)(nil).UpdateUserPasswordByID), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpsertSharing mocks base method
|
||||
func (m *MockStore) UpsertSharing(arg0 model.Sharing) error {
|
||||
// UpsertSharing mocks base method.
|
||||
func (m *MockStore) UpsertSharing(arg0 store.Container, arg1 model.Sharing) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertSharing", arg0)
|
||||
ret := m.ctrl.Call(m, "UpsertSharing", arg0, arg1)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertSharing indicates an expected call of UpsertSharing
|
||||
func (mr *MockStoreMockRecorder) UpsertSharing(arg0 interface{}) *gomock.Call {
|
||||
// UpsertSharing indicates an expected call of UpsertSharing.
|
||||
func (mr *MockStoreMockRecorder) UpsertSharing(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertSharing", reflect.TypeOf((*MockStore)(nil).UpsertSharing), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertSharing", reflect.TypeOf((*MockStore)(nil).UpsertSharing), arg0, arg1)
|
||||
}
|
||||
|
||||
// UpsertWorkspaceSettings mocks base method
|
||||
// UpsertWorkspaceSettings mocks base method.
|
||||
func (m *MockStore) UpsertWorkspaceSettings(arg0 model.Workspace) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertWorkspaceSettings", arg0)
|
||||
@ -492,13 +494,13 @@ func (m *MockStore) UpsertWorkspaceSettings(arg0 model.Workspace) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertWorkspaceSettings indicates an expected call of UpsertWorkspaceSettings
|
||||
// UpsertWorkspaceSettings indicates an expected call of UpsertWorkspaceSettings.
|
||||
func (mr *MockStoreMockRecorder) UpsertWorkspaceSettings(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSettings", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSettings), arg0)
|
||||
}
|
||||
|
||||
// UpsertWorkspaceSignupToken mocks base method
|
||||
// UpsertWorkspaceSignupToken mocks base method.
|
||||
func (m *MockStore) UpsertWorkspaceSignupToken(arg0 model.Workspace) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UpsertWorkspaceSignupToken", arg0)
|
||||
@ -506,7 +508,7 @@ func (m *MockStore) UpsertWorkspaceSignupToken(arg0 model.Workspace) error {
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UpsertWorkspaceSignupToken indicates an expected call of UpsertWorkspaceSignupToken
|
||||
// UpsertWorkspaceSignupToken indicates an expected call of UpsertWorkspaceSignupToken.
|
||||
func (mr *MockStoreMockRecorder) UpsertWorkspaceSignupToken(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpsertWorkspaceSignupToken", reflect.TypeOf((*MockStore)(nil).UpsertWorkspaceSignupToken), arg0)
|
||||
|
@ -10,19 +10,21 @@ import (
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
func (s *SQLStore) latestsBlocksSubquery() sq.SelectBuilder {
|
||||
func (s *SQLStore) latestsBlocksSubquery(c store.Container) sq.SelectBuilder {
|
||||
internalQuery := sq.Select("*", "ROW_NUMBER() OVER (PARTITION BY id ORDER BY insert_at DESC) AS rn").From("blocks")
|
||||
|
||||
return sq.Select("*").
|
||||
FromSelect(internalQuery, "a").
|
||||
Where(sq.Eq{"rn": 1}).
|
||||
Where(sq.Eq{"delete_at": 0})
|
||||
Where(sq.Eq{"delete_at": 0}).
|
||||
Where(sq.Eq{"coalesce(workspace_id, \"\")": c.WorkspaceID})
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetBlocksWithParentAndType(parentID, blockType string) ([]model.Block, error) {
|
||||
func (s *SQLStore) GetBlocksWithParentAndType(c store.Container, parentID string, blockType string) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
@ -37,7 +39,7 @@ func (s *SQLStore) GetBlocksWithParentAndType(parentID, blockType string) ([]mod
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Eq{"parent_id": parentID}).
|
||||
Where(sq.Eq{"type": blockType})
|
||||
|
||||
@ -51,7 +53,7 @@ func (s *SQLStore) GetBlocksWithParentAndType(parentID, blockType string) ([]mod
|
||||
return blocksFromRows(rows)
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
|
||||
func (s *SQLStore) GetBlocksWithParent(c store.Container, parentID string) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
@ -66,7 +68,7 @@ func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Eq{"parent_id": parentID})
|
||||
|
||||
rows, err := query.Query()
|
||||
@ -79,7 +81,7 @@ func (s *SQLStore) GetBlocksWithParent(parentID string) ([]model.Block, error) {
|
||||
return blocksFromRows(rows)
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetBlocksWithType(blockType string) ([]model.Block, error) {
|
||||
func (s *SQLStore) GetBlocksWithType(c store.Container, blockType string) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
@ -94,7 +96,7 @@ func (s *SQLStore) GetBlocksWithType(blockType string) ([]model.Block, error) {
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Eq{"type": blockType})
|
||||
|
||||
rows, err := query.Query()
|
||||
@ -108,7 +110,7 @@ func (s *SQLStore) GetBlocksWithType(blockType string) ([]model.Block, error) {
|
||||
}
|
||||
|
||||
// GetSubTree2 returns blocks within 2 levels of the given blockID
|
||||
func (s *SQLStore) GetSubTree2(blockID string) ([]model.Block, error) {
|
||||
func (s *SQLStore) GetSubTree2(c store.Container, blockID string) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
@ -123,7 +125,7 @@ func (s *SQLStore) GetSubTree2(blockID string) ([]model.Block, error) {
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Or{sq.Eq{"id": blockID}, sq.Eq{"parent_id": blockID}})
|
||||
|
||||
rows, err := query.Query()
|
||||
@ -137,7 +139,7 @@ func (s *SQLStore) GetSubTree2(blockID string) ([]model.Block, error) {
|
||||
}
|
||||
|
||||
// GetSubTree3 returns blocks within 3 levels of the given blockID
|
||||
func (s *SQLStore) GetSubTree3(blockID string) ([]model.Block, error) {
|
||||
func (s *SQLStore) GetSubTree3(c store.Container, blockID string) ([]model.Block, error) {
|
||||
// This first subquery returns repeated blocks
|
||||
subquery1 := sq.Select(
|
||||
"l3.id",
|
||||
@ -152,9 +154,9 @@ func (s *SQLStore) GetSubTree3(blockID string) ([]model.Block, error) {
|
||||
"l3.update_at",
|
||||
"l3.delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "l1").
|
||||
JoinClause(s.latestsBlocksSubquery().Prefix("JOIN (").Suffix(") l2 on l2.parent_id = l1.id or l2.id = l1.id")).
|
||||
JoinClause(s.latestsBlocksSubquery().Prefix("JOIN (").Suffix(") l3 on l3.parent_id = l2.id or l3.id = l2.id")).
|
||||
FromSelect(s.latestsBlocksSubquery(c), "l1").
|
||||
JoinClause(s.latestsBlocksSubquery(c).Prefix("JOIN (").Suffix(") l2 on l2.parent_id = l1.id or l2.id = l1.id")).
|
||||
JoinClause(s.latestsBlocksSubquery(c).Prefix("JOIN (").Suffix(") l3 on l3.parent_id = l2.id or l3.id = l2.id")).
|
||||
Where(sq.Eq{"l1.id": blockID})
|
||||
|
||||
// This second subquery is used to return distinct blocks
|
||||
@ -188,7 +190,7 @@ func (s *SQLStore) GetSubTree3(blockID string) ([]model.Block, error) {
|
||||
return blocksFromRows(rows)
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetAllBlocks() ([]model.Block, error) {
|
||||
func (s *SQLStore) GetAllBlocks(c store.Container) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
@ -203,7 +205,7 @@ func (s *SQLStore) GetAllBlocks() ([]model.Block, error) {
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest")
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest")
|
||||
|
||||
rows, err := query.Query()
|
||||
if err != nil {
|
||||
@ -262,9 +264,9 @@ func blocksFromRows(rows *sql.Rows) ([]model.Block, error) {
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetRootID(blockID string) (string, error) {
|
||||
func (s *SQLStore) GetRootID(c store.Container, blockID string) (string, error) {
|
||||
query := s.getQueryBuilder().Select("root_id").
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Eq{"id": blockID})
|
||||
|
||||
row := query.QueryRow()
|
||||
@ -279,9 +281,9 @@ func (s *SQLStore) GetRootID(blockID string) (string, error) {
|
||||
return rootID, nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetParentID(blockID string) (string, error) {
|
||||
func (s *SQLStore) GetParentID(c store.Container, blockID string) (string, error) {
|
||||
query := s.getQueryBuilder().Select("parent_id").
|
||||
FromSelect(s.latestsBlocksSubquery(), "latest").
|
||||
FromSelect(s.latestsBlocksSubquery(c), "latest").
|
||||
Where(sq.Eq{"id": blockID})
|
||||
|
||||
row := query.QueryRow()
|
||||
@ -296,7 +298,7 @@ func (s *SQLStore) GetParentID(blockID string) (string, error) {
|
||||
return parentID, nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) InsertBlock(block model.Block) error {
|
||||
func (s *SQLStore) InsertBlock(c store.Container, block model.Block) error {
|
||||
if block.RootID == "" {
|
||||
return errors.New("rootId is nil")
|
||||
}
|
||||
@ -308,6 +310,7 @@ func (s *SQLStore) InsertBlock(block model.Block) error {
|
||||
|
||||
query := s.getQueryBuilder().Insert("blocks").
|
||||
Columns(
|
||||
"workspace_id",
|
||||
"id",
|
||||
"parent_id",
|
||||
"root_id",
|
||||
@ -320,6 +323,7 @@ func (s *SQLStore) InsertBlock(block model.Block) error {
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).Values(
|
||||
c.WorkspaceID,
|
||||
block.ID,
|
||||
block.ParentID,
|
||||
block.RootID,
|
||||
@ -341,16 +345,18 @@ func (s *SQLStore) InsertBlock(block model.Block) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) DeleteBlock(blockID, modifiedBy string) error {
|
||||
func (s *SQLStore) DeleteBlock(c store.Container, blockID string, modifiedBy string) error {
|
||||
now := time.Now().Unix()
|
||||
query := s.getQueryBuilder().Insert("blocks").
|
||||
Columns(
|
||||
"workspace_id",
|
||||
"id",
|
||||
"modified_by",
|
||||
"update_at",
|
||||
"delete_at",
|
||||
).
|
||||
Values(
|
||||
c.WorkspaceID,
|
||||
blockID,
|
||||
modifiedBy,
|
||||
now,
|
||||
|
@ -1,13 +1,11 @@
|
||||
// Code generated by go-bindata. DO NOT EDIT.
|
||||
// sources:
|
||||
// templates/templates.json (22.926kB)
|
||||
|
||||
// templates/templates.json
|
||||
package initializations
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
@ -20,7 +18,7 @@ import (
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %w", name, err)
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
@ -28,7 +26,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read %q: %w", name, err)
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
@ -38,9 +36,8 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
digest [sha256.Size]byte
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
@ -84,8 +81,8 @@ func templatesJson() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates.json", size: 22926, mode: os.FileMode(0644), modTime: time.Unix(1610369786, 0)}
|
||||
a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3, 0x15, 0x49, 0xe, 0xb2, 0xe7, 0x7, 0xd0, 0x6e, 0x35, 0x6f, 0xd0, 0x76, 0xe7, 0x1d, 0x9d, 0xc7, 0xa0, 0x55, 0x1, 0x25, 0x51, 0x9e, 0xd5, 0xf0, 0x81, 0x4c, 0x91, 0xd7, 0x33, 0x37, 0x3b}}
|
||||
info := bindataFileInfo{name: "templates.json", size: 22926, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
@ -93,8 +90,8 @@ func templatesJson() (*asset, error) {
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
@ -104,12 +101,6 @@ func Asset(name string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// AssetString returns the asset contents as a string (instead of a []byte).
|
||||
func AssetString(name string) (string, error) {
|
||||
data, err := Asset(name)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
@ -121,18 +112,12 @@ func MustAsset(name string) []byte {
|
||||
return a
|
||||
}
|
||||
|
||||
// MustAssetString is like AssetString but panics when Asset would return an
|
||||
// error. It simplifies safe initialization of global variables.
|
||||
func MustAssetString(name string) string {
|
||||
return string(MustAsset(name))
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
@ -142,33 +127,6 @@ func AssetInfo(name string) (os.FileInfo, error) {
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetDigest returns the digest of the file with the given name. It returns an
|
||||
// error if the asset could not be found or the digest could not be loaded.
|
||||
func AssetDigest(name string) ([sha256.Size]byte, error) {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[canonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.digest, nil
|
||||
}
|
||||
return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
|
||||
}
|
||||
|
||||
// Digests returns a map of all known files and their checksums.
|
||||
func Digests() (map[string][sha256.Size]byte, error) {
|
||||
mp := make(map[string][sha256.Size]byte, len(_bindata))
|
||||
for name := range _bindata {
|
||||
a, err := _bindata[name]()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp[name] = a.digest
|
||||
}
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
@ -183,9 +141,6 @@ var _bindata = map[string]func() (*asset, error){
|
||||
"templates.json": templatesJson,
|
||||
}
|
||||
|
||||
// AssetDebug is true if the assets were built with the debug flag enabled.
|
||||
const AssetDebug = false
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
@ -195,15 +150,15 @@ const AssetDebug = false
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"},
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"},
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(canonicalName, "/")
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
@ -225,12 +180,11 @@ type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"templates.json": {templatesJson, map[string]*bintree{}},
|
||||
"templates.json": &bintree{templatesJson, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory.
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
@ -248,10 +202,14 @@ func RestoreAsset(dir, name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively.
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
@ -269,6 +227,7 @@ func RestoreAssets(dir, name string) error {
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
canonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"log"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
"github.com/mattermost/focalboard/server/services/store/sqlstore/initializations"
|
||||
)
|
||||
|
||||
@ -32,10 +33,14 @@ func (s *SQLStore) importInitialTemplates() error {
|
||||
return err
|
||||
}
|
||||
|
||||
globalContainer := store.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
|
||||
log.Printf("Inserting %d blocks", len(archive.Blocks))
|
||||
for _, block := range archive.Blocks {
|
||||
// log.Printf("\t%v %v %v", block.ID, block.Type, block.Title)
|
||||
err := s.InsertBlock(block)
|
||||
err := s.InsertBlock(globalContainer, block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -14,6 +14,8 @@
|
||||
// postgres_files/000006_sharing_table.up.sql
|
||||
// postgres_files/000007_workspaces_table.down.sql
|
||||
// postgres_files/000007_workspaces_table.up.sql
|
||||
// postgres_files/000008_teams.down.sql
|
||||
// postgres_files/000008_teams.up.sql
|
||||
package postgres
|
||||
|
||||
import (
|
||||
@ -214,7 +216,7 @@ func _000004_auth_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000004_auth_table.down.sql", size: 39, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000004_auth_table.down.sql", size: 39, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -234,7 +236,7 @@ func _000004_auth_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000004_auth_table.up.sql", size: 491, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000004_auth_table.up.sql", size: 491, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -254,7 +256,7 @@ func _000005_blocks_modifiedbyDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.down.sql", size: 44, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.down.sql", size: 44, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -274,7 +276,7 @@ func _000005_blocks_modifiedbyUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.up.sql", size: 55, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.up.sql", size: 55, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -294,7 +296,7 @@ func _000006_sharing_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000006_sharing_table.down.sql", size: 20, mode: os.FileMode(420), modTime: time.Unix(1610576067, 0)}
|
||||
info := bindataFileInfo{name: "000006_sharing_table.down.sql", size: 20, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -314,7 +316,7 @@ func _000006_sharing_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000006_sharing_table.up.sql", size: 159, mode: os.FileMode(420), modTime: time.Unix(1610576067, 0)}
|
||||
info := bindataFileInfo{name: "000006_sharing_table.up.sql", size: 159, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -334,7 +336,7 @@ func _000007_workspaces_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.down.sql", size: 23, mode: os.FileMode(420), modTime: time.Unix(1610576169, 0)}
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.down.sql", size: 23, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -354,7 +356,47 @@ func _000007_workspaces_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.up.sql", size: 179, mode: os.FileMode(420), modTime: time.Unix(1610577228, 0)}
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.up.sql", size: 179, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000008_teamsDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xca\xc9\x4f\xce\x2e\xe6\x72\x09\xf2\x0f\x50\x70\xf6\xf7\x09\xf5\xf5\x53\x28\xcf\x2f\xca\x2e\x2e\x48\x4c\x4e\x8d\xcf\x4c\xb1\xe6\xe2\x42\x56\x5d\x9c\x91\x58\x94\x99\x97\x4e\xb4\xf2\xd4\xe2\xe2\xcc\xfc\x3c\x54\xe3\x13\x4b\x4b\x32\xe2\x8b\x53\x8b\xca\x32\x93\x53\xad\xb9\x00\x01\x00\x00\xff\xff\xdd\xff\x41\x9f\x8c\x00\x00\x00")
|
||||
|
||||
func _000008_teamsDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000008_teamsDownSql,
|
||||
"000008_teams.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000008_teamsDownSql() (*asset, error) {
|
||||
bytes, err := _000008_teamsDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000008_teams.down.sql", size: 140, mode: os.FileMode(420), modTime: time.Unix(1616709037, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000008_teamsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xca\xc9\x4f\xce\x2e\xe6\x72\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x28\xcf\x2f\xca\x2e\x2e\x48\x4c\x4e\x8d\xcf\x4c\x51\x08\x73\x0c\x72\xf6\x70\x0c\xd2\x30\x36\xd3\xb4\xe6\xe2\x42\xd6\x58\x9c\x91\x58\x94\x99\x97\x4e\x8e\xce\xd4\xe2\xe2\xcc\xfc\x3c\x14\x4b\x13\x4b\x4b\x32\xe2\x8b\x53\x8b\xca\x32\x93\x53\xe1\x5a\x8d\x0c\x34\xad\xb9\x00\x01\x00\x00\xff\xff\xba\x55\x30\xd8\xad\x00\x00\x00")
|
||||
|
||||
func _000008_teamsUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000008_teamsUpSql,
|
||||
"000008_teams.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000008_teamsUpSql() (*asset, error) {
|
||||
bytes, err := _000008_teamsUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000008_teams.up.sql", size: 173, mode: os.FileMode(420), modTime: time.Unix(1616709035, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -425,6 +467,8 @@ var _bindata = map[string]func() (*asset, error){
|
||||
"000006_sharing_table.up.sql": _000006_sharing_tableUpSql,
|
||||
"000007_workspaces_table.down.sql": _000007_workspaces_tableDownSql,
|
||||
"000007_workspaces_table.up.sql": _000007_workspaces_tableUpSql,
|
||||
"000008_teams.down.sql": _000008_teamsDownSql,
|
||||
"000008_teams.up.sql": _000008_teamsUpSql,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@ -481,6 +525,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"000006_sharing_table.up.sql": &bintree{_000006_sharing_tableUpSql, map[string]*bintree{}},
|
||||
"000007_workspaces_table.down.sql": &bintree{_000007_workspaces_tableDownSql, map[string]*bintree{}},
|
||||
"000007_workspaces_table.up.sql": &bintree{_000007_workspaces_tableUpSql, map[string]*bintree{}},
|
||||
"000008_teams.down.sql": &bintree{_000008_teamsDownSql, map[string]*bintree{}},
|
||||
"000008_teams.up.sql": &bintree{_000008_teamsUpSql, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
|
@ -0,0 +1,8 @@
|
||||
ALTER TABLE blocks
|
||||
DROP COLUMN workspace_id;
|
||||
|
||||
ALTER TABLE sharing
|
||||
DROP COLUMN workspace_id;
|
||||
|
||||
ALTER TABLE sessions
|
||||
DROP COLUMN auth_service;
|
@ -0,0 +1,8 @@
|
||||
ALTER TABLE blocks
|
||||
ADD COLUMN workspace_id VARCHAR(36);
|
||||
|
||||
ALTER TABLE sharing
|
||||
ADD COLUMN workspace_id VARCHAR(36);
|
||||
|
||||
ALTER TABLE sessions
|
||||
ADD COLUMN auth_service VARCHAR(20);
|
@ -14,6 +14,8 @@
|
||||
// sqlite_files/000006_sharing_table.up.sql
|
||||
// sqlite_files/000007_workspaces_table.down.sql
|
||||
// sqlite_files/000007_workspaces_table.up.sql
|
||||
// sqlite_files/000008_teams.down.sql
|
||||
// sqlite_files/000008_teams.up.sql
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
@ -214,7 +216,7 @@ func _000004_auth_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000004_auth_table.down.sql", size: 39, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000004_auth_table.down.sql", size: 39, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -234,7 +236,7 @@ func _000004_auth_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000004_auth_table.up.sql", size: 491, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000004_auth_table.up.sql", size: 491, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -254,7 +256,7 @@ func _000005_blocks_modifiedbyDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.down.sql", size: 44, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.down.sql", size: 44, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -274,7 +276,7 @@ func _000005_blocks_modifiedbyUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.up.sql", size: 55, mode: os.FileMode(420), modTime: time.Unix(1610481092, 0)}
|
||||
info := bindataFileInfo{name: "000005_blocks_modifiedby.up.sql", size: 55, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -294,7 +296,7 @@ func _000006_sharing_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000006_sharing_table.down.sql", size: 20, mode: os.FileMode(420), modTime: time.Unix(1610576067, 0)}
|
||||
info := bindataFileInfo{name: "000006_sharing_table.down.sql", size: 20, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -314,7 +316,7 @@ func _000006_sharing_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000006_sharing_table.up.sql", size: 159, mode: os.FileMode(420), modTime: time.Unix(1610576067, 0)}
|
||||
info := bindataFileInfo{name: "000006_sharing_table.up.sql", size: 159, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -334,7 +336,7 @@ func _000007_workspaces_tableDownSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.down.sql", size: 23, mode: os.FileMode(420), modTime: time.Unix(1610576588, 0)}
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.down.sql", size: 23, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -354,7 +356,47 @@ func _000007_workspaces_tableUpSql() (*asset, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.up.sql", size: 179, mode: os.FileMode(420), modTime: time.Unix(1610577231, 0)}
|
||||
info := bindataFileInfo{name: "000007_workspaces_table.up.sql", size: 179, mode: os.FileMode(420), modTime: time.Unix(1611791102, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000008_teamsDownSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xca\xc9\x4f\xce\x2e\xe6\x72\x09\xf2\x0f\x50\x70\xf6\xf7\x09\xf5\xf5\x53\x28\xcf\x2f\xca\x2e\x2e\x48\x4c\x4e\x8d\xcf\x4c\xb1\xe6\xe2\x42\x56\x5d\x9c\x91\x58\x94\x99\x97\x4e\xb4\xf2\xd4\xe2\xe2\xcc\xfc\x3c\x54\xe3\x13\x4b\x4b\x32\xe2\x8b\x53\x8b\xca\x32\x93\x53\xad\xb9\x00\x01\x00\x00\xff\xff\xdd\xff\x41\x9f\x8c\x00\x00\x00")
|
||||
|
||||
func _000008_teamsDownSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000008_teamsDownSql,
|
||||
"000008_teams.down.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000008_teamsDownSql() (*asset, error) {
|
||||
bytes, err := _000008_teamsDownSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000008_teams.down.sql", size: 140, mode: os.FileMode(420), modTime: time.Unix(1616709044, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
var __000008_teamsUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x72\xf4\x09\x71\x0d\x52\x08\x71\x74\xf2\x71\x55\x48\xca\xc9\x4f\xce\x2e\xe6\x72\x74\x71\x51\x70\xf6\xf7\x09\xf5\xf5\x53\x28\xcf\x2f\xca\x2e\x2e\x48\x4c\x4e\x8d\xcf\x4c\x51\x08\x73\x0c\x72\xf6\x70\x0c\xd2\x30\x36\xd3\xb4\xe6\xe2\x42\xd6\x58\x9c\x91\x58\x94\x99\x97\x4e\x8e\xce\xd4\xe2\xe2\xcc\xfc\x3c\x14\x4b\x13\x4b\x4b\x32\xe2\x8b\x53\x8b\xca\x32\x93\x53\xe1\x5a\x8d\x0c\x34\xad\xb9\x00\x01\x00\x00\xff\xff\xba\x55\x30\xd8\xad\x00\x00\x00")
|
||||
|
||||
func _000008_teamsUpSqlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
__000008_teamsUpSql,
|
||||
"000008_teams.up.sql",
|
||||
)
|
||||
}
|
||||
|
||||
func _000008_teamsUpSql() (*asset, error) {
|
||||
bytes, err := _000008_teamsUpSqlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "000008_teams.up.sql", size: 173, mode: os.FileMode(420), modTime: time.Unix(1616709052, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
@ -425,6 +467,8 @@ var _bindata = map[string]func() (*asset, error){
|
||||
"000006_sharing_table.up.sql": _000006_sharing_tableUpSql,
|
||||
"000007_workspaces_table.down.sql": _000007_workspaces_tableDownSql,
|
||||
"000007_workspaces_table.up.sql": _000007_workspaces_tableUpSql,
|
||||
"000008_teams.down.sql": _000008_teamsDownSql,
|
||||
"000008_teams.up.sql": _000008_teamsUpSql,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@ -481,6 +525,8 @@ var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"000006_sharing_table.up.sql": &bintree{_000006_sharing_tableUpSql, map[string]*bintree{}},
|
||||
"000007_workspaces_table.down.sql": &bintree{_000007_workspaces_tableDownSql, map[string]*bintree{}},
|
||||
"000007_workspaces_table.up.sql": &bintree{_000007_workspaces_tableUpSql, map[string]*bintree{}},
|
||||
"000008_teams.down.sql": &bintree{_000008_teamsDownSql, map[string]*bintree{}},
|
||||
"000008_teams.up.sql": &bintree{_000008_teamsUpSql, map[string]*bintree{}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
|
@ -0,0 +1,8 @@
|
||||
ALTER TABLE blocks
|
||||
DROP COLUMN workspace_id;
|
||||
|
||||
ALTER TABLE sharing
|
||||
DROP COLUMN workspace_id;
|
||||
|
||||
ALTER TABLE sessions
|
||||
DROP COLUMN auth_service;
|
@ -0,0 +1,8 @@
|
||||
ALTER TABLE blocks
|
||||
ADD COLUMN workspace_id VARCHAR(36);
|
||||
|
||||
ALTER TABLE sharing
|
||||
ADD COLUMN workspace_id VARCHAR(36);
|
||||
|
||||
ALTER TABLE sessions
|
||||
ADD COLUMN auth_service VARCHAR(20);
|
@ -28,7 +28,7 @@ func (s *SQLStore) GetActiveUserCount(updatedSecondsAgo int64) (int, error) {
|
||||
|
||||
func (s *SQLStore) GetSession(token string, expireTime int64) (*model.Session, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("id", "token", "user_id", "props").
|
||||
Select("id", "token", "user_id", "auth_service", "props").
|
||||
From("sessions").
|
||||
Where(sq.Eq{"token": token}).
|
||||
Where(sq.Gt{"update_at": time.Now().Unix() - expireTime})
|
||||
@ -37,7 +37,7 @@ func (s *SQLStore) GetSession(token string, expireTime int64) (*model.Session, e
|
||||
session := model.Session{}
|
||||
|
||||
var propsBytes []byte
|
||||
err := row.Scan(&session.ID, &session.Token, &session.UserID, &propsBytes)
|
||||
err := row.Scan(&session.ID, &session.Token, &session.UserID, &session.AuthService, &propsBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -59,8 +59,8 @@ func (s *SQLStore) CreateSession(session *model.Session) error {
|
||||
}
|
||||
|
||||
query := s.getQueryBuilder().Insert("sessions").
|
||||
Columns("id", "token", "user_id", "props", "create_at", "update_at").
|
||||
Values(session.ID, session.Token, session.UserID, propsBytes, now, now)
|
||||
Columns("id", "token", "user_id", "auth_service", "props", "create_at", "update_at").
|
||||
Values(session.ID, session.Token, session.UserID, session.AuthService, propsBytes, now, now)
|
||||
|
||||
_, err = query.Exec()
|
||||
return err
|
||||
|
@ -4,11 +4,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
func (s *SQLStore) UpsertSharing(sharing model.Sharing) error {
|
||||
func (s *SQLStore) UpsertSharing(c store.Container, sharing model.Sharing) error {
|
||||
now := time.Now().Unix()
|
||||
|
||||
query := s.getQueryBuilder().
|
||||
@ -33,7 +34,7 @@ func (s *SQLStore) UpsertSharing(sharing model.Sharing) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetSharing(rootID string) (*model.Sharing, error) {
|
||||
func (s *SQLStore) GetSharing(c store.Container, rootID string) (*model.Sharing, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
"id",
|
||||
|
@ -3,18 +3,24 @@ package store
|
||||
|
||||
import "github.com/mattermost/focalboard/server/model"
|
||||
|
||||
// Conainer represents a container in a store
|
||||
// Using a struct to make extending this easier in the future
|
||||
type Container struct {
|
||||
WorkspaceID string
|
||||
}
|
||||
|
||||
// Store represents the abstraction of the data storage.
|
||||
type Store interface {
|
||||
GetBlocksWithParentAndType(parentID, blockType string) ([]model.Block, error)
|
||||
GetBlocksWithParent(parentID string) ([]model.Block, error)
|
||||
GetBlocksWithType(blockType string) ([]model.Block, error)
|
||||
GetSubTree2(blockID string) ([]model.Block, error)
|
||||
GetSubTree3(blockID string) ([]model.Block, error)
|
||||
GetAllBlocks() ([]model.Block, error)
|
||||
GetRootID(blockID string) (string, error)
|
||||
GetParentID(blockID string) (string, error)
|
||||
InsertBlock(block model.Block) error
|
||||
DeleteBlock(blockID, modifiedBy string) error
|
||||
GetBlocksWithParentAndType(c Container, parentID string, blockType string) ([]model.Block, error)
|
||||
GetBlocksWithParent(c Container, parentID string) ([]model.Block, error)
|
||||
GetBlocksWithType(c Container, blockType string) ([]model.Block, error)
|
||||
GetSubTree2(c Container, blockID string) ([]model.Block, error)
|
||||
GetSubTree3(c Container, blockID string) ([]model.Block, error)
|
||||
GetAllBlocks(c Container) ([]model.Block, error)
|
||||
GetRootID(c Container, blockID string) (string, error)
|
||||
GetParentID(c Container, blockID string) (string, error)
|
||||
InsertBlock(c Container, block model.Block) error
|
||||
DeleteBlock(c Container, blockID string, modifiedBy string) error
|
||||
|
||||
Shutdown() error
|
||||
|
||||
@ -38,8 +44,8 @@ type Store interface {
|
||||
DeleteSession(sessionId string) error
|
||||
CleanUpSessions(expireTime int64) error
|
||||
|
||||
UpsertSharing(sharing model.Sharing) error
|
||||
GetSharing(rootID string) (*model.Sharing, error)
|
||||
UpsertSharing(c Container, sharing model.Sharing) error
|
||||
GetSharing(c Container, rootID string) (*model.Sharing, error)
|
||||
|
||||
UpsertWorkspaceSignupToken(workspace model.Workspace) error
|
||||
UpsertWorkspaceSettings(workspace model.Workspace) error
|
||||
|
@ -10,42 +10,46 @@ import (
|
||||
)
|
||||
|
||||
func StoreTestBlocksStore(t *testing.T, setup func(t *testing.T) (store.Store, func())) {
|
||||
container := store.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
|
||||
t.Run("InsertBlock", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testInsertBlock(t, store)
|
||||
testInsertBlock(t, store, container)
|
||||
})
|
||||
t.Run("DeleteBlock", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testDeleteBlock(t, store)
|
||||
testDeleteBlock(t, store, container)
|
||||
})
|
||||
t.Run("GetSubTree2", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testGetSubTree2(t, store)
|
||||
testGetSubTree2(t, store, container)
|
||||
})
|
||||
t.Run("GetSubTree3", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testGetSubTree3(t, store)
|
||||
testGetSubTree3(t, store, container)
|
||||
})
|
||||
t.Run("GetParentID", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testGetParentID(t, store)
|
||||
testGetParentID(t, store, container)
|
||||
})
|
||||
t.Run("GetRootID", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testGetRootID(t, store)
|
||||
testGetRootID(t, store, container)
|
||||
})
|
||||
}
|
||||
|
||||
func testInsertBlock(t *testing.T, store store.Store) {
|
||||
func testInsertBlock(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -56,10 +60,10 @@ func testInsertBlock(t *testing.T, store store.Store) {
|
||||
ModifiedBy: userID,
|
||||
}
|
||||
|
||||
err := store.InsertBlock(block)
|
||||
err := store.InsertBlock(container, block)
|
||||
require.NoError(t, err)
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+1)
|
||||
})
|
||||
@ -71,10 +75,10 @@ func testInsertBlock(t *testing.T, store store.Store) {
|
||||
ModifiedBy: userID,
|
||||
}
|
||||
|
||||
err := store.InsertBlock(block)
|
||||
err := store.InsertBlock(container, block)
|
||||
require.Error(t, err)
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+1)
|
||||
})
|
||||
@ -87,19 +91,19 @@ func testInsertBlock(t *testing.T, store store.Store) {
|
||||
Fields: map[string]interface{}{"no-serialiable-value": t.Run},
|
||||
}
|
||||
|
||||
err := store.InsertBlock(block)
|
||||
err := store.InsertBlock(container, block)
|
||||
require.Error(t, err)
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+1)
|
||||
})
|
||||
}
|
||||
|
||||
func testGetSubTree2(t *testing.T, store store.Store) {
|
||||
func testGetSubTree2(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -141,14 +145,14 @@ func testGetSubTree2(t *testing.T, store store.Store) {
|
||||
},
|
||||
}
|
||||
|
||||
InsertBlocks(t, store, blocksToInsert)
|
||||
InsertBlocks(t, store, container, blocksToInsert)
|
||||
|
||||
blocks, err = store.GetAllBlocks()
|
||||
blocks, err = store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+6)
|
||||
|
||||
t.Run("from root id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree2("parent")
|
||||
blocks, err = store.GetSubTree2(container, "parent")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 3)
|
||||
require.True(t, ContainsBlockWithID(blocks, "parent"))
|
||||
@ -157,7 +161,7 @@ func testGetSubTree2(t *testing.T, store store.Store) {
|
||||
})
|
||||
|
||||
t.Run("from child id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree2("child1")
|
||||
blocks, err = store.GetSubTree2(container, "child1")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 2)
|
||||
require.True(t, ContainsBlockWithID(blocks, "child1"))
|
||||
@ -165,16 +169,16 @@ func testGetSubTree2(t *testing.T, store store.Store) {
|
||||
})
|
||||
|
||||
t.Run("from not existing id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree2("not-exists")
|
||||
blocks, err = store.GetSubTree2(container, "not-exists")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func testGetSubTree3(t *testing.T, store store.Store) {
|
||||
func testGetSubTree3(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -216,14 +220,14 @@ func testGetSubTree3(t *testing.T, store store.Store) {
|
||||
},
|
||||
}
|
||||
|
||||
InsertBlocks(t, store, blocksToInsert)
|
||||
InsertBlocks(t, store, container, blocksToInsert)
|
||||
|
||||
blocks, err = store.GetAllBlocks()
|
||||
blocks, err = store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+6)
|
||||
|
||||
t.Run("from root id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree3("parent")
|
||||
blocks, err = store.GetSubTree3(container, "parent")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 5)
|
||||
require.True(t, ContainsBlockWithID(blocks, "parent"))
|
||||
@ -234,7 +238,7 @@ func testGetSubTree3(t *testing.T, store store.Store) {
|
||||
})
|
||||
|
||||
t.Run("from child id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree3("child1")
|
||||
blocks, err = store.GetSubTree3(container, "child1")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 3)
|
||||
require.True(t, ContainsBlockWithID(blocks, "child1"))
|
||||
@ -243,16 +247,16 @@ func testGetSubTree3(t *testing.T, store store.Store) {
|
||||
})
|
||||
|
||||
t.Run("from not existing id", func(t *testing.T) {
|
||||
blocks, err = store.GetSubTree3("not-exists")
|
||||
blocks, err = store.GetSubTree3(container, "not-exists")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func testGetRootID(t *testing.T, store store.Store) {
|
||||
func testGetRootID(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -294,34 +298,34 @@ func testGetRootID(t *testing.T, store store.Store) {
|
||||
},
|
||||
}
|
||||
|
||||
InsertBlocks(t, store, blocksToInsert)
|
||||
InsertBlocks(t, store, container, blocksToInsert)
|
||||
|
||||
blocks, err = store.GetAllBlocks()
|
||||
blocks, err = store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+6)
|
||||
|
||||
t.Run("from root id", func(t *testing.T) {
|
||||
rootID, err := store.GetRootID("parent")
|
||||
rootID, err := store.GetRootID(container, "parent")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "parent", rootID)
|
||||
})
|
||||
|
||||
t.Run("from child id", func(t *testing.T) {
|
||||
rootID, err := store.GetRootID("child1")
|
||||
rootID, err := store.GetRootID(container, "child1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "parent", rootID)
|
||||
})
|
||||
|
||||
t.Run("from not existing id", func(t *testing.T) {
|
||||
_, err := store.GetRootID("not-exists")
|
||||
_, err := store.GetRootID(container, "not-exists")
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func testGetParentID(t *testing.T, store store.Store) {
|
||||
func testGetParentID(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -363,34 +367,34 @@ func testGetParentID(t *testing.T, store store.Store) {
|
||||
},
|
||||
}
|
||||
|
||||
InsertBlocks(t, store, blocksToInsert)
|
||||
InsertBlocks(t, store, container, blocksToInsert)
|
||||
|
||||
blocks, err = store.GetAllBlocks()
|
||||
blocks, err = store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+6)
|
||||
|
||||
t.Run("from root id", func(t *testing.T) {
|
||||
parentID, err := store.GetParentID("parent")
|
||||
parentID, err := store.GetParentID(container, "parent")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "", parentID)
|
||||
})
|
||||
|
||||
t.Run("from child id", func(t *testing.T) {
|
||||
parentID, err := store.GetParentID("grandchild1")
|
||||
parentID, err := store.GetParentID(container, "grandchild1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "child1", parentID)
|
||||
})
|
||||
|
||||
t.Run("from not existing id", func(t *testing.T) {
|
||||
_, err := store.GetParentID("not-exists")
|
||||
_, err := store.GetParentID(container, "not-exists")
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func testDeleteBlock(t *testing.T, store store.Store) {
|
||||
func testDeleteBlock(t *testing.T, store store.Store, container store.Container) {
|
||||
userID := "user-id"
|
||||
|
||||
blocks, err := store.GetAllBlocks()
|
||||
blocks, err := store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
initialCount := len(blocks)
|
||||
|
||||
@ -411,34 +415,34 @@ func testDeleteBlock(t *testing.T, store store.Store) {
|
||||
ModifiedBy: userID,
|
||||
},
|
||||
}
|
||||
InsertBlocks(t, store, blocksToInsert)
|
||||
InsertBlocks(t, store, container, blocksToInsert)
|
||||
|
||||
blocks, err = store.GetAllBlocks()
|
||||
blocks, err = store.GetAllBlocks(container)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, blocks, initialCount+3)
|
||||
|
||||
t.Run("exiting id", func(t *testing.T) {
|
||||
// Wait for not colliding the ID+insert_at key
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
err := store.DeleteBlock("block1", userID)
|
||||
err := store.DeleteBlock(container, "block1", userID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("exiting id multiple times", func(t *testing.T) {
|
||||
// Wait for not colliding the ID+insert_at key
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
err := store.DeleteBlock("block1", userID)
|
||||
err := store.DeleteBlock(container, "block1", userID)
|
||||
require.NoError(t, err)
|
||||
// Wait for not colliding the ID+insert_at key
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
err = store.DeleteBlock("block1", userID)
|
||||
err = store.DeleteBlock(container, "block1", userID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("from not existing id", func(t *testing.T) {
|
||||
// Wait for not colliding the ID+insert_at key
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
err := store.DeleteBlock("not-exists", userID)
|
||||
err := store.DeleteBlock(container, "not-exists", userID)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -8,16 +8,16 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func InsertBlocks(t *testing.T, s store.Store, blocks []model.Block) {
|
||||
func InsertBlocks(t *testing.T, s store.Store, container store.Container, blocks []model.Block) {
|
||||
for _, block := range blocks {
|
||||
err := s.InsertBlock(block)
|
||||
err := s.InsertBlock(container, block)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteBlocks(t *testing.T, s store.Store, blocks []model.Block, modifiedBy string) {
|
||||
func DeleteBlocks(t *testing.T, s store.Store, container store.Container, blocks []model.Block, modifiedBy string) {
|
||||
for _, block := range blocks {
|
||||
err := s.DeleteBlock(block.ID, modifiedBy)
|
||||
err := s.DeleteBlock(container, block.ID, modifiedBy)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
@ -9,14 +9,18 @@ import (
|
||||
)
|
||||
|
||||
func StoreTestSharingStore(t *testing.T, setup func(t *testing.T) (store.Store, func())) {
|
||||
container := store.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
|
||||
t.Run("UpsertSharingAndGetSharing", func(t *testing.T) {
|
||||
store, tearDown := setup(t)
|
||||
defer tearDown()
|
||||
testUpsertSharingAndGetSharing(t, store)
|
||||
testUpsertSharingAndGetSharing(t, store, container)
|
||||
})
|
||||
}
|
||||
|
||||
func testUpsertSharingAndGetSharing(t *testing.T, store store.Store) {
|
||||
func testUpsertSharingAndGetSharing(t *testing.T, store store.Store, container store.Container) {
|
||||
t.Run("Insert first sharing and get it", func(t *testing.T) {
|
||||
sharing := model.Sharing{
|
||||
ID: "sharing-id",
|
||||
@ -25,9 +29,9 @@ func testUpsertSharingAndGetSharing(t *testing.T, store store.Store) {
|
||||
ModifiedBy: "user-id",
|
||||
}
|
||||
|
||||
err := store.UpsertSharing(sharing)
|
||||
err := store.UpsertSharing(container, sharing)
|
||||
require.NoError(t, err)
|
||||
newSharing, err := store.GetSharing("sharing-id")
|
||||
newSharing, err := store.GetSharing(container, "sharing-id")
|
||||
require.NoError(t, err)
|
||||
newSharing.UpdateAt = 0
|
||||
require.Equal(t, sharing, *newSharing)
|
||||
@ -40,20 +44,20 @@ func testUpsertSharingAndGetSharing(t *testing.T, store store.Store) {
|
||||
ModifiedBy: "user-id2",
|
||||
}
|
||||
|
||||
newSharing, err := store.GetSharing("sharing-id")
|
||||
newSharing, err := store.GetSharing(container, "sharing-id")
|
||||
require.NoError(t, err)
|
||||
newSharing.UpdateAt = 0
|
||||
require.NotEqual(t, sharing, *newSharing)
|
||||
|
||||
err = store.UpsertSharing(sharing)
|
||||
err = store.UpsertSharing(container, sharing)
|
||||
require.NoError(t, err)
|
||||
newSharing, err = store.GetSharing("sharing-id")
|
||||
newSharing, err = store.GetSharing(container, "sharing-id")
|
||||
require.NoError(t, err)
|
||||
newSharing.UpdateAt = 0
|
||||
require.Equal(t, sharing, *newSharing)
|
||||
})
|
||||
t.Run("Get not existing sharing", func(t *testing.T) {
|
||||
_, err := store.GetSharing("not-existing")
|
||||
_, err := store.GetSharing(container, "not-existing")
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -88,6 +88,11 @@ definitions:
|
||||
description: The error message
|
||||
type: string
|
||||
x-go-name: Error
|
||||
errorCode:
|
||||
description: The error code
|
||||
format: int64
|
||||
type: integer
|
||||
x-go-name: ErrorCode
|
||||
type: object
|
||||
x-go-package: github.com/mattermost/focalboard/server/model
|
||||
FileUploadResponse:
|
||||
@ -286,152 +291,6 @@ info:
|
||||
title: Focalboard Server
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/api/v1/blocks:
|
||||
get:
|
||||
description: Returns blocks
|
||||
operationId: getBlocks
|
||||
parameters:
|
||||
- description: ID of parent block, omit to specify all blocks
|
||||
in: query
|
||||
name: parent_id
|
||||
type: string
|
||||
- description: Type of blocks to return, omit to specify all types
|
||||
in: query
|
||||
name: type
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Insert or update blocks
|
||||
operationId: updateBlocks
|
||||
parameters:
|
||||
- description: array of blocks to insert or update
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/{blockID}:
|
||||
delete:
|
||||
description: Deletes a block
|
||||
operationId: deleteBlock
|
||||
parameters:
|
||||
- description: ID of block to delete
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/{blockID}/subtree:
|
||||
get:
|
||||
description: Returns the blocks of a subtree
|
||||
operationId: getSubTree
|
||||
parameters:
|
||||
- description: The ID of the root block of the subtree
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
- description: The number of levels to return. 2 or 3. Defaults to 2.
|
||||
in: query
|
||||
maximum: 3
|
||||
minimum: 2
|
||||
name: l
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/export:
|
||||
get:
|
||||
description: Returns all blocks
|
||||
operationId: exportBlocks
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/blocks/import:
|
||||
post:
|
||||
description: Import blocks
|
||||
operationId: importBlocks
|
||||
parameters:
|
||||
- description: array of blocks to import
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/files:
|
||||
post:
|
||||
consumes:
|
||||
@ -504,55 +363,6 @@ paths:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
/api/v1/sharing/{rootID}:
|
||||
get:
|
||||
description: Returns sharing information for a root block
|
||||
operationId: getSharing
|
||||
parameters:
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Sets sharing information for a root block
|
||||
operationId: postSharing
|
||||
parameters:
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
- description: sharing information for a root block
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/users/{userID}:
|
||||
get:
|
||||
description: Returns a user
|
||||
@ -624,10 +434,16 @@ paths:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspace:
|
||||
/api/v1/workspaces/{workspaceID}:
|
||||
get:
|
||||
description: Returns information of the root workspace
|
||||
operationId: getWorkspace
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
@ -641,10 +457,252 @@ paths:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspace/regenerate_signup_token:
|
||||
/api/v1/workspaces/{workspaceID}/blocks:
|
||||
get:
|
||||
description: Returns blocks
|
||||
operationId: getBlocks
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: ID of parent block, omit to specify all blocks
|
||||
in: query
|
||||
name: parent_id
|
||||
type: string
|
||||
- description: Type of blocks to return, omit to specify all types
|
||||
in: query
|
||||
name: type
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Insert or update blocks
|
||||
operationId: updateBlocks
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: array of blocks to insert or update
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/blocks/{blockID}:
|
||||
delete:
|
||||
description: Deletes a block
|
||||
operationId: deleteBlock
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: ID of block to delete
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/blocks/{blockID}/subtree:
|
||||
get:
|
||||
description: Returns the blocks of a subtree
|
||||
operationId: getSubTree
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: The ID of the root block of the subtree
|
||||
in: path
|
||||
name: blockID
|
||||
required: true
|
||||
type: string
|
||||
- description: The number of levels to return. 2 or 3. Defaults to 2.
|
||||
in: query
|
||||
maximum: 3
|
||||
minimum: 2
|
||||
name: l
|
||||
type: integer
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/blocks/export:
|
||||
get:
|
||||
description: Returns all blocks
|
||||
operationId: exportBlocks
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/blocks/import:
|
||||
post:
|
||||
description: Import blocks
|
||||
operationId: importBlocks
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: array of blocks to import
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/Block'
|
||||
type: array
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/regenerate_signup_token:
|
||||
post:
|
||||
description: Regenerates the signup token for the root workspace
|
||||
operationId: regenerateSignupToken
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
/api/v1/workspaces/{workspaceID}/sharing/{rootID}:
|
||||
get:
|
||||
description: Returns sharing information for a root block
|
||||
operationId: getSharing
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: success
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
default:
|
||||
description: internal error
|
||||
schema:
|
||||
$ref: '#/definitions/ErrorResponse'
|
||||
security:
|
||||
- BearerAuth: []
|
||||
post:
|
||||
description: Sets sharing information for a root block
|
||||
operationId: postSharing
|
||||
parameters:
|
||||
- description: Workspace ID
|
||||
in: path
|
||||
name: workspaceID
|
||||
required: true
|
||||
type: string
|
||||
- description: ID of the root block
|
||||
in: path
|
||||
name: rootID
|
||||
required: true
|
||||
type: string
|
||||
- description: sharing information for a root block
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Sharing'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/mattermost/focalboard/server/auth"
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
)
|
||||
|
||||
// IsValidSessionToken authenticates session tokens
|
||||
@ -159,15 +160,31 @@ func (ws *Server) authenticateListener(wsSession *websocketSession, token, readT
|
||||
log.Printf("authenticateListener: Authenticated")
|
||||
}
|
||||
|
||||
func (ws *Server) getContainer(wsSession *websocketSession) (store.Container, error) {
|
||||
// TODO
|
||||
container := store.Container{
|
||||
WorkspaceID: "",
|
||||
}
|
||||
|
||||
return container, nil
|
||||
}
|
||||
|
||||
func (ws *Server) checkAuthentication(wsSession *websocketSession, command *WebsocketCommand) bool {
|
||||
if wsSession.isAuthenticated {
|
||||
return true
|
||||
}
|
||||
|
||||
container, err := ws.getContainer(wsSession)
|
||||
if err != nil {
|
||||
log.Printf("checkAuthentication: No container")
|
||||
sendError(wsSession.client, "No container")
|
||||
return false
|
||||
}
|
||||
|
||||
if len(command.ReadToken) > 0 {
|
||||
// Read token must be valid for all block IDs
|
||||
for _, blockID := range command.BlockIDs {
|
||||
isValid, _ := ws.auth.IsValidReadToken(blockID, command.ReadToken)
|
||||
isValid, _ := ws.auth.IsValidReadToken(container, blockID, command.ReadToken)
|
||||
if !isValid {
|
||||
return false
|
||||
}
|
||||
|
@ -11,9 +11,10 @@ import {
|
||||
|
||||
import {FlashMessages} from './components/flashMessages'
|
||||
import {getCurrentLanguage, getMessages, storeLanguage} from './i18n'
|
||||
import client from './octoClient'
|
||||
import {default as client} from './octoClient'
|
||||
import BoardPage from './pages/boardPage'
|
||||
import ChangePasswordPage from './pages/changePasswordPage'
|
||||
import ErrorPage from './pages/errorPage'
|
||||
import LoginPage from './pages/loginPage'
|
||||
import RegisterPage from './pages/registerPage'
|
||||
import {IUser, UserContext} from './user'
|
||||
@ -56,6 +57,9 @@ export default class App extends React.PureComponent<unknown, State> {
|
||||
<div id='frame'>
|
||||
<div id='main'>
|
||||
<Switch>
|
||||
<Route path='/error'>
|
||||
<ErrorPage/>
|
||||
</Route>
|
||||
<Route path='/login'>
|
||||
<LoginPage/>
|
||||
</Route>
|
||||
@ -67,17 +71,52 @@ export default class App extends React.PureComponent<unknown, State> {
|
||||
</Route>
|
||||
<Route path='/shared'>
|
||||
<BoardPage
|
||||
workspaceId='0'
|
||||
readonly={true}
|
||||
setLanguage={this.setAndStoreLanguage}
|
||||
/>
|
||||
</Route>
|
||||
<Route path='/board'>
|
||||
{this.state.initialLoad && !this.state.user && <Redirect to='login'/>}
|
||||
<BoardPage setLanguage={this.setAndStoreLanguage}/>
|
||||
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
|
||||
<BoardPage
|
||||
workspaceId='0'
|
||||
setLanguage={this.setAndStoreLanguage}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path='/workspace/:workspaceId/shared'
|
||||
render={({match}) => {
|
||||
return (
|
||||
<BoardPage
|
||||
workspaceId={match.params.workspaceId}
|
||||
readonly={true}
|
||||
setLanguage={this.setAndStoreLanguage}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Route
|
||||
path='/workspace/:workspaceId/'
|
||||
render={({match}) => {
|
||||
if (this.state.initialLoad && !this.state.user) {
|
||||
const redirectUrl = `/workspace/${match.params.workspaceId}/`
|
||||
const loginUrl = `/login?r=${encodeURIComponent(redirectUrl)}`
|
||||
return <Redirect to={loginUrl}/>
|
||||
}
|
||||
return (
|
||||
<BoardPage
|
||||
workspaceId={match.params.workspaceId}
|
||||
setLanguage={this.setAndStoreLanguage}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Route path='/'>
|
||||
{this.state.initialLoad && !this.state.user && <Redirect to='login'/>}
|
||||
<BoardPage setLanguage={this.setAndStoreLanguage}/>
|
||||
{this.state.initialLoad && !this.state.user && <Redirect to='/login'/>}
|
||||
<BoardPage
|
||||
workspaceId='0'
|
||||
setLanguage={this.setAndStoreLanguage}
|
||||
/>
|
||||
</Route>
|
||||
</Switch>
|
||||
</div>
|
||||
|
@ -14,12 +14,17 @@ class OctoClient {
|
||||
get token(): string {
|
||||
return localStorage.getItem('sessionId') || ''
|
||||
}
|
||||
set token(value: string) {
|
||||
localStorage.setItem('sessionId', value)
|
||||
}
|
||||
get readToken(): string {
|
||||
const queryString = new URLSearchParams(window.location.search)
|
||||
const readToken = queryString.get('r') || ''
|
||||
return readToken
|
||||
}
|
||||
|
||||
workspaceId = '0'
|
||||
|
||||
constructor(serverUrl?: string) {
|
||||
this.serverUrl = serverUrl || window.location.origin
|
||||
Utils.log(`OctoClient serverUrl: ${this.serverUrl}`)
|
||||
@ -92,6 +97,10 @@ class OctoClient {
|
||||
}
|
||||
}
|
||||
|
||||
private workspacePath() {
|
||||
return `/api/v1/workspaces/${this.workspaceId}`
|
||||
}
|
||||
|
||||
async getMe(): Promise<IUser | undefined> {
|
||||
const path = '/api/v1/users/me'
|
||||
const response = await fetch(this.serverUrl + path, {headers: this.headers()})
|
||||
@ -113,7 +122,7 @@ class OctoClient {
|
||||
}
|
||||
|
||||
async getSubtree(rootId?: string, levels = 2): Promise<IBlock[]> {
|
||||
let path = `/api/v1/blocks/${encodeURIComponent(rootId || '')}/subtree?l=${levels}`
|
||||
let path = this.workspacePath() + `/blocks/${encodeURIComponent(rootId || '')}/subtree?l=${levels}`
|
||||
if (this.readToken) {
|
||||
path += `&read_token=${this.readToken}`
|
||||
}
|
||||
@ -127,7 +136,7 @@ class OctoClient {
|
||||
}
|
||||
|
||||
async exportFullArchive(): Promise<IBlock[]> {
|
||||
const path = '/api/v1/blocks/export'
|
||||
const path = this.workspacePath() + '/blocks/export'
|
||||
const response = await fetch(this.serverUrl + path, {headers: this.headers()})
|
||||
if (response.status !== 200) {
|
||||
return []
|
||||
@ -144,7 +153,7 @@ class OctoClient {
|
||||
// Utils.log(`\t ${block.type}, ${block.id}`)
|
||||
// })
|
||||
const body = JSON.stringify(blocks)
|
||||
return fetch(this.serverUrl + '/api/v1/blocks/import', {
|
||||
return fetch(this.serverUrl + this.workspacePath() + '/blocks/import', {
|
||||
method: 'POST',
|
||||
headers: this.headers(),
|
||||
body,
|
||||
@ -154,15 +163,15 @@ class OctoClient {
|
||||
async getBlocksWithParent(parentId: string, type?: string): Promise<IBlock[]> {
|
||||
let path: string
|
||||
if (type) {
|
||||
path = `/api/v1/blocks?parent_id=${encodeURIComponent(parentId)}&type=${encodeURIComponent(type)}`
|
||||
path = this.workspacePath() + `/blocks?parent_id=${encodeURIComponent(parentId)}&type=${encodeURIComponent(type)}`
|
||||
} else {
|
||||
path = `/api/v1/blocks?parent_id=${encodeURIComponent(parentId)}`
|
||||
path = this.workspacePath() + `/blocks?parent_id=${encodeURIComponent(parentId)}`
|
||||
}
|
||||
return this.getBlocksWithPath(path)
|
||||
}
|
||||
|
||||
async getBlocksWithType(type: string): Promise<IBlock[]> {
|
||||
const path = `/api/v1/blocks?type=${encodeURIComponent(type)}`
|
||||
const path = this.workspacePath() + `/blocks?type=${encodeURIComponent(type)}`
|
||||
return this.getBlocksWithPath(path)
|
||||
}
|
||||
|
||||
@ -218,7 +227,7 @@ class OctoClient {
|
||||
|
||||
async deleteBlock(blockId: string): Promise<Response> {
|
||||
Utils.log(`deleteBlock: ${blockId}`)
|
||||
return fetch(this.serverUrl + `/api/v1/blocks/${encodeURIComponent(blockId)}`, {
|
||||
return fetch(this.serverUrl + this.workspacePath() + `/blocks/${encodeURIComponent(blockId)}`, {
|
||||
method: 'DELETE',
|
||||
headers: this.headers(),
|
||||
})
|
||||
@ -234,7 +243,7 @@ class OctoClient {
|
||||
Utils.log(`\t ${block.type}, ${block.id}, ${block.title?.substr(0, 50) || ''}`)
|
||||
})
|
||||
const body = JSON.stringify(blocks)
|
||||
return fetch(this.serverUrl + '/api/v1/blocks', {
|
||||
return fetch(this.serverUrl + this.workspacePath() + '/blocks', {
|
||||
method: 'POST',
|
||||
headers: this.headers(),
|
||||
body,
|
||||
@ -244,7 +253,7 @@ class OctoClient {
|
||||
// Sharing
|
||||
|
||||
async getSharing(rootId: string): Promise<ISharing | undefined> {
|
||||
const path = `/api/v1/sharing/${rootId}`
|
||||
const path = this.workspacePath() + `/sharing/${rootId}`
|
||||
const response = await fetch(this.serverUrl + path, {headers: this.headers()})
|
||||
if (response.status !== 200) {
|
||||
return undefined
|
||||
@ -254,7 +263,7 @@ class OctoClient {
|
||||
}
|
||||
|
||||
async setSharing(sharing: ISharing): Promise<boolean> {
|
||||
const path = `/api/v1/sharing/${sharing.id}`
|
||||
const path = this.workspacePath() + `/sharing/${sharing.id}`
|
||||
const body = JSON.stringify(sharing)
|
||||
const response = await fetch(
|
||||
this.serverUrl + path,
|
||||
@ -274,7 +283,7 @@ class OctoClient {
|
||||
// Workspace
|
||||
|
||||
async getWorkspace(): Promise<IWorkspace | undefined> {
|
||||
const path = '/api/v1/workspace'
|
||||
const path = this.workspacePath()
|
||||
const response = await fetch(this.serverUrl + path, {headers: this.headers()})
|
||||
if (response.status !== 200) {
|
||||
return undefined
|
||||
@ -284,7 +293,7 @@ class OctoClient {
|
||||
}
|
||||
|
||||
async regenerateWorkspaceSignupToken(): Promise<boolean> {
|
||||
const path = '/api/v1/workspace/regenerate_signup_token'
|
||||
const path = this.workspacePath() + '/regenerate_signup_token'
|
||||
const response = await fetch(this.serverUrl + path, {
|
||||
method: 'POST',
|
||||
headers: this.headers(),
|
||||
|
@ -7,6 +7,7 @@ import {IBlock} from '../blocks/block'
|
||||
import {sendFlashMessage} from '../components/flashMessages'
|
||||
import {WorkspaceComponent} from '../components/workspaceComponent'
|
||||
import mutator from '../mutator'
|
||||
import octoClient from '../octoClient'
|
||||
import {OctoListener} from '../octoListener'
|
||||
import {Utils} from '../utils'
|
||||
import {BoardTree, MutableBoardTree} from '../viewModel/boardTree'
|
||||
@ -15,6 +16,7 @@ import './boardPage.scss'
|
||||
|
||||
type Props = {
|
||||
readonly?: boolean
|
||||
workspaceId: string
|
||||
setLanguage: (lang: string) => void
|
||||
intl: IntlShape
|
||||
}
|
||||
@ -32,6 +34,7 @@ class BoardPage extends React.Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
const queryString = new URLSearchParams(window.location.search)
|
||||
let boardId = queryString.get('id') || ''
|
||||
let viewId = queryString.get('v') || ''
|
||||
@ -142,7 +145,10 @@ class BoardPage extends React.Component<Props, State> {
|
||||
const {intl} = this.props
|
||||
const {workspaceTree} = this.state
|
||||
|
||||
Utils.log(`BoardPage.render ${this.state.boardTree?.board?.title}`)
|
||||
Utils.log(`BoardPage.render (workspace ${this.props.workspaceId}) ${this.state.boardTree?.board?.title}`)
|
||||
|
||||
// TODO: Make this less brittle. This only works because this is the root render function
|
||||
octoClient.workspaceId = this.props.workspaceId
|
||||
|
||||
if (this.props.readonly && this.state.syncFailed) {
|
||||
Utils.log('BoardPage.render: sync failed')
|
||||
@ -196,6 +202,11 @@ class BoardPage extends React.Component<Props, State> {
|
||||
private async sync(boardId: string = this.state.boardId, viewId: string | undefined = this.state.viewId) {
|
||||
Utils.log(`sync start: ${boardId}`)
|
||||
|
||||
const workspace = await octoClient.getWorkspace()
|
||||
if (!workspace) {
|
||||
location.href = '/error?id=no_workspace'
|
||||
}
|
||||
|
||||
const workspaceTree = await MutableWorkspaceTree.sync()
|
||||
const boardIds = [...workspaceTree.boards.map((o) => o.id), ...workspaceTree.boardTemplates.map((o) => o.id)]
|
||||
this.setState({workspaceTree})
|
||||
|
41
webapp/src/pages/errorPage.scss
Normal file
41
webapp/src/pages/errorPage.scss
Normal file
@ -0,0 +1,41 @@
|
||||
.ErrorPage {
|
||||
border: 1px solid #cccccc;
|
||||
border-radius: 15px;
|
||||
width: 450px;
|
||||
height: 400px;
|
||||
margin: 150px auto;
|
||||
padding: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
box-shadow: rgba(var(--body-color), 0.1) 0px 0px 0px 1px, rgba(var(--body-color), 0.3) 0px 4px 8px;
|
||||
|
||||
@media screen and (max-width: 430px) {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: auto;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
> .Button {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 20px;
|
||||
min-height: 38px;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #900000;
|
||||
}
|
||||
}
|
24
webapp/src/pages/errorPage.tsx
Normal file
24
webapp/src/pages/errorPage.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react'
|
||||
|
||||
import {
|
||||
withRouter,
|
||||
RouteComponentProps,
|
||||
} from 'react-router-dom'
|
||||
|
||||
import './errorPage.scss'
|
||||
|
||||
type Props = RouteComponentProps
|
||||
|
||||
class ErrorPage extends React.PureComponent<Props> {
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<div className='ErrorPage'>
|
||||
<div className='title'>{'Error'}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default withRouter(ErrorPage)
|
Loading…
x
Reference in New Issue
Block a user