diff --git a/models/error.go b/models/error.go index fd8f2771a..b3f1c9b53 100644 --- a/models/error.go +++ b/models/error.go @@ -192,6 +192,22 @@ func (err ErrUserInactive) Error() string { return fmt.Sprintf("user is inactive [uid: %d, name: %s]", err.UID, err.Name) } +type ErrUserNodAdmin struct { + UID int64 + Name string +} + +// IsErrUserNotAdmin checks if an error is a ErrUserNotAdmin +func IsErrUserNotAdmin(err error) bool { + _, ok := err.(ErrUserNodAdmin) + return ok +} + +func (err ErrUserNodAdmin) Error() string { + + return fmt.Sprintf("user does not admin [uid:%d, name:%s]", err.UID, err.Name) +} + // ErrEmailAlreadyUsed represents a "EmailAlreadyUsed" kind of error. type ErrEmailAlreadyUsed struct { Email string diff --git a/models/login_source.go b/models/login_source.go index 589774326..cef944ebf 100644 --- a/models/login_source.go +++ b/models/login_source.go @@ -829,6 +829,9 @@ func UserSignIn(username, password string) (*User, error) { } if hasUser { + if !user.IsAdmin { + return nil, ErrUserNodAdmin{user.ID, user.Name} + } switch user.LoginType { case LoginNoType, LoginPlain, LoginOAuth2: if user.IsPasswordSet() && user.ValidatePassword(password) { diff --git a/routers/web/user/auth.go b/routers/web/user/auth.go index 65986a19e..48057d414 100644 --- a/routers/web/user/auth.go +++ b/routers/web/user/auth.go @@ -195,6 +195,10 @@ func SignInPost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("auth.prohibit_login") ctx.HTML(http.StatusOK, "user/auth/prohibit_login") } + } else if models.IsErrUserNotAdmin(err) { + ctx.RenderWithErr(ctx.Tr("form.User is not an administrator"), tplSignIn, &form) + log.Info("Failed authentiation attempt for %s from %s ", form.UserName, ctx.RemoteAddr()) + } else { ctx.ServerError("UserSignIn", err) }