auths.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // Copyright 2015 - Present, The Gogs Authors. All rights reserved.
  2. // Copyright 2018 - Present, Gitote. All rights reserved.
  3. //
  4. // This source code is licensed under the MIT license found in the
  5. // LICENSE file in the root directory of this source tree.
  6. package admin
  7. import (
  8. "fmt"
  9. "gitote/gitote/models"
  10. "gitote/gitote/pkg/auth/ldap"
  11. "gitote/gitote/pkg/context"
  12. "gitote/gitote/pkg/form"
  13. "gitote/gitote/pkg/setting"
  14. "net/http"
  15. "strings"
  16. "github.com/go-xorm/core"
  17. "gitlab.com/gitote/com"
  18. log "gopkg.in/clog.v1"
  19. )
  20. const (
  21. // AuthsTPL list page template
  22. AuthsTPL = "admin/auth/list"
  23. // AuthNewTPL page template
  24. AuthNewTPL = "admin/auth/new"
  25. // AuthEditTPL page template
  26. AuthEditTPL = "admin/auth/edit"
  27. )
  28. // Authentications shows authentication page
  29. func Authentications(c *context.Context) {
  30. c.Title("admin.authentication")
  31. c.PageIs("Admin")
  32. c.PageIs("AdminAuthentications")
  33. var err error
  34. c.Data["Sources"], err = models.LoginSources()
  35. if err != nil {
  36. c.ServerError("LoginSources", err)
  37. return
  38. }
  39. c.Data["Total"] = models.CountLoginSources()
  40. c.Success(AuthsTPL)
  41. }
  42. type dropdownItem struct {
  43. Name string
  44. Type interface{}
  45. }
  46. var (
  47. authSources = []dropdownItem{
  48. {models.LoginNames[models.LoginLDAP], models.LoginLDAP},
  49. {models.LoginNames[models.LoginDLDAP], models.LoginDLDAP},
  50. {models.LoginNames[models.LoginSMTP], models.LoginSMTP},
  51. {models.LoginNames[models.LoginPAM], models.LoginPAM},
  52. {models.LoginNames[models.LoginGitHub], models.LoginGitHub},
  53. }
  54. securityProtocols = []dropdownItem{
  55. {models.SecurityProtocolNames[ldap.SecurityProtocolUnencrypted], ldap.SecurityProtocolUnencrypted},
  56. {models.SecurityProtocolNames[ldap.SecurityProtocolLDAPS], ldap.SecurityProtocolLDAPS},
  57. {models.SecurityProtocolNames[ldap.SecurityProtocolStartTLS], ldap.SecurityProtocolStartTLS},
  58. }
  59. )
  60. // NewAuthSource shows create auth page
  61. func NewAuthSource(c *context.Context) {
  62. c.Title("admin.auths.new")
  63. c.PageIs("Admin")
  64. c.PageIs("AdminAuthentications")
  65. c.Data["type"] = models.LoginLDAP
  66. c.Data["CurrentTypeName"] = models.LoginNames[models.LoginLDAP]
  67. c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocolUnencrypted]
  68. c.Data["smtp_auth"] = "PLAIN"
  69. c.Data["is_active"] = true
  70. c.Data["is_default"] = true
  71. c.Data["AuthSources"] = authSources
  72. c.Data["SecurityProtocols"] = securityProtocols
  73. c.Data["SMTPAuths"] = models.SMTPAuths
  74. c.Success(AuthNewTPL)
  75. }
  76. func parseLDAPConfig(f form.Authentication) *models.LDAPConfig {
  77. return &models.LDAPConfig{
  78. Source: &ldap.Source{
  79. Host: f.Host,
  80. Port: f.Port,
  81. SecurityProtocol: ldap.SecurityProtocol(f.SecurityProtocol),
  82. SkipVerify: f.SkipVerify,
  83. BindDN: f.BindDN,
  84. UserDN: f.UserDN,
  85. BindPassword: f.BindPassword,
  86. UserBase: f.UserBase,
  87. AttributeUsername: f.AttributeUsername,
  88. AttributeName: f.AttributeName,
  89. AttributeSurname: f.AttributeSurname,
  90. AttributeMail: f.AttributeMail,
  91. AttributesInBind: f.AttributesInBind,
  92. Filter: f.Filter,
  93. GroupEnabled: f.GroupEnabled,
  94. GroupDN: f.GroupDN,
  95. GroupFilter: f.GroupFilter,
  96. GroupMemberUID: f.GroupMemberUID,
  97. UserUID: f.UserUID,
  98. AdminFilter: f.AdminFilter,
  99. },
  100. }
  101. }
  102. func parseSMTPConfig(f form.Authentication) *models.SMTPConfig {
  103. return &models.SMTPConfig{
  104. Auth: f.SMTPAuth,
  105. Host: f.SMTPHost,
  106. Port: f.SMTPPort,
  107. AllowedDomains: f.AllowedDomains,
  108. TLS: f.TLS,
  109. SkipVerify: f.SkipVerify,
  110. }
  111. }
  112. // NewAuthSourcePost creates a new auth source
  113. func NewAuthSourcePost(c *context.Context, f form.Authentication) {
  114. c.Title("admin.auths.new")
  115. c.PageIs("Admin")
  116. c.PageIs("AdminAuthentications")
  117. c.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(f.Type)]
  118. c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(f.SecurityProtocol)]
  119. c.Data["AuthSources"] = authSources
  120. c.Data["SecurityProtocols"] = securityProtocols
  121. c.Data["SMTPAuths"] = models.SMTPAuths
  122. hasTLS := false
  123. var config core.Conversion
  124. switch models.LoginType(f.Type) {
  125. case models.LoginLDAP, models.LoginDLDAP:
  126. config = parseLDAPConfig(f)
  127. hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SecurityProtocolUnencrypted
  128. case models.LoginSMTP:
  129. config = parseSMTPConfig(f)
  130. hasTLS = true
  131. case models.LoginPAM:
  132. config = &models.PAMConfig{
  133. ServiceName: f.PAMServiceName,
  134. }
  135. case models.LoginGitHub:
  136. config = &models.GitHubConfig{
  137. APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
  138. }
  139. default:
  140. c.Error(http.StatusBadRequest)
  141. return
  142. }
  143. c.Data["HasTLS"] = hasTLS
  144. if c.HasError() {
  145. c.Success(AuthNewTPL)
  146. return
  147. }
  148. if err := models.CreateLoginSource(&models.LoginSource{
  149. Type: models.LoginType(f.Type),
  150. Name: f.Name,
  151. IsActived: f.IsActive,
  152. IsDefault: f.IsDefault,
  153. Cfg: config,
  154. }); err != nil {
  155. if models.IsErrLoginSourceAlreadyExist(err) {
  156. c.FormErr("Name")
  157. c.RenderWithErr(c.Tr("admin.auths.login_source_exist", err.(models.ErrLoginSourceAlreadyExist).Name), AuthNewTPL, f)
  158. } else {
  159. c.ServerError("CreateSource", err)
  160. }
  161. return
  162. }
  163. log.Trace("Authentication created by admin(%s): %s", c.User.Name, f.Name)
  164. c.Flash.Success(c.Tr("admin.auths.new_success", f.Name))
  165. c.Redirect(setting.AppSubURL + "/admin/auths")
  166. }
  167. // EditAuthSource shows edit auth source page
  168. func EditAuthSource(c *context.Context) {
  169. c.Title("admin.auths.edit")
  170. c.PageIs("Admin")
  171. c.PageIs("AdminAuthentications")
  172. c.Data["SecurityProtocols"] = securityProtocols
  173. c.Data["SMTPAuths"] = models.SMTPAuths
  174. source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid"))
  175. if err != nil {
  176. c.ServerError("GetLoginSourceByID", err)
  177. return
  178. }
  179. c.Data["Source"] = source
  180. c.Data["HasTLS"] = source.HasTLS()
  181. c.Success(AuthEditTPL)
  182. }
  183. // EditAuthSourcePost edits an auth source
  184. func EditAuthSourcePost(c *context.Context, f form.Authentication) {
  185. c.Title("admin.auths.edit")
  186. c.PageIs("Admin")
  187. c.PageIs("AdminAuthentications")
  188. c.Data["SMTPAuths"] = models.SMTPAuths
  189. source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid"))
  190. if err != nil {
  191. c.ServerError("GetLoginSourceByID", err)
  192. return
  193. }
  194. c.Data["Source"] = source
  195. c.Data["HasTLS"] = source.HasTLS()
  196. if c.HasError() {
  197. c.Success(AuthEditTPL)
  198. return
  199. }
  200. var config core.Conversion
  201. switch models.LoginType(f.Type) {
  202. case models.LoginLDAP, models.LoginDLDAP:
  203. config = parseLDAPConfig(f)
  204. case models.LoginSMTP:
  205. config = parseSMTPConfig(f)
  206. case models.LoginPAM:
  207. config = &models.PAMConfig{
  208. ServiceName: f.PAMServiceName,
  209. }
  210. case models.LoginGitHub:
  211. config = &models.GitHubConfig{
  212. APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",
  213. }
  214. default:
  215. c.Error(http.StatusBadRequest)
  216. return
  217. }
  218. source.Name = f.Name
  219. source.IsActived = f.IsActive
  220. source.IsDefault = f.IsDefault
  221. source.Cfg = config
  222. if err := models.UpdateLoginSource(source); err != nil {
  223. c.ServerError("UpdateLoginSource", err)
  224. return
  225. }
  226. log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID)
  227. c.Flash.Success("Authentication setting has been updated successfully.")
  228. c.Redirect(setting.AppSubURL + "/admin/auths/" + com.ToStr(f.ID))
  229. }
  230. // DeleteAuthSource deletes an auth source
  231. func DeleteAuthSource(c *context.Context) {
  232. source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid"))
  233. if err != nil {
  234. c.ServerError("GetLoginSourceByID", err)
  235. return
  236. }
  237. if err = models.DeleteSource(source); err != nil {
  238. if models.IsErrLoginSourceInUse(err) {
  239. c.Flash.Error("This authentication is still used by some users, please delete or convert these users to another login type first.")
  240. } else {
  241. c.Flash.Error(fmt.Sprintf("DeleteSource: %v", err))
  242. }
  243. c.JSONSuccess(map[string]interface{}{
  244. "redirect": setting.AppSubURL + "/admin/auths/" + c.Params(":authid"),
  245. })
  246. return
  247. }
  248. log.Trace("Authentication deleted by admin(%s): %d", c.User.Name, source.ID)
  249. c.Flash.Success("Authentication has been deleted successfully!")
  250. c.JSONSuccess(map[string]interface{}{
  251. "redirect": setting.AppSubURL + "/admin/auths",
  252. })
  253. }