// Copyright 2015 - Present, The Gogs Authors. All rights reserved. // Copyright 2018 - Present, Gitote. All rights reserved. // // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. package admin import ( "fmt" "gitote/gitote/models" "gitote/gitote/pkg/auth/ldap" "gitote/gitote/pkg/context" "gitote/gitote/pkg/form" "gitote/gitote/pkg/setting" "net/http" "strings" "github.com/go-xorm/core" "gitlab.com/gitote/com" log "gopkg.in/clog.v1" ) const ( // AuthsTPL list page template AuthsTPL = "admin/auth/list" // AuthNewTPL page template AuthNewTPL = "admin/auth/new" // AuthEditTPL page template AuthEditTPL = "admin/auth/edit" ) // Authentications shows authentication page func Authentications(c *context.Context) { c.Title("admin.authentication") c.PageIs("Admin") c.PageIs("AdminAuthentications") var err error c.Data["Sources"], err = models.LoginSources() if err != nil { c.ServerError("LoginSources", err) return } c.Data["Total"] = models.CountLoginSources() c.Success(AuthsTPL) } type dropdownItem struct { Name string Type interface{} } var ( authSources = []dropdownItem{ {models.LoginNames[models.LoginLDAP], models.LoginLDAP}, {models.LoginNames[models.LoginDLDAP], models.LoginDLDAP}, {models.LoginNames[models.LoginSMTP], models.LoginSMTP}, {models.LoginNames[models.LoginPAM], models.LoginPAM}, {models.LoginNames[models.LoginGitHub], models.LoginGitHub}, } securityProtocols = []dropdownItem{ {models.SecurityProtocolNames[ldap.SecurityProtocolUnencrypted], ldap.SecurityProtocolUnencrypted}, {models.SecurityProtocolNames[ldap.SecurityProtocolLDAPS], ldap.SecurityProtocolLDAPS}, {models.SecurityProtocolNames[ldap.SecurityProtocolStartTLS], ldap.SecurityProtocolStartTLS}, } ) // NewAuthSource shows create auth page func NewAuthSource(c *context.Context) { c.Title("admin.auths.new") c.PageIs("Admin") c.PageIs("AdminAuthentications") c.Data["type"] = models.LoginLDAP c.Data["CurrentTypeName"] = models.LoginNames[models.LoginLDAP] c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocolUnencrypted] c.Data["smtp_auth"] = "PLAIN" c.Data["is_active"] = true c.Data["is_default"] = true c.Data["AuthSources"] = authSources c.Data["SecurityProtocols"] = securityProtocols c.Data["SMTPAuths"] = models.SMTPAuths c.Success(AuthNewTPL) } func parseLDAPConfig(f form.Authentication) *models.LDAPConfig { return &models.LDAPConfig{ Source: &ldap.Source{ Host: f.Host, Port: f.Port, SecurityProtocol: ldap.SecurityProtocol(f.SecurityProtocol), SkipVerify: f.SkipVerify, BindDN: f.BindDN, UserDN: f.UserDN, BindPassword: f.BindPassword, UserBase: f.UserBase, AttributeUsername: f.AttributeUsername, AttributeName: f.AttributeName, AttributeSurname: f.AttributeSurname, AttributeMail: f.AttributeMail, AttributesInBind: f.AttributesInBind, Filter: f.Filter, GroupEnabled: f.GroupEnabled, GroupDN: f.GroupDN, GroupFilter: f.GroupFilter, GroupMemberUID: f.GroupMemberUID, UserUID: f.UserUID, AdminFilter: f.AdminFilter, }, } } func parseSMTPConfig(f form.Authentication) *models.SMTPConfig { return &models.SMTPConfig{ Auth: f.SMTPAuth, Host: f.SMTPHost, Port: f.SMTPPort, AllowedDomains: f.AllowedDomains, TLS: f.TLS, SkipVerify: f.SkipVerify, } } // NewAuthSourcePost creates a new auth source func NewAuthSourcePost(c *context.Context, f form.Authentication) { c.Title("admin.auths.new") c.PageIs("Admin") c.PageIs("AdminAuthentications") c.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(f.Type)] c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(f.SecurityProtocol)] c.Data["AuthSources"] = authSources c.Data["SecurityProtocols"] = securityProtocols c.Data["SMTPAuths"] = models.SMTPAuths hasTLS := false var config core.Conversion switch models.LoginType(f.Type) { case models.LoginLDAP, models.LoginDLDAP: config = parseLDAPConfig(f) hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SecurityProtocolUnencrypted case models.LoginSMTP: config = parseSMTPConfig(f) hasTLS = true case models.LoginPAM: config = &models.PAMConfig{ ServiceName: f.PAMServiceName, } case models.LoginGitHub: config = &models.GitHubConfig{ APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/", } default: c.Error(http.StatusBadRequest) return } c.Data["HasTLS"] = hasTLS if c.HasError() { c.Success(AuthNewTPL) return } if err := models.CreateLoginSource(&models.LoginSource{ Type: models.LoginType(f.Type), Name: f.Name, IsActived: f.IsActive, IsDefault: f.IsDefault, Cfg: config, }); err != nil { if models.IsErrLoginSourceAlreadyExist(err) { c.FormErr("Name") c.RenderWithErr(c.Tr("admin.auths.login_source_exist", err.(models.ErrLoginSourceAlreadyExist).Name), AuthNewTPL, f) } else { c.ServerError("CreateSource", err) } return } log.Trace("Authentication created by admin(%s): %s", c.User.Name, f.Name) c.Flash.Success(c.Tr("admin.auths.new_success", f.Name)) c.Redirect(setting.AppSubURL + "/admin/auths") } // EditAuthSource shows edit auth source page func EditAuthSource(c *context.Context) { c.Title("admin.auths.edit") c.PageIs("Admin") c.PageIs("AdminAuthentications") c.Data["SecurityProtocols"] = securityProtocols c.Data["SMTPAuths"] = models.SMTPAuths source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { c.ServerError("GetLoginSourceByID", err) return } c.Data["Source"] = source c.Data["HasTLS"] = source.HasTLS() c.Success(AuthEditTPL) } // EditAuthSourcePost edits an auth source func EditAuthSourcePost(c *context.Context, f form.Authentication) { c.Title("admin.auths.edit") c.PageIs("Admin") c.PageIs("AdminAuthentications") c.Data["SMTPAuths"] = models.SMTPAuths source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { c.ServerError("GetLoginSourceByID", err) return } c.Data["Source"] = source c.Data["HasTLS"] = source.HasTLS() if c.HasError() { c.Success(AuthEditTPL) return } var config core.Conversion switch models.LoginType(f.Type) { case models.LoginLDAP, models.LoginDLDAP: config = parseLDAPConfig(f) case models.LoginSMTP: config = parseSMTPConfig(f) case models.LoginPAM: config = &models.PAMConfig{ ServiceName: f.PAMServiceName, } case models.LoginGitHub: config = &models.GitHubConfig{ APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/", } default: c.Error(http.StatusBadRequest) return } source.Name = f.Name source.IsActived = f.IsActive source.IsDefault = f.IsDefault source.Cfg = config if err := models.UpdateLoginSource(source); err != nil { c.ServerError("UpdateLoginSource", err) return } log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID) c.Flash.Success("Authentication setting has been updated successfully.") c.Redirect(setting.AppSubURL + "/admin/auths/" + com.ToStr(f.ID)) } // DeleteAuthSource deletes an auth source func DeleteAuthSource(c *context.Context) { source, err := models.GetLoginSourceByID(c.ParamsInt64(":authid")) if err != nil { c.ServerError("GetLoginSourceByID", err) return } if err = models.DeleteSource(source); err != nil { if models.IsErrLoginSourceInUse(err) { c.Flash.Error("This authentication is still used by some users, please delete or convert these users to another login type first.") } else { c.Flash.Error(fmt.Sprintf("DeleteSource: %v", err)) } c.JSONSuccess(map[string]interface{}{ "redirect": setting.AppSubURL + "/admin/auths/" + c.Params(":authid"), }) return } log.Trace("Authentication deleted by admin(%s): %d", c.User.Name, source.ID) c.Flash.Success("Authentication has been deleted successfully!") c.JSONSuccess(map[string]interface{}{ "redirect": setting.AppSubURL + "/admin/auths", }) }