diff --git a/server/app/helper_test.go b/server/app/helper_test.go index 43b46e9e..828e948a 100644 --- a/server/app/helper_test.go +++ b/server/app/helper_test.go @@ -36,8 +36,7 @@ func SetupTestHelper(t *testing.T) (*TestHelper, func()) { filesBackend := &mocks.FileBackend{} auth := auth.New(&cfg, store, nil) logger, _ := mlog.NewLogger() - sessionToken := "TESTTOKEN" - wsserver := ws.NewServer(auth, sessionToken, false, logger, store) + wsserver := ws.NewServer(auth, logger, store) webhook := webhook.NewClient(&cfg, logger) metricsService := metrics.NewMetrics(metrics.InstanceInfo{}) diff --git a/server/server/initHandlers.go b/server/server/initHandlers.go index e891032a..6f71a462 100644 --- a/server/server/initHandlers.go +++ b/server/server/initHandlers.go @@ -1,6 +1,5 @@ package server func (s *Server) initHandlers() { - cfg := s.config - s.api.MattermostAuth = cfg.AuthMode == MattermostAuthMod + s.api.MattermostAuth = true } diff --git a/server/server/server.go b/server/server/server.go index b5838bf2..2139b0f8 100644 --- a/server/server/server.go +++ b/server/server/server.go @@ -40,10 +40,6 @@ import ( const ( cleanupSessionTaskFrequency = 10 * time.Minute updateMetricsTaskFrequency = 15 * time.Minute - - minSessionExpiryTime = int64(60 * 60 * 24 * 31) // 31 days - - MattermostAuthMod = "mattermost" ) type Server struct { @@ -78,7 +74,7 @@ func New(params Params) (*Server, error) { // if no ws adapter is provided, we spin up a websocket server wsAdapter := params.WSAdapter if wsAdapter == nil { - wsAdapter = ws.NewServer(authenticator, params.SingleUserToken, params.Cfg.AuthMode == MattermostAuthMod, params.Logger, params.DBStore) + wsAdapter = ws.NewServer(authenticator, params.Logger, params.DBStore) } filesBackendSettings := filestore.FileBackendSettings{} @@ -253,19 +249,6 @@ func (s *Server) Start() error { } } - if s.config.AuthMode != MattermostAuthMod { - s.cleanUpSessionsTask = scheduler.CreateRecurringTask("cleanUpSessions", func() { - secondsAgo := minSessionExpiryTime - if secondsAgo < s.config.SessionExpireTime { - secondsAgo = s.config.SessionExpireTime - } - - if err := s.store.CleanUpSessions(secondsAgo); err != nil { - s.logger.Error("Unable to clean up the sessions", mlog.Err(err)) - } - }, cleanupSessionTaskFrequency) - } - metricsUpdater := func() { blockCounts, err := s.store.GetBlockCountsByType() if err != nil { diff --git a/server/services/store/sqlstore/board.go b/server/services/store/sqlstore/board.go index 48998c68..42896baa 100644 --- a/server/services/store/sqlstore/board.go +++ b/server/services/store/sqlstore/board.go @@ -234,36 +234,6 @@ func (s *SQLStore) getBoard(db sq.BaseRunner, boardID string) (*model.Board, err return s.getBoardByCondition(db, sq.Eq{"id": boardID}) } -func (s *SQLStore) getBoardsForUserAndTeam(db sq.BaseRunner, userID, teamID string, includePublicBoards bool) ([]*model.Board, error) { - query := s.getQueryBuilder(db). - Select(boardFields("b.")...). - Distinct(). - From(s.tablePrefix + "boards as b"). - LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id"). - Where(sq.Eq{"b.team_id": teamID}). - Where(sq.Eq{"b.is_template": false}) - - if includePublicBoards { - query = query.Where(sq.Or{ - sq.Eq{"b.type": model.BoardTypeOpen}, - sq.Eq{"bm.user_id": userID}, - }) - } else { - query = query.Where(sq.Or{ - sq.Eq{"bm.user_id": userID}, - }) - } - - rows, err := query.Query() - if err != nil { - s.logger.Error(`getBoardsForUserAndTeam ERROR`, mlog.Err(err)) - return nil, err - } - defer s.CloseRows(rows) - - return s.boardsFromRows(rows) -} - func (s *SQLStore) getBoardsInTeamByIds(db sq.BaseRunner, boardIDs []string, teamID string) ([]*model.Board, error) { query := s.getQueryBuilder(db). Select(boardFields("b.")...). @@ -646,112 +616,6 @@ func (s *SQLStore) getMembersForBoard(db sq.BaseRunner, boardID string) ([]*mode return s.boardMembersFromRows(rows) } -// searchBoardsForUser returns all boards that match with the -// term that are either private and which the user is a member of, or -// they're open, regardless of the user membership. -// Search is case-insensitive. -func (s *SQLStore) searchBoardsForUser(db sq.BaseRunner, term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) { - query := s.getQueryBuilder(db). - Select(boardFields("b.")...). - Distinct(). - From(s.tablePrefix + "boards as b"). - LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id"). - Where(sq.Eq{"b.is_template": false}) - - if includePublicBoards { - query = query.Where(sq.Or{ - sq.Eq{"b.type": model.BoardTypeOpen}, - sq.Eq{"bm.user_id": userID}, - }) - } else { - query = query.Where(sq.Or{ - sq.Eq{"bm.user_id": userID}, - }) - } - - if term != "" { - if searchField == model.BoardSearchFieldPropertyName { - switch s.dbType { - case model.PostgresDBType: - where := "b.properties->? is not null" - query = query.Where(where, term) - case model.MysqlDBType, model.SqliteDBType: - where := "JSON_EXTRACT(b.properties, ?) IS NOT NULL" - query = query.Where(where, "$."+term) - default: - where := "b.properties LIKE ?" - query = query.Where(where, "%\""+term+"\"%") - } - } else { // model.BoardSearchFieldTitle - // break search query into space separated words - // and search for all words. - // This should later be upgraded to industrial-strength - // word tokenizer, that uses much more than space - // to break words. - conditions := sq.And{} - for _, word := range strings.Split(strings.TrimSpace(term), " ") { - conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"}) - } - query = query.Where(conditions) - } - } - - rows, err := query.Query() - if err != nil { - s.logger.Error(`searchBoardsForUser ERROR`, mlog.Err(err)) - return nil, err - } - defer s.CloseRows(rows) - - return s.boardsFromRows(rows) -} - -// searchBoardsForUserInTeam returns all boards that match with the -// term that are either private and which the user is a member of, or -// they're open, regardless of the user membership. -// Search is case-insensitive. -func (s *SQLStore) searchBoardsForUserInTeam(db sq.BaseRunner, teamID, term, userID string) ([]*model.Board, error) { - query := s.getQueryBuilder(db). - Select(boardFields("b.")...). - Distinct(). - From(s.tablePrefix + "boards as b"). - LeftJoin(s.tablePrefix + "board_members as bm on b.id=bm.board_id"). - Where(sq.Eq{"b.is_template": false}). - Where(sq.Eq{"b.team_id": teamID}). - Where(sq.Or{ - sq.Eq{"b.type": model.BoardTypeOpen}, - sq.And{ - sq.Eq{"b.type": model.BoardTypePrivate}, - sq.Eq{"bm.user_id": userID}, - }, - }) - - if term != "" { - // break search query into space separated words - // and search for all words. - // This should later be upgraded to industrial-strength - // word tokenizer, that uses much more than space - // to break words. - - conditions := sq.And{} - - for _, word := range strings.Split(strings.TrimSpace(term), " ") { - conditions = append(conditions, sq.Like{"lower(b.title)": "%" + strings.ToLower(word) + "%"}) - } - - query = query.Where(conditions) - } - - rows, err := query.Query() - if err != nil { - s.logger.Error(`searchBoardsForUser ERROR`, mlog.Err(err)) - return nil, err - } - defer s.CloseRows(rows) - - return s.boardsFromRows(rows) -} - func (s *SQLStore) getBoardHistory(db sq.BaseRunner, boardID string, opts model.QueryBoardHistoryOptions) ([]*model.Board, error) { var order string if opts.Descending { diff --git a/server/services/store/sqlstore/file.go b/server/services/store/sqlstore/file.go deleted file mode 100644 index 72645690..00000000 --- a/server/services/store/sqlstore/file.go +++ /dev/null @@ -1,92 +0,0 @@ -package sqlstore - -import ( - "database/sql" - "errors" - - sq "github.com/Masterminds/squirrel" - - "github.com/mattermost/mattermost-plugin-boards/server/model" - - mmModel "github.com/mattermost/mattermost/server/public/model" - "github.com/mattermost/mattermost/server/public/shared/mlog" -) - -func (s *SQLStore) saveFileInfo(db sq.BaseRunner, fileInfo *mmModel.FileInfo) error { - query := s.getQueryBuilder(db). - Insert(s.tablePrefix+"file_info"). - Columns( - "id", - "create_at", - "name", - "extension", - "size", - "delete_at", - "path", - "archived", - ). - Values( - fileInfo.Id, - fileInfo.CreateAt, - fileInfo.Name, - fileInfo.Extension, - fileInfo.Size, - fileInfo.DeleteAt, - fileInfo.Path, - false, - ) - - if _, err := query.Exec(); err != nil { - s.logger.Error( - "failed to save fileinfo", - mlog.String("file_name", fileInfo.Name), - mlog.Int("size", fileInfo.Size), - mlog.Err(err), - ) - return err - } - - return nil -} - -func (s *SQLStore) getFileInfo(db sq.BaseRunner, id string) (*mmModel.FileInfo, error) { - query := s.getQueryBuilder(db). - Select( - "id", - "create_at", - "delete_at", - "name", - "extension", - "size", - "archived", - "path", - ). - From(s.tablePrefix + "file_info"). - Where(sq.Eq{"Id": id}) - - row := query.QueryRow() - - fileInfo := mmModel.FileInfo{} - - err := row.Scan( - &fileInfo.Id, - &fileInfo.CreateAt, - &fileInfo.DeleteAt, - &fileInfo.Name, - &fileInfo.Extension, - &fileInfo.Size, - &fileInfo.Archived, - &fileInfo.Path, - ) - - if err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, model.NewErrNotFound("file info ID=" + id) - } - - s.logger.Error("error scanning fileinfo row", mlog.String("id", id), mlog.Err(err)) - return nil, err - } - - return &fileInfo, nil -} diff --git a/server/services/store/sqlstore/public_methods.go b/server/services/store/sqlstore/public_methods.go index 45e1b53c..98229f18 100644 --- a/server/services/store/sqlstore/public_methods.go +++ b/server/services/store/sqlstore/public_methods.go @@ -14,6 +14,7 @@ package sqlstore import ( "context" + "errors" "time" "github.com/mattermost/mattermost-plugin-boards/server/model" @@ -47,12 +48,12 @@ func (s *SQLStore) AddUpdateCategoryBoard(userID string, categoryID string, boar } func (s *SQLStore) CanSeeUser(seerID string, seenID string) (bool, error) { - return s.canSeeUser(s.db, seerID, seenID) + return false, errors.New("can see user not supported in focalboard, will fetch from mattermost") } func (s *SQLStore) CleanUpSessions(expireTime int64) error { - return s.cleanUpSessions(s.db, expireTime) + return errors.New("no clean up sessions allowed from focalboard, update it using mattermost") } @@ -129,7 +130,7 @@ func (s *SQLStore) CreateCategory(category model.Category) error { } func (s *SQLStore) CreateSession(session *model.Session) error { - return s.createSession(s.db, session) + return errors.New("no update allowed from focalboard, update it using mattermost") } @@ -139,7 +140,7 @@ func (s *SQLStore) CreateSubscription(sub *model.Subscription) (*model.Subscript } func (s *SQLStore) CreateUser(user *model.User) (*model.User, error) { - return s.createUser(s.db, user) + return nil, errors.New("no user creation allowed from focalboard, create it using mattermost") } @@ -241,7 +242,7 @@ func (s *SQLStore) DeleteNotificationHint(blockID string) error { } func (s *SQLStore) DeleteSession(sessionID string) error { - return s.deleteSession(s.db, sessionID) + return errors.New("no delete session allowed from focalboard, update it using mattermost") } @@ -299,7 +300,7 @@ func (s *SQLStore) DuplicateBoard(boardID string, userID string, toTeam string, } func (s *SQLStore) GetActiveUserCount(updatedSecondsAgo int64) (int, error) { - return s.getActiveUserCount(s.db, updatedSecondsAgo) + return 0, errors.New("active user count not supported in focalboard when using plugin mode, will fetch from mattermost") } @@ -409,7 +410,7 @@ func (s *SQLStore) GetBoardsForCompliance(opts model.QueryBoardsForComplianceOpt } func (s *SQLStore) GetBoardsForUserAndTeam(userID string, teamID string, includePublicBoards bool) ([]*model.Board, error) { - return s.getBoardsForUserAndTeam(s.db, userID, teamID, includePublicBoards) + return nil, errors.New("boards for user and team will be fetch from mattermost not from focalboard while using in plugin mode") } @@ -429,17 +430,17 @@ func (s *SQLStore) GetCategory(id string) (*model.Category, error) { } func (s *SQLStore) GetChannel(teamID string, channelID string) (*mmModel.Channel, error) { - return s.getChannel(s.db, teamID, channelID) + return nil, errors.New("channel will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetFileInfo(id string) (*mmModel.FileInfo, error) { - return s.getFileInfo(s.db, id) + return nil, errors.New("file info will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetLicense() *mmModel.License { - return s.getLicense(s.db) + return nil } @@ -469,12 +470,12 @@ func (s *SQLStore) GetNotificationHint(blockID string) (*model.NotificationHint, } func (s *SQLStore) GetRegisteredUserCount() (int, error) { - return s.getRegisteredUserCount(s.db) + return 0, errors.New("registered user count not supported in focalboard, will fetch from mattermost") } func (s *SQLStore) GetSession(token string, expireTime int64) (*model.Session, error) { - return s.getSession(s.db, token, expireTime) + return nil, errors.New("sessions not used when using mattermost") } @@ -519,7 +520,7 @@ func (s *SQLStore) GetSystemSettings() (map[string]string, error) { } func (s *SQLStore) GetTeam(ID string) (*model.Team, error) { - return s.getTeam(s.db, ID) + return nil, errors.New("team will be fetch from mattermost not from focalboard while using in plugin mode") } @@ -529,7 +530,7 @@ func (s *SQLStore) GetTeamCount() (int64, error) { } func (s *SQLStore) GetTeamsForUser(userID string) ([]*model.Team, error) { - return s.getTeamsForUser(s.db, userID) + return nil, errors.New("teams for user will be fetch from mattermost not from focalboard while using in plugin mode") } @@ -544,17 +545,17 @@ func (s *SQLStore) GetUsedCardsCount() (int, error) { } func (s *SQLStore) GetUserByEmail(email string) (*model.User, error) { - return s.getUserByEmail(s.db, email) + return nil, errors.New("user email will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetUserByID(userID string) (*model.User, error) { - return s.getUserByID(s.db, userID) + return nil, errors.New("user id will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetUserByUsername(username string) (*model.User, error) { - return s.getUserByUsername(s.db, username) + return nil, errors.New("user username will be fetch from mattermost not from focalboard while using in plugin mode") } @@ -569,22 +570,22 @@ func (s *SQLStore) GetUserCategoryBoards(userID string, teamID string) ([]model. } func (s *SQLStore) GetUserPreferences(userID string) (mmModel.Preferences, error) { - return s.getUserPreferences(s.db, userID) + return nil, errors.New("user preferences will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetUserTimezone(userID string) (string, error) { - return s.getUserTimezone(s.db, userID) + return "", errors.New("user timezone will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetUsersByTeam(teamID string, asGuestID string, showEmail bool, showName bool) ([]*model.User, error) { - return s.getUsersByTeam(s.db, teamID, asGuestID, showEmail, showName) + return nil, errors.New("users by team will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) GetUsersList(userIDs []string, showEmail bool, showName bool) ([]*model.User, error) { - return s.getUsersList(s.db, userIDs, showEmail, showName) + return nil, errors.New("users list will be fetch from mattermost not from focalboard while using in plugin mode") } @@ -762,17 +763,17 @@ func (s *SQLStore) PatchBoardsAndBlocks(pbab *model.PatchBoardsAndBlocks, userID } func (s *SQLStore) PatchUserPreferences(userID string, patch model.UserPreferencesPatch) (mmModel.Preferences, error) { - return s.patchUserPreferences(s.db, userID, patch) + return nil, errors.New("no patch allowed from focalboard, patch it using mattermost") } func (s *SQLStore) PostMessage(message string, postType string, channelID string) error { - return s.postMessage(s.db, message, postType, channelID) + return errors.New("no post message allowed from focalboard, post it using mattermost") } func (s *SQLStore) RefreshSession(session *model.Session) error { - return s.refreshSession(s.db, session) + return errors.New("no update allowed from focalboard, update it using mattermost") } @@ -816,7 +817,7 @@ func (s *SQLStore) RunDataRetention(globalRetentionDate int64, batchSize int64) } func (s *SQLStore) SaveFileInfo(fileInfo *mmModel.FileInfo) error { - return s.saveFileInfo(s.db, fileInfo) + return errors.New("no save file info allowed from focalboard, save it using mattermost") } @@ -826,27 +827,27 @@ func (s *SQLStore) SaveMember(bm *model.BoardMember) (*model.BoardMember, error) } func (s *SQLStore) SearchBoardsForUser(term string, searchField model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) { - return s.searchBoardsForUser(s.db, term, searchField, userID, includePublicBoards) + return nil, errors.New("searching boards for user will be using from mattermost not from focalboard in plugin mode") } func (s *SQLStore) SearchBoardsForUserInTeam(teamID string, term string, userID string) ([]*model.Board, error) { - return s.searchBoardsForUserInTeam(s.db, teamID, term, userID) + return nil, errors.New("searching boards for user in team will be using from mattermost not from focalboard in plugin mode") } func (s *SQLStore) SearchUserChannels(teamID string, userID string, query string) ([]*mmModel.Channel, error) { - return s.searchUserChannels(s.db, teamID, userID, query) + return nil, errors.New("searching user channels will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) SearchUsersByTeam(teamID string, searchQuery string, asGuestID string, excludeBots bool, showEmail bool, showName bool) ([]*model.User, error) { - return s.searchUsersByTeam(s.db, teamID, searchQuery, asGuestID, excludeBots, showEmail, showName) + return nil, errors.New("searching users by team will be fetch from mattermost not from focalboard while using in plugin mode") } func (s *SQLStore) SendMessage(message string, postType string, receipts []string) error { - return s.sendMessage(s.db, message, postType, receipts) + return errors.New("no send message allowed from focalboard, send it using mattermost") } @@ -919,7 +920,7 @@ func (s *SQLStore) UpdateCategory(category model.Category) error { } func (s *SQLStore) UpdateSession(session *model.Session) error { - return s.updateSession(s.db, session) + return errors.New("no update allowed from focalboard, update it using mattermost") } @@ -929,17 +930,17 @@ func (s *SQLStore) UpdateSubscribersNotifiedAt(blockID string, notifiedAt int64) } func (s *SQLStore) UpdateUser(user *model.User) (*model.User, error) { - return s.updateUser(s.db, user) + return nil, errors.New("no update allowed from focalboard, update it using mattermost") } func (s *SQLStore) UpdateUserPassword(username string, password string) error { - return s.updateUserPassword(s.db, username, password) + return errors.New("no update allowed from focalboard, update it using mattermost") } func (s *SQLStore) UpdateUserPasswordByID(userID string, password string) error { - return s.updateUserPasswordByID(s.db, userID, password) + return errors.New("no update allowed from focalboard, update it using mattermost") } diff --git a/server/services/store/sqlstore/session.go b/server/services/store/sqlstore/session.go deleted file mode 100644 index f87b68eb..00000000 --- a/server/services/store/sqlstore/session.go +++ /dev/null @@ -1,111 +0,0 @@ -package sqlstore - -import ( - "encoding/json" - - sq "github.com/Masterminds/squirrel" - "github.com/mattermost/mattermost-plugin-boards/server/model" - "github.com/mattermost/mattermost-plugin-boards/server/utils" -) - -// GetActiveUserCount returns the number of users with active sessions within N seconds ago. -func (s *SQLStore) getActiveUserCount(db sq.BaseRunner, updatedSecondsAgo int64) (int, error) { - query := s.getQueryBuilder(db). - Select("count(distinct user_id)"). - From(s.tablePrefix + "sessions"). - Where(sq.Gt{"update_at": utils.GetMillis() - utils.SecondsToMillis(updatedSecondsAgo)}) - - row := query.QueryRow() - - var count int - err := row.Scan(&count) - if err != nil { - return 0, err - } - - return count, nil -} - -func (s *SQLStore) getSession(db sq.BaseRunner, token string, expireTimeSeconds int64) (*model.Session, error) { - query := s.getQueryBuilder(db). - Select("id", "token", "user_id", "auth_service", "props"). - From(s.tablePrefix + "sessions"). - Where(sq.Eq{"token": token}). - Where(sq.Gt{"update_at": utils.GetMillis() - utils.SecondsToMillis(expireTimeSeconds)}) - - row := query.QueryRow() - session := model.Session{} - - var propsBytes []byte - err := row.Scan(&session.ID, &session.Token, &session.UserID, &session.AuthService, &propsBytes) - if err != nil { - return nil, err - } - - err = json.Unmarshal(propsBytes, &session.Props) - if err != nil { - return nil, err - } - - return &session, nil -} - -func (s *SQLStore) createSession(db sq.BaseRunner, session *model.Session) error { - now := utils.GetMillis() - - propsBytes, err := json.Marshal(session.Props) - if err != nil { - return err - } - - query := s.getQueryBuilder(db).Insert(s.tablePrefix+"sessions"). - Columns("id", "token", "user_id", "auth_service", "props", "create_at", "update_at"). - Values(session.ID, session.Token, session.UserID, session.AuthService, propsBytes, now, now) - - _, err = query.Exec() - return err -} - -func (s *SQLStore) refreshSession(db sq.BaseRunner, session *model.Session) error { - now := utils.GetMillis() - - query := s.getQueryBuilder(db).Update(s.tablePrefix+"sessions"). - Where(sq.Eq{"token": session.Token}). - Set("update_at", now) - - _, err := query.Exec() - return err -} - -func (s *SQLStore) updateSession(db sq.BaseRunner, session *model.Session) error { - now := utils.GetMillis() - - propsBytes, err := json.Marshal(session.Props) - if err != nil { - return err - } - - query := s.getQueryBuilder(db).Update(s.tablePrefix+"sessions"). - Where(sq.Eq{"token": session.Token}). - Set("update_at", now). - Set("props", propsBytes) - - _, err = query.Exec() - return err -} - -func (s *SQLStore) deleteSession(db sq.BaseRunner, sessionID string) error { - query := s.getQueryBuilder(db).Delete(s.tablePrefix + "sessions"). - Where(sq.Eq{"id": sessionID}) - - _, err := query.Exec() - return err -} - -func (s *SQLStore) cleanUpSessions(db sq.BaseRunner, expireTimeSeconds int64) error { - query := s.getQueryBuilder(db).Delete(s.tablePrefix + "sessions"). - Where(sq.Lt{"update_at": utils.GetMillis() - utils.SecondsToMillis(expireTimeSeconds)}) - - _, err := query.Exec() - return err -} diff --git a/server/services/store/sqlstore/sqlstore.go b/server/services/store/sqlstore/sqlstore.go index d9b43a35..a0148c2c 100644 --- a/server/services/store/sqlstore/sqlstore.go +++ b/server/services/store/sqlstore/sqlstore.go @@ -9,7 +9,6 @@ import ( sq "github.com/Masterminds/squirrel" "github.com/mattermost/mattermost-plugin-boards/server/model" - "github.com/mattermost/mattermost-plugin-boards/server/services/store" "github.com/mattermost/mattermost/server/public/pluginapi/cluster" mmModel "github.com/mattermost/mattermost/server/public/model" @@ -171,18 +170,6 @@ func (s *SQLStore) elementInColumn(column string) string { return "" } -func (s *SQLStore) getLicense(db sq.BaseRunner) *mmModel.License { - return nil -} - -func (s *SQLStore) searchUserChannels(db sq.BaseRunner, teamID, userID, query string) ([]*mmModel.Channel, error) { - return nil, store.NewNotSupportedError("search user channels not supported on standalone mode") -} - -func (s *SQLStore) getChannel(db sq.BaseRunner, teamID, channel string) (*mmModel.Channel, error) { - return nil, store.NewNotSupportedError("get channel not supported on standalone mode") -} - func (s *SQLStore) DBVersion() string { var version string var row *sql.Row diff --git a/server/services/store/sqlstore/team.go b/server/services/store/sqlstore/team.go index 3702d04c..7a6c8d59 100644 --- a/server/services/store/sqlstore/team.go +++ b/server/services/store/sqlstore/team.go @@ -91,46 +91,6 @@ func (s *SQLStore) upsertTeamSettings(db sq.BaseRunner, team model.Team) error { return err } -func (s *SQLStore) getTeam(db sq.BaseRunner, id string) (*model.Team, error) { - var settingsJSON string - - query := s.getQueryBuilder(db). - Select( - "id", - "signup_token", - "COALESCE(settings, '{}')", - "modified_by", - "update_at", - ). - From(s.tablePrefix + "teams"). - Where(sq.Eq{"id": id}) - row := query.QueryRow() - team := model.Team{} - - err := row.Scan( - &team.ID, - &team.SignupToken, - &settingsJSON, - &team.ModifiedBy, - &team.UpdateAt, - ) - if err != nil { - return nil, err - } - - err = json.Unmarshal([]byte(settingsJSON), &team.Settings) - if err != nil { - s.logger.Error(`ERROR GetTeam settings json.Unmarshal`, mlog.Err(err)) - return nil, err - } - - return &team, nil -} - -func (s *SQLStore) getTeamsForUser(db sq.BaseRunner, _ string) ([]*model.Team, error) { - return s.getAllTeams(db) -} - func (s *SQLStore) getTeamCount(db sq.BaseRunner) (int64, error) { query := s.getQueryBuilder(db). Select( diff --git a/server/services/store/sqlstore/user.go b/server/services/store/sqlstore/user.go index 849d8191..ef5e747f 100644 --- a/server/services/store/sqlstore/user.go +++ b/server/services/store/sqlstore/user.go @@ -1,23 +1,7 @@ package sqlstore import ( - "database/sql" - "errors" "fmt" - - mmModel "github.com/mattermost/mattermost/server/public/model" - "github.com/mattermost/mattermost/server/v8/channels/store" - - sq "github.com/Masterminds/squirrel" - - "github.com/mattermost/mattermost-plugin-boards/server/model" - "github.com/mattermost/mattermost-plugin-boards/server/utils" - - "github.com/mattermost/mattermost/server/public/shared/mlog" -) - -var ( - errUnsupportedOperation = errors.New("unsupported operation") ) type UserNotFoundError struct { @@ -27,393 +11,3 @@ type UserNotFoundError struct { func (unf UserNotFoundError) Error() string { return fmt.Sprintf("user not found (%s)", unf.id) } - -func (s *SQLStore) getRegisteredUserCount(db sq.BaseRunner) (int, error) { - query := s.getQueryBuilder(db). - Select("count(*)"). - From(s.tablePrefix + "users"). - Where(sq.Eq{"delete_at": 0}) - row := query.QueryRow() - - var count int - err := row.Scan(&count) - if err != nil { - return 0, err - } - - return count, nil -} - -func (s *SQLStore) getUserByCondition(db sq.BaseRunner, condition sq.Eq) (*model.User, error) { - users, err := s.getUsersByCondition(db, condition, 0) - if err != nil { - return nil, err - } - - if len(users) == 0 { - return nil, model.NewErrNotFound("user") - } - - return users[0], nil -} - -func (s *SQLStore) getUsersByCondition(db sq.BaseRunner, condition interface{}, limit uint64) ([]*model.User, error) { - query := s.getQueryBuilder(db). - Select( - "id", - "username", - "email", - "password", - "mfa_secret", - "auth_service", - "auth_data", - "create_at", - "update_at", - "delete_at", - ). - From(s.tablePrefix + "users"). - Where(sq.Eq{"delete_at": 0}). - Where(condition) - - if limit != 0 { - query = query.Limit(limit) - } - - rows, err := query.Query() - if err != nil { - s.logger.Error(`getUsersByCondition ERROR`, mlog.Err(err)) - return nil, err - } - defer s.CloseRows(rows) - - users, err := s.usersFromRows(rows) - if err != nil { - return nil, err - } - - if len(users) == 0 { - return nil, model.NewErrNotFound("user") - } - - return users, nil -} - -func (s *SQLStore) getUserByID(db sq.BaseRunner, userID string) (*model.User, error) { - return s.getUserByCondition(db, sq.Eq{"id": userID}) -} - -func (s *SQLStore) getUsersList(db sq.BaseRunner, userIDs []string, _, _ bool) ([]*model.User, error) { - users, err := s.getUsersByCondition(db, sq.Eq{"id": userIDs}, 0) - if err != nil { - return nil, err - } - - if len(users) != len(userIDs) { - return users, model.NewErrNotAllFound("user", userIDs) - } - - return users, nil -} - -func (s *SQLStore) getUserByEmail(db sq.BaseRunner, email string) (*model.User, error) { - return s.getUserByCondition(db, sq.Eq{"email": email}) -} - -func (s *SQLStore) getUserByUsername(db sq.BaseRunner, username string) (*model.User, error) { - return s.getUserByCondition(db, sq.Eq{"username": username}) -} - -func (s *SQLStore) createUser(db sq.BaseRunner, user *model.User) (*model.User, error) { - now := utils.GetMillis() - user.CreateAt = now - user.UpdateAt = now - user.DeleteAt = 0 - - query := s.getQueryBuilder(db).Insert(s.tablePrefix+"users"). - Columns("id", "username", "email", "password", "mfa_secret", "auth_service", "auth_data", "create_at", "update_at", "delete_at"). - Values(user.ID, user.Username, user.Email, user.Password, user.MfaSecret, user.AuthService, user.AuthData, user.CreateAt, user.UpdateAt, user.DeleteAt) - - _, err := query.Exec() - return user, err -} - -func (s *SQLStore) updateUser(db sq.BaseRunner, user *model.User) (*model.User, error) { - now := utils.GetMillis() - user.UpdateAt = now - - query := s.getQueryBuilder(db).Update(s.tablePrefix+"users"). - Set("username", user.Username). - Set("email", user.Email). - Set("update_at", user.UpdateAt). - Where(sq.Eq{"id": user.ID}) - - result, err := query.Exec() - if err != nil { - return nil, err - } - - rowCount, err := result.RowsAffected() - if err != nil { - return nil, err - } - - if rowCount < 1 { - return nil, UserNotFoundError{user.ID} - } - - return user, nil -} - -func (s *SQLStore) updateUserPassword(db sq.BaseRunner, username, password string) error { - now := utils.GetMillis() - - query := s.getQueryBuilder(db).Update(s.tablePrefix+"users"). - Set("password", password). - Set("update_at", now). - Where(sq.Eq{"username": username}) - - result, err := query.Exec() - if err != nil { - return err - } - - rowCount, err := result.RowsAffected() - if err != nil { - return err - } - - if rowCount < 1 { - return UserNotFoundError{username} - } - - return nil -} - -func (s *SQLStore) updateUserPasswordByID(db sq.BaseRunner, userID, password string) error { - now := utils.GetMillis() - - query := s.getQueryBuilder(db).Update(s.tablePrefix+"users"). - Set("password", password). - Set("update_at", now). - Where(sq.Eq{"id": userID}) - - result, err := query.Exec() - if err != nil { - return err - } - - rowCount, err := result.RowsAffected() - if err != nil { - return err - } - - if rowCount < 1 { - return UserNotFoundError{userID} - } - - return nil -} - -func (s *SQLStore) getUsersByTeam(db sq.BaseRunner, _ string, _ string, _, _ bool) ([]*model.User, error) { - users, err := s.getUsersByCondition(db, nil, 0) - if model.IsErrNotFound(err) { - return []*model.User{}, nil - } - - return users, err -} - -func (s *SQLStore) searchUsersByTeam(db sq.BaseRunner, _ string, searchQuery string, _ string, _, _, _ bool) ([]*model.User, error) { - users, err := s.getUsersByCondition(db, &sq.Like{"username": "%" + searchQuery + "%"}, 10) - if model.IsErrNotFound(err) { - return []*model.User{}, nil - } - - return users, err -} - -func (s *SQLStore) usersFromRows(rows *sql.Rows) ([]*model.User, error) { - users := []*model.User{} - - for rows.Next() { - var user model.User - - err := rows.Scan( - &user.ID, - &user.Username, - &user.Email, - &user.Password, - &user.MfaSecret, - &user.AuthService, - &user.AuthData, - &user.CreateAt, - &user.UpdateAt, - &user.DeleteAt, - ) - if err != nil { - return nil, err - } - - users = append(users, &user) - } - - return users, nil -} - -func (s *SQLStore) patchUserPreferences(db sq.BaseRunner, userID string, patch model.UserPreferencesPatch) (mmModel.Preferences, error) { - preferences, err := s.getUserPreferences(db, userID) - if err != nil { - return nil, err - } - - if len(patch.UpdatedFields) > 0 { - for key, value := range patch.UpdatedFields { - preference := mmModel.Preference{ - UserId: userID, - Category: model.PreferencesCategoryFocalboard, - Name: key, - Value: value, - } - - if err := s.updateUserPreference(db, preference); err != nil { - return nil, err - } - - newPreferences := mmModel.Preferences{} - for _, existingPreference := range preferences { - if preference.Name != existingPreference.Name { - newPreferences = append(newPreferences, existingPreference) - } - } - newPreferences = append(newPreferences, preference) - preferences = newPreferences - } - } - - if len(patch.DeletedFields) > 0 { - for _, key := range patch.DeletedFields { - preference := mmModel.Preference{ - UserId: userID, - Category: model.PreferencesCategoryFocalboard, - Name: key, - } - - if err := s.deleteUserPreference(db, preference); err != nil { - return nil, err - } - - newPreferences := mmModel.Preferences{} - for _, existingPreference := range preferences { - if preference.Name != existingPreference.Name { - newPreferences = append(newPreferences, existingPreference) - } - } - preferences = newPreferences - } - } - - return preferences, nil -} - -func (s *SQLStore) updateUserPreference(db sq.BaseRunner, preference mmModel.Preference) error { - query := s.getQueryBuilder(db). - Insert(s.tablePrefix+"preferences"). - Columns("UserId", "Category", "Name", "Value"). - Values(preference.UserId, preference.Category, preference.Name, preference.Value) - - switch s.dbType { - case model.MysqlDBType: - query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE Value = ?", preference.Value)) - case model.PostgresDBType: - query = query.SuffixExpr(sq.Expr("ON CONFLICT (userid, category, name) DO UPDATE SET Value = ?", preference.Value)) - case model.SqliteDBType: - query = query.SuffixExpr(sq.Expr(" on conflict(userid, category, name) do update set value = excluded.value")) - default: - return store.NewErrNotImplemented("failed to update preference because of missing driver") - } - - if _, err := query.Exec(); err != nil { - return fmt.Errorf("failed to upsert user preference in database: userID: %s name: %s value: %s error: %w", preference.UserId, preference.Name, preference.Value, err) - } - - return nil -} - -func (s *SQLStore) deleteUserPreference(db sq.BaseRunner, preference mmModel.Preference) error { - query := s.getQueryBuilder(db). - Delete(s.tablePrefix + "preferences"). - Where(sq.Eq{"UserId": preference.UserId}). - Where(sq.Eq{"Category": preference.Category}). - Where(sq.Eq{"Name": preference.Name}) - - if _, err := query.Exec(); err != nil { - return fmt.Errorf("failed to delete user preference from database: %w", err) - } - - return nil -} - -func (s *SQLStore) canSeeUser(db sq.BaseRunner, seerID string, seenID string) (bool, error) { - return true, nil -} - -func (s *SQLStore) sendMessage(db sq.BaseRunner, message, postType string, receipts []string) error { - return errUnsupportedOperation -} - -func (s *SQLStore) postMessage(db sq.BaseRunner, message, postType string, channel string) error { - return errUnsupportedOperation -} - -func (s *SQLStore) getUserTimezone(_ sq.BaseRunner, _ string) (string, error) { - return "", errUnsupportedOperation -} - -func (s *SQLStore) getUserPreferences(db sq.BaseRunner, userID string) (mmModel.Preferences, error) { - query := s.getQueryBuilder(db). - Select("userid", "category", "name", "value"). - From(s.tablePrefix + "preferences"). - Where(sq.Eq{ - "userid": userID, - "category": model.PreferencesCategoryFocalboard, - }) - - rows, err := query.Query() - if err != nil { - s.logger.Error("failed to fetch user preferences", mlog.String("user_id", userID), mlog.Err(err)) - return nil, err - } - - defer rows.Close() - - preferences, err := s.preferencesFromRows(rows) - if err != nil { - return nil, err - } - - return preferences, nil -} - -func (s *SQLStore) preferencesFromRows(rows *sql.Rows) ([]mmModel.Preference, error) { - preferences := []mmModel.Preference{} - - for rows.Next() { - var preference mmModel.Preference - - err := rows.Scan( - &preference.UserId, - &preference.Category, - &preference.Name, - &preference.Value, - ) - - if err != nil { - s.logger.Error("failed to scan row for user preference", mlog.Err(err)) - return nil, err - } - - preferences = append(preferences, preference) - } - - return preferences, nil -} diff --git a/server/ws/server.go b/server/ws/server.go index b39f1585..dd249b91 100644 --- a/server/ws/server.go +++ b/server/ws/server.go @@ -67,7 +67,7 @@ func (wss *websocketSession) isAuthenticated() bool { } // NewServer creates a new Server. -func NewServer(auth *auth.Auth, singleUserToken string, isMattermostAuth bool, logger mlog.LoggerIFace, store Store) *Server { +func NewServer(auth *auth.Auth, logger mlog.LoggerIFace, store Store) *Server { return &Server{ listeners: make(map[*websocketSession]bool), listenersByTeam: make(map[string][]*websocketSession), @@ -78,7 +78,7 @@ func NewServer(auth *auth.Auth, singleUserToken string, isMattermostAuth bool, l }, }, auth: auth, - isMattermostAuth: isMattermostAuth, + isMattermostAuth: true, logger: logger, store: store, } diff --git a/server/ws/server_test.go b/server/ws/server_test.go index b345d079..585045b9 100644 --- a/server/ws/server_test.go +++ b/server/ws/server_test.go @@ -13,7 +13,7 @@ import ( ) func TestTeamSubscription(t *testing.T) { - server := NewServer(&auth.Auth{}, "token", false, &mlog.Logger{}, nil) + server := NewServer(&auth.Auth{}, &mlog.Logger{}, nil) session := &websocketSession{ conn: &websocket.Conn{}, mu: sync.Mutex{}, @@ -145,7 +145,7 @@ func TestTeamSubscription(t *testing.T) { } func TestBlocksSubscription(t *testing.T) { - server := NewServer(&auth.Auth{}, "token", false, &mlog.Logger{}, nil) + server := NewServer(&auth.Auth{}, &mlog.Logger{}, nil) session := &websocketSession{ conn: &websocket.Conn{}, mu: sync.Mutex{}, @@ -264,7 +264,7 @@ func TestBlocksSubscription(t *testing.T) { } func TestGetUserIDForTokenInSingleUserMode(t *testing.T) { - server := NewServer(&auth.Auth{}, "token", false, &mlog.Logger{}, nil) + server := NewServer(&auth.Auth{}, &mlog.Logger{}, nil) t.Run("Should return nothing if the token is empty", func(t *testing.T) { require.Empty(t, server.getUserIDForToken(""))