mirror of
https://github.com/mattermost/focalboard.git
synced 2024-11-24 08:22:29 +02:00
First pass linter cleanup (#603)
* first pass linter cleanup * address review comments
This commit is contained in:
parent
c4154cd2dd
commit
66975bdfe9
@ -12,10 +12,14 @@ linters-settings:
|
||||
enable-all: true
|
||||
disable:
|
||||
- fieldalignment
|
||||
lll:
|
||||
line-length: 150
|
||||
gomnd:
|
||||
ignored-numbers: 10
|
||||
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
@ -43,10 +47,10 @@ linters:
|
||||
- goconst
|
||||
- gocritic
|
||||
- godot
|
||||
- goerr113
|
||||
# - goerr113
|
||||
- goheader
|
||||
- golint
|
||||
- gomnd
|
||||
# - gomnd
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosimple
|
||||
|
@ -1,7 +1,6 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -22,13 +21,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
HEADER_REQUESTED_WITH = "X-Requested-With"
|
||||
HEADER_REQUESTED_WITH_XML = "XMLHttpRequest"
|
||||
HeaderRequestedWith = "X-Requested-With"
|
||||
HeaderRequestedWithXML = "XMLHttpRequest"
|
||||
SingleUser = "single-user"
|
||||
)
|
||||
|
||||
const (
|
||||
ERROR_NO_WORKSPACE_CODE = 1000
|
||||
ERROR_NO_WORKSPACE_MESSAGE = "No workspace"
|
||||
ErrorNoWorkspaceCode = 1000
|
||||
ErrorNoWorkspaceMessage = "No workspace"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------------------------------------
|
||||
@ -105,13 +105,8 @@ func (a *API) requireCSRFToken(next http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
func (a *API) checkCSRFToken(r *http.Request) bool {
|
||||
token := r.Header.Get(HEADER_REQUESTED_WITH)
|
||||
|
||||
if token == HEADER_REQUESTED_WITH_XML {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
token := r.Header.Get(HeaderRequestedWith)
|
||||
return token == HeaderRequestedWithXML
|
||||
}
|
||||
|
||||
func (a *API) hasValidReadTokenForBlock(r *http.Request, container store.Container, blockID string) bool {
|
||||
@ -158,7 +153,7 @@ func (a *API) getContainerAllowingReadTokenForBlock(r *http.Request, blockID str
|
||||
return &container, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("Access denied to workspace")
|
||||
return nil, errors.New("access denied to workspace")
|
||||
}
|
||||
|
||||
// Native auth: always use root workspace
|
||||
@ -176,7 +171,7 @@ func (a *API) getContainerAllowingReadTokenForBlock(r *http.Request, blockID str
|
||||
return &container, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("Access denied to workspace")
|
||||
return nil, errors.New("access denied to workspace")
|
||||
}
|
||||
|
||||
func (a *API) getContainer(r *http.Request) (*store.Container, error) {
|
||||
@ -263,7 +258,7 @@ func stampModifiedByUser(r *http.Request, blocks []model.Block, auditRec *audit.
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
userID := session.UserID
|
||||
if userID == "single-user" {
|
||||
if userID == SingleUser {
|
||||
userID = ""
|
||||
}
|
||||
|
||||
@ -444,12 +439,12 @@ func (a *API) handleGetMe(w http.ResponseWriter, r *http.Request) {
|
||||
auditRec := a.makeAuditRecord(r, "getMe", audit.Fail)
|
||||
defer a.audit.LogRecord(audit.LevelRead, auditRec)
|
||||
|
||||
if session.UserID == "single-user" {
|
||||
if session.UserID == SingleUser {
|
||||
now := time.Now().Unix()
|
||||
user = &model.User{
|
||||
ID: "single-user",
|
||||
Username: "single-user",
|
||||
Email: "single-user",
|
||||
ID: SingleUser,
|
||||
Username: SingleUser,
|
||||
Email: SingleUser,
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
}
|
||||
@ -659,12 +654,16 @@ func (a *API) handleExport(w http.ResponseWriter, r *http.Request) {
|
||||
defer a.audit.LogRecord(audit.LevelRead, auditRec)
|
||||
auditRec.AddMeta("rootID", rootID)
|
||||
|
||||
blocks := []model.Block{}
|
||||
var blocks []model.Block
|
||||
if rootID == "" {
|
||||
blocks, err = a.app.GetAllBlocks(*container)
|
||||
} else {
|
||||
blocks, err = a.app.GetBlocksWithRootID(*container, rootID)
|
||||
}
|
||||
if err != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
|
||||
a.logger.Debug("raw blocks", mlog.Int("block_count", len(blocks)))
|
||||
auditRec.AddMeta("rawCount", len(blocks))
|
||||
@ -720,15 +719,6 @@ func filterOrphanBlocks(blocks []model.Block) (ret []model.Block) {
|
||||
return blocks
|
||||
}
|
||||
|
||||
func arrayContainsBlockWithID(array []model.Block, blockID string) bool {
|
||||
for _, item := range array {
|
||||
if item.ID == blockID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *API) handleImport(w http.ResponseWriter, r *http.Request) {
|
||||
// swagger:operation POST /api/v1/workspaces/{workspaceID}/blocks/import importBlocks
|
||||
//
|
||||
@ -936,7 +926,7 @@ func (a *API) handlePostSharing(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session := ctx.Value("session").(*model.Session)
|
||||
userID := session.UserID
|
||||
if userID == "single-user" {
|
||||
if userID == SingleUser {
|
||||
userID = ""
|
||||
}
|
||||
sharing.ModifiedBy = userID
|
||||
@ -1213,7 +1203,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
|
||||
@ -1221,9 +1211,9 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
a.logger.Debug("uploadFile",
|
||||
mlog.String("filename", handle.Filename),
|
||||
mlog.String("fileID", fileId),
|
||||
mlog.String("fileID", fileID),
|
||||
)
|
||||
data, err := json.Marshal(FileUploadResponse{FileID: fileId})
|
||||
data, err := json.Marshal(FileUploadResponse{FileID: fileID})
|
||||
if err != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
@ -1231,7 +1221,7 @@ func (a *API) handleUploadFile(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, data)
|
||||
|
||||
auditRec.AddMeta("fileID", fileId)
|
||||
auditRec.AddMeta("fileID", fileID)
|
||||
auditRec.Success()
|
||||
}
|
||||
|
||||
@ -1269,7 +1259,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) {
|
||||
a.errorResponse(w, http.StatusForbidden, "Access denied to workspace", errors.New("Access denied to workspace"))
|
||||
a.errorResponse(w, http.StatusForbidden, "Access denied to workspace", errors.New("access denied to workspace"))
|
||||
return
|
||||
}
|
||||
|
||||
@ -1307,7 +1297,7 @@ func (a *API) errorResponse(w http.ResponseWriter, code int, message string, sou
|
||||
data = []byte("{}")
|
||||
}
|
||||
w.WriteHeader(code)
|
||||
w.Write(data)
|
||||
_, _ = w.Write(data)
|
||||
}
|
||||
|
||||
func (a *API) errorResponseWithCode(w http.ResponseWriter, statusCode int, errorCode int, message string, sourceError error) {
|
||||
@ -1322,27 +1312,21 @@ func (a *API) errorResponseWithCode(w http.ResponseWriter, statusCode int, error
|
||||
data = []byte("{}")
|
||||
}
|
||||
w.WriteHeader(statusCode)
|
||||
w.Write(data)
|
||||
_, _ = w.Write(data)
|
||||
}
|
||||
|
||||
func (a *API) noContainerErrorResponse(w http.ResponseWriter, sourceError error) {
|
||||
a.errorResponseWithCode(w, http.StatusBadRequest, ERROR_NO_WORKSPACE_CODE, ERROR_NO_WORKSPACE_MESSAGE, sourceError)
|
||||
a.errorResponseWithCode(w, http.StatusBadRequest, ErrorNoWorkspaceCode, ErrorNoWorkspaceMessage, sourceError)
|
||||
}
|
||||
|
||||
func jsonStringResponse(w http.ResponseWriter, code int, message string) {
|
||||
func jsonStringResponse(w http.ResponseWriter, code int, message string) { //nolint:unparam
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(code)
|
||||
fmt.Fprint(w, message)
|
||||
}
|
||||
|
||||
func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) {
|
||||
func jsonBytesResponse(w http.ResponseWriter, code int, json []byte) { //nolint:unparam
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(code)
|
||||
w.Write(json)
|
||||
}
|
||||
|
||||
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)
|
||||
next.ServeHTTP(rw, req)
|
||||
_, _ = w.Write(json)
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
// makeAuditRecord creates an audit record pre-populated with data from the request.
|
||||
func (a *API) makeAuditRecord(r *http.Request, event string, initialStatus string) *audit.Record {
|
||||
func (a *API) makeAuditRecord(r *http.Request, event string, initialStatus string) *audit.Record { //nolint:unparam
|
||||
ctx := r.Context()
|
||||
var sessionID string
|
||||
var userID string
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -18,6 +19,10 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
MinimumPasswordLength = 8
|
||||
)
|
||||
|
||||
// LoginRequest is a login request
|
||||
// swagger:model
|
||||
type LoginRequest struct {
|
||||
@ -102,13 +107,13 @@ type ChangePasswordRequest struct {
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
||||
// IsValid validates a password change request
|
||||
// IsValid validates a password change request.
|
||||
func (rd *ChangePasswordRequest) IsValid() error {
|
||||
if rd.OldPassword == "" {
|
||||
return errors.New("Old password is required")
|
||||
return errors.New("old password is required")
|
||||
}
|
||||
if rd.NewPassword == "" {
|
||||
return errors.New("New password is required")
|
||||
return errors.New("new password is required")
|
||||
}
|
||||
if err := isValidPassword(rd.NewPassword); err != nil {
|
||||
return err
|
||||
@ -118,8 +123,8 @@ func (rd *ChangePasswordRequest) IsValid() error {
|
||||
}
|
||||
|
||||
func isValidPassword(password string) error {
|
||||
if len(password) < 8 {
|
||||
return errors.New("Password must be at least 8 characters")
|
||||
if len(password) < MinimumPasswordLength {
|
||||
return fmt.Errorf("password must be at least %d characters", MinimumPasswordLength)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -243,9 +248,9 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Validate token
|
||||
if len(registerData.Token) > 0 {
|
||||
workspace, err := a.app.GetRootWorkspace()
|
||||
if err != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
workspace, err2 := a.app.GetRootWorkspace()
|
||||
if err2 != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err2)
|
||||
return
|
||||
}
|
||||
|
||||
@ -255,9 +260,9 @@ func (a *API) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
} else {
|
||||
// No signup token, check if no active users
|
||||
userCount, err := a.app.GetRegisteredUserCount()
|
||||
if err != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
userCount, err2 := a.app.GetRegisteredUserCount()
|
||||
if err2 != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err2)
|
||||
return
|
||||
}
|
||||
if userCount > 0 {
|
||||
@ -335,7 +340,7 @@ func (a *API) handleChangePassword(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
var requestData ChangePasswordRequest
|
||||
if err := json.Unmarshal(requestBody, &requestData); err != nil {
|
||||
if err = json.Unmarshal(requestBody, &requestData); err != nil {
|
||||
a.errorResponse(w, http.StatusInternalServerError, "", err)
|
||||
return
|
||||
}
|
||||
@ -374,9 +379,9 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
now := time.Now().Unix()
|
||||
session := &model.Session{
|
||||
ID: "single-user",
|
||||
ID: SingleUser,
|
||||
Token: token,
|
||||
UserID: "single-user",
|
||||
UserID: SingleUser,
|
||||
AuthService: a.authService,
|
||||
Props: map[string]interface{}{},
|
||||
CreateAt: now,
|
||||
@ -441,6 +446,5 @@ func (a *API) adminRequired(handler func(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
handler(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -10,53 +10,61 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GetSession Get a user active session and refresh the session if is needed
|
||||
const (
|
||||
DaysPerMonth = 30
|
||||
DaysPerWeek = 7
|
||||
HoursPerDay = 24
|
||||
MinutesPerHour = 60
|
||||
SecondsPerMinute = 60
|
||||
)
|
||||
|
||||
// GetSession Get a user active session and refresh the session if is needed.
|
||||
func (a *App) GetSession(token string) (*model.Session, error) {
|
||||
return a.auth.GetSession(token)
|
||||
}
|
||||
|
||||
// IsValidReadToken validates the read token for a block
|
||||
// IsValidReadToken validates the read token for a block.
|
||||
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
|
||||
// GetRegisteredUserCount returns the number of registered users.
|
||||
func (a *App) GetRegisteredUserCount() (int, error) {
|
||||
return a.store.GetRegisteredUserCount()
|
||||
}
|
||||
|
||||
// GetDailyActiveUsers returns the number of daily active users
|
||||
// GetDailyActiveUsers returns the number of daily active users.
|
||||
func (a *App) GetDailyActiveUsers() (int, error) {
|
||||
secondsAgo := int64(60 * 60 * 24)
|
||||
secondsAgo := int64(SecondsPerMinute * MinutesPerHour * HoursPerDay)
|
||||
return a.store.GetActiveUserCount(secondsAgo)
|
||||
}
|
||||
|
||||
// GetWeeklyActiveUsers returns the number of weekly active users
|
||||
// GetWeeklyActiveUsers returns the number of weekly active users.
|
||||
func (a *App) GetWeeklyActiveUsers() (int, error) {
|
||||
secondsAgo := int64(60 * 60 * 24 * 7)
|
||||
secondsAgo := int64(SecondsPerMinute * MinutesPerHour * HoursPerDay * DaysPerWeek)
|
||||
return a.store.GetActiveUserCount(secondsAgo)
|
||||
}
|
||||
|
||||
// GetMonthlyActiveUsers returns the number of monthly active users
|
||||
// GetMonthlyActiveUsers returns the number of monthly active users.
|
||||
func (a *App) GetMonthlyActiveUsers() (int, error) {
|
||||
secondsAgo := int64(60 * 60 * 24 * 30)
|
||||
secondsAgo := int64(SecondsPerMinute * MinutesPerHour * HoursPerDay * DaysPerMonth)
|
||||
return a.store.GetActiveUserCount(secondsAgo)
|
||||
}
|
||||
|
||||
// GetUser Get an existing active user by id
|
||||
func (a *App) GetUser(ID string) (*model.User, error) {
|
||||
if len(ID) < 1 {
|
||||
// GetUser gets an existing active user by id.
|
||||
func (a *App) GetUser(id string) (*model.User, error) {
|
||||
if len(id) < 1 {
|
||||
return nil, errors.New("no user ID")
|
||||
}
|
||||
|
||||
user, err := a.store.GetUserById(ID)
|
||||
user, err := a.store.GetUserByID(id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to find user")
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Login create a new user session if the authentication data is valid
|
||||
// Login create a new user session if the authentication data is valid.
|
||||
func (a *App) Login(username, email, password, mfaToken string) (string, error) {
|
||||
var user *model.User
|
||||
if username != "" {
|
||||
@ -110,7 +118,7 @@ func (a *App) Login(username, email, password, mfaToken string) (string, error)
|
||||
return session.Token, nil
|
||||
}
|
||||
|
||||
// RegisterUser create a new user if the provided data is valid
|
||||
// RegisterUser creates a new user if the provided data is valid.
|
||||
func (a *App) RegisterUser(username, email, password string) error {
|
||||
var user *model.User
|
||||
if username != "" {
|
||||
@ -169,7 +177,7 @@ func (a *App) ChangePassword(userID, oldPassword, newPassword string) error {
|
||||
var user *model.User
|
||||
if userID != "" {
|
||||
var err error
|
||||
user, err = a.store.GetUserById(userID)
|
||||
user, err = a.store.GetUserByID(userID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid username or password")
|
||||
}
|
||||
|
@ -70,8 +70,8 @@ func TestGetUser(t *testing.T) {
|
||||
{"success", "goodID", false},
|
||||
}
|
||||
|
||||
th.Store.EXPECT().GetUserById("badID").Return(nil, errors.New("Bad Id"))
|
||||
th.Store.EXPECT().GetUserById("goodID").Return(mockUser, nil)
|
||||
th.Store.EXPECT().GetUserByID("badID").Return(nil, errors.New("Bad Id"))
|
||||
th.Store.EXPECT().GetUserByID("goodID").Return(mockUser, nil)
|
||||
|
||||
for _, test := range testcases {
|
||||
t.Run(test.title, func(t *testing.T) {
|
||||
@ -168,8 +168,8 @@ func TestChangePassword(t *testing.T) {
|
||||
{"success, using username", mockUser.ID, "testPassword", "newPassword", false},
|
||||
}
|
||||
|
||||
th.Store.EXPECT().GetUserById("badID").Return(nil, errors.New("userID not found"))
|
||||
th.Store.EXPECT().GetUserById(mockUser.ID).Return(mockUser, nil).Times(2)
|
||||
th.Store.EXPECT().GetUserByID("badID").Return(nil, errors.New("userID not found"))
|
||||
th.Store.EXPECT().GetUserByID(mockUser.ID).Return(mockUser, nil).Times(2)
|
||||
th.Store.EXPECT().UpdateUserPasswordByID(mockUser.ID, gomock.Any()).Return(nil)
|
||||
|
||||
for _, test := range testcases {
|
||||
|
@ -38,20 +38,7 @@ func (a *App) InsertBlock(c store.Container, block model.Block) error {
|
||||
}
|
||||
|
||||
func (a *App) InsertBlocks(c store.Container, blocks []model.Block) error {
|
||||
blockIDsToNotify := []string{}
|
||||
|
||||
uniqueBlockIDs := make(map[string]bool)
|
||||
|
||||
for _, block := range blocks {
|
||||
if !uniqueBlockIDs[block.ID] {
|
||||
blockIDsToNotify = append(blockIDsToNotify, block.ID)
|
||||
}
|
||||
|
||||
// ParentID as empty string denotes a block at the root
|
||||
if !uniqueBlockIDs[block.ParentID] {
|
||||
blockIDsToNotify = append(blockIDsToNotify, block.ParentID)
|
||||
}
|
||||
|
||||
err := a.store.InsertBlock(c, block)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -78,16 +65,11 @@ func (a *App) GetAllBlocks(c store.Container) ([]model.Block, error) {
|
||||
}
|
||||
|
||||
func (a *App) DeleteBlock(c store.Container, blockID string, modifiedBy string) error {
|
||||
blockIDsToNotify := []string{blockID}
|
||||
parentID, err := a.GetParentID(c, blockID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(parentID) > 0 {
|
||||
blockIDsToNotify = append(blockIDsToNotify, parentID)
|
||||
}
|
||||
|
||||
err = a.store.DeleteBlock(c, blockID, modifiedBy)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
@ -40,16 +39,23 @@ func (a *App) GetFileReader(workspaceID, rootID, filename string) (filestore.Rea
|
||||
}
|
||||
// FIXUP: Check the deprecated old location
|
||||
if workspaceID == "0" && !exists {
|
||||
oldExists, err := a.filesBackend.FileExists(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
oldExists, err2 := a.filesBackend.FileExists(filename)
|
||||
if err2 != nil {
|
||||
return nil, err2
|
||||
}
|
||||
if oldExists {
|
||||
err := a.filesBackend.MoveFile(filename, filePath)
|
||||
if err != nil {
|
||||
a.logger.Error("ERROR moving file", mlog.String("old", filename), mlog.String("new", filePath))
|
||||
err2 := a.filesBackend.MoveFile(filename, filePath)
|
||||
if err2 != nil {
|
||||
a.logger.Error("ERROR moving file",
|
||||
mlog.String("old", filename),
|
||||
mlog.String("new", filePath),
|
||||
mlog.Err(err2),
|
||||
)
|
||||
} else {
|
||||
a.logger.Debug("Moved file", mlog.String("old", filename), mlog.String("new", filePath))
|
||||
a.logger.Debug("Moved file",
|
||||
mlog.String("old", filename),
|
||||
mlog.String("new", filePath),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,8 +67,3 @@ func (a *App) GetFileReader(workspaceID, rootID, filename string) (filestore.Rea
|
||||
|
||||
return reader, nil
|
||||
}
|
||||
|
||||
func fileExists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ type TestHelper struct {
|
||||
}
|
||||
|
||||
func SetupTestHelper(t *testing.T) *TestHelper {
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
cfg := config.Configuration{}
|
||||
|
@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
@ -9,7 +10,7 @@ import (
|
||||
|
||||
func (a *App) GetSharing(c store.Container, rootID string) (*model.Sharing, error) {
|
||||
sharing, err := a.store.GetSharing(c, rootID)
|
||||
if err == sql.ErrNoRows {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -19,7 +19,7 @@ func TestGetSharing(t *testing.T) {
|
||||
WorkspaceID: utils.CreateGUID(),
|
||||
}
|
||||
|
||||
t.Run("should get a sharing sucessfully", func(t *testing.T) {
|
||||
t.Run("should get a sharing successfully", func(t *testing.T) {
|
||||
want := &model.Sharing{
|
||||
ID: utils.CreateGUID(),
|
||||
Enabled: true,
|
||||
|
@ -2,6 +2,7 @@ package app
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
"github.com/mattermost/focalboard/server/services/mlog"
|
||||
@ -33,9 +34,9 @@ func (a *App) GetRootWorkspace() (*model.Workspace, error) {
|
||||
return workspace, nil
|
||||
}
|
||||
|
||||
func (a *App) GetWorkspace(ID string) (*model.Workspace, error) {
|
||||
workspace, err := a.store.GetWorkspace(ID)
|
||||
if err == sql.ErrNoRows {
|
||||
func (a *App) GetWorkspace(id string) (*model.Workspace, error) {
|
||||
workspace, err := a.store.GetWorkspace(id)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -10,18 +10,18 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Auth authenticates sessions
|
||||
// Auth authenticates sessions.
|
||||
type Auth struct {
|
||||
config *config.Configuration
|
||||
store store.Store
|
||||
}
|
||||
|
||||
// New returns a new Auth
|
||||
// New returns a new Auth.
|
||||
func New(config *config.Configuration, store store.Store) *Auth {
|
||||
return &Auth{config: config, store: store}
|
||||
}
|
||||
|
||||
// GetSession Get a user active session and refresh the session if is needed
|
||||
// GetSession Get a user active session and refresh the session if needed.
|
||||
func (a *Auth) GetSession(token string) (*model.Session, error) {
|
||||
if len(token) < 1 {
|
||||
return nil, errors.New("no session token")
|
||||
@ -32,12 +32,12 @@ func (a *Auth) GetSession(token string) (*model.Session, error) {
|
||||
return nil, errors.Wrap(err, "unable to get the session for the token")
|
||||
}
|
||||
if session.UpdateAt < (time.Now().Unix() - a.config.SessionRefreshTime) {
|
||||
a.store.RefreshSession(session)
|
||||
_ = a.store.RefreshSession(session)
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
// IsValidReadToken validates the read token for a block
|
||||
// IsValidReadToken validates the read token for a block.
|
||||
func (a *Auth) IsValidReadToken(c store.Container, blockID string, readToken string) (bool, error) {
|
||||
rootID, err := a.store.GetRootID(c, blockID)
|
||||
if err != nil {
|
||||
@ -45,7 +45,7 @@ func (a *Auth) IsValidReadToken(c store.Container, blockID string, readToken str
|
||||
}
|
||||
|
||||
sharing, err := a.store.GetSharing(c, rootID)
|
||||
if err == sql.ErrNoRows {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
|
@ -41,11 +41,9 @@ func setupTestHelper(t *testing.T) *TestHelper {
|
||||
Session: *mockSession,
|
||||
Store: mockStore,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetSession(t *testing.T) {
|
||||
|
||||
th := setupTestHelper(t)
|
||||
|
||||
testcases := []struct {
|
||||
|
@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
API_URL_SUFFIX = "/api/v1"
|
||||
APIURLSuffix = "/api/v1"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
@ -57,10 +57,10 @@ func toJSON(v interface{}) string {
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
Url string
|
||||
ApiUrl string
|
||||
HttpClient *http.Client
|
||||
HttpHeader map[string]string
|
||||
URL string
|
||||
APIURL string
|
||||
HTTPClient *http.Client
|
||||
HTTPHeader map[string]string
|
||||
}
|
||||
|
||||
func NewClient(url, sessionToken string) *Client {
|
||||
@ -69,63 +69,63 @@ func NewClient(url, sessionToken string) *Client {
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"Authorization": "Bearer " + sessionToken,
|
||||
}
|
||||
return &Client{url, url + API_URL_SUFFIX, &http.Client{}, headers}
|
||||
return &Client{url, url + APIURLSuffix, &http.Client{}, headers}
|
||||
}
|
||||
|
||||
func (c *Client) DoApiGet(url, etag string) (*http.Response, error) {
|
||||
return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
|
||||
func (c *Client) DoAPIGet(url, etag string) (*http.Response, error) {
|
||||
return c.DoAPIRequest(http.MethodGet, c.APIURL+url, "", etag)
|
||||
}
|
||||
|
||||
func (c *Client) DoApiPost(url, data string) (*http.Response, error) {
|
||||
return c.DoApiRequest(http.MethodPost, c.ApiUrl+url, data, "")
|
||||
func (c *Client) DoAPIPost(url, data string) (*http.Response, error) {
|
||||
return c.DoAPIRequest(http.MethodPost, c.APIURL+url, data, "")
|
||||
}
|
||||
|
||||
func (c *Client) doApiPostBytes(url string, data []byte) (*http.Response, error) {
|
||||
return c.doApiRequestBytes(http.MethodPost, c.ApiUrl+url, data, "")
|
||||
func (c *Client) doAPIPostBytes(url string, data []byte) (*http.Response, error) {
|
||||
return c.doAPIRequestBytes(http.MethodPost, c.APIURL+url, data, "")
|
||||
}
|
||||
|
||||
func (c *Client) DoApiPut(url, data string) (*http.Response, error) {
|
||||
return c.DoApiRequest(http.MethodPut, c.ApiUrl+url, data, "")
|
||||
func (c *Client) DoAPIPut(url, data string) (*http.Response, error) {
|
||||
return c.DoAPIRequest(http.MethodPut, c.APIURL+url, data, "")
|
||||
}
|
||||
|
||||
func (c *Client) doApiPutBytes(url string, data []byte) (*http.Response, error) {
|
||||
return c.doApiRequestBytes(http.MethodPut, c.ApiUrl+url, data, "")
|
||||
func (c *Client) doAPIPutBytes(url string, data []byte) (*http.Response, error) {
|
||||
return c.doAPIRequestBytes(http.MethodPut, c.APIURL+url, data, "")
|
||||
}
|
||||
|
||||
func (c *Client) DoApiDelete(url string) (*http.Response, error) {
|
||||
return c.DoApiRequest(http.MethodDelete, c.ApiUrl+url, "", "")
|
||||
func (c *Client) DoAPIDelete(url string) (*http.Response, error) {
|
||||
return c.DoAPIRequest(http.MethodDelete, c.APIURL+url, "", "")
|
||||
}
|
||||
|
||||
func (c *Client) DoApiRequest(method, url, data, etag string) (*http.Response, error) {
|
||||
return c.doApiRequestReader(method, url, strings.NewReader(data), etag)
|
||||
func (c *Client) DoAPIRequest(method, url, data, etag string) (*http.Response, error) {
|
||||
return c.doAPIRequestReader(method, url, strings.NewReader(data), etag)
|
||||
}
|
||||
|
||||
func (c *Client) doApiRequestBytes(method, url string, data []byte, etag string) (*http.Response, error) {
|
||||
return c.doApiRequestReader(method, url, bytes.NewReader(data), etag)
|
||||
func (c *Client) doAPIRequestBytes(method, url string, data []byte, etag string) (*http.Response, error) {
|
||||
return c.doAPIRequestReader(method, url, bytes.NewReader(data), etag)
|
||||
}
|
||||
|
||||
func (c *Client) doApiRequestReader(method, url string, data io.Reader, etag string) (*http.Response, error) {
|
||||
func (c *Client) doAPIRequestReader(method, url string, data io.Reader, _ /* etag */ string) (*http.Response, error) {
|
||||
rq, err := http.NewRequest(method, url, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.HttpHeader != nil && len(c.HttpHeader) > 0 {
|
||||
for k, v := range c.HttpHeader {
|
||||
if c.HTTPHeader != nil && len(c.HTTPHeader) > 0 {
|
||||
for k, v := range c.HTTPHeader {
|
||||
rq.Header.Set(k, v)
|
||||
}
|
||||
}
|
||||
|
||||
rp, err := c.HttpClient.Do(rq)
|
||||
rp, err := c.HTTPClient.Do(rq)
|
||||
if err != nil || rp == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if rp.StatusCode == 304 {
|
||||
if rp.StatusCode == http.StatusNotModified {
|
||||
return rp, nil
|
||||
}
|
||||
|
||||
if rp.StatusCode >= 300 {
|
||||
if rp.StatusCode >= http.StatusMultipleChoices {
|
||||
defer closeBody(rp)
|
||||
b, err := ioutil.ReadAll(rp.Body)
|
||||
if err != nil {
|
||||
@ -150,7 +150,7 @@ func (c *Client) GetSubtreeRoute(id string) string {
|
||||
}
|
||||
|
||||
func (c *Client) GetBlocks() ([]model.Block, *Response) {
|
||||
r, err := c.DoApiGet(c.GetBlocksRoute(), "")
|
||||
r, err := c.DoAPIGet(c.GetBlocksRoute(), "")
|
||||
if err != nil {
|
||||
return nil, BuildErrorResponse(r, err)
|
||||
}
|
||||
@ -160,7 +160,7 @@ func (c *Client) GetBlocks() ([]model.Block, *Response) {
|
||||
}
|
||||
|
||||
func (c *Client) InsertBlocks(blocks []model.Block) (bool, *Response) {
|
||||
r, err := c.DoApiPost(c.GetBlocksRoute(), toJSON(blocks))
|
||||
r, err := c.DoAPIPost(c.GetBlocksRoute(), toJSON(blocks))
|
||||
if err != nil {
|
||||
return false, BuildErrorResponse(r, err)
|
||||
}
|
||||
@ -170,7 +170,7 @@ func (c *Client) InsertBlocks(blocks []model.Block) (bool, *Response) {
|
||||
}
|
||||
|
||||
func (c *Client) DeleteBlock(blockID string) (bool, *Response) {
|
||||
r, err := c.DoApiDelete(c.GetBlockRoute(blockID))
|
||||
r, err := c.DoAPIDelete(c.GetBlockRoute(blockID))
|
||||
if err != nil {
|
||||
return false, BuildErrorResponse(r, err)
|
||||
}
|
||||
@ -180,7 +180,7 @@ func (c *Client) DeleteBlock(blockID string) (bool, *Response) {
|
||||
}
|
||||
|
||||
func (c *Client) GetSubtree(blockID string) ([]model.Block, *Response) {
|
||||
r, err := c.DoApiGet(c.GetSubtreeRoute(blockID), "")
|
||||
r, err := c.DoAPIGet(c.GetSubtreeRoute(blockID), "")
|
||||
if err != nil {
|
||||
return nil, BuildErrorResponse(r, err)
|
||||
}
|
||||
@ -196,7 +196,7 @@ func (c *Client) GetSharingRoute(rootID string) string {
|
||||
}
|
||||
|
||||
func (c *Client) GetSharing(rootID string) (*model.Sharing, *Response) {
|
||||
r, err := c.DoApiGet(c.GetSharingRoute(rootID), "")
|
||||
r, err := c.DoAPIGet(c.GetSharingRoute(rootID), "")
|
||||
if err != nil {
|
||||
return nil, BuildErrorResponse(r, err)
|
||||
}
|
||||
@ -207,7 +207,7 @@ func (c *Client) GetSharing(rootID string) (*model.Sharing, *Response) {
|
||||
}
|
||||
|
||||
func (c *Client) PostSharing(sharing model.Sharing) (bool, *Response) {
|
||||
r, err := c.DoApiPost(c.GetSharingRoute(sharing.ID), toJSON(sharing))
|
||||
r, err := c.DoAPIPost(c.GetSharingRoute(sharing.ID), toJSON(sharing))
|
||||
if err != nil {
|
||||
return false, BuildErrorResponse(r, err)
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ type contextKey struct {
|
||||
|
||||
var connContextKey = &contextKey{"http-conn"}
|
||||
|
||||
// SetContextConn stores the connection in the request context
|
||||
// SetContextConn stores the connection in the request context.
|
||||
func SetContextConn(ctx context.Context, c net.Conn) context.Context {
|
||||
return context.WithValue(ctx, connContextKey, c)
|
||||
}
|
||||
|
||||
// GetContextConn gets the stored connection from the request context
|
||||
// GetContextConn gets the stored connection from the request context.
|
||||
func GetContextConn(r *http.Request) net.Conn {
|
||||
value := r.Context().Value(connContextKey)
|
||||
if value == nil {
|
||||
|
@ -66,7 +66,9 @@ func SetupTestHelper() *TestHelper {
|
||||
sessionToken := "TESTTOKEN"
|
||||
th := &TestHelper{}
|
||||
logger := mlog.NewLogger()
|
||||
logger.Configure("", getTestConfig().LoggingCfgJSON)
|
||||
if err := logger.Configure("", getTestConfig().LoggingCfgJSON); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
srv, err := server.New(getTestConfig(), sessionToken, logger)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -111,7 +113,7 @@ func (th *TestHelper) InitBasic() *TestHelper {
|
||||
}
|
||||
|
||||
func (th *TestHelper) TearDown() {
|
||||
defer th.Server.Logger().Shutdown()
|
||||
defer func() { _ = th.Server.Logger().Shutdown() }()
|
||||
|
||||
err := th.Server.Shutdown()
|
||||
if err != nil {
|
||||
|
@ -105,7 +105,7 @@ func main() {
|
||||
log.Fatal("Error in config file for logger: ", err)
|
||||
return
|
||||
}
|
||||
defer logger.Shutdown()
|
||||
defer func() { _ = logger.Shutdown() }()
|
||||
|
||||
if logger.HasTargets() {
|
||||
restore := logger.RedirectStdLog(mlog.Info, mlog.String("src", "stdlog"))
|
||||
@ -176,7 +176,7 @@ func main() {
|
||||
// Waiting for SIGINT (pkill -2)
|
||||
<-stop
|
||||
|
||||
server.Shutdown()
|
||||
_ = server.Shutdown()
|
||||
}
|
||||
|
||||
// StartServer starts the server
|
||||
@ -254,7 +254,7 @@ func stopServer() {
|
||||
if err != nil {
|
||||
pServer.Logger().Error("server.Shutdown ERROR", mlog.Err(err))
|
||||
}
|
||||
pServer.Logger().Shutdown()
|
||||
_ = pServer.Logger().Shutdown()
|
||||
pServer = nil
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ type Block struct {
|
||||
DeleteAt int64 `json:"deleteAt"`
|
||||
}
|
||||
|
||||
// Archive is an import / export archive
|
||||
// Archive is an import / export archive.
|
||||
type Archive struct {
|
||||
Version int64 `json:"version"`
|
||||
Date int64 `json:"date"`
|
||||
@ -62,7 +62,7 @@ type Archive struct {
|
||||
|
||||
func BlocksFromJSON(data io.Reader) []Block {
|
||||
var blocks []Block
|
||||
json.NewDecoder(data).Decode(&blocks)
|
||||
_ = json.NewDecoder(data).Decode(&blocks)
|
||||
return blocks
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,6 @@ type Sharing struct {
|
||||
|
||||
func SharingFromJSON(data io.Reader) Sharing {
|
||||
var sharing Sharing
|
||||
json.NewDecoder(data).Decode(&sharing)
|
||||
_ = json.NewDecoder(data).Decode(&sharing)
|
||||
return sharing
|
||||
}
|
||||
|
@ -2,5 +2,5 @@ package server
|
||||
|
||||
func (s *Server) initHandlers() {
|
||||
cfg := s.config
|
||||
s.api.MattermostAuth = cfg.AuthMode == "mattermost"
|
||||
s.api.MattermostAuth = cfg.AuthMode == MattermostAuthMod
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -43,6 +43,8 @@ const (
|
||||
|
||||
//nolint:gomnd
|
||||
minSessionExpiryTime = int64(60 * 60 * 24 * 31) // 31 days
|
||||
|
||||
MattermostAuthMod = "mattermost"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
@ -72,18 +74,18 @@ func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger)
|
||||
logger.Error("Unable to start the database", mlog.Err(err))
|
||||
return nil, err
|
||||
}
|
||||
if cfg.AuthMode == "mattermost" {
|
||||
layeredStore, err := mattermostauthlayer.New(cfg.DBType, cfg.DBConfigString, db)
|
||||
if err != nil {
|
||||
log.Print("Unable to start the database", err)
|
||||
return nil, err
|
||||
if cfg.AuthMode == MattermostAuthMod {
|
||||
layeredStore, err2 := mattermostauthlayer.New(cfg.DBType, cfg.DBConfigString, db)
|
||||
if err2 != nil {
|
||||
logger.Error("Unable to start the database", mlog.Err(err2))
|
||||
return nil, err2
|
||||
}
|
||||
db = layeredStore
|
||||
}
|
||||
|
||||
authenticator := auth.New(cfg, db)
|
||||
|
||||
wsServer := ws.NewServer(authenticator, singleUserToken, cfg.AuthMode == "mattermost", logger)
|
||||
wsServer := ws.NewServer(authenticator, singleUserToken, cfg.AuthMode == MattermostAuthMod, logger)
|
||||
|
||||
filesBackendSettings := filestore.FileBackendSettings{}
|
||||
filesBackendSettings.DriverName = cfg.FilesDriver
|
||||
@ -119,8 +121,8 @@ func New(cfg *config.Configuration, singleUserToken string, logger *mlog.Logger)
|
||||
|
||||
// Init audit
|
||||
auditService := audit.NewAudit()
|
||||
if err := auditService.Configure(cfg.AuditCfgFile, cfg.AuditCfgJSON); err != nil {
|
||||
return nil, errors.New("unable to initialize the audit service")
|
||||
if err2 := auditService.Configure(cfg.AuditCfgFile, cfg.AuditCfgJSON); err2 != nil {
|
||||
return nil, fmt.Errorf("unable to initialize the audit service: %w", err2)
|
||||
}
|
||||
|
||||
appServices := app.Services{
|
||||
@ -250,7 +252,7 @@ func (s *Server) Start() error {
|
||||
}
|
||||
return nil
|
||||
}, func(error) {
|
||||
s.metricsServer.Shutdown()
|
||||
_ = s.metricsServer.Shutdown()
|
||||
})
|
||||
|
||||
if err := group.Run(); err != nil {
|
||||
|
@ -33,7 +33,7 @@ type Audit struct {
|
||||
auditLogger *mlog.Logger
|
||||
}
|
||||
|
||||
// NewAudit creates a new Audit instance which can be configured via `(*Audit).Configure`
|
||||
// NewAudit creates a new Audit instance which can be configured via `(*Audit).Configure`.
|
||||
func NewAudit(options ...mlog.Option) *Audit {
|
||||
logger := mlog.NewLogger(options...)
|
||||
|
||||
|
@ -2,6 +2,7 @@ package auth
|
||||
|
||||
import "regexp"
|
||||
|
||||
//nolint:lll
|
||||
var emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
||||
|
||||
// IsEmailValid checks if the email provided passes the required structure and length.
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
|
||||
const (
|
||||
PasswordMaximumLength = 64
|
||||
PasswordSpecialChars = "!\"\\#$%&'()*+,-./:;<=>?@[]^_`|~"
|
||||
PasswordSpecialChars = "!\"\\#$%&'()*+,-./:;<=>?@[]^_`|~" //nolint:gosec
|
||||
PasswordNumbers = "0123456789"
|
||||
PasswordUpperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
PasswordLowerCaseLetters = "abcdefghijklmnopqrstuvwxyz"
|
||||
@ -23,7 +23,7 @@ const (
|
||||
InvalidSymbolPassword = "symbol"
|
||||
)
|
||||
|
||||
// HashPassword generates a hash using the bcrypt.GenerateFromPassword
|
||||
// HashPassword generates a hash using the bcrypt.GenerateFromPassword.
|
||||
func HashPassword(password string) string {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
|
||||
if err != nil {
|
||||
@ -33,7 +33,7 @@ func HashPassword(password string) string {
|
||||
return string(hash)
|
||||
}
|
||||
|
||||
// ComparePassword compares the hash
|
||||
// ComparePassword compares the hash.
|
||||
func ComparePassword(hash, password string) bool {
|
||||
if len(password) == 0 || len(hash) == 0 {
|
||||
return false
|
||||
@ -48,7 +48,7 @@ type InvalidPasswordError struct {
|
||||
}
|
||||
|
||||
func (ipe *InvalidPasswordError) Error() string {
|
||||
return fmt.Sprintf("invalid password, failing criterias: %s", strings.Join(ipe.FailingCriterias, ", "))
|
||||
return fmt.Sprintf("invalid password, failing criteria: %s", strings.Join(ipe.FailingCriterias, ", "))
|
||||
}
|
||||
|
||||
type PasswordSettings struct {
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
HEADER_TOKEN = "token"
|
||||
HEADER_AUTH = "Authorization"
|
||||
HEADER_BEARER = "BEARER"
|
||||
SESSION_COOKIE_TOKEN = "FOCALBOARDAUTHTOKEN"
|
||||
HeaderToken = "token"
|
||||
HeaderAuth = "Authorization"
|
||||
HeaderBearer = "BEARER"
|
||||
SessionCookieToken = "FOCALBOARDAUTHTOKEN"
|
||||
)
|
||||
|
||||
type TokenLocation int
|
||||
@ -40,20 +40,20 @@ func (tl TokenLocation) String() string {
|
||||
}
|
||||
|
||||
func ParseAuthTokenFromRequest(r *http.Request) (string, TokenLocation) {
|
||||
authHeader := r.Header.Get(HEADER_AUTH)
|
||||
authHeader := r.Header.Get(HeaderAuth)
|
||||
|
||||
// Attempt to parse the token from the cookie
|
||||
if cookie, err := r.Cookie(SESSION_COOKIE_TOKEN); err == nil {
|
||||
if cookie, err := r.Cookie(SessionCookieToken); err == nil {
|
||||
return cookie.Value, TokenLocationCookie
|
||||
}
|
||||
|
||||
// Parse the token from the header
|
||||
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == HEADER_BEARER {
|
||||
if len(authHeader) > 6 && strings.ToUpper(authHeader[0:6]) == HeaderBearer {
|
||||
// Default session token
|
||||
return authHeader[7:], TokenLocationHeader
|
||||
}
|
||||
|
||||
if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == HEADER_TOKEN {
|
||||
if len(authHeader) > 5 && strings.ToLower(authHeader[0:5]) == HeaderToken {
|
||||
// OAuth token
|
||||
return authHeader[6:], TokenLocationHeader
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ func TestParseAuthTokenFromRequest(t *testing.T) {
|
||||
}
|
||||
req := httptest.NewRequest("GET", pathname, nil)
|
||||
if tc.header != "" {
|
||||
req.Header.Add(HEADER_AUTH, tc.header)
|
||||
req.Header.Add(HeaderAuth, tc.header)
|
||||
}
|
||||
if tc.cookie != "" {
|
||||
req.AddCookie(&http.Cookie{
|
||||
|
@ -22,7 +22,7 @@ type InstanceInfo struct {
|
||||
InstallationID string
|
||||
}
|
||||
|
||||
// Metrics used to instrumentate metrics in prometheus
|
||||
// Metrics used to instrumentate metrics in prometheus.
|
||||
type Metrics struct {
|
||||
registry *prometheus.Registry
|
||||
|
||||
@ -41,7 +41,7 @@ type Metrics struct {
|
||||
blockLastActivity prometheus.Gauge
|
||||
}
|
||||
|
||||
// NewMetrics Factory method to create a new metrics collector
|
||||
// NewMetrics Factory method to create a new metrics collector.
|
||||
func NewMetrics(info InstanceInfo) *Metrics {
|
||||
m := &Metrics{}
|
||||
|
||||
|
@ -8,12 +8,12 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
)
|
||||
|
||||
// Service prometheus to run the server
|
||||
// Service prometheus to run the server.
|
||||
type Service struct {
|
||||
*http.Server
|
||||
}
|
||||
|
||||
// NewMetricsServer factory method to create a new prometheus server
|
||||
// NewMetricsServer factory method to create a new prometheus server.
|
||||
func NewMetricsServer(address string, metricsService *Metrics, logger *mlog.Logger) *Service {
|
||||
return &Service{
|
||||
&http.Server{
|
||||
@ -25,12 +25,12 @@ func NewMetricsServer(address string, metricsService *Metrics, logger *mlog.Logg
|
||||
}
|
||||
}
|
||||
|
||||
// Run will start the prometheus server
|
||||
// Run will start the prometheus server.
|
||||
func (h *Service) Run() error {
|
||||
return errors.Wrap(h.Server.ListenAndServe(), "prometheus ListenAndServe")
|
||||
}
|
||||
|
||||
// Shutdown will shutdown the prometheus server
|
||||
// Shutdown will shutdown the prometheus server.
|
||||
func (h *Service) Shutdown() error {
|
||||
return errors.Wrap(h.Server.Close(), "prometheus Close")
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
//nolint:gomnd
|
||||
package mlog
|
||||
|
||||
import "github.com/mattermost/logr/v2"
|
||||
|
||||
// Standard levels
|
||||
// Standard levels.
|
||||
var (
|
||||
Panic = logr.Panic // ID = 0
|
||||
Fatal = logr.Fatal // ID = 1
|
||||
@ -33,7 +34,7 @@ var (
|
||||
Metrics = Level{ID: 501, Name: "metrics"}
|
||||
)
|
||||
|
||||
// Combinations for LogM (log multi)
|
||||
// Combinations for LogM (log multi).
|
||||
var (
|
||||
/* Example
|
||||
MAuditAll = []Level{AuditAPI, AuditContent, AuditPerms, AuditCLI}
|
||||
|
@ -106,7 +106,7 @@ type Logger struct {
|
||||
log *logr.Logger
|
||||
}
|
||||
|
||||
// NewLogger creates a new Logger instance which can be configured via `(*Logger).Configure`
|
||||
// NewLogger creates a new Logger instance which can be configured via `(*Logger).Configure`.
|
||||
func NewLogger(options ...Option) *Logger {
|
||||
lgr, _ := logr.New(options...)
|
||||
log := lgr.NewLogger()
|
||||
@ -129,15 +129,16 @@ func (l *Logger) Configure(cfgFile string, cfgEscaped string) error {
|
||||
|
||||
// Add config from file
|
||||
if cfgFile != "" {
|
||||
if b, err := ioutil.ReadFile(string(cfgFile)); err != nil {
|
||||
b, err := ioutil.ReadFile(cfgFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading logger config file %s: %w", cfgFile, err)
|
||||
} else {
|
||||
var mapCfgFile LoggerConfig
|
||||
if err := json.Unmarshal(b, &mapCfgFile); err != nil {
|
||||
return fmt.Errorf("error decoding logger config file %s: %w", cfgFile, err)
|
||||
}
|
||||
cfgMap.append(mapCfgFile)
|
||||
}
|
||||
|
||||
var mapCfgFile LoggerConfig
|
||||
if err := json.Unmarshal(b, &mapCfgFile); err != nil {
|
||||
return fmt.Errorf("error decoding logger config file %s: %w", cfgFile, err)
|
||||
}
|
||||
cfgMap.append(mapCfgFile)
|
||||
}
|
||||
|
||||
// Add config from escaped json string
|
||||
@ -172,7 +173,7 @@ func (l *Logger) With(fields ...Field) *Logger {
|
||||
// Note, transformations and serializations done via fields are already
|
||||
// lazily evaluated and don't require this check beforehand.
|
||||
func (l *Logger) IsLevelEnabled(level Level) bool {
|
||||
return l.IsLevelEnabled(level)
|
||||
return l.log.IsLevelEnabled(level)
|
||||
}
|
||||
|
||||
// Log emits the log record for any targets configured for the specified level.
|
||||
@ -215,7 +216,7 @@ func (l *Logger) Error(msg string, fields ...Field) {
|
||||
// followed by `os.Exit(1)`.
|
||||
func (l *Logger) Fatal(msg string, fields ...Field) {
|
||||
l.log.Log(logr.Fatal, msg, fields...)
|
||||
l.Shutdown()
|
||||
_ = l.Shutdown()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/mattermost/logr/v2/formatters"
|
||||
)
|
||||
|
||||
// CreateTestLogger creates a logger for unit tests. Log records are output to `(*testing.T)Log`
|
||||
// CreateTestLogger creates a logger for unit tests. Log records are output to `(*testing.T)Log`.
|
||||
func CreateTestLogger(t *testing.T, levels ...Field) (logger *Logger) {
|
||||
logger = NewLogger()
|
||||
|
||||
@ -16,7 +16,10 @@ func CreateTestLogger(t *testing.T, levels ...Field) (logger *Logger) {
|
||||
formatter := &formatters.Plain{}
|
||||
target := newTestingTarget(t)
|
||||
|
||||
logger.log.Logr().AddTarget(target, "test", filter, formatter, 1000)
|
||||
if err := logger.log.Logr().AddTarget(target, "test", filter, formatter, 1000); err != nil {
|
||||
t.Fail()
|
||||
return nil
|
||||
}
|
||||
return logger
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
mysqlDBType = "mysql"
|
||||
sqliteDBType = "sqlite3"
|
||||
postgresDBType = "postgres"
|
||||
)
|
||||
@ -56,12 +55,12 @@ func New(dbType, connectionString string, store store.Store) (*MattermostAuthLay
|
||||
}
|
||||
|
||||
// Shutdown close the connection with the store.
|
||||
func (l *MattermostAuthLayer) Shutdown() error {
|
||||
err := l.Store.Shutdown()
|
||||
func (s *MattermostAuthLayer) Shutdown() error {
|
||||
err := s.Store.Shutdown()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return l.mmDB.Close()
|
||||
return s.mmDB.Close()
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetRegisteredUserCount() (int, error) {
|
||||
@ -82,7 +81,8 @@ func (s *MattermostAuthLayer) GetRegisteredUserCount() (int, error) {
|
||||
|
||||
func (s *MattermostAuthLayer) getUserByCondition(condition sq.Eq) (*model.User, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data", "props", "CreateAt as create_at", "UpdateAt as update_at", "DeleteAt as delete_at").
|
||||
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data",
|
||||
"props", "CreateAt as create_at", "UpdateAt as update_at", "DeleteAt as delete_at").
|
||||
From("Users").
|
||||
Where(sq.Eq{"deleteAt": 0}).
|
||||
Where(condition)
|
||||
@ -90,7 +90,8 @@ func (s *MattermostAuthLayer) getUserByCondition(condition sq.Eq) (*model.User,
|
||||
user := model.User{}
|
||||
|
||||
var propsBytes []byte
|
||||
err := row.Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.MfaSecret, &user.AuthService, &user.AuthData, &propsBytes, &user.CreateAt, &user.UpdateAt, &user.DeleteAt)
|
||||
err := row.Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.MfaSecret, &user.AuthService,
|
||||
&user.AuthData, &propsBytes, &user.CreateAt, &user.UpdateAt, &user.DeleteAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -103,7 +104,7 @@ func (s *MattermostAuthLayer) getUserByCondition(condition sq.Eq) (*model.User,
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetUserById(userID string) (*model.User, error) {
|
||||
func (s *MattermostAuthLayer) GetUserByID(userID string) (*model.User, error) {
|
||||
return s.getUserByCondition(sq.Eq{"id": userID})
|
||||
}
|
||||
|
||||
@ -131,7 +132,7 @@ func (s *MattermostAuthLayer) UpdateUserPasswordByID(userID, password string) er
|
||||
return errors.New("no update allowed from focalboard, update it using mattermost")
|
||||
}
|
||||
|
||||
// GetActiveUserCount returns the number of users with active sessions within N seconds ago
|
||||
// GetActiveUserCount returns the number of users with active sessions within N seconds ago.
|
||||
func (s *MattermostAuthLayer) GetActiveUserCount(updatedSecondsAgo int64) (int, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("count(distinct userId)").
|
||||
@ -165,7 +166,7 @@ func (s *MattermostAuthLayer) UpdateSession(session *model.Session) error {
|
||||
return errors.New("no update allowed from focalboard, update it using mattermost")
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) DeleteSession(sessionId string) error {
|
||||
func (s *MattermostAuthLayer) DeleteSession(sessionID string) error {
|
||||
return errors.New("no update allowed from focalboard, update it using mattermost")
|
||||
}
|
||||
|
||||
@ -173,10 +174,10 @@ func (s *MattermostAuthLayer) CleanUpSessions(expireTime int64) error {
|
||||
return errors.New("no update allowed from focalboard, update it using mattermost")
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) GetWorkspace(ID string) (*model.Workspace, error) {
|
||||
if ID == "0" {
|
||||
func (s *MattermostAuthLayer) GetWorkspace(id string) (*model.Workspace, error) {
|
||||
if id == "0" {
|
||||
workspace := model.Workspace{
|
||||
ID: ID,
|
||||
ID: id,
|
||||
Title: "",
|
||||
}
|
||||
|
||||
@ -186,7 +187,7 @@ func (s *MattermostAuthLayer) GetWorkspace(ID string) (*model.Workspace, error)
|
||||
query := s.getQueryBuilder().
|
||||
Select("DisplayName, Type").
|
||||
From("Channels").
|
||||
Where(sq.Eq{"ID": ID})
|
||||
Where(sq.Eq{"ID": id})
|
||||
|
||||
row := query.QueryRow()
|
||||
var displayName string
|
||||
@ -197,14 +198,14 @@ func (s *MattermostAuthLayer) GetWorkspace(ID string) (*model.Workspace, error)
|
||||
}
|
||||
|
||||
if channelType != "D" && channelType != "G" {
|
||||
return &model.Workspace{ID: ID, Title: displayName}, nil
|
||||
return &model.Workspace{ID: id, Title: displayName}, nil
|
||||
}
|
||||
|
||||
query = s.getQueryBuilder().
|
||||
Select("Username").
|
||||
From("ChannelMembers").
|
||||
Join("Users ON Users.ID=ChannelMembers.UserID").
|
||||
Where(sq.Eq{"ChannelID": ID})
|
||||
Where(sq.Eq{"ChannelID": id})
|
||||
|
||||
var sb strings.Builder
|
||||
rows, err := query.Query()
|
||||
@ -223,7 +224,7 @@ func (s *MattermostAuthLayer) GetWorkspace(ID string) (*model.Workspace, error)
|
||||
}
|
||||
sb.WriteString(name)
|
||||
}
|
||||
return &model.Workspace{ID: ID, Title: sb.String()}, nil
|
||||
return &model.Workspace{ID: id, Title: sb.String()}, nil
|
||||
}
|
||||
|
||||
func (s *MattermostAuthLayer) HasWorkspaceAccess(userID string, workspaceID string) (bool, error) {
|
||||
@ -255,7 +256,8 @@ func (s *MattermostAuthLayer) getQueryBuilder() sq.StatementBuilderType {
|
||||
|
||||
func (s *MattermostAuthLayer) GetUsersByWorkspace(workspaceID string) ([]*model.User, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data", "props", "CreateAt as create_at", "UpdateAt as update_at", "DeleteAt as delete_at").
|
||||
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data",
|
||||
"props", "CreateAt as create_at", "UpdateAt as update_at", "DeleteAt as delete_at").
|
||||
From("Users").
|
||||
Join("ChannelMembers ON ChannelMembers.UserID = Users.ID").
|
||||
Where(sq.Eq{"deleteAt": 0}).
|
||||
|
@ -345,19 +345,19 @@ func (mr *MockStoreMockRecorder) GetUserByEmail(email interface{}) *gomock.Call
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByEmail", reflect.TypeOf((*MockStore)(nil).GetUserByEmail), email)
|
||||
}
|
||||
|
||||
// GetUserById mocks base method.
|
||||
func (m *MockStore) GetUserById(userID string) (*model.User, error) {
|
||||
// GetUserByID mocks base method.
|
||||
func (m *MockStore) GetUserByID(userID string) (*model.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetUserById", userID)
|
||||
ret := m.ctrl.Call(m, "GetUserByID", userID)
|
||||
ret0, _ := ret[0].(*model.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetUserById indicates an expected call of GetUserById.
|
||||
func (mr *MockStoreMockRecorder) GetUserById(userID interface{}) *gomock.Call {
|
||||
// GetUserByID indicates an expected call of GetUserByID.
|
||||
func (mr *MockStoreMockRecorder) GetUserByID(userID interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserById", reflect.TypeOf((*MockStore)(nil).GetUserById), userID)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserByID", reflect.TypeOf((*MockStore)(nil).GetUserByID), userID)
|
||||
}
|
||||
|
||||
// GetUserByUsername mocks base method.
|
||||
|
@ -132,7 +132,7 @@ func (s *SQLStore) GetBlocksWithType(c store.Container, blockType string) ([]mod
|
||||
return s.blocksFromRows(rows)
|
||||
}
|
||||
|
||||
// GetSubTree2 returns blocks within 2 levels of the given blockID
|
||||
// GetSubTree2 returns blocks within 2 levels of the given blockID.
|
||||
func (s *SQLStore) GetSubTree2(c store.Container, blockID string) ([]model.Block, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select(
|
||||
@ -162,7 +162,7 @@ func (s *SQLStore) GetSubTree2(c store.Container, blockID string) ([]model.Block
|
||||
return s.blocksFromRows(rows)
|
||||
}
|
||||
|
||||
// GetSubTree3 returns blocks within 3 levels of the given blockID
|
||||
// GetSubTree3 returns blocks within 3 levels of the given blockID.
|
||||
func (s *SQLStore) GetSubTree3(c store.Container, blockID string) ([]model.Block, error) {
|
||||
// This first subquery returns repeated blocks
|
||||
query := s.getQueryBuilder().Select(
|
||||
@ -363,19 +363,19 @@ func (s *SQLStore) InsertBlock(c store.Container, block model.Block) error {
|
||||
Where(sq.Eq{"COALESCE(workspace_id, '0')": c.WorkspaceID})
|
||||
_, err = sq.ExecContextWith(ctx, tx, deleteQuery)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sq.ExecContextWith(ctx, tx, query.Into(s.tablePrefix+"blocks"))
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = sq.ExecContextWith(ctx, tx, query.Into(s.tablePrefix+"blocks_history"))
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
@ -413,7 +413,7 @@ func (s *SQLStore) DeleteBlock(c store.Container, blockID string, modifiedBy str
|
||||
|
||||
_, err = sq.ExecContextWith(ctx, tx, insertQuery)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
@ -424,7 +424,7 @@ func (s *SQLStore) DeleteBlock(c store.Container, blockID string, modifiedBy str
|
||||
|
||||
_, err = sq.ExecContextWith(ctx, tx, deleteQuery)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
_ = tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/store/sqlstore/initializations"
|
||||
)
|
||||
|
||||
// InitializeTemplates imports default templates if the blocks table is empty
|
||||
// InitializeTemplates imports default templates if the blocks table is empty.
|
||||
func (s *SQLStore) InitializeTemplates() error {
|
||||
isNeeded, err := s.isInitializationNeeded()
|
||||
if err != nil {
|
||||
@ -54,7 +54,7 @@ func (s *SQLStore) importInitialTemplates() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isInitializationNeeded returns true if the blocks table is empty
|
||||
// isInitializationNeeded returns true if the blocks table is empty.
|
||||
func (s *SQLStore) isInitializationNeeded() (bool, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("count(*)").
|
||||
|
@ -84,7 +84,7 @@ func appendMultipleStatementsFlag(connectionString string) (string, error) {
|
||||
|
||||
// migrations in MySQL need to run with the multiStatements flag
|
||||
// enabled, so this method creates a new connection ensuring that it's
|
||||
// enabled
|
||||
// enabled.
|
||||
func (s *SQLStore) getMySQLMigrationConnection() (*sql.DB, error) {
|
||||
connectionString, err := appendMultipleStatementsFlag(s.connectionString)
|
||||
if err != nil {
|
||||
@ -123,9 +123,9 @@ func (s *SQLStore) Migrate() error {
|
||||
}
|
||||
|
||||
if s.dbType == mysqlDBType {
|
||||
db, err := s.getMySQLMigrationConnection()
|
||||
if err != nil {
|
||||
return err
|
||||
db, err2 := s.getMySQLMigrationConnection()
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
)
|
||||
|
||||
// GetActiveUserCount returns the number of users with active sessions within N seconds ago
|
||||
// GetActiveUserCount returns the number of users with active sessions within N seconds ago.
|
||||
func (s *SQLStore) GetActiveUserCount(updatedSecondsAgo int64) (int, error) {
|
||||
query := s.getQueryBuilder().
|
||||
Select("count(distinct user_id)").
|
||||
@ -94,9 +94,9 @@ func (s *SQLStore) UpdateSession(session *model.Session) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLStore) DeleteSession(sessionId string) error {
|
||||
func (s *SQLStore) DeleteSession(sessionID string) error {
|
||||
query := s.getQueryBuilder().Delete(s.tablePrefix+"sessions").
|
||||
Where("id", sessionId)
|
||||
Where("id", sessionID)
|
||||
|
||||
_, err := query.Exec()
|
||||
return err
|
||||
|
@ -29,9 +29,13 @@ func (s *SQLStore) UpsertSharing(c store.Container, sharing model.Sharing) error
|
||||
now,
|
||||
)
|
||||
if s.dbType == mysqlDBType {
|
||||
query = query.Suffix("ON DUPLICATE KEY UPDATE enabled = ?, token = ?, modified_by = ?, update_at = ?", sharing.Enabled, sharing.Token, sharing.ModifiedBy, now)
|
||||
query = query.Suffix("ON DUPLICATE KEY UPDATE enabled = ?, token = ?, modified_by = ?, update_at = ?",
|
||||
sharing.Enabled, sharing.Token, sharing.ModifiedBy, now)
|
||||
} else {
|
||||
query = query.Suffix("ON CONFLICT (id) DO UPDATE SET enabled = EXCLUDED.enabled, token = EXCLUDED.token, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at")
|
||||
query = query.Suffix(
|
||||
`ON CONFLICT (id)
|
||||
DO UPDATE SET enabled = EXCLUDED.enabled, token = EXCLUDED.token, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at`,
|
||||
)
|
||||
}
|
||||
|
||||
_, err := query.Exec()
|
||||
|
@ -27,7 +27,7 @@ func SetupTests(t *testing.T) (store.Store, func()) {
|
||||
require.Nil(t, err)
|
||||
|
||||
tearDown := func() {
|
||||
defer logger.Shutdown()
|
||||
defer func() { _ = logger.Shutdown() }()
|
||||
err = store.Shutdown()
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ func (s *SQLStore) getUsersByCondition(condition sq.Eq) ([]*model.User, error) {
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetUserById(userID string) (*model.User, error) {
|
||||
func (s *SQLStore) GetUserByID(userID string) (*model.User, error) {
|
||||
return s.getUserByCondition(sq.Eq{"id": userID})
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,13 @@ func (s *SQLStore) UpsertWorkspaceSignupToken(workspace model.Workspace) error {
|
||||
now,
|
||||
)
|
||||
if s.dbType == mysqlDBType {
|
||||
query = query.Suffix("ON DUPLICATE KEY UPDATE signup_token = ?, modified_by = ?, update_at = ?", workspace.SignupToken, workspace.ModifiedBy, now)
|
||||
query = query.Suffix("ON DUPLICATE KEY UPDATE signup_token = ?, modified_by = ?, update_at = ?",
|
||||
workspace.SignupToken, workspace.ModifiedBy, now)
|
||||
} else {
|
||||
query = query.Suffix("ON CONFLICT (id) DO UPDATE SET signup_token = EXCLUDED.signup_token, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at")
|
||||
query = query.Suffix(
|
||||
`ON CONFLICT (id)
|
||||
DO UPDATE SET signup_token = EXCLUDED.signup_token, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at`,
|
||||
)
|
||||
}
|
||||
|
||||
_, err := query.Exec()
|
||||
@ -62,14 +66,17 @@ func (s *SQLStore) UpsertWorkspaceSettings(workspace model.Workspace) error {
|
||||
if s.dbType == mysqlDBType {
|
||||
query = query.Suffix("ON DUPLICATE KEY UPDATE settings = ?, modified_by = ?, update_at = ?", settingsJSON, workspace.ModifiedBy, now)
|
||||
} else {
|
||||
query = query.Suffix("ON CONFLICT (id) DO UPDATE SET settings = EXCLUDED.settings, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at")
|
||||
query = query.Suffix(
|
||||
`ON CONFLICT (id)
|
||||
DO UPDATE SET settings = EXCLUDED.settings, modified_by = EXCLUDED.modified_by, update_at = EXCLUDED.update_at`,
|
||||
)
|
||||
}
|
||||
|
||||
_, err = query.Exec()
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLStore) GetWorkspace(ID string) (*model.Workspace, error) {
|
||||
func (s *SQLStore) GetWorkspace(id string) (*model.Workspace, error) {
|
||||
var settingsJSON string
|
||||
|
||||
query := s.getQueryBuilder().
|
||||
@ -81,7 +88,7 @@ func (s *SQLStore) GetWorkspace(ID string) (*model.Workspace, error) {
|
||||
"update_at",
|
||||
).
|
||||
From(s.tablePrefix + "workspaces").
|
||||
Where(sq.Eq{"id": ID})
|
||||
Where(sq.Eq{"id": id})
|
||||
row := query.QueryRow()
|
||||
workspace := model.Workspace{}
|
||||
|
||||
|
@ -4,7 +4,7 @@ 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
|
||||
// Using a struct to make extending this easier in the future.
|
||||
type Container struct {
|
||||
WorkspaceID string
|
||||
}
|
||||
@ -30,7 +30,7 @@ type Store interface {
|
||||
SetSystemSetting(key, value string) error
|
||||
|
||||
GetRegisteredUserCount() (int, error)
|
||||
GetUserById(userID string) (*model.User, error)
|
||||
GetUserByID(userID string) (*model.User, error)
|
||||
GetUserByEmail(email string) (*model.User, error)
|
||||
GetUserByUsername(username string) (*model.User, error)
|
||||
CreateUser(user *model.User) error
|
||||
@ -44,7 +44,7 @@ type Store interface {
|
||||
CreateSession(session *model.Session) error
|
||||
RefreshSession(session *model.Session) error
|
||||
UpdateSession(session *model.Session) error
|
||||
DeleteSession(sessionId string) error
|
||||
DeleteSession(sessionID string) error
|
||||
CleanUpSessions(expireTime int64) error
|
||||
|
||||
UpsertSharing(c Container, sharing model.Sharing) error
|
||||
|
@ -19,7 +19,7 @@ func StoreTestSystemStore(t *testing.T, setup func(t *testing.T) (store.Store, f
|
||||
})
|
||||
}
|
||||
|
||||
func testSetGetSystemSettings(t *testing.T, store store.Store, container store.Container) {
|
||||
func testSetGetSystemSettings(t *testing.T, store store.Store, _ /*container*/ store.Container) {
|
||||
t.Run("Get empty settings", func(t *testing.T) {
|
||||
settings, err := store.GetSystemSettings()
|
||||
require.NoError(t, err)
|
||||
|
@ -39,10 +39,12 @@ func testGetWorkspaceUsers(t *testing.T, store store.Store) {
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
defer store.UpdateUser(&model.User{
|
||||
ID: userID,
|
||||
DeleteAt: time.Now().Unix(),
|
||||
})
|
||||
defer func() {
|
||||
_ = store.UpdateUser(&model.User{
|
||||
ID: userID,
|
||||
DeleteAt: time.Now().Unix(),
|
||||
})
|
||||
}()
|
||||
|
||||
users, err = store.GetUsersByWorkspace("workspace_1")
|
||||
require.Equal(t, 1, len(users))
|
||||
|
@ -79,7 +79,7 @@ func (ts *Service) sendDailyTelemetry(override bool) {
|
||||
func (ts *Service) sendTelemetry(event string, properties map[string]interface{}) {
|
||||
if ts.rudderClient != nil {
|
||||
var context *rudder.Context
|
||||
ts.rudderClient.Enqueue(rudder.Track{
|
||||
_ = ts.rudderClient.Enqueue(rudder.Track{
|
||||
Event: event,
|
||||
UserId: ts.telemetryID,
|
||||
Properties: properties,
|
||||
@ -103,7 +103,7 @@ func (ts *Service) initRudder(endpoint, rudderKey string) {
|
||||
ts.logger.Fatal("Failed to create Rudder instance")
|
||||
return
|
||||
}
|
||||
client.Enqueue(rudder.Identify{
|
||||
_ = client.Enqueue(rudder.Identify{
|
||||
UserId: ts.telemetryID,
|
||||
})
|
||||
|
||||
|
@ -3,6 +3,7 @@ package webhook
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/focalboard/server/model"
|
||||
@ -10,7 +11,7 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/mlog"
|
||||
)
|
||||
|
||||
// NotifyUpdate calls webhooks
|
||||
// NotifyUpdate calls webhooks.
|
||||
func (wh *Client) NotifyUpdate(block model.Block) {
|
||||
if len(wh.config.WebhookUpdate) < 1 {
|
||||
return
|
||||
@ -21,18 +22,21 @@ func (wh *Client) NotifyUpdate(block model.Block) {
|
||||
wh.logger.Fatal("NotifyUpdate: json.Marshal", mlog.Err(err))
|
||||
}
|
||||
for _, url := range wh.config.WebhookUpdate {
|
||||
http.Post(url, "application/json", bytes.NewBuffer(json))
|
||||
resp, _ := http.Post(url, "application/json", bytes.NewBuffer(json)) //nolint:gosec
|
||||
_, _ = ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
|
||||
wh.logger.Debug("webhook.NotifyUpdate", mlog.String("url", url))
|
||||
}
|
||||
}
|
||||
|
||||
// Client is a webhook client
|
||||
// Client is a webhook client.
|
||||
type Client struct {
|
||||
config *config.Configuration
|
||||
logger *mlog.Logger
|
||||
}
|
||||
|
||||
// NewClient creates a new Client
|
||||
// NewClient creates a new Client.
|
||||
func NewClient(config *config.Configuration, logger *mlog.Logger) *Client {
|
||||
return &Client{
|
||||
config: config,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -24,12 +25,11 @@ type RoutedService interface {
|
||||
type Server struct {
|
||||
http.Server
|
||||
|
||||
baseURL string
|
||||
rootPath string
|
||||
port int
|
||||
ssl bool
|
||||
localOnly bool
|
||||
logger *mlog.Logger
|
||||
baseURL string
|
||||
rootPath string
|
||||
port int
|
||||
ssl bool
|
||||
logger *mlog.Logger
|
||||
}
|
||||
|
||||
// NewServer creates a new instance of the webserver.
|
||||
@ -81,13 +81,13 @@ func (ws *Server) registerRoutes() {
|
||||
indexTemplate, err := template.New("index").ParseFiles(path.Join(ws.rootPath, "index.html"))
|
||||
if err != nil {
|
||||
ws.logger.Error("Unable to serve the index.html file", mlog.Err(err))
|
||||
w.WriteHeader(500)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
err = indexTemplate.ExecuteTemplate(w, "index.html", map[string]string{"BaseURL": ws.baseURL})
|
||||
if err != nil {
|
||||
ws.logger.Error("Unable to serve the index.html file", mlog.Err(err))
|
||||
w.WriteHeader(500)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
})
|
||||
@ -115,7 +115,7 @@ func (ws *Server) Start() {
|
||||
|
||||
ws.logger.Info("http server started", mlog.Int("port", ws.port))
|
||||
go func() {
|
||||
if err := ws.ListenAndServe(); err != http.ErrServerClosed {
|
||||
if err := ws.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
|
||||
ws.logger.Fatal("ListenAndServeTLS", mlog.Err(err))
|
||||
}
|
||||
ws.logger.Info("http server stopped")
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
"github.com/mattermost/focalboard/server/services/store"
|
||||
)
|
||||
|
||||
// IsValidSessionToken authenticates session tokens
|
||||
// IsValidSessionToken authenticates session tokens.
|
||||
type IsValidSessionToken func(token string) bool
|
||||
|
||||
type Hub interface {
|
||||
@ -36,20 +36,20 @@ type Server struct {
|
||||
logger *mlog.Logger
|
||||
}
|
||||
|
||||
// UpdateMsg is sent on block updates
|
||||
// UpdateMsg is sent on block updates.
|
||||
type UpdateMsg struct {
|
||||
Action string `json:"action"`
|
||||
Block model.Block `json:"block"`
|
||||
}
|
||||
|
||||
// clusterUpdateMsg is sent on block updates
|
||||
// clusterUpdateMsg is sent on block updates.
|
||||
type clusterUpdateMsg struct {
|
||||
UpdateMsg
|
||||
BlockID string `json:"block_id"`
|
||||
WorkspaceID string `json:"workspace_id"`
|
||||
}
|
||||
|
||||
// ErrorMsg is sent on errors
|
||||
// ErrorMsg is sent on errors.
|
||||
type ErrorMsg struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
@ -219,7 +219,7 @@ func (ws *Server) getAuthenticatedWorkspaceID(wsSession *websocketSession, comma
|
||||
workspaceID := command.WorkspaceID
|
||||
if len(workspaceID) == 0 {
|
||||
ws.logger.Error("getAuthenticatedWorkspaceID: No workspace")
|
||||
return "", errors.New("No workspace")
|
||||
return "", errors.New("no workspace")
|
||||
}
|
||||
|
||||
container := store.Container{
|
||||
@ -231,16 +231,16 @@ func (ws *Server) getAuthenticatedWorkspaceID(wsSession *websocketSession, comma
|
||||
for _, blockID := range command.BlockIDs {
|
||||
isValid, _ := ws.auth.IsValidReadToken(container, blockID, command.ReadToken)
|
||||
if !isValid {
|
||||
return "", errors.New("Invalid read token for workspace")
|
||||
return "", errors.New("invalid read token for workspace")
|
||||
}
|
||||
}
|
||||
return workspaceID, nil
|
||||
}
|
||||
|
||||
return "", errors.New("No read token")
|
||||
return "", errors.New("no read token")
|
||||
}
|
||||
|
||||
// TODO: Refactor workspace hashing
|
||||
// TODO: Refactor workspace hashing.
|
||||
func makeItemID(workspaceID, blockID string) string {
|
||||
return workspaceID + "-" + blockID
|
||||
}
|
||||
@ -283,7 +283,7 @@ func (ws *Server) removeListener(client *websocket.Conn) {
|
||||
ws.mu.Unlock()
|
||||
}
|
||||
|
||||
// removeListenerFromBlocks removes a webSocket listener from a set of block.
|
||||
// removeListenerFromBlocks removes a webSocket listener from a set of blocks.
|
||||
func (ws *Server) removeListenerFromBlocks(wsSession *websocketSession, command *WebsocketCommand) {
|
||||
workspaceID, err := ws.getAuthenticatedWorkspaceID(wsSession, command)
|
||||
if err != nil {
|
||||
@ -345,15 +345,13 @@ func (ws *Server) SetHub(hub Hub) {
|
||||
Block: msg.Block,
|
||||
}
|
||||
|
||||
if listeners != nil {
|
||||
for _, listener := range listeners {
|
||||
log.Printf("Broadcast change, workspaceID: %s, blockID: %s, remoteAddr: %s", msg.WorkspaceID, msg.BlockID, listener.RemoteAddr())
|
||||
for _, listener := range listeners {
|
||||
log.Printf("Broadcast change, workspaceID: %s, blockID: %s, remoteAddr: %s", msg.WorkspaceID, msg.BlockID, listener.RemoteAddr())
|
||||
|
||||
err := listener.WriteJSON(message)
|
||||
if err != nil {
|
||||
log.Printf("broadcast error: %v", err)
|
||||
listener.Close()
|
||||
}
|
||||
err := listener.WriteJSON(message)
|
||||
if err != nil {
|
||||
log.Printf("broadcast error: %v", err)
|
||||
listener.Close()
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -369,7 +367,7 @@ func (ws *Server) getListeners(workspaceID string, blockID string) []*websocket.
|
||||
return listeners
|
||||
}
|
||||
|
||||
// BroadcastBlockDelete broadcasts delete messages to clients
|
||||
// BroadcastBlockDelete broadcasts delete messages to clients.
|
||||
func (ws *Server) BroadcastBlockDelete(workspaceID, blockID, parentID string) {
|
||||
now := time.Now().Unix()
|
||||
block := model.Block{}
|
||||
@ -381,7 +379,7 @@ func (ws *Server) BroadcastBlockDelete(workspaceID, blockID, parentID string) {
|
||||
ws.BroadcastBlockChange(workspaceID, block)
|
||||
}
|
||||
|
||||
// BroadcastBlockChange broadcasts update messages to clients
|
||||
// BroadcastBlockChange broadcasts update messages to clients.
|
||||
func (ws *Server) BroadcastBlockChange(workspaceID string, block model.Block) {
|
||||
blockIDsToNotify := []string{block.ID, block.ParentID}
|
||||
|
||||
@ -404,19 +402,17 @@ func (ws *Server) BroadcastBlockChange(workspaceID string, block model.Block) {
|
||||
ws.hub.SendWSMessage(data)
|
||||
}
|
||||
|
||||
if listeners != nil {
|
||||
for _, listener := range listeners {
|
||||
ws.logger.Debug("Broadcast change",
|
||||
mlog.String("workspaceID", workspaceID),
|
||||
mlog.String("blockID", blockID),
|
||||
mlog.Stringer("remoteAddr", listener.RemoteAddr()),
|
||||
)
|
||||
for _, listener := range listeners {
|
||||
ws.logger.Debug("Broadcast change",
|
||||
mlog.String("workspaceID", workspaceID),
|
||||
mlog.String("blockID", blockID),
|
||||
mlog.Stringer("remoteAddr", listener.RemoteAddr()),
|
||||
)
|
||||
|
||||
err := listener.WriteJSON(message)
|
||||
if err != nil {
|
||||
ws.logger.Error("broadcast error", mlog.Err(err))
|
||||
listener.Close()
|
||||
}
|
||||
err := listener.WriteJSON(message)
|
||||
if err != nil {
|
||||
ws.logger.Error("broadcast error", mlog.Err(err))
|
||||
listener.Close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user