github.com/teloshs/mattermost-server@v5.11.1+incompatible/store/sqlstore/status_store.go (about)

     1  // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package sqlstore
     5  
     6  import (
     7  	"database/sql"
     8  	"net/http"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/mattermost/mattermost-server/model"
    13  	"github.com/mattermost/mattermost-server/store"
    14  )
    15  
    16  const (
    17  	MISSING_STATUS_ERROR = "store.sql_status.get.missing.app_error"
    18  )
    19  
    20  type SqlStatusStore struct {
    21  	SqlStore
    22  }
    23  
    24  func NewSqlStatusStore(sqlStore SqlStore) store.StatusStore {
    25  	s := &SqlStatusStore{sqlStore}
    26  
    27  	for _, db := range sqlStore.GetAllConns() {
    28  		table := db.AddTableWithName(model.Status{}, "Status").SetKeys(false, "UserId")
    29  		table.ColMap("UserId").SetMaxSize(26)
    30  		table.ColMap("Status").SetMaxSize(32)
    31  		table.ColMap("ActiveChannel").SetMaxSize(26)
    32  	}
    33  
    34  	return s
    35  }
    36  
    37  func (s SqlStatusStore) CreateIndexesIfNotExists() {
    38  	s.CreateIndexIfNotExists("idx_status_user_id", "Status", "UserId")
    39  	s.CreateIndexIfNotExists("idx_status_status", "Status", "Status")
    40  }
    41  
    42  func (s SqlStatusStore) SaveOrUpdate(status *model.Status) store.StoreChannel {
    43  	return store.Do(func(result *store.StoreResult) {
    44  		if err := s.GetReplica().SelectOne(&model.Status{}, "SELECT * FROM Status WHERE UserId = :UserId", map[string]interface{}{"UserId": status.UserId}); err == nil {
    45  			if _, err := s.GetMaster().Update(status); err != nil {
    46  				result.Err = model.NewAppError("SqlStatusStore.SaveOrUpdate", "store.sql_status.update.app_error", nil, err.Error(), http.StatusInternalServerError)
    47  			}
    48  		} else {
    49  			if err := s.GetMaster().Insert(status); err != nil {
    50  				if !(strings.Contains(err.Error(), "for key 'PRIMARY'") && strings.Contains(err.Error(), "Duplicate entry")) {
    51  					result.Err = model.NewAppError("SqlStatusStore.SaveOrUpdate", "store.sql_status.save.app_error", nil, err.Error(), http.StatusInternalServerError)
    52  				}
    53  			}
    54  		}
    55  	})
    56  }
    57  
    58  func (s SqlStatusStore) Get(userId string) store.StoreChannel {
    59  	return store.Do(func(result *store.StoreResult) {
    60  		var status model.Status
    61  
    62  		if err := s.GetReplica().SelectOne(&status,
    63  			`SELECT
    64  				*
    65  			FROM
    66  				Status
    67  			WHERE
    68  				UserId = :UserId`, map[string]interface{}{"UserId": userId}); err != nil {
    69  			if err == sql.ErrNoRows {
    70  				result.Err = model.NewAppError("SqlStatusStore.Get", MISSING_STATUS_ERROR, nil, err.Error(), http.StatusNotFound)
    71  			} else {
    72  				result.Err = model.NewAppError("SqlStatusStore.Get", "store.sql_status.get.app_error", nil, err.Error(), http.StatusInternalServerError)
    73  			}
    74  		} else {
    75  			result.Data = &status
    76  		}
    77  	})
    78  }
    79  
    80  func (s SqlStatusStore) GetByIds(userIds []string) store.StoreChannel {
    81  	return store.Do(func(result *store.StoreResult) {
    82  		props := make(map[string]interface{})
    83  		idQuery := ""
    84  
    85  		for index, userId := range userIds {
    86  			if len(idQuery) > 0 {
    87  				idQuery += ", "
    88  			}
    89  
    90  			props["userId"+strconv.Itoa(index)] = userId
    91  			idQuery += ":userId" + strconv.Itoa(index)
    92  		}
    93  
    94  		var statuses []*model.Status
    95  		if _, err := s.GetReplica().Select(&statuses, "SELECT * FROM Status WHERE UserId IN ("+idQuery+")", props); err != nil {
    96  			result.Err = model.NewAppError("SqlStatusStore.GetByIds", "store.sql_status.get.app_error", nil, err.Error(), http.StatusInternalServerError)
    97  		} else {
    98  			result.Data = statuses
    99  		}
   100  	})
   101  }
   102  
   103  func (s SqlStatusStore) GetOnlineAway() store.StoreChannel {
   104  	return store.Do(func(result *store.StoreResult) {
   105  		var statuses []*model.Status
   106  		if _, err := s.GetReplica().Select(&statuses, "SELECT * FROM Status WHERE Status = :Online OR Status = :Away LIMIT 300", map[string]interface{}{"Online": model.STATUS_ONLINE, "Away": model.STATUS_AWAY}); err != nil {
   107  			result.Err = model.NewAppError("SqlStatusStore.GetOnlineAway", "store.sql_status.get_online_away.app_error", nil, err.Error(), http.StatusInternalServerError)
   108  		} else {
   109  			result.Data = statuses
   110  		}
   111  	})
   112  }
   113  
   114  func (s SqlStatusStore) GetOnline() store.StoreChannel {
   115  	return store.Do(func(result *store.StoreResult) {
   116  		var statuses []*model.Status
   117  		if _, err := s.GetReplica().Select(&statuses, "SELECT * FROM Status WHERE Status = :Online", map[string]interface{}{"Online": model.STATUS_ONLINE}); err != nil {
   118  			result.Err = model.NewAppError("SqlStatusStore.GetOnline", "store.sql_status.get_online.app_error", nil, err.Error(), http.StatusInternalServerError)
   119  		} else {
   120  			result.Data = statuses
   121  		}
   122  	})
   123  }
   124  
   125  func (s SqlStatusStore) GetAllFromTeam(teamId string) store.StoreChannel {
   126  	return store.Do(func(result *store.StoreResult) {
   127  		var statuses []*model.Status
   128  		if _, err := s.GetReplica().Select(&statuses,
   129  			`SELECT s.* FROM Status AS s INNER JOIN
   130  			TeamMembers AS tm ON tm.TeamId=:TeamId AND s.UserId=tm.UserId`, map[string]interface{}{"TeamId": teamId}); err != nil {
   131  			result.Err = model.NewAppError("SqlStatusStore.GetAllFromTeam", "store.sql_status.get_team_statuses.app_error", nil, err.Error(), http.StatusInternalServerError)
   132  		} else {
   133  			result.Data = statuses
   134  		}
   135  	})
   136  }
   137  
   138  func (s SqlStatusStore) ResetAll() store.StoreChannel {
   139  	return store.Do(func(result *store.StoreResult) {
   140  		if _, err := s.GetMaster().Exec("UPDATE Status SET Status = :Status WHERE Manual = false", map[string]interface{}{"Status": model.STATUS_OFFLINE}); err != nil {
   141  			result.Err = model.NewAppError("SqlStatusStore.ResetAll", "store.sql_status.reset_all.app_error", nil, "", http.StatusInternalServerError)
   142  		}
   143  	})
   144  }
   145  
   146  func (s SqlStatusStore) GetTotalActiveUsersCount() store.StoreChannel {
   147  	return store.Do(func(result *store.StoreResult) {
   148  		time := model.GetMillis() - (1000 * 60 * 60 * 24)
   149  
   150  		if count, err := s.GetReplica().SelectInt("SELECT COUNT(UserId) FROM Status WHERE LastActivityAt > :Time", map[string]interface{}{"Time": time}); err != nil {
   151  			result.Err = model.NewAppError("SqlStatusStore.GetTotalActiveUsersCount", "store.sql_status.get_total_active_users_count.app_error", nil, err.Error(), http.StatusInternalServerError)
   152  		} else {
   153  			result.Data = count
   154  		}
   155  	})
   156  }
   157  
   158  func (s SqlStatusStore) UpdateLastActivityAt(userId string, lastActivityAt int64) store.StoreChannel {
   159  	return store.Do(func(result *store.StoreResult) {
   160  		if _, err := s.GetMaster().Exec("UPDATE Status SET LastActivityAt = :Time WHERE UserId = :UserId", map[string]interface{}{"UserId": userId, "Time": lastActivityAt}); err != nil {
   161  			result.Err = model.NewAppError("SqlStatusStore.UpdateLastActivityAt", "store.sql_status.update_last_activity_at.app_error", nil, "", http.StatusInternalServerError)
   162  		}
   163  	})
   164  }