@@ -794,6 +794,7 @@ auths.smtp_auth = SMTP Authorization Type | |||
auths.smtphost = SMTP Host | |||
auths.smtpport = SMTP Port | |||
auths.enable_tls = Enable TLS Encryption | |||
auths.skip_tls_verify = Skip TLS Verify | |||
auths.pam_service_name = PAM Service Name | |||
auths.enable_auto_register = Enable Auto Registration | |||
auths.tips = Tips |
@@ -63,10 +63,11 @@ func (cfg *LDAPConfig) ToDB() ([]byte, error) { | |||
} | |||
type SMTPConfig struct { | |||
Auth string | |||
Host string | |||
Port int | |||
TLS bool | |||
Auth string | |||
Host string | |||
Port int | |||
TLS bool | |||
SkipVerify bool | |||
} | |||
func (cfg *SMTPConfig) FromDB(bs []byte) error { | |||
@@ -90,7 +91,7 @@ func (cfg *PAMConfig) ToDB() ([]byte, error) { | |||
} | |||
type LoginSource struct { | |||
Id int64 | |||
ID int64 `xorm:"pk autoincr"` | |||
Type LoginType | |||
Name string `xorm:"UNIQUE"` | |||
IsActived bool `xorm:"NOT NULL DEFAULT false"` | |||
@@ -100,6 +101,20 @@ type LoginSource struct { | |||
Updated time.Time `xorm:"UPDATED"` | |||
} | |||
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { | |||
switch colName { | |||
case "type": | |||
switch LoginType((*val).(int64)) { | |||
case LDAP: | |||
source.Cfg = new(LDAPConfig) | |||
case SMTP: | |||
source.Cfg = new(SMTPConfig) | |||
case PAM: | |||
source.Cfg = new(PAMConfig) | |||
} | |||
} | |||
} | |||
func (source *LoginSource) TypeString() string { | |||
return LoginTypes[source.Type] | |||
} | |||
@@ -116,32 +131,17 @@ func (source *LoginSource) PAM() *PAMConfig { | |||
return source.Cfg.(*PAMConfig) | |||
} | |||
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { | |||
if colName == "type" { | |||
ty := (*val).(int64) | |||
switch LoginType(ty) { | |||
case LDAP: | |||
source.Cfg = new(LDAPConfig) | |||
case SMTP: | |||
source.Cfg = new(SMTPConfig) | |||
case PAM: | |||
source.Cfg = new(PAMConfig) | |||
} | |||
} | |||
} | |||
func CreateSource(source *LoginSource) error { | |||
_, err := x.Insert(source) | |||
return err | |||
} | |||
func GetAuths() ([]*LoginSource, error) { | |||
var auths = make([]*LoginSource, 0, 5) | |||
err := x.Find(&auths) | |||
return auths, err | |||
auths := make([]*LoginSource, 0, 5) | |||
return auths, x.Find(&auths) | |||
} | |||
func GetLoginSourceById(id int64) (*LoginSource, error) { | |||
func GetLoginSourceByID(id int64) (*LoginSource, error) { | |||
source := new(LoginSource) | |||
has, err := x.Id(id).Get(source) | |||
if err != nil { | |||
@@ -153,19 +153,19 @@ func GetLoginSourceById(id int64) (*LoginSource, error) { | |||
} | |||
func UpdateSource(source *LoginSource) error { | |||
_, err := x.Id(source.Id).AllCols().Update(source) | |||
_, err := x.Id(source.ID).AllCols().Update(source) | |||
return err | |||
} | |||
func DelLoginSource(source *LoginSource) error { | |||
cnt, err := x.Count(&User{LoginSource: source.Id}) | |||
cnt, err := x.Count(&User{LoginSource: source.ID}) | |||
if err != nil { | |||
return err | |||
} | |||
if cnt > 0 { | |||
return ErrAuthenticationUserUsed | |||
} | |||
_, err = x.Id(source.Id).Delete(&LoginSource{}) | |||
_, err = x.Id(source.ID).Delete(&LoginSource{}) | |||
return err | |||
} | |||
@@ -206,21 +206,21 @@ func UserSignIn(uname, passwd string) (*User, error) { | |||
for _, source := range sources { | |||
if source.Type == LDAP { | |||
u, err := LoginUserLdapSource(nil, uname, passwd, | |||
source.Id, source.Cfg.(*LDAPConfig), true) | |||
source.ID, source.Cfg.(*LDAPConfig), true) | |||
if err == nil { | |||
return u, nil | |||
} | |||
log.Warn("Fail to login(%s) by LDAP(%s): %v", uname, source.Name, err) | |||
} else if source.Type == SMTP { | |||
u, err := LoginUserSMTPSource(nil, uname, passwd, | |||
source.Id, source.Cfg.(*SMTPConfig), true) | |||
source.ID, source.Cfg.(*SMTPConfig), true) | |||
if err == nil { | |||
return u, nil | |||
} | |||
log.Warn("Fail to login(%s) by SMTP(%s): %v", uname, source.Name, err) | |||
} else if source.Type == PAM { | |||
u, err := LoginUserPAMSource(nil, uname, passwd, | |||
source.Id, source.Cfg.(*PAMConfig), true) | |||
source.ID, source.Cfg.(*PAMConfig), true) | |||
if err == nil { | |||
return u, nil | |||
} | |||
@@ -243,11 +243,11 @@ func UserSignIn(uname, passwd string) (*User, error) { | |||
switch u.LoginType { | |||
case LDAP: | |||
return LoginUserLdapSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*LDAPConfig), false) | |||
return LoginUserLdapSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*LDAPConfig), false) | |||
case SMTP: | |||
return LoginUserSMTPSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*SMTPConfig), false) | |||
return LoginUserSMTPSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*SMTPConfig), false) | |||
case PAM: | |||
return LoginUserPAMSource(u, u.LoginName, passwd, source.Id, source.Cfg.(*PAMConfig), false) | |||
return LoginUserPAMSource(u, u.LoginName, passwd, source.ID, source.Cfg.(*PAMConfig), false) | |||
} | |||
return nil, ErrUnsupportedLoginType | |||
} | |||
@@ -311,14 +311,17 @@ func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { | |||
return nil, nil | |||
} | |||
var ( | |||
const ( | |||
SMTP_PLAIN = "PLAIN" | |||
SMTP_LOGIN = "LOGIN" | |||
SMTPAuths = []string{SMTP_PLAIN, SMTP_LOGIN} | |||
) | |||
func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error { | |||
c, err := smtp.Dial(fmt.Sprintf("%s:%d", host, port)) | |||
var ( | |||
SMTPAuths = []string{SMTP_PLAIN, SMTP_LOGIN} | |||
) | |||
func SMTPAuth(a smtp.Auth, cfg *SMTPConfig) error { | |||
c, err := smtp.Dial(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)) | |||
if err != nil { | |||
return err | |||
} | |||
@@ -328,10 +331,12 @@ func SmtpAuth(host string, port int, a smtp.Auth, useTls bool) error { | |||
return err | |||
} | |||
if useTls { | |||
if cfg.TLS { | |||
if ok, _ := c.Extension("STARTTLS"); ok { | |||
config := &tls.Config{ServerName: host} | |||
if err = c.StartTLS(config); err != nil { | |||
if err = c.StartTLS(&tls.Config{ | |||
InsecureSkipVerify: cfg.SkipVerify, | |||
ServerName: cfg.Host, | |||
}); err != nil { | |||
return err | |||
} | |||
} else { | |||
@@ -361,7 +366,7 @@ func LoginUserSMTPSource(u *User, name, passwd string, sourceId int64, cfg *SMTP | |||
return nil, errors.New("Unsupported SMTP auth type") | |||
} | |||
if err := SmtpAuth(cfg.Host, cfg.Port, auth, cfg.TLS); err != nil { | |||
if err := SMTPAuth(auth, cfg); err != nil { | |||
if strings.Contains(err.Error(), "Username and Password not accepted") { | |||
return nil, ErrUserNotExist{u.Id, u.Name} | |||
} |
@@ -48,10 +48,6 @@ var ( | |||
Gitignores, Licenses, Readmes []string | |||
) | |||
var ( | |||
DescPattern = regexp.MustCompile(`https?://\S+`) | |||
) | |||
func LoadRepoConfig() { | |||
// Load .gitignore and license files and readme templates. | |||
types := []string{"gitignore", "license", "readme"} | |||
@@ -266,6 +262,10 @@ func (repo *Repository) IsOwnedBy(userID int64) bool { | |||
return repo.OwnerID == userID | |||
} | |||
var ( | |||
DescPattern = regexp.MustCompile(`https?://\S+`) | |||
) | |||
// DescriptionHtml does special handles to description and return HTML string. | |||
func (repo *Repository) DescriptionHtml() template.HTML { | |||
sanitize := func(s string) string { |
@@ -29,7 +29,8 @@ type AuthenticationForm struct { | |||
SMTPHost string `form:"smtp_host"` | |||
SMTPPort int `form:"smtp_port"` | |||
TLS bool `form:"tls"` | |||
AllowAutoRegister bool `form:"allowautoregister"` | |||
SkipVerify bool | |||
AllowAutoRegister bool `form:"allowautoregister"` | |||
PAMServiceName string | |||
} | |||
@@ -63,27 +63,28 @@ func NewAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) { | |||
case models.LDAP: | |||
u = &models.LDAPConfig{ | |||
Ldapsource: ldap.Ldapsource{ | |||
Name: form.Name, | |||
Host: form.Host, | |||
Port: form.Port, | |||
UseSSL: form.UseSSL, | |||
BindDN: form.BindDN, | |||
BindPassword: form.BindPassword, | |||
UserBase: form.UserBase, | |||
Filter: form.Filter, | |||
AdminFilter: form.AdminFilter, | |||
AttributeName: form.AttributeName, | |||
AttributeSurname: form.AttributeSurname, | |||
AttributeMail: form.AttributeMail, | |||
Enabled: true, | |||
Name: form.Name, | |||
Host: form.Host, | |||
Port: form.Port, | |||
UseSSL: form.UseSSL, | |||
BindDN: form.BindDN, | |||
BindPassword: form.BindPassword, | |||
UserBase: form.UserBase, | |||
Filter: form.Filter, | |||
AdminFilter: form.AdminFilter, | |||
AttributeName: form.AttributeName, | |||
AttributeSurname: form.AttributeSurname, | |||
AttributeMail: form.AttributeMail, | |||
Enabled: true, | |||
}, | |||
} | |||
case models.SMTP: | |||
u = &models.SMTPConfig{ | |||
Auth: form.SMTPAuth, | |||
Host: form.SMTPHost, | |||
Port: form.SMTPPort, | |||
TLS: form.TLS, | |||
Auth: form.SMTPAuth, | |||
Host: form.SMTPHost, | |||
Port: form.SMTPPort, | |||
TLS: form.TLS, | |||
SkipVerify: form.SkipVerify, | |||
} | |||
case models.PAM: | |||
u = &models.PAMConfig{ | |||
@@ -123,7 +124,7 @@ func EditAuthSource(ctx *middleware.Context) { | |||
ctx.Handle(404, "EditAuthSource", nil) | |||
return | |||
} | |||
u, err := models.GetLoginSourceById(id) | |||
u, err := models.GetLoginSourceByID(id) | |||
if err != nil { | |||
ctx.Handle(500, "GetLoginSourceById", err) | |||
return | |||
@@ -150,27 +151,28 @@ func EditAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) { | |||
case models.LDAP: | |||
config = &models.LDAPConfig{ | |||
Ldapsource: ldap.Ldapsource{ | |||
Name: form.Name, | |||
Host: form.Host, | |||
Port: form.Port, | |||
UseSSL: form.UseSSL, | |||
BindDN: form.BindDN, | |||
BindPassword: form.BindPassword, | |||
UserBase: form.UserBase, | |||
AttributeName: form.AttributeName, | |||
AttributeSurname: form.AttributeSurname, | |||
AttributeMail: form.AttributeMail, | |||
Filter: form.Filter, | |||
AdminFilter: form.AdminFilter, | |||
Enabled: true, | |||
Name: form.Name, | |||
Host: form.Host, | |||
Port: form.Port, | |||
UseSSL: form.UseSSL, | |||
BindDN: form.BindDN, | |||
BindPassword: form.BindPassword, | |||
UserBase: form.UserBase, | |||
AttributeName: form.AttributeName, | |||
AttributeSurname: form.AttributeSurname, | |||
AttributeMail: form.AttributeMail, | |||
Filter: form.Filter, | |||
AdminFilter: form.AdminFilter, | |||
Enabled: true, | |||
}, | |||
} | |||
case models.SMTP: | |||
config = &models.SMTPConfig{ | |||
Auth: form.SMTPAuth, | |||
Host: form.SMTPHost, | |||
Port: form.SMTPPort, | |||
TLS: form.TLS, | |||
Auth: form.SMTPAuth, | |||
Host: form.SMTPHost, | |||
Port: form.SMTPPort, | |||
TLS: form.TLS, | |||
SkipVerify: form.SkipVerify, | |||
} | |||
case models.PAM: | |||
config = &models.PAMConfig{ | |||
@@ -182,7 +184,7 @@ func EditAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) { | |||
} | |||
u := models.LoginSource{ | |||
Id: form.ID, | |||
ID: form.ID, | |||
Name: form.Name, | |||
IsActived: form.IsActived, | |||
Type: models.LoginType(form.Type), | |||
@@ -207,7 +209,7 @@ func DeleteAuthSource(ctx *middleware.Context) { | |||
return | |||
} | |||
a, err := models.GetLoginSourceById(id) | |||
a, err := models.GetLoginSourceByID(id) | |||
if err != nil { | |||
ctx.Handle(500, "GetLoginSourceById", err) | |||
return |
@@ -12,9 +12,9 @@ | |||
<div class="panel-header"> | |||
<strong>{{.i18n.Tr "admin.auths.edit"}}</strong> | |||
</div> | |||
<form class="form form-align panel-body" id="auth-setting-form" action="{{AppSubUrl}}/admin/auths/{{.Source.Id}}" data-delete-url="{{AppSubUrl}}/admin/auths/{{.Source.Id}}/delete" method="post"> | |||
<form class="form form-align panel-body" id="auth-setting-form" action="{{AppSubUrl}}/admin/auths/{{.Source.ID}}" data-delete-url="{{AppSubUrl}}/admin/auths/{{.Source.ID}}/delete" method="post"> | |||
{{.CsrfTokenHtml}} | |||
<input type="hidden" value="{{.Source.Id}}" name="id"/> | |||
<input type="hidden" value="{{.Source.ID}}" name="id"/> | |||
{{$type := .Source.Type}} | |||
<div class="field"> | |||
<label>{{.i18n.Tr "admin.auths.auth_type"}}</label> | |||
@@ -109,6 +109,10 @@ | |||
<input name="tls" type="checkbox" {{if .Source.SMTP.TLS}}checked{{end}}> | |||
<strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong> | |||
<br> | |||
<label></label> | |||
<input name="skip_verify" type="checkbox" {{if .Source.SMTP.SkipVerify}}checked{{end}}> | |||
<strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong> | |||
<br> | |||
{{end}} | |||
<label></label> | |||
<input name="allowautoregister" type="checkbox" {{if .Source.AllowAutoRegister}}checked{{end}}> |
@@ -30,13 +30,13 @@ | |||
<tbody> | |||
{{range .Sources}} | |||
<tr> | |||
<td>{{.Id}}</td> | |||
<td><a href="{{AppSubUrl}}/admin/auths/{{.Id}}">{{.Name}}</a></td> | |||
<td>{{.ID}}</td> | |||
<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{.Name}}</a></td> | |||
<td>{{.TypeString}}</td> | |||
<td><i class="fa fa{{if .IsActived}}-check{{end}}-square-o"></i></td> | |||
<td><span title="{{DateFmtLong .Updated}}">{{DateFmtShort .Updated}}</span></td> | |||
<td><span title="{{DateFmtLong .Created}}">{{DateFmtShort .Created}}</span></td> | |||
<td><a href="{{AppSubUrl}}/admin/auths/{{.Id}}"><i class="fa fa-pencil-square-o"></i></a></td> | |||
<td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}"><i class="fa fa-pencil-square-o"></i></a></td> | |||
</tr> | |||
{{end}} | |||
</tbody> |
@@ -102,6 +102,10 @@ | |||
<input name="tls" type="checkbox" {{if .tls}}checked{{end}}> | |||
<strong>{{.i18n.Tr "admin.auths.enable_tls"}}</strong> | |||
<br> | |||
<label></label> | |||
<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> | |||
<strong>{{.i18n.Tr "admin.auths.skip_tls_verify"}}</strong> | |||
<br> | |||
</div> | |||
<label></label> | |||
<input name="allowautoregister" type="checkbox" {{if .allowautoregister}}checked{{end}}> |