Initially proposed by #2376 and fixes #3068 as well.tags/v0.9.99
@@ -3,7 +3,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra | |||
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | |||
##### Current tip version: 0.9.36 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
##### Current tip version: 0.9.37 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | |||
| Web | UI | Preview | | |||
|:-------------:|:-------:|:-------:| |
@@ -919,6 +919,7 @@ auths.enabled = Enabled | |||
auths.updated = Updated | |||
auths.auth_type = Authentication Type | |||
auths.auth_name = Authentication Name | |||
auths.security_protocol = Security Protocol | |||
auths.domain = Domain | |||
auths.host = Host | |||
auths.port = Port |
@@ -6,7 +6,7 @@ imports: | |||
subpackages: | |||
- memcache | |||
- name: github.com/codegangsta/cli | |||
version: e5bef42c62aa7d25aba4880dc02b7624f01e9e19 | |||
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e | |||
- name: github.com/go-macaron/binding | |||
version: bd00823a7e9aa00cb3b1738fde244573ba7cce2c | |||
- name: github.com/go-macaron/cache |
@@ -17,7 +17,7 @@ import ( | |||
"github.com/gogits/gogs/modules/setting" | |||
) | |||
const APP_VER = "0.9.36.0704" | |||
const APP_VER = "0.9.37.0708" | |||
func init() { | |||
runtime.GOMAXPROCS(runtime.NumCPU()) |
@@ -23,6 +23,11 @@ import ( | |||
"github.com/gogits/gogs/modules/log" | |||
) | |||
var ( | |||
ErrAuthenticationAlreadyExist = errors.New("Authentication already exist") | |||
ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users") | |||
) | |||
type LoginType int | |||
// Note: new type must be added at the end of list to maintain compatibility. | |||
@@ -35,11 +40,6 @@ const ( | |||
LOGIN_DLDAP // 5 | |||
) | |||
var ( | |||
ErrAuthenticationAlreadyExist = errors.New("Authentication already exist") | |||
ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users") | |||
) | |||
var LoginNames = map[LoginType]string{ | |||
LOGIN_LDAP: "LDAP (via BindDN)", | |||
LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind | |||
@@ -47,6 +47,12 @@ var LoginNames = map[LoginType]string{ | |||
LOGIN_PAM: "PAM", | |||
} | |||
var SecurityProtocolNames = map[ldap.SecurityProtocol]string{ | |||
ldap.SECURITY_PROTOCOL_UNENCRYPTED: "Unencrypted", | |||
ldap.SECURITY_PROTOCOL_LDAPS: "LDAPS", | |||
ldap.SECURITY_PROTOCOL_START_TLS: "StartTLS", | |||
} | |||
// Ensure structs implemented interface. | |||
var ( | |||
_ core.Conversion = &LDAPConfig{} | |||
@@ -66,6 +72,10 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) { | |||
return json.Marshal(cfg) | |||
} | |||
func (cfg *LDAPConfig) SecurityProtocolName() string { | |||
return SecurityProtocolNames[cfg.SecurityProtocol] | |||
} | |||
type SMTPConfig struct { | |||
Auth string | |||
Host string | |||
@@ -173,10 +183,16 @@ func (source *LoginSource) IsPAM() bool { | |||
return source.Type == LOGIN_PAM | |||
} | |||
func (source *LoginSource) HasTLS() bool { | |||
return ((source.IsLDAP() || source.IsDLDAP()) && | |||
source.LDAP().SecurityProtocol > ldap.SECURITY_PROTOCOL_UNENCRYPTED) || | |||
source.IsSMTP() | |||
} | |||
func (source *LoginSource) UseTLS() bool { | |||
switch source.Type { | |||
case LOGIN_LDAP, LOGIN_DLDAP: | |||
return source.LDAP().UseSSL | |||
return source.LDAP().SecurityProtocol != ldap.SECURITY_PROTOCOL_UNENCRYPTED | |||
case LOGIN_SMTP: | |||
return source.SMTP().TLS | |||
} |
@@ -59,14 +59,15 @@ type Version struct { | |||
// If you want to "retire" a migration, remove it from the top of the list and | |||
// update _MIN_VER_DB accordingly | |||
var migrations = []Migration{ | |||
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0 | |||
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3 | |||
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4 | |||
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4 | |||
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16 | |||
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20 | |||
NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5 | |||
NewMigration("convert date to unix timestamp", convertDateToUnix), // V11 -> V12:v0.9.2 | |||
NewMigration("fix locale file load panic", fixLocaleFileLoadPanic), // V4 -> V5:v0.6.0 | |||
NewMigration("trim action compare URL prefix", trimCommitActionAppUrlPrefix), // V5 -> V6:v0.6.3 | |||
NewMigration("generate issue-label from issue", issueToIssueLabel), // V6 -> V7:v0.6.4 | |||
NewMigration("refactor attachment table", attachmentRefactor), // V7 -> V8:v0.6.4 | |||
NewMigration("rename pull request fields", renamePullRequestFields), // V8 -> V9:v0.6.16 | |||
NewMigration("clean up migrate repo info", cleanUpMigrateRepoInfo), // V9 -> V10:v0.6.20 | |||
NewMigration("generate rands and salt for organizations", generateOrgRandsAndSalt), // V10 -> V11:v0.8.5 | |||
NewMigration("convert date to unix timestamp", convertDateToUnix), // V11 -> V12:v0.9.2 | |||
NewMigration("convert LDAP UseSSL option to SecurityProtocol", ldapUseSSLToSecurityProtocol), // V12 -> V13:v0.9.37 | |||
} | |||
// Migrate database to current version | |||
@@ -580,6 +581,7 @@ type TWebhook struct { | |||
func (t *TWebhook) TableName() string { return "webhook" } | |||
func convertDateToUnix(x *xorm.Engine) (err error) { | |||
log.Info("This migration could take up to minutes, please be patient.") | |||
type Bean struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
Created time.Time |
@@ -0,0 +1,52 @@ | |||
// Copyright 2016 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 migrations | |||
import ( | |||
"encoding/json" | |||
"fmt" | |||
"strings" | |||
"github.com/Unknwon/com" | |||
"github.com/go-xorm/xorm" | |||
) | |||
func ldapUseSSLToSecurityProtocol(x *xorm.Engine) error { | |||
results, err := x.Query("SELECT `id`,`cfg` FROM `login_source` WHERE `type` = 2 OR `type` = 5") | |||
if err != nil { | |||
if strings.Contains(err.Error(), "no such column") { | |||
return nil | |||
} | |||
return fmt.Errorf("select LDAP login sources: %v", err) | |||
} | |||
sess := x.NewSession() | |||
defer sessionRelease(sess) | |||
if err = sess.Begin(); err != nil { | |||
return err | |||
} | |||
for _, result := range results { | |||
cfg := map[string]interface{}{} | |||
if err = json.Unmarshal(result["cfg"], &cfg); err != nil { | |||
return fmt.Errorf("decode JSON config: %v", err) | |||
} | |||
if com.ToStr(cfg["UseSSL"]) == "true" { | |||
cfg["SecurityProtocol"] = 1 // LDAPS | |||
} | |||
delete(cfg, "UseSSL") | |||
data, err := json.Marshal(&cfg) | |||
if err != nil { | |||
return fmt.Errorf("encode JSON config: %v", err) | |||
} | |||
if _, err = sess.Exec("UPDATE `login_source` SET `cfg`=? WHERE `id`=?", | |||
string(data), com.StrTo(result["id"]).MustInt64()); err != nil { | |||
return fmt.Errorf("update config column: %v", err) | |||
} | |||
} | |||
return sess.Commit() | |||
} |
@@ -31,6 +31,7 @@ type AuthenticationForm struct { | |||
SMTPHost string | |||
SMTPPort int | |||
AllowedDomains string | |||
SecurityProtocol int `binding:"Range(0,2)"` | |||
TLS bool | |||
SkipVerify bool | |||
PAMServiceName string |
@@ -16,12 +16,21 @@ import ( | |||
"github.com/gogits/gogs/modules/log" | |||
) | |||
type SecurityProtocol int | |||
// Note: new type must be added at the end of list to maintain compatibility. | |||
const ( | |||
SECURITY_PROTOCOL_UNENCRYPTED SecurityProtocol = iota | |||
SECURITY_PROTOCOL_LDAPS | |||
SECURITY_PROTOCOL_START_TLS | |||
) | |||
// Basic LDAP authentication service | |||
type Source struct { | |||
Name string // canonical name (ie. corporate.ad) | |||
Host string // LDAP host | |||
Port int // port number | |||
UseSSL bool // Use SSL | |||
SecurityProtocol SecurityProtocol | |||
SkipVerify bool | |||
BindDN string // DN to bind with | |||
BindPassword string // Bind DN password | |||
@@ -102,9 +111,46 @@ func (ls *Source) findUserDN(l *ldap.Conn, name string) (string, bool) { | |||
return userDN, true | |||
} | |||
func dial(ls *Source) (*ldap.Conn, error) { | |||
log.Trace("Dialing LDAP with security protocol (%v) without verifying: %v", ls.SecurityProtocol, ls.SkipVerify) | |||
tlsCfg := &tls.Config{ | |||
ServerName: ls.Host, | |||
InsecureSkipVerify: ls.SkipVerify, | |||
} | |||
if ls.SecurityProtocol == SECURITY_PROTOCOL_LDAPS { | |||
return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), tlsCfg) | |||
} | |||
conn, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port)) | |||
if err != nil { | |||
return nil, fmt.Errorf("Dial: %v", err) | |||
} | |||
if ls.SecurityProtocol == SECURITY_PROTOCOL_START_TLS { | |||
if err = conn.StartTLS(tlsCfg); err != nil { | |||
conn.Close() | |||
return nil, fmt.Errorf("StartTLS: %v", err) | |||
} | |||
} | |||
return conn, nil | |||
} | |||
func bindUser(l *ldap.Conn, userDN, passwd string) error { | |||
log.Trace("Binding with userDN: %s", userDN) | |||
err := l.Bind(userDN, passwd) | |||
if err != nil { | |||
log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err) | |||
return err | |||
} | |||
log.Trace("Bound successfully with userDN: %s", userDN) | |||
return err | |||
} | |||
// searchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter | |||
func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, string, string, string, bool, bool) { | |||
l, err := ldapDial(ls) | |||
l, err := dial(ls) | |||
if err != nil { | |||
log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err) | |||
ls.Enabled = false | |||
@@ -197,26 +243,3 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str | |||
return username_attr, name_attr, sn_attr, mail_attr, admin_attr, true | |||
} | |||
func bindUser(l *ldap.Conn, userDN, passwd string) error { | |||
log.Trace("Binding with userDN: %s", userDN) | |||
err := l.Bind(userDN, passwd) | |||
if err != nil { | |||
log.Debug("LDAP auth. failed for %s, reason: %v", userDN, err) | |||
return err | |||
} | |||
log.Trace("Bound successfully with userDN: %s", userDN) | |||
return err | |||
} | |||
func ldapDial(ls *Source) (*ldap.Conn, error) { | |||
if ls.UseSSL { | |||
log.Debug("Using TLS for LDAP without verifying: %v", ls.SkipVerify) | |||
return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), &tls.Config{ | |||
ServerName: ls.Host, | |||
InsecureSkipVerify: ls.SkipVerify, | |||
}) | |||
} else { | |||
return ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port)) | |||
} | |||
} |
@@ -612,6 +612,13 @@ function initAdmin() { | |||
}); | |||
} | |||
function onSecurityProtocolChange() { | |||
if ($('#security_protocol').val() > 0) { | |||
$('.has-tls').show(); | |||
} else { | |||
$('.has-tls').hide(); | |||
} | |||
} | |||
// New authentication | |||
if ($('.admin.new.authentication').length > 0) { | |||
@@ -620,6 +627,7 @@ function initAdmin() { | |||
$('.dldap').hide(); | |||
$('.smtp').hide(); | |||
$('.pam').hide(); | |||
$('.has-tls').hide(); | |||
var auth_type = $(this).val(); | |||
switch (auth_type) { | |||
@@ -628,6 +636,7 @@ function initAdmin() { | |||
break; | |||
case '3': // SMTP | |||
$('.smtp').show(); | |||
$('.has-tls').show(); | |||
break; | |||
case '4': // PAM | |||
$('.pam').show(); | |||
@@ -636,7 +645,19 @@ function initAdmin() { | |||
$('.dldap').show(); | |||
break; | |||
} | |||
if (auth_type == '2' || auth_type == '5') { | |||
onSecurityProtocolChange() | |||
} | |||
}); | |||
$('#security_protocol').change(onSecurityProtocolChange) | |||
} | |||
// Edit authentication | |||
if ($('.admin.edit.authentication').length > 0) { | |||
var auth_type = $('#auth_type').val(); | |||
if (auth_type == '2' || auth_type == '5') { | |||
$('#security_protocol').change(onSecurityProtocolChange); | |||
} | |||
} | |||
// Notice |
@@ -41,17 +41,24 @@ func Authentications(ctx *context.Context) { | |||
ctx.HTML(200, AUTHS) | |||
} | |||
type AuthSource struct { | |||
type dropdownItem struct { | |||
Name string | |||
Type models.LoginType | |||
Type interface{} | |||
} | |||
var authSources = []AuthSource{ | |||
{models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP}, | |||
{models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP}, | |||
{models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP}, | |||
{models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM}, | |||
} | |||
var ( | |||
authSources = []dropdownItem{ | |||
{models.LoginNames[models.LOGIN_LDAP], models.LOGIN_LDAP}, | |||
{models.LoginNames[models.LOGIN_DLDAP], models.LOGIN_DLDAP}, | |||
{models.LoginNames[models.LOGIN_SMTP], models.LOGIN_SMTP}, | |||
{models.LoginNames[models.LOGIN_PAM], models.LOGIN_PAM}, | |||
} | |||
securityProtocols = []dropdownItem{ | |||
{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED], ldap.SECURITY_PROTOCOL_UNENCRYPTED}, | |||
{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_LDAPS], ldap.SECURITY_PROTOCOL_LDAPS}, | |||
{models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_START_TLS], ldap.SECURITY_PROTOCOL_START_TLS}, | |||
} | |||
) | |||
func NewAuthSource(ctx *context.Context) { | |||
ctx.Data["Title"] = ctx.Tr("admin.auths.new") | |||
@@ -59,10 +66,12 @@ func NewAuthSource(ctx *context.Context) { | |||
ctx.Data["PageIsAdminAuthentications"] = true | |||
ctx.Data["type"] = models.LOGIN_LDAP | |||
ctx.Data["CurTypeName"] = models.LoginNames[models.LOGIN_LDAP] | |||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LOGIN_LDAP] | |||
ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED] | |||
ctx.Data["smtp_auth"] = "PLAIN" | |||
ctx.Data["is_active"] = true | |||
ctx.Data["AuthSources"] = authSources | |||
ctx.Data["SecurityProtocols"] = securityProtocols | |||
ctx.Data["SMTPAuths"] = models.SMTPAuths | |||
ctx.HTML(200, AUTH_NEW) | |||
} | |||
@@ -73,7 +82,7 @@ func parseLDAPConfig(form auth.AuthenticationForm) *models.LDAPConfig { | |||
Name: form.Name, | |||
Host: form.Host, | |||
Port: form.Port, | |||
UseSSL: form.TLS, | |||
SecurityProtocol: ldap.SecurityProtocol(form.SecurityProtocol), | |||
SkipVerify: form.SkipVerify, | |||
BindDN: form.BindDN, | |||
UserDN: form.UserDN, | |||
@@ -107,21 +116,21 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { | |||
ctx.Data["PageIsAdmin"] = true | |||
ctx.Data["PageIsAdminAuthentications"] = true | |||
ctx.Data["CurTypeName"] = models.LoginNames[models.LoginType(form.Type)] | |||
ctx.Data["CurrentTypeName"] = models.LoginNames[models.LoginType(form.Type)] | |||
ctx.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SecurityProtocol(form.SecurityProtocol)] | |||
ctx.Data["AuthSources"] = authSources | |||
ctx.Data["SecurityProtocols"] = securityProtocols | |||
ctx.Data["SMTPAuths"] = models.SMTPAuths | |||
if ctx.HasError() { | |||
ctx.HTML(200, AUTH_NEW) | |||
return | |||
} | |||
hasTLS := false | |||
var config core.Conversion | |||
switch models.LoginType(form.Type) { | |||
case models.LOGIN_LDAP, models.LOGIN_DLDAP: | |||
config = parseLDAPConfig(form) | |||
hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED | |||
case models.LOGIN_SMTP: | |||
config = parseSMTPConfig(form) | |||
hasTLS = true | |||
case models.LOGIN_PAM: | |||
config = &models.PAMConfig{ | |||
ServiceName: form.PAMServiceName, | |||
@@ -130,6 +139,12 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { | |||
ctx.Error(400) | |||
return | |||
} | |||
ctx.Data["HasTLS"] = hasTLS | |||
if ctx.HasError() { | |||
ctx.HTML(200, AUTH_NEW) | |||
return | |||
} | |||
if err := models.CreateSource(&models.LoginSource{ | |||
Type: models.LoginType(form.Type), | |||
@@ -152,6 +167,7 @@ func EditAuthSource(ctx *context.Context) { | |||
ctx.Data["PageIsAdmin"] = true | |||
ctx.Data["PageIsAdminAuthentications"] = true | |||
ctx.Data["SecurityProtocols"] = securityProtocols | |||
ctx.Data["SMTPAuths"] = models.SMTPAuths | |||
source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid")) | |||
@@ -160,6 +176,8 @@ func EditAuthSource(ctx *context.Context) { | |||
return | |||
} | |||
ctx.Data["Source"] = source | |||
ctx.Data["HasTLS"] = source.HasTLS() | |||
ctx.HTML(200, AUTH_EDIT) | |||
} | |||
@@ -176,6 +194,7 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) { | |||
return | |||
} | |||
ctx.Data["Source"] = source | |||
ctx.Data["HasTLS"] = source.HasTLS() | |||
if ctx.HasError() { | |||
ctx.HTML(200, AUTH_EDIT) |
@@ -1 +1 @@ | |||
0.9.36.0704 | |||
0.9.37.0708 |
@@ -14,7 +14,7 @@ | |||
<input type="hidden" name="id" value="{{.Source.ID}}"> | |||
<div class="inline field"> | |||
<label>{{$.i18n.Tr "admin.auths.auth_type"}}</label> | |||
<input type="hidden" name="type" value="{{.Source.Type}}"> | |||
<input type="hidden" id="auth_type" name="type" value="{{.Source.Type}}"> | |||
<span>{{.Source.TypeName}}</span> | |||
</div> | |||
<div class="required inline field {{if .Err_Name}}error{{end}}"> | |||
@@ -25,6 +25,19 @@ | |||
<!-- LDAP and DLDAP --> | |||
{{if or .Source.IsLDAP .Source.IsDLDAP}} | |||
{{ $cfg:=.Source.LDAP }} | |||
<div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}"> | |||
<label>{{.i18n.Tr "admin.auths.security_protocol"}}</label> | |||
<div class="ui selection security-protocol dropdown"> | |||
<input type="hidden" id="security_protocol" name="security_protocol" value="{{$cfg.SecurityProtocol}}"> | |||
<div class="text">{{$cfg.SecurityProtocolName}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
{{range .SecurityProtocols}} | |||
<div class="item" data-value="{{.Type}}">{{.Name}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="required field"> | |||
<label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | |||
<input id="host" name="host" value="{{$cfg.Host}}" placeholder="e.g. mydomain.com" required> | |||
@@ -129,13 +142,13 @@ | |||
</div> | |||
{{end}} | |||
<div class="inline field {{if not (or (or .Source.IsLDAP .Source.IsDLDAP) .Source.IsSMTP)}}hide{{end}}"> | |||
<div class="inline field {{if not .Source.IsSMTP}}hide{{end}}"> | |||
<div class="ui checkbox"> | |||
<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | |||
<input name="tls" type="checkbox" {{if .Source.UseTLS}}checked{{end}}> | |||
</div> | |||
</div> | |||
<div class="inline field {{if not (or (or .Source.IsLDAP .Source.IsDLDAP) .Source.IsSMTP)}}hide{{end}}"> | |||
<div class="has-tls inline field {{if not .HasTLS}}hide{{end}}"> | |||
<div class="ui checkbox"> | |||
<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | |||
<input name="skip_verify" type="checkbox" {{if .Source.SkipVerify}}checked{{end}}> |
@@ -16,7 +16,7 @@ | |||
<label>{{.i18n.Tr "admin.auths.auth_type"}}</label> | |||
<div class="ui selection type dropdown"> | |||
<input type="hidden" id="auth_type" name="type" value="{{.type}}"> | |||
<div class="text">{{.CurTypeName}}</div> | |||
<div class="text">{{.CurrentTypeName}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
{{range .AuthSources}} | |||
@@ -32,6 +32,19 @@ | |||
<!-- LDAP and DLDAP --> | |||
<div class="ldap dldap field {{if not (or (eq .type 2) (eq .type 5))}}hide{{end}}"> | |||
<div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}"> | |||
<label>{{.i18n.Tr "admin.auths.security_protocol"}}</label> | |||
<div class="ui selection security-protocol dropdown"> | |||
<input type="hidden" id="security_protocol" name="security_protocol" value="{{.security_protocol}}"> | |||
<div class="text">{{.CurrentSecurityProtocol}}</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
{{range .SecurityProtocols}} | |||
<div class="item" data-value="{{.Type}}">{{.Name}}</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="required field"> | |||
<label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | |||
<input id="host" name="host" value="{{.host}}" placeholder="e.g. mydomain.com"> | |||
@@ -126,13 +139,13 @@ | |||
<input name="attributes_in_bind" type="checkbox" {{if .attributes_in_bind}}checked{{end}}> | |||
</div> | |||
</div> | |||
<div class="ldap dldap smtp inline field {{if not (or (or (eq .type 2) (eq .type 5)) (eq .type 3))}}hide{{end}}"> | |||
<div class="smtp inline field {{if not (eq .type 3)}}hide{{end}}"> | |||
<div class="ui checkbox"> | |||
<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | |||
<input name="tls" type="checkbox" {{if .tls}}checked{{end}}> | |||
</div> | |||
</div> | |||
<div class="ldap dldap smtp inline field {{if not (or (or (eq .type 2) (eq .type 5)) (eq .type 3))}}hide{{end}}"> | |||
<div class="has-tls inline field {{if not .HasTLS}}hide{{end}}"> | |||
<div class="ui checkbox"> | |||
<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | |||
<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> |