Initially proposed by #2376 and fixes #3068 as well.tags/v0.9.99
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true) | ![](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 | | | Web | UI | Preview | | ||||
|:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| |
auths.updated = Updated | auths.updated = Updated | ||||
auths.auth_type = Authentication Type | auths.auth_type = Authentication Type | ||||
auths.auth_name = Authentication Name | auths.auth_name = Authentication Name | ||||
auths.security_protocol = Security Protocol | |||||
auths.domain = Domain | auths.domain = Domain | ||||
auths.host = Host | auths.host = Host | ||||
auths.port = Port | auths.port = Port |
subpackages: | subpackages: | ||||
- memcache | - memcache | ||||
- name: github.com/codegangsta/cli | - name: github.com/codegangsta/cli | ||||
version: e5bef42c62aa7d25aba4880dc02b7624f01e9e19 | |||||
version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e | |||||
- name: github.com/go-macaron/binding | - name: github.com/go-macaron/binding | ||||
version: bd00823a7e9aa00cb3b1738fde244573ba7cce2c | version: bd00823a7e9aa00cb3b1738fde244573ba7cce2c | ||||
- name: github.com/go-macaron/cache | - name: github.com/go-macaron/cache |
"github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
) | ) | ||||
const APP_VER = "0.9.36.0704" | |||||
const APP_VER = "0.9.37.0708" | |||||
func init() { | func init() { | ||||
runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) |
"github.com/gogits/gogs/modules/log" | "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 | type LoginType int | ||||
// Note: new type must be added at the end of list to maintain compatibility. | // Note: new type must be added at the end of list to maintain compatibility. | ||||
LOGIN_DLDAP // 5 | 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{ | var LoginNames = map[LoginType]string{ | ||||
LOGIN_LDAP: "LDAP (via BindDN)", | LOGIN_LDAP: "LDAP (via BindDN)", | ||||
LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind | LOGIN_DLDAP: "LDAP (simple auth)", // Via direct bind | ||||
LOGIN_PAM: "PAM", | 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. | // Ensure structs implemented interface. | ||||
var ( | var ( | ||||
_ core.Conversion = &LDAPConfig{} | _ core.Conversion = &LDAPConfig{} | ||||
return json.Marshal(cfg) | return json.Marshal(cfg) | ||||
} | } | ||||
func (cfg *LDAPConfig) SecurityProtocolName() string { | |||||
return SecurityProtocolNames[cfg.SecurityProtocol] | |||||
} | |||||
type SMTPConfig struct { | type SMTPConfig struct { | ||||
Auth string | Auth string | ||||
Host string | Host string | ||||
return source.Type == LOGIN_PAM | 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 { | func (source *LoginSource) UseTLS() bool { | ||||
switch source.Type { | switch source.Type { | ||||
case LOGIN_LDAP, LOGIN_DLDAP: | case LOGIN_LDAP, LOGIN_DLDAP: | ||||
return source.LDAP().UseSSL | |||||
return source.LDAP().SecurityProtocol != ldap.SECURITY_PROTOCOL_UNENCRYPTED | |||||
case LOGIN_SMTP: | case LOGIN_SMTP: | ||||
return source.SMTP().TLS | return source.SMTP().TLS | ||||
} | } |
// If you want to "retire" a migration, remove it from the top of the list and | // If you want to "retire" a migration, remove it from the top of the list and | ||||
// update _MIN_VER_DB accordingly | // update _MIN_VER_DB accordingly | ||||
var migrations = []Migration{ | 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 | // Migrate database to current version | ||||
func (t *TWebhook) TableName() string { return "webhook" } | func (t *TWebhook) TableName() string { return "webhook" } | ||||
func convertDateToUnix(x *xorm.Engine) (err error) { | func convertDateToUnix(x *xorm.Engine) (err error) { | ||||
log.Info("This migration could take up to minutes, please be patient.") | |||||
type Bean struct { | type Bean struct { | ||||
ID int64 `xorm:"pk autoincr"` | ID int64 `xorm:"pk autoincr"` | ||||
Created time.Time | Created time.Time |
// 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() | |||||
} |
SMTPHost string | SMTPHost string | ||||
SMTPPort int | SMTPPort int | ||||
AllowedDomains string | AllowedDomains string | ||||
SecurityProtocol int `binding:"Range(0,2)"` | |||||
TLS bool | TLS bool | ||||
SkipVerify bool | SkipVerify bool | ||||
PAMServiceName string | PAMServiceName string |
"github.com/gogits/gogs/modules/log" | "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 | // Basic LDAP authentication service | ||||
type Source struct { | type Source struct { | ||||
Name string // canonical name (ie. corporate.ad) | Name string // canonical name (ie. corporate.ad) | ||||
Host string // LDAP host | Host string // LDAP host | ||||
Port int // port number | Port int // port number | ||||
UseSSL bool // Use SSL | |||||
SecurityProtocol SecurityProtocol | |||||
SkipVerify bool | SkipVerify bool | ||||
BindDN string // DN to bind with | BindDN string // DN to bind with | ||||
BindPassword string // Bind DN password | BindPassword string // Bind DN password | ||||
return userDN, true | 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 | // 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) { | 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 { | if err != nil { | ||||
log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err) | log.Error(4, "LDAP Connect error, %s:%v", ls.Host, err) | ||||
ls.Enabled = false | ls.Enabled = false | ||||
return username_attr, name_attr, sn_attr, mail_attr, admin_attr, true | 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)) | |||||
} | |||||
} |
}); | }); | ||||
} | } | ||||
function onSecurityProtocolChange() { | |||||
if ($('#security_protocol').val() > 0) { | |||||
$('.has-tls').show(); | |||||
} else { | |||||
$('.has-tls').hide(); | |||||
} | |||||
} | |||||
// New authentication | // New authentication | ||||
if ($('.admin.new.authentication').length > 0) { | if ($('.admin.new.authentication').length > 0) { | ||||
$('.dldap').hide(); | $('.dldap').hide(); | ||||
$('.smtp').hide(); | $('.smtp').hide(); | ||||
$('.pam').hide(); | $('.pam').hide(); | ||||
$('.has-tls').hide(); | |||||
var auth_type = $(this).val(); | var auth_type = $(this).val(); | ||||
switch (auth_type) { | switch (auth_type) { | ||||
break; | break; | ||||
case '3': // SMTP | case '3': // SMTP | ||||
$('.smtp').show(); | $('.smtp').show(); | ||||
$('.has-tls').show(); | |||||
break; | break; | ||||
case '4': // PAM | case '4': // PAM | ||||
$('.pam').show(); | $('.pam').show(); | ||||
$('.dldap').show(); | $('.dldap').show(); | ||||
break; | 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 | // Notice |
ctx.HTML(200, AUTHS) | ctx.HTML(200, AUTHS) | ||||
} | } | ||||
type AuthSource struct { | |||||
type dropdownItem struct { | |||||
Name string | 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) { | func NewAuthSource(ctx *context.Context) { | ||||
ctx.Data["Title"] = ctx.Tr("admin.auths.new") | ctx.Data["Title"] = ctx.Tr("admin.auths.new") | ||||
ctx.Data["PageIsAdminAuthentications"] = true | ctx.Data["PageIsAdminAuthentications"] = true | ||||
ctx.Data["type"] = models.LOGIN_LDAP | 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["smtp_auth"] = "PLAIN" | ||||
ctx.Data["is_active"] = true | ctx.Data["is_active"] = true | ||||
ctx.Data["AuthSources"] = authSources | ctx.Data["AuthSources"] = authSources | ||||
ctx.Data["SecurityProtocols"] = securityProtocols | |||||
ctx.Data["SMTPAuths"] = models.SMTPAuths | ctx.Data["SMTPAuths"] = models.SMTPAuths | ||||
ctx.HTML(200, AUTH_NEW) | ctx.HTML(200, AUTH_NEW) | ||||
} | } | ||||
Name: form.Name, | Name: form.Name, | ||||
Host: form.Host, | Host: form.Host, | ||||
Port: form.Port, | Port: form.Port, | ||||
UseSSL: form.TLS, | |||||
SecurityProtocol: ldap.SecurityProtocol(form.SecurityProtocol), | |||||
SkipVerify: form.SkipVerify, | SkipVerify: form.SkipVerify, | ||||
BindDN: form.BindDN, | BindDN: form.BindDN, | ||||
UserDN: form.UserDN, | UserDN: form.UserDN, | ||||
ctx.Data["PageIsAdmin"] = true | ctx.Data["PageIsAdmin"] = true | ||||
ctx.Data["PageIsAdminAuthentications"] = 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["AuthSources"] = authSources | ||||
ctx.Data["SecurityProtocols"] = securityProtocols | |||||
ctx.Data["SMTPAuths"] = models.SMTPAuths | ctx.Data["SMTPAuths"] = models.SMTPAuths | ||||
if ctx.HasError() { | |||||
ctx.HTML(200, AUTH_NEW) | |||||
return | |||||
} | |||||
hasTLS := false | |||||
var config core.Conversion | var config core.Conversion | ||||
switch models.LoginType(form.Type) { | switch models.LoginType(form.Type) { | ||||
case models.LOGIN_LDAP, models.LOGIN_DLDAP: | case models.LOGIN_LDAP, models.LOGIN_DLDAP: | ||||
config = parseLDAPConfig(form) | config = parseLDAPConfig(form) | ||||
hasTLS = ldap.SecurityProtocol(form.SecurityProtocol) > ldap.SECURITY_PROTOCOL_UNENCRYPTED | |||||
case models.LOGIN_SMTP: | case models.LOGIN_SMTP: | ||||
config = parseSMTPConfig(form) | config = parseSMTPConfig(form) | ||||
hasTLS = true | |||||
case models.LOGIN_PAM: | case models.LOGIN_PAM: | ||||
config = &models.PAMConfig{ | config = &models.PAMConfig{ | ||||
ServiceName: form.PAMServiceName, | ServiceName: form.PAMServiceName, | ||||
ctx.Error(400) | ctx.Error(400) | ||||
return | return | ||||
} | } | ||||
ctx.Data["HasTLS"] = hasTLS | |||||
if ctx.HasError() { | |||||
ctx.HTML(200, AUTH_NEW) | |||||
return | |||||
} | |||||
if err := models.CreateSource(&models.LoginSource{ | if err := models.CreateSource(&models.LoginSource{ | ||||
Type: models.LoginType(form.Type), | Type: models.LoginType(form.Type), | ||||
ctx.Data["PageIsAdmin"] = true | ctx.Data["PageIsAdmin"] = true | ||||
ctx.Data["PageIsAdminAuthentications"] = true | ctx.Data["PageIsAdminAuthentications"] = true | ||||
ctx.Data["SecurityProtocols"] = securityProtocols | |||||
ctx.Data["SMTPAuths"] = models.SMTPAuths | ctx.Data["SMTPAuths"] = models.SMTPAuths | ||||
source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid")) | source, err := models.GetLoginSourceByID(ctx.ParamsInt64(":authid")) | ||||
return | return | ||||
} | } | ||||
ctx.Data["Source"] = source | ctx.Data["Source"] = source | ||||
ctx.Data["HasTLS"] = source.HasTLS() | |||||
ctx.HTML(200, AUTH_EDIT) | ctx.HTML(200, AUTH_EDIT) | ||||
} | } | ||||
return | return | ||||
} | } | ||||
ctx.Data["Source"] = source | ctx.Data["Source"] = source | ||||
ctx.Data["HasTLS"] = source.HasTLS() | |||||
if ctx.HasError() { | if ctx.HasError() { | ||||
ctx.HTML(200, AUTH_EDIT) | ctx.HTML(200, AUTH_EDIT) |
0.9.36.0704 | |||||
0.9.37.0708 |
<input type="hidden" name="id" value="{{.Source.ID}}"> | <input type="hidden" name="id" value="{{.Source.ID}}"> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{$.i18n.Tr "admin.auths.auth_type"}}</label> | <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> | <span>{{.Source.TypeName}}</span> | ||||
</div> | </div> | ||||
<div class="required inline field {{if .Err_Name}}error{{end}}"> | <div class="required inline field {{if .Err_Name}}error{{end}}"> | ||||
<!-- LDAP and DLDAP --> | <!-- LDAP and DLDAP --> | ||||
{{if or .Source.IsLDAP .Source.IsDLDAP}} | {{if or .Source.IsLDAP .Source.IsDLDAP}} | ||||
{{ $cfg:=.Source.LDAP }} | {{ $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"> | <div class="required field"> | ||||
<label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | <label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | ||||
<input id="host" name="host" value="{{$cfg.Host}}" placeholder="e.g. mydomain.com" required> | <input id="host" name="host" value="{{$cfg.Host}}" placeholder="e.g. mydomain.com" required> | ||||
</div> | </div> | ||||
{{end}} | {{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"> | <div class="ui checkbox"> | ||||
<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | <label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | ||||
<input name="tls" type="checkbox" {{if .Source.UseTLS}}checked{{end}}> | <input name="tls" type="checkbox" {{if .Source.UseTLS}}checked{{end}}> | ||||
</div> | </div> | ||||
</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"> | <div class="ui checkbox"> | ||||
<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | <label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | ||||
<input name="skip_verify" type="checkbox" {{if .Source.SkipVerify}}checked{{end}}> | <input name="skip_verify" type="checkbox" {{if .Source.SkipVerify}}checked{{end}}> |
<label>{{.i18n.Tr "admin.auths.auth_type"}}</label> | <label>{{.i18n.Tr "admin.auths.auth_type"}}</label> | ||||
<div class="ui selection type dropdown"> | <div class="ui selection type dropdown"> | ||||
<input type="hidden" id="auth_type" name="type" value="{{.type}}"> | <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> | <i class="dropdown icon"></i> | ||||
<div class="menu"> | <div class="menu"> | ||||
{{range .AuthSources}} | {{range .AuthSources}} | ||||
<!-- LDAP and DLDAP --> | <!-- LDAP and DLDAP --> | ||||
<div class="ldap dldap field {{if not (or (eq .type 2) (eq .type 5))}}hide{{end}}"> | <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"> | <div class="required field"> | ||||
<label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | <label for="host">{{.i18n.Tr "admin.auths.host"}}</label> | ||||
<input id="host" name="host" value="{{.host}}" placeholder="e.g. mydomain.com"> | <input id="host" name="host" value="{{.host}}" placeholder="e.g. mydomain.com"> | ||||
<input name="attributes_in_bind" type="checkbox" {{if .attributes_in_bind}}checked{{end}}> | <input name="attributes_in_bind" type="checkbox" {{if .attributes_in_bind}}checked{{end}}> | ||||
</div> | </div> | ||||
</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"> | <div class="ui checkbox"> | ||||
<label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | <label><strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong></label> | ||||
<input name="tls" type="checkbox" {{if .tls}}checked{{end}}> | <input name="tls" type="checkbox" {{if .tls}}checked{{end}}> | ||||
</div> | </div> | ||||
</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"> | <div class="ui checkbox"> | ||||
<label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | <label><strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong></label> | ||||
<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> | <input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> |