| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 | // Copyright 2014 The Gogs Authors. All rights reserved.// Use of this source code is governed by a MIT-style// license that can be found in the LICENSE file.package adminimport (	"fmt"	"net/http"	"strings"	"github.com/unknwon/com"	log "unknwon.dev/clog/v2"	"gogs.io/gogs/internal/auth"	"gogs.io/gogs/internal/auth/github"	"gogs.io/gogs/internal/auth/ldap"	"gogs.io/gogs/internal/auth/pam"	"gogs.io/gogs/internal/auth/smtp"	"gogs.io/gogs/internal/conf"	"gogs.io/gogs/internal/context"	"gogs.io/gogs/internal/database"	"gogs.io/gogs/internal/form")const (	AUTHS     = "admin/auth/list"	AUTH_NEW  = "admin/auth/new"	AUTH_EDIT = "admin/auth/edit")func Authentications(c *context.Context) {	c.Title("admin.authentication")	c.PageIs("Admin")	c.PageIs("AdminAuthentications")	var err error	c.Data["Sources"], err = database.Handle.LoginSources().List(c.Req.Context(), database.ListLoginSourceOptions{})	if err != nil {		c.Error(err, "list login sources")		return	}	c.Data["Total"] = database.Handle.LoginSources().Count(c.Req.Context())	c.Success(AUTHS)}type dropdownItem struct {	Name string	Type any}var (	authSources = []dropdownItem{		{auth.Name(auth.LDAP), auth.LDAP},		{auth.Name(auth.DLDAP), auth.DLDAP},		{auth.Name(auth.SMTP), auth.SMTP},		{auth.Name(auth.PAM), auth.PAM},		{auth.Name(auth.GitHub), auth.GitHub},	}	securityProtocols = []dropdownItem{		{ldap.SecurityProtocolName(ldap.SecurityProtocolUnencrypted), ldap.SecurityProtocolUnencrypted},		{ldap.SecurityProtocolName(ldap.SecurityProtocolLDAPS), ldap.SecurityProtocolLDAPS},		{ldap.SecurityProtocolName(ldap.SecurityProtocolStartTLS), ldap.SecurityProtocolStartTLS},	})func NewAuthSource(c *context.Context) {	c.Title("admin.auths.new")	c.PageIs("Admin")	c.PageIs("AdminAuthentications")	c.Data["type"] = auth.LDAP	c.Data["CurrentTypeName"] = auth.Name(auth.LDAP)	c.Data["CurrentSecurityProtocol"] = ldap.SecurityProtocolName(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"] = smtp.AuthTypes	c.Success(AUTH_NEW)}func parseLDAPConfig(f form.Authentication) *ldap.Config {	return &ldap.Config{		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) *smtp.Config {	return &smtp.Config{		Auth:           f.SMTPAuth,		Host:           f.SMTPHost,		Port:           f.SMTPPort,		AllowedDomains: f.AllowedDomains,		TLS:            f.TLS,		SkipVerify:     f.SkipVerify,	}}func NewAuthSourcePost(c *context.Context, f form.Authentication) {	c.Title("admin.auths.new")	c.PageIs("Admin")	c.PageIs("AdminAuthentications")	c.Data["CurrentTypeName"] = auth.Name(auth.Type(f.Type))	c.Data["CurrentSecurityProtocol"] = ldap.SecurityProtocolName(ldap.SecurityProtocol(f.SecurityProtocol))	c.Data["AuthSources"] = authSources	c.Data["SecurityProtocols"] = securityProtocols	c.Data["SMTPAuths"] = smtp.AuthTypes	hasTLS := false	var config any	switch auth.Type(f.Type) {	case auth.LDAP, auth.DLDAP:		config = parseLDAPConfig(f)		hasTLS = ldap.SecurityProtocol(f.SecurityProtocol) > ldap.SecurityProtocolUnencrypted	case auth.SMTP:		config = parseSMTPConfig(f)		hasTLS = true	case auth.PAM:		config = &pam.Config{			ServiceName: f.PAMServiceName,		}	case auth.GitHub:		config = &github.Config{			APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",			SkipVerify:  f.SkipVerify,		}		hasTLS = true	default:		c.Status(http.StatusBadRequest)		return	}	c.Data["HasTLS"] = hasTLS	if c.HasError() {		c.Success(AUTH_NEW)		return	}	source, err := database.Handle.LoginSources().Create(c.Req.Context(),		database.CreateLoginSourceOptions{			Type:      auth.Type(f.Type),			Name:      f.Name,			Activated: f.IsActive,			Default:   f.IsDefault,			Config:    config,		},	)	if err != nil {		if database.IsErrLoginSourceAlreadyExist(err) {			c.FormErr("Name")			c.RenderWithErr(c.Tr("admin.auths.login_source_exist", f.Name), AUTH_NEW, f)		} else {			c.Error(err, "create login source")		}		return	}	if source.IsDefault {		err = database.Handle.LoginSources().ResetNonDefault(c.Req.Context(), source)		if err != nil {			c.Error(err, "reset non-default login sources")			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(conf.Server.Subpath + "/admin/auths")}func EditAuthSource(c *context.Context) {	c.Title("admin.auths.edit")	c.PageIs("Admin")	c.PageIs("AdminAuthentications")	c.Data["SecurityProtocols"] = securityProtocols	c.Data["SMTPAuths"] = smtp.AuthTypes	source, err := database.Handle.LoginSources().GetByID(c.Req.Context(), c.ParamsInt64(":authid"))	if err != nil {		c.Error(err, "get login source by ID")		return	}	c.Data["Source"] = source	c.Data["HasTLS"] = source.Provider.HasTLS()	c.Success(AUTH_EDIT)}func EditAuthSourcePost(c *context.Context, f form.Authentication) {	c.Title("admin.auths.edit")	c.PageIs("Admin")	c.PageIs("AdminAuthentications")	c.Data["SMTPAuths"] = smtp.AuthTypes	source, err := database.Handle.LoginSources().GetByID(c.Req.Context(), c.ParamsInt64(":authid"))	if err != nil {		c.Error(err, "get login source by ID")		return	}	c.Data["Source"] = source	c.Data["HasTLS"] = source.Provider.HasTLS()	if c.HasError() {		c.Success(AUTH_EDIT)		return	}	var provider auth.Provider	switch auth.Type(f.Type) {	case auth.LDAP:		provider = ldap.NewProvider(false, parseLDAPConfig(f))	case auth.DLDAP:		provider = ldap.NewProvider(true, parseLDAPConfig(f))	case auth.SMTP:		provider = smtp.NewProvider(parseSMTPConfig(f))	case auth.PAM:		provider = pam.NewProvider(&pam.Config{			ServiceName: f.PAMServiceName,		})	case auth.GitHub:		provider = github.NewProvider(&github.Config{			APIEndpoint: strings.TrimSuffix(f.GitHubAPIEndpoint, "/") + "/",			SkipVerify:  f.SkipVerify,		})	default:		c.Status(http.StatusBadRequest)		return	}	source.Name = f.Name	source.IsActived = f.IsActive	source.IsDefault = f.IsDefault	source.Provider = provider	if err := database.Handle.LoginSources().Save(c.Req.Context(), source); err != nil {		c.Error(err, "update login source")		return	}	if source.IsDefault {		err = database.Handle.LoginSources().ResetNonDefault(c.Req.Context(), source)		if err != nil {			c.Error(err, "reset non-default login sources")			return		}	}	log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID)	c.Flash.Success(c.Tr("admin.auths.update_success"))	c.Redirect(conf.Server.Subpath + "/admin/auths/" + com.ToStr(f.ID))}func DeleteAuthSource(c *context.Context) {	id := c.ParamsInt64(":authid")	if err := database.Handle.LoginSources().DeleteByID(c.Req.Context(), id); err != nil {		if database.IsErrLoginSourceInUse(err) {			c.Flash.Error(c.Tr("admin.auths.still_in_used"))		} else {			c.Flash.Error(fmt.Sprintf("DeleteSource: %v", err))		}		c.JSONSuccess(map[string]any{			"redirect": conf.Server.Subpath + "/admin/auths/" + c.Params(":authid"),		})		return	}	log.Trace("Authentication deleted by admin(%s): %d", c.User.Name, id)	c.Flash.Success(c.Tr("admin.auths.deletion_success"))	c.JSONSuccess(map[string]any{		"redirect": conf.Server.Subpath + "/admin/auths",	})}
 |