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

284 lines
6.8 KiB

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