commit
d8136c9c3c
@ -0,0 +1,117 @@ |
|||||||
|
package models |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"errors" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/go-xorm/core" |
||||||
|
"github.com/go-xorm/xorm" |
||||||
|
"github.com/gogits/gogs/modules/auth/ldap" |
||||||
|
) |
||||||
|
|
||||||
|
// Login types.
|
||||||
|
const ( |
||||||
|
LT_PLAIN = iota + 1 |
||||||
|
LT_LDAP |
||||||
|
LT_SMTP |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
ErrAuthenticationAlreadyExist = errors.New("Authentication already exist") |
||||||
|
ErrAuthenticationNotExist = errors.New("Authentication is not exist") |
||||||
|
ErrAuthenticationUserUsed = errors.New("Authentication has been used by some users") |
||||||
|
) |
||||||
|
|
||||||
|
var LoginTypes = map[int]string{ |
||||||
|
LT_LDAP: "LDAP", |
||||||
|
LT_SMTP: "SMTP", |
||||||
|
} |
||||||
|
|
||||||
|
var _ core.Conversion = &LDAPConfig{} |
||||||
|
|
||||||
|
type LDAPConfig struct { |
||||||
|
ldap.Ldapsource |
||||||
|
} |
||||||
|
|
||||||
|
// implement
|
||||||
|
func (cfg *LDAPConfig) FromDB(bs []byte) error { |
||||||
|
return json.Unmarshal(bs, &cfg.Ldapsource) |
||||||
|
} |
||||||
|
|
||||||
|
func (cfg *LDAPConfig) ToDB() ([]byte, error) { |
||||||
|
return json.Marshal(cfg.Ldapsource) |
||||||
|
} |
||||||
|
|
||||||
|
type LoginSource struct { |
||||||
|
Id int64 |
||||||
|
Type int |
||||||
|
Name string `xorm:"unique"` |
||||||
|
IsActived bool `xorm:"not null default false"` |
||||||
|
Cfg core.Conversion `xorm:"TEXT"` |
||||||
|
Created time.Time `xorm:"created"` |
||||||
|
Updated time.Time `xorm:"updated"` |
||||||
|
} |
||||||
|
|
||||||
|
func (source *LoginSource) TypeString() string { |
||||||
|
return LoginTypes[source.Type] |
||||||
|
} |
||||||
|
|
||||||
|
func (source *LoginSource) LDAP() *LDAPConfig { |
||||||
|
return source.Cfg.(*LDAPConfig) |
||||||
|
} |
||||||
|
|
||||||
|
// for xorm callback
|
||||||
|
func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) { |
||||||
|
if colName == "type" { |
||||||
|
ty := (*val).(int64) |
||||||
|
switch ty { |
||||||
|
case LT_LDAP: |
||||||
|
source.Cfg = new(LDAPConfig) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func GetAuths() ([]*LoginSource, error) { |
||||||
|
var auths = make([]*LoginSource, 0) |
||||||
|
err := orm.Find(&auths) |
||||||
|
return auths, err |
||||||
|
} |
||||||
|
|
||||||
|
func GetLoginSourceById(id int64) (*LoginSource, error) { |
||||||
|
source := new(LoginSource) |
||||||
|
has, err := orm.Id(id).Get(source) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if !has { |
||||||
|
return nil, ErrAuthenticationNotExist |
||||||
|
} |
||||||
|
return source, nil |
||||||
|
} |
||||||
|
|
||||||
|
func AddLDAPSource(name string, cfg *LDAPConfig) error { |
||||||
|
_, err := orm.Insert(&LoginSource{Type: LT_LDAP, |
||||||
|
Name: name, |
||||||
|
IsActived: true, |
||||||
|
Cfg: cfg, |
||||||
|
}) |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
func UpdateLDAPSource(source *LoginSource) error { |
||||||
|
_, err := orm.AllCols().Id(source.Id).Update(source) |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
func DelLoginSource(source *LoginSource) error { |
||||||
|
cnt, err := orm.Count(&User{LoginSource: source.Id}) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
if cnt > 0 { |
||||||
|
return ErrAuthenticationUserUsed |
||||||
|
} |
||||||
|
_, err = orm.Id(source.Id).Delete(&LoginSource{}) |
||||||
|
return err |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package auth |
||||||
|
|
||||||
|
type AuthenticationForm struct { |
||||||
|
Id int64 `form:"id"` |
||||||
|
Type int `form:"type"` |
||||||
|
Name string `form:"name" binding:"MaxSize(50)"` |
||||||
|
Domain string `form:"domain"` |
||||||
|
Host string `form:"host"` |
||||||
|
Port int `form:"port"` |
||||||
|
BaseDN string `form:"base_dn"` |
||||||
|
Attributes string `form:"attributes"` |
||||||
|
Filter string `form:"filter"` |
||||||
|
MsAdSA string `form:"ms_ad_sa"` |
||||||
|
IsActived bool `form:"is_actived"` |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
package admin |
||||||
|
|
||||||
|
import ( |
||||||
|
"strings" |
||||||
|
|
||||||
|
"github.com/go-martini/martini" |
||||||
|
"github.com/gogits/gogs/models" |
||||||
|
"github.com/gogits/gogs/modules/auth" |
||||||
|
"github.com/gogits/gogs/modules/auth/ldap" |
||||||
|
"github.com/gogits/gogs/modules/base" |
||||||
|
"github.com/gogits/gogs/modules/middleware" |
||||||
|
"github.com/gpmgo/gopm/log" |
||||||
|
) |
||||||
|
|
||||||
|
func NewAuthSource(ctx *middleware.Context) { |
||||||
|
ctx.Data["Title"] = "New Authentication" |
||||||
|
ctx.Data["PageIsAuths"] = true |
||||||
|
ctx.Data["LoginTypes"] = models.LoginTypes |
||||||
|
ctx.HTML(200, "admin/auths/new") |
||||||
|
} |
||||||
|
|
||||||
|
func NewAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) { |
||||||
|
ctx.Data["Title"] = "New Authentication" |
||||||
|
ctx.Data["PageIsAuths"] = true |
||||||
|
|
||||||
|
if ctx.HasError() { |
||||||
|
ctx.HTML(200, "admin/auths/new") |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
u := &models.LDAPConfig{ |
||||||
|
Ldapsource: ldap.Ldapsource{ |
||||||
|
Host: form.Host, |
||||||
|
Port: form.Port, |
||||||
|
BaseDN: form.BaseDN, |
||||||
|
Attributes: form.Attributes, |
||||||
|
Filter: form.Filter, |
||||||
|
MsAdSAFormat: form.MsAdSA, |
||||||
|
Enabled: true, |
||||||
|
Name: form.Name, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
if err := models.AddLDAPSource(form.Name, u); err != nil { |
||||||
|
switch err { |
||||||
|
default: |
||||||
|
ctx.Handle(500, "admin.auths.NewAuth", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
log.Trace("%s Authentication created by admin(%s): %s", ctx.Req.RequestURI, |
||||||
|
ctx.User.LowerName, strings.ToLower(form.Name)) |
||||||
|
|
||||||
|
ctx.Redirect("/admin/auths") |
||||||
|
} |
||||||
|
|
||||||
|
func EditAuthSource(ctx *middleware.Context, params martini.Params) { |
||||||
|
ctx.Data["Title"] = "Edit Authentication" |
||||||
|
ctx.Data["PageIsAuths"] = true |
||||||
|
id, err := base.StrTo(params["authid"]).Int64() |
||||||
|
if err != nil { |
||||||
|
ctx.Handle(404, "admin.auths.EditAuthSource", err) |
||||||
|
return |
||||||
|
} |
||||||
|
u, err := models.GetLoginSourceById(id) |
||||||
|
if err != nil { |
||||||
|
ctx.Handle(500, "admin.user.EditUser", err) |
||||||
|
return |
||||||
|
} |
||||||
|
ctx.Data["Source"] = u |
||||||
|
ctx.Data["LoginTypes"] = models.LoginTypes |
||||||
|
ctx.HTML(200, "admin/auths/edit") |
||||||
|
} |
||||||
|
|
||||||
|
func EditAuthSourcePost(ctx *middleware.Context, form auth.AuthenticationForm) { |
||||||
|
ctx.Data["Title"] = "Edit Authentication" |
||||||
|
ctx.Data["PageIsAuths"] = true |
||||||
|
|
||||||
|
if ctx.HasError() { |
||||||
|
ctx.HTML(200, "admin/auths/edit") |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
u := models.LoginSource{ |
||||||
|
Name: form.Name, |
||||||
|
IsActived: form.IsActived, |
||||||
|
Type: models.LT_LDAP, |
||||||
|
Cfg: &models.LDAPConfig{ |
||||||
|
Ldapsource: ldap.Ldapsource{ |
||||||
|
Host: form.Host, |
||||||
|
Port: form.Port, |
||||||
|
BaseDN: form.BaseDN, |
||||||
|
Attributes: form.Attributes, |
||||||
|
Filter: form.Filter, |
||||||
|
MsAdSAFormat: form.MsAdSA, |
||||||
|
Enabled: true, |
||||||
|
Name: form.Name, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
if err := models.UpdateLDAPSource(&u); err != nil { |
||||||
|
switch err { |
||||||
|
default: |
||||||
|
ctx.Handle(500, "admin.auths.EditAuth", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
log.Trace("%s Authentication changed by admin(%s): %s", ctx.Req.RequestURI, |
||||||
|
ctx.User.LowerName, strings.ToLower(form.Name)) |
||||||
|
|
||||||
|
ctx.Redirect("/admin/auths") |
||||||
|
} |
||||||
|
|
||||||
|
func DeleteAuthSource(ctx *middleware.Context, params martini.Params) { |
||||||
|
ctx.Data["Title"] = "Delete Authentication" |
||||||
|
ctx.Data["PageIsAuths"] = true |
||||||
|
|
||||||
|
id, err := base.StrTo(params["authid"]).Int64() |
||||||
|
if err != nil { |
||||||
|
ctx.Handle(404, "admin.auths.DeleteAuth", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
a, err := models.GetLoginSourceById(id) |
||||||
|
if err != nil { |
||||||
|
ctx.Handle(500, "admin.auths.DeleteAuth", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
if err = models.DelLoginSource(a); err != nil { |
||||||
|
switch err { |
||||||
|
case models.ErrAuthenticationUserUsed: |
||||||
|
ctx.Flash.Error("This authentication still has used by some users, you should move them and then delete again.") |
||||||
|
ctx.Redirect("/admin/auths/" + params["authid"]) |
||||||
|
default: |
||||||
|
ctx.Handle(500, "admin.auths.DeleteAuth", err) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
log.Trace("%s Authentication deleted by admin(%s): %s", ctx.Req.RequestURI, |
||||||
|
ctx.User.LowerName, ctx.User.LowerName) |
||||||
|
|
||||||
|
ctx.Redirect("/admin/auths") |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
<div id="body" class="container" data-page="admin"> |
||||||
|
{{template "admin/nav" .}} |
||||||
|
<div id="admin-container" class="col-md-10"> |
||||||
|
<div class="panel panel-default"> |
||||||
|
<div class="panel-heading"> |
||||||
|
Authentication Management |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="panel-body"> |
||||||
|
<a href="/admin/auths/new" class="btn btn-primary">New Auth Source</a> |
||||||
|
<table class="table table-striped"> |
||||||
|
<thead> |
||||||
|
<tr> |
||||||
|
<th>Id</th> |
||||||
|
<th>Name</th> |
||||||
|
<th>Type</th> |
||||||
|
<th>Actived</th> |
||||||
|
<th>Updated</th> |
||||||
|
<th>Created</th> |
||||||
|
<th>Operation</th> |
||||||
|
</tr> |
||||||
|
</thead> |
||||||
|
<tbody> |
||||||
|
{{range .Sources}} |
||||||
|
<tr> |
||||||
|
<td>{{.Id}}</td> |
||||||
|
<td><a href="/admin/auths/{{.Id}}">{{.Name}}</a></td> |
||||||
|
<td>{{.TypeString}}</td> |
||||||
|
<td><i class="fa fa{{if .IsActived}}-check{{end}}-square-o"></i></td> |
||||||
|
<td>{{DateFormat .Updated "M d, Y"}}</td> |
||||||
|
<td>{{DateFormat .Created "M d, Y"}}</td> |
||||||
|
<td><a href="/admin/auths/{{.Id}}"><i class="fa fa-pencil-square-o"></i></a></td> |
||||||
|
</tr> |
||||||
|
{{end}} |
||||||
|
</tbody> |
||||||
|
</table> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
@ -0,0 +1,107 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
<div id="body" class="container" data-page="admin"> |
||||||
|
{{template "admin/nav" .}} |
||||||
|
<div id="admin-container" class="col-md-9"> |
||||||
|
<div class="panel panel-default"> |
||||||
|
<div class="panel-heading"> |
||||||
|
Edit Authentication |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="panel-body"> |
||||||
|
<br/> |
||||||
|
<form action="/admin/auths/{{.Source.Id}}" method="post" class="form-horizontal"> |
||||||
|
{{.CsrfTokenHtml}} |
||||||
|
{{template "base/alert" .}} |
||||||
|
<input type="hidden" value="{{.Source.Id}}" name="id"/> |
||||||
|
<div class="form-group"> |
||||||
|
<label class="col-md-3 control-label">Auth Type: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<select class="form-control"> |
||||||
|
{{$type := .Source.Type}} |
||||||
|
{{range $key, $val := .LoginTypes}} |
||||||
|
<option value="{{$key}}" {{if eq $key $type}}selected{{end}}>{{$val}}</option> |
||||||
|
{{end}} |
||||||
|
</select> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Name: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="name" class="form-control" placeholder="Type account's username" value="{{.Source.Name}}" required="required"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Domain: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="domain" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.Name}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Host: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="host" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.Host}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Port: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="port" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.Port}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Base DN: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="base_dn" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.BaseDN}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Search Attributes: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="attributes" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.Attributes}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Search Filter: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="filter" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.Filter}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Ms Ad SA: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="ms_ad_sa" class="form-control" placeholder="Type account's e-mail address" value="{{.Source.LDAP.MsAdSAFormat}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group"> |
||||||
|
<div class="col-md-7 col-md-offset-3"> |
||||||
|
<div class="checkbox"> |
||||||
|
<label> |
||||||
|
<input type="checkbox" name="is_actived" {{if .Source.IsActived}}checked{{end}}> |
||||||
|
<strong>This authentication has activated.</strong> |
||||||
|
</label> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<hr/> |
||||||
|
<div class="form-group"> |
||||||
|
<div class="col-md-offset-3 col-md-6"> |
||||||
|
<button type="submit" class="btn btn-lg btn-primary btn-block">Update authentication config</button> |
||||||
|
<a type="button" href="/admin/auths/{{.Source.Id}}/delete" class="btn btn-lg btn-danger btn-block">Delete this authentication</a> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
@ -0,0 +1,94 @@ |
|||||||
|
{{template "base/head" .}} |
||||||
|
{{template "base/navbar" .}} |
||||||
|
<div id="body" class="container" data-page="admin"> |
||||||
|
{{template "admin/nav" .}} |
||||||
|
<div id="admin-container" class="col-md-9"> |
||||||
|
<div class="panel panel-default"> |
||||||
|
<div class="panel-heading"> |
||||||
|
New Authentication |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="panel-body"> |
||||||
|
<br/> |
||||||
|
<form action="/admin/auths/new" method="post" class="form-horizontal"> |
||||||
|
{{.CsrfTokenHtml}} |
||||||
|
{{template "base/alert" .}} |
||||||
|
<div class="form-group"> |
||||||
|
<label class="col-md-3 control-label">Auth Type: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<select class="form-control"> |
||||||
|
{{range $key, $val := .LoginTypes}} |
||||||
|
<option value="{{$key}}">{{$val}}</option> |
||||||
|
{{end}} |
||||||
|
</select> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Name: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="name" class="form-control" placeholder="Authentication's name" required="required"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Domain: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="domain" class="form-control" placeholder="Domain name" value="{{.domain}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Host: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="host" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Port: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="port" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Base DN: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="base_dn" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Search Attributes: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="attributes" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Search Filter: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="filter" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-group {{if .Err_Email}}has-error has-feedback{{end}}"> |
||||||
|
<label class="col-md-3 control-label">Ms Ad SA: </label> |
||||||
|
<div class="col-md-7"> |
||||||
|
<input name="ms_ad_sa" class="form-control" placeholder="Type account's e-mail address" value="{{.email}}" required="required" title="Email is not valid"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<hr/> |
||||||
|
<div class="form-group"> |
||||||
|
<div class="col-md-offset-3 col-md-7"> |
||||||
|
<button type="submit" class="btn btn-lg btn-primary">Create new authentication</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
</div> |
||||||
|
</div> |
||||||
|
{{template "base/footer" .}} |
Loading…
Reference in new issue