code.gitea.io/gitea@v1.22.3/models/auth/session.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package auth 5 6 import ( 7 "context" 8 "fmt" 9 10 "code.gitea.io/gitea/models/db" 11 "code.gitea.io/gitea/modules/timeutil" 12 13 "xorm.io/builder" 14 ) 15 16 // Session represents a session compatible for go-chi session 17 type Session struct { 18 Key string `xorm:"pk CHAR(16)"` // has to be Key to match with go-chi/session 19 Data []byte `xorm:"BLOB"` // on MySQL this has a maximum size of 64Kb - this may need to be increased 20 Expiry timeutil.TimeStamp // has to be Expiry to match with go-chi/session 21 } 22 23 func init() { 24 db.RegisterModel(new(Session)) 25 } 26 27 // UpdateSession updates the session with provided id 28 func UpdateSession(ctx context.Context, key string, data []byte) error { 29 _, err := db.GetEngine(ctx).ID(key).Update(&Session{ 30 Data: data, 31 Expiry: timeutil.TimeStampNow(), 32 }) 33 return err 34 } 35 36 // ReadSession reads the data for the provided session 37 func ReadSession(ctx context.Context, key string) (*Session, error) { 38 ctx, committer, err := db.TxContext(ctx) 39 if err != nil { 40 return nil, err 41 } 42 defer committer.Close() 43 44 session, exist, err := db.Get[Session](ctx, builder.Eq{"`key`": key}) 45 if err != nil { 46 return nil, err 47 } else if !exist { 48 session = &Session{ 49 Key: key, 50 Expiry: timeutil.TimeStampNow(), 51 } 52 if err := db.Insert(ctx, session); err != nil { 53 return nil, err 54 } 55 } 56 57 return session, committer.Commit() 58 } 59 60 // ExistSession checks if a session exists 61 func ExistSession(ctx context.Context, key string) (bool, error) { 62 return db.Exist[Session](ctx, builder.Eq{"`key`": key}) 63 } 64 65 // DestroySession destroys a session 66 func DestroySession(ctx context.Context, key string) error { 67 _, err := db.GetEngine(ctx).Delete(&Session{ 68 Key: key, 69 }) 70 return err 71 } 72 73 // RegenerateSession regenerates a session from the old id 74 func RegenerateSession(ctx context.Context, oldKey, newKey string) (*Session, error) { 75 ctx, committer, err := db.TxContext(ctx) 76 if err != nil { 77 return nil, err 78 } 79 defer committer.Close() 80 81 if has, err := db.Exist[Session](ctx, builder.Eq{"`key`": newKey}); err != nil { 82 return nil, err 83 } else if has { 84 return nil, fmt.Errorf("session Key: %s already exists", newKey) 85 } 86 87 if has, err := db.Exist[Session](ctx, builder.Eq{"`key`": oldKey}); err != nil { 88 return nil, err 89 } else if !has { 90 if err := db.Insert(ctx, &Session{ 91 Key: oldKey, 92 Expiry: timeutil.TimeStampNow(), 93 }); err != nil { 94 return nil, err 95 } 96 } 97 98 if _, err := db.Exec(ctx, "UPDATE "+db.TableName(&Session{})+" SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil { 99 return nil, err 100 } 101 102 s, _, err := db.Get[Session](ctx, builder.Eq{"`key`": newKey}) 103 if err != nil { 104 // is not exist, it should be impossible 105 return nil, err 106 } 107 108 return s, committer.Commit() 109 } 110 111 // CountSessions returns the number of sessions 112 func CountSessions(ctx context.Context) (int64, error) { 113 return db.GetEngine(ctx).Count(&Session{}) 114 } 115 116 // CleanupSessions cleans up expired sessions 117 func CleanupSessions(ctx context.Context, maxLifetime int64) error { 118 _, err := db.GetEngine(ctx).Where("expiry <= ?", timeutil.TimeStampNow().Add(-maxLifetime)).Delete(&Session{}) 119 return err 120 }