1
0
mirror of https://github.com/mattermost/focalboard.git synced 2025-07-12 23:50:27 +02:00

Logger for FocalBoard server (#466)

- structured, asynchronous logging
- supports discreet log levels, including custom levels
- supports output to console, files, and all common log aggregators.
- supports JSON, plain text and GELF formats
- lazy formatting and writing
This commit is contained in:
Doug Lauder
2021-05-29 02:23:10 -04:00
committed by GitHub
parent fe6b0d04b3
commit 417de9f837
29 changed files with 1150 additions and 275 deletions

View File

@ -5,7 +5,6 @@ import (
"encoding/json"
"errors"
"io/ioutil"
"log"
"net"
"net/http"
"strings"
@ -15,6 +14,7 @@ import (
serverContext "github.com/mattermost/focalboard/server/context"
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/auth"
"github.com/mattermost/focalboard/server/services/mlog"
)
// LoginRequest is a login request
@ -154,32 +154,32 @@ func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
if len(a.singleUserToken) > 0 {
// Not permitted in single-user mode
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
var loginData LoginRequest
err = json.Unmarshal(requestBody, &loginData)
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
if loginData.Type == "normal" {
token, err := a.app().Login(loginData.Username, loginData.Email, loginData.Password, loginData.MfaToken)
if err != nil {
errorResponse(w, http.StatusUnauthorized, "incorrect login", err)
a.errorResponse(w, http.StatusUnauthorized, "incorrect login", err)
return
}
json, err := json.Marshal(LoginResponse{Token: token})
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
@ -187,7 +187,7 @@ func (a *API) handleLogin(w http.ResponseWriter, r *http.Request) {
return
}
errorResponse(w, http.StatusBadRequest, "invalid login type", nil)
a.errorResponse(w, http.StatusBadRequest, "invalid login type", nil)
}
func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
@ -217,20 +217,20 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
if len(a.singleUserToken) > 0 {
// Not permitted in single-user mode
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
var registerData RegisterRequest
err = json.Unmarshal(requestBody, &registerData)
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
@ -238,35 +238,35 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
if len(registerData.Token) > 0 {
workspace, err := a.app().GetRootWorkspace()
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
if registerData.Token != workspace.SignupToken {
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
} else {
// No signup token, check if no active users
userCount, err := a.app().GetRegisteredUserCount()
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
if userCount > 0 {
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
}
if err = registerData.IsValid(); err != nil {
errorResponse(w, http.StatusBadRequest, err.Error(), err)
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
}
err = a.app().RegisterUser(registerData.Username, registerData.Email, registerData.Password)
if err != nil {
errorResponse(w, http.StatusBadRequest, err.Error(), err)
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
}
@ -309,7 +309,7 @@ func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
if len(a.singleUserToken) > 0 {
// Not permitted in single-user mode
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
@ -318,23 +318,23 @@ func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
var requestData ChangePasswordRequest
if err := json.Unmarshal(requestBody, &requestData); err != nil {
errorResponse(w, http.StatusInternalServerError, "", err)
a.errorResponse(w, http.StatusInternalServerError, "", err)
return
}
if err = requestData.IsValid(); err != nil {
errorResponse(w, http.StatusBadRequest, err.Error(), err)
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
}
if err = a.app().ChangePassword(userID, requestData.OldPassword, requestData.NewPassword); err != nil {
errorResponse(w, http.StatusBadRequest, err.Error(), err)
a.errorResponse(w, http.StatusBadRequest, err.Error(), err)
return
}
@ -349,10 +349,10 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
return func(w http.ResponseWriter, r *http.Request) {
token, _ := auth.ParseAuthTokenFromRequest(r)
log.Printf(`Single User: %v`, len(a.singleUserToken) > 0)
a.logger.Debug(`attachSession`, mlog.Bool("single_user", len(a.singleUserToken) > 0))
if len(a.singleUserToken) > 0 {
if required && (token != a.singleUserToken) {
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}
@ -391,7 +391,7 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
session, err := a.app().GetSession(token)
if err != nil {
if required {
errorResponse(w, http.StatusUnauthorized, "", err)
a.errorResponse(w, http.StatusUnauthorized, "", err)
return
}
@ -401,8 +401,12 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
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)
a.logger.Error(`Session authService mismatch`,
mlog.String("sessionID", session.ID),
mlog.String("want", a.authService),
mlog.String("got", authService),
)
a.errorResponse(w, http.StatusUnauthorized, "", err)
return
}
@ -416,7 +420,7 @@ func (a *API) adminRequired(handler func(w http.ResponseWriter, r *http.Request)
// Currently, admin APIs require local unix connections
conn := serverContext.GetContextConn(r)
if _, isUnix := conn.(*net.UnixConn); !isUnix {
errorResponse(w, http.StatusUnauthorized, "", nil)
a.errorResponse(w, http.StatusUnauthorized, "", nil)
return
}