From 01c7204895b78d5e48600316f25955821c1e6c99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=B5=B5=E6=99=BA=E8=B6=85?= <1012112796@qq.com>
Date: Mon, 5 Oct 2020 05:39:31 +0800
Subject: [PATCH] Return sample message for login error in api context (#12994)

* Return sample message for login error in api context

Signed-off-by: a1012112796 <1012112796@qq.com>

* Update modules/context/auth.go

Co-authored-by: silverwind <me@silverwind.io>

* Apply suggestions from code review

Co-authored-by: Lauris BH <lauris@nix.lv>

* Apply suggestions from code review

Co-authored-by: zeripath <art27@cantab.net>

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lauris BH <lauris@nix.lv>
Co-authored-by: zeripath <art27@cantab.net>
Co-authored-by: techknowlogick <techknowlogick@gitea.io>
---
 modules/context/auth.go | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/modules/context/auth.go b/modules/context/auth.go
index 14dfab7344..00a7032e27 100644
--- a/modules/context/auth.go
+++ b/modules/context/auth.go
@@ -32,20 +32,40 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 			return
 		}
 
+		isAPIPath := auth.IsAPIPath(ctx.Req.URL.Path)
+
 		// Check prohibit login users.
 		if ctx.IsSigned {
 			if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
 				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
+				if isAPIPath {
+					ctx.JSON(403, map[string]string{
+						"message": "This account is not activated.",
+					})
+					return
+				}
 				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")
+				if isAPIPath {
+					ctx.JSON(403, map[string]string{
+						"message": "This account is prohibited from signing in, please contact your site administrator.",
+					})
+					return
+				}
 				ctx.HTML(200, "user/auth/prohibit_login")
 				return
 			}
 
 			if ctx.User.MustChangePassword {
+				if isAPIPath {
+					ctx.JSON(403, map[string]string{
+						"message": "You must change your password. Change it at: " + setting.AppURL + "/user/change_password",
+					})
+					return
+				}
 				if ctx.Req.URL.Path != "/user/settings/change_password" {
 					ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
 					ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
@@ -78,7 +98,7 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 		if options.SignInRequired {
 			if !ctx.IsSigned {
 				// Restrict API calls with error message.
-				if auth.IsAPIPath(ctx.Req.URL.Path) {
+				if isAPIPath {
 					ctx.JSON(403, map[string]string{
 						"message": "Only signed in user is allowed to call APIs.",
 					})
@@ -94,7 +114,7 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 				ctx.HTML(200, "user/auth/activate")
 				return
 			}
-			if ctx.IsSigned && auth.IsAPIPath(ctx.Req.URL.Path) && ctx.IsBasicAuth {
+			if ctx.IsSigned && isAPIPath && ctx.IsBasicAuth {
 				twofa, err := models.GetTwoFactorByUID(ctx.User.ID)
 				if err != nil {
 					if models.IsErrTwoFactorNotEnrolled(err) {
@@ -119,7 +139,7 @@ func Toggle(options *ToggleOptions) macaron.Handler {
 		}
 
 		// Redirect to log in page if auto-signin info is provided and has not signed in.
-		if !options.SignOutRequired && !ctx.IsSigned && !auth.IsAPIPath(ctx.Req.URL.Path) &&
+		if !options.SignOutRequired && !ctx.IsSigned && !isAPIPath &&
 			len(ctx.GetCookie(setting.CookieUserName)) > 0 {
 			if ctx.Req.URL.Path != "/user/events" {
 				ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)