2020-05-18 10:06:36 +00:00
package view
import (
2024-09-04 10:14:50 +00:00
"context"
2024-01-30 15:17:54 +00:00
"database/sql"
_ "embed"
"errors"
"github.com/zitadel/zitadel/internal/database"
2022-04-26 23:01:45 +00:00
"github.com/zitadel/zitadel/internal/user/repository/view/model"
2023-12-08 14:30:55 +00:00
"github.com/zitadel/zitadel/internal/zerrors"
2020-05-18 10:06:36 +00:00
)
2024-01-30 15:17:54 +00:00
//go:embed user_session_by_id.sql
var userSessionByIDQuery string
2020-05-18 10:06:36 +00:00
2024-01-30 15:17:54 +00:00
//go:embed user_sessions_by_user_agent.sql
var userSessionsByUserAgentQuery string
2020-06-05 05:50:04 +00:00
2024-09-04 10:14:50 +00:00
//go:embed user_agent_by_user_session_id.sql
var userAgentByUserSessionIDQuery string
2024-10-31 14:57:17 +00:00
//go:embed active_user_sessions_by_session_id.sql
var activeUserSessionsBySessionIDQuery string
2024-09-04 10:14:50 +00:00
func UserSessionByIDs ( ctx context . Context , db * database . DB , agentID , userID , instanceID string ) ( userSession * model . UserSessionView , err error ) {
err = db . QueryRowContext (
ctx ,
2024-01-30 15:17:54 +00:00
func ( row * sql . Row ) error {
userSession , err = scanUserSession ( row )
return err
} ,
userSessionByIDQuery ,
agentID ,
userID ,
instanceID ,
)
return userSession , err
2020-05-18 10:06:36 +00:00
}
2024-09-04 10:14:50 +00:00
func UserSessionsByAgentID ( ctx context . Context , db * database . DB , agentID , instanceID string ) ( userSessions [ ] * model . UserSessionView , err error ) {
err = db . QueryContext (
ctx ,
2024-01-30 15:17:54 +00:00
func ( rows * sql . Rows ) error {
userSessions , err = scanUserSessions ( rows )
return err
} ,
userSessionsByUserAgentQuery ,
agentID ,
instanceID ,
)
2022-06-03 12:37:24 +00:00
return userSessions , err
}
2024-09-04 10:14:50 +00:00
func UserAgentIDBySessionID ( ctx context . Context , db * database . DB , sessionID , instanceID string ) ( userAgentID string , err error ) {
err = db . QueryRowContext (
ctx ,
func ( row * sql . Row ) error {
return row . Scan ( & userAgentID )
} ,
userAgentByUserSessionIDQuery ,
sessionID ,
instanceID ,
)
return userAgentID , err
}
2024-10-31 14:57:17 +00:00
// ActiveUserSessionsBySessionID returns all sessions (sessionID:userID map) with an active session on the same user agent (its id is also returned) based on a sessionID
func ActiveUserSessionsBySessionID ( ctx context . Context , db * database . DB , sessionID , instanceID string ) ( userAgentID string , sessions map [ string ] string , err error ) {
2024-09-04 10:14:50 +00:00
err = db . QueryContext (
ctx ,
func ( rows * sql . Rows ) error {
2024-10-31 14:57:17 +00:00
userAgentID , sessions , err = scanActiveUserAgentUserIDs ( rows )
2024-09-04 10:14:50 +00:00
return err
} ,
2024-10-31 14:57:17 +00:00
activeUserSessionsBySessionIDQuery ,
2024-09-04 10:14:50 +00:00
sessionID ,
instanceID ,
)
2024-10-31 14:57:17 +00:00
return userAgentID , sessions , err
2024-09-04 10:14:50 +00:00
}
2024-10-31 14:57:17 +00:00
func scanActiveUserAgentUserIDs ( rows * sql . Rows ) ( userAgentID string , sessions map [ string ] string , err error ) {
sessions = make ( map [ string ] string )
2024-09-04 10:14:50 +00:00
for rows . Next ( ) {
2024-10-31 14:57:17 +00:00
var userID , sessionID string
2024-09-04 10:14:50 +00:00
err := rows . Scan (
& userAgentID ,
2024-10-31 14:57:17 +00:00
& userID ,
& sessionID ,
)
2024-09-04 10:14:50 +00:00
if err != nil {
return "" , nil , err
}
2024-10-31 14:57:17 +00:00
sessions [ sessionID ] = userID
2024-09-04 10:14:50 +00:00
}
if err := rows . Close ( ) ; err != nil {
return "" , nil , zerrors . ThrowInternal ( err , "VIEW-Sbrws" , "Errors.Query.CloseRows" )
}
2024-10-31 14:57:17 +00:00
return userAgentID , sessions , nil
2024-09-04 10:14:50 +00:00
}
2024-01-30 15:17:54 +00:00
func scanUserSession ( row * sql . Row ) ( * model . UserSessionView , error ) {
session := new ( model . UserSessionView )
err := row . Scan (
& session . CreationDate ,
& session . ChangeDate ,
& session . ResourceOwner ,
& session . State ,
& session . UserAgentID ,
& session . UserID ,
2024-05-22 15:26:02 +00:00
& session . UserName ,
& session . LoginName ,
& session . DisplayName ,
& session . AvatarKey ,
2024-01-30 15:17:54 +00:00
& session . SelectedIDPConfigID ,
& session . PasswordVerification ,
& session . PasswordlessVerification ,
& session . ExternalLoginVerification ,
& session . SecondFactorVerification ,
& session . SecondFactorVerificationType ,
& session . MultiFactorVerification ,
& session . MultiFactorVerificationType ,
& session . Sequence ,
& session . InstanceID ,
2024-09-03 13:19:00 +00:00
& session . ID ,
2024-01-30 15:17:54 +00:00
)
if errors . Is ( err , sql . ErrNoRows ) {
return nil , zerrors . ThrowNotFound ( nil , "VIEW-NGBs1" , "Errors.UserSession.NotFound" )
}
return session , err
}
func scanUserSessions ( rows * sql . Rows ) ( [ ] * model . UserSessionView , error ) {
sessions := make ( [ ] * model . UserSessionView , 0 )
for rows . Next ( ) {
session := new ( model . UserSessionView )
err := rows . Scan (
& session . CreationDate ,
& session . ChangeDate ,
& session . ResourceOwner ,
& session . State ,
& session . UserAgentID ,
& session . UserID ,
2024-05-22 15:26:02 +00:00
& session . UserName ,
& session . LoginName ,
& session . DisplayName ,
& session . AvatarKey ,
2024-01-30 15:17:54 +00:00
& session . SelectedIDPConfigID ,
& session . PasswordVerification ,
& session . PasswordlessVerification ,
& session . ExternalLoginVerification ,
& session . SecondFactorVerification ,
& session . SecondFactorVerificationType ,
& session . MultiFactorVerification ,
& session . MultiFactorVerificationType ,
& session . Sequence ,
& session . InstanceID ,
2024-09-03 13:19:00 +00:00
& session . ID ,
2024-01-30 15:17:54 +00:00
)
if err != nil {
return nil , err
}
sessions = append ( sessions , session )
}
if err := rows . Close ( ) ; err != nil {
return nil , zerrors . ThrowInternal ( err , "VIEW-FSF3g" , "Errors.Query.CloseRows" )
}
return sessions , nil
}