2021-02-15 08:33:31 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2021-02-15 08:33:31 +03:00
2022-01-02 16:12:35 +03:00
package auth
2021-02-15 08:33:31 +03:00
import (
2023-09-16 17:39:12 +03:00
"context"
2021-02-15 08:33:31 +03:00
"fmt"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-02-15 08:33:31 +03:00
"code.gitea.io/gitea/modules/timeutil"
2023-12-07 10:27:36 +03:00
"xorm.io/builder"
2021-02-15 08:33:31 +03:00
)
// Session represents a session compatible for go-chi session
type Session struct {
Key string ` xorm:"pk CHAR(16)" ` // has to be Key to match with go-chi/session
2021-11-03 03:33:54 +03:00
Data [ ] byte ` xorm:"BLOB" ` // on MySQL this has a maximum size of 64Kb - this may need to be increased
2021-02-15 08:33:31 +03:00
Expiry timeutil . TimeStamp // has to be Expiry to match with go-chi/session
}
2021-09-19 14:49:59 +03:00
func init ( ) {
db . RegisterModel ( new ( Session ) )
}
2021-02-15 08:33:31 +03:00
// UpdateSession updates the session with provided id
2023-09-16 17:39:12 +03:00
func UpdateSession ( ctx context . Context , key string , data [ ] byte ) error {
_ , err := db . GetEngine ( ctx ) . ID ( key ) . Update ( & Session {
2021-02-15 08:33:31 +03:00
Data : data ,
Expiry : timeutil . TimeStampNow ( ) ,
} )
return err
}
// ReadSession reads the data for the provided session
2023-09-16 17:39:12 +03:00
func ReadSession ( ctx context . Context , key string ) ( * Session , error ) {
ctx , committer , err := db . TxContext ( ctx )
2021-11-21 18:41:00 +03:00
if err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
}
2021-11-21 18:41:00 +03:00
defer committer . Close ( )
2021-02-15 08:33:31 +03:00
2023-12-27 10:24:23 +03:00
session , exist , err := db . Get [ Session ] ( ctx , builder . Eq { "`key`" : key } )
2023-12-07 10:27:36 +03:00
if err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
2023-12-07 10:27:36 +03:00
} else if ! exist {
2023-12-27 10:24:23 +03:00
session = & Session {
Key : key ,
Expiry : timeutil . TimeStampNow ( ) ,
}
if err := db . Insert ( ctx , session ) ; err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
}
}
2023-12-07 10:27:36 +03:00
return session , committer . Commit ( )
2021-02-15 08:33:31 +03:00
}
// ExistSession checks if a session exists
2023-09-16 17:39:12 +03:00
func ExistSession ( ctx context . Context , key string ) ( bool , error ) {
2023-12-27 10:24:23 +03:00
return db . Exist [ Session ] ( ctx , builder . Eq { "`key`" : key } )
2021-02-15 08:33:31 +03:00
}
// DestroySession destroys a session
2023-09-16 17:39:12 +03:00
func DestroySession ( ctx context . Context , key string ) error {
_ , err := db . GetEngine ( ctx ) . Delete ( & Session {
2021-02-15 08:33:31 +03:00
Key : key ,
} )
return err
}
// RegenerateSession regenerates a session from the old id
2023-09-16 17:39:12 +03:00
func RegenerateSession ( ctx context . Context , oldKey , newKey string ) ( * Session , error ) {
ctx , committer , err := db . TxContext ( ctx )
2021-11-21 18:41:00 +03:00
if err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
}
2021-11-21 18:41:00 +03:00
defer committer . Close ( )
2021-02-15 08:33:31 +03:00
2023-12-27 10:24:23 +03:00
if has , err := db . Exist [ Session ] ( ctx , builder . Eq { "`key`" : newKey } ) ; err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
} else if has {
return nil , fmt . Errorf ( "session Key: %s already exists" , newKey )
}
2023-12-27 10:24:23 +03:00
if has , err := db . Exist [ Session ] ( ctx , builder . Eq { "`key`" : oldKey } ) ; err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
} else if ! has {
2021-11-21 18:41:00 +03:00
if err := db . Insert ( ctx , & Session {
2021-02-15 08:33:31 +03:00
Key : oldKey ,
Expiry : timeutil . TimeStampNow ( ) ,
2021-11-21 18:41:00 +03:00
} ) ; err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
}
}
2021-11-21 18:41:00 +03:00
if _ , err := db . Exec ( ctx , "UPDATE " + db . TableName ( & Session { } ) + " SET `key` = ? WHERE `key`=?" , newKey , oldKey ) ; err != nil {
2021-02-15 08:33:31 +03:00
return nil , err
}
2023-12-27 10:24:23 +03:00
s , _ , err := db . Get [ Session ] ( ctx , builder . Eq { "`key`" : newKey } )
2023-12-07 10:27:36 +03:00
if err != nil {
// is not exist, it should be impossible
2021-02-15 08:33:31 +03:00
return nil , err
}
2023-12-07 10:27:36 +03:00
return s , committer . Commit ( )
2021-02-15 08:33:31 +03:00
}
// CountSessions returns the number of sessions
2023-09-16 17:39:12 +03:00
func CountSessions ( ctx context . Context ) ( int64 , error ) {
return db . GetEngine ( ctx ) . Count ( & Session { } )
2021-02-15 08:33:31 +03:00
}
// CleanupSessions cleans up expired sessions
2023-09-16 17:39:12 +03:00
func CleanupSessions ( ctx context . Context , maxLifetime int64 ) error {
_ , err := db . GetEngine ( ctx ) . Where ( "expiry <= ?" , timeutil . TimeStampNow ( ) . Add ( - maxLifetime ) ) . Delete ( & Session { } )
2021-02-15 08:33:31 +03:00
return err
}