1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-01-05 14:50:29 +02:00

Refactor App lifecycle (#590)

* remove Server dep from App

* remove appbuilder
This commit is contained in:
Doug Lauder 2021-06-18 10:03:42 -04:00 committed by GitHub
parent ddfae3266a
commit edc3eb7e8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 56 deletions

View File

@ -41,7 +41,7 @@ func (a *API) handleAdminSetPassword(w http.ResponseWriter, r *http.Request) {
return
}
err = a.app().UpdateUserPassword(username, requestData.Password)
err = a.app.UpdateUserPassword(username, requestData.Password)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return

View File

@ -35,7 +35,7 @@ const (
// REST APIs
type API struct {
appBuilder func() *app.App
app *app.App
authService string
singleUserToken string
MattermostAuth bool
@ -43,9 +43,9 @@ type API struct {
audit *audit.Audit
}
func NewAPI(appBuilder func() *app.App, singleUserToken string, authService string, logger *mlog.Logger, audit *audit.Audit) *API {
func NewAPI(app *app.App, singleUserToken string, authService string, logger *mlog.Logger, audit *audit.Audit) *API {
return &API{
appBuilder: appBuilder,
app: app,
singleUserToken: singleUserToken,
authService: authService,
logger: logger,
@ -53,10 +53,6 @@ func NewAPI(appBuilder func() *app.App, singleUserToken string, authService stri
}
}
func (a *API) app() *app.App {
return a.appBuilder()
}
func (a *API) RegisterRoutes(r *mux.Router) {
apiv1 := r.PathPrefix("/api/v1").Subrouter()
apiv1.Use(a.requireCSRFToken)
@ -126,7 +122,7 @@ func (a *API) hasValidReadTokenForBlock(r *http.Request, container store.Contain
return false
}
isValid, err := a.app().IsValidReadToken(container, blockID, readToken)
isValid, err := a.app.IsValidReadToken(container, blockID, readToken)
if err != nil {
a.logger.Error("IsValidReadToken ERROR", mlog.Err(err))
return false
@ -153,7 +149,7 @@ func (a *API) getContainerAllowingReadTokenForBlock(r *http.Request, blockID str
}
// Has session and access to workspace
if session != nil && a.app().DoesUserHaveWorkspaceAccess(session.UserID, container.WorkspaceID) {
if session != nil && a.app.DoesUserHaveWorkspaceAccess(session.UserID, container.WorkspaceID) {
return &container, nil
}
@ -239,7 +235,7 @@ func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
auditRec.AddMeta("parentID", parentID)
auditRec.AddMeta("blockType", blockType)
blocks, err := a.app().GetBlocks(*container, parentID, blockType)
blocks, err := a.app.GetBlocks(*container, parentID, blockType)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -358,7 +354,7 @@ func (a *API) handlePostBlocks(w http.ResponseWriter, r *http.Request) {
stampModifiedByUser(r, blocks, auditRec)
err = a.app().InsertBlocks(*container, blocks)
err = a.app.InsertBlocks(*container, blocks)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -404,7 +400,7 @@ func (a *API) handleGetUser(w http.ResponseWriter, r *http.Request) {
defer a.audit.LogRecord(audit.LevelRead, auditRec)
auditRec.AddMeta("userID", userID)
user, err := a.app().GetUser(userID)
user, err := a.app.GetUser(userID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -458,7 +454,7 @@ func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) {
UpdateAt: now,
}
} else {
user, err = a.app().GetUser(session.UserID)
user, err = a.app.GetUser(session.UserID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -523,7 +519,7 @@ func (a *API) handleDeleteBlock(w http.ResponseWriter, r *http.Request) {
defer a.audit.LogRecord(audit.LevelModify, auditRec)
auditRec.AddMeta("blockID", blockID)
err = a.app().DeleteBlock(*container, blockID, userID)
err = a.app.DeleteBlock(*container, blockID, userID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -600,7 +596,7 @@ func (a *API) handleGetSubTree(w http.ResponseWriter, r *http.Request) {
defer a.audit.LogRecord(audit.LevelRead, auditRec)
auditRec.AddMeta("blockID", blockID)
blocks, err := a.app().GetSubTree(*container, blockID, int(levels))
blocks, err := a.app.GetSubTree(*container, blockID, int(levels))
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -665,9 +661,9 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
blocks := []model.Block{}
if rootID == "" {
blocks, err = a.app().GetAllBlocks(*container)
blocks, err = a.app.GetAllBlocks(*container)
} else {
blocks, err = a.app().GetBlocksWithRootID(*container, rootID)
blocks, err = a.app.GetBlocksWithRootID(*container, rootID)
}
a.logger.Debug("raw blocks", mlog.Int("block_count", len(blocks)))
@ -790,7 +786,7 @@ func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
stampModifiedByUser(r, blocks, auditRec)
err = a.app().InsertBlocks(*container, blocks)
err = a.app.InsertBlocks(*container, blocks)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -849,7 +845,7 @@ func (a *API) handleGetSharing(w http.ResponseWriter, r *http.Request) {
defer a.audit.LogRecord(audit.LevelRead, auditRec)
auditRec.AddMeta("rootID", rootID)
sharing, err := a.app().GetSharing(*container, rootID)
sharing, err := a.app.GetSharing(*container, rootID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -945,7 +941,7 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
}
sharing.ModifiedBy = userID
err = a.app().UpsertSharing(*container, sharing)
err = a.app.UpsertSharing(*container, sharing)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -994,12 +990,12 @@ func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session := ctx.Value("session").(*model.Session)
if !a.app().DoesUserHaveWorkspaceAccess(session.UserID, workspaceID) {
if !a.app.DoesUserHaveWorkspaceAccess(session.UserID, workspaceID) {
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
workspace, err = a.app().GetWorkspace(workspaceID)
workspace, err = a.app.GetWorkspace(workspaceID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
}
@ -1008,7 +1004,7 @@ func (a *API) handleGetWorkspace(w http.ResponseWriter, r *http.Request) {
return
}
} else {
workspace, err = a.app().GetRootWorkspace()
workspace, err = a.app.GetRootWorkspace()
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -1053,7 +1049,7 @@ func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r
// schema:
// "$ref": "#/definitions/ErrorResponse"
workspace, err := a.app().GetRootWorkspace()
workspace, err := a.app.GetRootWorkspace()
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -1064,7 +1060,7 @@ func (a *API) handlePostWorkspaceRegenerateSignupToken(w http.ResponseWriter, r
workspace.SignupToken = utils.CreateGUID()
err = a.app().UpsertWorkspaceSignupToken(*workspace)
err = a.app.UpsertWorkspaceSignupToken(*workspace)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -1138,7 +1134,7 @@ func (a *API) handleServeFile(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", contentType)
fileReader, err := a.app().GetFileReader(workspaceID, rootID, filename)
fileReader, err := a.app.GetFileReader(workspaceID, rootID, filename)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -1217,7 +1213,7 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
auditRec.AddMeta("rootID", rootID)
auditRec.AddMeta("filename", handle.Filename)
fileId, err := a.app().SaveFile(file, workspaceID, rootID, handle.Filename)
fileId, err := a.app.SaveFile(file, workspaceID, rootID, handle.Filename)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -1272,7 +1268,7 @@ func (a *API) getWorkspaceUsers(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
session := ctx.Value("session").(*model.Session)
if !a.app().DoesUserHaveWorkspaceAccess(session.UserID, workspaceID) {
if !a.app.DoesUserHaveWorkspaceAccess(session.UserID, workspaceID) {
a.errorResponse(w, http.StatusForbidden, "Access denied to workspace", errors.New("Access denied to workspace"))
return
}
@ -1280,7 +1276,7 @@ func (a *API) getWorkspaceUsers(w http.ResponseWriter, r *http.Request) {
auditRec := a.makeAuditRecord(r, "getUsers", audit.Fail)
defer a.audit.LogRecord(audit.LevelRead, auditRec)
users, err := a.app().GetWorkspaceUsers(workspaceID)
users, err := a.app.GetWorkspaceUsers(workspaceID)
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return

View File

@ -178,7 +178,7 @@ func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
auditRec.AddMeta("type", loginData.Type)
if loginData.Type == "normal" {
token, err := a.app().Login(loginData.Username, loginData.Email, loginData.Password, loginData.MfaToken)
token, err := a.app.Login(loginData.Username, loginData.Email, loginData.Password, loginData.MfaToken)
if err != nil {
a.errorResponse(w, http.StatusUnauthorized, "incorrect login", err)
return
@ -243,7 +243,7 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
// Validate token
if len(registerData.Token) > 0 {
workspace, err := a.app().GetRootWorkspace()
workspace, err := a.app.GetRootWorkspace()
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -255,7 +255,7 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
}
} else {
// No signup token, check if no active users
userCount, err := a.app().GetRegisteredUserCount()
userCount, err := a.app.GetRegisteredUserCount()
if err != nil {
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
@ -275,7 +275,7 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
defer a.audit.LogRecord(audit.LevelAuth, auditRec)
auditRec.AddMeta("username", registerData.Username)
err = a.app().RegisterUser(registerData.Username, registerData.Email, registerData.Password)
err = a.app.RegisterUser(registerData.Username, registerData.Email, registerData.Password)
if err != nil {
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
@ -348,7 +348,7 @@ func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
auditRec := a.makeAuditRecord(r, "changePassword", audit.Fail)
defer a.audit.LogRecord(audit.LevelAuth, auditRec)
if err = a.app().ChangePassword(userID, requestData.OldPassword, requestData.NewPassword); err != nil {
if err = a.app.ChangePassword(userID, requestData.OldPassword, requestData.NewPassword); err != nil {
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
}
@ -404,7 +404,7 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
return
}
session, err := a.app().GetSession(token)
session, err := a.app.GetSession(token)
if err != nil {
if required {
a.errorResponse(w, http.StatusUnauthorized, "", err)

View File

@ -2,16 +2,21 @@ package app
import (
"github.com/mattermost/focalboard/server/auth"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/config"
"github.com/mattermost/focalboard/server/services/metrics"
"github.com/mattermost/focalboard/server/services/mlog"
"github.com/mattermost/focalboard/server/services/store"
"github.com/mattermost/focalboard/server/services/webhook"
"github.com/mattermost/focalboard/server/ws"
"github.com/mattermost/mattermost-server/v5/shared/filestore"
)
type WebsocketServer interface {
BroadcastBlockChange(workspaceID string, block model.Block)
BroadcastBlockDelete(workspaceID, blockID, parentID string)
}
type Services struct {
Auth *auth.Auth
Store store.Store
@ -25,14 +30,14 @@ type App struct {
config *config.Configuration
store store.Store
auth *auth.Auth
wsServer *ws.Server
wsServer WebsocketServer
filesBackend filestore.FileBackend
webhook *webhook.Client
metrics *metrics.Metrics
logger *mlog.Logger
}
func New(config *config.Configuration, wsServer *ws.Server, services Services) *App {
func New(config *config.Configuration, wsServer WebsocketServer, services Services) *App {
return &App{
config: config,
store: services.Store,

View File

@ -63,7 +63,6 @@ type Server struct {
localRouter *mux.Router
localModeServer *http.Server
api *api.API
appBuilder func() *app.App
}
func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger) (*Server, error) {
@ -132,16 +131,16 @@ func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger)
Metrics: metricsService,
Logger: logger,
}
appBuilder := func() *app.App { return app.New(cfg, wsServer, appServices) }
app := app.New(cfg, wsServer, appServices)
focalboardAPI := api.NewAPI(appBuilder, singleUserToken, cfg.AuthMode, logger, auditService)
focalboardAPI := api.NewAPI(app, singleUserToken, cfg.AuthMode, logger, auditService)
// Local router for admin APIs
localRouter := mux.NewRouter()
focalboardAPI.RegisterAdminRoutes(localRouter)
// Init workspace
if _, err = appBuilder().GetRootWorkspace(); err != nil {
if _, err = app.GetRootWorkspace(); err != nil {
logger.Error("Unable to get root workspace", mlog.Err(err))
return nil, err
}
@ -164,7 +163,7 @@ func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger)
}
}
telemetryOpts := telemetryOptions{
appBuilder: appBuilder,
app: app,
cfg: cfg,
telemetryID: telemetryID,
logger: logger,
@ -185,7 +184,6 @@ func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger)
logger: logger,
localRouter: localRouter,
api: focalboardAPI,
appBuilder: appBuilder,
}
server.initHandlers()
@ -219,8 +217,7 @@ func (s *Server) Start() error {
}, cleanupSessionTaskFrequency)
metricsUpdater := func() {
app := s.appBuilder()
blockCounts, err := app.GetBlockCountsByType()
blockCounts, err := s.store.GetBlockCountsByType()
if err != nil {
s.logger.Error("Error updating metrics", mlog.String("group", "blocks"), mlog.Err(err))
return
@ -229,7 +226,7 @@ func (s *Server) Start() error {
for blockType, count := range blockCounts {
s.metricsService.ObserveBlockCount(blockType, count)
}
workspaceCount, err := app.GetWorkspaceCount()
workspaceCount, err := s.store.GetWorkspaceCount()
if err != nil {
s.logger.Error("Error updating metrics", mlog.String("group", "workspaces"), mlog.Err(err))
return
@ -237,7 +234,7 @@ func (s *Server) Start() error {
s.logger.Log(mlog.Metrics, "Workspace metrics collected", mlog.Int64("workspace_count", workspaceCount))
s.metricsService.ObserveWorkspaceCount(workspaceCount)
}
//metricsUpdater() Calling this immediately causes integration unit tests to fail.
// metricsUpdater() Calling this immediately causes integration unit tests to fail.
s.metricsUpdaterTask = scheduler.CreateRecurringTask("updateMetrics", metricsUpdater, updateMetricsTaskFrequency)
if s.config.Telemetry {
@ -351,7 +348,7 @@ func (s *Server) SetWSHub(hub ws.Hub) {
}
type telemetryOptions struct {
appBuilder func() *app.App
app *app.App
cfg *config.Configuration
telemetryID string
logger *mlog.Logger
@ -383,29 +380,29 @@ func initTelemetry(opts telemetryOptions) *telemetry.Service {
m := make(map[string]interface{})
var count int
var err error
if count, err = opts.appBuilder().GetRegisteredUserCount(); err != nil {
if count, err = opts.app.GetRegisteredUserCount(); err != nil {
return nil, err
}
m["registered_users"] = count
if count, err = opts.appBuilder().GetDailyActiveUsers(); err != nil {
if count, err = opts.app.GetDailyActiveUsers(); err != nil {
return nil, err
}
m["daily_active_users"] = count
if count, err = opts.appBuilder().GetWeeklyActiveUsers(); err != nil {
if count, err = opts.app.GetWeeklyActiveUsers(); err != nil {
return nil, err
}
m["weekly_active_users"] = count
if count, err = opts.appBuilder().GetMonthlyActiveUsers(); err != nil {
if count, err = opts.app.GetMonthlyActiveUsers(); err != nil {
return nil, err
}
m["monthly_active_users"] = count
return m, nil
})
telemetryService.RegisterTracker("blocks", func() (telemetry.Tracker, error) {
blockCounts, err := opts.appBuilder().GetBlockCountsByType()
blockCounts, err := opts.app.GetBlockCountsByType()
if err != nil {
return nil, err
}
@ -416,7 +413,7 @@ func initTelemetry(opts telemetryOptions) *telemetry.Service {
return m, nil
})
telemetryService.RegisterTracker("workspaces", func() (telemetry.Tracker, error) {
count, err := opts.appBuilder().GetWorkspaceCount()
count, err := opts.app.GetWorkspaceCount()
if err != nil {
return nil, err
}