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.3 kB

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