2017-04-12 08:27:57 -04:00
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
2016-07-18 11:10:03 -04:00
// See License.txt for license information.
2017-09-25 09:11:25 -05:00
package sqlstore
2016-07-18 11:10:03 -04:00
import (
"database/sql"
2017-09-20 14:34:50 +01:00
"net/http"
2016-10-19 14:49:25 -04:00
"strconv"
2017-08-18 12:45:48 -07:00
"strings"
2016-08-31 06:24:14 -07:00
2017-09-06 23:05:10 -07:00
"github.com/mattermost/mattermost-server/model"
2017-09-25 09:11:25 -05:00
"github.com/mattermost/mattermost-server/store"
2016-07-18 11:10:03 -04:00
)
const (
MISSING_STATUS_ERROR = "store.sql_status.get.missing.app_error"
)
type SqlStatusStore struct {
2017-06-27 08:02:08 -07:00
SqlStore
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func NewSqlStatusStore ( sqlStore SqlStore ) store . StatusStore {
2016-07-18 11:10:03 -04:00
s := & SqlStatusStore { sqlStore }
for _ , db := range sqlStore . GetAllConns ( ) {
table := db . AddTableWithName ( model . Status { } , "Status" ) . SetKeys ( false , "UserId" )
table . ColMap ( "UserId" ) . SetMaxSize ( 26 )
table . ColMap ( "Status" ) . SetMaxSize ( 32 )
2016-09-02 12:50:15 -04:00
table . ColMap ( "ActiveChannel" ) . SetMaxSize ( 26 )
2016-07-18 11:10:03 -04:00
}
return s
}
func ( s SqlStatusStore ) CreateIndexesIfNotExists ( ) {
s . CreateIndexIfNotExists ( "idx_status_user_id" , "Status" , "UserId" )
s . CreateIndexIfNotExists ( "idx_status_status" , "Status" , "Status" )
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) SaveOrUpdate ( status * model . Status ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-18 11:10:03 -04:00
if err := s . GetReplica ( ) . SelectOne ( & model . Status { } , "SELECT * FROM Status WHERE UserId = :UserId" , map [ string ] interface { } { "UserId" : status . UserId } ) ; err == nil {
if _ , err := s . GetMaster ( ) . Update ( status ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.SaveOrUpdate" , "store.sql_status.update.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
}
} else {
if err := s . GetMaster ( ) . Insert ( status ) ; err != nil {
2017-08-18 12:45:48 -07:00
if ! ( strings . Contains ( err . Error ( ) , "for key 'PRIMARY'" ) && strings . Contains ( err . Error ( ) , "Duplicate entry" ) ) {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.SaveOrUpdate" , "store.sql_status.save.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2017-08-18 12:45:48 -07:00
}
2016-07-18 11:10:03 -04:00
}
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) Get ( userId string ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-18 11:10:03 -04:00
var status model . Status
if err := s . GetReplica ( ) . SelectOne ( & status ,
` SELECT
*
FROM
Status
WHERE
UserId = : UserId ` , map [ string ] interface { } { "UserId" : userId } ) ; err != nil {
if err == sql . ErrNoRows {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.Get" , MISSING_STATUS_ERROR , nil , err . Error ( ) , http . StatusNotFound )
2016-07-18 11:10:03 -04:00
} else {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.Get" , "store.sql_status.get.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
}
} else {
result . Data = & status
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) GetByIds ( userIds [ ] string ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-10-19 14:49:25 -04:00
props := make ( map [ string ] interface { } )
idQuery := ""
for index , userId := range userIds {
if len ( idQuery ) > 0 {
idQuery += ", "
}
props [ "userId" + strconv . Itoa ( index ) ] = userId
idQuery += ":userId" + strconv . Itoa ( index )
}
var statuses [ ] * model . Status
if _ , err := s . GetReplica ( ) . Select ( & statuses , "SELECT * FROM Status WHERE UserId IN (" + idQuery + ")" , props ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.GetByIds" , "store.sql_status.get.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-10-19 14:49:25 -04:00
} else {
result . Data = statuses
}
2017-10-06 08:12:10 -07:00
} )
2016-10-19 14:49:25 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) GetOnlineAway ( ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-18 11:10:03 -04:00
var statuses [ ] * model . Status
2016-10-19 14:49:25 -04:00
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 {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.GetOnlineAway" , "store.sql_status.get_online_away.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-07-21 10:00:09 -04:00
} else {
result . Data = statuses
}
2017-10-06 08:12:10 -07:00
} )
2016-07-21 10:00:09 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) GetOnline ( ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-21 10:00:09 -04:00
var statuses [ ] * model . Status
if _ , err := s . GetReplica ( ) . Select ( & statuses , "SELECT * FROM Status WHERE Status = :Online" , map [ string ] interface { } { "Online" : model . STATUS_ONLINE } ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.GetOnline" , "store.sql_status.get_online.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
} else {
result . Data = statuses
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) GetAllFromTeam ( teamId string ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-09-06 15:48:43 -03:00
var statuses [ ] * model . Status
if _ , err := s . GetReplica ( ) . Select ( & statuses ,
` SELECT s . * FROM Status AS s INNER JOIN
TeamMembers AS tm ON tm . TeamId = : TeamId AND s . UserId = tm . UserId ` , map [ string ] interface { } { "TeamId" : teamId } ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.GetAllFromTeam" , "store.sql_status.get_team_statuses.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-09-06 15:48:43 -03:00
} else {
result . Data = statuses
}
2017-10-06 08:12:10 -07:00
} )
2016-09-06 15:48:43 -03:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) ResetAll ( ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-11-11 15:32:29 -05:00
if _ , err := s . GetMaster ( ) . Exec ( "UPDATE Status SET Status = :Status WHERE Manual = false" , map [ string ] interface { } { "Status" : model . STATUS_OFFLINE } ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.ResetAll" , "store.sql_status.reset_all.app_error" , nil , "" , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) GetTotalActiveUsersCount ( ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-18 11:10:03 -04:00
time := model . GetMillis ( ) - ( 1000 * 60 * 60 * 24 )
if count , err := s . GetReplica ( ) . SelectInt ( "SELECT COUNT(UserId) FROM Status WHERE LastActivityAt > :Time" , map [ string ] interface { } { "Time" : time } ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.GetTotalActiveUsersCount" , "store.sql_status.get_total_active_users_count.app_error" , nil , err . Error ( ) , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
} else {
result . Data = count
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}
2017-09-25 09:11:25 -05:00
func ( s SqlStatusStore ) UpdateLastActivityAt ( userId string , lastActivityAt int64 ) store . StoreChannel {
2017-10-06 08:12:10 -07:00
return store . Do ( func ( result * store . StoreResult ) {
2016-07-18 11:10:03 -04:00
if _ , err := s . GetMaster ( ) . Exec ( "UPDATE Status SET LastActivityAt = :Time WHERE UserId = :UserId" , map [ string ] interface { } { "UserId" : userId , "Time" : lastActivityAt } ) ; err != nil {
2017-09-20 14:34:50 +01:00
result . Err = model . NewAppError ( "SqlStatusStore.UpdateLastActivityAt" , "store.sql_status.update_last_activity_at.app_error" , nil , "" , http . StatusInternalServerError )
2016-07-18 11:10:03 -04:00
}
2017-10-06 08:12:10 -07:00
} )
2016-07-18 11:10:03 -04:00
}