2017-04-12 08:27:57 -04:00
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
2015-06-14 23:53:32 -08:00
// See License.txt for license information.
package store
import (
2016-01-11 09:12:51 -06:00
l4g "github.com/alecthomas/log4go"
2015-06-14 23:53:32 -08:00
"github.com/mattermost/platform/model"
2016-01-25 16:08:06 -03:00
"github.com/mattermost/platform/utils"
2015-06-14 23:53:32 -08:00
)
type SqlSessionStore struct {
* SqlStore
}
func NewSqlSessionStore ( sqlStore * SqlStore ) SessionStore {
us := & SqlSessionStore { sqlStore }
for _ , db := range sqlStore . GetAllConns ( ) {
table := db . AddTableWithName ( model . Session { } , "Sessions" ) . SetKeys ( false , "Id" )
table . ColMap ( "Id" ) . SetMaxSize ( 26 )
2015-09-16 15:49:12 -04:00
table . ColMap ( "Token" ) . SetMaxSize ( 26 )
2015-06-14 23:53:32 -08:00
table . ColMap ( "UserId" ) . SetMaxSize ( 26 )
2016-02-22 16:08:40 -08:00
table . ColMap ( "DeviceId" ) . SetMaxSize ( 512 )
2015-06-14 23:53:32 -08:00
table . ColMap ( "Roles" ) . SetMaxSize ( 64 )
table . ColMap ( "Props" ) . SetMaxSize ( 1000 )
}
return us
}
func ( me SqlSessionStore ) CreateIndexesIfNotExists ( ) {
2015-07-12 18:19:03 -08:00
me . CreateIndexIfNotExists ( "idx_sessions_user_id" , "Sessions" , "UserId" )
2015-09-16 15:49:12 -04:00
me . CreateIndexIfNotExists ( "idx_sessions_token" , "Sessions" , "Token" )
2016-10-24 17:05:27 -03:00
me . CreateIndexIfNotExists ( "idx_sessions_expires_at" , "Sessions" , "ExpiresAt" )
me . CreateIndexIfNotExists ( "idx_sessions_create_at" , "Sessions" , "CreateAt" )
me . CreateIndexIfNotExists ( "idx_sessions_last_activity_at" , "Sessions" , "LastActivityAt" )
2015-06-14 23:53:32 -08:00
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) Save ( session * model . Session ) StoreChannel {
2015-06-14 23:53:32 -08:00
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
result := StoreResult { }
if len ( session . Id ) > 0 {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.Save" , "store.sql_session.save.existing.app_error" , nil , "id=" + session . Id )
2015-06-14 23:53:32 -08:00
storeChannel <- result
close ( storeChannel )
return
}
session . PreSave ( )
2016-01-20 13:36:16 -06:00
if cur := <- me . CleanUpExpiredSessions ( session . UserId ) ; cur . Err != nil {
2016-01-25 16:08:06 -03:00
l4g . Error ( utils . T ( "store.sql_session.save.cleanup.error" ) , cur . Err )
2015-06-14 23:53:32 -08:00
}
2016-04-21 22:37:01 -07:00
tcs := me . Team ( ) . GetTeamsForUser ( session . UserId )
2015-06-14 23:53:32 -08:00
if err := me . GetMaster ( ) . Insert ( session ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.Save" , "store.sql_session.save.app_error" , nil , "id=" + session . Id + ", " + err . Error ( ) )
2016-04-21 22:37:01 -07:00
return
2015-06-14 23:53:32 -08:00
} else {
result . Data = session
}
2016-04-21 22:37:01 -07:00
if rtcs := <- tcs ; rtcs . Err != nil {
result . Err = model . NewLocAppError ( "SqlSessionStore.Save" , "store.sql_session.save.app_error" , nil , "id=" + session . Id + ", " + rtcs . Err . Error ( ) )
return
} else {
2016-07-06 13:40:59 -08:00
tempMembers := rtcs . Data . ( [ ] * model . TeamMember )
session . TeamMembers = make ( [ ] * model . TeamMember , 0 , len ( tempMembers ) )
for _ , tm := range tempMembers {
if tm . DeleteAt == 0 {
session . TeamMembers = append ( session . TeamMembers , tm )
}
}
2016-04-21 22:37:01 -07:00
}
2015-06-14 23:53:32 -08:00
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) Get ( sessionIdOrToken string ) StoreChannel {
2015-06-14 23:53:32 -08:00
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
result := StoreResult { }
2015-09-16 15:49:12 -04:00
var sessions [ ] * model . Session
if _ , err := me . GetReplica ( ) . Select ( & sessions , "SELECT * FROM Sessions WHERE Token = :Token OR Id = :Id LIMIT 1" , map [ string ] interface { } { "Token" : sessionIdOrToken , "Id" : sessionIdOrToken } ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.Get" , "store.sql_session.get.app_error" , nil , "sessionIdOrToken=" + sessionIdOrToken + ", " + err . Error ( ) )
2015-09-16 15:49:12 -04:00
} else if sessions == nil || len ( sessions ) == 0 {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.Get" , "store.sql_session.get.app_error" , nil , "sessionIdOrToken=" + sessionIdOrToken )
2015-06-14 23:53:32 -08:00
} else {
2015-09-16 15:49:12 -04:00
result . Data = sessions [ 0 ]
2016-04-21 22:37:01 -07:00
tcs := me . Team ( ) . GetTeamsForUser ( sessions [ 0 ] . UserId )
if rtcs := <- tcs ; rtcs . Err != nil {
result . Err = model . NewLocAppError ( "SqlSessionStore.Get" , "store.sql_session.get.app_error" , nil , "sessionIdOrToken=" + sessionIdOrToken + ", " + rtcs . Err . Error ( ) )
return
} else {
2016-07-06 13:40:59 -08:00
tempMembers := rtcs . Data . ( [ ] * model . TeamMember )
sessions [ 0 ] . TeamMembers = make ( [ ] * model . TeamMember , 0 , len ( tempMembers ) )
for _ , tm := range tempMembers {
if tm . DeleteAt == 0 {
sessions [ 0 ] . TeamMembers = append ( sessions [ 0 ] . TeamMembers , tm )
}
}
2016-04-21 22:37:01 -07:00
}
2015-06-14 23:53:32 -08:00
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) GetSessions ( userId string ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
2016-01-20 13:36:16 -06:00
if cur := <- me . CleanUpExpiredSessions ( userId ) ; cur . Err != nil {
2016-01-25 16:08:06 -03:00
l4g . Error ( utils . T ( "store.sql_session.get_sessions.error" ) , cur . Err )
2015-06-14 23:53:32 -08:00
}
result := StoreResult { }
var sessions [ ] * model . Session
2016-04-21 22:37:01 -07:00
tcs := me . Team ( ) . GetTeamsForUser ( userId )
2015-07-12 18:19:03 -08:00
if _ , err := me . GetReplica ( ) . Select ( & sessions , "SELECT * FROM Sessions WHERE UserId = :UserId ORDER BY LastActivityAt DESC" , map [ string ] interface { } { "UserId" : userId } ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.GetSessions" , "store.sql_session.get_sessions.app_error" , nil , err . Error ( ) )
2015-06-14 23:53:32 -08:00
} else {
result . Data = sessions
}
2016-04-21 22:37:01 -07:00
if rtcs := <- tcs ; rtcs . Err != nil {
result . Err = model . NewLocAppError ( "SqlSessionStore.GetSessions" , "store.sql_session.get_sessions.app_error" , nil , rtcs . Err . Error ( ) )
return
} else {
for _ , session := range sessions {
2016-07-06 13:40:59 -08:00
tempMembers := rtcs . Data . ( [ ] * model . TeamMember )
session . TeamMembers = make ( [ ] * model . TeamMember , 0 , len ( tempMembers ) )
for _ , tm := range tempMembers {
if tm . DeleteAt == 0 {
session . TeamMembers = append ( session . TeamMembers , tm )
}
}
2016-04-21 22:37:01 -07:00
}
}
2015-06-14 23:53:32 -08:00
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-10-24 17:04:11 -07:00
func ( me SqlSessionStore ) GetSessionsWithActiveDeviceIds ( userId string ) StoreChannel {
storeChannel := make ( StoreChannel , 1 )
go func ( ) {
result := StoreResult { }
var sessions [ ] * model . Session
if _ , err := me . GetReplica ( ) . Select ( & sessions , "SELECT * FROM Sessions WHERE UserId = :UserId AND ExpiresAt != 0 AND :ExpiresAt <= ExpiresAt AND DeviceId != ''" , map [ string ] interface { } { "UserId" : userId , "ExpiresAt" : model . GetMillis ( ) } ) ; err != nil {
result . Err = model . NewLocAppError ( "SqlSessionStore.GetActiveSessionsWithDeviceIds" , "store.sql_session.get_sessions.app_error" , nil , err . Error ( ) )
} else {
result . Data = sessions
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) Remove ( sessionIdOrToken string ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
result := StoreResult { }
2015-09-16 15:49:12 -04:00
_ , err := me . GetMaster ( ) . Exec ( "DELETE FROM Sessions WHERE Id = :Id Or Token = :Token" , map [ string ] interface { } { "Id" : sessionIdOrToken , "Token" : sessionIdOrToken } )
2015-06-14 23:53:32 -08:00
if err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.RemoveSession" , "store.sql_session.remove.app_error" , nil , "id=" + sessionIdOrToken + ", err=" + err . Error ( ) )
2015-06-14 23:53:32 -08:00
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-04-21 22:37:01 -07:00
func ( me SqlSessionStore ) RemoveAllSessions ( ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-09-23 12:49:28 -07:00
go func ( ) {
result := StoreResult { }
2016-04-21 22:37:01 -07:00
_ , err := me . GetMaster ( ) . Exec ( "DELETE FROM Sessions" )
2015-09-23 12:49:28 -07:00
if err != nil {
2016-04-21 22:37:01 -07:00
result . Err = model . NewLocAppError ( "SqlSessionStore.RemoveAllSessions" , "store.sql_session.remove_all_sessions_for_team.app_error" , nil , err . Error ( ) )
2015-09-23 12:49:28 -07:00
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) PermanentDeleteSessionsByUser ( userId string ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-11-15 18:18:02 -08:00
go func ( ) {
result := StoreResult { }
_ , err := me . GetMaster ( ) . Exec ( "DELETE FROM Sessions WHERE UserId = :UserId" , map [ string ] interface { } { "UserId" : userId } )
if err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.RemoveAllSessionsForUser" , "store.sql_session.permanent_delete_sessions_by_user.app_error" , nil , "id=" + userId + ", err=" + err . Error ( ) )
2015-11-15 18:18:02 -08:00
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) CleanUpExpiredSessions ( userId string ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
result := StoreResult { }
2015-07-12 18:19:03 -08:00
if _ , err := me . GetMaster ( ) . Exec ( "DELETE FROM Sessions WHERE UserId = :UserId AND ExpiresAt != 0 AND :ExpiresAt > ExpiresAt" , map [ string ] interface { } { "UserId" : userId , "ExpiresAt" : model . GetMillis ( ) } ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.CleanUpExpiredSessions" , "store.sql_session.cleanup_expired_sessions.app_error" , nil , err . Error ( ) )
2015-06-14 23:53:32 -08:00
} else {
result . Data = userId
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) UpdateLastActivityAt ( sessionId string , time int64 ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-06-14 23:53:32 -08:00
go func ( ) {
result := StoreResult { }
2015-07-12 18:19:03 -08:00
if _ , err := me . GetMaster ( ) . Exec ( "UPDATE Sessions SET LastActivityAt = :LastActivityAt WHERE Id = :Id" , map [ string ] interface { } { "LastActivityAt" : time , "Id" : sessionId } ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.UpdateLastActivityAt" , "store.sql_session.update_last_activity.app_error" , nil , "sessionId=" + sessionId )
2015-06-14 23:53:32 -08:00
} else {
result . Data = sessionId
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2015-08-17 09:28:20 -04:00
2016-01-20 13:36:16 -06:00
func ( me SqlSessionStore ) UpdateRoles ( userId , roles string ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2015-08-17 09:28:20 -04:00
go func ( ) {
result := StoreResult { }
if _ , err := me . GetMaster ( ) . Exec ( "UPDATE Sessions SET Roles = :Roles WHERE UserId = :UserId" , map [ string ] interface { } { "Roles" : roles , "UserId" : userId } ) ; err != nil {
2016-01-25 16:08:06 -03:00
result . Err = model . NewLocAppError ( "SqlSessionStore.UpdateRoles" , "store.sql_session.update_roles.app_error" , nil , "userId=" + userId )
2015-08-17 09:28:20 -04:00
} else {
result . Data = userId
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-01-26 20:32:24 -05:00
2016-07-21 08:36:11 -08:00
func ( me SqlSessionStore ) UpdateDeviceId ( id string , deviceId string , expiresAt int64 ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2016-01-26 20:32:24 -05:00
go func ( ) {
result := StoreResult { }
2016-07-21 08:36:11 -08:00
if _ , err := me . GetMaster ( ) . Exec ( "UPDATE Sessions SET DeviceId = :DeviceId, ExpiresAt = :ExpiresAt WHERE Id = :Id" , map [ string ] interface { } { "DeviceId" : deviceId , "Id" : id , "ExpiresAt" : expiresAt } ) ; err != nil {
2016-02-22 16:08:40 -08:00
result . Err = model . NewLocAppError ( "SqlSessionStore.UpdateDeviceId" , "store.sql_session.update_device_id.app_error" , nil , err . Error ( ) )
2016-01-26 20:32:24 -05:00
} else {
result . Data = deviceId
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}
2016-02-25 12:32:46 -05:00
2016-04-21 22:37:01 -07:00
func ( me SqlSessionStore ) AnalyticsSessionCount ( ) StoreChannel {
2016-09-19 19:30:41 +07:00
storeChannel := make ( StoreChannel , 1 )
2016-02-25 12:32:46 -05:00
go func ( ) {
result := StoreResult { }
query :=
` SELECT
COUNT ( * )
FROM
2016-02-26 11:27:45 -05:00
Sessions
WHERE ExpiresAt > : Time `
2016-02-25 12:32:46 -05:00
2016-04-21 22:37:01 -07:00
if c , err := me . GetReplica ( ) . SelectInt ( query , map [ string ] interface { } { "Time" : model . GetMillis ( ) } ) ; err != nil {
2016-02-25 12:32:46 -05:00
result . Err = model . NewLocAppError ( "SqlSessionStore.AnalyticsSessionCount" , "store.sql_session.analytics_session_count.app_error" , nil , err . Error ( ) )
} else {
result . Data = c
}
storeChannel <- result
close ( storeChannel )
} ( )
return storeChannel
}