mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-22 10:03:54 +01:00
Merge branch 'dev-ldap' into dev
This commit is contained in:
commit
d8136c9c3c
18 changed files with 614 additions and 24 deletions
11
cmd/web.go
11
cmd/web.go
|
@ -134,6 +134,7 @@ func runWeb(*cli.Context) {
|
||||||
r.Get("/users", admin.Users)
|
r.Get("/users", admin.Users)
|
||||||
r.Get("/repos", admin.Repositories)
|
r.Get("/repos", admin.Repositories)
|
||||||
r.Get("/config", admin.Config)
|
r.Get("/config", admin.Config)
|
||||||
|
r.Get("/auths", admin.Auths)
|
||||||
}, adminReq)
|
}, adminReq)
|
||||||
m.Group("/admin/users", func(r martini.Router) {
|
m.Group("/admin/users", func(r martini.Router) {
|
||||||
r.Get("/new", admin.NewUser)
|
r.Get("/new", admin.NewUser)
|
||||||
|
@ -143,6 +144,14 @@ func runWeb(*cli.Context) {
|
||||||
r.Get("/:userid/delete", admin.DeleteUser)
|
r.Get("/:userid/delete", admin.DeleteUser)
|
||||||
}, adminReq)
|
}, adminReq)
|
||||||
|
|
||||||
|
m.Group("/admin/auths", func(r martini.Router) {
|
||||||
|
r.Get("/new", admin.NewAuthSource)
|
||||||
|
r.Post("/new", bindIgnErr(auth.AuthenticationForm{}), admin.NewAuthSourcePost)
|
||||||
|
r.Get("/:authid", admin.EditAuthSource)
|
||||||
|
r.Post("/:authid", bindIgnErr(auth.AuthenticationForm{}), admin.EditAuthSourcePost)
|
||||||
|
r.Get("/:authid/delete", admin.DeleteAuthSource)
|
||||||
|
}, adminReq)
|
||||||
|
|
||||||
if martini.Env == martini.Dev {
|
if martini.Env == martini.Dev {
|
||||||
m.Get("/template/**", dev.TemplatePreview)
|
m.Get("/template/**", dev.TemplatePreview)
|
||||||
}
|
}
|
||||||
|
@ -195,7 +204,7 @@ func runWeb(*cli.Context) {
|
||||||
|
|
||||||
protocol := base.Cfg.MustValue("server", "PROTOCOL", "http")
|
protocol := base.Cfg.MustValue("server", "PROTOCOL", "http")
|
||||||
listenAddr := fmt.Sprintf("%s:%s",
|
listenAddr := fmt.Sprintf("%s:%s",
|
||||||
base.Cfg.MustValue("server", "HTTP_ADDR"),
|
base.Cfg.MustValue("server", "HTTP_ADDR", "0.0.0.0"),
|
||||||
base.Cfg.MustValue("server", "HTTP_PORT", "3000"))
|
base.Cfg.MustValue("server", "HTTP_PORT", "3000"))
|
||||||
|
|
||||||
if protocol == "http" {
|
if protocol == "http" {
|
||||||
|
|
|
@ -30,7 +30,7 @@ func LoginUserLdap(name, passwd string) (*User, error) {
|
||||||
Email: mail}
|
Email: mail}
|
||||||
_, err := RegisterUser(&user)
|
_, err := RegisterUser(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("LDAP local user %s fond (%s) ", name, err)
|
log.Debug("LDAP local user %s found (%s) ", name, err)
|
||||||
}
|
}
|
||||||
// simulate local user login
|
// simulate local user login
|
||||||
localUser, err2 := GetUserByName(user.Name)
|
localUser, err2 := GetUserByName(user.Name)
|
||||||
|
|
117
models/login.go
Normal file
117
models/login.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ var (
|
||||||
func init() {
|
func init() {
|
||||||
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
|
tables = append(tables, new(User), new(PublicKey), new(Repository), new(Watch),
|
||||||
new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow),
|
new(Action), new(Access), new(Issue), new(Comment), new(Oauth2), new(Follow),
|
||||||
new(Mirror), new(Release))
|
new(Mirror), new(Release), new(LoginSource))
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadModelsConfig() {
|
func LoadModelsConfig() {
|
||||||
|
|
|
@ -26,12 +26,6 @@ const (
|
||||||
UT_ORGANIZATION
|
UT_ORGANIZATION
|
||||||
)
|
)
|
||||||
|
|
||||||
// Login types.
|
|
||||||
const (
|
|
||||||
LT_PLAIN = iota + 1
|
|
||||||
LT_LDAP
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrUserOwnRepos = errors.New("User still have ownership of repositories")
|
ErrUserOwnRepos = errors.New("User still have ownership of repositories")
|
||||||
ErrUserAlreadyExist = errors.New("User already exist")
|
ErrUserAlreadyExist = errors.New("User already exist")
|
||||||
|
@ -50,6 +44,7 @@ type User struct {
|
||||||
Email string `xorm:"unique not null"`
|
Email string `xorm:"unique not null"`
|
||||||
Passwd string `xorm:"not null"`
|
Passwd string `xorm:"not null"`
|
||||||
LoginType int
|
LoginType int
|
||||||
|
LoginSource int64 `xorm:"not null default 0"`
|
||||||
Type int
|
Type int
|
||||||
NumFollowers int
|
NumFollowers int
|
||||||
NumFollowings int
|
NumFollowings int
|
||||||
|
|
|
@ -16,12 +16,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type AdminEditUserForm struct {
|
type AdminEditUserForm struct {
|
||||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||||
Website string `form:"website" binding:"MaxSize(50)"`
|
Website string `form:"website" binding:"MaxSize(50)"`
|
||||||
Location string `form:"location" binding:"MaxSize(50)"`
|
Location string `form:"location" binding:"MaxSize(50)"`
|
||||||
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
Avatar string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
|
||||||
Active string `form:"active"`
|
Active string `form:"active"`
|
||||||
Admin string `form:"admin"`
|
Admin string `form:"admin"`
|
||||||
|
LoginType int `form:"login_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *AdminEditUserForm) Name(field string) string {
|
func (f *AdminEditUserForm) Name(field string) string {
|
||||||
|
|
|
@ -26,6 +26,7 @@ type RegisterForm struct {
|
||||||
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
|
||||||
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
|
||||||
RetypePasswd string `form:"retypepasswd"`
|
RetypePasswd string `form:"retypepasswd"`
|
||||||
|
LoginType string `form:"logintype"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *RegisterForm) Name(field string) string {
|
func (f *RegisterForm) Name(field string) string {
|
||||||
|
|
15
modules/auth/authentication.go
Normal file
15
modules/auth/authentication.go
Normal file
|
@ -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"`
|
||||||
|
}
|
|
@ -8,12 +8,13 @@ package ldap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
goldap "github.com/juju2013/goldap"
|
goldap "github.com/juju2013/goldap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Basic LDAP authentication service
|
// Basic LDAP authentication service
|
||||||
type ldapsource struct {
|
type Ldapsource 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
|
||||||
|
@ -26,12 +27,12 @@ type ldapsource struct {
|
||||||
|
|
||||||
//Global LDAP directory pool
|
//Global LDAP directory pool
|
||||||
var (
|
var (
|
||||||
Authensource []ldapsource
|
Authensource []Ldapsource
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add a new source (LDAP directory) to the global pool
|
// Add a new source (LDAP directory) to the global pool
|
||||||
func AddSource(name string, host string, port int, basedn string, attributes string, filter string, msadsaformat string) {
|
func AddSource(name string, host string, port int, basedn string, attributes string, filter string, msadsaformat string) {
|
||||||
ldaphost := ldapsource{name, host, port, basedn, attributes, filter, msadsaformat, true}
|
ldaphost := Ldapsource{name, host, port, basedn, attributes, filter, msadsaformat, true}
|
||||||
Authensource = append(Authensource, ldaphost)
|
Authensource = append(Authensource, ldaphost)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ func LoginUser(name, passwd string) (a string, r bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
|
// searchEntry : search an LDAP source if an entry (name, passwd) is valide and in the specific filter
|
||||||
func (ls ldapsource) searchEntry(name, passwd string) (string, bool) {
|
func (ls Ldapsource) searchEntry(name, passwd string) (string, bool) {
|
||||||
l, err := goldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
|
l, err := goldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("LDAP Connect error, disabled source %s", ls.Host)
|
log.Debug("LDAP Connect error, disabled source %s", ls.Host)
|
||||||
|
|
|
@ -120,6 +120,19 @@ func Users(ctx *middleware.Context) {
|
||||||
ctx.HTML(200, "admin/users")
|
ctx.HTML(200, "admin/users")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Auths(ctx *middleware.Context) {
|
||||||
|
ctx.Data["Title"] = "Auth Sources"
|
||||||
|
ctx.Data["PageIsAuths"] = true
|
||||||
|
|
||||||
|
var err error
|
||||||
|
ctx.Data["Sources"], err = models.GetAuths()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(200, "admin.Auths", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.HTML(200, "admin/auths")
|
||||||
|
}
|
||||||
|
|
||||||
func Repositories(ctx *middleware.Context) {
|
func Repositories(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "Repository Management"
|
ctx.Data["Title"] = "Repository Management"
|
||||||
ctx.Data["PageIsRepos"] = true
|
ctx.Data["PageIsRepos"] = true
|
||||||
|
|
147
routers/admin/auths.go
Normal file
147
routers/admin/auths.go
Normal file
|
@ -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")
|
||||||
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
package admin
|
package admin
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
@ -19,6 +21,12 @@ import (
|
||||||
func NewUser(ctx *middleware.Context) {
|
func NewUser(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "New Account"
|
ctx.Data["Title"] = "New Account"
|
||||||
ctx.Data["PageIsUsers"] = true
|
ctx.Data["PageIsUsers"] = true
|
||||||
|
auths, err := models.GetAuths()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "admin.user.NewUser", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["LoginSources"] = auths
|
||||||
ctx.HTML(200, "admin/users/new")
|
ctx.HTML(200, "admin/users/new")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +48,18 @@ func NewUserPost(ctx *middleware.Context, form auth.RegisterForm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u := &models.User{
|
u := &models.User{
|
||||||
Name: form.UserName,
|
Name: form.UserName,
|
||||||
Email: form.Email,
|
Email: form.Email,
|
||||||
Passwd: form.Password,
|
Passwd: form.Password,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
|
LoginType: models.LT_PLAIN,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(form.LoginType) > 0 {
|
||||||
|
fields := strings.Split(form.LoginType, "-")
|
||||||
|
u.LoginType, _ = strconv.Atoi(fields[0])
|
||||||
|
u.LoginSource, _ = strconv.ParseInt(fields[1], 10, 64)
|
||||||
|
fmt.Println(u.LoginSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -84,6 +100,12 @@ func EditUser(ctx *middleware.Context, params martini.Params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["User"] = u
|
ctx.Data["User"] = u
|
||||||
|
auths, err := models.GetAuths()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Handle(500, "admin.user.NewUser", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Data["LoginSources"] = auths
|
||||||
ctx.HTML(200, "admin/users/edit")
|
ctx.HTML(200, "admin/users/edit")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +132,7 @@ func EditUserPost(ctx *middleware.Context, params martini.Params, form auth.Admi
|
||||||
u.AvatarEmail = form.Avatar
|
u.AvatarEmail = form.Avatar
|
||||||
u.IsActive = form.Active == "on"
|
u.IsActive = form.Active == "on"
|
||||||
u.IsAdmin = form.Admin == "on"
|
u.IsAdmin = form.Admin == "on"
|
||||||
|
u.LoginType = form.LoginType
|
||||||
if err := models.UpdateUser(u); err != nil {
|
if err := models.UpdateUser(u); err != nil {
|
||||||
ctx.Handle(500, "admin.user.EditUser", err)
|
ctx.Handle(500, "admin.user.EditUser", err)
|
||||||
return
|
return
|
||||||
|
@ -126,7 +149,7 @@ func DeleteUser(ctx *middleware.Context, params martini.Params) {
|
||||||
ctx.Data["Title"] = "Delete Account"
|
ctx.Data["Title"] = "Delete Account"
|
||||||
ctx.Data["PageIsUsers"] = true
|
ctx.Data["PageIsUsers"] = true
|
||||||
|
|
||||||
log.Info("delete")
|
//log.Info("delete")
|
||||||
uid, err := base.StrTo(params["userid"]).Int()
|
uid, err := base.StrTo(params["userid"]).Int()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(404, "admin.user.EditUser", err)
|
ctx.Handle(404, "admin.user.EditUser", err)
|
||||||
|
|
43
templates/admin/auths.tmpl
Normal file
43
templates/admin/auths.tmpl
Normal file
|
@ -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" .}}
|
107
templates/admin/auths/edit.tmpl
Normal file
107
templates/admin/auths/edit.tmpl
Normal file
|
@ -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" .}}
|
94
templates/admin/auths/new.tmpl
Normal file
94
templates/admin/auths/new.tmpl
Normal file
|
@ -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" .}}
|
|
@ -4,5 +4,6 @@
|
||||||
<li class="list-group-item{{if .PageIsUsers}} active{{end}}"><a href="/admin/users"><i class="fa fa-users fa-lg"></i> Users</a></li>
|
<li class="list-group-item{{if .PageIsUsers}} active{{end}}"><a href="/admin/users"><i class="fa fa-users fa-lg"></i> Users</a></li>
|
||||||
<li class="list-group-item{{if .PageIsRepos}} active{{end}}"><a href="/admin/repos"><i class="fa fa-book fa-lg"></i> Repositories</a></li>
|
<li class="list-group-item{{if .PageIsRepos}} active{{end}}"><a href="/admin/repos"><i class="fa fa-book fa-lg"></i> Repositories</a></li>
|
||||||
<li class="list-group-item{{if .PageIsConfig}} active{{end}}"><a href="/admin/config"><i class="fa fa-cogs fa-lg"></i> Configuration</a></li>
|
<li class="list-group-item{{if .PageIsConfig}} active{{end}}"><a href="/admin/config"><i class="fa fa-cogs fa-lg"></i> Configuration</a></li>
|
||||||
|
<li class="list-group-item{{if .PageIsAuths}} active{{end}}"><a href="/admin/auths"><i class="fa fa-cogs fa-lg"></i> Authentication</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
|
@ -14,6 +14,18 @@
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
<input type="hidden" value="{{.User.Id}}" name="userId"/>
|
<input type="hidden" value="{{.User.Id}}" name="userId"/>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">Auth Source: </label>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<select name="logintype" class="form-control">
|
||||||
|
<option value="0-0"{{if eq 0 .User.LoginSource}} selected{{end}}>Local</option>
|
||||||
|
{{$tp := .User.LoginSource}}
|
||||||
|
{{range $key, $val := .LoginSources}}
|
||||||
|
<option value="{{$val.Type}}-{{$val.Id}}"{{if eq $val.Id $tp}} selected{{end}}>{{$val.Name}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-md-3 control-label">Username: </label>
|
<label class="col-md-3 control-label">Username: </label>
|
||||||
<label class="control-label">{{.User.Name}}</label>
|
<label class="control-label">{{.User.Name}}</label>
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
<form action="/admin/users/new" method="post" class="form-horizontal">
|
<form action="/admin/users/new" method="post" class="form-horizontal">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
{{template "base/alert" .}}
|
{{template "base/alert" .}}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">Auth Source: </label>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<select name="logintype" class="form-control">
|
||||||
|
<option value="0-0">Local</option>
|
||||||
|
{{range $key, $val := .LoginSources}}
|
||||||
|
<option value="{{$val.Type}}-{{$val.Id}}">{{$val.Name}}</option>
|
||||||
|
{{end}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
|
<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}">
|
||||||
<label class="col-md-3 control-label">Username: </label>
|
<label class="col-md-3 control-label">Username: </label>
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
|
|
Loading…
Reference in a new issue