gitea源码

v233.go 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package v1_19
  4. import (
  5. "fmt"
  6. "code.gitea.io/gitea/modules/json"
  7. "code.gitea.io/gitea/modules/secret"
  8. "code.gitea.io/gitea/modules/setting"
  9. api "code.gitea.io/gitea/modules/structs"
  10. "xorm.io/builder"
  11. "xorm.io/xorm"
  12. )
  13. func batchProcess[T any](x *xorm.Engine, buf []T, query func(limit, start int) *xorm.Session, process func(*xorm.Session, T) error) error {
  14. size := cap(buf)
  15. start := 0
  16. for {
  17. err := query(size, start).Find(&buf)
  18. if err != nil {
  19. return err
  20. }
  21. if len(buf) == 0 {
  22. return nil
  23. }
  24. err = func() error {
  25. sess := x.NewSession()
  26. defer sess.Close()
  27. if err := sess.Begin(); err != nil {
  28. return fmt.Errorf("unable to allow start session. Error: %w", err)
  29. }
  30. for _, record := range buf {
  31. if err := process(sess, record); err != nil {
  32. return err
  33. }
  34. }
  35. return sess.Commit()
  36. }()
  37. if err != nil {
  38. return err
  39. }
  40. if len(buf) < size {
  41. return nil
  42. }
  43. start += size
  44. buf = buf[:0]
  45. }
  46. }
  47. func AddHeaderAuthorizationEncryptedColWebhook(x *xorm.Engine) error {
  48. // Add the column to the table
  49. type Webhook struct {
  50. ID int64 `xorm:"pk autoincr"`
  51. Type string `xorm:"VARCHAR(16) 'type'"`
  52. Meta string `xorm:"TEXT"` // store hook-specific attributes
  53. // HeaderAuthorizationEncrypted should be accessed using HeaderAuthorization() and SetHeaderAuthorization()
  54. HeaderAuthorizationEncrypted string `xorm:"TEXT"`
  55. }
  56. err := x.Sync(new(Webhook))
  57. if err != nil {
  58. return err
  59. }
  60. // Migrate the matrix webhooks
  61. type MatrixMeta struct {
  62. HomeserverURL string `json:"homeserver_url"`
  63. Room string `json:"room_id"`
  64. MessageType int `json:"message_type"`
  65. }
  66. type MatrixMetaWithAccessToken struct {
  67. MatrixMeta
  68. AccessToken string `json:"access_token"`
  69. }
  70. err = batchProcess(x,
  71. make([]*Webhook, 0, 50),
  72. func(limit, start int) *xorm.Session {
  73. return x.Where("type=?", "matrix").OrderBy("id").Limit(limit, start)
  74. },
  75. func(sess *xorm.Session, hook *Webhook) error {
  76. // retrieve token from meta
  77. var withToken MatrixMetaWithAccessToken
  78. err := json.Unmarshal([]byte(hook.Meta), &withToken)
  79. if err != nil {
  80. return fmt.Errorf("unable to unmarshal matrix meta for webhook[id=%d]: %w", hook.ID, err)
  81. }
  82. if withToken.AccessToken == "" {
  83. return nil
  84. }
  85. // encrypt token
  86. authorization := "Bearer " + withToken.AccessToken
  87. hook.HeaderAuthorizationEncrypted, err = secret.EncryptSecret(setting.SecretKey, authorization)
  88. if err != nil {
  89. return fmt.Errorf("unable to encrypt access token for webhook[id=%d]: %w", hook.ID, err)
  90. }
  91. // remove token from meta
  92. withoutToken, err := json.Marshal(withToken.MatrixMeta)
  93. if err != nil {
  94. return fmt.Errorf("unable to marshal matrix meta for webhook[id=%d]: %w", hook.ID, err)
  95. }
  96. hook.Meta = string(withoutToken)
  97. // save in database
  98. count, err := sess.ID(hook.ID).Cols("meta", "header_authorization_encrypted").Update(hook)
  99. if count != 1 || err != nil {
  100. return fmt.Errorf("unable to update header_authorization_encrypted for webhook[id=%d]: %d,%w", hook.ID, count, err)
  101. }
  102. return nil
  103. })
  104. if err != nil {
  105. return err
  106. }
  107. // Remove access_token from HookTask
  108. type HookTask struct {
  109. ID int64 `xorm:"pk autoincr"`
  110. HookID int64
  111. PayloadContent string `xorm:"LONGTEXT"`
  112. }
  113. type MatrixPayloadSafe struct {
  114. Body string `json:"body"`
  115. MsgType string `json:"msgtype"`
  116. Format string `json:"format"`
  117. FormattedBody string `json:"formatted_body"`
  118. Commits []*api.PayloadCommit `json:"io.gitea.commits,omitempty"`
  119. }
  120. type MatrixPayloadUnsafe struct {
  121. MatrixPayloadSafe
  122. AccessToken string `json:"access_token"`
  123. }
  124. err = batchProcess(x,
  125. make([]*HookTask, 0, 50),
  126. func(limit, start int) *xorm.Session {
  127. return x.Where(builder.And(
  128. builder.In("hook_id", builder.Select("id").From("webhook").Where(builder.Eq{"type": "matrix"})),
  129. builder.Like{"payload_content", "access_token"},
  130. )).OrderBy("id").Limit(limit, 0) // ignore the provided "start", since other payload were already converted and don't contain 'payload_content' anymore
  131. },
  132. func(sess *xorm.Session, hookTask *HookTask) error {
  133. // retrieve token from payload_content
  134. var withToken MatrixPayloadUnsafe
  135. err := json.Unmarshal([]byte(hookTask.PayloadContent), &withToken)
  136. if err != nil {
  137. return fmt.Errorf("unable to unmarshal payload_content for hook_task[id=%d]: %w", hookTask.ID, err)
  138. }
  139. if withToken.AccessToken == "" {
  140. return nil
  141. }
  142. // remove token from payload_content
  143. withoutToken, err := json.Marshal(withToken.MatrixPayloadSafe)
  144. if err != nil {
  145. return fmt.Errorf("unable to marshal payload_content for hook_task[id=%d]: %w", hookTask.ID, err)
  146. }
  147. hookTask.PayloadContent = string(withoutToken)
  148. // save in database
  149. count, err := sess.ID(hookTask.ID).Cols("payload_content").Update(hookTask)
  150. if count != 1 || err != nil {
  151. return fmt.Errorf("unable to update payload_content for hook_task[id=%d]: %d,%w", hookTask.ID, count, err)
  152. }
  153. return nil
  154. })
  155. if err != nil {
  156. return err
  157. }
  158. return nil
  159. }