auth.go 6.3 KB

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