Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix prohibit login check on authorization (#6106) #6115

Merged
merged 2 commits into from Feb 19, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions integrations/release_test.go
Expand Up @@ -112,7 +112,7 @@ func TestCreateReleasePaging(t *testing.T) {

checkLatestReleaseAndCount(t, session, "/user2/repo1", "v0.0.12", i18n.Tr("en", "repo.release.draft"), 10)

// Check that user3 does not see draft and still see 10 latest releases
session2 := loginUser(t, "user3")
// Check that user4 does not see draft and still see 10 latest releases
session2 := loginUser(t, "user4")
checkLatestReleaseAndCount(t, session2, "/user2/repo1", "v0.0.11", i18n.Tr("en", "repo.release.stable"), 10)
}
20 changes: 20 additions & 0 deletions integrations/repo_test.go
Expand Up @@ -99,3 +99,23 @@ func TestViewRepoWithSymlinks(t *testing.T) {
assert.Equal(t, items[3], "link_hi: octicon octicon-file-symlink-file")
assert.Equal(t, items[4], "link_link: octicon octicon-file-symlink-file")
}

// TestViewAsRepoAdmin tests PR #2167
func TestViewAsRepoAdmin(t *testing.T) {
for user, expectedNoDescription := range map[string]bool{
"user2": true,
"user4": false,
} {
prepareTestEnv(t)

session := loginUser(t, user)

req := NewRequest(t, "GET", "/user2/repo1.git")
resp := session.MakeRequest(t, req, http.StatusOK)

htmlDoc := NewHTMLParser(t, resp.Body)
noDescription := htmlDoc.doc.Find("#repo-desc").Children()

assert.Equal(t, expectedNoDescription, noDescription.HasClass("no-description"))
}
}
32 changes: 32 additions & 0 deletions models/error.go
Expand Up @@ -90,6 +90,38 @@ func (err ErrUserNotExist) Error() string {
return fmt.Sprintf("user does not exist [uid: %d, name: %s, keyid: %d]", err.UID, err.Name, err.KeyID)
}

// ErrUserProhibitLogin represents a "ErrUserProhibitLogin" kind of error.
type ErrUserProhibitLogin struct {
UID int64
Name string
}

// IsErrUserProhibitLogin checks if an error is a ErrUserProhibitLogin
func IsErrUserProhibitLogin(err error) bool {
_, ok := err.(ErrUserProhibitLogin)
return ok
}

func (err ErrUserProhibitLogin) Error() string {
return fmt.Sprintf("user is not allowed login [uid: %d, name: %s]", err.UID, err.Name)
}

// ErrUserInactive represents a "ErrUserInactive" kind of error.
type ErrUserInactive struct {
UID int64
Name string
}

// IsErrUserInactive checks if an error is a ErrUserInactive
func IsErrUserInactive(err error) bool {
_, ok := err.(ErrUserInactive)
return ok
}

func (err ErrUserInactive) Error() string {
return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name)
}

// ErrEmailAlreadyUsed represents a "EmailAlreadyUsed" kind of error.
type ErrEmailAlreadyUsed struct {
Email string
Expand Down
27 changes: 23 additions & 4 deletions models/login_source.go
Expand Up @@ -600,16 +600,29 @@ func ExternalUserLogin(user *User, login, password string, source *LoginSource,
return nil, ErrLoginSourceNotActived
}

var err error
switch source.Type {
case LoginLDAP, LoginDLDAP:
return LoginViaLDAP(user, login, password, source, autoRegister)
user, err = LoginViaLDAP(user, login, password, source, autoRegister)
case LoginSMTP:
return LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
user, err = LoginViaSMTP(user, login, password, source.ID, source.Cfg.(*SMTPConfig), autoRegister)
case LoginPAM:
return LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
user, err = LoginViaPAM(user, login, password, source.ID, source.Cfg.(*PAMConfig), autoRegister)
default:
return nil, ErrUnsupportedLoginType
}

if err != nil {
return nil, err
}

if !user.IsActive {
return nil, ErrUserInactive{user.ID, user.Name}
} else if user.ProhibitLogin {
return nil, ErrUserProhibitLogin{user.ID, user.Name}
}

return nil, ErrUnsupportedLoginType
return user, nil
}

// UserSignIn validates user name and password.
Expand Down Expand Up @@ -645,6 +658,12 @@ func UserSignIn(username, password string) (*User, error) {
switch user.LoginType {
case LoginNoType, LoginPlain, LoginOAuth2:
if user.IsPasswordSet() && user.ValidatePassword(password) {
if !user.IsActive {
return nil, ErrUserInactive{user.ID, user.Name}
} else if user.ProhibitLogin {
return nil, ErrUserProhibitLogin{user.ID, user.Name}
}

return user, nil
}

Expand Down
9 changes: 7 additions & 2 deletions modules/context/auth.go
Expand Up @@ -8,6 +8,7 @@ import (
"net/url"

"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/go-macaron/csrf"
macaron "gopkg.in/macaron.v1"
Expand All @@ -32,8 +33,12 @@ func Toggle(options *ToggleOptions) macaron.Handler {

// Check prohibit login users.
if ctx.IsSigned {

if ctx.User.ProhibitLogin {
if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(200, "user/auth/activate")
return
} else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(200, "user/auth/prohibit_login")
return
Expand Down
5 changes: 5 additions & 0 deletions routers/home.go
Expand Up @@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/search"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
Expand Down Expand Up @@ -38,6 +39,10 @@ func Home(ctx *context.Context) {
if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(200, user.TplActivate)
} else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(200, "user/auth/prohibit_login")
} else {
user.Dashboard(ctx)
}
Expand Down
13 changes: 13 additions & 0 deletions routers/user/auth.go
Expand Up @@ -161,6 +161,19 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) {
} else if models.IsErrEmailAlreadyUsed(err) {
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSignIn, &form)
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
} else if models.IsErrUserProhibitLogin(err) {
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(200, "user/auth/prohibit_login")
} else if models.IsErrUserInactive(err) {
if setting.Service.RegisterEmailConfirm {
ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
ctx.HTML(200, TplActivate)
} else {
log.Info("Failed authentication attempt for %s from %s", form.UserName, ctx.RemoteAddr())
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
ctx.HTML(200, "user/auth/prohibit_login")
}
} else {
ctx.ServerError("UserSignIn", err)
}
Expand Down