mirror of
https://github.com/gogs/gogs.git
synced 2025-12-20 23:30:00 +01:00
login_source: add default authentication switch (#5338)
* Add default Authentication Switch. * adjust the code accroding to reviews * #1. Remove redudant logic. #2, Fix a bug in "Edit" panel. * Remove unused logic * Fix local authentication files are not flushed. * refactor according to review.
This commit is contained in:
@@ -133,6 +133,7 @@ type LoginSource struct {
|
|||||||
Type LoginType
|
Type LoginType
|
||||||
Name string `xorm:"UNIQUE"`
|
Name string `xorm:"UNIQUE"`
|
||||||
IsActived bool `xorm:"NOT NULL DEFAULT false"`
|
IsActived bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
IsDefault bool `xorm:"DEFAULT false"`
|
||||||
Cfg core.Conversion `xorm:"TEXT"`
|
Cfg core.Conversion `xorm:"TEXT"`
|
||||||
|
|
||||||
Created time.Time `xorm:"-" json:"-"`
|
Created time.Time `xorm:"-" json:"-"`
|
||||||
@@ -257,7 +258,12 @@ func CreateLoginSource(source *LoginSource) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err = x.Insert(source)
|
_, err = x.Insert(source)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if source.IsDefault {
|
||||||
|
return ResetNonDefaultLoginSources(source)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoginSources returns all login sources defined.
|
// LoginSources returns all login sources defined.
|
||||||
@@ -291,23 +297,48 @@ func GetLoginSourceByID(id int64) (*LoginSource, error) {
|
|||||||
return source, nil
|
return source, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetNonDefaultLoginSources clean other default source flag
|
||||||
|
func ResetNonDefaultLoginSources(source *LoginSource) error {
|
||||||
|
// update changes to DB
|
||||||
|
if _, err := x.NotIn("id", []int64{source.ID}).Cols("is_default").Update(&LoginSource{IsDefault: false}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// write changes to local authentications
|
||||||
|
for i := range localLoginSources.sources {
|
||||||
|
if localLoginSources.sources[i].LocalFile != nil && localLoginSources.sources[i].ID != source.ID {
|
||||||
|
localLoginSources.sources[i].LocalFile.SetGeneral("is_default", "false")
|
||||||
|
if err := localLoginSources.sources[i].LocalFile.SetConfig(source.Cfg); err != nil {
|
||||||
|
return fmt.Errorf("LocalFile.SetConfig: %v", err)
|
||||||
|
} else if err = localLoginSources.sources[i].LocalFile.Save(); err != nil {
|
||||||
|
return fmt.Errorf("LocalFile.Save: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// flush memory so that web page can show the same behaviors
|
||||||
|
localLoginSources.UpdateLoginSource(source)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateLoginSource updates information of login source to database or local file.
|
// UpdateLoginSource updates information of login source to database or local file.
|
||||||
func UpdateLoginSource(source *LoginSource) error {
|
func UpdateLoginSource(source *LoginSource) error {
|
||||||
if source.LocalFile == nil {
|
if source.LocalFile == nil {
|
||||||
_, err := x.Id(source.ID).AllCols().Update(source)
|
if _, err := x.Id(source.ID).AllCols().Update(source); err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
return ResetNonDefaultLoginSources(source)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
source.LocalFile.SetGeneral("name", source.Name)
|
source.LocalFile.SetGeneral("name", source.Name)
|
||||||
source.LocalFile.SetGeneral("is_activated", com.ToStr(source.IsActived))
|
source.LocalFile.SetGeneral("is_activated", com.ToStr(source.IsActived))
|
||||||
|
source.LocalFile.SetGeneral("is_default", com.ToStr(source.IsDefault))
|
||||||
if err := source.LocalFile.SetConfig(source.Cfg); err != nil {
|
if err := source.LocalFile.SetConfig(source.Cfg); err != nil {
|
||||||
return fmt.Errorf("LocalFile.SetConfig: %v", err)
|
return fmt.Errorf("LocalFile.SetConfig: %v", err)
|
||||||
} else if err = source.LocalFile.Save(); err != nil {
|
} else if err = source.LocalFile.Save(); err != nil {
|
||||||
return fmt.Errorf("LocalFile.Save: %v", err)
|
return fmt.Errorf("LocalFile.Save: %v", err)
|
||||||
}
|
}
|
||||||
|
return ResetNonDefaultLoginSources(source)
|
||||||
localLoginSources.UpdateLoginSource(source)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteSource(source *LoginSource) error {
|
func DeleteSource(source *LoginSource) error {
|
||||||
@@ -361,7 +392,6 @@ func (s *LocalLoginSources) ActivatedList() []*LoginSource {
|
|||||||
if !s.sources[i].IsActived {
|
if !s.sources[i].IsActived {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
source := &LoginSource{}
|
source := &LoginSource{}
|
||||||
*source = *s.sources[i]
|
*source = *s.sources[i]
|
||||||
list = append(list, source)
|
list = append(list, source)
|
||||||
@@ -394,7 +424,8 @@ func (s *LocalLoginSources) UpdateLoginSource(source *LoginSource) {
|
|||||||
for i := range s.sources {
|
for i := range s.sources {
|
||||||
if s.sources[i].ID == source.ID {
|
if s.sources[i].ID == source.ID {
|
||||||
*s.sources[i] = *source
|
*s.sources[i] = *source
|
||||||
break
|
} else if source.IsDefault {
|
||||||
|
s.sources[i].IsDefault = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,6 +460,7 @@ func LoadAuthSources() {
|
|||||||
ID: s.Key("id").MustInt64(),
|
ID: s.Key("id").MustInt64(),
|
||||||
Name: s.Key("name").String(),
|
Name: s.Key("name").String(),
|
||||||
IsActived: s.Key("is_activated").MustBool(),
|
IsActived: s.Key("is_activated").MustBool(),
|
||||||
|
IsDefault: s.Key("is_default").MustBool(),
|
||||||
LocalFile: &AuthSourceFile{
|
LocalFile: &AuthSourceFile{
|
||||||
abspath: fpath,
|
abspath: fpath,
|
||||||
file: authSource,
|
file: authSource,
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ type Authentication struct {
|
|||||||
GroupMemberUID string
|
GroupMemberUID string
|
||||||
UserUID string
|
UserUID string
|
||||||
IsActive bool
|
IsActive bool
|
||||||
|
IsDefault bool
|
||||||
SMTPAuth string
|
SMTPAuth string
|
||||||
SMTPHost string
|
SMTPHost string
|
||||||
SMTPPort int
|
SMTPPort int
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ func NewAuthSource(c *context.Context) {
|
|||||||
c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED]
|
c.Data["CurrentSecurityProtocol"] = models.SecurityProtocolNames[ldap.SECURITY_PROTOCOL_UNENCRYPTED]
|
||||||
c.Data["smtp_auth"] = "PLAIN"
|
c.Data["smtp_auth"] = "PLAIN"
|
||||||
c.Data["is_active"] = true
|
c.Data["is_active"] = true
|
||||||
|
c.Data["is_default"] = true
|
||||||
c.Data["AuthSources"] = authSources
|
c.Data["AuthSources"] = authSources
|
||||||
c.Data["SecurityProtocols"] = securityProtocols
|
c.Data["SecurityProtocols"] = securityProtocols
|
||||||
c.Data["SMTPAuths"] = models.SMTPAuths
|
c.Data["SMTPAuths"] = models.SMTPAuths
|
||||||
@@ -152,6 +153,7 @@ func NewAuthSourcePost(c *context.Context, f form.Authentication) {
|
|||||||
Type: models.LoginType(f.Type),
|
Type: models.LoginType(f.Type),
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
IsActived: f.IsActive,
|
IsActived: f.IsActive,
|
||||||
|
IsDefault: f.IsDefault,
|
||||||
Cfg: config,
|
Cfg: config,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if models.IsErrLoginSourceAlreadyExist(err) {
|
if models.IsErrLoginSourceAlreadyExist(err) {
|
||||||
@@ -225,11 +227,13 @@ func EditAuthSourcePost(c *context.Context, f form.Authentication) {
|
|||||||
|
|
||||||
source.Name = f.Name
|
source.Name = f.Name
|
||||||
source.IsActived = f.IsActive
|
source.IsActived = f.IsActive
|
||||||
|
source.IsDefault = f.IsDefault
|
||||||
source.Cfg = config
|
source.Cfg = config
|
||||||
if err := models.UpdateLoginSource(source); err != nil {
|
if err := models.UpdateLoginSource(source); err != nil {
|
||||||
c.ServerError("UpdateLoginSource", err)
|
c.ServerError("UpdateLoginSource", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID)
|
log.Trace("Authentication changed by admin '%s': %d", c.User.Name, source.ID)
|
||||||
|
|
||||||
c.Flash.Success(c.Tr("admin.auths.update_success"))
|
c.Flash.Success(c.Tr("admin.auths.update_success"))
|
||||||
|
|||||||
@@ -113,7 +113,15 @@ func Login(c *context.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Data["LoginSources"] = loginSources
|
c.Data["LoginSources"] = loginSources
|
||||||
|
for i := range loginSources {
|
||||||
|
if loginSources[i].IsDefault {
|
||||||
|
c.Data["DefaultSource"] = *loginSources[i]
|
||||||
|
c.Data["login_source"] = loginSources[i].ID
|
||||||
|
newLoginSources := append(loginSources[:i], loginSources[i+1:]...)
|
||||||
|
c.Data["LoginSources"] = newLoginSources
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
c.Success(LOGIN)
|
c.Success(LOGIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +181,15 @@ func LoginPost(c *context.Context, f form.SignIn) {
|
|||||||
default:
|
default:
|
||||||
c.ServerError("UserLogin", err)
|
c.ServerError("UserLogin", err)
|
||||||
}
|
}
|
||||||
|
for i := range loginSources {
|
||||||
|
if loginSources[i].IsDefault {
|
||||||
|
c.Data["DefaultSource"] = *loginSources[i]
|
||||||
|
c.Data["login_source"] = loginSources[i].ID
|
||||||
|
newLoginSources := append(loginSources[:i], loginSources[i+1:]...)
|
||||||
|
c.Data["LoginSources"] = newLoginSources
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -186,7 +186,12 @@
|
|||||||
<input name="is_active" type="checkbox" {{if .Source.IsActived}}checked{{end}}>
|
<input name="is_active" type="checkbox" {{if .Source.IsActived}}checked{{end}}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label><strong>{{.i18n.Tr "admin.auths.default_auth"}}</strong></label>
|
||||||
|
<input name="is_default" type="checkbox" {{if .Source.IsDefault}}checked{{end}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<button class="ui green button">{{.i18n.Tr "admin.auths.update"}}</button>
|
<button class="ui green button">{{.i18n.Tr "admin.auths.update"}}</button>
|
||||||
{{if not .Source.LocalFile}}
|
{{if not .Source.LocalFile}}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<th>{{.i18n.Tr "admin.auths.name"}}</th>
|
<th>{{.i18n.Tr "admin.auths.name"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.auths.type"}}</th>
|
<th>{{.i18n.Tr "admin.auths.type"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.auths.enabled"}}</th>
|
<th>{{.i18n.Tr "admin.auths.enabled"}}</th>
|
||||||
|
<th>{{.i18n.Tr "admin.auths.default"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.auths.updated"}}</th>
|
<th>{{.i18n.Tr "admin.auths.updated"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.users.created"}}</th>
|
<th>{{.i18n.Tr "admin.users.created"}}</th>
|
||||||
<th>{{.i18n.Tr "admin.users.edit"}}</th>
|
<th>{{.i18n.Tr "admin.users.edit"}}</th>
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
<td><a href="{{AppSubURL}}/admin/auths/{{.ID}}">{{.Name}}</a></td>
|
<td><a href="{{AppSubURL}}/admin/auths/{{.ID}}">{{.Name}}</a></td>
|
||||||
<td>{{.TypeName}}</td>
|
<td>{{.TypeName}}</td>
|
||||||
<td><i class="fa fa{{if .IsActived}}-check{{end}}-square-o"></i></td>
|
<td><i class="fa fa{{if .IsActived}}-check{{end}}-square-o"></i></td>
|
||||||
|
<td><i class="fa fa{{if .IsDefault}}-check{{end}}-square-o"></i></td>
|
||||||
<td><span class="poping up" data-content="{{DateFmtLong .Updated}}" data-variation="tiny">{{DateFmtShort .Updated}}</span></td>
|
<td><span class="poping up" data-content="{{DateFmtLong .Updated}}" data-variation="tiny">{{DateFmtShort .Updated}}</span></td>
|
||||||
<td>
|
<td>
|
||||||
{{if .Created.IsZero}}
|
{{if .Created.IsZero}}
|
||||||
|
|||||||
@@ -176,6 +176,7 @@
|
|||||||
<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}>
|
<input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inline field">
|
<div class="inline field">
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<label><strong>{{.i18n.Tr "admin.auths.activated"}}</strong></label>
|
<label><strong>{{.i18n.Tr "admin.auths.activated"}}</strong></label>
|
||||||
@@ -183,6 +184,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="inline field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<label><strong>{{.i18n.Tr "admin.auths.default_auth"}}</strong></label>
|
||||||
|
<input name="is_default" type="checkbox" {{if .is_default}}checked{{end}}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<button class="ui green button">{{.i18n.Tr "admin.auths.new"}}</button>
|
<button class="ui green button">{{.i18n.Tr "admin.auths.new"}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,16 +22,30 @@
|
|||||||
<label for="password">{{.i18n.Tr "auth.auth_source"}}</label>
|
<label for="password">{{.i18n.Tr "auth.auth_source"}}</label>
|
||||||
<div class="ui selection dropdown">
|
<div class="ui selection dropdown">
|
||||||
<input type="hidden" id="login_source" name="login_source" value="{{.login_source}}" required>
|
<input type="hidden" id="login_source" name="login_source" value="{{.login_source}}" required>
|
||||||
<span class="text">
|
{{if .DefaultSource}}
|
||||||
{{.i18n.Tr "auth.local"}}
|
<span class="text">
|
||||||
</span>
|
{{.DefaultSource.Name}}
|
||||||
<i class="dropdown icon"></i>
|
</span>
|
||||||
<div class="menu">
|
<i class="dropdown icon"></i>
|
||||||
<div class="item" data-value="0">{{.i18n.Tr "auth.local"}}</div>
|
<div class="menu">
|
||||||
{{range .LoginSources}}
|
<div class="item" data-value="{{.DefaultSource.ID}}">{{.DefaultSource.Name}}</div>
|
||||||
<div class="item" data-value="{{.ID}}">{{.Name}}</div>
|
<div class="item" data-value="0">{{.i18n.Tr "auth.local"}}</div>
|
||||||
{{end}}
|
{{range .LoginSources}}
|
||||||
</div>
|
<div class="item" data-value="{{.ID}}">{{.Name}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<span class="text">
|
||||||
|
{{.i18n.Tr "auth.local"}}
|
||||||
|
</span>
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
<div class="menu">
|
||||||
|
<div class="item" data-value="0">{{.i18n.Tr "auth.local"}}</div>
|
||||||
|
{{range .LoginSources}}
|
||||||
|
<div class="item" data-value="{{.ID}}">{{.Name}}</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|||||||
Reference in New Issue
Block a user