gitea

Development moved to Codeberg

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 38
  39. 39
  40. 40
  41. 41
  42. 42
  43. 43
  44. 44
  45. 45
  46. 46
  47. 47
  48. 48
  49. 49
  50. 50
  51. 51
  52. 52
  53. 53
  54. 54
  55. 55
  56. 56
  57. 57
  58. 58
  59. 59
  60. 60
  61. 61
  62. 62
  63. 63
  64. 64
  65. 65
  66. 66
  67. 67
  68. 68
  69. 69
  70. 70
  71. 71
  72. 72
  73. 73
  74. 74
  75. 75
  76. 76
  77. 77
  78. 78
  79. 79
  80. 80
  81. 81
  82. 82
  83. 83
  84. 84
  85. 85
  86. 86
  87. 87
  88. 88
  89. 89
  90. 90
  91. 91
  92. 92
  93. 93
  94. 94
  95. 95
  96. 96
  97. 97
  98. 98
  99. 99
  100. 100
  101. 101
  102. 102
  103. 103
  104. 104
  105. 105
  106. 106
  107. 107
  108. 108
  109. 109
  110. 110
  111. 111
  112. 112
  113. 113
  114. 114
  115. 115
  116. 116
  117. 117
  118. 118
  119. 119
  120. 120
  121. 121
  122. 122
  123. 123
  124. 124
  125. 125
  126. 126
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package auth

import (
	"fmt"

	"code.gitea.io/gitea/models/db"
	"code.gitea.io/gitea/modules/timeutil"
)

// 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
	Data   []byte             `xorm:"BLOB"`        // on MySQL this has a maximum size of 64Kb - this may need to be increased
	Expiry timeutil.TimeStamp // has to be Expiry to match with go-chi/session
}

func init() {
	db.RegisterModel(new(Session))
}

// UpdateSession updates the session with provided id
func UpdateSession(key string, data []byte) error {
	_, err := db.GetEngine(db.DefaultContext).ID(key).Update(&Session{
		Data:   data,
		Expiry: timeutil.TimeStampNow(),
	})
	return err
}

// ReadSession reads the data for the provided session
func ReadSession(key string) (*Session, error) {
	session := Session{
		Key: key,
	}

	ctx, committer, err := db.TxContext()
	if err != nil {
		return nil, err
	}
	defer committer.Close()

	if has, err := db.GetByBean(ctx, &session); err != nil {
		return nil, err
	} else if !has {
		session.Expiry = timeutil.TimeStampNow()
		if err := db.Insert(ctx, &session); err != nil {
			return nil, err
		}
	}

	return &session, committer.Commit()
}

// ExistSession checks if a session exists
func ExistSession(key string) (bool, error) {
	session := Session{
		Key: key,
	}
	return db.GetEngine(db.DefaultContext).Get(&session)
}

// DestroySession destroys a session
func DestroySession(key string) error {
	_, err := db.GetEngine(db.DefaultContext).Delete(&Session{
		Key: key,
	})
	return err
}

// RegenerateSession regenerates a session from the old id
func RegenerateSession(oldKey, newKey string) (*Session, error) {
	ctx, committer, err := db.TxContext()
	if err != nil {
		return nil, err
	}
	defer committer.Close()

	if has, err := db.GetByBean(ctx, &Session{
		Key: newKey,
	}); err != nil {
		return nil, err
	} else if has {
		return nil, fmt.Errorf("session Key: %s already exists", newKey)
	}

	if has, err := db.GetByBean(ctx, &Session{
		Key: oldKey,
	}); err != nil {
		return nil, err
	} else if !has {
		if err := db.Insert(ctx, &Session{
			Key:    oldKey,
			Expiry: timeutil.TimeStampNow(),
		}); err != nil {
			return nil, err
		}
	}

	if _, err := db.Exec(ctx, "UPDATE "+db.TableName(&Session{})+" SET `key` = ? WHERE `key`=?", newKey, oldKey); err != nil {
		return nil, err
	}

	s := Session{
		Key: newKey,
	}
	if _, err := db.GetByBean(ctx, &s); err != nil {
		return nil, err
	}

	return &s, committer.Commit()
}

// CountSessions returns the number of sessions
func CountSessions() (int64, error) {
	return db.GetEngine(db.DefaultContext).Count(&Session{})
}

// CleanupSessions cleans up expired sessions
func CleanupSessions(maxLifetime int64) error {
	_, err := db.GetEngine(db.DefaultContext).Where("expiry <= ?", timeutil.TimeStampNow().Add(-maxLifetime)).Delete(&Session{})
	return err
}