auths.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 admin
  5. import (
  6. "fmt"
  7. "net/http"
  8. "strings"
  9. "github.com/unknwon/com"
  10. log "unknwon.dev/clog/v2"
  11. "gogs.io/gogs/internal/auth"
  12. "gogs.io/gogs/internal/auth/github"
  13. "gogs.io/gogs/internal/auth/ldap"
  14. "gogs.io/gogs/internal/auth/pam"
  15. "gogs.io/gogs/internal/auth/smtp"
  16. "gogs.io/gogs/internal/conf"
  17. "gogs.io/gogs/internal/context"
  18. "gogs.io/gogs/internal/db"
  19. "gogs.io/gogs/internal/form"
  20. )
  21. const (
  22. AUTHS = "admin/auth/list"
  23. AUTH_NEW = "admin/auth/new"
  24. AUTH_EDIT = "admin/auth/edit"
  25. )
  26. func Authentications(c *context.Context) {
  27. c.Title("admin.authentication")
  28. c.PageIs("Admin")
  29. c.PageIs("AdminAuthentications")
  30. var err error
  31. c.Data["Sources"], err = db.LoginSources.List(db.ListLoginSourceOpts{})
  32. if err != nil {
  33. c.Error(err, "list login sources")
  34. return
  35. }
  36. c.Data["Total"] = db.LoginSources.Count()
  37. c.Success(AUTHS)
  38. }
  39. type dropdownItem struct {
  40. Name string
  41. Type interface{}
  42. }
  43. var (
  44. authSources = []dropdownItem{
  45. {auth.Name(auth.LDAP), auth.LDAP},
  46. {auth.Name(auth.DLDAP), auth.DLDAP},
  47. {auth.Name(auth.SMTP), auth.SMTP},
  48. {auth.Name(auth.PAM), auth.PAM},
  49. {auth.Name(auth.GitHub), auth.GitHub},
  50. }
  51. securityProtocols = []dropdownItem{
  52. {ldap.SecurityProtocolName(ldap.SecurityProtocolUnencrypted), ldap.SecurityProtocolUnencrypted},
  53. {ldap.SecurityProtocolName(ldap.SecurityProtocolLDAPS), ldap.SecurityProtocolLDAPS},
  54. {ldap.SecurityProtocolName(ldap.SecurityProtocolStartTLS), ldap.SecurityProtocolStartTLS},
  55. }
  56. )
  57. func NewAuthSource(c *context.Context) {
  58. c.Title("admin.auths.new")
  59. c.PageIs("Admin")
  60. c.PageIs("AdminAuthentications")
  61. c.Data["type"] = auth.LDAP
  62. c.Data["CurrentTypeName"] = auth.Name(auth.LDAP)
  63. c.Data["CurrentSecurityProtocol"] = ldap.SecurityProtocolName(ldap.SecurityProtocolUnencrypted)
  64. c.Data["smtp_auth"] = "PLAIN"
  65. c.Data["is_active"] = true
  66. c.Data["is_default"] = true
  67. c.Data["AuthSources"] = authSources
  68. c.Data["SecurityProtocols"] = securityProtocols
  69. c.Data["SMTPAuths"] = smtp.AuthTypes
  70. c.Success(AUTH_NEW)
  71. }
  72. func parseLDAPConfig(f form.Authentication) *ldap.Config {
  73. return &ldap.Config{
  74. Host: f.Host,
  75. Port: f.Port,
  76. SecurityProtocol: ldap.SecurityProtocol(f.SecurityProtocol),
  77. SkipVerify: f.SkipVerify,
  78. BindDN: f.BindDN,
  79. UserDN: f.UserDN,
  80. BindPassword: f.BindPassword,
  81. UserBase: f.UserBase,
  82. AttributeUsername: f.AttributeUsername,
  83. AttributeName: f.AttributeName,
  84. AttributeSurname: f.AttributeSurname,
  85. AttributeMail: f.AttributeMail,
  86. AttributesInBind: f.AttributesInBind,
  87. Filter: f.Filter,
  88. GroupEnabled: f.GroupEnabled,
  89. GroupDN: f.GroupDN,
  90. GroupFilter: f.GroupFilter,
  91. GroupMemberUID: f.GroupMemberUID,
  92. UserUID: f.UserUID,
  93. AdminFilter: f.AdminFilter,
  94. }
  95. }
  96. func parseSMTPConfig(f form.Authentication) *smtp.Config {
  97. return &smtp.Config{
  98. Auth: f.SMTPAuth,
  99. Host: f.SMTPHost,
  100. Port: f.SMTPPort,
  101. AllowedDomains: f.AllowedDomains,
  102. TLS: f.TLS,
  103. SkipVerify: f.SkipVerify,
  104. }
  105. }
  106. func NewAuthSourcePost(c *context.Context, f form.Authentication) {
  107. c.Title("admin.auths.new")
  108. c.PageIs("Admin")
  109. c.PageIs("AdminAuthentications")
  110. c.Data["CurrentTypeName"] = auth.Name(auth.Type(f.Type))
  111. c.Data["CurrentSecurityProtocol"] = ldap.SecurityProtocolName(ldap.SecurityProtocol(f.SecurityProtocol))
  112. c.Data["AuthSources"] = authSources
  113. c.Data["SecurityProtocols"] = securityProtocols
  114. c.Data["SMTPAuths"] = smtp.AuthTypes
  115. hasTLS := false
  116. var config interface{}
  117. switch auth.Type(f.Type) {
  118. case auth.LDAP, auth.DLDAP:
  119. config = parseLDAPConfig(f)
  120. hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SecurityProtocolUnencrypted
  121. case auth.SMTP:
  122. config = parseSMTPConfig(f)
  123. hasTLS = true
  124. case auth.PAM:
  125. config = &pam.Config{
  126. ServiceName: f.PAMServiceName,
  127. }
  128. case auth.GitHub:
  129. config = &github.Config{
  130. APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
  131. SkipVerify: f.SkipVerify,
  132. }
  133. hasTLS = true
  134. default:
  135. c.Status(http.StatusBadRequest)
  136. return
  137. }
  138. c.Data["HasTLS"] = hasTLS
  139. if c.HasError() {
  140. c.Success(AUTH_NEW)
  141. return
  142. }
  143. source, err := db.LoginSources.Create(db.CreateLoginSourceOpts{
  144. Type: auth.Type(f.Type),
  145. Name: f.Name,
  146. Activated: f.IsActive,
  147. Default: f.IsDefault,
  148. Config: config,
  149. })
  150. if err != nil {
  151. if db.IsErrLoginSourceAlreadyExist(err) {
  152. c.FormErr("Name")
  153. c.RenderWithErr(c.Tr("admin.auths.login_source_exist", f.Name), AUTH_NEW, f)
  154. } else {
  155. c.Error(err, "create login source")
  156. }
  157. return
  158. }
  159. if source.IsDefault {
  160. err = db.LoginSources.ResetNonDefault(source)
  161. if err != nil {
  162. c.Error(err, "reset non-default login sources")
  163. return
  164. }
  165. }
  166. log.Trace("Authentication created by admin(%s): %s", c.User.Name, f.Name)
  167. c.Flash.Success(c.Tr("admin.auths.new_success", f.Name))
  168. c.Redirect(conf.Server.Subpath + "/admin/auths")
  169. }
  170. func EditAuthSource(c *context.Context) {
  171. c.Title("admin.auths.edit")
  172. c.PageIs("Admin")
  173. c.PageIs("AdminAuthentications")
  174. c.Data["SecurityProtocols"] = securityProtocols
  175. c.Data["SMTPAuths"] = smtp.AuthTypes
  176. source, err := db.LoginSources.GetByID(c.ParamsInt64(":authid"))
  177. if err != nil {
  178. c.Error(err, "get login source by ID")
  179. return
  180. }
  181. c.Data["Source"] = source
  182. c.Data["HasTLS"] = source.Provider.HasTLS()
  183. c.Success(AUTH_EDIT)
  184. }
  185. func EditAuthSourcePost(c *context.Context, f form.Authentication) {
  186. c.Title("admin.auths.edit")
  187. c.PageIs("Admin")
  188. c.PageIs("AdminAuthentications")
  189. c.Data["SMTPAuths"] = smtp.AuthTypes
  190. source, err := db.LoginSources.GetByID(c.ParamsInt64(":authid"))
  191. if err != nil {
  192. c.Error(err, "get login source by ID")
  193. return
  194. }
  195. c.Data["Source"] = source
  196. c.Data["HasTLS"] = source.Provider.HasTLS()
  197. if c.HasError() {
  198. c.Success(AUTH_EDIT)
  199. return
  200. }
  201. var provider auth.Provider
  202. switch auth.Type(f.Type) {
  203. case auth.LDAP:
  204. provider = ldap.NewProvider(false, parseLDAPConfig(f))
  205. case auth.DLDAP:
  206. provider = ldap.NewProvider(true, parseLDAPConfig(f))
  207. case auth.SMTP:
  208. provider = smtp.NewProvider(parseSMTPConfig(f))
  209. case auth.PAM:
  210. provider = pam.NewProvider(&pam.Config{
  211. ServiceName: f.PAMServiceName,
  212. })
  213. case auth.GitHub:
  214. provider = github.NewProvider(&github.Config{
  215. APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
  216. SkipVerify: f.SkipVerify,
  217. })
  218. default:
  219. c.Status(http.StatusBadRequest)
  220. return
  221. }
  222. source.Name = f.Name
  223. source.IsActived = f.IsActive
  224. source.IsDefault = f.IsDefault
  225. source.Provider = provider
  226. if err := db.LoginSources.Save(source); err != nil {
  227. c.Error(err, "update login source")
  228. return
  229. }
  230. if source.IsDefault {
  231. err = db.LoginSources.ResetNonDefault(source)
  232. if err != nil {
  233. c.Error(err, "reset non-default login sources")
  234. return
  235. }
  236. }
  237. log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID)
  238. c.Flash.Success(c.Tr("admin.auths.update_success"))
  239. c.Redirect(conf.Server.Subpath + "/admin/auths/" + com.ToStr(f.ID))
  240. }
  241. func DeleteAuthSource(c *context.Context) {
  242. id := c.ParamsInt64(":authid")
  243. if err := db.LoginSources.DeleteByID(id); err != nil {
  244. if db.IsErrLoginSourceInUse(err) {
  245. c.Flash.Error(c.Tr("admin.auths.still_in_used"))
  246. } else {
  247. c.Flash.Error(fmt.Sprintf("DeleteSource: %v", err))
  248. }
  249. c.JSONSuccess(map[string]interface{}{
  250. "redirect": conf.Server.Subpath + "/admin/auths/" + c.Params(":authid"),
  251. })
  252. return
  253. }
  254. log.Trace("Authentication deleted by admin(%s): %d", c.User.Name, id)
  255. c.Flash.Success(c.Tr("admin.auths.deletion_success"))
  256. c.JSONSuccess(map[string]interface{}{
  257. "redirect": conf.Server.Subpath + "/admin/auths",
  258. })
  259. }