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