You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

auth.go 6.1 kB

10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package auth
  5. import (
  6. "net/http"
  7. "reflect"
  8. "strings"
  9. "github.com/Unknwon/com"
  10. "github.com/Unknwon/macaron"
  11. "github.com/macaron-contrib/binding"
  12. "github.com/macaron-contrib/session"
  13. "github.com/gogits/gogs/models"
  14. "github.com/gogits/gogs/modules/base"
  15. "github.com/gogits/gogs/modules/log"
  16. "github.com/gogits/gogs/modules/setting"
  17. "github.com/gogits/gogs/modules/uuid"
  18. )
  19. func IsAPIPath(url string) bool {
  20. return strings.HasPrefix(url, "/api/")
  21. }
  22. // SignedInId returns the id of signed in user.
  23. func SignedInId(req *http.Request, sess session.Store) int64 {
  24. if !models.HasEngine {
  25. return 0
  26. }
  27. // API calls need to check access token.
  28. if IsAPIPath(req.URL.Path) {
  29. auHead := req.Header.Get("Authorization")
  30. if len(auHead) > 0 {
  31. auths := strings.Fields(auHead)
  32. if len(auths) == 2 && auths[0] == "token" {
  33. t, err := models.GetAccessTokenBySha(auths[1])
  34. if err != nil {
  35. if err != models.ErrAccessTokenNotExist {
  36. log.Error(4, "GetAccessTokenBySha: %v", err)
  37. }
  38. return 0
  39. }
  40. return t.UID
  41. }
  42. }
  43. }
  44. uid := sess.Get("uid")
  45. if uid == nil {
  46. return 0
  47. }
  48. if id, ok := uid.(int64); ok {
  49. if _, err := models.GetUserByID(id); err != nil {
  50. if !models.IsErrUserNotExist(err) {
  51. log.Error(4, "GetUserById: %v", err)
  52. }
  53. return 0
  54. }
  55. return id
  56. }
  57. return 0
  58. }
  59. // SignedInUser returns the user object of signed user.
  60. // It returns a bool value to indicate whether user uses basic auth or not.
  61. func SignedInUser(req *http.Request, sess session.Store) (*models.User, bool) {
  62. if !models.HasEngine {
  63. return nil, false
  64. }
  65. uid := SignedInId(req, sess)
  66. if uid <= 0 {
  67. if setting.Service.EnableReverseProxyAuth {
  68. webAuthUser := req.Header.Get(setting.ReverseProxyAuthUser)
  69. if len(webAuthUser) > 0 {
  70. u, err := models.GetUserByName(webAuthUser)
  71. if err != nil {
  72. if !models.IsErrUserNotExist(err) {
  73. log.Error(4, "GetUserByName: %v", err)
  74. return nil, false
  75. }
  76. // Check if enabled auto-registration.
  77. if setting.Service.EnableReverseProxyAutoRegister {
  78. u := &models.User{
  79. Name: webAuthUser,
  80. Email: uuid.NewV4().String() + "@localhost",
  81. Passwd: webAuthUser,
  82. IsActive: true,
  83. }
  84. if err = models.CreateUser(u); err != nil {
  85. // FIXME: should I create a system notice?
  86. log.Error(4, "CreateUser: %v", err)
  87. return nil, false
  88. } else {
  89. return u, false
  90. }
  91. }
  92. }
  93. return u, false
  94. }
  95. }
  96. // Check with basic auth.
  97. baHead := req.Header.Get("Authorization")
  98. if len(baHead) > 0 {
  99. auths := strings.Fields(baHead)
  100. if len(auths) == 2 && auths[0] == "Basic" {
  101. uname, passwd, _ := base.BasicAuthDecode(auths[1])
  102. u, err := models.UserSignIn(uname, passwd)
  103. if err != nil {
  104. if !models.IsErrUserNotExist(err) {
  105. log.Error(4, "UserSignIn: %v", err)
  106. }
  107. return nil, false
  108. }
  109. return u, true
  110. }
  111. }
  112. return nil, false
  113. }
  114. u, err := models.GetUserByID(uid)
  115. if err != nil {
  116. log.Error(4, "GetUserById: %v", err)
  117. return nil, false
  118. }
  119. return u, false
  120. }
  121. type Form interface {
  122. binding.Validator
  123. }
  124. func init() {
  125. binding.SetNameMapper(com.ToSnakeCase)
  126. }
  127. // AssignForm assign form values back to the template data.
  128. func AssignForm(form interface{}, data map[string]interface{}) {
  129. typ := reflect.TypeOf(form)
  130. val := reflect.ValueOf(form)
  131. if typ.Kind() == reflect.Ptr {
  132. typ = typ.Elem()
  133. val = val.Elem()
  134. }
  135. for i := 0; i < typ.NumField(); i++ {
  136. field := typ.Field(i)
  137. fieldName := field.Tag.Get("form")
  138. // Allow ignored fields in the struct
  139. if fieldName == "-" {
  140. continue
  141. } else if len(fieldName) == 0 {
  142. fieldName = com.ToSnakeCase(field.Name)
  143. }
  144. data[fieldName] = val.Field(i).Interface()
  145. }
  146. }
  147. func getSize(field reflect.StructField, prefix string) string {
  148. for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
  149. if strings.HasPrefix(rule, prefix) {
  150. return rule[len(prefix) : len(rule)-1]
  151. }
  152. }
  153. return ""
  154. }
  155. func GetSize(field reflect.StructField) string {
  156. return getSize(field, "Size(")
  157. }
  158. func GetMinSize(field reflect.StructField) string {
  159. return getSize(field, "MinSize(")
  160. }
  161. func GetMaxSize(field reflect.StructField) string {
  162. return getSize(field, "MaxSize(")
  163. }
  164. func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
  165. if errs.Len() == 0 {
  166. return errs
  167. }
  168. data["HasError"] = true
  169. AssignForm(f, data)
  170. typ := reflect.TypeOf(f)
  171. val := reflect.ValueOf(f)
  172. if typ.Kind() == reflect.Ptr {
  173. typ = typ.Elem()
  174. val = val.Elem()
  175. }
  176. for i := 0; i < typ.NumField(); i++ {
  177. field := typ.Field(i)
  178. fieldName := field.Tag.Get("form")
  179. // Allow ignored fields in the struct
  180. if fieldName == "-" {
  181. continue
  182. }
  183. if errs[0].FieldNames[0] == field.Name {
  184. data["Err_"+field.Name] = true
  185. trName := field.Tag.Get("locale")
  186. if len(trName) == 0 {
  187. trName = l.Tr("form." + field.Name)
  188. } else {
  189. trName = l.Tr(trName)
  190. }
  191. switch errs[0].Classification {
  192. case binding.ERR_REQUIRED:
  193. data["ErrorMsg"] = trName + l.Tr("form.require_error")
  194. case binding.ERR_ALPHA_DASH:
  195. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
  196. case binding.ERR_ALPHA_DASH_DOT:
  197. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
  198. case binding.ERR_SIZE:
  199. data["ErrorMsg"] = trName + l.Tr("form.size_error", GetSize(field))
  200. case binding.ERR_MIN_SIZE:
  201. data["ErrorMsg"] = trName + l.Tr("form.min_size_error", GetMinSize(field))
  202. case binding.ERR_MAX_SIZE:
  203. data["ErrorMsg"] = trName + l.Tr("form.max_size_error", GetMaxSize(field))
  204. case binding.ERR_EMAIL:
  205. data["ErrorMsg"] = trName + l.Tr("form.email_error")
  206. case binding.ERR_URL:
  207. data["ErrorMsg"] = trName + l.Tr("form.url_error")
  208. default:
  209. data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
  210. }
  211. return errs
  212. }
  213. }
  214. return errs
  215. }