From 80fd25524e13dedbdc3527b32d008de152213a89 Mon Sep 17 00:00:00 2001
From: KN4CK3R <admin@oldschoolhack.me>
Date: Tue, 22 Mar 2022 08:03:22 +0100
Subject: [PATCH] Renamed ctx.User to ctx.Doer. (#19161)

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
---
 integrations/repofiles_delete_test.go         |   6 +-
 integrations/repofiles_update_test.go         |  10 +-
 modules/context/api.go                        |  20 +--
 modules/context/auth.go                       |  26 +--
 modules/context/context.go                    |  22 +--
 modules/context/org.go                        |  12 +-
 modules/context/permission.go                 |   4 +-
 modules/context/repo.go                       |  24 +--
 modules/test/context_tests.go                 |   4 +-
 routers/api/v1/admin/adopt.go                 |   4 +-
 routers/api/v1/admin/cron.go                  |   2 +-
 routers/api/v1/admin/org.go                   |   2 +-
 routers/api/v1/admin/user.go                  |  16 +-
 routers/api/v1/api.go                         |  30 ++--
 routers/api/v1/notify/notifications.go        |   4 +-
 routers/api/v1/notify/repo.go                 |   4 +-
 routers/api/v1/notify/threads.go              |   4 +-
 routers/api/v1/notify/user.go                 |   4 +-
 routers/api/v1/org/member.go                  |  20 +--
 routers/api/v1/org/org.go                     |  14 +-
 routers/api/v1/org/team.go                    |  16 +-
 routers/api/v1/repo/branch.go                 |  10 +-
 routers/api/v1/repo/collaborators.go          |   8 +-
 routers/api/v1/repo/file.go                   |  10 +-
 routers/api/v1/repo/fork.go                   |   8 +-
 routers/api/v1/repo/hook.go                   |   4 +-
 routers/api/v1/repo/issue.go                  |  30 ++--
 routers/api/v1/repo/issue_comment.go          |  16 +-
 routers/api/v1/repo/issue_label.go            |   8 +-
 routers/api/v1/repo/issue_reaction.go         |  20 +--
 routers/api/v1/repo/issue_stopwatch.go        |  14 +-
 routers/api/v1/repo/issue_subscription.go     |   8 +-
 routers/api/v1/repo/issue_tracked_time.go     |  30 ++--
 routers/api/v1/repo/key.go                    |   6 +-
 routers/api/v1/repo/migrate.go                |  20 +--
 routers/api/v1/repo/patch.go                  |   4 +-
 routers/api/v1/repo/pull.go                   |  60 +++----
 routers/api/v1/repo/pull_review.go            |  42 ++---
 routers/api/v1/repo/release.go                |  14 +-
 routers/api/v1/repo/release_attachment.go     |   2 +-
 routers/api/v1/repo/release_tags.go           |   2 +-
 routers/api/v1/repo/repo.go                   |  38 ++---
 routers/api/v1/repo/repo_test.go              |   4 +-
 routers/api/v1/repo/star.go                   |   2 +-
 routers/api/v1/repo/status.go                 |   2 +-
 routers/api/v1/repo/subscriber.go             |   2 +-
 routers/api/v1/repo/tag.go                    |   4 +-
 routers/api/v1/repo/transfer.go               |   6 +-
 routers/api/v1/repo/wiki.go                   |   6 +-
 routers/api/v1/user/app.go                    |  16 +-
 routers/api/v1/user/email.go                  |   6 +-
 routers/api/v1/user/follower.go               |  12 +-
 routers/api/v1/user/gpg_key.go                |  20 +--
 routers/api/v1/user/key.go                    |  16 +-
 routers/api/v1/user/repo.go                   |  10 +-
 routers/api/v1/user/settings.go               |  24 +--
 routers/api/v1/user/star.go                   |  12 +-
 routers/api/v1/user/user.go                   |  12 +-
 routers/api/v1/user/watch.go                  |  10 +-
 routers/web/admin/admin.go                    |   2 +-
 routers/web/admin/auths.go                    |   6 +-
 routers/web/admin/emails.go                   |   2 +-
 routers/web/admin/notice.go                   |   2 +-
 routers/web/admin/orgs.go                     |   2 +-
 routers/web/admin/repos.go                    |   6 +-
 routers/web/admin/users.go                    |  10 +-
 routers/web/admin/users_test.go               |  10 +-
 routers/web/auth/auth.go                      |  12 +-
 routers/web/auth/oauth.go                     |  20 +--
 routers/web/auth/password.go                  |   8 +-
 routers/web/events/events.go                  |  10 +-
 routers/web/explore/code.go                   |  14 +-
 routers/web/explore/org.go                    |   4 +-
 routers/web/explore/repo.go                   |   8 +-
 routers/web/explore/user.go                   |   2 +-
 routers/web/feed/profile.go                   |   2 +-
 routers/web/feed/repo.go                      |   2 +-
 routers/web/home.go                           |   8 +-
 routers/web/org/home.go                       |  10 +-
 routers/web/org/members.go                    |  12 +-
 routers/web/org/org.go                        |   6 +-
 routers/web/org/setting.go                    |   2 +-
 routers/web/org/teams.go                      |   4 +-
 routers/web/repo/attachment.go                |   8 +-
 routers/web/repo/branch.go                    |  16 +-
 routers/web/repo/cherry_pick.go               |   4 +-
 routers/web/repo/compare.go                   |  24 +--
 routers/web/repo/editor.go                    |  10 +-
 routers/web/repo/http.go                      |  16 +-
 routers/web/repo/issue.go                     | 154 +++++++++---------
 routers/web/repo/issue_content_history.go     |   4 +-
 routers/web/repo/issue_dependency.go          |   8 +-
 routers/web/repo/issue_label.go               |  10 +-
 routers/web/repo/issue_lock.go                |   4 +-
 routers/web/repo/issue_stopwatch.go           |  12 +-
 routers/web/repo/issue_timetrack.go           |   8 +-
 routers/web/repo/issue_watch.go               |   6 +-
 routers/web/repo/lfs.go                       |   8 +-
 routers/web/repo/middlewares.go               |   8 +-
 routers/web/repo/migrate.go                   |   8 +-
 routers/web/repo/patch.go                     |   2 +-
 routers/web/repo/projects.go                  |  12 +-
 routers/web/repo/pull.go                      |  60 +++----
 routers/web/repo/pull_review.go               |  16 +-
 routers/web/repo/release.go                   |  20 +--
 routers/web/repo/repo.go                      |  40 ++---
 routers/web/repo/setting.go                   |  26 +--
 routers/web/repo/setting_protected_branch.go  |   2 +-
 routers/web/repo/topic.go                     |   2 +-
 routers/web/repo/view.go                      |   6 +-
 routers/web/repo/webhook.go                   |   4 +-
 routers/web/repo/wiki.go                      |   8 +-
 routers/web/user/home.go                      |  22 +--
 routers/web/user/home_test.go                 |   2 +-
 routers/web/user/notification.go              |  10 +-
 routers/web/user/profile.go                   |  26 +--
 routers/web/user/setting/account.go           |  62 +++----
 routers/web/user/setting/adopt.go             |   2 +-
 routers/web/user/setting/applications.go      |  10 +-
 routers/web/user/setting/keys.go              |  44 ++---
 routers/web/user/setting/oauth2.go            |  16 +-
 routers/web/user/setting/profile.go           |  60 +++----
 routers/web/user/setting/security/2fa.go      |  16 +-
 routers/web/user/setting/security/openid.go   |  10 +-
 routers/web/user/setting/security/security.go |  12 +-
 routers/web/user/setting/security/webauthn.go |  12 +-
 routers/web/user/task.go                      |   2 +-
 services/lfs/locks.go                         |  10 +-
 services/lfs/server.go                        |  10 +-
 129 files changed, 881 insertions(+), 881 deletions(-)

diff --git a/integrations/repofiles_delete_test.go b/integrations/repofiles_delete_test.go
index 09794f8c9..a6c2484a5 100644
--- a/integrations/repofiles_delete_test.go
+++ b/integrations/repofiles_delete_test.go
@@ -77,7 +77,7 @@ func testDeleteRepoFile(t *testing.T, u *url.URL) {
 	test.LoadGitRepo(t, ctx)
 	defer ctx.Repo.GitRepo.Close()
 	repo := ctx.Repo.Repository
-	doer := ctx.User
+	doer := ctx.Doer
 	opts := getDeleteRepoFileOptions(repo)
 
 	t.Run("Delete README.md file", func(t *testing.T) {
@@ -117,7 +117,7 @@ func testDeleteRepoFileWithoutBranchNames(t *testing.T, u *url.URL) {
 	defer ctx.Repo.GitRepo.Close()
 
 	repo := ctx.Repo.Repository
-	doer := ctx.User
+	doer := ctx.Doer
 	opts := getDeleteRepoFileOptions(repo)
 	opts.OldBranch = ""
 	opts.NewBranch = ""
@@ -147,7 +147,7 @@ func TestDeleteRepoFileErrors(t *testing.T) {
 	defer ctx.Repo.GitRepo.Close()
 
 	repo := ctx.Repo.Repository
-	doer := ctx.User
+	doer := ctx.Doer
 
 	t.Run("Bad branch", func(t *testing.T) {
 		opts := getDeleteRepoFileOptions(repo)
diff --git a/integrations/repofiles_update_test.go b/integrations/repofiles_update_test.go
index 46c73b48f..bb11a048e 100644
--- a/integrations/repofiles_update_test.go
+++ b/integrations/repofiles_update_test.go
@@ -194,7 +194,7 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
 		defer ctx.Repo.GitRepo.Close()
 
 		repo := ctx.Repo.Repository
-		doer := ctx.User
+		doer := ctx.Doer
 		opts := getCreateRepoFileOptions(repo)
 
 		// test
@@ -230,7 +230,7 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
 		defer ctx.Repo.GitRepo.Close()
 
 		repo := ctx.Repo.Repository
-		doer := ctx.User
+		doer := ctx.Doer
 		opts := getUpdateRepoFileOptions(repo)
 
 		// test
@@ -263,7 +263,7 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
 		defer ctx.Repo.GitRepo.Close()
 
 		repo := ctx.Repo.Repository
-		doer := ctx.User
+		doer := ctx.Doer
 		opts := getUpdateRepoFileOptions(repo)
 		opts.FromTreePath = "README.md"
 		opts.TreePath = "README_new.md" // new file name, README_new.md
@@ -313,7 +313,7 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
 		defer ctx.Repo.GitRepo.Close()
 
 		repo := ctx.Repo.Repository
-		doer := ctx.User
+		doer := ctx.Doer
 		opts := getUpdateRepoFileOptions(repo)
 		opts.OldBranch = ""
 		opts.NewBranch = ""
@@ -344,7 +344,7 @@ func TestCreateOrUpdateRepoFileErrors(t *testing.T) {
 		defer ctx.Repo.GitRepo.Close()
 
 		repo := ctx.Repo.Repository
-		doer := ctx.User
+		doer := ctx.Doer
 
 		t.Run("bad branch", func(t *testing.T) {
 			opts := getUpdateRepoFileOptions(repo)
diff --git a/modules/context/api.go b/modules/context/api.go
index c825e4875..c1b31dcff 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -100,7 +100,7 @@ func (ctx *APIContext) Error(status int, title string, obj interface{}) {
 	if status == http.StatusInternalServerError {
 		log.ErrorWithSkip(1, "%s: %s", title, message)
 
-		if setting.IsProd && !(ctx.User != nil && ctx.User.IsAdmin) {
+		if setting.IsProd && !(ctx.Doer != nil && ctx.Doer.IsAdmin) {
 			message = ""
 		}
 	}
@@ -117,7 +117,7 @@ func (ctx *APIContext) InternalServerError(err error) {
 	log.ErrorWithSkip(1, "InternalServerError: %v", err)
 
 	var message string
-	if !setting.IsProd || (ctx.User != nil && ctx.User.IsAdmin) {
+	if !setting.IsProd || (ctx.Doer != nil && ctx.Doer.IsAdmin) {
 		message = err.Error()
 	}
 
@@ -225,7 +225,7 @@ func (ctx *APIContext) CheckForOTP() {
 	}
 
 	otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
-	twofa, err := auth.GetTwoFactorByUID(ctx.Context.User.ID)
+	twofa, err := auth.GetTwoFactorByUID(ctx.Context.Doer.ID)
 	if err != nil {
 		if auth.IsErrTwoFactorNotEnrolled(err) {
 			return // No 2FA enrollment for this user
@@ -248,18 +248,18 @@ func (ctx *APIContext) CheckForOTP() {
 func APIAuth(authMethod auth_service.Method) func(*APIContext) {
 	return func(ctx *APIContext) {
 		// Get user from session if logged in.
-		ctx.User = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
-		if ctx.User != nil {
-			if ctx.Locale.Language() != ctx.User.Language {
+		ctx.Doer = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
+		if ctx.Doer != nil {
+			if ctx.Locale.Language() != ctx.Doer.Language {
 				ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
 			}
 			ctx.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == auth_service.BasicMethodName
 			ctx.IsSigned = true
 			ctx.Data["IsSigned"] = ctx.IsSigned
-			ctx.Data["SignedUser"] = ctx.User
-			ctx.Data["SignedUserID"] = ctx.User.ID
-			ctx.Data["SignedUserName"] = ctx.User.Name
-			ctx.Data["IsAdmin"] = ctx.User.IsAdmin
+			ctx.Data["SignedUser"] = ctx.Doer
+			ctx.Data["SignedUserID"] = ctx.Doer.ID
+			ctx.Data["SignedUserName"] = ctx.Doer.Name
+			ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin
 		} else {
 			ctx.Data["SignedUserID"] = int64(0)
 			ctx.Data["SignedUserName"] = ""
diff --git a/modules/context/auth.go b/modules/context/auth.go
index 7e7e8ab96..1a46ab586 100644
--- a/modules/context/auth.go
+++ b/modules/context/auth.go
@@ -27,19 +27,19 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
 	return func(ctx *Context) {
 		// Check prohibit login users.
 		if ctx.IsSigned {
-			if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+			if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
 				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
 				ctx.HTML(http.StatusOK, "user/auth/activate")
 				return
 			}
-			if !ctx.User.IsActive || ctx.User.ProhibitLogin {
-				log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
+			if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
+				log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
 				ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
 				ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
 				return
 			}
 
-			if ctx.User.MustChangePassword {
+			if ctx.Doer.MustChangePassword {
 				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"
@@ -76,7 +76,7 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
 				}
 				ctx.Redirect(setting.AppSubURL + "/user/login")
 				return
-			} else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+			} else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
 				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
 				ctx.HTML(http.StatusOK, "user/auth/activate")
 				return
@@ -94,7 +94,7 @@ func Toggle(options *ToggleOptions) func(ctx *Context) {
 		}
 
 		if options.AdminRequired {
-			if !ctx.User.IsAdmin {
+			if !ctx.Doer.IsAdmin {
 				ctx.Error(http.StatusForbidden)
 				return
 			}
@@ -108,15 +108,15 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
 	return func(ctx *APIContext) {
 		// Check prohibit login users.
 		if ctx.IsSigned {
-			if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+			if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
 				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
 				ctx.JSON(http.StatusForbidden, map[string]string{
 					"message": "This account is not activated.",
 				})
 				return
 			}
-			if !ctx.User.IsActive || ctx.User.ProhibitLogin {
-				log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
+			if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
+				log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
 				ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
 				ctx.JSON(http.StatusForbidden, map[string]string{
 					"message": "This account is prohibited from signing in, please contact your site administrator.",
@@ -124,7 +124,7 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
 				return
 			}
 
-			if ctx.User.MustChangePassword {
+			if ctx.Doer.MustChangePassword {
 				ctx.JSON(http.StatusForbidden, map[string]string{
 					"message": "You must change your password. Change it at: " + setting.AppURL + "/user/change_password",
 				})
@@ -145,7 +145,7 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
 					"message": "Only signed in user is allowed to call APIs.",
 				})
 				return
-			} else if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+			} else if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
 				ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
 				ctx.HTML(http.StatusOK, "user/auth/activate")
 				return
@@ -154,7 +154,7 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
 				if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) {
 					return // Skip 2FA
 				}
-				twofa, err := auth.GetTwoFactorByUID(ctx.User.ID)
+				twofa, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
 				if err != nil {
 					if auth.IsErrTwoFactorNotEnrolled(err) {
 						return // No 2FA enrollment for this user
@@ -178,7 +178,7 @@ func ToggleAPI(options *ToggleOptions) func(ctx *APIContext) {
 		}
 
 		if options.AdminRequired {
-			if !ctx.User.IsAdmin {
+			if !ctx.Doer.IsAdmin {
 				ctx.JSON(http.StatusForbidden, map[string]string{
 					"message": "You have no permission to request for this.",
 				})
diff --git a/modules/context/context.go b/modules/context/context.go
index 8e50e154a..57448907e 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -63,7 +63,7 @@ type Context struct {
 
 	Link        string // current request URL
 	EscapedLink string
-	User        *user_model.User
+	Doer        *user_model.User
 	IsSigned    bool
 	IsBasicAuth bool
 
@@ -88,7 +88,7 @@ func (ctx *Context) GetData() map[string]interface{} {
 
 // IsUserSiteAdmin returns true if current user is a site admin
 func (ctx *Context) IsUserSiteAdmin() bool {
-	return ctx.IsSigned && ctx.User.IsAdmin
+	return ctx.IsSigned && ctx.Doer.IsAdmin
 }
 
 // IsUserRepoOwner returns true if current user owns current repo
@@ -574,10 +574,10 @@ func GetContext(req *http.Request) *Context {
 // GetContextUser returns context user
 func GetContextUser(req *http.Request) *user_model.User {
 	if apiContext, ok := req.Context().Value(apiContextKey).(*APIContext); ok {
-		return apiContext.User
+		return apiContext.Doer
 	}
 	if ctx, ok := req.Context().Value(contextKey).(*Context); ok {
-		return ctx.User
+		return ctx.Doer
 	}
 	return nil
 }
@@ -599,18 +599,18 @@ func getCsrfOpts() CsrfOptions {
 // Auth converts auth.Auth as a middleware
 func Auth(authMethod auth.Method) func(*Context) {
 	return func(ctx *Context) {
-		ctx.User = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
-		if ctx.User != nil {
-			if ctx.Locale.Language() != ctx.User.Language {
+		ctx.Doer = authMethod.Verify(ctx.Req, ctx.Resp, ctx, ctx.Session)
+		if ctx.Doer != nil {
+			if ctx.Locale.Language() != ctx.Doer.Language {
 				ctx.Locale = middleware.Locale(ctx.Resp, ctx.Req)
 			}
 			ctx.IsBasicAuth = ctx.Data["AuthedMethod"].(string) == auth.BasicMethodName
 			ctx.IsSigned = true
 			ctx.Data["IsSigned"] = ctx.IsSigned
-			ctx.Data["SignedUser"] = ctx.User
-			ctx.Data["SignedUserID"] = ctx.User.ID
-			ctx.Data["SignedUserName"] = ctx.User.Name
-			ctx.Data["IsAdmin"] = ctx.User.IsAdmin
+			ctx.Data["SignedUser"] = ctx.Doer
+			ctx.Data["SignedUserID"] = ctx.Doer.ID
+			ctx.Data["SignedUserName"] = ctx.Doer.Name
+			ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin
 		} else {
 			ctx.Data["SignedUserID"] = int64(0)
 			ctx.Data["SignedUserName"] = ""
diff --git a/modules/context/org.go b/modules/context/org.go
index 824f22b2f..a1080fc0f 100644
--- a/modules/context/org.go
+++ b/modules/context/org.go
@@ -77,14 +77,14 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 	ctx.Data["OrgTeams"] = teams
 
 	// Admin has super access.
-	if ctx.IsSigned && ctx.User.IsAdmin {
+	if ctx.IsSigned && ctx.Doer.IsAdmin {
 		ctx.Org.IsOwner = true
 		ctx.Org.IsMember = true
 		ctx.Org.IsTeamMember = true
 		ctx.Org.IsTeamAdmin = true
 		ctx.Org.CanCreateOrgRepo = true
 	} else if ctx.IsSigned {
-		ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.User.ID)
+		ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("IsOwnedBy", err)
 			return
@@ -96,12 +96,12 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 			ctx.Org.IsTeamAdmin = true
 			ctx.Org.CanCreateOrgRepo = true
 		} else {
-			ctx.Org.IsMember, err = org.IsOrgMember(ctx.User.ID)
+			ctx.Org.IsMember, err = org.IsOrgMember(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("IsOrgMember", err)
 				return
 			}
-			ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx.User.ID)
+			ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("CanCreateOrgRepo", err)
 				return
@@ -133,7 +133,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 		if ctx.Org.IsOwner {
 			shouldSeeAllTeams = true
 		} else {
-			teams, err := org.GetUserTeams(ctx.User.ID)
+			teams, err := org.GetUserTeams(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("GetUserTeams", err)
 				return
@@ -152,7 +152,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 				return
 			}
 		} else {
-			ctx.Org.Teams, err = org.GetUserTeams(ctx.User.ID)
+			ctx.Org.Teams, err = org.GetUserTeams(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("GetUserTeams", err)
 				return
diff --git a/modules/context/permission.go b/modules/context/permission.go
index 2b87aa459..142b86fae 100644
--- a/modules/context/permission.go
+++ b/modules/context/permission.go
@@ -49,7 +49,7 @@ func RequireRepoReader(unitType unit.Type) func(ctx *Context) {
 				if ctx.IsSigned {
 					log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
 						"User in Repo has Permissions: %-+v",
-						ctx.User,
+						ctx.Doer,
 						unitType,
 						ctx.Repo.Repository,
 						ctx.Repo.Permission)
@@ -80,7 +80,7 @@ func RequireRepoReaderOr(unitTypes ...unit.Type) func(ctx *Context) {
 			var args []interface{}
 			if ctx.IsSigned {
 				format = "Permission Denied: User %-v cannot read ["
-				args = append(args, ctx.User)
+				args = append(args, ctx.Doer)
 			} else {
 				format = "Permission Denied: Anonymous user cannot read ["
 			}
diff --git a/modules/context/repo.go b/modules/context/repo.go
index e55c13f49..d64380dd9 100644
--- a/modules/context/repo.go
+++ b/modules/context/repo.go
@@ -278,7 +278,7 @@ func RetrieveTemplateRepo(ctx *Context, repo *repo_model.Repository) {
 		return
 	}
 
-	perm, err := models.GetUserRepoPermission(templateRepo, ctx.User)
+	perm, err := models.GetUserRepoPermission(templateRepo, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserRepoPermission", err)
 		return
@@ -346,7 +346,7 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
 		return
 	}
 
-	ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.User)
+	ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserRepoPermission", err)
 		return
@@ -422,8 +422,8 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 	repoName = strings.TrimSuffix(repoName, ".atom")
 
 	// Check if the user is the same as the repository owner
-	if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
-		owner = ctx.User
+	if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
+		owner = ctx.Doer
 	} else {
 		owner, err = user_model.GetUserByName(userName)
 		if err != nil {
@@ -502,14 +502,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 	ctx.Data["CanWriteIssues"] = ctx.Repo.CanWrite(unit_model.TypeIssues)
 	ctx.Data["CanWritePulls"] = ctx.Repo.CanWrite(unit_model.TypePullRequests)
 
-	canSignedUserFork, err := models.CanUserForkRepo(ctx.User, ctx.Repo.Repository)
+	canSignedUserFork, err := models.CanUserForkRepo(ctx.Doer, ctx.Repo.Repository)
 	if err != nil {
 		ctx.ServerError("CanUserForkRepo", err)
 		return
 	}
 	ctx.Data["CanSignedUserFork"] = canSignedUserFork
 
-	userAndOrgForks, err := models.GetForksByUserAndOrgs(ctx.User, ctx.Repo.Repository)
+	userAndOrgForks, err := models.GetForksByUserAndOrgs(ctx.Doer, ctx.Repo.Repository)
 	if err != nil {
 		ctx.ServerError("GetForksByUserAndOrgs", err)
 		return
@@ -532,8 +532,8 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 	ctx.Data["WikiCloneLink"] = repo.WikiCloneLink()
 
 	if ctx.IsSigned {
-		ctx.Data["IsWatchingRepo"] = repo_model.IsWatching(ctx.User.ID, repo.ID)
-		ctx.Data["IsStaringRepo"] = repo_model.IsStaring(ctx.User.ID, repo.ID)
+		ctx.Data["IsWatchingRepo"] = repo_model.IsWatching(ctx.Doer.ID, repo.ID)
+		ctx.Data["IsStaringRepo"] = repo_model.IsStaring(ctx.Doer.ID, repo.ID)
 	}
 
 	if repo.IsFork {
@@ -633,7 +633,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 
 	// People who have push access or have forked repository can propose a new pull request.
 	canPush := ctx.Repo.CanWrite(unit_model.TypeCode) ||
-		(ctx.IsSigned && repo_model.HasForkedRepo(ctx.User.ID, ctx.Repo.Repository.ID))
+		(ctx.IsSigned && repo_model.HasForkedRepo(ctx.Doer.ID, ctx.Repo.Repository.ID))
 	canCompare := false
 
 	// Pull request is allowed if this is a fork repository
@@ -669,8 +669,8 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
 		}
 
 		ctx.Data["RepoTransfer"] = repoTransfer
-		if ctx.User != nil {
-			ctx.Data["CanUserAcceptTransfer"] = repoTransfer.CanUserAcceptTransfer(ctx.User)
+		if ctx.Doer != nil {
+			ctx.Data["CanUserAcceptTransfer"] = repoTransfer.CanUserAcceptTransfer(ctx.Doer)
 		}
 	}
 
@@ -950,7 +950,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
 // GitHookService checks if repository Git hooks service has been enabled.
 func GitHookService() func(ctx *Context) {
 	return func(ctx *Context) {
-		if !ctx.User.CanEditGitHook() {
+		if !ctx.Doer.CanEditGitHook() {
 			ctx.NotFound("GitHookService", nil)
 			return
 		}
diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go
index e6c78bcaa..e5cea26eb 100644
--- a/modules/test/context_tests.go
+++ b/modules/test/context_tests.go
@@ -61,7 +61,7 @@ func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
 	ctx.Repo.Owner, err = user_model.GetUserByID(ctx.Repo.Repository.OwnerID)
 	assert.NoError(t, err)
 	ctx.Repo.RepoLink = ctx.Repo.Repository.Link()
-	ctx.Repo.Permission, err = models.GetUserRepoPermission(ctx.Repo.Repository, ctx.User)
+	ctx.Repo.Permission, err = models.GetUserRepoPermission(ctx.Repo.Repository, ctx.Doer)
 	assert.NoError(t, err)
 }
 
@@ -81,7 +81,7 @@ func LoadRepoCommit(t *testing.T, ctx *context.Context) {
 
 // LoadUser load a user into a test context.
 func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
-	ctx.User = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}).(*user_model.User)
+	ctx.Doer = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}).(*user_model.User)
 }
 
 // LoadGitRepo load a git repo into a test context. Requires that ctx.Repo has
diff --git a/routers/api/v1/admin/adopt.go b/routers/api/v1/admin/adopt.go
index db1754c8d..3c39d7c2b 100644
--- a/routers/api/v1/admin/adopt.go
+++ b/routers/api/v1/admin/adopt.go
@@ -110,7 +110,7 @@ func AdoptRepository(ctx *context.APIContext) {
 		ctx.NotFound()
 		return
 	}
-	if _, err := repo_service.AdoptRepository(ctx.User, ctxUser, models.CreateRepoOptions{
+	if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, models.CreateRepoOptions{
 		Name:      repoName,
 		IsPrivate: true,
 	}); err != nil {
@@ -173,7 +173,7 @@ func DeleteUnadoptedRepository(ctx *context.APIContext) {
 		return
 	}
 
-	if err := repo_service.DeleteUnadoptedRepository(ctx.User, ctxUser, repoName); err != nil {
+	if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, repoName); err != nil {
 		ctx.InternalServerError(err)
 		return
 	}
diff --git a/routers/api/v1/admin/cron.go b/routers/api/v1/admin/cron.go
index 1476872a9..0c4333b89 100644
--- a/routers/api/v1/admin/cron.go
+++ b/routers/api/v1/admin/cron.go
@@ -81,7 +81,7 @@ func PostCronTask(ctx *context.APIContext) {
 		return
 	}
 	task.Run()
-	log.Trace("Cron Task %s started by admin(%s)", task.Name, ctx.User.Name)
+	log.Trace("Cron Task %s started by admin(%s)", task.Name, ctx.Doer.Name)
 
 	ctx.Status(http.StatusNoContent)
 }
diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go
index aaa27afb9..4ebfe9863 100644
--- a/routers/api/v1/admin/org.go
+++ b/routers/api/v1/admin/org.go
@@ -107,7 +107,7 @@ func GetAllOrgs(ctx *context.APIContext) {
 	listOptions := utils.GetListOptions(ctx)
 
 	users, maxResults, err := user_model.SearchUsers(&user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		Type:        user_model.UserTypeOrganization,
 		OrderBy:     db.SearchOrderByAlphabetically,
 		ListOptions: listOptions,
diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go
index 1d3854df9..677950664 100644
--- a/routers/api/v1/admin/user.go
+++ b/routers/api/v1/admin/user.go
@@ -128,13 +128,13 @@ func CreateUser(ctx *context.APIContext) {
 		}
 		return
 	}
-	log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 
 	// Send email notification.
 	if form.SendNotify {
 		mailer.SendRegisterNotifyMail(u)
 	}
-	ctx.JSON(http.StatusCreated, convert.ToUser(u, ctx.User))
+	ctx.JSON(http.StatusCreated, convert.ToUser(u, ctx.Doer))
 }
 
 // EditUser api for modifying a user's information
@@ -275,9 +275,9 @@ func EditUser(ctx *context.APIContext) {
 		}
 		return
 	}
-	log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account profile updated by admin (%s): %s", ctx.Doer.Name, u.Name)
 
-	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.User))
+	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.Doer))
 }
 
 // DeleteUser api for deleting a user
@@ -320,7 +320,7 @@ func DeleteUser(ctx *context.APIContext) {
 		}
 		return
 	}
-	log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account deleted by admin(%s): %s", ctx.Doer.Name, u.Name)
 
 	ctx.Status(http.StatusNoContent)
 }
@@ -401,7 +401,7 @@ func DeleteUserPublicKey(ctx *context.APIContext) {
 		}
 		return
 	}
-	log.Trace("Key deleted by admin(%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Key deleted by admin(%s): %s", ctx.Doer.Name, u.Name)
 
 	ctx.Status(http.StatusNoContent)
 }
@@ -431,7 +431,7 @@ func GetAllUsers(ctx *context.APIContext) {
 	listOptions := utils.GetListOptions(ctx)
 
 	users, maxResults, err := user_model.SearchUsers(&user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		Type:        user_model.UserTypeIndividual,
 		OrderBy:     db.SearchOrderByAlphabetically,
 		ListOptions: listOptions,
@@ -443,7 +443,7 @@ func GetAllUsers(ctx *context.APIContext) {
 
 	results := make([]*api.User, len(users))
 	for i := range users {
-		results[i] = convert.ToUser(users[i], ctx.User)
+		results[i] = convert.ToUser(users[i], ctx.Doer)
 	}
 
 	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index d4891daef..4b3016402 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -103,7 +103,7 @@ func sudo() func(ctx *context.APIContext) {
 		}
 
 		if len(sudo) > 0 {
-			if ctx.IsSigned && ctx.User.IsAdmin {
+			if ctx.IsSigned && ctx.Doer.IsAdmin {
 				user, err := user_model.GetUserByName(sudo)
 				if err != nil {
 					if user_model.IsErrUserNotExist(err) {
@@ -113,8 +113,8 @@ func sudo() func(ctx *context.APIContext) {
 					}
 					return
 				}
-				log.Trace("Sudo from (%s) to: %s", ctx.User.Name, user.Name)
-				ctx.User = user
+				log.Trace("Sudo from (%s) to: %s", ctx.Doer.Name, user.Name)
+				ctx.Doer = user
 			} else {
 				ctx.JSON(http.StatusForbidden, map[string]string{
 					"message": "Only administrators allowed to sudo.",
@@ -136,8 +136,8 @@ func repoAssignment() func(ctx *context.APIContext) {
 		)
 
 		// Check if the user is the same as the repository owner.
-		if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) {
-			owner = ctx.User
+		if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
+			owner = ctx.Doer
 		} else {
 			owner, err = user_model.GetUserByName(userName)
 			if err != nil {
@@ -178,7 +178,7 @@ func repoAssignment() func(ctx *context.APIContext) {
 		repo.Owner = owner
 		ctx.Repo.Repository = repo
 
-		ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.User)
+		ctx.Repo.Permission, err = models.GetUserRepoPermission(repo, ctx.Doer)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
 			return
@@ -307,7 +307,7 @@ func reqOrgOwnership() func(ctx *context.APIContext) {
 			return
 		}
 
-		isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID)
+		isOwner, err := models.IsOrganizationOwner(orgID, ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
 			return
@@ -334,7 +334,7 @@ func reqTeamMembership() func(ctx *context.APIContext) {
 		}
 
 		orgID := ctx.Org.Team.OrgID
-		isOwner, err := models.IsOrganizationOwner(orgID, ctx.User.ID)
+		isOwner, err := models.IsOrganizationOwner(orgID, ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrganizationOwner", err)
 			return
@@ -342,11 +342,11 @@ func reqTeamMembership() func(ctx *context.APIContext) {
 			return
 		}
 
-		if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.User.ID); err != nil {
+		if isTeamMember, err := models.IsTeamMember(orgID, ctx.Org.Team.ID, ctx.Doer.ID); err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsTeamMember", err)
 			return
 		} else if !isTeamMember {
-			isOrgMember, err := models.IsOrganizationMember(orgID, ctx.User.ID)
+			isOrgMember, err := models.IsOrganizationMember(orgID, ctx.Doer.ID)
 			if err != nil {
 				ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
 			} else if isOrgMember {
@@ -376,7 +376,7 @@ func reqOrgMembership() func(ctx *context.APIContext) {
 			return
 		}
 
-		if isMember, err := models.IsOrganizationMember(orgID, ctx.User.ID); err != nil {
+		if isMember, err := models.IsOrganizationMember(orgID, ctx.Doer.ID); err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
 			return
 		} else if !isMember {
@@ -392,7 +392,7 @@ func reqOrgMembership() func(ctx *context.APIContext) {
 
 func reqGitHook() func(ctx *context.APIContext) {
 	return func(ctx *context.APIContext) {
-		if !ctx.User.CanEditGitHook() {
+		if !ctx.Doer.CanEditGitHook() {
 			ctx.Error(http.StatusForbidden, "", "must be allowed to edit Git hooks")
 			return
 		}
@@ -463,7 +463,7 @@ func mustEnableIssues(ctx *context.APIContext) {
 			if ctx.IsSigned {
 				log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					unit.TypeIssues,
 					ctx.Repo.Repository,
 					ctx.Repo.Permission)
@@ -486,7 +486,7 @@ func mustAllowPulls(ctx *context.APIContext) {
 			if ctx.IsSigned {
 				log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					unit.TypePullRequests,
 					ctx.Repo.Repository,
 					ctx.Repo.Permission)
@@ -510,7 +510,7 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) {
 			if ctx.IsSigned {
 				log.Trace("Permission Denied: User %-v cannot read %-v and %-v in Repo %-v\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					unit.TypeIssues,
 					unit.TypePullRequests,
 					ctx.Repo.Repository,
diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go
index 9dd9da85c..1821c3037 100644
--- a/routers/api/v1/notify/notifications.go
+++ b/routers/api/v1/notify/notifications.go
@@ -22,7 +22,7 @@ func NewAvailable(ctx *context.APIContext) {
 	// responses:
 	//   "200":
 	//     "$ref": "#/responses/NotificationCount"
-	ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.User)})
+	ctx.JSON(http.StatusOK, api.NotificationCount{New: models.CountUnread(ctx.Doer)})
 }
 
 func getFindNotificationOptions(ctx *context.APIContext) *models.FindNotificationOptions {
@@ -33,7 +33,7 @@ func getFindNotificationOptions(ctx *context.APIContext) *models.FindNotificatio
 	}
 	opts := &models.FindNotificationOptions{
 		ListOptions:       utils.GetListOptions(ctx),
-		UserID:            ctx.User.ID,
+		UserID:            ctx.Doer.ID,
 		UpdatedBeforeUnix: before,
 		UpdatedAfterUnix:  since,
 	}
diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go
index 30357ebd3..a36bbc6b4 100644
--- a/routers/api/v1/notify/repo.go
+++ b/routers/api/v1/notify/repo.go
@@ -193,7 +193,7 @@ func ReadRepoNotifications(ctx *context.APIContext) {
 	}
 
 	opts := &models.FindNotificationOptions{
-		UserID:            ctx.User.ID,
+		UserID:            ctx.Doer.ID,
 		RepoID:            ctx.Repo.Repository.ID,
 		UpdatedBeforeUnix: lastRead,
 	}
@@ -217,7 +217,7 @@ func ReadRepoNotifications(ctx *context.APIContext) {
 	changed := make([]*structs.NotificationThread, len(nl))
 
 	for _, n := range nl {
-		notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
+		notif, err := models.SetNotificationStatus(n.ID, ctx.Doer, targetStatus)
 		if err != nil {
 			ctx.InternalServerError(err)
 			return
diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go
index 5bfdd4d96..fe89304dc 100644
--- a/routers/api/v1/notify/threads.go
+++ b/routers/api/v1/notify/threads.go
@@ -87,7 +87,7 @@ func ReadThread(ctx *context.APIContext) {
 		targetStatus = models.NotificationStatusRead
 	}
 
-	notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
+	notif, err := models.SetNotificationStatus(n.ID, ctx.Doer, targetStatus)
 	if err != nil {
 		ctx.InternalServerError(err)
 		return
@@ -109,7 +109,7 @@ func getThread(ctx *context.APIContext) *models.Notification {
 		}
 		return nil
 	}
-	if n.UserID != ctx.User.ID && !ctx.User.IsAdmin {
+	if n.UserID != ctx.Doer.ID && !ctx.Doer.IsAdmin {
 		ctx.Error(http.StatusForbidden, "GetNotificationByID", fmt.Errorf("only user itself and admin are allowed to read/change this thread %d", n.ID))
 		return nil
 	}
diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go
index 6e4c19d1b..ac3d0591d 100644
--- a/routers/api/v1/notify/user.go
+++ b/routers/api/v1/notify/user.go
@@ -141,7 +141,7 @@ func ReadNotifications(ctx *context.APIContext) {
 		}
 	}
 	opts := &models.FindNotificationOptions{
-		UserID:            ctx.User.ID,
+		UserID:            ctx.Doer.ID,
 		UpdatedBeforeUnix: lastRead,
 	}
 	if !ctx.FormBool("all") {
@@ -162,7 +162,7 @@ func ReadNotifications(ctx *context.APIContext) {
 	changed := make([]*structs.NotificationThread, 0, len(nl))
 
 	for _, n := range nl {
-		notif, err := models.SetNotificationStatus(n.ID, ctx.User, targetStatus)
+		notif, err := models.SetNotificationStatus(n.ID, ctx.Doer, targetStatus)
 		if err != nil {
 			ctx.InternalServerError(err)
 			return
diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go
index d81832179..7f82f1938 100644
--- a/routers/api/v1/org/member.go
+++ b/routers/api/v1/org/member.go
@@ -39,7 +39,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
 
 	apiMembers := make([]*api.User, len(members))
 	for i, member := range members {
-		apiMembers[i] = convert.ToUser(member, ctx.User)
+		apiMembers[i] = convert.ToUser(member, ctx.Doer)
 	}
 
 	ctx.SetTotalCountHeader(count)
@@ -72,13 +72,13 @@ func ListMembers(ctx *context.APIContext) {
 	//     "$ref": "#/responses/UserList"
 
 	publicOnly := true
-	if ctx.User != nil {
-		isMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID)
+	if ctx.Doer != nil {
+		isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
 			return
 		}
-		publicOnly = !isMember && !ctx.User.IsAdmin
+		publicOnly = !isMember && !ctx.Doer.IsAdmin
 	}
 	listMembers(ctx, publicOnly)
 }
@@ -139,12 +139,12 @@ func IsMember(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if ctx.User != nil {
-		userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID)
+	if ctx.Doer != nil {
+		userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
 			return
-		} else if userIsMember || ctx.User.IsAdmin {
+		} else if userIsMember || ctx.Doer.IsAdmin {
 			userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(userToCheck.ID)
 			if err != nil {
 				ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
@@ -154,7 +154,7 @@ func IsMember(ctx *context.APIContext) {
 				ctx.NotFound()
 			}
 			return
-		} else if ctx.User.ID == userToCheck.ID {
+		} else if ctx.Doer.ID == userToCheck.ID {
 			ctx.NotFound()
 			return
 		}
@@ -230,7 +230,7 @@ func PublicizeMember(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if userToPublicize.ID != ctx.User.ID {
+	if userToPublicize.ID != ctx.Doer.ID {
 		ctx.Error(http.StatusForbidden, "", "Cannot publicize another member")
 		return
 	}
@@ -270,7 +270,7 @@ func ConcealMember(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if userToConceal.ID != ctx.User.ID {
+	if userToConceal.ID != ctx.Doer.ID {
 		ctx.Error(http.StatusForbidden, "", "Cannot conceal another member")
 		return
 	}
diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go
index 1f097225f..a920b49a8 100644
--- a/routers/api/v1/org/org.go
+++ b/routers/api/v1/org/org.go
@@ -23,7 +23,7 @@ import (
 
 func listUserOrgs(ctx *context.APIContext, u *user_model.User) {
 	listOptions := utils.GetListOptions(ctx)
-	showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == u.ID)
+	showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == u.ID)
 
 	opts := models.FindOrgOptions{
 		ListOptions:    listOptions,
@@ -71,7 +71,7 @@ func ListMyOrgs(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/OrganizationList"
 
-	listUserOrgs(ctx, ctx.User)
+	listUserOrgs(ctx, ctx.Doer)
 }
 
 // ListUserOrgs list user's orgs
@@ -201,7 +201,7 @@ func GetAll(ctx *context.APIContext) {
 	vMode := []api.VisibleType{api.VisibleTypePublic}
 	if ctx.IsSigned {
 		vMode = append(vMode, api.VisibleTypeLimited)
-		if ctx.User.IsAdmin {
+		if ctx.Doer.IsAdmin {
 			vMode = append(vMode, api.VisibleTypePrivate)
 		}
 	}
@@ -209,7 +209,7 @@ func GetAll(ctx *context.APIContext) {
 	listOptions := utils.GetListOptions(ctx)
 
 	publicOrgs, maxResults, err := user_model.SearchUsers(&user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		ListOptions: listOptions,
 		Type:        user_model.UserTypeOrganization,
 		OrderBy:     db.SearchOrderByAlphabetically,
@@ -251,7 +251,7 @@ func Create(ctx *context.APIContext) {
 	//   "422":
 	//     "$ref": "#/responses/validationError"
 	form := web.GetForm(ctx).(*api.CreateOrgOption)
-	if !ctx.User.CanCreateOrganization() {
+	if !ctx.Doer.CanCreateOrganization() {
 		ctx.Error(http.StatusForbidden, "Create organization not allowed", nil)
 		return
 	}
@@ -272,7 +272,7 @@ func Create(ctx *context.APIContext) {
 		Visibility:                visibility,
 		RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
 	}
-	if err := models.CreateOrganization(org, ctx.User); err != nil {
+	if err := models.CreateOrganization(org, ctx.Doer); err != nil {
 		if user_model.IsErrUserAlreadyExist(err) ||
 			db.IsErrNameReserved(err) ||
 			db.IsErrNameCharsNotAllowed(err) ||
@@ -304,7 +304,7 @@ func Get(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/Organization"
 
-	if !models.HasOrgOrUserVisible(ctx.Org.Organization.AsUser(), ctx.User) {
+	if !models.HasOrgOrUserVisible(ctx.Org.Organization.AsUser(), ctx.Doer) {
 		ctx.NotFound("HasOrgOrUserVisible", nil)
 		return
 	}
diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go
index 62e6c0a6b..ca8cda269 100644
--- a/routers/api/v1/org/team.go
+++ b/routers/api/v1/org/team.go
@@ -92,7 +92,7 @@ func ListUserTeams(ctx *context.APIContext) {
 
 	teams, count, err := models.GetUserTeams(&models.GetUserTeamOptions{
 		ListOptions: utils.GetListOptions(ctx),
-		UserID:      ctx.User.ID,
+		UserID:      ctx.Doer.ID,
 	})
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetUserTeams", err)
@@ -368,11 +368,11 @@ func GetTeamMembers(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/UserList"
 
-	isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.User.ID)
+	isMember, err := models.IsOrganizationMember(ctx.Org.Team.OrgID, ctx.Doer.ID)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "IsOrganizationMember", err)
 		return
-	} else if !isMember && !ctx.User.IsAdmin {
+	} else if !isMember && !ctx.Doer.IsAdmin {
 		ctx.NotFound()
 		return
 	}
@@ -385,7 +385,7 @@ func GetTeamMembers(ctx *context.APIContext) {
 	}
 	members := make([]*api.User, len(ctx.Org.Team.Members))
 	for i, member := range ctx.Org.Team.Members {
-		members[i] = convert.ToUser(member, ctx.User)
+		members[i] = convert.ToUser(member, ctx.Doer)
 	}
 
 	ctx.SetTotalCountHeader(int64(ctx.Org.Team.NumMembers))
@@ -430,7 +430,7 @@ func GetTeamMember(ctx *context.APIContext) {
 		ctx.NotFound()
 		return
 	}
-	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.User))
+	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.Doer))
 }
 
 // AddTeamMember api for add a member to a team
@@ -540,7 +540,7 @@ func GetTeamRepos(ctx *context.APIContext) {
 	}
 	repos := make([]*api.Repository, len(team.Repos))
 	for i, repo := range team.Repos {
-		access, err := models.AccessLevel(ctx.User, repo)
+		access, err := models.AccessLevel(ctx.Doer, repo)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
 			return
@@ -599,7 +599,7 @@ func AddTeamRepository(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if access, err := models.AccessLevel(ctx.User, repo); err != nil {
+	if access, err := models.AccessLevel(ctx.Doer, repo); err != nil {
 		ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 		return
 	} else if access < perm.AccessModeAdmin {
@@ -649,7 +649,7 @@ func RemoveTeamRepository(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if access, err := models.AccessLevel(ctx.User, repo); err != nil {
+	if access, err := models.AccessLevel(ctx.Doer, repo); err != nil {
 		ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 		return
 	} else if access < perm.AccessModeAdmin {
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 3a0c3201a..065bad270 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -75,7 +75,7 @@ func GetBranch(ctx *context.APIContext) {
 		return
 	}
 
-	br, err := convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User, ctx.Repo.IsAdmin())
+	br, err := convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin())
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err)
 		return
@@ -117,7 +117,7 @@ func DeleteBranch(ctx *context.APIContext) {
 
 	branchName := ctx.Params("*")
 
-	if err := repo_service.DeleteBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
+	if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
 		switch {
 		case git.IsErrBranchNotExist(err):
 			ctx.NotFound(err)
@@ -176,7 +176,7 @@ func CreateBranch(ctx *context.APIContext) {
 		opt.OldBranchName = ctx.Repo.Repository.DefaultBranch
 	}
 
-	err := repo_service.CreateNewBranch(ctx, ctx.User, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName)
+	err := repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, opt.OldBranchName, opt.BranchName)
 	if err != nil {
 		if models.IsErrBranchDoesNotExist(err) {
 			ctx.Error(http.StatusNotFound, "", "The old branch does not exist")
@@ -211,7 +211,7 @@ func CreateBranch(ctx *context.APIContext) {
 		return
 	}
 
-	br, err := convert.ToBranch(ctx.Repo.Repository, branch, commit, branchProtection, ctx.User, ctx.Repo.IsAdmin())
+	br, err := convert.ToBranch(ctx.Repo.Repository, branch, commit, branchProtection, ctx.Doer, ctx.Repo.IsAdmin())
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err)
 		return
@@ -270,7 +270,7 @@ func ListBranches(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err)
 			return
 		}
-		apiBranches[i], err = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User, ctx.Repo.IsAdmin())
+		apiBranches[i], err = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.Doer, ctx.Repo.IsAdmin())
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "convert.ToBranch", err)
 			return
diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go
index d49b6357b..3bb6113d7 100644
--- a/routers/api/v1/repo/collaborators.go
+++ b/routers/api/v1/repo/collaborators.go
@@ -63,7 +63,7 @@ func ListCollaborators(ctx *context.APIContext) {
 
 	users := make([]*api.User, len(collaborators))
 	for i, collaborator := range collaborators {
-		users[i] = convert.ToUser(collaborator.User, ctx.User)
+		users[i] = convert.ToUser(collaborator.User, ctx.Doer)
 	}
 
 	ctx.SetTotalCountHeader(count)
@@ -255,12 +255,12 @@ func GetReviewers(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/UserList"
 
-	reviewers, err := models.GetReviewers(ctx.Repo.Repository, ctx.User.ID, 0)
+	reviewers, err := models.GetReviewers(ctx.Repo.Repository, ctx.Doer.ID, 0)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "ListCollaborators", err)
 		return
 	}
-	ctx.JSON(http.StatusOK, convert.ToUsers(ctx.User, reviewers))
+	ctx.JSON(http.StatusOK, convert.ToUsers(ctx.Doer, reviewers))
 }
 
 // GetAssignees return all users that have write access and can be assigned to issues
@@ -290,5 +290,5 @@ func GetAssignees(ctx *context.APIContext) {
 		ctx.Error(http.StatusInternalServerError, "ListCollaborators", err)
 		return
 	}
-	ctx.JSON(http.StatusOK, convert.ToUsers(ctx.User, assignees))
+	ctx.JSON(http.StatusOK, convert.ToUsers(ctx.Doer, assignees))
 }
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index a27e383bc..37781f79c 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -391,7 +391,7 @@ func handleCreateOrUpdateFileError(ctx *context.APIContext, err error) {
 func createOrUpdateFile(ctx *context.APIContext, opts *files_service.UpdateRepoFileOptions) (*api.FileResponse, error) {
 	if !canWriteFiles(ctx.Repo) {
 		return nil, models.ErrUserDoesNotHaveAccessToRepo{
-			UserID:   ctx.User.ID,
+			UserID:   ctx.Doer.ID,
 			RepoName: ctx.Repo.Repository.LowerName,
 		}
 	}
@@ -402,7 +402,7 @@ func createOrUpdateFile(ctx *context.APIContext, opts *files_service.UpdateRepoF
 	}
 	opts.Content = string(content)
 
-	return files_service.CreateOrUpdateRepoFile(ctx, ctx.Repo.Repository, ctx.User, opts)
+	return files_service.CreateOrUpdateRepoFile(ctx, ctx.Repo.Repository, ctx.Doer, opts)
 }
 
 // DeleteFile Delete a file in a repository
@@ -448,7 +448,7 @@ func DeleteFile(ctx *context.APIContext) {
 	apiOpts := web.GetForm(ctx).(*api.DeleteFileOptions)
 	if !canWriteFiles(ctx.Repo) {
 		ctx.Error(http.StatusForbidden, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{
-			UserID:   ctx.User.ID,
+			UserID:   ctx.Doer.ID,
 			RepoName: ctx.Repo.Repository.LowerName,
 		})
 		return
@@ -489,7 +489,7 @@ func DeleteFile(ctx *context.APIContext) {
 		opts.Message = ctx.Tr("repo.editor.delete", opts.TreePath)
 	}
 
-	if fileResponse, err := files_service.DeleteRepoFile(ctx, ctx.Repo.Repository, ctx.User, opts); err != nil {
+	if fileResponse, err := files_service.DeleteRepoFile(ctx, ctx.Repo.Repository, ctx.Doer, opts); err != nil {
 		if git.IsErrBranchNotExist(err) || models.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
 			ctx.Error(http.StatusNotFound, "DeleteFile", err)
 			return
@@ -546,7 +546,7 @@ func GetContents(ctx *context.APIContext) {
 
 	if !canReadFiles(ctx.Repo) {
 		ctx.Error(http.StatusInternalServerError, "GetContentsOrList", models.ErrUserDoesNotHaveAccessToRepo{
-			UserID:   ctx.User.ID,
+			UserID:   ctx.Doer.ID,
 			RepoName: ctx.Repo.Repository.LowerName,
 		})
 		return
diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go
index d814ae909..6cf51b246 100644
--- a/routers/api/v1/repo/fork.go
+++ b/routers/api/v1/repo/fork.go
@@ -58,7 +58,7 @@ func ListForks(ctx *context.APIContext) {
 	}
 	apiForks := make([]*api.Repository, len(forks))
 	for i, fork := range forks {
-		access, err := models.AccessLevel(ctx.User, fork)
+		access, err := models.AccessLevel(ctx.Doer, fork)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 			return
@@ -106,7 +106,7 @@ func CreateFork(ctx *context.APIContext) {
 	repo := ctx.Repo.Repository
 	var forker *user_model.User // user/org that will own the fork
 	if form.Organization == nil {
-		forker = ctx.User
+		forker = ctx.Doer
 	} else {
 		org, err := models.GetOrgByName(*form.Organization)
 		if err != nil {
@@ -117,7 +117,7 @@ func CreateFork(ctx *context.APIContext) {
 			}
 			return
 		}
-		isMember, err := org.IsOrgMember(ctx.User.ID)
+		isMember, err := org.IsOrgMember(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
 			return
@@ -135,7 +135,7 @@ func CreateFork(ctx *context.APIContext) {
 		name = *form.Name
 	}
 
-	fork, err := repo_service.ForkRepository(ctx.User, forker, repo_service.ForkRepoOptions{
+	fork, err := repo_service.ForkRepository(ctx.Doer, forker, repo_service.ForkRepoOptions{
 		BaseRepo:    repo,
 		Name:        name,
 		Description: repo.Description,
diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go
index fdcaf5e38..c79a1d6b1 100644
--- a/routers/api/v1/repo/hook.go
+++ b/routers/api/v1/repo/hook.go
@@ -163,8 +163,8 @@ func TestHook(ctx *context.APIContext) {
 		Commits:    []*api.PayloadCommit{commit},
 		HeadCommit: commit,
 		Repo:       convert.ToRepo(ctx.Repo.Repository, perm.AccessModeNone),
-		Pusher:     convert.ToUserWithAccessMode(ctx.User, perm.AccessModeNone),
-		Sender:     convert.ToUserWithAccessMode(ctx.User, perm.AccessModeNone),
+		Pusher:     convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone),
+		Sender:     convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone),
 	}); err != nil {
 		ctx.Error(http.StatusInternalServerError, "PrepareWebhook: ", err)
 		return
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index c96eb3485..ef8c2d008 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -135,7 +135,7 @@ func SearchIssues(ctx *context.APIContext) {
 		// This needs to be a column that is not nil in fixtures or
 		// MySQL will return different results when sorting by null in some cases
 		OrderBy: db.SearchOrderByAlphabetically,
-		Actor:   ctx.User,
+		Actor:   ctx.Doer,
 	}
 	if ctx.IsSigned {
 		opts.Private = true
@@ -247,7 +247,7 @@ func SearchIssues(ctx *context.APIContext) {
 
 		ctxUserID := int64(0)
 		if ctx.IsSigned {
-			ctxUserID = ctx.User.ID
+			ctxUserID = ctx.Doer.ID
 		}
 
 		// Filter for: Created by User, Assigned to User, Mentioning User, Review of User Requested
@@ -597,8 +597,8 @@ func CreateIssue(ctx *context.APIContext) {
 		RepoID:       ctx.Repo.Repository.ID,
 		Repo:         ctx.Repo.Repository,
 		Title:        form.Title,
-		PosterID:     ctx.User.ID,
-		Poster:       ctx.User,
+		PosterID:     ctx.Doer.ID,
+		Poster:       ctx.Doer,
 		Content:      form.Body,
 		Ref:          form.Ref,
 		DeadlineUnix: deadlineUnix,
@@ -651,7 +651,7 @@ func CreateIssue(ctx *context.APIContext) {
 	}
 
 	if form.Closed {
-		if err := issue_service.ChangeStatus(issue, ctx.User, true); err != nil {
+		if err := issue_service.ChangeStatus(issue, ctx.Doer, true); err != nil {
 			if models.IsErrDependenciesLeft(err) {
 				ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
 				return
@@ -729,7 +729,7 @@ func EditIssue(ctx *context.APIContext) {
 		return
 	}
 
-	if !issue.IsPoster(ctx.User.ID) && !canWrite {
+	if !issue.IsPoster(ctx.Doer.ID) && !canWrite {
 		ctx.Status(http.StatusForbidden)
 		return
 	}
@@ -742,7 +742,7 @@ func EditIssue(ctx *context.APIContext) {
 		issue.Content = *form.Body
 	}
 	if form.Ref != nil {
-		err = issue_service.ChangeIssueRef(issue, ctx.User, *form.Ref)
+		err = issue_service.ChangeIssueRef(issue, ctx.Doer, *form.Ref)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "UpdateRef", err)
 			return
@@ -759,7 +759,7 @@ func EditIssue(ctx *context.APIContext) {
 			deadlineUnix = timeutil.TimeStamp(deadline.Unix())
 		}
 
-		if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
+		if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil {
 			ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err)
 			return
 		}
@@ -780,7 +780,7 @@ func EditIssue(ctx *context.APIContext) {
 			oneAssignee = *form.Assignee
 		}
 
-		err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.User)
+		err = issue_service.UpdateAssignees(issue, oneAssignee, form.Assignees, ctx.Doer)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "UpdateAssignees", err)
 			return
@@ -791,7 +791,7 @@ func EditIssue(ctx *context.APIContext) {
 		issue.MilestoneID != *form.Milestone {
 		oldMilestoneID := issue.MilestoneID
 		issue.MilestoneID = *form.Milestone
-		if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
+		if err = issue_service.ChangeMilestoneAssign(issue, ctx.Doer, oldMilestoneID); err != nil {
 			ctx.Error(http.StatusInternalServerError, "ChangeMilestoneAssign", err)
 			return
 		}
@@ -808,7 +808,7 @@ func EditIssue(ctx *context.APIContext) {
 		}
 		issue.IsClosed = api.StateClosed == api.StateType(*form.State)
 	}
-	statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.User)
+	statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.Doer)
 	if err != nil {
 		if models.IsErrDependenciesLeft(err) {
 			ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies")
@@ -819,11 +819,11 @@ func EditIssue(ctx *context.APIContext) {
 	}
 
 	if titleChanged {
-		notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle)
+		notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle)
 	}
 
 	if statusChangeComment != nil {
-		notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed)
+		notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed)
 	}
 
 	// Refetch from database to assign some automatic values
@@ -877,7 +877,7 @@ func DeleteIssue(ctx *context.APIContext) {
 		return
 	}
 
-	if err = issue_service.DeleteIssue(ctx.User, ctx.Repo.GitRepo, issue); err != nil {
+	if err = issue_service.DeleteIssue(ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteIssueByID", err)
 		return
 	}
@@ -946,7 +946,7 @@ func UpdateIssueDeadline(ctx *context.APIContext) {
 		deadlineUnix = timeutil.TimeStamp(deadline.Unix())
 	}
 
-	if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
+	if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil {
 		ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err)
 		return
 	}
diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go
index f90028a0a..d63a71afc 100644
--- a/routers/api/v1/repo/issue_comment.go
+++ b/routers/api/v1/repo/issue_comment.go
@@ -183,9 +183,9 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) {
 
 	var apiComments []*api.TimelineComment
 	for _, comment := range comments {
-		if comment.Type != models.CommentTypeCode && isXRefCommentAccessible(ctx.User, comment, issue.RepoID) {
+		if comment.Type != models.CommentTypeCode && isXRefCommentAccessible(ctx.Doer, comment, issue.RepoID) {
 			comment.Issue = issue
-			apiComments = append(apiComments, convert.ToTimelineComment(comment, ctx.User))
+			apiComments = append(apiComments, convert.ToTimelineComment(comment, ctx.Doer))
 		}
 	}
 
@@ -347,12 +347,12 @@ func CreateIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
+	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
 		ctx.Error(http.StatusForbidden, "CreateIssueComment", errors.New(ctx.Tr("repo.issues.comment_on_locked")))
 		return
 	}
 
-	comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Body, nil)
+	comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Body, nil)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "CreateIssueComment", err)
 		return
@@ -534,7 +534,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
+	if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
 		ctx.Status(http.StatusForbidden)
 		return
 	}
@@ -546,7 +546,7 @@ func editIssueComment(ctx *context.APIContext, form api.EditIssueCommentOption)
 
 	oldContent := comment.Content
 	comment.Content = form.Body
-	if err := comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil {
+	if err := comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil {
 		ctx.Error(http.StatusInternalServerError, "UpdateComment", err)
 		return
 	}
@@ -637,7 +637,7 @@ func deleteIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
+	if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.IsAdmin()) {
 		ctx.Status(http.StatusForbidden)
 		return
 	} else if comment.Type != models.CommentTypeComment {
@@ -645,7 +645,7 @@ func deleteIssueComment(ctx *context.APIContext) {
 		return
 	}
 
-	if err = comment_service.DeleteComment(ctx.User, comment); err != nil {
+	if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteCommentByID", err)
 		return
 	}
diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go
index 0469ae247..e314e756d 100644
--- a/routers/api/v1/repo/issue_label.go
+++ b/routers/api/v1/repo/issue_label.go
@@ -106,7 +106,7 @@ func AddIssueLabels(ctx *context.APIContext) {
 		return
 	}
 
-	if err = issue_service.AddLabels(issue, ctx.User, labels); err != nil {
+	if err = issue_service.AddLabels(issue, ctx.Doer, labels); err != nil {
 		ctx.Error(http.StatusInternalServerError, "AddLabels", err)
 		return
 	}
@@ -183,7 +183,7 @@ func DeleteIssueLabel(ctx *context.APIContext) {
 		return
 	}
 
-	if err := issue_service.RemoveLabel(issue, ctx.User, label); err != nil {
+	if err := issue_service.RemoveLabel(issue, ctx.Doer, label); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteIssueLabel", err)
 		return
 	}
@@ -232,7 +232,7 @@ func ReplaceIssueLabels(ctx *context.APIContext) {
 		return
 	}
 
-	if err := issue_service.ReplaceLabels(issue, ctx.User, labels); err != nil {
+	if err := issue_service.ReplaceLabels(issue, ctx.Doer, labels); err != nil {
 		ctx.Error(http.StatusInternalServerError, "ReplaceLabels", err)
 		return
 	}
@@ -291,7 +291,7 @@ func ClearIssueLabels(ctx *context.APIContext) {
 		return
 	}
 
-	if err := issue_service.ClearLabels(issue, ctx.User); err != nil {
+	if err := issue_service.ClearLabels(issue, ctx.Doer); err != nil {
 		ctx.Error(http.StatusInternalServerError, "ClearLabels", err)
 		return
 	}
diff --git a/routers/api/v1/repo/issue_reaction.go b/routers/api/v1/repo/issue_reaction.go
index 9c5086700..38f4bc475 100644
--- a/routers/api/v1/repo/issue_reaction.go
+++ b/routers/api/v1/repo/issue_reaction.go
@@ -81,7 +81,7 @@ func GetIssueCommentReactions(ctx *context.APIContext) {
 	var result []api.Reaction
 	for _, r := range reactions {
 		result = append(result, api.Reaction{
-			User:     convert.ToUser(r.User, ctx.User),
+			User:     convert.ToUser(r.User, ctx.Doer),
 			Reaction: r.Type,
 			Created:  r.CreatedUnix.AsTime(),
 		})
@@ -197,13 +197,13 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
 
 	if isCreateType {
 		// PostIssueCommentReaction part
-		reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Reaction)
+		reaction, err := models.CreateCommentReaction(ctx.Doer, comment.Issue, comment, form.Reaction)
 		if err != nil {
 			if models.IsErrForbiddenIssueReaction(err) {
 				ctx.Error(http.StatusForbidden, err.Error(), err)
 			} else if models.IsErrReactionAlreadyExist(err) {
 				ctx.JSON(http.StatusOK, api.Reaction{
-					User:     convert.ToUser(ctx.User, ctx.User),
+					User:     convert.ToUser(ctx.Doer, ctx.Doer),
 					Reaction: reaction.Type,
 					Created:  reaction.CreatedUnix.AsTime(),
 				})
@@ -214,13 +214,13 @@ func changeIssueCommentReaction(ctx *context.APIContext, form api.EditReactionOp
 		}
 
 		ctx.JSON(http.StatusCreated, api.Reaction{
-			User:     convert.ToUser(ctx.User, ctx.User),
+			User:     convert.ToUser(ctx.Doer, ctx.Doer),
 			Reaction: reaction.Type,
 			Created:  reaction.CreatedUnix.AsTime(),
 		})
 	} else {
 		// DeleteIssueCommentReaction part
-		err = models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Reaction)
+		err = models.DeleteCommentReaction(ctx.Doer, comment.Issue, comment, form.Reaction)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "DeleteCommentReaction", err)
 			return
@@ -299,7 +299,7 @@ func GetIssueReactions(ctx *context.APIContext) {
 	var result []api.Reaction
 	for _, r := range reactions {
 		result = append(result, api.Reaction{
-			User:     convert.ToUser(r.User, ctx.User),
+			User:     convert.ToUser(r.User, ctx.Doer),
 			Reaction: r.Type,
 			Created:  r.CreatedUnix.AsTime(),
 		})
@@ -407,13 +407,13 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
 
 	if isCreateType {
 		// PostIssueReaction part
-		reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Reaction)
+		reaction, err := models.CreateIssueReaction(ctx.Doer, issue, form.Reaction)
 		if err != nil {
 			if models.IsErrForbiddenIssueReaction(err) {
 				ctx.Error(http.StatusForbidden, err.Error(), err)
 			} else if models.IsErrReactionAlreadyExist(err) {
 				ctx.JSON(http.StatusOK, api.Reaction{
-					User:     convert.ToUser(ctx.User, ctx.User),
+					User:     convert.ToUser(ctx.Doer, ctx.Doer),
 					Reaction: reaction.Type,
 					Created:  reaction.CreatedUnix.AsTime(),
 				})
@@ -424,13 +424,13 @@ func changeIssueReaction(ctx *context.APIContext, form api.EditReactionOption, i
 		}
 
 		ctx.JSON(http.StatusCreated, api.Reaction{
-			User:     convert.ToUser(ctx.User, ctx.User),
+			User:     convert.ToUser(ctx.Doer, ctx.Doer),
 			Reaction: reaction.Type,
 			Created:  reaction.CreatedUnix.AsTime(),
 		})
 	} else {
 		// DeleteIssueReaction part
-		err = models.DeleteIssueReaction(ctx.User, issue, form.Reaction)
+		err = models.DeleteIssueReaction(ctx.Doer, issue, form.Reaction)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "DeleteIssueReaction", err)
 			return
diff --git a/routers/api/v1/repo/issue_stopwatch.go b/routers/api/v1/repo/issue_stopwatch.go
index ce8018251..19ee983b8 100644
--- a/routers/api/v1/repo/issue_stopwatch.go
+++ b/routers/api/v1/repo/issue_stopwatch.go
@@ -56,7 +56,7 @@ func StartIssueStopwatch(ctx *context.APIContext) {
 		return
 	}
 
-	if err := models.CreateIssueStopwatch(db.DefaultContext, ctx.User, issue); err != nil {
+	if err := models.CreateIssueStopwatch(db.DefaultContext, ctx.Doer, issue); err != nil {
 		ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
 		return
 	}
@@ -105,7 +105,7 @@ func StopIssueStopwatch(ctx *context.APIContext) {
 		return
 	}
 
-	if err := models.FinishIssueStopwatch(db.DefaultContext, ctx.User, issue); err != nil {
+	if err := models.FinishIssueStopwatch(db.DefaultContext, ctx.Doer, issue); err != nil {
 		ctx.Error(http.StatusInternalServerError, "CreateOrStopIssueStopwatch", err)
 		return
 	}
@@ -154,7 +154,7 @@ func DeleteIssueStopwatch(ctx *context.APIContext) {
 		return
 	}
 
-	if err := models.CancelStopwatch(ctx.User, issue); err != nil {
+	if err := models.CancelStopwatch(ctx.Doer, issue); err != nil {
 		ctx.Error(http.StatusInternalServerError, "CancelStopwatch", err)
 		return
 	}
@@ -179,12 +179,12 @@ func prepareIssueStopwatch(ctx *context.APIContext, shouldExist bool) (*models.I
 		return nil, errors.New("Unable to write to PRs")
 	}
 
-	if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
 		ctx.Status(http.StatusForbidden)
 		return nil, errors.New("Cannot use time tracker")
 	}
 
-	if models.StopwatchExists(ctx.User.ID, issue.ID) != shouldExist {
+	if models.StopwatchExists(ctx.Doer.ID, issue.ID) != shouldExist {
 		if shouldExist {
 			ctx.Error(http.StatusConflict, "StopwatchExists", "cannot stop/cancel a non existent stopwatch")
 			err = errors.New("cannot stop/cancel a non existent stopwatch")
@@ -220,13 +220,13 @@ func GetStopwatches(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/StopWatchList"
 
-	sws, err := models.GetUserStopwatches(ctx.User.ID, utils.GetListOptions(ctx))
+	sws, err := models.GetUserStopwatches(ctx.Doer.ID, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetUserStopwatches", err)
 		return
 	}
 
-	count, err := models.CountUserStopwatches(ctx.User.ID)
+	count, err := models.CountUserStopwatches(ctx.Doer.ID)
 	if err != nil {
 		ctx.InternalServerError(err)
 		return
diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go
index 76c668697..f00c85b12 100644
--- a/routers/api/v1/repo/issue_subscription.go
+++ b/routers/api/v1/repo/issue_subscription.go
@@ -128,8 +128,8 @@ func setIssueSubscription(ctx *context.APIContext, watch bool) {
 	}
 
 	// only admin and user for itself can change subscription
-	if user.ID != ctx.User.ID && !ctx.User.IsAdmin {
-		ctx.Error(http.StatusForbidden, "User", fmt.Errorf("%s is not permitted to change subscriptions for %s", ctx.User.Name, user.Name))
+	if user.ID != ctx.Doer.ID && !ctx.Doer.IsAdmin {
+		ctx.Error(http.StatusForbidden, "User", fmt.Errorf("%s is not permitted to change subscriptions for %s", ctx.Doer.Name, user.Name))
 		return
 	}
 
@@ -197,7 +197,7 @@ func CheckIssueSubscription(ctx *context.APIContext) {
 		return
 	}
 
-	watching, err := models.CheckIssueWatch(ctx.User, issue)
+	watching, err := models.CheckIssueWatch(ctx.Doer, issue)
 	if err != nil {
 		ctx.InternalServerError(err)
 		return
@@ -281,7 +281,7 @@ func GetIssueSubscribers(ctx *context.APIContext) {
 	}
 	apiUsers := make([]*api.User, 0, len(users))
 	for _, v := range users {
-		apiUsers = append(apiUsers, convert.ToUser(v, ctx.User))
+		apiUsers = append(apiUsers, convert.ToUser(v, ctx.Doer))
 	}
 
 	count, err := models.CountIssueWatchers(issue.ID)
diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go
index 79ba59996..5cc39becb 100644
--- a/routers/api/v1/repo/issue_tracked_time.go
+++ b/routers/api/v1/repo/issue_tracked_time.go
@@ -108,13 +108,13 @@ func ListTrackedTimes(ctx *context.APIContext) {
 		return
 	}
 
-	cantSetUser := !ctx.User.IsAdmin &&
-		opts.UserID != ctx.User.ID &&
+	cantSetUser := !ctx.Doer.IsAdmin &&
+		opts.UserID != ctx.Doer.ID &&
 		!ctx.IsUserRepoWriter([]unit.Type{unit.TypeIssues})
 
 	if cantSetUser {
 		if opts.UserID == 0 {
-			opts.UserID = ctx.User.ID
+			opts.UserID = ctx.Doer.ID
 		} else {
 			ctx.Error(http.StatusForbidden, "", fmt.Errorf("query by user not allowed; not enough rights"))
 			return
@@ -189,7 +189,7 @@ func AddTime(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
 		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
 			ctx.Error(http.StatusBadRequest, "", "time tracking disabled")
 			return
@@ -198,9 +198,9 @@ func AddTime(ctx *context.APIContext) {
 		return
 	}
 
-	user := ctx.User
+	user := ctx.Doer
 	if form.User != "" {
-		if (ctx.IsUserRepoAdmin() && ctx.User.Name != form.User) || ctx.User.IsAdmin {
+		if (ctx.IsUserRepoAdmin() && ctx.Doer.Name != form.User) || ctx.Doer.IsAdmin {
 			// allow only RepoAdmin, Admin and User to add time
 			user, err = user_model.GetUserByName(form.User)
 			if err != nil {
@@ -270,7 +270,7 @@ func ResetIssueTime(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
 		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
 			ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
 			return
@@ -279,7 +279,7 @@ func ResetIssueTime(ctx *context.APIContext) {
 		return
 	}
 
-	err = models.DeleteIssueUserTimes(issue, ctx.User)
+	err = models.DeleteIssueUserTimes(issue, ctx.Doer)
 	if err != nil {
 		if models.IsErrNotExist(err) {
 			ctx.Error(http.StatusNotFound, "DeleteIssueUserTimes", err)
@@ -341,7 +341,7 @@ func DeleteTime(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.Repo.CanUseTimetracker(issue, ctx.User) {
+	if !ctx.Repo.CanUseTimetracker(issue, ctx.Doer) {
 		if !ctx.Repo.Repository.IsTimetrackerEnabled() {
 			ctx.JSON(http.StatusBadRequest, struct{ Message string }{Message: "time tracking disabled"})
 			return
@@ -364,7 +364,7 @@ func DeleteTime(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.User.IsAdmin && time.UserID != ctx.User.ID {
+	if !ctx.Doer.IsAdmin && time.UserID != ctx.Doer.ID {
 		// Only Admin and User itself can delete their time
 		ctx.Status(http.StatusForbidden)
 		return
@@ -428,7 +428,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.IsUserRepoAdmin() && !ctx.User.IsAdmin && ctx.User.ID != user.ID {
+	if !ctx.IsUserRepoAdmin() && !ctx.Doer.IsAdmin && ctx.Doer.ID != user.ID {
 		ctx.Error(http.StatusForbidden, "", fmt.Errorf("query by user not allowed; not enough rights"))
 		return
 	}
@@ -527,13 +527,13 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
 		return
 	}
 
-	cantSetUser := !ctx.User.IsAdmin &&
-		opts.UserID != ctx.User.ID &&
+	cantSetUser := !ctx.Doer.IsAdmin &&
+		opts.UserID != ctx.Doer.ID &&
 		!ctx.IsUserRepoWriter([]unit.Type{unit.TypeIssues})
 
 	if cantSetUser {
 		if opts.UserID == 0 {
-			opts.UserID = ctx.User.ID
+			opts.UserID = ctx.Doer.ID
 		} else {
 			ctx.Error(http.StatusForbidden, "", fmt.Errorf("query by user not allowed; not enough rights"))
 			return
@@ -593,7 +593,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
 
 	opts := &models.FindTrackedTimesOptions{
 		ListOptions: utils.GetListOptions(ctx),
-		UserID:      ctx.User.ID,
+		UserID:      ctx.Doer.ID,
 	}
 
 	var err error
diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go
index 669cc7c51..35efa64ad 100644
--- a/routers/api/v1/repo/key.go
+++ b/routers/api/v1/repo/key.go
@@ -107,7 +107,7 @@ func ListDeployKeys(ctx *context.APIContext) {
 			return
 		}
 		apiKeys[i] = convert.ToDeployKey(apiLink, keys[i])
-		if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == keys[i].RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) {
+		if ctx.Doer.IsAdmin || ((ctx.Repo.Repository.ID == keys[i].RepoID) && (ctx.Doer.ID == ctx.Repo.Owner.ID)) {
 			apiKeys[i], _ = appendPrivateInformation(apiKeys[i], keys[i], ctx.Repo.Repository)
 		}
 	}
@@ -161,7 +161,7 @@ func GetDeployKey(ctx *context.APIContext) {
 
 	apiLink := composeDeployKeysAPILink(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name)
 	apiKey := convert.ToDeployKey(apiLink, key)
-	if ctx.User.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.User.ID == ctx.Repo.Owner.ID)) {
+	if ctx.Doer.IsAdmin || ((ctx.Repo.Repository.ID == key.RepoID) && (ctx.Doer.ID == ctx.Repo.Owner.ID)) {
 		apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Repo.Repository)
 	}
 	ctx.JSON(http.StatusOK, apiKey)
@@ -270,7 +270,7 @@ func DeleteDeploykey(ctx *context.APIContext) {
 	//   "403":
 	//     "$ref": "#/responses/forbidden"
 
-	if err := asymkey_service.DeleteDeployKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
+	if err := asymkey_service.DeleteDeployKey(ctx.Doer, ctx.ParamsInt64(":id")); err != nil {
 		if asymkey_model.IsErrKeyAccessDenied(err) {
 			ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
 		} else {
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index 26da83554..1461c2a14 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -66,7 +66,7 @@ func Migrate(ctx *context.APIContext) {
 	} else if form.RepoOwnerID != 0 {
 		repoOwner, err = user_model.GetUserByID(form.RepoOwnerID)
 	} else {
-		repoOwner = ctx.User
+		repoOwner = ctx.Doer
 	}
 	if err != nil {
 		if user_model.IsErrUserNotExist(err) {
@@ -82,15 +82,15 @@ func Migrate(ctx *context.APIContext) {
 		return
 	}
 
-	if !ctx.User.IsAdmin {
-		if !repoOwner.IsOrganization() && ctx.User.ID != repoOwner.ID {
+	if !ctx.Doer.IsAdmin {
+		if !repoOwner.IsOrganization() && ctx.Doer.ID != repoOwner.ID {
 			ctx.Error(http.StatusForbidden, "", "Given user is not an organization.")
 			return
 		}
 
 		if repoOwner.IsOrganization() {
 			// Check ownership of organization.
-			isOwner, err := models.OrgFromUser(repoOwner).IsOwnedBy(ctx.User.ID)
+			isOwner, err := models.OrgFromUser(repoOwner).IsOwnedBy(ctx.Doer.ID)
 			if err != nil {
 				ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err)
 				return
@@ -103,7 +103,7 @@ func Migrate(ctx *context.APIContext) {
 
 	remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
 	if err == nil {
-		err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.User)
+		err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
 	}
 	if err != nil {
 		handleRemoteAddrError(ctx, err)
@@ -130,7 +130,7 @@ func Migrate(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "", ctx.Tr("repo.migrate.invalid_lfs_endpoint"))
 			return
 		}
-		err = migrations.IsMigrateURLAllowed(ep.String(), ctx.User)
+		err = migrations.IsMigrateURLAllowed(ep.String(), ctx.Doer)
 		if err != nil {
 			handleRemoteAddrError(ctx, err)
 			return
@@ -167,7 +167,7 @@ func Migrate(ctx *context.APIContext) {
 		opts.Releases = false
 	}
 
-	repo, err := repo_module.CreateRepository(ctx.User, repoOwner, models.CreateRepoOptions{
+	repo, err := repo_module.CreateRepository(ctx.Doer, repoOwner, models.CreateRepoOptions{
 		Name:           opts.RepoName,
 		Description:    opts.Description,
 		OriginalURL:    form.CloneAddr,
@@ -192,18 +192,18 @@ func Migrate(ctx *context.APIContext) {
 		}
 
 		if err == nil {
-			notification.NotifyMigrateRepository(ctx.User, repoOwner, repo)
+			notification.NotifyMigrateRepository(ctx.Doer, repoOwner, repo)
 			return
 		}
 
 		if repo != nil {
-			if errDelete := models.DeleteRepository(ctx.User, repoOwner.ID, repo.ID); errDelete != nil {
+			if errDelete := models.DeleteRepository(ctx.Doer, repoOwner.ID, repo.ID); errDelete != nil {
 				log.Error("DeleteRepository: %v", errDelete)
 			}
 		}
 	}()
 
-	if repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.User, repoOwner.Name, opts, nil); err != nil {
+	if repo, err = migrations.MigrateRepository(graceful.GetManager().HammerContext(), ctx.Doer, repoOwner.Name, opts, nil); err != nil {
 		handleMigrateError(ctx, repoOwner, remoteAddr, err)
 		return
 	}
diff --git a/routers/api/v1/repo/patch.go b/routers/api/v1/repo/patch.go
index 64a7a32d1..ae64c6efe 100644
--- a/routers/api/v1/repo/patch.go
+++ b/routers/api/v1/repo/patch.go
@@ -79,13 +79,13 @@ func ApplyDiffPatch(ctx *context.APIContext) {
 
 	if !canWriteFiles(ctx.Repo) {
 		ctx.Error(http.StatusInternalServerError, "ApplyPatch", models.ErrUserDoesNotHaveAccessToRepo{
-			UserID:   ctx.User.ID,
+			UserID:   ctx.Doer.ID,
 			RepoName: ctx.Repo.Repository.LowerName,
 		})
 		return
 	}
 
-	fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.User, opts)
+	fileResponse, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts)
 	if err != nil {
 		if models.IsErrUserCannotCommit(err) || models.IsErrFilePathProtected(err) {
 			ctx.Error(http.StatusForbidden, "Access", err)
diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go
index a494cb06c..ba3c42d9d 100644
--- a/routers/api/v1/repo/pull.go
+++ b/routers/api/v1/repo/pull.go
@@ -118,7 +118,7 @@ func ListPullRequests(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
 			return
 		}
-		apiPrs[i] = convert.ToAPIPullRequest(ctx, prs[i], ctx.User)
+		apiPrs[i] = convert.ToAPIPullRequest(ctx, prs[i], ctx.Doer)
 	}
 
 	ctx.SetLinkHeader(int(maxResults), listOptions.PageSize)
@@ -174,7 +174,7 @@ func GetPullRequest(ctx *context.APIContext) {
 		ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
 		return
 	}
-	ctx.JSON(http.StatusOK, convert.ToAPIPullRequest(ctx, pr, ctx.User))
+	ctx.JSON(http.StatusOK, convert.ToAPIPullRequest(ctx, pr, ctx.Doer))
 }
 
 // DownloadPullDiffOrPatch render a pull's raw diff or patch
@@ -363,8 +363,8 @@ func CreatePullRequest(ctx *context.APIContext) {
 	prIssue := &models.Issue{
 		RepoID:       repo.ID,
 		Title:        form.Title,
-		PosterID:     ctx.User.ID,
-		Poster:       ctx.User,
+		PosterID:     ctx.Doer.ID,
+		Poster:       ctx.Doer,
 		MilestoneID:  milestoneID,
 		IsPull:       true,
 		Content:      form.Body,
@@ -420,7 +420,7 @@ func CreatePullRequest(ctx *context.APIContext) {
 	}
 
 	log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID)
-	ctx.JSON(http.StatusCreated, convert.ToAPIPullRequest(ctx, pr, ctx.User))
+	ctx.JSON(http.StatusCreated, convert.ToAPIPullRequest(ctx, pr, ctx.Doer))
 }
 
 // EditPullRequest does what it says
@@ -484,7 +484,7 @@ func EditPullRequest(ctx *context.APIContext) {
 	issue := pr.Issue
 	issue.Repo = ctx.Repo.Repository
 
-	if !issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWrite(unit.TypePullRequests) {
+	if !issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWrite(unit.TypePullRequests) {
 		ctx.Status(http.StatusForbidden)
 		return
 	}
@@ -506,7 +506,7 @@ func EditPullRequest(ctx *context.APIContext) {
 			deadlineUnix = timeutil.TimeStamp(deadline.Unix())
 		}
 
-		if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.User); err != nil {
+		if err := models.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil {
 			ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err)
 			return
 		}
@@ -522,7 +522,7 @@ func EditPullRequest(ctx *context.APIContext) {
 	// Send an empty array ([]) to clear all assignees from the Issue.
 
 	if ctx.Repo.CanWrite(unit.TypePullRequests) && (form.Assignees != nil || len(form.Assignee) > 0) {
-		err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.User)
+		err = issue_service.UpdateAssignees(issue, form.Assignee, form.Assignees, ctx.Doer)
 		if err != nil {
 			if user_model.IsErrUserNotExist(err) {
 				ctx.Error(http.StatusUnprocessableEntity, "", fmt.Sprintf("Assignee does not exist: [name: %s]", err))
@@ -537,7 +537,7 @@ func EditPullRequest(ctx *context.APIContext) {
 		issue.MilestoneID != form.Milestone {
 		oldMilestoneID := issue.MilestoneID
 		issue.MilestoneID = form.Milestone
-		if err = issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
+		if err = issue_service.ChangeMilestoneAssign(issue, ctx.Doer, oldMilestoneID); err != nil {
 			ctx.Error(http.StatusInternalServerError, "ChangeMilestoneAssign", err)
 			return
 		}
@@ -560,7 +560,7 @@ func EditPullRequest(ctx *context.APIContext) {
 			labels = append(labels, orgLabels...)
 		}
 
-		if err = issue.ReplaceLabels(labels, ctx.User); err != nil {
+		if err = issue.ReplaceLabels(labels, ctx.Doer); err != nil {
 			ctx.Error(http.StatusInternalServerError, "ReplaceLabelsError", err)
 			return
 		}
@@ -573,7 +573,7 @@ func EditPullRequest(ctx *context.APIContext) {
 		}
 		issue.IsClosed = api.StateClosed == api.StateType(*form.State)
 	}
-	statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.User)
+	statusChangeComment, titleChanged, err := models.UpdateIssueByAPI(issue, ctx.Doer)
 	if err != nil {
 		if models.IsErrDependenciesLeft(err) {
 			ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies")
@@ -584,11 +584,11 @@ func EditPullRequest(ctx *context.APIContext) {
 	}
 
 	if titleChanged {
-		notification.NotifyIssueChangeTitle(ctx.User, issue, oldTitle)
+		notification.NotifyIssueChangeTitle(ctx.Doer, issue, oldTitle)
 	}
 
 	if statusChangeComment != nil {
-		notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed)
+		notification.NotifyIssueChangeStatus(ctx.Doer, issue, statusChangeComment, issue.IsClosed)
 	}
 
 	// change pull target branch
@@ -597,7 +597,7 @@ func EditPullRequest(ctx *context.APIContext) {
 			ctx.Error(http.StatusNotFound, "NewBaseBranchNotExist", fmt.Errorf("new base '%s' not exist", form.Base))
 			return
 		}
-		if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.User, form.Base); err != nil {
+		if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.Doer, form.Base); err != nil {
 			if models.IsErrPullRequestAlreadyExists(err) {
 				ctx.Error(http.StatusConflict, "IsErrPullRequestAlreadyExists", err)
 				return
@@ -612,7 +612,7 @@ func EditPullRequest(ctx *context.APIContext) {
 			}
 			return
 		}
-		notification.NotifyPullRequestChangeTargetBranch(ctx.User, pr, form.Base)
+		notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, form.Base)
 	}
 
 	// Refetch from database
@@ -627,7 +627,7 @@ func EditPullRequest(ctx *context.APIContext) {
 	}
 
 	// TODO this should be 200, not 201
-	ctx.JSON(http.StatusCreated, convert.ToAPIPullRequest(ctx, pr, ctx.User))
+	ctx.JSON(http.StatusCreated, convert.ToAPIPullRequest(ctx, pr, ctx.Doer))
 }
 
 // IsPullRequestMerged checks if a PR exists given an index
@@ -737,7 +737,7 @@ func MergePullRequest(ctx *context.APIContext) {
 
 	if ctx.IsSigned {
 		// Update issue-user.
-		if err = pr.Issue.ReadBy(ctx.User.ID); err != nil {
+		if err = pr.Issue.ReadBy(ctx.Doer.ID); err != nil {
 			ctx.Error(http.StatusInternalServerError, "ReadBy", err)
 			return
 		}
@@ -748,7 +748,7 @@ func MergePullRequest(ctx *context.APIContext) {
 		return
 	}
 
-	allowedMerge, err := pull_service.IsUserAllowedToMerge(pr, ctx.Repo.Permission, ctx.User)
+	allowedMerge, err := pull_service.IsUserAllowedToMerge(pr, ctx.Repo.Permission, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "IsUSerAllowedToMerge", err)
 		return
@@ -765,7 +765,7 @@ func MergePullRequest(ctx *context.APIContext) {
 
 	// handle manually-merged mark
 	if repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged {
-		if err = pull_service.MergedManually(pr, ctx.User, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
+		if err = pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
 			if models.IsErrInvalidMergeStyle(err) {
 				ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
 				return
@@ -797,7 +797,7 @@ func MergePullRequest(ctx *context.APIContext) {
 			return
 		}
 		if form.ForceMerge != nil && *form.ForceMerge {
-			if isRepoAdmin, err := models.IsUserRepoAdmin(pr.BaseRepo, ctx.User); err != nil {
+			if isRepoAdmin, err := models.IsUserRepoAdmin(pr.BaseRepo, ctx.Doer); err != nil {
 				ctx.Error(http.StatusInternalServerError, "IsUserRepoAdmin", err)
 				return
 			} else if !isRepoAdmin {
@@ -809,7 +809,7 @@ func MergePullRequest(ctx *context.APIContext) {
 		}
 	}
 
-	if _, err := pull_service.IsSignedIfRequired(ctx, pr, ctx.User); err != nil {
+	if _, err := pull_service.IsSignedIfRequired(ctx, pr, ctx.Doer); err != nil {
 		if !asymkey_service.IsErrWontSign(err) {
 			ctx.Error(http.StatusInternalServerError, "IsSignedIfRequired", err)
 			return
@@ -837,7 +837,7 @@ func MergePullRequest(ctx *context.APIContext) {
 		message += "\n\n" + form.MergeMessageField
 	}
 
-	if err := pull_service.Merge(ctx, pr, ctx.User, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil {
+	if err := pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil {
 		if models.IsErrInvalidMergeStyle(err) {
 			ctx.Error(http.StatusMethodNotAllowed, "Invalid merge style", fmt.Errorf("%s is not allowed an allowed merge style for this repository", repo_model.MergeStyle(form.Do)))
 			return
@@ -894,7 +894,7 @@ func MergePullRequest(ctx *context.APIContext) {
 			}
 			defer headRepo.Close()
 		}
-		if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
+		if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
 			switch {
 			case git.IsErrBranchNotExist(err):
 				ctx.NotFound(err)
@@ -907,7 +907,7 @@ func MergePullRequest(ctx *context.APIContext) {
 			}
 			return
 		}
-		if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
+		if err := models.AddDeletePRBranchComment(ctx.Doer, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
 			// Do not fail here as branch has already been deleted
 			log.Error("DeleteBranch: %v", err)
 		}
@@ -989,7 +989,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
 	}
 
 	// user should have permission to read baseRepo's codes and pulls, NOT headRepo's
-	permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
+	permBase, err := models.GetUserRepoPermission(baseRepo, ctx.Doer)
 	if err != nil {
 		headGitRepo.Close()
 		ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
@@ -998,7 +998,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
 	if !permBase.CanReadIssuesOrPulls(true) || !permBase.CanRead(unit.TypeCode) {
 		if log.IsTrace() {
 			log.Trace("Permission Denied: User %-v cannot create/read pull requests or cannot read code in Repo %-v\nUser in baseRepo has Permissions: %-+v",
-				ctx.User,
+				ctx.Doer,
 				baseRepo,
 				permBase)
 		}
@@ -1008,7 +1008,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
 	}
 
 	// user should have permission to read headrepo's codes
-	permHead, err := models.GetUserRepoPermission(headRepo, ctx.User)
+	permHead, err := models.GetUserRepoPermission(headRepo, ctx.Doer)
 	if err != nil {
 		headGitRepo.Close()
 		ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
@@ -1017,7 +1017,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
 	if !permHead.CanRead(unit.TypeCode) {
 		if log.IsTrace() {
 			log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
-				ctx.User,
+				ctx.Doer,
 				headRepo,
 				permHead)
 		}
@@ -1120,7 +1120,7 @@ func UpdatePullRequest(ctx *context.APIContext) {
 
 	rebase := ctx.FormString("style") == "rebase"
 
-	allowedUpdateByMerge, allowedUpdateByRebase, err := pull_service.IsUserAllowedToUpdate(pr, ctx.User)
+	allowedUpdateByMerge, allowedUpdateByRebase, err := pull_service.IsUserAllowedToUpdate(pr, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "IsUserAllowedToMerge", err)
 		return
@@ -1134,7 +1134,7 @@ func UpdatePullRequest(ctx *context.APIContext) {
 	// default merge commit message
 	message := fmt.Sprintf("Merge branch '%s' into %s", pr.BaseBranch, pr.HeadBranch)
 
-	if err = pull_service.Update(ctx, pr, ctx.User, message, rebase); err != nil {
+	if err = pull_service.Update(ctx, pr, ctx.Doer, message, rebase); err != nil {
 		if models.IsErrMergeConflicts(err) {
 			ctx.Error(http.StatusConflict, "Update", "merge failed because of conflict")
 			return
diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go
index 9eb63bafa..b4a484f68 100644
--- a/routers/api/v1/repo/pull_review.go
+++ b/routers/api/v1/repo/pull_review.go
@@ -97,7 +97,7 @@ func ListPullReviews(ctx *context.APIContext) {
 		return
 	}
 
-	apiReviews, err := convert.ToPullReviewList(ctx, allReviews, ctx.User)
+	apiReviews, err := convert.ToPullReviewList(ctx, allReviews, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReviewList", err)
 		return
@@ -148,7 +148,7 @@ func GetPullReview(ctx *context.APIContext) {
 		return
 	}
 
-	apiReview, err := convert.ToPullReview(ctx, review, ctx.User)
+	apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
 		return
@@ -198,7 +198,7 @@ func GetPullReviewComments(ctx *context.APIContext) {
 		return
 	}
 
-	apiComments, err := convert.ToPullReviewCommentList(ctx, review, ctx.User)
+	apiComments, err := convert.ToPullReviewCommentList(ctx, review, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReviewCommentList", err)
 		return
@@ -250,11 +250,11 @@ func DeletePullReview(ctx *context.APIContext) {
 		return
 	}
 
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.NotFound()
 		return
 	}
-	if !ctx.User.IsAdmin && ctx.User.ID != review.ReviewerID {
+	if !ctx.Doer.IsAdmin && ctx.Doer.ID != review.ReviewerID {
 		ctx.Error(http.StatusForbidden, "only admin and user itself can delete a review", nil)
 		return
 	}
@@ -353,7 +353,7 @@ func CreatePullReview(ctx *context.APIContext) {
 		}
 
 		if _, err := pull_service.CreateCodeComment(ctx,
-			ctx.User,
+			ctx.Doer,
 			ctx.Repo.GitRepo,
 			pr.Issue,
 			line,
@@ -369,14 +369,14 @@ func CreatePullReview(ctx *context.APIContext) {
 	}
 
 	// create review and associate all pending review comments
-	review, _, err := pull_service.SubmitReview(ctx, ctx.User, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, opts.CommitID, nil)
+	review, _, err := pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, opts.CommitID, nil)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
 		return
 	}
 
 	// convert response
-	apiReview, err := convert.ToPullReview(ctx, review, ctx.User)
+	apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
 		return
@@ -457,14 +457,14 @@ func SubmitPullReview(ctx *context.APIContext) {
 	}
 
 	// create review and associate all pending review comments
-	review, _, err = pull_service.SubmitReview(ctx, ctx.User, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, headCommitID, nil)
+	review, _, err = pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, pr.Issue, reviewType, opts.Body, headCommitID, nil)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "SubmitReview", err)
 		return
 	}
 
 	// convert response
-	apiReview, err := convert.ToPullReview(ctx, review, ctx.User)
+	apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
 		return
@@ -486,7 +486,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *models.PullRequest, even
 	switch event {
 	case api.ReviewStateApproved:
 		// can not approve your own PR
-		if pr.Issue.IsPoster(ctx.User.ID) {
+		if pr.Issue.IsPoster(ctx.Doer.ID) {
 			ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("approve your own pull is not allowed"))
 			return -1, true
 		}
@@ -495,7 +495,7 @@ func preparePullReviewType(ctx *context.APIContext, pr *models.PullRequest, even
 
 	case api.ReviewStateRequestChanges:
 		// can not reject your own PR
-		if pr.Issue.IsPoster(ctx.User.ID) {
+		if pr.Issue.IsPoster(ctx.Doer.ID) {
 			ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("reject your own pull is not allowed"))
 			return -1, true
 		}
@@ -551,7 +551,7 @@ func prepareSingleReview(ctx *context.APIContext) (*models.Review, *models.PullR
 	}
 
 	// make sure that the user has access to this review if it is pending
-	if review.Type == models.ReviewTypePending && review.ReviewerID != ctx.User.ID && !ctx.User.IsAdmin {
+	if review.Type == models.ReviewTypePending && review.ReviewerID != ctx.Doer.ID && !ctx.Doer.IsAdmin {
 		ctx.NotFound("GetReviewByID")
 		return nil, nil, true
 	}
@@ -663,7 +663,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 
 	reviewers := make([]*user_model.User, 0, len(opts.Reviewers))
 
-	permDoer, err := models.GetUserRepoPermission(pr.Issue.Repo, ctx.User)
+	permDoer, err := models.GetUserRepoPermission(pr.Issue.Repo, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
 		return
@@ -686,7 +686,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 			return
 		}
 
-		err = issue_service.IsValidReviewRequest(reviewer, ctx.User, isAdd, pr.Issue, &permDoer)
+		err = issue_service.IsValidReviewRequest(reviewer, ctx.Doer, isAdd, pr.Issue, &permDoer)
 		if err != nil {
 			if models.IsErrNotValidReviewRequest(err) {
 				ctx.Error(http.StatusUnprocessableEntity, "NotValidReviewRequest", err)
@@ -705,7 +705,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 	}
 
 	for _, reviewer := range reviewers {
-		comment, err := issue_service.ReviewRequest(pr.Issue, ctx.User, reviewer, isAdd)
+		comment, err := issue_service.ReviewRequest(pr.Issue, ctx.Doer, reviewer, isAdd)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
 			return
@@ -735,7 +735,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 				return
 			}
 
-			err = issue_service.IsValidTeamReviewRequest(teamReviewer, ctx.User, isAdd, pr.Issue)
+			err = issue_service.IsValidTeamReviewRequest(teamReviewer, ctx.Doer, isAdd, pr.Issue)
 			if err != nil {
 				if models.IsErrNotValidReviewRequest(err) {
 					ctx.Error(http.StatusUnprocessableEntity, "NotValidReviewRequest", err)
@@ -749,7 +749,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 		}
 
 		for _, teamReviewer := range teamReviewers {
-			comment, err := issue_service.TeamReviewRequest(pr.Issue, ctx.User, teamReviewer, isAdd)
+			comment, err := issue_service.TeamReviewRequest(pr.Issue, ctx.Doer, teamReviewer, isAdd)
 			if err != nil {
 				ctx.ServerError("TeamReviewRequest", err)
 				return
@@ -766,7 +766,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
 	}
 
 	if isAdd {
-		apiReviews, err := convert.ToPullReviewList(ctx, reviews, ctx.User)
+		apiReviews, err := convert.ToPullReviewList(ctx, reviews, ctx.Doer)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "convertToPullReviewList", err)
 			return
@@ -884,7 +884,7 @@ func dismissReview(ctx *context.APIContext, msg string, isDismiss bool) {
 		return
 	}
 
-	_, err := pull_service.DismissReview(ctx, review.ID, msg, ctx.User, isDismiss)
+	_, err := pull_service.DismissReview(ctx, review.ID, msg, ctx.Doer, isDismiss)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "pull_service.DismissReview", err)
 		return
@@ -896,7 +896,7 @@ func dismissReview(ctx *context.APIContext, msg string, isDismiss bool) {
 	}
 
 	// convert response
-	apiReview, err := convert.ToPullReview(ctx, review, ctx.User)
+	apiReview, err := convert.ToPullReview(ctx, review, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "convertToPullReview", err)
 		return
diff --git a/routers/api/v1/repo/release.go b/routers/api/v1/repo/release.go
index 3cdd79815..7d23a38ad 100644
--- a/routers/api/v1/repo/release.go
+++ b/routers/api/v1/repo/release.go
@@ -191,8 +191,8 @@ func CreateRelease(ctx *context.APIContext) {
 		}
 		rel = &models.Release{
 			RepoID:       ctx.Repo.Repository.ID,
-			PublisherID:  ctx.User.ID,
-			Publisher:    ctx.User,
+			PublisherID:  ctx.Doer.ID,
+			Publisher:    ctx.Doer,
 			TagName:      form.TagName,
 			Target:       form.Target,
 			Title:        form.Title,
@@ -220,12 +220,12 @@ func CreateRelease(ctx *context.APIContext) {
 		rel.Note = form.Note
 		rel.IsDraft = form.IsDraft
 		rel.IsPrerelease = form.IsPrerelease
-		rel.PublisherID = ctx.User.ID
+		rel.PublisherID = ctx.Doer.ID
 		rel.IsTag = false
 		rel.Repo = ctx.Repo.Repository
-		rel.Publisher = ctx.User
+		rel.Publisher = ctx.Doer
 
-		if err = releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, nil, nil, nil); err != nil {
+		if err = releaseservice.UpdateRelease(ctx.Doer, ctx.Repo.GitRepo, rel, nil, nil, nil); err != nil {
 			ctx.Error(http.StatusInternalServerError, "UpdateRelease", err)
 			return
 		}
@@ -300,7 +300,7 @@ func EditRelease(ctx *context.APIContext) {
 	if form.IsPrerelease != nil {
 		rel.IsPrerelease = *form.IsPrerelease
 	}
-	if err := releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, nil, nil, nil); err != nil {
+	if err := releaseservice.UpdateRelease(ctx.Doer, ctx.Repo.GitRepo, rel, nil, nil, nil); err != nil {
 		ctx.Error(http.StatusInternalServerError, "UpdateRelease", err)
 		return
 	}
@@ -356,7 +356,7 @@ func DeleteRelease(ctx *context.APIContext) {
 		ctx.NotFound()
 		return
 	}
-	if err := releaseservice.DeleteReleaseByID(ctx, id, ctx.User, false); err != nil {
+	if err := releaseservice.DeleteReleaseByID(ctx, id, ctx.Doer, false); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)
 		return
 	}
diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go
index b1bc48d30..c172b6612 100644
--- a/routers/api/v1/repo/release_attachment.go
+++ b/routers/api/v1/repo/release_attachment.go
@@ -184,7 +184,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) {
 	}
 
 	// Create a new attachment and save the file
-	attach, err := attachment.UploadAttachment(file, ctx.User.ID, release.RepoID, releaseID, filename, setting.Repository.Release.AllowedTypes)
+	attach, err := attachment.UploadAttachment(file, ctx.Doer.ID, release.RepoID, releaseID, filename, setting.Repository.Release.AllowedTypes)
 	if err != nil {
 		if upload.IsErrFileTypeForbidden(err) {
 			ctx.Error(http.StatusBadRequest, "DetectContentType", err)
diff --git a/routers/api/v1/repo/release_tags.go b/routers/api/v1/repo/release_tags.go
index d77bdf033..a737bcf1c 100644
--- a/routers/api/v1/repo/release_tags.go
+++ b/routers/api/v1/repo/release_tags.go
@@ -110,7 +110,7 @@ func DeleteReleaseByTag(ctx *context.APIContext) {
 		return
 	}
 
-	if err = releaseservice.DeleteReleaseByID(ctx, release.ID, ctx.User, false); err != nil {
+	if err = releaseservice.DeleteReleaseByID(ctx, release.ID, ctx.Doer, false); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)
 	}
 
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 560139c45..3bb32d75d 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -139,7 +139,7 @@ func Search(ctx *context.APIContext) {
 
 	opts := &models.SearchRepoOptions{
 		ListOptions:        utils.GetListOptions(ctx),
-		Actor:              ctx.User,
+		Actor:              ctx.Doer,
 		Keyword:            ctx.FormTrim("q"),
 		OwnerID:            ctx.FormInt64("uid"),
 		PriorityOwnerID:    ctx.FormInt64("priority_owner_id"),
@@ -224,7 +224,7 @@ func Search(ctx *context.APIContext) {
 			})
 			return
 		}
-		accessMode, err := models.AccessLevel(ctx.User, repo)
+		accessMode, err := models.AccessLevel(ctx.Doer, repo)
 		if err != nil {
 			ctx.JSON(http.StatusInternalServerError, api.SearchError{
 				OK:    false,
@@ -247,7 +247,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre
 	if opt.AutoInit && opt.Readme == "" {
 		opt.Readme = "Default"
 	}
-	repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{
+	repo, err := repo_service.CreateRepository(ctx.Doer, owner, models.CreateRepoOptions{
 		Name:          opt.Name,
 		Description:   opt.Description,
 		IssueLabels:   opt.IssueLabels,
@@ -303,12 +303,12 @@ func Create(ctx *context.APIContext) {
 	//   "422":
 	//     "$ref": "#/responses/validationError"
 	opt := web.GetForm(ctx).(*api.CreateRepoOption)
-	if ctx.User.IsOrganization() {
+	if ctx.Doer.IsOrganization() {
 		// Shouldn't reach this condition, but just in case.
 		ctx.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization")
 		return
 	}
-	CreateUserRepo(ctx, ctx.User, *opt)
+	CreateUserRepo(ctx, ctx.Doer, *opt)
 }
 
 // Generate Create a repository using a template
@@ -353,7 +353,7 @@ func Generate(ctx *context.APIContext) {
 		return
 	}
 
-	if ctx.User.IsOrganization() {
+	if ctx.Doer.IsOrganization() {
 		ctx.Error(http.StatusUnprocessableEntity, "", "not allowed creating repository for organization")
 		return
 	}
@@ -375,7 +375,7 @@ func Generate(ctx *context.APIContext) {
 		return
 	}
 
-	ctxUser := ctx.User
+	ctxUser := ctx.Doer
 	var err error
 	if form.Owner != ctxUser.Name {
 		ctxUser, err = user_model.GetUserByName(form.Owner)
@@ -391,13 +391,13 @@ func Generate(ctx *context.APIContext) {
 			return
 		}
 
-		if !ctx.User.IsAdmin && !ctxUser.IsOrganization() {
+		if !ctx.Doer.IsAdmin && !ctxUser.IsOrganization() {
 			ctx.Error(http.StatusForbidden, "", "Only admin can generate repository for other user.")
 			return
 		}
 
-		if !ctx.User.IsAdmin {
-			canCreate, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.User.ID)
+		if !ctx.Doer.IsAdmin {
+			canCreate, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("CanCreateOrgRepo", err)
 				return
@@ -408,7 +408,7 @@ func Generate(ctx *context.APIContext) {
 		}
 	}
 
-	repo, err := repo_service.GenerateRepository(ctx.User, ctxUser, ctx.Repo.Repository, opts)
+	repo, err := repo_service.GenerateRepository(ctx.Doer, ctxUser, ctx.Repo.Repository, opts)
 	if err != nil {
 		if repo_model.IsErrRepoAlreadyExist(err) {
 			ctx.Error(http.StatusConflict, "", "The repository with the same name already exists.")
@@ -493,13 +493,13 @@ func CreateOrgRepo(ctx *context.APIContext) {
 		return
 	}
 
-	if !models.HasOrgOrUserVisible(org.AsUser(), ctx.User) {
+	if !models.HasOrgOrUserVisible(org.AsUser(), ctx.Doer) {
 		ctx.NotFound("HasOrgOrUserVisible", nil)
 		return
 	}
 
-	if !ctx.User.IsAdmin {
-		canCreate, err := org.CanCreateOrgRepo(ctx.User.ID)
+	if !ctx.Doer.IsAdmin {
+		canCreate, err := org.CanCreateOrgRepo(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "CanCreateOrgRepo", err)
 			return
@@ -569,7 +569,7 @@ func GetByID(ctx *context.APIContext) {
 		return
 	}
 
-	perm, err := models.GetUserRepoPermission(repo, ctx.User)
+	perm, err := models.GetUserRepoPermission(repo, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 		return
@@ -653,7 +653,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
 	}
 	// Check if repository name has been changed and not just a case change
 	if repo.LowerName != strings.ToLower(newRepoName) {
-		if err := repo_service.ChangeRepositoryName(ctx.User, repo, newRepoName); err != nil {
+		if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil {
 			switch {
 			case repo_model.IsErrRepoAlreadyExist(err):
 				ctx.Error(http.StatusUnprocessableEntity, fmt.Sprintf("repo name is already taken [name: %s]", newRepoName), err)
@@ -694,7 +694,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
 
 		visibilityChanged = repo.IsPrivate != *opts.Private
 		// when ForcePrivate enabled, you could change public repo to private, but only admin users can change private to public
-		if visibilityChanged && setting.Repository.ForcePrivate && !*opts.Private && !ctx.User.IsAdmin {
+		if visibilityChanged && setting.Repository.ForcePrivate && !*opts.Private && !ctx.Doer.IsAdmin {
 			err := fmt.Errorf("cannot change private repository to public")
 			ctx.Error(http.StatusUnprocessableEntity, "Force Private enabled", err)
 			return err
@@ -1019,7 +1019,7 @@ func Delete(ctx *context.APIContext) {
 	owner := ctx.Repo.Owner
 	repo := ctx.Repo.Repository
 
-	canDelete, err := models.CanUserDelete(repo, ctx.User)
+	canDelete, err := models.CanUserDelete(repo, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "CanUserDelete", err)
 		return
@@ -1032,7 +1032,7 @@ func Delete(ctx *context.APIContext) {
 		ctx.Repo.GitRepo.Close()
 	}
 
-	if err := repo_service.DeleteRepository(ctx, ctx.User, repo, true); err != nil {
+	if err := repo_service.DeleteRepository(ctx, ctx.Doer, repo, true); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteRepository", err)
 		return
 	}
diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go
index 652fecefb..9acc0ee7d 100644
--- a/routers/api/v1/repo/repo_test.go
+++ b/routers/api/v1/repo/repo_test.go
@@ -24,7 +24,7 @@ func TestRepoEdit(t *testing.T) {
 	ctx := test.MockContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadUser(t, ctx, 2)
-	ctx.Repo.Owner = ctx.User
+	ctx.Repo.Owner = ctx.Doer
 	description := "new description"
 	website := "http://wwww.newwebsite.com"
 	private := true
@@ -71,7 +71,7 @@ func TestRepoEditNameChange(t *testing.T) {
 	ctx := test.MockContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadUser(t, ctx, 2)
-	ctx.Repo.Owner = ctx.User
+	ctx.Repo.Owner = ctx.Doer
 	name := "newname"
 	opts := api.EditRepoOption{
 		Name: &name,
diff --git a/routers/api/v1/repo/star.go b/routers/api/v1/repo/star.go
index a53ed7136..c78c3cc51 100644
--- a/routers/api/v1/repo/star.go
+++ b/routers/api/v1/repo/star.go
@@ -51,7 +51,7 @@ func ListStargazers(ctx *context.APIContext) {
 	}
 	users := make([]*api.User, len(stargazers))
 	for i, stargazer := range stargazers {
-		users[i] = convert.ToUser(stargazer, ctx.User)
+		users[i] = convert.ToUser(stargazer, ctx.Doer)
 	}
 
 	ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumStars))
diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go
index 01faf5ad2..f4c0ebd38 100644
--- a/routers/api/v1/repo/status.go
+++ b/routers/api/v1/repo/status.go
@@ -62,7 +62,7 @@ func NewCommitStatus(ctx *context.APIContext) {
 		Description: form.Description,
 		Context:     form.Context,
 	}
-	if err := files_service.CreateCommitStatus(ctx, ctx.Repo.Repository, ctx.User, sha, status); err != nil {
+	if err := files_service.CreateCommitStatus(ctx, ctx.Repo.Repository, ctx.Doer, sha, status); err != nil {
 		ctx.Error(http.StatusInternalServerError, "CreateCommitStatus", err)
 		return
 	}
diff --git a/routers/api/v1/repo/subscriber.go b/routers/api/v1/repo/subscriber.go
index 31126d569..c1aaa2419 100644
--- a/routers/api/v1/repo/subscriber.go
+++ b/routers/api/v1/repo/subscriber.go
@@ -51,7 +51,7 @@ func ListSubscribers(ctx *context.APIContext) {
 	}
 	users := make([]*api.User, len(subscribers))
 	for i, subscriber := range subscribers {
-		users[i] = convert.ToUser(subscriber, ctx.User)
+		users[i] = convert.ToUser(subscriber, ctx.Doer)
 	}
 
 	ctx.SetTotalCountHeader(int64(ctx.Repo.Repository.NumWatches))
diff --git a/routers/api/v1/repo/tag.go b/routers/api/v1/repo/tag.go
index a60f4f320..894291275 100644
--- a/routers/api/v1/repo/tag.go
+++ b/routers/api/v1/repo/tag.go
@@ -191,7 +191,7 @@ func CreateTag(ctx *context.APIContext) {
 		return
 	}
 
-	if err := releaseservice.CreateNewTag(ctx, ctx.User, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil {
+	if err := releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, commit.ID.String(), form.TagName, form.Message); err != nil {
 		if models.IsErrTagAlreadyExists(err) {
 			ctx.Error(http.StatusConflict, "tag exist", err)
 			return
@@ -255,7 +255,7 @@ func DeleteTag(ctx *context.APIContext) {
 		return
 	}
 
-	if err = releaseservice.DeleteReleaseByID(ctx, tag.ID, ctx.User, true); err != nil {
+	if err = releaseservice.DeleteReleaseByID(ctx, tag.ID, ctx.Doer, true); err != nil {
 		ctx.Error(http.StatusInternalServerError, "DeleteReleaseByID", err)
 	}
 
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index a997444f4..e149f9c8f 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -67,7 +67,7 @@ func Transfer(ctx *context.APIContext) {
 	}
 
 	if newOwner.Type == user_model.UserTypeOrganization {
-		if !ctx.User.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.User.ID) {
+		if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
 			// The user shouldn't know about this organization
 			ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found")
 			return
@@ -103,7 +103,7 @@ func Transfer(ctx *context.APIContext) {
 		ctx.Repo.GitRepo = nil
 	}
 
-	if err := repo_service.StartRepositoryTransfer(ctx.User, newOwner, ctx.Repo.Repository, teams); err != nil {
+	if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, ctx.Repo.Repository, teams); err != nil {
 		if models.IsErrRepoTransferInProgress(err) {
 			ctx.Error(http.StatusConflict, "CreatePendingRepositoryTransfer", err)
 			return
@@ -218,7 +218,7 @@ func acceptOrRejectRepoTransfer(ctx *context.APIContext, accept bool) error {
 		return err
 	}
 
-	if !repoTransfer.CanUserAcceptTransfer(ctx.User) {
+	if !repoTransfer.CanUserAcceptTransfer(ctx.Doer) {
 		ctx.Error(http.StatusForbidden, "CanUserAcceptTransfer", nil)
 		return fmt.Errorf("user does not have permissions to do this")
 	}
diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go
index f7054b506..3ea8a3118 100644
--- a/routers/api/v1/repo/wiki.go
+++ b/routers/api/v1/repo/wiki.go
@@ -71,7 +71,7 @@ func NewWikiPage(ctx *context.APIContext) {
 	}
 	form.ContentBase64 = string(content)
 
-	if err := wiki_service.AddWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName, form.ContentBase64, form.Message); err != nil {
+	if err := wiki_service.AddWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.ContentBase64, form.Message); err != nil {
 		if models.IsErrWikiReservedName(err) {
 			ctx.Error(http.StatusBadRequest, "IsErrWikiReservedName", err)
 		} else if models.IsErrWikiAlreadyExist(err) {
@@ -144,7 +144,7 @@ func EditWikiPage(ctx *context.APIContext) {
 	}
 	form.ContentBase64 = string(content)
 
-	if err := wiki_service.EditWikiPage(ctx, ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.ContentBase64, form.Message); err != nil {
+	if err := wiki_service.EditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, oldWikiName, newWikiName, form.ContentBase64, form.Message); err != nil {
 		ctx.Error(http.StatusInternalServerError, "EditWikiPage", err)
 		return
 	}
@@ -233,7 +233,7 @@ func DeleteWikiPage(ctx *context.APIContext) {
 
 	wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName"))
 
-	if err := wiki_service.DeleteWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName); err != nil {
+	if err := wiki_service.DeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName); err != nil {
 		if err.Error() == "file does not exist" {
 			ctx.NotFound(err)
 			return
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index 94cfab45b..165b8f005 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -45,7 +45,7 @@ func ListAccessTokens(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/AccessTokenList"
 
-	opts := models.ListAccessTokensOptions{UserID: ctx.User.ID, ListOptions: utils.GetListOptions(ctx)}
+	opts := models.ListAccessTokensOptions{UserID: ctx.Doer.ID, ListOptions: utils.GetListOptions(ctx)}
 
 	count, err := models.CountAccessTokens(opts)
 	if err != nil {
@@ -99,7 +99,7 @@ func CreateAccessToken(ctx *context.APIContext) {
 	form := web.GetForm(ctx).(*api.CreateAccessTokenOption)
 
 	t := &models.AccessToken{
-		UID:  ctx.User.ID,
+		UID:  ctx.Doer.ID,
 		Name: form.Name,
 	}
 
@@ -157,7 +157,7 @@ func DeleteAccessToken(ctx *context.APIContext) {
 	if tokenID == 0 {
 		tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{
 			Name:   token,
-			UserID: ctx.User.ID,
+			UserID: ctx.Doer.ID,
 		})
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
@@ -180,7 +180,7 @@ func DeleteAccessToken(ctx *context.APIContext) {
 		return
 	}
 
-	if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil {
+	if err := models.DeleteAccessTokenByID(tokenID, ctx.Doer.ID); err != nil {
 		if models.IsErrAccessTokenNotExist(err) {
 			ctx.NotFound()
 		} else {
@@ -215,7 +215,7 @@ func CreateOauth2Application(ctx *context.APIContext) {
 
 	app, err := auth.CreateOAuth2Application(auth.CreateOAuth2ApplicationOptions{
 		Name:         data.Name,
-		UserID:       ctx.User.ID,
+		UserID:       ctx.Doer.ID,
 		RedirectURIs: data.RedirectURIs,
 	})
 	if err != nil {
@@ -252,7 +252,7 @@ func ListOauth2Applications(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/OAuth2ApplicationList"
 
-	apps, total, err := auth.ListOAuth2Applications(ctx.User.ID, utils.GetListOptions(ctx))
+	apps, total, err := auth.ListOAuth2Applications(ctx.Doer.ID, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "ListOAuth2Applications", err)
 		return
@@ -288,7 +288,7 @@ func DeleteOauth2Application(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 	appID := ctx.ParamsInt64(":id")
-	if err := auth.DeleteOAuth2Application(appID, ctx.User.ID); err != nil {
+	if err := auth.DeleteOAuth2Application(appID, ctx.Doer.ID); err != nil {
 		if auth.IsErrOAuthApplicationNotFound(err) {
 			ctx.NotFound()
 		} else {
@@ -365,7 +365,7 @@ func UpdateOauth2Application(ctx *context.APIContext) {
 
 	app, err := auth.UpdateOAuth2Application(auth.UpdateOAuth2ApplicationOptions{
 		Name:         data.Name,
-		UserID:       ctx.User.ID,
+		UserID:       ctx.Doer.ID,
 		ID:           appID,
 		RedirectURIs: data.RedirectURIs,
 	})
diff --git a/routers/api/v1/user/email.go b/routers/api/v1/user/email.go
index ed79723c6..9060741c5 100644
--- a/routers/api/v1/user/email.go
+++ b/routers/api/v1/user/email.go
@@ -28,7 +28,7 @@ func ListEmails(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/EmailList"
 
-	emails, err := user_model.GetEmailAddresses(ctx.User.ID)
+	emails, err := user_model.GetEmailAddresses(ctx.Doer.ID)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetEmailAddresses", err)
 		return
@@ -71,7 +71,7 @@ func AddEmail(ctx *context.APIContext) {
 	emails := make([]*user_model.EmailAddress, len(form.Emails))
 	for i := range form.Emails {
 		emails[i] = &user_model.EmailAddress{
-			UID:         ctx.User.ID,
+			UID:         ctx.Doer.ID,
 			Email:       form.Emails[i],
 			IsActivated: !setting.Service.RegisterEmailConfirm,
 		}
@@ -124,7 +124,7 @@ func DeleteEmail(ctx *context.APIContext) {
 	for i := range form.Emails {
 		emails[i] = &user_model.EmailAddress{
 			Email: form.Emails[i],
-			UID:   ctx.User.ID,
+			UID:   ctx.Doer.ID,
 		}
 	}
 
diff --git a/routers/api/v1/user/follower.go b/routers/api/v1/user/follower.go
index 1eacb89db..063f68519 100644
--- a/routers/api/v1/user/follower.go
+++ b/routers/api/v1/user/follower.go
@@ -18,7 +18,7 @@ import (
 func responseAPIUsers(ctx *context.APIContext, users []*user_model.User) {
 	apiUsers := make([]*api.User, len(users))
 	for i := range users {
-		apiUsers[i] = convert.ToUser(users[i], ctx.User)
+		apiUsers[i] = convert.ToUser(users[i], ctx.Doer)
 	}
 	ctx.JSON(http.StatusOK, &apiUsers)
 }
@@ -54,7 +54,7 @@ func ListMyFollowers(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/UserList"
 
-	listUserFollowers(ctx, ctx.User)
+	listUserFollowers(ctx, ctx.Doer)
 }
 
 // ListFollowers list the given user's followers
@@ -120,7 +120,7 @@ func ListMyFollowing(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/UserList"
 
-	listUserFollowing(ctx, ctx.User)
+	listUserFollowing(ctx, ctx.Doer)
 }
 
 // ListFollowing list the users that the given user is following
@@ -184,7 +184,7 @@ func CheckMyFollowing(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	checkUserFollowing(ctx, ctx.User, target.ID)
+	checkUserFollowing(ctx, ctx.Doer, target.ID)
 }
 
 // CheckFollowing check if one user is following another user
@@ -239,7 +239,7 @@ func Follow(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if err := user_model.FollowUser(ctx.User.ID, target.ID); err != nil {
+	if err := user_model.FollowUser(ctx.Doer.ID, target.ID); err != nil {
 		ctx.Error(http.StatusInternalServerError, "FollowUser", err)
 		return
 	}
@@ -265,7 +265,7 @@ func Unfollow(ctx *context.APIContext) {
 	if ctx.Written() {
 		return
 	}
-	if err := user_model.UnfollowUser(ctx.User.ID, target.ID); err != nil {
+	if err := user_model.UnfollowUser(ctx.Doer.ID, target.ID); err != nil {
 		ctx.Error(http.StatusInternalServerError, "UnfollowUser", err)
 		return
 	}
diff --git a/routers/api/v1/user/gpg_key.go b/routers/api/v1/user/gpg_key.go
index 26aeeeabf..5e98b21fb 100644
--- a/routers/api/v1/user/gpg_key.go
+++ b/routers/api/v1/user/gpg_key.go
@@ -91,7 +91,7 @@ func ListMyGPGKeys(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/GPGKeyList"
 
-	listGPGKeys(ctx, ctx.User.ID, utils.GetListOptions(ctx))
+	listGPGKeys(ctx, ctx.Doer.ID, utils.GetListOptions(ctx))
 }
 
 // GetGPGKey get the GPG key based on a id
@@ -128,8 +128,8 @@ func GetGPGKey(ctx *context.APIContext) {
 
 // CreateUserGPGKey creates new GPG key to given user by ID.
 func CreateUserGPGKey(ctx *context.APIContext, form api.CreateGPGKeyOption, uid int64) {
-	token := asymkey_model.VerificationToken(ctx.User, 1)
-	lastToken := asymkey_model.VerificationToken(ctx.User, 0)
+	token := asymkey_model.VerificationToken(ctx.Doer, 1)
+	lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
 
 	keys, err := asymkey_model.AddGPGKey(uid, form.ArmoredKey, token, form.Signature)
 	if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
@@ -156,7 +156,7 @@ func GetVerificationToken(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 
-	token := asymkey_model.VerificationToken(ctx.User, 1)
+	token := asymkey_model.VerificationToken(ctx.Doer, 1)
 	ctx.PlainText(http.StatusOK, token)
 }
 
@@ -178,12 +178,12 @@ func VerifyUserGPGKey(ctx *context.APIContext) {
 	//     "$ref": "#/responses/validationError"
 
 	form := web.GetForm(ctx).(*api.VerifyGPGKeyOption)
-	token := asymkey_model.VerificationToken(ctx.User, 1)
-	lastToken := asymkey_model.VerificationToken(ctx.User, 0)
+	token := asymkey_model.VerificationToken(ctx.Doer, 1)
+	lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
 
-	_, err := asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
+	_, err := asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, token, form.Signature)
 	if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
-		_, err = asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
+		_, err = asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, lastToken, form.Signature)
 	}
 
 	if err != nil {
@@ -230,7 +230,7 @@ func CreateGPGKey(ctx *context.APIContext) {
 	//     "$ref": "#/responses/validationError"
 
 	form := web.GetForm(ctx).(*api.CreateGPGKeyOption)
-	CreateUserGPGKey(ctx, *form, ctx.User.ID)
+	CreateUserGPGKey(ctx, *form, ctx.Doer.ID)
 }
 
 // DeleteGPGKey remove a GPG key belonging to the authenticated user
@@ -255,7 +255,7 @@ func DeleteGPGKey(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 
-	if err := asymkey_model.DeleteGPGKey(ctx.User, ctx.ParamsInt64(":id")); err != nil {
+	if err := asymkey_model.DeleteGPGKey(ctx.Doer, ctx.ParamsInt64(":id")); err != nil {
 		if asymkey_model.IsErrGPGKeyAccessDenied(err) {
 			ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
 		} else {
diff --git a/routers/api/v1/user/key.go b/routers/api/v1/user/key.go
index e8cc2035e..67ffec723 100644
--- a/routers/api/v1/user/key.go
+++ b/routers/api/v1/user/key.go
@@ -86,7 +86,7 @@ func listPublicKeys(ctx *context.APIContext, user *user_model.User) {
 	apiKeys := make([]*api.PublicKey, len(keys))
 	for i := range keys {
 		apiKeys[i] = convert.ToPublicKey(apiLink, keys[i])
-		if ctx.User.IsAdmin || ctx.User.ID == keys[i].OwnerID {
+		if ctx.Doer.IsAdmin || ctx.Doer.ID == keys[i].OwnerID {
 			apiKeys[i], _ = appendPrivateInformation(apiKeys[i], keys[i], user)
 		}
 	}
@@ -119,7 +119,7 @@ func ListMyPublicKeys(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/PublicKeyList"
 
-	listPublicKeys(ctx, ctx.User)
+	listPublicKeys(ctx, ctx.Doer)
 }
 
 // ListPublicKeys list the given user's public keys
@@ -190,8 +190,8 @@ func GetPublicKey(ctx *context.APIContext) {
 
 	apiLink := composePublicKeysAPILink()
 	apiKey := convert.ToPublicKey(apiLink, key)
-	if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID {
-		apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User)
+	if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID {
+		apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Doer)
 	}
 	ctx.JSON(http.StatusOK, apiKey)
 }
@@ -211,8 +211,8 @@ func CreateUserPublicKey(ctx *context.APIContext, form api.CreateKeyOption, uid
 	}
 	apiLink := composePublicKeysAPILink()
 	apiKey := convert.ToPublicKey(apiLink, key)
-	if ctx.User.IsAdmin || ctx.User.ID == key.OwnerID {
-		apiKey, _ = appendPrivateInformation(apiKey, key, ctx.User)
+	if ctx.Doer.IsAdmin || ctx.Doer.ID == key.OwnerID {
+		apiKey, _ = appendPrivateInformation(apiKey, key, ctx.Doer)
 	}
 	ctx.JSON(http.StatusCreated, apiKey)
 }
@@ -238,7 +238,7 @@ func CreatePublicKey(ctx *context.APIContext) {
 	//     "$ref": "#/responses/validationError"
 
 	form := web.GetForm(ctx).(*api.CreateKeyOption)
-	CreateUserPublicKey(ctx, *form, ctx.User.ID)
+	CreateUserPublicKey(ctx, *form, ctx.Doer.ID)
 }
 
 // DeletePublicKey delete one public key
@@ -272,7 +272,7 @@ func DeletePublicKey(ctx *context.APIContext) {
 		ctx.Error(http.StatusForbidden, "", "SSH Key is externally managed for this user")
 	}
 
-	if err := asymkey_service.DeletePublicKey(ctx.User, id); err != nil {
+	if err := asymkey_service.DeletePublicKey(ctx.Doer, id); err != nil {
 		if asymkey_model.IsErrKeyNotExist(err) {
 			ctx.NotFound()
 		} else if asymkey_model.IsErrKeyAccessDenied(err) {
diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go
index 109548ec7..2b933bea1 100644
--- a/routers/api/v1/user/repo.go
+++ b/routers/api/v1/user/repo.go
@@ -39,12 +39,12 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) {
 
 	apiRepos := make([]*api.Repository, 0, len(repos))
 	for i := range repos {
-		access, err := models.AccessLevel(ctx.User, repos[i])
+		access, err := models.AccessLevel(ctx.Doer, repos[i])
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 			return
 		}
-		if ctx.IsSigned && ctx.User.IsAdmin || access >= perm.AccessModeRead {
+		if ctx.IsSigned && ctx.Doer.IsAdmin || access >= perm.AccessModeRead {
 			apiRepos = append(apiRepos, convert.ToRepo(repos[i], access))
 		}
 	}
@@ -109,8 +109,8 @@ func ListMyRepos(ctx *context.APIContext) {
 
 	opts := &models.SearchRepoOptions{
 		ListOptions:        utils.GetListOptions(ctx),
-		Actor:              ctx.User,
-		OwnerID:            ctx.User.ID,
+		Actor:              ctx.Doer,
+		OwnerID:            ctx.Doer.ID,
 		Private:            ctx.IsSigned,
 		IncludeDescription: true,
 	}
@@ -128,7 +128,7 @@ func ListMyRepos(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "GetOwner", err)
 			return
 		}
-		accessMode, err := models.AccessLevel(ctx.User, repo)
+		accessMode, err := models.AccessLevel(ctx.Doer, repo)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 		}
diff --git a/routers/api/v1/user/settings.go b/routers/api/v1/user/settings.go
index 5f4d76ed7..dc7e7f116 100644
--- a/routers/api/v1/user/settings.go
+++ b/routers/api/v1/user/settings.go
@@ -24,7 +24,7 @@ func GetUserSettings(ctx *context.APIContext) {
 	// responses:
 	//   "200":
 	//     "$ref": "#/responses/UserSettings"
-	ctx.JSON(http.StatusOK, convert.User2UserSettings(ctx.User))
+	ctx.JSON(http.StatusOK, convert.User2UserSettings(ctx.Doer))
 }
 
 // UpdateUserSettings returns user settings
@@ -46,38 +46,38 @@ func UpdateUserSettings(ctx *context.APIContext) {
 	form := web.GetForm(ctx).(*api.UserSettingsOptions)
 
 	if form.FullName != nil {
-		ctx.User.FullName = *form.FullName
+		ctx.Doer.FullName = *form.FullName
 	}
 	if form.Description != nil {
-		ctx.User.Description = *form.Description
+		ctx.Doer.Description = *form.Description
 	}
 	if form.Website != nil {
-		ctx.User.Website = *form.Website
+		ctx.Doer.Website = *form.Website
 	}
 	if form.Location != nil {
-		ctx.User.Location = *form.Location
+		ctx.Doer.Location = *form.Location
 	}
 	if form.Language != nil {
-		ctx.User.Language = *form.Language
+		ctx.Doer.Language = *form.Language
 	}
 	if form.Theme != nil {
-		ctx.User.Theme = *form.Theme
+		ctx.Doer.Theme = *form.Theme
 	}
 	if form.DiffViewStyle != nil {
-		ctx.User.DiffViewStyle = *form.DiffViewStyle
+		ctx.Doer.DiffViewStyle = *form.DiffViewStyle
 	}
 
 	if form.HideEmail != nil {
-		ctx.User.KeepEmailPrivate = *form.HideEmail
+		ctx.Doer.KeepEmailPrivate = *form.HideEmail
 	}
 	if form.HideActivity != nil {
-		ctx.User.KeepActivityPrivate = *form.HideActivity
+		ctx.Doer.KeepActivityPrivate = *form.HideActivity
 	}
 
-	if err := user_model.UpdateUser(ctx.User, false); err != nil {
+	if err := user_model.UpdateUser(ctx.Doer, false); err != nil {
 		ctx.InternalServerError(err)
 		return
 	}
 
-	ctx.JSON(http.StatusOK, convert.User2UserSettings(ctx.User))
+	ctx.JSON(http.StatusOK, convert.User2UserSettings(ctx.Doer))
 }
diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go
index cc527d921..95d3785a8 100644
--- a/routers/api/v1/user/star.go
+++ b/routers/api/v1/user/star.go
@@ -63,7 +63,7 @@ func GetStarredRepos(ctx *context.APIContext) {
 	//     "$ref": "#/responses/RepositoryList"
 
 	user := GetUserByParams(ctx)
-	private := user.ID == ctx.User.ID
+	private := user.ID == ctx.Doer.ID
 	repos, err := getStarredRepos(user, private, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
@@ -94,12 +94,12 @@ func GetMyStarredRepos(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/RepositoryList"
 
-	repos, err := getStarredRepos(ctx.User, true, utils.GetListOptions(ctx))
+	repos, err := getStarredRepos(ctx.Doer, true, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "getStarredRepos", err)
 	}
 
-	ctx.SetTotalCountHeader(int64(ctx.User.NumStars))
+	ctx.SetTotalCountHeader(int64(ctx.Doer.NumStars))
 	ctx.JSON(http.StatusOK, &repos)
 }
 
@@ -125,7 +125,7 @@ func IsStarring(ctx *context.APIContext) {
 	//   "404":
 	//     "$ref": "#/responses/notFound"
 
-	if repo_model.IsStaring(ctx.User.ID, ctx.Repo.Repository.ID) {
+	if repo_model.IsStaring(ctx.Doer.ID, ctx.Repo.Repository.ID) {
 		ctx.Status(http.StatusNoContent)
 	} else {
 		ctx.NotFound()
@@ -152,7 +152,7 @@ func Star(ctx *context.APIContext) {
 	//   "204":
 	//     "$ref": "#/responses/empty"
 
-	err := repo_model.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
+	err := repo_model.StarRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, true)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "StarRepo", err)
 		return
@@ -180,7 +180,7 @@ func Unstar(ctx *context.APIContext) {
 	//   "204":
 	//     "$ref": "#/responses/empty"
 
-	err := repo_model.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
+	err := repo_model.StarRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, false)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "StarRepo", err)
 		return
diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go
index bba7b7a5d..56e6ad887 100644
--- a/routers/api/v1/user/user.go
+++ b/routers/api/v1/user/user.go
@@ -56,7 +56,7 @@ func Search(ctx *context.APIContext) {
 	listOptions := utils.GetListOptions(ctx)
 
 	users, maxResults, err := user_model.SearchUsers(&user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		Keyword:     ctx.FormTrim("q"),
 		UID:         ctx.FormInt64("uid"),
 		Type:        user_model.UserTypeIndividual,
@@ -75,7 +75,7 @@ func Search(ctx *context.APIContext) {
 
 	ctx.JSON(http.StatusOK, map[string]interface{}{
 		"ok":   true,
-		"data": convert.ToUsers(ctx.User, users),
+		"data": convert.ToUsers(ctx.Doer, users),
 	})
 }
 
@@ -104,12 +104,12 @@ func GetInfo(ctx *context.APIContext) {
 		return
 	}
 
-	if !models.IsUserVisibleToViewer(u, ctx.User) {
+	if !models.IsUserVisibleToViewer(u, ctx.Doer) {
 		// fake ErrUserNotExist error message to not leak information about existence
 		ctx.NotFound("GetUserByName", user_model.ErrUserNotExist{Name: ctx.Params(":username")})
 		return
 	}
-	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.User))
+	ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.Doer))
 }
 
 // GetAuthenticatedUser get current user's information
@@ -123,7 +123,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/User"
 
-	ctx.JSON(http.StatusOK, convert.ToUser(ctx.User, ctx.User))
+	ctx.JSON(http.StatusOK, convert.ToUser(ctx.Doer, ctx.Doer))
 }
 
 // GetUserHeatmapData is the handler to get a users heatmap
@@ -150,7 +150,7 @@ func GetUserHeatmapData(ctx *context.APIContext) {
 		return
 	}
 
-	heatmap, err := models.GetUserHeatmapDataByUser(user, ctx.User)
+	heatmap, err := models.GetUserHeatmapDataByUser(user, ctx.Doer)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "GetUserHeatmapDataByUser", err)
 		return
diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go
index 49b1d47d9..718a9282e 100644
--- a/routers/api/v1/user/watch.go
+++ b/routers/api/v1/user/watch.go
@@ -61,7 +61,7 @@ func GetWatchedRepos(ctx *context.APIContext) {
 	//     "$ref": "#/responses/RepositoryList"
 
 	user := GetUserByParams(ctx)
-	private := user.ID == ctx.User.ID
+	private := user.ID == ctx.Doer.ID
 	repos, total, err := getWatchedRepos(user, private, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
@@ -91,7 +91,7 @@ func GetMyWatchedRepos(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/RepositoryList"
 
-	repos, total, err := getWatchedRepos(ctx.User, true, utils.GetListOptions(ctx))
+	repos, total, err := getWatchedRepos(ctx.Doer, true, utils.GetListOptions(ctx))
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err)
 	}
@@ -123,7 +123,7 @@ func IsWatching(ctx *context.APIContext) {
 	//   "404":
 	//     description: User is not watching this repo or repo do not exist
 
-	if repo_model.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) {
+	if repo_model.IsWatching(ctx.Doer.ID, ctx.Repo.Repository.ID) {
 		ctx.JSON(http.StatusOK, api.WatchInfo{
 			Subscribed:    true,
 			Ignored:       false,
@@ -157,7 +157,7 @@ func Watch(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/WatchInfo"
 
-	err := repo_model.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
+	err := repo_model.WatchRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, true)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "WatchRepo", err)
 		return
@@ -192,7 +192,7 @@ func Unwatch(ctx *context.APIContext) {
 	//   "204":
 	//     "$ref": "#/responses/empty"
 
-	err := repo_model.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
+	err := repo_model.WatchRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, false)
 	if err != nil {
 		ctx.Error(http.StatusInternalServerError, "UnwatchRepo", err)
 		return
diff --git a/routers/web/admin/admin.go b/routers/web/admin/admin.go
index fac3ef962..63bc7de7d 100644
--- a/routers/web/admin/admin.go
+++ b/routers/web/admin/admin.go
@@ -149,7 +149,7 @@ func DashboardPost(ctx *context.Context) {
 	if form.Op != "" {
 		task := cron.GetTask(form.Op)
 		if task != nil {
-			go task.RunWithUser(ctx.User, nil)
+			go task.RunWithUser(ctx.Doer, nil)
 			ctx.Flash.Success(ctx.Tr("admin.dashboard.task.started", ctx.Tr("admin.dashboard."+form.Op)))
 		} else {
 			ctx.Flash.Error(ctx.Tr("admin.dashboard.task.unknown", form.Op))
diff --git a/routers/web/admin/auths.go b/routers/web/admin/auths.go
index 4c77a169a..1d72a88aa 100644
--- a/routers/web/admin/auths.go
+++ b/routers/web/admin/auths.go
@@ -310,7 +310,7 @@ func NewAuthSourcePost(ctx *context.Context) {
 		return
 	}
 
-	log.Trace("Authentication created by admin(%s): %s", ctx.User.Name, form.Name)
+	log.Trace("Authentication created by admin(%s): %s", ctx.Doer.Name, form.Name)
 
 	ctx.Flash.Success(ctx.Tr("admin.auths.new_success", form.Name))
 	ctx.Redirect(setting.AppSubURL + "/admin/auths")
@@ -413,7 +413,7 @@ func EditAuthSourcePost(ctx *context.Context) {
 		}
 		return
 	}
-	log.Trace("Authentication changed by admin(%s): %d", ctx.User.Name, source.ID)
+	log.Trace("Authentication changed by admin(%s): %d", ctx.Doer.Name, source.ID)
 
 	ctx.Flash.Success(ctx.Tr("admin.auths.update_success"))
 	ctx.Redirect(setting.AppSubURL + "/admin/auths/" + strconv.FormatInt(form.ID, 10))
@@ -438,7 +438,7 @@ func DeleteAuthSource(ctx *context.Context) {
 		})
 		return
 	}
-	log.Trace("Authentication deleted by admin(%s): %d", ctx.User.Name, source.ID)
+	log.Trace("Authentication deleted by admin(%s): %d", ctx.Doer.Name, source.ID)
 
 	ctx.Flash.Success(ctx.Tr("admin.auths.deletion_success"))
 	ctx.JSON(http.StatusOK, map[string]interface{}{
diff --git a/routers/web/admin/emails.go b/routers/web/admin/emails.go
index b94f9d72c..9482ae012 100644
--- a/routers/web/admin/emails.go
+++ b/routers/web/admin/emails.go
@@ -87,7 +87,7 @@ func Emails(ctx *context.Context) {
 			emails[i].SearchEmailResult = *baseEmails[i]
 			// Don't let the admin deactivate its own primary email address
 			// We already know the user is admin
-			emails[i].CanChange = ctx.User.ID != emails[i].UID || !emails[i].IsPrimary
+			emails[i].CanChange = ctx.Doer.ID != emails[i].UID || !emails[i].IsPrimary
 		}
 	}
 	ctx.Data["Keyword"] = opts.Keyword
diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go
index 3613f428e..147e03ba0 100644
--- a/routers/web/admin/notice.go
+++ b/routers/web/admin/notice.go
@@ -73,7 +73,7 @@ func EmptyNotices(ctx *context.Context) {
 		return
 	}
 
-	log.Trace("System notices deleted by admin (%s): [start: %d]", ctx.User.Name, 0)
+	log.Trace("System notices deleted by admin (%s): [start: %d]", ctx.Doer.Name, 0)
 	ctx.Flash.Success(ctx.Tr("admin.notices.delete_success"))
 	ctx.Redirect(setting.AppSubURL + "/admin/notices")
 }
diff --git a/routers/web/admin/orgs.go b/routers/web/admin/orgs.go
index 3d440d83c..6081ab9b1 100644
--- a/routers/web/admin/orgs.go
+++ b/routers/web/admin/orgs.go
@@ -26,7 +26,7 @@ func Organizations(ctx *context.Context) {
 	ctx.Data["PageIsAdminOrganizations"] = true
 
 	explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{
-		Actor: ctx.User,
+		Actor: ctx.Doer,
 		Type:  user_model.UserTypeOrganization,
 		ListOptions: db.ListOptions{
 			PageSize: setting.UI.Admin.OrgPagingNum,
diff --git a/routers/web/admin/repos.go b/routers/web/admin/repos.go
index c4290fc22..fb7be12c3 100644
--- a/routers/web/admin/repos.go
+++ b/routers/web/admin/repos.go
@@ -52,7 +52,7 @@ func DeleteRepo(ctx *context.Context) {
 		ctx.Repo.GitRepo.Close()
 	}
 
-	if err := repo_service.DeleteRepository(ctx, ctx.User, repo, true); err != nil {
+	if err := repo_service.DeleteRepository(ctx, ctx.Doer, repo, true); err != nil {
 		ctx.ServerError("DeleteRepository", err)
 		return
 	}
@@ -148,7 +148,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
 	if has || !isDir {
 		// Fallthrough to failure mode
 	} else if action == "adopt" {
-		if _, err := repo_service.AdoptRepository(ctx.User, ctxUser, models.CreateRepoOptions{
+		if _, err := repo_service.AdoptRepository(ctx.Doer, ctxUser, models.CreateRepoOptions{
 			Name:      dirSplit[1],
 			IsPrivate: true,
 		}); err != nil {
@@ -157,7 +157,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
 		}
 		ctx.Flash.Success(ctx.Tr("repo.adopt_preexisting_success", dir))
 	} else if action == "delete" {
-		if err := repo_service.DeleteUnadoptedRepository(ctx.User, ctxUser, dirSplit[1]); err != nil {
+		if err := repo_service.DeleteUnadoptedRepository(ctx.Doer, ctxUser, dirSplit[1]); err != nil {
 			ctx.ServerError("repository.AdoptRepository", err)
 			return
 		}
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index a7d7d62d9..454e4ce07 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -63,7 +63,7 @@ func Users(ctx *context.Context) {
 	}
 
 	explore.RenderUserSearch(ctx, &user_model.SearchUserOptions{
-		Actor: ctx.User,
+		Actor: ctx.Doer,
 		Type:  user_model.UserTypeIndividual,
 		ListOptions: db.ListOptions{
 			PageSize: setting.UI.Admin.UserPagingNum,
@@ -191,7 +191,7 @@ func NewUserPost(ctx *context.Context) {
 		}
 		return
 	}
-	log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account created by admin (%s): %s", ctx.Doer.Name, u.Name)
 
 	// Send email notification.
 	if form.SendNotify {
@@ -379,7 +379,7 @@ func EditUserPost(ctx *context.Context) {
 	u.Visibility = form.Visibility
 
 	// skip self Prohibit Login
-	if ctx.User.ID == u.ID {
+	if ctx.Doer.ID == u.ID {
 		u.ProhibitLogin = false
 	} else {
 		u.ProhibitLogin = form.ProhibitLogin
@@ -398,7 +398,7 @@ func EditUserPost(ctx *context.Context) {
 		}
 		return
 	}
-	log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account profile updated by admin (%s): %s", ctx.Doer.Name, u.Name)
 
 	ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success"))
 	ctx.Redirect(setting.AppSubURL + "/admin/users/" + url.PathEscape(ctx.Params(":userid")))
@@ -429,7 +429,7 @@ func DeleteUser(ctx *context.Context) {
 		}
 		return
 	}
-	log.Trace("Account deleted by admin (%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account deleted by admin (%s): %s", ctx.Doer.Name, u.Name)
 
 	ctx.Flash.Success(ctx.Tr("admin.users.deletion_success"))
 	ctx.JSON(http.StatusOK, map[string]interface{}{
diff --git a/routers/web/admin/users_test.go b/routers/web/admin/users_test.go
index 46133688a..9de548685 100644
--- a/routers/web/admin/users_test.go
+++ b/routers/web/admin/users_test.go
@@ -27,7 +27,7 @@ func TestNewUserPost_MustChangePassword(t *testing.T) {
 		ID:      2,
 	}).(*user_model.User)
 
-	ctx.User = u
+	ctx.Doer = u
 
 	username := "gitea"
 	email := "gitea@gitea.io"
@@ -64,7 +64,7 @@ func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
 		ID:      2,
 	}).(*user_model.User)
 
-	ctx.User = u
+	ctx.Doer = u
 
 	username := "gitea"
 	email := "gitea@gitea.io"
@@ -101,7 +101,7 @@ func TestNewUserPost_InvalidEmail(t *testing.T) {
 		ID:      2,
 	}).(*user_model.User)
 
-	ctx.User = u
+	ctx.Doer = u
 
 	username := "gitea"
 	email := "gitea@gitea.io\r\n"
@@ -131,7 +131,7 @@ func TestNewUserPost_VisibilityDefaultPublic(t *testing.T) {
 		ID:      2,
 	}).(*user_model.User)
 
-	ctx.User = u
+	ctx.Doer = u
 
 	username := "gitea"
 	email := "gitea@gitea.io"
@@ -169,7 +169,7 @@ func TestNewUserPost_VisibilityPrivate(t *testing.T) {
 		ID:      2,
 	}).(*user_model.User)
 
-	ctx.User = u
+	ctx.Doer = u
 
 	username := "gitea"
 	email := "gitea@gitea.io"
diff --git a/routers/web/auth/auth.go b/routers/web/auth/auth.go
index f20af80c1..556fd26d0 100644
--- a/routers/web/auth/auth.go
+++ b/routers/web/auth/auth.go
@@ -393,8 +393,8 @@ func HandleSignOut(ctx *context.Context) {
 
 // SignOut sign out from login status
 func SignOut(ctx *context.Context) {
-	if ctx.User != nil {
-		eventsource.GetManager().SendMessageBlocking(ctx.User.ID, &eventsource.Event{
+	if ctx.Doer != nil {
+		eventsource.GetManager().SendMessageBlocking(ctx.Doer.ID, &eventsource.Event{
 			Name: "logout",
 			Data: ctx.Session.ID(),
 		})
@@ -649,19 +649,19 @@ func Activate(ctx *context.Context) {
 
 	if len(code) == 0 {
 		ctx.Data["IsActivatePage"] = true
-		if ctx.User == nil || ctx.User.IsActive {
+		if ctx.Doer == nil || ctx.Doer.IsActive {
 			ctx.NotFound("invalid user", nil)
 			return
 		}
 		// Resend confirmation email.
 		if setting.Service.RegisterEmailConfirm {
-			if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
+			if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
 				ctx.Data["ResendLimited"] = true
 			} else {
 				ctx.Data["ActiveCodeLives"] = timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())
-				mailer.SendActivateAccountMail(ctx.Locale, ctx.User)
+				mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
 
-				if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
+				if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
 					log.Error("Set cache(MailResendLimit) fail: %v", err)
 				}
 			}
diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go
index 64e9c5c20..83b58d6cb 100644
--- a/routers/web/auth/oauth.go
+++ b/routers/web/auth/oauth.go
@@ -267,21 +267,21 @@ type userInfoResponse struct {
 
 // InfoOAuth manages request for userinfo endpoint
 func InfoOAuth(ctx *context.Context) {
-	if ctx.User == nil || ctx.Data["AuthedMethod"] != (&auth_service.OAuth2{}).Name() {
+	if ctx.Doer == nil || ctx.Data["AuthedMethod"] != (&auth_service.OAuth2{}).Name() {
 		ctx.Resp.Header().Set("WWW-Authenticate", `Bearer realm=""`)
 		ctx.PlainText(http.StatusUnauthorized, "no valid authorization")
 		return
 	}
 
 	response := &userInfoResponse{
-		Sub:      fmt.Sprint(ctx.User.ID),
-		Name:     ctx.User.FullName,
-		Username: ctx.User.Name,
-		Email:    ctx.User.Email,
-		Picture:  ctx.User.AvatarLink(),
+		Sub:      fmt.Sprint(ctx.Doer.ID),
+		Name:     ctx.Doer.FullName,
+		Username: ctx.Doer.Name,
+		Email:    ctx.Doer.Email,
+		Picture:  ctx.Doer.AvatarLink(),
 	}
 
-	groups, err := getOAuthGroupsForUser(ctx.User)
+	groups, err := getOAuthGroupsForUser(ctx.Doer)
 	if err != nil {
 		ctx.ServerError("Oauth groups for user", err)
 		return
@@ -317,7 +317,7 @@ func getOAuthGroupsForUser(user *user_model.User) ([]string, error) {
 
 // IntrospectOAuth introspects an oauth token
 func IntrospectOAuth(ctx *context.Context) {
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.Resp.Header().Set("WWW-Authenticate", `Bearer realm=""`)
 		ctx.PlainText(http.StatusUnauthorized, "no valid authorization")
 		return
@@ -438,7 +438,7 @@ func AuthorizeOAuth(ctx *context.Context) {
 		return
 	}
 
-	grant, err := app.GetGrantByUserID(ctx.User.ID)
+	grant, err := app.GetGrantByUserID(ctx.Doer.ID)
 	if err != nil {
 		handleServerError(ctx, form.State, form.RedirectURI)
 		return
@@ -515,7 +515,7 @@ func GrantApplicationOAuth(ctx *context.Context) {
 		ctx.ServerError("GetOAuth2ApplicationByClientID", err)
 		return
 	}
-	grant, err := app.CreateGrant(ctx.User.ID, form.Scope)
+	grant, err := app.CreateGrant(ctx.Doer.ID, form.Scope)
 	if err != nil {
 		handleAuthorizeError(ctx, AuthorizeError{
 			State:            form.State,
diff --git a/routers/web/auth/password.go b/routers/web/auth/password.go
index 65d5c5597..8e309ebb1 100644
--- a/routers/web/auth/password.go
+++ b/routers/web/auth/password.go
@@ -103,7 +103,7 @@ func commonResetPassword(ctx *context.Context) (*user_model.User, *auth.TwoFacto
 	ctx.Data["Title"] = ctx.Tr("auth.reset_password")
 	ctx.Data["Code"] = code
 
-	if nil != ctx.User {
+	if nil != ctx.Doer {
 		ctx.Data["user_signed_in"] = true
 	}
 
@@ -133,8 +133,8 @@ func commonResetPassword(ctx *context.Context) (*user_model.User, *auth.TwoFacto
 	// Show the user that they are affecting the account that they intended to
 	ctx.Data["user_email"] = u.Email
 
-	if nil != ctx.User && u.ID != ctx.User.ID {
-		ctx.Flash.Error(ctx.Tr("auth.reset_password_wrong_user", ctx.User.Email, u.Email))
+	if nil != ctx.Doer && u.ID != ctx.Doer.ID {
+		ctx.Flash.Error(ctx.Tr("auth.reset_password_wrong_user", ctx.Doer.Email, u.Email))
 		return nil, nil
 	}
 
@@ -283,7 +283,7 @@ func MustChangePasswordPost(ctx *context.Context) {
 		ctx.HTML(http.StatusOK, tplMustChangePassword)
 		return
 	}
-	u := ctx.User
+	u := ctx.Doer
 	// Make sure only requests for users who are eligible to change their password via
 	// this method passes through
 	if !u.MustChangePassword {
diff --git a/routers/web/events/events.go b/routers/web/events/events.go
index 41f52375c..02d20550a 100644
--- a/routers/web/events/events.go
+++ b/routers/web/events/events.go
@@ -48,7 +48,7 @@ func Events(ctx *context.Context) {
 
 	shutdownCtx := graceful.GetManager().ShutdownContext()
 
-	uid := ctx.User.ID
+	uid := ctx.Doer.ID
 
 	messageChan := eventsource.GetManager().Register(uid)
 
@@ -82,7 +82,7 @@ loop:
 			}
 			_, err := event.WriteTo(ctx.Resp)
 			if err != nil {
-				log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err)
+				log.Error("Unable to write to EventStream for user %s: %v", ctx.Doer.Name, err)
 				go unregister()
 				break loop
 			}
@@ -94,7 +94,7 @@ loop:
 			go unregister()
 			break loop
 		case <-stopwatchTimer.C:
-			sws, err := models.GetUserStopwatches(ctx.User.ID, db.ListOptions{})
+			sws, err := models.GetUserStopwatches(ctx.Doer.ID, db.ListOptions{})
 			if err != nil {
 				log.Error("Unable to GetUserStopwatches: %v", err)
 				continue
@@ -114,7 +114,7 @@ loop:
 				Data: string(dataBs),
 			}).WriteTo(ctx.Resp)
 			if err != nil {
-				log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err)
+				log.Error("Unable to write to EventStream for user %s: %v", ctx.Doer.Name, err)
 				go unregister()
 				break loop
 			}
@@ -145,7 +145,7 @@ loop:
 
 			_, err := event.WriteTo(ctx.Resp)
 			if err != nil {
-				log.Error("Unable to write to EventStream for user %s: %v", ctx.User.Name, err)
+				log.Error("Unable to write to EventStream for user %s: %v", ctx.Doer.Name, err)
 				go unregister()
 				break loop
 			}
diff --git a/routers/web/explore/code.go b/routers/web/explore/code.go
index 640a5a0e4..506d13b59 100644
--- a/routers/web/explore/code.go
+++ b/routers/web/explore/code.go
@@ -49,13 +49,13 @@ func Code(ctx *context.Context) {
 		err     error
 		isAdmin bool
 	)
-	if ctx.User != nil {
-		isAdmin = ctx.User.IsAdmin
+	if ctx.Doer != nil {
+		isAdmin = ctx.Doer.IsAdmin
 	}
 
 	// guest user or non-admin user
-	if ctx.User == nil || !isAdmin {
-		repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.User)
+	if ctx.Doer == nil || !isAdmin {
+		repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.Doer)
 		if err != nil {
 			ctx.ServerError("SearchResults", err)
 			return
@@ -69,7 +69,7 @@ func Code(ctx *context.Context) {
 	)
 
 	// if non-admin login user, we need check UnitTypeCode at first
-	if ctx.User != nil && len(repoIDs) > 0 {
+	if ctx.Doer != nil && len(repoIDs) > 0 {
 		repoMaps, err := repo_model.GetRepositoriesMapByIDs(repoIDs)
 		if err != nil {
 			ctx.ServerError("SearchResults", err)
@@ -79,7 +79,7 @@ func Code(ctx *context.Context) {
 		rightRepoMap := make(map[int64]*repo_model.Repository, len(repoMaps))
 		repoIDs = make([]int64, 0, len(repoMaps))
 		for id, repo := range repoMaps {
-			if models.CheckRepoUnitUser(repo, ctx.User, unit.TypeCode) {
+			if models.CheckRepoUnitUser(repo, ctx.Doer, unit.TypeCode) {
 				rightRepoMap[id] = repo
 				repoIDs = append(repoIDs, id)
 			}
@@ -98,7 +98,7 @@ func Code(ctx *context.Context) {
 			ctx.Data["CodeIndexerUnavailable"] = !code_indexer.IsAvailable()
 		}
 		// if non-login user or isAdmin, no need to check UnitTypeCode
-	} else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
+	} else if (ctx.Doer == nil && len(repoIDs) > 0) || isAdmin {
 		total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(ctx, repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum, isMatch)
 		if err != nil {
 			if code_indexer.IsAvailable() {
diff --git a/routers/web/explore/org.go b/routers/web/explore/org.go
index 41c0a0c83..eb6972fad 100644
--- a/routers/web/explore/org.go
+++ b/routers/web/explore/org.go
@@ -27,12 +27,12 @@ func Organizations(ctx *context.Context) {
 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
 
 	visibleTypes := []structs.VisibleType{structs.VisibleTypePublic}
-	if ctx.User != nil {
+	if ctx.Doer != nil {
 		visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate)
 	}
 
 	RenderUserSearch(ctx, &user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		Type:        user_model.UserTypeOrganization,
 		ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
 		Visible:     visibleTypes,
diff --git a/routers/web/explore/repo.go b/routers/web/explore/repo.go
index ce3aefe26..3e8aa2bb0 100644
--- a/routers/web/explore/repo.go
+++ b/routers/web/explore/repo.go
@@ -86,7 +86,7 @@ func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
 			Page:     page,
 			PageSize: opts.PageSize,
 		},
-		Actor:              ctx.User,
+		Actor:              ctx.Doer,
 		OrderBy:            orderBy,
 		Private:            opts.Private,
 		Keyword:            keyword,
@@ -124,14 +124,14 @@ func Repos(ctx *context.Context) {
 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
 
 	var ownerID int64
-	if ctx.User != nil && !ctx.User.IsAdmin {
-		ownerID = ctx.User.ID
+	if ctx.Doer != nil && !ctx.Doer.IsAdmin {
+		ownerID = ctx.Doer.ID
 	}
 
 	RenderRepoSearch(ctx, &RepoSearchOptions{
 		PageSize: setting.UI.ExplorePagingNum,
 		OwnerID:  ownerID,
-		Private:  ctx.User != nil,
+		Private:  ctx.Doer != nil,
 		TplName:  tplExploreRepos,
 	})
 }
diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go
index 98788f543..ea0d7d5f9 100644
--- a/routers/web/explore/user.go
+++ b/routers/web/explore/user.go
@@ -102,7 +102,7 @@ func Users(ctx *context.Context) {
 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
 
 	RenderUserSearch(ctx, &user_model.SearchUserOptions{
-		Actor:       ctx.User,
+		Actor:       ctx.Doer,
 		Type:        user_model.UserTypeIndividual,
 		ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
 		IsActive:    util.OptionalBoolTrue,
diff --git a/routers/web/feed/profile.go b/routers/web/feed/profile.go
index a7b8efcdb..32898c6ee 100644
--- a/routers/web/feed/profile.go
+++ b/routers/web/feed/profile.go
@@ -19,7 +19,7 @@ import (
 func ShowUserFeed(ctx *context.Context, ctxUser *user_model.User, formatType string) {
 	actions, err := models.GetFeeds(ctx, models.GetFeedsOptions{
 		RequestedUser:   ctxUser,
-		Actor:           ctx.User,
+		Actor:           ctx.Doer,
 		IncludePrivate:  false,
 		OnlyPerformedBy: !ctxUser.IsOrganization(),
 		IncludeDeleted:  false,
diff --git a/routers/web/feed/repo.go b/routers/web/feed/repo.go
index 53fb8148e..ac856195b 100644
--- a/routers/web/feed/repo.go
+++ b/routers/web/feed/repo.go
@@ -18,7 +18,7 @@ import (
 func ShowRepoFeed(ctx *context.Context, repo *repo_model.Repository, formatType string) {
 	actions, err := models.GetFeeds(ctx, models.GetFeedsOptions{
 		RequestedRepo:  repo,
-		Actor:          ctx.User,
+		Actor:          ctx.Doer,
 		IncludePrivate: true,
 		Date:           ctx.FormString("date"),
 	})
diff --git a/routers/web/home.go b/routers/web/home.go
index ed81d84c7..9036814dd 100644
--- a/routers/web/home.go
+++ b/routers/web/home.go
@@ -25,14 +25,14 @@ const (
 // Home render home page
 func Home(ctx *context.Context) {
 	if ctx.IsSigned {
-		if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
+		if !ctx.Doer.IsActive && setting.Service.RegisterEmailConfirm {
 			ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
 			ctx.HTML(http.StatusOK, auth.TplActivate)
-		} else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
-			log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
+		} else if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
+			log.Info("Failed authentication attempt for %s from %s", ctx.Doer.Name, ctx.RemoteAddr())
 			ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
 			ctx.HTML(http.StatusOK, "user/auth/prohibit_login")
-		} else if ctx.User.MustChangePassword {
+		} else if ctx.Doer.MustChangePassword {
 			ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
 			ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
 			middleware.SetRedirectToCookie(ctx.Resp, setting.AppSubURL+ctx.Req.URL.RequestURI())
diff --git a/routers/web/org/home.go b/routers/web/org/home.go
index fc81ceb71..1466731b9 100644
--- a/routers/web/org/home.go
+++ b/routers/web/org/home.go
@@ -39,7 +39,7 @@ func Home(ctx *context.Context) {
 
 	org := ctx.Org.Organization
 
-	if !models.HasOrgOrUserVisible(org.AsUser(), ctx.User) {
+	if !models.HasOrgOrUserVisible(org.AsUser(), ctx.Doer) {
 		ctx.NotFound("HasOrgOrUserVisible", nil)
 		return
 	}
@@ -113,7 +113,7 @@ func Home(ctx *context.Context) {
 		OwnerID:            org.ID,
 		OrderBy:            orderBy,
 		Private:            ctx.IsSigned,
-		Actor:              ctx.User,
+		Actor:              ctx.Doer,
 		Language:           language,
 		IncludeDescription: setting.UI.SearchRepoDescription,
 	})
@@ -128,13 +128,13 @@ func Home(ctx *context.Context) {
 		ListOptions: db.ListOptions{Page: 1, PageSize: 25},
 	}
 
-	if ctx.User != nil {
-		isMember, err := org.IsOrgMember(ctx.User.ID)
+	if ctx.Doer != nil {
+		isMember, err := org.IsOrgMember(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrgMember")
 			return
 		}
-		opts.PublicOnly = !isMember && !ctx.User.IsAdmin
+		opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
 	}
 
 	members, _, err := models.FindOrgMembers(opts)
diff --git a/routers/web/org/members.go b/routers/web/org/members.go
index b8e7fa1ff..9e65e6140 100644
--- a/routers/web/org/members.go
+++ b/routers/web/org/members.go
@@ -36,13 +36,13 @@ func Members(ctx *context.Context) {
 		PublicOnly: true,
 	}
 
-	if ctx.User != nil {
-		isMember, err := ctx.Org.Organization.IsOrgMember(ctx.User.ID)
+	if ctx.Doer != nil {
+		isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "IsOrgMember")
 			return
 		}
-		opts.PublicOnly = !isMember && !ctx.User.IsAdmin
+		opts.PublicOnly = !isMember && !ctx.Doer.IsAdmin
 	}
 
 	total, err := models.CountOrgMembers(opts)
@@ -80,13 +80,13 @@ func MembersAction(ctx *context.Context) {
 	var err error
 	switch ctx.Params(":action") {
 	case "private":
-		if ctx.User.ID != uid && !ctx.Org.IsOwner {
+		if ctx.Doer.ID != uid && !ctx.Org.IsOwner {
 			ctx.Error(http.StatusNotFound)
 			return
 		}
 		err = models.ChangeOrgUserStatus(org.ID, uid, false)
 	case "public":
-		if ctx.User.ID != uid && !ctx.Org.IsOwner {
+		if ctx.Doer.ID != uid && !ctx.Org.IsOwner {
 			ctx.Error(http.StatusNotFound)
 			return
 		}
@@ -105,7 +105,7 @@ func MembersAction(ctx *context.Context) {
 			return
 		}
 	case "leave":
-		err = org.RemoveMember(ctx.User.ID)
+		err = org.RemoveMember(ctx.Doer.ID)
 		if models.IsErrLastOrgOwner(err) {
 			ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
 			ctx.JSON(http.StatusOK, map[string]interface{}{
diff --git a/routers/web/org/org.go b/routers/web/org/org.go
index c66a0cd4c..b641f768b 100644
--- a/routers/web/org/org.go
+++ b/routers/web/org/org.go
@@ -29,7 +29,7 @@ const (
 func Create(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("new_org")
 	ctx.Data["DefaultOrgVisibilityMode"] = setting.Service.DefaultOrgVisibilityMode
-	if !ctx.User.CanCreateOrganization() {
+	if !ctx.Doer.CanCreateOrganization() {
 		ctx.ServerError("Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
 		return
 	}
@@ -41,7 +41,7 @@ func CreatePost(ctx *context.Context) {
 	form := *web.GetForm(ctx).(*forms.CreateOrgForm)
 	ctx.Data["Title"] = ctx.Tr("new_org")
 
-	if !ctx.User.CanCreateOrganization() {
+	if !ctx.Doer.CanCreateOrganization() {
 		ctx.ServerError("Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
 		return
 	}
@@ -59,7 +59,7 @@ func CreatePost(ctx *context.Context) {
 		RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess,
 	}
 
-	if err := models.CreateOrganization(org, ctx.User); err != nil {
+	if err := models.CreateOrganization(org, ctx.Doer); err != nil {
 		ctx.Data["Err_OrgName"] = true
 		switch {
 		case user_model.IsErrUserAlreadyExist(err):
diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go
index 404aac889..72c25ec25 100644
--- a/routers/web/org/setting.go
+++ b/routers/web/org/setting.go
@@ -96,7 +96,7 @@ func SettingsPost(ctx *context.Context) {
 	org.Name = form.Name
 	org.LowerName = strings.ToLower(form.Name)
 
-	if ctx.User.IsAdmin {
+	if ctx.Doer.IsAdmin {
 		org.MaxRepoCreation = form.MaxRepoCreation
 	}
 
diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go
index f6e09eb4c..d13c4e854 100644
--- a/routers/web/org/teams.go
+++ b/routers/web/org/teams.go
@@ -69,9 +69,9 @@ func TeamsAction(ctx *context.Context) {
 			ctx.Error(http.StatusNotFound)
 			return
 		}
-		err = ctx.Org.Team.AddMember(ctx.User.ID)
+		err = ctx.Org.Team.AddMember(ctx.Doer.ID)
 	case "leave":
-		err = ctx.Org.Team.RemoveMember(ctx.User.ID)
+		err = ctx.Org.Team.RemoveMember(ctx.Doer.ID)
 		if err != nil {
 			if models.IsErrLastOrgOwner(err) {
 				ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go
index 4101d81ac..be5b5812d 100644
--- a/routers/web/repo/attachment.go
+++ b/routers/web/repo/attachment.go
@@ -44,7 +44,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) {
 	}
 	defer file.Close()
 
-	attach, err := attachment.UploadAttachment(file, ctx.User.ID, repoID, 0, header.Filename, allowedTypes)
+	attach, err := attachment.UploadAttachment(file, ctx.Doer.ID, repoID, 0, header.Filename, allowedTypes)
 	if err != nil {
 		if upload.IsErrFileTypeForbidden(err) {
 			ctx.Error(http.StatusBadRequest, err.Error())
@@ -68,7 +68,7 @@ func DeleteAttachment(ctx *context.Context) {
 		ctx.Error(http.StatusBadRequest, err.Error())
 		return
 	}
-	if !ctx.IsSigned || (ctx.User.ID != attach.UploaderID) {
+	if !ctx.IsSigned || (ctx.Doer.ID != attach.UploaderID) {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
@@ -101,12 +101,12 @@ func GetAttachment(ctx *context.Context) {
 	}
 
 	if repository == nil { // If not linked
-		if !(ctx.IsSigned && attach.UploaderID == ctx.User.ID) { // We block if not the uploader
+		if !(ctx.IsSigned && attach.UploaderID == ctx.Doer.ID) { // We block if not the uploader
 			ctx.Error(http.StatusNotFound)
 			return
 		}
 	} else { // If we have the repository we check access
-		perm, err := models.GetUserRepoPermission(repository, ctx.User)
+		perm, err := models.GetUserRepoPermission(repository, ctx.Doer)
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err.Error())
 			return
diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go
index 489ef9a35..3fc575a19 100644
--- a/routers/web/repo/branch.go
+++ b/routers/web/repo/branch.go
@@ -56,7 +56,7 @@ func Branches(ctx *context.Context) {
 	ctx.Data["IsWriter"] = ctx.Repo.CanWrite(unit.TypeCode)
 	ctx.Data["IsMirror"] = ctx.Repo.Repository.IsMirror
 	ctx.Data["CanPull"] = ctx.Repo.CanWrite(unit.TypeCode) ||
-		(ctx.IsSigned && repo_model.HasForkedRepo(ctx.User.ID, ctx.Repo.Repository.ID))
+		(ctx.IsSigned && repo_model.HasForkedRepo(ctx.Doer.ID, ctx.Repo.Repository.ID))
 	ctx.Data["PageIsViewCode"] = true
 	ctx.Data["PageIsBranches"] = true
 
@@ -90,7 +90,7 @@ func DeleteBranchPost(ctx *context.Context) {
 	defer redirect(ctx)
 	branchName := ctx.FormString("name")
 
-	if err := repo_service.DeleteBranch(ctx.User, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
+	if err := repo_service.DeleteBranch(ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil {
 		switch {
 		case git.IsErrBranchNotExist(err):
 			log.Debug("DeleteBranch: Can't delete non existing branch '%s'", branchName)
@@ -129,7 +129,7 @@ func RestoreBranchPost(ctx *context.Context) {
 	if err := git.Push(ctx, ctx.Repo.Repository.RepoPath(), git.PushOptions{
 		Remote: ctx.Repo.Repository.RepoPath(),
 		Branch: fmt.Sprintf("%s:%s%s", deletedBranch.Commit, git.BranchPrefix, deletedBranch.Name),
-		Env:    models.PushingEnvironment(ctx.User, ctx.Repo.Repository),
+		Env:    models.PushingEnvironment(ctx.Doer, ctx.Repo.Repository),
 	}); err != nil {
 		if strings.Contains(err.Error(), "already exists") {
 			log.Debug("RestoreBranch: Can't restore branch '%s', since one with same name already exist", deletedBranch.Name)
@@ -147,8 +147,8 @@ func RestoreBranchPost(ctx *context.Context) {
 			RefFullName:  git.BranchPrefix + deletedBranch.Name,
 			OldCommitID:  git.EmptySHA,
 			NewCommitID:  deletedBranch.Commit,
-			PusherID:     ctx.User.ID,
-			PusherName:   ctx.User.Name,
+			PusherID:     ctx.Doer.ID,
+			PusherName:   ctx.Doer.Name,
 			RepoUserName: ctx.Repo.Owner.Name,
 			RepoName:     ctx.Repo.Repository.Name,
 		}); err != nil {
@@ -364,11 +364,11 @@ func CreateBranch(ctx *context.Context) {
 		if ctx.Repo.IsViewBranch {
 			target = ctx.Repo.BranchName
 		}
-		err = release_service.CreateNewTag(ctx, ctx.User, ctx.Repo.Repository, target, form.NewBranchName, "")
+		err = release_service.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, target, form.NewBranchName, "")
 	} else if ctx.Repo.IsViewBranch {
-		err = repo_service.CreateNewBranch(ctx, ctx.User, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
+		err = repo_service.CreateNewBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.BranchName, form.NewBranchName)
 	} else {
-		err = repo_service.CreateNewBranchFromCommit(ctx, ctx.User, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName)
+		err = repo_service.CreateNewBranchFromCommit(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.CommitID, form.NewBranchName)
 	}
 	if err != nil {
 		if models.IsErrTagAlreadyExists(err) {
diff --git a/routers/web/repo/cherry_pick.go b/routers/web/repo/cherry_pick.go
index eb2280934..926361ccd 100644
--- a/routers/web/repo/cherry_pick.go
+++ b/routers/web/repo/cherry_pick.go
@@ -127,7 +127,7 @@ func CherryPickPost(ctx *context.Context) {
 
 	// First lets try the simple plain read-tree -m approach
 	opts.Content = sha
-	if _, err := files.CherryPick(ctx, ctx.Repo.Repository, ctx.User, form.Revert, opts); err != nil {
+	if _, err := files.CherryPick(ctx, ctx.Repo.Repository, ctx.Doer, form.Revert, opts); err != nil {
 		if models.IsErrBranchAlreadyExists(err) {
 			// User has specified a branch that already exists
 			branchErr := err.(models.ErrBranchAlreadyExists)
@@ -164,7 +164,7 @@ func CherryPickPost(ctx *context.Context) {
 		opts.Content = buf.String()
 		ctx.Data["FileContent"] = opts.Content
 
-		if _, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.User, opts); err != nil {
+		if _, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, opts); err != nil {
 			if models.IsErrBranchAlreadyExists(err) {
 				// User has specified a branch that already exists
 				branchErr := err.(models.ErrBranchAlreadyExists)
diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go
index 80d4fee19..c2ae86d5d 100644
--- a/routers/web/repo/compare.go
+++ b/routers/web/repo/compare.go
@@ -338,8 +338,8 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 	// check if they have a fork of the base repo and offer that as
 	// "OwnForkRepo"
 	var ownForkRepo *repo_model.Repository
-	if ctx.User != nil && baseRepo.OwnerID != ctx.User.ID {
-		repo := repo_model.GetForkedRepo(ctx.User.ID, baseRepo.ID)
+	if ctx.Doer != nil && baseRepo.OwnerID != ctx.Doer.ID {
+		repo := repo_model.GetForkedRepo(ctx.Doer.ID, baseRepo.ID)
 		if repo != nil {
 			ownForkRepo = repo
 			ctx.Data["OwnForkRepo"] = ownForkRepo
@@ -354,7 +354,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 		has = true
 	}
 
-	// 4. If the ctx.User has their own fork of the baseRepo and the headUser is the ctx.User
+	// 4. If the ctx.Doer has their own fork of the baseRepo and the headUser is the ctx.Doer
 	// set the headRepo to the ownFork
 	if !has && ownForkRepo != nil && ownForkRepo.OwnerID == ci.HeadUser.ID {
 		ci.HeadRepo = ownForkRepo
@@ -393,10 +393,10 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 
 	ctx.Data["HeadRepo"] = ci.HeadRepo
 
-	// Now we need to assert that the ctx.User has permission to read
+	// Now we need to assert that the ctx.Doer has permission to read
 	// the baseRepo's code and pulls
 	// (NOT headRepo's)
-	permBase, err := models.GetUserRepoPermission(baseRepo, ctx.User)
+	permBase, err := models.GetUserRepoPermission(baseRepo, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserRepoPermission", err)
 		return nil
@@ -404,7 +404,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 	if !permBase.CanRead(unit.TypeCode) {
 		if log.IsTrace() {
 			log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in baseRepo has Permissions: %-+v",
-				ctx.User,
+				ctx.Doer,
 				baseRepo,
 				permBase)
 		}
@@ -414,8 +414,8 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 
 	// If we're not merging from the same repo:
 	if !isSameRepo {
-		// Assert ctx.User has permission to read headRepo's codes
-		permHead, err := models.GetUserRepoPermission(ci.HeadRepo, ctx.User)
+		// Assert ctx.Doer has permission to read headRepo's codes
+		permHead, err := models.GetUserRepoPermission(ci.HeadRepo, ctx.Doer)
 		if err != nil {
 			ctx.ServerError("GetUserRepoPermission", err)
 			return nil
@@ -423,7 +423,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 		if !permHead.CanRead(unit.TypeCode) {
 			if log.IsTrace() {
 				log.Trace("Permission Denied: User: %-v cannot read code in Repo: %-v\nUser in headRepo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					ci.HeadRepo,
 					permHead)
 			}
@@ -439,7 +439,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 	if rootRepo != nil &&
 		rootRepo.ID != ci.HeadRepo.ID &&
 		rootRepo.ID != baseRepo.ID {
-		canRead := models.CheckRepoUnitUser(rootRepo, ctx.User, unit.TypeCode)
+		canRead := models.CheckRepoUnitUser(rootRepo, ctx.Doer, unit.TypeCode)
 		if canRead {
 			ctx.Data["RootRepo"] = rootRepo
 			if !fileOnly {
@@ -464,7 +464,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 		ownForkRepo.ID != ci.HeadRepo.ID &&
 		ownForkRepo.ID != baseRepo.ID &&
 		(rootRepo == nil || ownForkRepo.ID != rootRepo.ID) {
-		canRead := models.CheckRepoUnitUser(ownForkRepo, ctx.User, unit.TypeCode)
+		canRead := models.CheckRepoUnitUser(ownForkRepo, ctx.Doer, unit.TypeCode)
 		if canRead {
 			ctx.Data["OwnForkRepo"] = ownForkRepo
 			if !fileOnly {
@@ -506,7 +506,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
 	if ctx.Data["PageIsComparePull"] == true && !permBase.CanReadIssuesOrPulls(true) {
 		if log.IsTrace() {
 			log.Trace("Permission Denied: User: %-v cannot create/read pull requests in Repo: %-v\nUser in baseRepo has Permissions: %-+v",
-				ctx.User,
+				ctx.Doer,
 				baseRepo,
 				permBase)
 		}
diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go
index c4fff1e42..a2cf07037 100644
--- a/routers/web/repo/editor.go
+++ b/routers/web/repo/editor.go
@@ -40,7 +40,7 @@ const (
 )
 
 func renderCommitRights(ctx *context.Context) bool {
-	canCommitToBranch, err := ctx.Repo.CanCommitToBranch(ctx, ctx.User)
+	canCommitToBranch, err := ctx.Repo.CanCommitToBranch(ctx, ctx.Doer)
 	if err != nil {
 		log.Error("CanCommitToBranch: %v", err)
 	}
@@ -241,7 +241,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
 		message += "\n\n" + form.CommitMessage
 	}
 
-	if _, err := files_service.CreateOrUpdateRepoFile(ctx, ctx.Repo.Repository, ctx.User, &files_service.UpdateRepoFileOptions{
+	if _, err := files_service.CreateOrUpdateRepoFile(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.UpdateRepoFileOptions{
 		LastCommitID: form.LastCommit,
 		OldBranch:    ctx.Repo.BranchName,
 		NewBranch:    branchName,
@@ -447,7 +447,7 @@ func DeleteFilePost(ctx *context.Context) {
 		message += "\n\n" + form.CommitMessage
 	}
 
-	if _, err := files_service.DeleteRepoFile(ctx, ctx.Repo.Repository, ctx.User, &files_service.DeleteRepoFileOptions{
+	if _, err := files_service.DeleteRepoFile(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.DeleteRepoFileOptions{
 		LastCommitID: form.LastCommit,
 		OldBranch:    ctx.Repo.BranchName,
 		NewBranch:    branchName,
@@ -653,7 +653,7 @@ func UploadFilePost(ctx *context.Context) {
 		message += "\n\n" + form.CommitMessage
 	}
 
-	if err := files_service.UploadRepoFiles(ctx, ctx.Repo.Repository, ctx.User, &files_service.UploadRepoFileOptions{
+	if err := files_service.UploadRepoFiles(ctx, ctx.Repo.Repository, ctx.Doer, &files_service.UploadRepoFileOptions{
 		LastCommitID: ctx.Repo.CommitID,
 		OldBranch:    oldBranchName,
 		NewBranch:    branchName,
@@ -798,7 +798,7 @@ func RemoveUploadFileFromServer(ctx *context.Context) {
 // that doesn't already exist. If we exceed 1000 tries or an error is thrown, we just return "" so the user has to
 // type in the branch name themselves (will be an empty field)
 func GetUniquePatchBranchName(ctx *context.Context) string {
-	prefix := ctx.User.LowerName + "-patch-"
+	prefix := ctx.Doer.LowerName + "-patch-"
 	for i := 1; i <= 1000; i++ {
 		branchName := fmt.Sprintf("%s%d", prefix, i)
 		if _, err := ctx.Repo.GitRepo.GetBranch(branchName); err != nil {
diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go
index d5379b610..989e71a3c 100644
--- a/routers/web/repo/http.go
+++ b/routers/web/repo/http.go
@@ -178,7 +178,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
 		}
 
 		if ctx.IsBasicAuth && ctx.Data["IsApiToken"] != true {
-			_, err = auth.GetTwoFactorByUID(ctx.User.ID)
+			_, err = auth.GetTwoFactorByUID(ctx.Doer.ID)
 			if err == nil {
 				// TODO: This response should be changed to "invalid credentials" for security reasons once the expectation behind it (creating an app token to authenticate) is properly documented
 				ctx.PlainText(http.StatusUnauthorized, "Users with two-factor authentication enabled cannot perform HTTP/HTTPS operations via plain username and password. Please create and use a personal access token on the user settings page")
@@ -189,13 +189,13 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
 			}
 		}
 
-		if !ctx.User.IsActive || ctx.User.ProhibitLogin {
+		if !ctx.Doer.IsActive || ctx.Doer.ProhibitLogin {
 			ctx.PlainText(http.StatusForbidden, "Your account is disabled.")
 			return
 		}
 
 		if repoExist {
-			p, err := models.GetUserRepoPermission(repo, ctx.User)
+			p, err := models.GetUserRepoPermission(repo, ctx.Doer)
 			if err != nil {
 				ctx.ServerError("GetUserRepoPermission", err)
 				return
@@ -220,14 +220,14 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
 		environ = []string{
 			models.EnvRepoUsername + "=" + username,
 			models.EnvRepoName + "=" + reponame,
-			models.EnvPusherName + "=" + ctx.User.Name,
-			models.EnvPusherID + fmt.Sprintf("=%d", ctx.User.ID),
+			models.EnvPusherName + "=" + ctx.Doer.Name,
+			models.EnvPusherID + fmt.Sprintf("=%d", ctx.Doer.ID),
 			models.EnvIsDeployKey + "=false",
 			models.EnvAppURL + "=" + setting.AppURL,
 		}
 
-		if !ctx.User.KeepEmailPrivate {
-			environ = append(environ, models.EnvPusherEmail+"="+ctx.User.Email)
+		if !ctx.Doer.KeepEmailPrivate {
+			environ = append(environ, models.EnvPusherEmail+"="+ctx.Doer.Email)
 		}
 
 		if isWiki {
@@ -263,7 +263,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) {
 			return
 		}
 
-		repo, err = repo_service.PushCreateRepo(ctx.User, owner, reponame)
+		repo, err = repo_service.PushCreateRepo(ctx.Doer, owner, reponame)
 		if err != nil {
 			log.Error("pushCreateRepo: %v", err)
 			ctx.Status(http.StatusNotFound)
diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go
index a81b1f196..18f352265 100644
--- a/routers/web/repo/issue.go
+++ b/routers/web/repo/issue.go
@@ -77,7 +77,7 @@ func MustAllowUserComment(ctx *context.Context) {
 		return
 	}
 
-	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
+	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
 		ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
 		ctx.Redirect(issue.HTMLURL())
 		return
@@ -107,9 +107,9 @@ func MustAllowPulls(ctx *context.Context) {
 	}
 
 	// User can send pull request if owns a forked repository.
-	if ctx.IsSigned && repo_model.HasForkedRepo(ctx.User.ID, ctx.Repo.Repository.ID) {
+	if ctx.IsSigned && repo_model.HasForkedRepo(ctx.Doer.ID, ctx.Repo.Repository.ID) {
 		ctx.Repo.PullRequest.Allowed = true
-		ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.User.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
+		ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Doer.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
 	}
 }
 
@@ -133,13 +133,13 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
 	if ctx.IsSigned {
 		switch viewType {
 		case "created_by":
-			posterID = ctx.User.ID
+			posterID = ctx.Doer.ID
 		case "mentioned":
-			mentionedID = ctx.User.ID
+			mentionedID = ctx.Doer.ID
 		case "assigned":
-			assigneeID = ctx.User.ID
+			assigneeID = ctx.Doer.ID
 		case "review_requested":
-			reviewRequestedID = ctx.User.ID
+			reviewRequestedID = ctx.Doer.ID
 		}
 	}
 
@@ -259,7 +259,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti
 		// Check read status
 		if !ctx.IsSigned {
 			issues[i].IsRead = true
-		} else if err = issues[i].GetIsRead(ctx.User.ID); err != nil {
+		} else if err = issues[i].GetIsRead(ctx.Doer.ID); err != nil {
 			ctx.ServerError("GetIsRead", err)
 			return
 		}
@@ -514,7 +514,7 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
 			posterID = 0
 		}
 
-		reviewers, err = models.GetReviewers(repo, ctx.User.ID, posterID)
+		reviewers, err = models.GetReviewers(repo, ctx.Doer.ID, posterID)
 		if err != nil {
 			ctx.ServerError("GetReviewers", err)
 			return
@@ -551,11 +551,11 @@ func RetrieveRepoReviewers(ctx *context.Context, repo *repo_model.Repository, is
 		if ctx.Repo.IsAdmin() {
 			// Admin can dismiss or re-request any review requests
 			tmp.CanChange = true
-		} else if ctx.User != nil && ctx.User.ID == review.ReviewerID && review.Type == models.ReviewTypeRequest {
+		} else if ctx.Doer != nil && ctx.Doer.ID == review.ReviewerID && review.Type == models.ReviewTypeRequest {
 			// A user can refuse review requests
 			tmp.CanChange = true
-		} else if (canChooseReviewer || (ctx.User != nil && ctx.User.ID == issue.PosterID)) && review.Type != models.ReviewTypeRequest &&
-			ctx.User.ID != review.ReviewerID {
+		} else if (canChooseReviewer || (ctx.Doer != nil && ctx.Doer.ID == issue.PosterID)) && review.Type != models.ReviewTypeRequest &&
+			ctx.Doer.ID != review.ReviewerID {
 			// The poster of the PR, a manager, or official reviewers can re-request review from other reviewers
 			tmp.CanChange = true
 		}
@@ -699,7 +699,7 @@ func RetrieveRepoMetas(ctx *context.Context, repo *repo_model.Repository, isPull
 	ctx.Data["Branches"] = brs
 
 	// Contains true if the user can create issue dependencies
-	ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, isPull)
+	ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.Doer, isPull)
 
 	return labels
 }
@@ -859,7 +859,7 @@ func DeleteIssue(ctx *context.Context) {
 		return
 	}
 
-	if err := issue_service.DeleteIssue(ctx.User, ctx.Repo.GitRepo, issue); err != nil {
+	if err := issue_service.DeleteIssue(ctx.Doer, ctx.Repo.GitRepo, issue); err != nil {
 		ctx.ServerError("DeleteIssueByID", err)
 		return
 	}
@@ -1008,8 +1008,8 @@ func NewIssuePost(ctx *context.Context) {
 		RepoID:      repo.ID,
 		Repo:        repo,
 		Title:       form.Title,
-		PosterID:    ctx.User.ID,
-		Poster:      ctx.User,
+		PosterID:    ctx.Doer.ID,
+		Poster:      ctx.Doer,
 		MilestoneID: milestoneID,
 		Content:     form.Content,
 		Ref:         form.Ref,
@@ -1025,7 +1025,7 @@ func NewIssuePost(ctx *context.Context) {
 	}
 
 	if projectID > 0 {
-		if err := models.ChangeProjectAssign(issue, ctx.User, projectID); err != nil {
+		if err := models.ChangeProjectAssign(issue, ctx.Doer, projectID); err != nil {
 			ctx.ServerError("ChangeProjectAssign", err)
 			return
 		}
@@ -1177,10 +1177,10 @@ func ViewIssue(ctx *context.Context) {
 	ctx.Data["Title"] = fmt.Sprintf("#%d - %s", issue.Index, issue.Title)
 
 	iw := new(models.IssueWatch)
-	if ctx.User != nil {
-		iw.UserID = ctx.User.ID
+	if ctx.Doer != nil {
+		iw.UserID = ctx.Doer.ID
 		iw.IssueID = issue.ID
-		iw.IsWatching, err = models.CheckIssueWatch(ctx.User, issue)
+		iw.IsWatching, err = models.CheckIssueWatch(ctx.Doer, issue)
 		if err != nil {
 			ctx.ServerError("CheckIssueWatch", err)
 			return
@@ -1260,8 +1260,8 @@ func ViewIssue(ctx *context.Context) {
 
 	if issue.IsPull {
 		canChooseReviewer := ctx.Repo.CanWrite(unit.TypePullRequests)
-		if !canChooseReviewer && ctx.User != nil && ctx.IsSigned {
-			canChooseReviewer, err = models.IsOfficialReviewer(issue, ctx.User)
+		if !canChooseReviewer && ctx.Doer != nil && ctx.IsSigned {
+			canChooseReviewer, err = models.IsOfficialReviewer(issue, ctx.Doer)
 			if err != nil {
 				ctx.ServerError("IsOfficialReviewer", err)
 				return
@@ -1276,7 +1276,7 @@ func ViewIssue(ctx *context.Context) {
 
 	if ctx.IsSigned {
 		// Update issue-user.
-		if err = issue.ReadBy(ctx.User.ID); err != nil {
+		if err = issue.ReadBy(ctx.Doer.ID); err != nil {
 			ctx.ServerError("ReadBy", err)
 			return
 		}
@@ -1292,11 +1292,11 @@ func ViewIssue(ctx *context.Context) {
 	if ctx.Repo.Repository.IsTimetrackerEnabled() {
 		if ctx.IsSigned {
 			// Deal with the stopwatch
-			ctx.Data["IsStopwatchRunning"] = models.StopwatchExists(ctx.User.ID, issue.ID)
+			ctx.Data["IsStopwatchRunning"] = models.StopwatchExists(ctx.Doer.ID, issue.ID)
 			if !ctx.Data["IsStopwatchRunning"].(bool) {
 				var exists bool
 				var sw *models.Stopwatch
-				if exists, sw, err = models.HasUserStopwatch(ctx.User.ID); err != nil {
+				if exists, sw, err = models.HasUserStopwatch(ctx.Doer.ID); err != nil {
 					ctx.ServerError("HasUserStopwatch", err)
 					return
 				}
@@ -1316,7 +1316,7 @@ func ViewIssue(ctx *context.Context) {
 					ctx.Data["OtherStopwatchURL"] = otherIssue.HTMLURL()
 				}
 			}
-			ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.User)
+			ctx.Data["CanUseTimetracker"] = ctx.Repo.CanUseTimetracker(issue, ctx.Doer)
 		} else {
 			ctx.Data["CanUseTimetracker"] = false
 		}
@@ -1327,7 +1327,7 @@ func ViewIssue(ctx *context.Context) {
 	}
 
 	// Check if the user can use the dependencies
-	ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull)
+	ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx.Doer, issue.IsPull)
 
 	// check if dependencies can be created across repositories
 	ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies
@@ -1511,7 +1511,7 @@ func ViewIssue(ctx *context.Context) {
 			if err := pull.LoadHeadRepo(); err != nil {
 				log.Error("LoadHeadRepo: %v", err)
 			} else if pull.HeadRepo != nil && pull.HeadBranch != pull.HeadRepo.DefaultBranch {
-				perm, err := models.GetUserRepoPermission(pull.HeadRepo, ctx.User)
+				perm, err := models.GetUserRepoPermission(pull.HeadRepo, ctx.Doer)
 				if err != nil {
 					ctx.ServerError("GetUserRepoPermission", err)
 					return
@@ -1530,18 +1530,18 @@ func ViewIssue(ctx *context.Context) {
 			if err := pull.LoadBaseRepo(); err != nil {
 				log.Error("LoadBaseRepo: %v", err)
 			}
-			perm, err := models.GetUserRepoPermission(pull.BaseRepo, ctx.User)
+			perm, err := models.GetUserRepoPermission(pull.BaseRepo, ctx.Doer)
 			if err != nil {
 				ctx.ServerError("GetUserRepoPermission", err)
 				return
 			}
-			ctx.Data["AllowMerge"], err = pull_service.IsUserAllowedToMerge(pull, perm, ctx.User)
+			ctx.Data["AllowMerge"], err = pull_service.IsUserAllowedToMerge(pull, perm, ctx.Doer)
 			if err != nil {
 				ctx.ServerError("IsUserAllowedToMerge", err)
 				return
 			}
 
-			if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.User); err != nil {
+			if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.Doer); err != nil {
 				ctx.ServerError("CanMarkConversation", err)
 				return
 			}
@@ -1581,8 +1581,8 @@ func ViewIssue(ctx *context.Context) {
 		ctx.Data["ShowMergeInstructions"] = true
 		if pull.ProtectedBranch != nil {
 			var showMergeInstructions bool
-			if ctx.User != nil {
-				showMergeInstructions = pull.ProtectedBranch.CanUserPush(ctx.User.ID)
+			if ctx.Doer != nil {
+				showMergeInstructions = pull.ProtectedBranch.CanUserPush(ctx.Doer.ID)
 			}
 			cnt := pull.ProtectedBranch.GetGrantedApprovalsCount(pull)
 			ctx.Data["IsBlockedByApprovals"] = !pull.ProtectedBranch.HasEnoughApprovals(pull)
@@ -1597,8 +1597,8 @@ func ViewIssue(ctx *context.Context) {
 			ctx.Data["ShowMergeInstructions"] = showMergeInstructions
 		}
 		ctx.Data["WillSign"] = false
-		if ctx.User != nil {
-			sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.User, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
+		if ctx.Doer != nil {
+			sign, key, _, err := asymkey_service.SignMerge(ctx, pull, ctx.Doer, pull.BaseRepo.RepoPath(), pull.BaseBranch, pull.GetGitRefName())
 			ctx.Data["WillSign"] = sign
 			ctx.Data["SigningKey"] = key
 			if err != nil {
@@ -1636,7 +1636,7 @@ func ViewIssue(ctx *context.Context) {
 			if pull.CanAutoMerge() || pull.IsWorkInProgress() || pull.IsChecking() {
 				return false
 			}
-			if (ctx.User.IsAdmin || ctx.Repo.IsAdmin()) && prConfig.AllowManualMerge {
+			if (ctx.Doer.IsAdmin || ctx.Repo.IsAdmin()) && prConfig.AllowManualMerge {
 				return true
 			}
 
@@ -1663,16 +1663,16 @@ func ViewIssue(ctx *context.Context) {
 	ctx.Data["Issue"] = issue
 	ctx.Data["Reference"] = issue.Ref
 	ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login?redirect_to=" + url.QueryEscape(ctx.Data["Link"].(string))
-	ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
+	ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID)
 	ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
 	ctx.Data["HasProjectsWritePermission"] = ctx.Repo.CanWrite(unit.TypeProjects)
-	ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.User.IsAdmin)
+	ctx.Data["IsRepoAdmin"] = ctx.IsSigned && (ctx.Repo.IsAdmin() || ctx.Doer.IsAdmin)
 	ctx.Data["LockReasons"] = setting.Repository.Issue.LockReasons
 	ctx.Data["RefEndName"] = git.RefEndName(issue.Ref)
 
 	var hiddenCommentTypes *big.Int
 	if ctx.IsSigned {
-		val, err := user_model.GetUserSetting(ctx.User.ID, user_model.SettingsKeyHiddenCommentTypes)
+		val, err := user_model.GetUserSetting(ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes)
 		if err != nil {
 			ctx.ServerError("GetUserSetting", err)
 			return
@@ -1754,7 +1754,7 @@ func UpdateIssueTitle(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (!issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (!issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
@@ -1765,7 +1765,7 @@ func UpdateIssueTitle(ctx *context.Context) {
 		return
 	}
 
-	if err := issue_service.ChangeTitle(issue, ctx.User, title); err != nil {
+	if err := issue_service.ChangeTitle(issue, ctx.Doer, title); err != nil {
 		ctx.ServerError("ChangeTitle", err)
 		return
 	}
@@ -1782,14 +1782,14 @@ func UpdateIssueRef(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (!issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) || issue.IsPull {
+	if !ctx.IsSigned || (!issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) || issue.IsPull {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
 
 	ref := ctx.FormTrim("ref")
 
-	if err := issue_service.ChangeIssueRef(issue, ctx.User, ref); err != nil {
+	if err := issue_service.ChangeIssueRef(issue, ctx.Doer, ref); err != nil {
 		ctx.ServerError("ChangeRef", err)
 		return
 	}
@@ -1806,12 +1806,12 @@ func UpdateIssueContent(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != issue.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != issue.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
 
-	if err := issue_service.ChangeContent(issue, ctx.User, ctx.Req.FormValue("content")); err != nil {
+	if err := issue_service.ChangeContent(issue, ctx.Doer, ctx.Req.FormValue("content")); err != nil {
 		ctx.ServerError("ChangeContent", err)
 		return
 	}
@@ -1855,7 +1855,7 @@ func UpdateIssueMilestone(ctx *context.Context) {
 			continue
 		}
 		issue.MilestoneID = milestoneID
-		if err := issue_service.ChangeMilestoneAssign(issue, ctx.User, oldMilestoneID); err != nil {
+		if err := issue_service.ChangeMilestoneAssign(issue, ctx.Doer, oldMilestoneID); err != nil {
 			ctx.ServerError("ChangeMilestoneAssign", err)
 			return
 		}
@@ -1879,7 +1879,7 @@ func UpdateIssueAssignee(ctx *context.Context) {
 	for _, issue := range issues {
 		switch action {
 		case "clear":
-			if err := issue_service.DeleteNotPassedAssignee(issue, ctx.User, []*user_model.User{}); err != nil {
+			if err := issue_service.DeleteNotPassedAssignee(issue, ctx.Doer, []*user_model.User{}); err != nil {
 				ctx.ServerError("ClearAssignees", err)
 				return
 			}
@@ -1900,7 +1900,7 @@ func UpdateIssueAssignee(ctx *context.Context) {
 				return
 			}
 
-			_, _, err = issue_service.ToggleAssignee(issue, ctx.User, assigneeID)
+			_, _, err = issue_service.ToggleAssignee(issue, ctx.Doer, assigneeID)
 			if err != nil {
 				ctx.ServerError("ToggleAssignee", err)
 				return
@@ -1972,7 +1972,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
 				return
 			}
 
-			err = issue_service.IsValidTeamReviewRequest(team, ctx.User, action == "attach", issue)
+			err = issue_service.IsValidTeamReviewRequest(team, ctx.Doer, action == "attach", issue)
 			if err != nil {
 				if models.IsErrNotValidReviewRequest(err) {
 					log.Warn(
@@ -1987,7 +1987,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
 				return
 			}
 
-			_, err = issue_service.TeamReviewRequest(issue, ctx.User, team, action == "attach")
+			_, err = issue_service.TeamReviewRequest(issue, ctx.Doer, team, action == "attach")
 			if err != nil {
 				ctx.ServerError("TeamReviewRequest", err)
 				return
@@ -2010,7 +2010,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
 			return
 		}
 
-		err = issue_service.IsValidReviewRequest(reviewer, ctx.User, action == "attach", issue, nil)
+		err = issue_service.IsValidReviewRequest(reviewer, ctx.Doer, action == "attach", issue, nil)
 		if err != nil {
 			if models.IsErrNotValidReviewRequest(err) {
 				log.Warn(
@@ -2025,7 +2025,7 @@ func UpdatePullReviewRequest(ctx *context.Context) {
 			return
 		}
 
-		_, err = issue_service.ReviewRequest(issue, ctx.User, reviewer, action == "attach")
+		_, err = issue_service.ReviewRequest(issue, ctx.Doer, reviewer, action == "attach")
 		if err != nil {
 			ctx.ServerError("ReviewRequest", err)
 			return
@@ -2060,7 +2060,7 @@ func UpdateIssueStatus(ctx *context.Context) {
 	}
 	for _, issue := range issues {
 		if issue.IsClosed != isClosed {
-			if err := issue_service.ChangeStatus(issue, ctx.User, isClosed); err != nil {
+			if err := issue_service.ChangeStatus(issue, ctx.Doer, isClosed); err != nil {
 				if models.IsErrDependenciesLeft(err) {
 					ctx.JSON(http.StatusPreconditionFailed, map[string]interface{}{
 						"error": "cannot close this issue because it still has open dependencies",
@@ -2085,7 +2085,7 @@ func NewComment(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
 		if log.IsTrace() {
 			if ctx.IsSigned {
 				issueType := "issues"
@@ -2094,7 +2094,7 @@ func NewComment(ctx *context.Context) {
 				}
 				log.Trace("Permission Denied: User %-v not the Poster (ID: %d) and cannot read %s in Repo %-v.\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					log.NewColoredIDValue(issue.PosterID),
 					issueType,
 					ctx.Repo.Repository,
@@ -2108,7 +2108,7 @@ func NewComment(ctx *context.Context) {
 		return
 	}
 
-	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.User.IsAdmin {
+	if issue.IsLocked && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) && !ctx.Doer.IsAdmin {
 		ctx.Flash.Error(ctx.Tr("repo.issues.comment_on_locked"))
 		ctx.Redirect(issue.HTMLURL(), http.StatusSeeOther)
 		return
@@ -2128,7 +2128,7 @@ func NewComment(ctx *context.Context) {
 	var comment *models.Comment
 	defer func() {
 		// Check if issue admin/poster changes the status of issue.
-		if (ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) || (ctx.IsSigned && issue.IsPoster(ctx.User.ID))) &&
+		if (ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull) || (ctx.IsSigned && issue.IsPoster(ctx.Doer.ID))) &&
 			(form.Status == "reopen" || form.Status == "close") &&
 			!(issue.IsPull && issue.PullRequest.HasMerged) {
 
@@ -2157,7 +2157,7 @@ func NewComment(ctx *context.Context) {
 				ctx.Flash.Info(ctx.Tr("repo.pulls.open_unmerged_pull_exists", pr.Index))
 			} else {
 				isClosed := form.Status == "close"
-				if err := issue_service.ChangeStatus(issue, ctx.User, isClosed); err != nil {
+				if err := issue_service.ChangeStatus(issue, ctx.Doer, isClosed); err != nil {
 					log.Error("ChangeStatus: %v", err)
 
 					if models.IsErrDependenciesLeft(err) {
@@ -2171,7 +2171,7 @@ func NewComment(ctx *context.Context) {
 						return
 					}
 				} else {
-					if err := stopTimerIfAvailable(ctx.User, issue); err != nil {
+					if err := stopTimerIfAvailable(ctx.Doer, issue); err != nil {
 						ctx.ServerError("CreateOrStopIssueStopwatch", err)
 						return
 					}
@@ -2198,7 +2198,7 @@ func NewComment(ctx *context.Context) {
 		return
 	}
 
-	comment, err := comment_service.CreateIssueComment(ctx.User, ctx.Repo.Repository, issue, form.Content, attachments)
+	comment, err := comment_service.CreateIssueComment(ctx.Doer, ctx.Repo.Repository, issue, form.Content, attachments)
 	if err != nil {
 		ctx.ServerError("CreateIssueComment", err)
 		return
@@ -2220,7 +2220,7 @@ func UpdateCommentContent(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
@@ -2238,7 +2238,7 @@ func UpdateCommentContent(ctx *context.Context) {
 		})
 		return
 	}
-	if err = comment_service.UpdateComment(comment, ctx.User, oldContent); err != nil {
+	if err = comment_service.UpdateComment(comment, ctx.Doer, oldContent); err != nil {
 		ctx.ServerError("UpdateComment", err)
 		return
 	}
@@ -2286,7 +2286,7 @@ func DeleteComment(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanWriteIssuesOrPulls(comment.Issue.IsPull)) {
 		ctx.Error(http.StatusForbidden)
 		return
 	} else if comment.Type != models.CommentTypeComment && comment.Type != models.CommentTypeCode {
@@ -2294,7 +2294,7 @@ func DeleteComment(ctx *context.Context) {
 		return
 	}
 
-	if err = comment_service.DeleteComment(ctx.User, comment); err != nil {
+	if err = comment_service.DeleteComment(ctx.Doer, comment); err != nil {
 		ctx.ServerError("DeleteCommentByID", err)
 		return
 	}
@@ -2310,7 +2310,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
 		if log.IsTrace() {
 			if ctx.IsSigned {
 				issueType := "issues"
@@ -2319,7 +2319,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 				}
 				log.Trace("Permission Denied: User %-v not the Poster (ID: %d) and cannot read %s in Repo %-v.\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					log.NewColoredIDValue(issue.PosterID),
 					issueType,
 					ctx.Repo.Repository,
@@ -2340,7 +2340,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 
 	switch ctx.Params(":action") {
 	case "react":
-		reaction, err := models.CreateIssueReaction(ctx.User, issue, form.Content)
+		reaction, err := models.CreateIssueReaction(ctx.Doer, issue, form.Content)
 		if err != nil {
 			if models.IsErrForbiddenIssueReaction(err) {
 				ctx.ServerError("ChangeIssueReaction", err)
@@ -2358,7 +2358,7 @@ func ChangeIssueReaction(ctx *context.Context) {
 
 		log.Trace("Reaction for issue created: %d/%d/%d", ctx.Repo.Repository.ID, issue.ID, reaction.ID)
 	case "unreact":
-		if err := models.DeleteIssueReaction(ctx.User, issue, form.Content); err != nil {
+		if err := models.DeleteIssueReaction(ctx.Doer, issue, form.Content); err != nil {
 			ctx.ServerError("DeleteIssueReaction", err)
 			return
 		}
@@ -2412,7 +2412,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != comment.PosterID && !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != comment.PosterID && !ctx.Repo.CanReadIssuesOrPulls(comment.Issue.IsPull)) {
 		if log.IsTrace() {
 			if ctx.IsSigned {
 				issueType := "issues"
@@ -2421,7 +2421,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 				}
 				log.Trace("Permission Denied: User %-v not the Poster (ID: %d) and cannot read %s in Repo %-v.\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					log.NewColoredIDValue(comment.Issue.PosterID),
 					issueType,
 					ctx.Repo.Repository,
@@ -2442,7 +2442,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 
 	switch ctx.Params(":action") {
 	case "react":
-		reaction, err := models.CreateCommentReaction(ctx.User, comment.Issue, comment, form.Content)
+		reaction, err := models.CreateCommentReaction(ctx.Doer, comment.Issue, comment, form.Content)
 		if err != nil {
 			if models.IsErrForbiddenIssueReaction(err) {
 				ctx.ServerError("ChangeIssueReaction", err)
@@ -2460,7 +2460,7 @@ func ChangeCommentReaction(ctx *context.Context) {
 
 		log.Trace("Reaction for comment created: %d/%d/%d/%d", ctx.Repo.Repository.ID, comment.Issue.ID, comment.ID, reaction.ID)
 	case "unreact":
-		if err := models.DeleteCommentReaction(ctx.User, comment.Issue, comment, form.Content); err != nil {
+		if err := models.DeleteCommentReaction(ctx.Doer, comment.Issue, comment, form.Content); err != nil {
 			ctx.ServerError("DeleteCommentReaction", err)
 			return
 		}
@@ -2520,7 +2520,7 @@ func filterXRefComments(ctx *context.Context, issue *models.Issue) error {
 			if err != nil {
 				return err
 			}
-			perm, err := models.GetUserRepoPermission(c.RefRepo, ctx.User)
+			perm, err := models.GetUserRepoPermission(c.RefRepo, ctx.Doer)
 			if err != nil {
 				return err
 			}
@@ -2689,7 +2689,7 @@ func combineLabelComments(issue *models.Issue) {
 
 // get all teams that current user can mention
 func handleTeamMentions(ctx *context.Context) {
-	if ctx.User == nil || !ctx.Repo.Owner.IsOrganization() {
+	if ctx.Doer == nil || !ctx.Repo.Owner.IsOrganization() {
 		return
 	}
 
@@ -2698,10 +2698,10 @@ func handleTeamMentions(ctx *context.Context) {
 	var teams []*models.Team
 	org := models.OrgFromUser(ctx.Repo.Owner)
 	// Admin has super access.
-	if ctx.User.IsAdmin {
+	if ctx.Doer.IsAdmin {
 		isAdmin = true
 	} else {
-		isAdmin, err = org.IsOwnedBy(ctx.User.ID)
+		isAdmin, err = org.IsOwnedBy(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("IsOwnedBy", err)
 			return
@@ -2715,7 +2715,7 @@ func handleTeamMentions(ctx *context.Context) {
 			return
 		}
 	} else {
-		teams, err = org.GetUserTeams(ctx.User.ID)
+		teams, err = org.GetUserTeams(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("GetUserTeams", err)
 			return
diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go
index ed9468b91..0d3b23668 100644
--- a/routers/web/repo/issue_content_history.go
+++ b/routers/web/repo/issue_content_history.go
@@ -99,11 +99,11 @@ func canSoftDeleteContentHistory(ctx *context.Context, issue *models.Issue, comm
 	} else if ctx.Repo.CanWrite(unit.TypeIssues) {
 		if comment == nil {
 			// the issue poster or the history poster can soft-delete
-			canSoftDelete = ctx.User.ID == issue.PosterID || ctx.User.ID == history.PosterID
+			canSoftDelete = ctx.Doer.ID == issue.PosterID || ctx.Doer.ID == history.PosterID
 			canSoftDelete = canSoftDelete && (history.IssueID == issue.ID)
 		} else {
 			// the comment poster or the history poster can soft-delete
-			canSoftDelete = ctx.User.ID == comment.PosterID || ctx.User.ID == history.PosterID
+			canSoftDelete = ctx.Doer.ID == comment.PosterID || ctx.Doer.ID == history.PosterID
 			canSoftDelete = canSoftDelete && (history.IssueID == issue.ID)
 			canSoftDelete = canSoftDelete && (history.CommentID == comment.ID)
 		}
diff --git a/routers/web/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go
index 015f31d83..d9084328e 100644
--- a/routers/web/repo/issue_dependency.go
+++ b/routers/web/repo/issue_dependency.go
@@ -22,7 +22,7 @@ func AddDependency(ctx *context.Context) {
 	}
 
 	// Check if the Repo is allowed to have dependencies
-	if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
+	if !ctx.Repo.CanCreateIssueDependencies(ctx.Doer, issue.IsPull) {
 		ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
 		return
 	}
@@ -56,7 +56,7 @@ func AddDependency(ctx *context.Context) {
 		return
 	}
 
-	err = models.CreateIssueDependency(ctx.User, issue, dep)
+	err = models.CreateIssueDependency(ctx.Doer, issue, dep)
 	if err != nil {
 		if models.IsErrDependencyExists(err) {
 			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_exists"))
@@ -81,7 +81,7 @@ func RemoveDependency(ctx *context.Context) {
 	}
 
 	// Check if the Repo is allowed to have dependencies
-	if !ctx.Repo.CanCreateIssueDependencies(ctx.User, issue.IsPull) {
+	if !ctx.Repo.CanCreateIssueDependencies(ctx.Doer, issue.IsPull) {
 		ctx.Error(http.StatusForbidden, "CanCreateIssueDependencies")
 		return
 	}
@@ -115,7 +115,7 @@ func RemoveDependency(ctx *context.Context) {
 		return
 	}
 
-	if err = models.RemoveIssueDependency(ctx.User, issue, dep, depType); err != nil {
+	if err = models.RemoveIssueDependency(ctx.Doer, issue, dep, depType); err != nil {
 		if models.IsErrDependencyNotExists(err) {
 			ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_exist"))
 			return
diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go
index c6fa8c4c8..d1470910d 100644
--- a/routers/web/repo/issue_label.go
+++ b/routers/web/repo/issue_label.go
@@ -82,8 +82,8 @@ func RetrieveLabels(ctx *context.Context) {
 			ctx.ServerError("GetOrgByName", err)
 			return
 		}
-		if ctx.User != nil {
-			ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.User.ID)
+		if ctx.Doer != nil {
+			ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("org.IsOwnedBy", err)
 				return
@@ -169,7 +169,7 @@ func UpdateIssueLabel(ctx *context.Context) {
 	switch action := ctx.FormString("action"); action {
 	case "clear":
 		for _, issue := range issues {
-			if err := issue_service.ClearLabels(issue, ctx.User); err != nil {
+			if err := issue_service.ClearLabels(issue, ctx.Doer); err != nil {
 				ctx.ServerError("ClearLabels", err)
 				return
 			}
@@ -198,14 +198,14 @@ func UpdateIssueLabel(ctx *context.Context) {
 
 		if action == "attach" {
 			for _, issue := range issues {
-				if err = issue_service.AddLabel(issue, ctx.User, label); err != nil {
+				if err = issue_service.AddLabel(issue, ctx.Doer, label); err != nil {
 					ctx.ServerError("AddLabel", err)
 					return
 				}
 			}
 		} else {
 			for _, issue := range issues {
-				if err = issue_service.RemoveLabel(issue, ctx.User, label); err != nil {
+				if err = issue_service.RemoveLabel(issue, ctx.Doer, label); err != nil {
 					ctx.ServerError("RemoveLabel", err)
 					return
 				}
diff --git a/routers/web/repo/issue_lock.go b/routers/web/repo/issue_lock.go
index 103b60c65..b01681866 100644
--- a/routers/web/repo/issue_lock.go
+++ b/routers/web/repo/issue_lock.go
@@ -35,7 +35,7 @@ func LockIssue(ctx *context.Context) {
 	}
 
 	if err := models.LockIssue(&models.IssueLockOptions{
-		Doer:   ctx.User,
+		Doer:   ctx.Doer,
 		Issue:  issue,
 		Reason: form.Reason,
 	}); err != nil {
@@ -60,7 +60,7 @@ func UnlockIssue(ctx *context.Context) {
 	}
 
 	if err := models.UnlockIssue(&models.IssueLockOptions{
-		Doer:  ctx.User,
+		Doer:  ctx.Doer,
 		Issue: issue,
 	}); err != nil {
 		ctx.ServerError("UnlockIssue", err)
diff --git a/routers/web/repo/issue_stopwatch.go b/routers/web/repo/issue_stopwatch.go
index 0e9405fde..8e8f9555a 100644
--- a/routers/web/repo/issue_stopwatch.go
+++ b/routers/web/repo/issue_stopwatch.go
@@ -21,16 +21,16 @@ func IssueStopwatch(c *context.Context) {
 
 	var showSuccessMessage bool
 
-	if !models.StopwatchExists(c.User.ID, issue.ID) {
+	if !models.StopwatchExists(c.Doer.ID, issue.ID) {
 		showSuccessMessage = true
 	}
 
-	if !c.Repo.CanUseTimetracker(issue, c.User) {
+	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
 		c.NotFound("CanUseTimetracker", nil)
 		return
 	}
 
-	if err := models.CreateOrStopIssueStopwatch(c.User, issue); err != nil {
+	if err := models.CreateOrStopIssueStopwatch(c.Doer, issue); err != nil {
 		c.ServerError("CreateOrStopIssueStopwatch", err)
 		return
 	}
@@ -49,12 +49,12 @@ func CancelStopwatch(c *context.Context) {
 	if c.Written() {
 		return
 	}
-	if !c.Repo.CanUseTimetracker(issue, c.User) {
+	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
 		c.NotFound("CanUseTimetracker", nil)
 		return
 	}
 
-	if err := models.CancelStopwatch(c.User, issue); err != nil {
+	if err := models.CancelStopwatch(c.Doer, issue); err != nil {
 		c.ServerError("CancelStopwatch", err)
 		return
 	}
@@ -73,7 +73,7 @@ func GetActiveStopwatch(c *context.Context) {
 		return
 	}
 
-	_, sw, err := models.HasUserStopwatch(c.User.ID)
+	_, sw, err := models.HasUserStopwatch(c.Doer.ID)
 	if err != nil {
 		c.ServerError("HasUserStopwatch", err)
 		return
diff --git a/routers/web/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go
index ec6bb6142..0809acc2e 100644
--- a/routers/web/repo/issue_timetrack.go
+++ b/routers/web/repo/issue_timetrack.go
@@ -22,7 +22,7 @@ func AddTimeManually(c *context.Context) {
 	if c.Written() {
 		return
 	}
-	if !c.Repo.CanUseTimetracker(issue, c.User) {
+	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
 		c.NotFound("CanUseTimetracker", nil)
 		return
 	}
@@ -42,7 +42,7 @@ func AddTimeManually(c *context.Context) {
 		return
 	}
 
-	if _, err := models.AddTime(c.User, issue, int64(total.Seconds()), time.Now()); err != nil {
+	if _, err := models.AddTime(c.Doer, issue, int64(total.Seconds()), time.Now()); err != nil {
 		c.ServerError("AddTime", err)
 		return
 	}
@@ -56,7 +56,7 @@ func DeleteTime(c *context.Context) {
 	if c.Written() {
 		return
 	}
-	if !c.Repo.CanUseTimetracker(issue, c.User) {
+	if !c.Repo.CanUseTimetracker(issue, c.Doer) {
 		c.NotFound("CanUseTimetracker", nil)
 		return
 	}
@@ -72,7 +72,7 @@ func DeleteTime(c *context.Context) {
 	}
 
 	// only OP or admin may delete
-	if !c.IsSigned || (!c.IsUserSiteAdmin() && c.User.ID != t.UserID) {
+	if !c.IsSigned || (!c.IsUserSiteAdmin() && c.Doer.ID != t.UserID) {
 		c.Error(http.StatusForbidden, "not allowed")
 		return
 	}
diff --git a/routers/web/repo/issue_watch.go b/routers/web/repo/issue_watch.go
index dabbff842..223fc7207 100644
--- a/routers/web/repo/issue_watch.go
+++ b/routers/web/repo/issue_watch.go
@@ -20,7 +20,7 @@ func IssueWatch(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (ctx.User.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (ctx.Doer.ID != issue.PosterID && !ctx.Repo.CanReadIssuesOrPulls(issue.IsPull)) {
 		if log.IsTrace() {
 			if ctx.IsSigned {
 				issueType := "issues"
@@ -29,7 +29,7 @@ func IssueWatch(ctx *context.Context) {
 				}
 				log.Trace("Permission Denied: User %-v not the Poster (ID: %d) and cannot read %s in Repo %-v.\n"+
 					"User in Repo has Permissions: %-+v",
-					ctx.User,
+					ctx.Doer,
 					log.NewColoredIDValue(issue.PosterID),
 					issueType,
 					ctx.Repo.Repository,
@@ -48,7 +48,7 @@ func IssueWatch(ctx *context.Context) {
 		return
 	}
 
-	if err := models.CreateOrUpdateIssueWatch(ctx.User.ID, issue.ID, watch); err != nil {
+	if err := models.CreateOrUpdateIssueWatch(ctx.Doer.ID, issue.ID, watch); err != nil {
 		ctx.ServerError("CreateOrUpdateIssueWatch", err)
 		return
 	}
diff --git a/routers/web/repo/lfs.go b/routers/web/repo/lfs.go
index c0f6b039d..395a47a1f 100644
--- a/routers/web/repo/lfs.go
+++ b/routers/web/repo/lfs.go
@@ -217,7 +217,7 @@ func LFSLockFile(ctx *context.Context) {
 
 	_, err := models.CreateLFSLock(ctx.Repo.Repository, &models.LFSLock{
 		Path:    lockPath,
-		OwnerID: ctx.User.ID,
+		OwnerID: ctx.Doer.ID,
 	})
 	if err != nil {
 		if models.IsErrLFSLockAlreadyExist(err) {
@@ -237,7 +237,7 @@ func LFSUnlock(ctx *context.Context) {
 		ctx.NotFound("LFSUnlock", nil)
 		return
 	}
-	_, err := models.DeleteLFSLockByID(ctx.ParamsInt64("lid"), ctx.Repo.Repository, ctx.User, true)
+	_, err := models.DeleteLFSLockByID(ctx.ParamsInt64("lid"), ctx.Repo.Repository, ctx.Doer, true)
 	if err != nil {
 		ctx.ServerError("LFSUnlock", err)
 		return
@@ -476,7 +476,7 @@ func LFSPointerFiles(ctx *context.Context) {
 					// Can we fix?
 					// OK well that's "simple"
 					// - we need to check whether current user has access to a repo that has access to the file
-					result.Associatable, err = models.LFSObjectAccessible(ctx.User, pointerBlob.Oid)
+					result.Associatable, err = models.LFSObjectAccessible(ctx.Doer, pointerBlob.Oid)
 					if err != nil {
 						return err
 					}
@@ -551,7 +551,7 @@ func LFSAutoAssociate(ctx *context.Context) {
 		metas[i].Oid = oid[:idx]
 		// metas[i].RepositoryID = ctx.Repo.Repository.ID
 	}
-	if err := models.LFSAutoAssociate(metas, ctx.User, ctx.Repo.Repository.ID); err != nil {
+	if err := models.LFSAutoAssociate(metas, ctx.Doer, ctx.Repo.Repository.ID); err != nil {
 		ctx.ServerError("LFSAutoAssociate", err)
 		return
 	}
diff --git a/routers/web/repo/middlewares.go b/routers/web/repo/middlewares.go
index c99f0ee8f..ae4177cf1 100644
--- a/routers/web/repo/middlewares.go
+++ b/routers/web/repo/middlewares.go
@@ -43,7 +43,7 @@ func SetDiffViewStyle(ctx *context.Context) {
 	}
 
 	var (
-		userStyle = ctx.User.DiffViewStyle
+		userStyle = ctx.Doer.DiffViewStyle
 		style     string
 	)
 
@@ -56,7 +56,7 @@ func SetDiffViewStyle(ctx *context.Context) {
 	}
 
 	ctx.Data["IsSplitStyle"] = style == "split"
-	if err := user_model.UpdateUserDiffViewStyle(ctx.User, style); err != nil {
+	if err := user_model.UpdateUserDiffViewStyle(ctx.Doer, style); err != nil {
 		ctx.ServerError("ErrUpdateDiffViewStyle", err)
 	}
 }
@@ -72,12 +72,12 @@ func SetWhitespaceBehavior(ctx *context.Context) {
 		whitespaceBehavior = defaultWhitespaceBehavior
 	}
 	if ctx.IsSigned {
-		userWhitespaceBehavior, err := user_model.GetUserSetting(ctx.User.ID, user_model.SettingsKeyDiffWhitespaceBehavior, defaultWhitespaceBehavior)
+		userWhitespaceBehavior, err := user_model.GetUserSetting(ctx.Doer.ID, user_model.SettingsKeyDiffWhitespaceBehavior, defaultWhitespaceBehavior)
 		if err == nil {
 			if whitespaceBehavior == "" {
 				whitespaceBehavior = userWhitespaceBehavior
 			} else if whitespaceBehavior != userWhitespaceBehavior {
-				_ = user_model.SetUserSetting(ctx.User.ID, user_model.SettingsKeyDiffWhitespaceBehavior, whitespaceBehavior)
+				_ = user_model.SetUserSetting(ctx.Doer.ID, user_model.SettingsKeyDiffWhitespaceBehavior, whitespaceBehavior)
 			}
 		} // else: we can ignore the error safely
 	}
diff --git a/routers/web/repo/migrate.go b/routers/web/repo/migrate.go
index 9a31d809d..5845e7e5d 100644
--- a/routers/web/repo/migrate.go
+++ b/routers/web/repo/migrate.go
@@ -178,7 +178,7 @@ func MigratePost(ctx *context.Context) {
 
 	remoteAddr, err := forms.ParseRemoteAddr(form.CloneAddr, form.AuthUsername, form.AuthPassword)
 	if err == nil {
-		err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.User)
+		err = migrations.IsMigrateURLAllowed(remoteAddr, ctx.Doer)
 	}
 	if err != nil {
 		ctx.Data["Err_CloneAddr"] = true
@@ -195,7 +195,7 @@ func MigratePost(ctx *context.Context) {
 			ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_lfs_endpoint"), tpl, &form)
 			return
 		}
-		err = migrations.IsMigrateURLAllowed(ep.String(), ctx.User)
+		err = migrations.IsMigrateURLAllowed(ep.String(), ctx.Doer)
 		if err != nil {
 			ctx.Data["Err_LFSEndpoint"] = true
 			handleMigrateRemoteAddrError(ctx, err, tpl, form)
@@ -233,13 +233,13 @@ func MigratePost(ctx *context.Context) {
 		opts.Releases = false
 	}
 
-	err = repo_model.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, false)
+	err = repo_model.CheckCreateRepository(ctx.Doer, ctxUser, opts.RepoName, false)
 	if err != nil {
 		handleMigrateError(ctx, ctxUser, err, "MigratePost", tpl, form)
 		return
 	}
 
-	err = task.MigrateRepository(ctx.User, ctxUser, opts)
+	err = task.MigrateRepository(ctx.Doer, ctxUser, opts)
 	if err == nil {
 		ctx.Redirect(ctxUser.HomeLink() + "/" + url.PathEscape(opts.RepoName))
 		return
diff --git a/routers/web/repo/patch.go b/routers/web/repo/patch.go
index e08cde89f..2bb9dc119 100644
--- a/routers/web/repo/patch.go
+++ b/routers/web/repo/patch.go
@@ -90,7 +90,7 @@ func NewDiffPatchPost(ctx *context.Context) {
 		message += "\n\n" + form.CommitMessage
 	}
 
-	if _, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.User, &files.ApplyDiffPatchOptions{
+	if _, err := files.ApplyDiffPatch(ctx, ctx.Repo.Repository, ctx.Doer, &files.ApplyDiffPatchOptions{
 		LastCommitID: form.LastCommit,
 		OldBranch:    ctx.Repo.BranchName,
 		NewBranch:    branchName,
diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go
index 3836a00d0..9df2520a5 100644
--- a/routers/web/repo/projects.go
+++ b/routers/web/repo/projects.go
@@ -143,7 +143,7 @@ func NewProjectPost(ctx *context.Context) {
 		RepoID:      ctx.Repo.Repository.ID,
 		Title:       form.Title,
 		Description: form.Content,
-		CreatorID:   ctx.User.ID,
+		CreatorID:   ctx.Doer.ID,
 		BoardType:   form.BoardType,
 		Type:        models.ProjectTypeRepository,
 	}); err != nil {
@@ -354,7 +354,7 @@ func UpdateIssueProject(ctx *context.Context) {
 			continue
 		}
 
-		if err := models.ChangeProjectAssign(issue, ctx.User, projectID); err != nil {
+		if err := models.ChangeProjectAssign(issue, ctx.Doer, projectID); err != nil {
 			ctx.ServerError("ChangeProjectAssign", err)
 			return
 		}
@@ -367,7 +367,7 @@ func UpdateIssueProject(ctx *context.Context) {
 
 // DeleteProjectBoard allows for the deletion of a project board
 func DeleteProjectBoard(ctx *context.Context) {
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.JSON(http.StatusForbidden, map[string]string{
 			"message": "Only signed in users are allowed to perform this action.",
 		})
@@ -444,7 +444,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
 		ProjectID: project.ID,
 		Title:     form.Title,
 		Color:     form.Color,
-		CreatorID: ctx.User.ID,
+		CreatorID: ctx.Doer.ID,
 	}); err != nil {
 		ctx.ServerError("NewProjectBoard", err)
 		return
@@ -456,7 +456,7 @@ func AddBoardToProjectPost(ctx *context.Context) {
 }
 
 func checkProjectBoardChangePermissions(ctx *context.Context) (*models.Project, *models.ProjectBoard) {
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.JSON(http.StatusForbidden, map[string]string{
 			"message": "Only signed in users are allowed to perform this action.",
 		})
@@ -548,7 +548,7 @@ func SetDefaultProjectBoard(ctx *context.Context) {
 
 // MoveIssues moves or keeps issues in a column and sorts them inside that column
 func MoveIssues(ctx *context.Context) {
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.JSON(http.StatusForbidden, map[string]string{
 			"message": "Only signed in users are allowed to perform this action.",
 		})
diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 1ac3e51e4..05c1ab745 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -68,7 +68,7 @@ func getRepository(ctx *context.Context, repoID int64) *repo_model.Repository {
 		return nil
 	}
 
-	perm, err := models.GetUserRepoPermission(repo, ctx.User)
+	perm, err := models.GetUserRepoPermission(repo, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserRepoPermission", err)
 		return nil
@@ -77,7 +77,7 @@ func getRepository(ctx *context.Context, repoID int64) *repo_model.Repository {
 	if !perm.CanRead(unit.TypeCode) {
 		log.Trace("Permission Denied: User %-v cannot read %-v of repo %-v\n"+
 			"User in repo has Permissions: %-+v",
-			ctx.User,
+			ctx.Doer,
 			unit.TypeCode,
 			ctx.Repo,
 			perm)
@@ -107,11 +107,11 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
 	ctx.Data["repo_name"] = forkRepo.Name
 	ctx.Data["description"] = forkRepo.Description
 	ctx.Data["IsPrivate"] = forkRepo.IsPrivate || forkRepo.Owner.Visibility == structs.VisibleTypePrivate
-	canForkToUser := forkRepo.OwnerID != ctx.User.ID && !repo_model.HasForkedRepo(ctx.User.ID, forkRepo.ID)
+	canForkToUser := forkRepo.OwnerID != ctx.Doer.ID && !repo_model.HasForkedRepo(ctx.Doer.ID, forkRepo.ID)
 
 	ctx.Data["ForkRepo"] = forkRepo
 
-	ownedOrgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.User.ID)
+	ownedOrgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
 		return nil
@@ -125,7 +125,7 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
 
 	traverseParentRepo := forkRepo
 	for {
-		if ctx.User.ID == traverseParentRepo.OwnerID {
+		if ctx.Doer.ID == traverseParentRepo.OwnerID {
 			canForkToUser = false
 		} else {
 			for i, org := range orgs {
@@ -150,7 +150,7 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository {
 	ctx.Data["Orgs"] = orgs
 
 	if canForkToUser {
-		ctx.Data["ContextUser"] = ctx.User
+		ctx.Data["ContextUser"] = ctx.Doer
 	} else if len(orgs) > 0 {
 		ctx.Data["ContextUser"] = orgs[0]
 	}
@@ -216,7 +216,7 @@ func ForkPost(ctx *context.Context) {
 
 	// Check if user is allowed to create repo's on the organization.
 	if ctxUser.IsOrganization() {
-		isAllowedToFork, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.User.ID)
+		isAllowedToFork, err := models.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("CanCreateOrgRepo", err)
 			return
@@ -226,7 +226,7 @@ func ForkPost(ctx *context.Context) {
 		}
 	}
 
-	repo, err := repo_service.ForkRepository(ctx.User, ctxUser, repo_service.ForkRepoOptions{
+	repo, err := repo_service.ForkRepository(ctx.Doer, ctxUser, repo_service.ForkRepoOptions{
 		BaseRepo:    forkRepo,
 		Name:        form.RepoName,
 		Description: form.Description,
@@ -288,7 +288,7 @@ func checkPullInfo(ctx *context.Context) *models.Issue {
 
 	if ctx.IsSigned {
 		// Update issue-user.
-		if err = issue.ReadBy(ctx.User.ID); err != nil {
+		if err = issue.ReadBy(ctx.Doer.ID); err != nil {
 			ctx.ServerError("ReadBy", err)
 			return nil
 		}
@@ -497,7 +497,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
 
 	if headBranchExist {
 		var err error
-		ctx.Data["UpdateAllowed"], ctx.Data["UpdateByRebaseAllowed"], err = pull_service.IsUserAllowedToUpdate(pull, ctx.User)
+		ctx.Data["UpdateAllowed"], ctx.Data["UpdateByRebaseAllowed"], err = pull_service.IsUserAllowedToUpdate(pull, ctx.Doer)
 		if err != nil {
 			ctx.ServerError("IsUserAllowedToUpdate", err)
 			return nil
@@ -699,7 +699,7 @@ func ViewPullFiles(ctx *context.Context) {
 		return
 	}
 
-	if err = diff.LoadComments(ctx, issue, ctx.User); err != nil {
+	if err = diff.LoadComments(ctx, issue, ctx.Doer); err != nil {
 		ctx.ServerError("LoadComments", err)
 		return
 	}
@@ -732,8 +732,8 @@ func ViewPullFiles(ctx *context.Context) {
 		return
 	}
 
-	if ctx.IsSigned && ctx.User != nil {
-		if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.User); err != nil {
+	if ctx.IsSigned && ctx.Doer != nil {
+		if ctx.Data["CanMarkConversation"], err = models.CanMarkConversation(issue, ctx.Doer); err != nil {
 			ctx.ServerError("CanMarkConversation", err)
 			return
 		}
@@ -751,13 +751,13 @@ func ViewPullFiles(ctx *context.Context) {
 	if ctx.Written() {
 		return
 	}
-	ctx.Data["CurrentReview"], err = models.GetCurrentReview(ctx.User, issue)
+	ctx.Data["CurrentReview"], err = models.GetCurrentReview(ctx.Doer, issue)
 	if err != nil && !models.IsErrReviewNotExist(err) {
 		ctx.ServerError("GetCurrentReview", err)
 		return
 	}
 	getBranchData(ctx, issue)
-	ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.User.ID)
+	ctx.Data["IsIssuePoster"] = ctx.IsSigned && issue.IsPoster(ctx.Doer.ID)
 	ctx.Data["HasIssuesOrPullsWritePermission"] = ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)
 
 	ctx.Data["IsAttachmentEnabled"] = setting.Attachment.Enabled
@@ -792,7 +792,7 @@ func UpdatePullRequest(ctx *context.Context) {
 		return
 	}
 
-	allowedUpdateByMerge, allowedUpdateByRebase, err := pull_service.IsUserAllowedToUpdate(issue.PullRequest, ctx.User)
+	allowedUpdateByMerge, allowedUpdateByRebase, err := pull_service.IsUserAllowedToUpdate(issue.PullRequest, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("IsUserAllowedToMerge", err)
 		return
@@ -808,7 +808,7 @@ func UpdatePullRequest(ctx *context.Context) {
 	// default merge commit message
 	message := fmt.Sprintf("Merge branch '%s' into %s", issue.PullRequest.BaseBranch, issue.PullRequest.HeadBranch)
 
-	if err = pull_service.Update(ctx, issue.PullRequest, ctx.User, message, rebase); err != nil {
+	if err = pull_service.Update(ctx, issue.PullRequest, ctx.Doer, message, rebase); err != nil {
 		if models.IsErrMergeConflicts(err) {
 			conflictError := err.(models.ErrMergeConflicts)
 			flashError, err := ctx.RenderToString(tplAlertDetails, map[string]interface{}{
@@ -870,7 +870,7 @@ func MergePullRequest(ctx *context.Context) {
 
 	pr := issue.PullRequest
 
-	allowedMerge, err := pull_service.IsUserAllowedToMerge(pr, ctx.Repo.Permission, ctx.User)
+	allowedMerge, err := pull_service.IsUserAllowedToMerge(pr, ctx.Repo.Permission, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("IsUserAllowedToMerge", err)
 		return
@@ -889,7 +889,7 @@ func MergePullRequest(ctx *context.Context) {
 
 	// handle manually-merged mark
 	if repo_model.MergeStyle(form.Do) == repo_model.MergeStyleManuallyMerged {
-		if err = pull_service.MergedManually(pr, ctx.User, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
+		if err = pull_service.MergedManually(pr, ctx.Doer, ctx.Repo.GitRepo, form.MergeCommitID); err != nil {
 			if models.IsErrInvalidMergeStyle(err) {
 				ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
 				ctx.Redirect(issue.Link())
@@ -925,7 +925,7 @@ func MergePullRequest(ctx *context.Context) {
 			ctx.ServerError("Merge PR status", err)
 			return
 		}
-		if isRepoAdmin, err := models.IsUserRepoAdmin(pr.BaseRepo, ctx.User); err != nil {
+		if isRepoAdmin, err := models.IsUserRepoAdmin(pr.BaseRepo, ctx.Doer); err != nil {
 			ctx.ServerError("IsUserRepoAdmin", err)
 			return
 		} else if !isRepoAdmin {
@@ -973,7 +973,7 @@ func MergePullRequest(ctx *context.Context) {
 		return
 	}
 
-	if err = pull_service.Merge(ctx, pr, ctx.User, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil {
+	if err = pull_service.Merge(ctx, pr, ctx.Doer, ctx.Repo.GitRepo, repo_model.MergeStyle(form.Do), form.HeadCommitID, message); err != nil {
 		if models.IsErrInvalidMergeStyle(err) {
 			ctx.Flash.Error(ctx.Tr("repo.pulls.invalid_merge_option"))
 			ctx.Redirect(issue.Link())
@@ -1046,7 +1046,7 @@ func MergePullRequest(ctx *context.Context) {
 		return
 	}
 
-	if err := stopTimerIfAvailable(ctx.User, issue); err != nil {
+	if err := stopTimerIfAvailable(ctx.Doer, issue); err != nil {
 		ctx.ServerError("CreateOrStopIssueStopwatch", err)
 		return
 	}
@@ -1168,8 +1168,8 @@ func CompareAndPullRequestPost(ctx *context.Context) {
 		RepoID:      repo.ID,
 		Repo:        repo,
 		Title:       form.Title,
-		PosterID:    ctx.User.ID,
-		Poster:      ctx.User,
+		PosterID:    ctx.Doer.ID,
+		Poster:      ctx.Doer,
 		MilestoneID: milestoneID,
 		IsPull:      true,
 		Content:     form.Content,
@@ -1260,7 +1260,7 @@ func CleanUpPullRequest(ctx *context.Context) {
 		return
 	}
 
-	perm, err := models.GetUserRepoPermission(pr.HeadRepo, ctx.User)
+	perm, err := models.GetUserRepoPermission(pr.HeadRepo, ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserRepoPermission", err)
 		return
@@ -1331,7 +1331,7 @@ func CleanUpPullRequest(ctx *context.Context) {
 
 func deleteBranch(ctx *context.Context, pr *models.PullRequest, gitRepo *git.Repository) {
 	fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch
-	if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
+	if err := repo_service.DeleteBranch(ctx.Doer, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
 		switch {
 		case git.IsErrBranchNotExist(err):
 			ctx.Flash.Error(ctx.Tr("repo.branch.deletion_failed", fullBranchName))
@@ -1346,7 +1346,7 @@ func deleteBranch(ctx *context.Context, pr *models.PullRequest, gitRepo *git.Rep
 		return
 	}
 
-	if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil {
+	if err := models.AddDeletePRBranchComment(ctx.Doer, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil {
 		// Do not fail here as branch has already been deleted
 		log.Error("DeleteBranch: %v", err)
 	}
@@ -1396,7 +1396,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
 		return
 	}
 
-	if !ctx.IsSigned || (!issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
+	if !ctx.IsSigned || (!issue.IsPoster(ctx.Doer.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
 		ctx.Error(http.StatusForbidden)
 		return
 	}
@@ -1407,7 +1407,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
 		return
 	}
 
-	if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.User, targetBranch); err != nil {
+	if err := pull_service.ChangeTargetBranch(ctx, pr, ctx.Doer, targetBranch); err != nil {
 		if models.IsErrPullRequestAlreadyExists(err) {
 			err := err.(models.ErrPullRequestAlreadyExists)
 
@@ -1448,7 +1448,7 @@ func UpdatePullRequestTarget(ctx *context.Context) {
 		}
 		return
 	}
-	notification.NotifyPullRequestChangeTargetBranch(ctx.User, pr, targetBranch)
+	notification.NotifyPullRequestChangeTargetBranch(ctx.Doer, pr, targetBranch)
 
 	ctx.JSON(http.StatusOK, map[string]interface{}{
 		"base_branch": pr.BaseBranch,
diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go
index c92f08a88..939b0037a 100644
--- a/routers/web/repo/pull_review.go
+++ b/routers/web/repo/pull_review.go
@@ -29,7 +29,7 @@ func RenderNewCodeCommentForm(ctx *context.Context) {
 	if !issue.IsPull {
 		return
 	}
-	currentReview, err := models.GetCurrentReview(ctx.User, issue)
+	currentReview, err := models.GetCurrentReview(ctx.Doer, issue)
 	if err != nil && !models.IsErrReviewNotExist(err) {
 		ctx.ServerError("GetCurrentReview", err)
 		return
@@ -69,7 +69,7 @@ func CreateCodeComment(ctx *context.Context) {
 	}
 
 	comment, err := pull_service.CreateCodeComment(ctx,
-		ctx.User,
+		ctx.Doer,
 		ctx.Repo.GitRepo,
 		issue,
 		signedLine,
@@ -117,7 +117,7 @@ func UpdateResolveConversation(ctx *context.Context) {
 	}
 
 	var permResult bool
-	if permResult, err = models.CanMarkConversation(comment.Issue, ctx.User); err != nil {
+	if permResult, err = models.CanMarkConversation(comment.Issue, ctx.Doer); err != nil {
 		ctx.ServerError("CanMarkConversation", err)
 		return
 	}
@@ -132,7 +132,7 @@ func UpdateResolveConversation(ctx *context.Context) {
 	}
 
 	if action == "Resolve" || action == "UnResolve" {
-		err = models.MarkConversation(comment, ctx.User, action == "Resolve")
+		err = models.MarkConversation(comment, ctx.Doer, action == "Resolve")
 		if err != nil {
 			ctx.ServerError("MarkConversation", err)
 			return
@@ -152,7 +152,7 @@ func UpdateResolveConversation(ctx *context.Context) {
 }
 
 func renderConversation(ctx *context.Context, comment *models.Comment) {
-	comments, err := models.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.User, comment.TreePath, comment.Line)
+	comments, err := models.FetchCodeCommentsByLine(ctx, comment.Issue, ctx.Doer, comment.TreePath, comment.Line)
 	if err != nil {
 		ctx.ServerError("FetchCodeCommentsByLine", err)
 		return
@@ -198,7 +198,7 @@ func SubmitReview(ctx *context.Context) {
 
 	// can not approve/reject your own PR
 	case models.ReviewTypeApprove, models.ReviewTypeReject:
-		if issue.IsPoster(ctx.User.ID) {
+		if issue.IsPoster(ctx.Doer.ID) {
 			var translated string
 			if reviewType == models.ReviewTypeApprove {
 				translated = ctx.Tr("repo.issues.review.self.approval")
@@ -217,7 +217,7 @@ func SubmitReview(ctx *context.Context) {
 		attachments = form.Files
 	}
 
-	_, comm, err := pull_service.SubmitReview(ctx, ctx.User, ctx.Repo.GitRepo, issue, reviewType, form.Content, form.CommitID, attachments)
+	_, comm, err := pull_service.SubmitReview(ctx, ctx.Doer, ctx.Repo.GitRepo, issue, reviewType, form.Content, form.CommitID, attachments)
 	if err != nil {
 		if models.IsContentEmptyErr(err) {
 			ctx.Flash.Error(ctx.Tr("repo.issues.review.content.empty"))
@@ -234,7 +234,7 @@ func SubmitReview(ctx *context.Context) {
 // DismissReview dismissing stale review by repo admin
 func DismissReview(ctx *context.Context) {
 	form := web.GetForm(ctx).(*forms.DismissReviewForm)
-	comm, err := pull_service.DismissReview(ctx, form.ReviewID, form.Message, ctx.User, true)
+	comm, err := pull_service.DismissReview(ctx, form.ReviewID, form.Message, ctx.Doer, true)
 	if err != nil {
 		ctx.ServerError("pull_service.DismissReview", err)
 		return
diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go
index 4f58ac954..5f894ae50 100644
--- a/routers/web/repo/release.go
+++ b/routers/web/repo/release.go
@@ -134,8 +134,8 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
 	// Temporary cache commits count of used branches to speed up.
 	countCache := make(map[string]int64)
 	cacheUsers := make(map[int64]*user_model.User)
-	if ctx.User != nil {
-		cacheUsers[ctx.User.ID] = ctx.User
+	if ctx.Doer != nil {
+		cacheUsers[ctx.Doer.ID] = ctx.Doer
 	}
 	var ok bool
 
@@ -325,7 +325,7 @@ func NewReleasePost(ctx *context.Context) {
 		}
 
 		if len(form.TagOnly) > 0 {
-			if err = releaseservice.CreateNewTag(ctx, ctx.User, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
+			if err = releaseservice.CreateNewTag(ctx, ctx.Doer, ctx.Repo.Repository, form.Target, form.TagName, msg); err != nil {
 				if models.IsErrTagAlreadyExists(err) {
 					e := err.(models.ErrTagAlreadyExists)
 					ctx.Flash.Error(ctx.Tr("repo.branch.tag_collision", e.TagName))
@@ -357,8 +357,8 @@ func NewReleasePost(ctx *context.Context) {
 		rel = &models.Release{
 			RepoID:       ctx.Repo.Repository.ID,
 			Repo:         ctx.Repo.Repository,
-			PublisherID:  ctx.User.ID,
-			Publisher:    ctx.User,
+			PublisherID:  ctx.Doer.ID,
+			Publisher:    ctx.Doer,
 			Title:        form.Title,
 			TagName:      form.TagName,
 			Target:       form.Target,
@@ -394,16 +394,16 @@ func NewReleasePost(ctx *context.Context) {
 		rel.Target = form.Target
 		rel.IsDraft = len(form.Draft) > 0
 		rel.IsPrerelease = form.Prerelease
-		rel.PublisherID = ctx.User.ID
+		rel.PublisherID = ctx.Doer.ID
 		rel.IsTag = false
 
-		if err = releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
+		if err = releaseservice.UpdateRelease(ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil); err != nil {
 			ctx.Data["Err_TagName"] = true
 			ctx.ServerError("UpdateRelease", err)
 			return
 		}
 	}
-	log.Trace("Release created: %s/%s:%s", ctx.User.LowerName, ctx.Repo.Repository.Name, form.TagName)
+	log.Trace("Release created: %s/%s:%s", ctx.Doer.LowerName, ctx.Repo.Repository.Name, form.TagName)
 
 	ctx.Redirect(ctx.Repo.RepoLink + "/releases")
 }
@@ -497,7 +497,7 @@ func EditReleasePost(ctx *context.Context) {
 	rel.Note = form.Content
 	rel.IsDraft = len(form.Draft) > 0
 	rel.IsPrerelease = form.Prerelease
-	if err = releaseservice.UpdateRelease(ctx.User, ctx.Repo.GitRepo,
+	if err = releaseservice.UpdateRelease(ctx.Doer, ctx.Repo.GitRepo,
 		rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments); err != nil {
 		ctx.ServerError("UpdateRelease", err)
 		return
@@ -516,7 +516,7 @@ func DeleteTag(ctx *context.Context) {
 }
 
 func deleteReleaseOrTag(ctx *context.Context, isDelTag bool) {
-	if err := releaseservice.DeleteReleaseByID(ctx, ctx.FormInt64("id"), ctx.User, isDelTag); err != nil {
+	if err := releaseservice.DeleteReleaseByID(ctx, ctx.FormInt64("id"), ctx.Doer, isDelTag); err != nil {
 		ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
 	} else {
 		if isDelTag {
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index 89ebef3a5..7e08a8af0 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -57,13 +57,13 @@ func MustBeAbleToUpload(ctx *context.Context) {
 }
 
 func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
-	orgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.User.ID)
+	orgs, err := models.GetOrgsCanCreateRepoByUserID(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetOrgsCanCreateRepoByUserID", err)
 		return nil
 	}
 
-	if !ctx.User.IsAdmin {
+	if !ctx.Doer.IsAdmin {
 		orgsAvailable := []*models.Organization{}
 		for i := 0; i < len(orgs); i++ {
 			if orgs[i].CanCreateRepo() {
@@ -76,13 +76,13 @@ func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
 	}
 
 	// Not equal means current user is an organization.
-	if uid == ctx.User.ID || uid == 0 {
-		return ctx.User
+	if uid == ctx.Doer.ID || uid == 0 {
+		return ctx.Doer
 	}
 
 	org, err := user_model.GetUserByID(uid)
 	if user_model.IsErrUserNotExist(err) {
-		return ctx.User
+		return ctx.Doer
 	}
 
 	if err != nil {
@@ -95,8 +95,8 @@ func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
 		ctx.Error(http.StatusForbidden)
 		return nil
 	}
-	if !ctx.User.IsAdmin {
-		canCreate, err := models.OrgFromUser(org).CanCreateOrgRepo(ctx.User.ID)
+	if !ctx.Doer.IsAdmin {
+		canCreate, err := models.OrgFromUser(org).CanCreateOrgRepo(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("CanCreateOrgRepo", err)
 			return nil
@@ -113,13 +113,13 @@ func checkContextUser(ctx *context.Context, uid int64) *user_model.User {
 func getRepoPrivate(ctx *context.Context) bool {
 	switch strings.ToLower(setting.Repository.DefaultPrivate) {
 	case setting.RepoCreatingLastUserVisibility:
-		return ctx.User.LastRepoVisibility
+		return ctx.Doer.LastRepoVisibility
 	case setting.RepoCreatingPrivate:
 		return true
 	case setting.RepoCreatingPublic:
 		return false
 	default:
-		return ctx.User.LastRepoVisibility
+		return ctx.Doer.LastRepoVisibility
 	}
 }
 
@@ -153,8 +153,8 @@ func Create(ctx *context.Context) {
 		}
 	}
 
-	ctx.Data["CanCreateRepo"] = ctx.User.CanCreateRepo()
-	ctx.Data["MaxCreationLimit"] = ctx.User.MaxCreationLimit()
+	ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo()
+	ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit()
 
 	ctx.HTML(http.StatusOK, tplCreate)
 }
@@ -201,8 +201,8 @@ func CreatePost(ctx *context.Context) {
 	ctx.Data["Licenses"] = models.Licenses
 	ctx.Data["Readmes"] = models.Readmes
 
-	ctx.Data["CanCreateRepo"] = ctx.User.CanCreateRepo()
-	ctx.Data["MaxCreationLimit"] = ctx.User.MaxCreationLimit()
+	ctx.Data["CanCreateRepo"] = ctx.Doer.CanCreateRepo()
+	ctx.Data["MaxCreationLimit"] = ctx.Doer.MaxCreationLimit()
 
 	ctxUser := checkContextUser(ctx, form.UID)
 	if ctx.Written() {
@@ -245,14 +245,14 @@ func CreatePost(ctx *context.Context) {
 			return
 		}
 
-		repo, err = repo_service.GenerateRepository(ctx.User, ctxUser, templateRepo, opts)
+		repo, err = repo_service.GenerateRepository(ctx.Doer, ctxUser, templateRepo, opts)
 		if err == nil {
 			log.Trace("Repository generated [%d]: %s/%s", repo.ID, ctxUser.Name, repo.Name)
 			ctx.Redirect(repo.Link())
 			return
 		}
 	} else {
-		repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{
+		repo, err = repo_service.CreateRepository(ctx.Doer, ctxUser, models.CreateRepoOptions{
 			Name:          form.RepoName,
 			Description:   form.Description,
 			Gitignores:    form.Gitignores,
@@ -280,13 +280,13 @@ func Action(ctx *context.Context) {
 	var err error
 	switch ctx.Params(":action") {
 	case "watch":
-		err = repo_model.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
+		err = repo_model.WatchRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, true)
 	case "unwatch":
-		err = repo_model.WatchRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
+		err = repo_model.WatchRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, false)
 	case "star":
-		err = repo_model.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, true)
+		err = repo_model.StarRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, true)
 	case "unstar":
-		err = repo_model.StarRepo(ctx.User.ID, ctx.Repo.Repository.ID, false)
+		err = repo_model.StarRepo(ctx.Doer.ID, ctx.Repo.Repository.ID, false)
 	case "accept_transfer":
 		err = acceptOrRejectRepoTransfer(ctx, true)
 	case "reject_transfer":
@@ -320,7 +320,7 @@ func acceptOrRejectRepoTransfer(ctx *context.Context, accept bool) error {
 		return err
 	}
 
-	if !repoTransfer.CanUserAcceptTransfer(ctx.User) {
+	if !repoTransfer.CanUserAcceptTransfer(ctx.Doer) {
 		return errors.New("user does not have enough permissions")
 	}
 
diff --git a/routers/web/repo/setting.go b/routers/web/repo/setting.go
index 5f7b948b8..8c8f627fa 100644
--- a/routers/web/repo/setting.go
+++ b/routers/web/repo/setting.go
@@ -70,7 +70,7 @@ func Settings(ctx *context.Context) {
 	ctx.Data["SigningKeyAvailable"] = len(signing) > 0
 	ctx.Data["SigningSettings"] = setting.Repository.Signing
 	ctx.Data["CodeIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-	if ctx.User.IsAdmin {
+	if ctx.Doer.IsAdmin {
 		if setting.Indexer.RepoIndexerEnabled {
 			status, err := repo_model.GetIndexerStatus(ctx.Repo.Repository, repo_model.RepoIndexerTypeCode)
 			if err != nil {
@@ -119,7 +119,7 @@ func SettingsPost(ctx *context.Context) {
 				ctx.Repo.GitRepo.Close()
 				ctx.Repo.GitRepo = nil
 			}
-			if err := repo_service.ChangeRepositoryName(ctx.User, repo, newRepoName); err != nil {
+			if err := repo_service.ChangeRepositoryName(ctx.Doer, repo, newRepoName); err != nil {
 				ctx.Data["Err_RepoName"] = true
 				switch {
 				case repo_model.IsErrRepoAlreadyExist(err):
@@ -162,7 +162,7 @@ func SettingsPost(ctx *context.Context) {
 
 		visibilityChanged := repo.IsPrivate != form.Private
 		// when ForcePrivate enabled, you could change public repo to private, but only admin users can change private to public
-		if visibilityChanged && setting.Repository.ForcePrivate && !form.Private && !ctx.User.IsAdmin {
+		if visibilityChanged && setting.Repository.ForcePrivate && !form.Private && !ctx.Doer.IsAdmin {
 			ctx.RenderWithErr(ctx.Tr("form.repository_force_private"), tplSettingsOptions, form)
 			return
 		}
@@ -213,7 +213,7 @@ func SettingsPost(ctx *context.Context) {
 
 		address, err := forms.ParseRemoteAddr(form.MirrorAddress, form.MirrorUsername, form.MirrorPassword)
 		if err == nil {
-			err = migrations.IsMigrateURLAllowed(address, ctx.User)
+			err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
 		}
 		if err != nil {
 			ctx.Data["Err_MirrorAddress"] = true
@@ -235,7 +235,7 @@ func SettingsPost(ctx *context.Context) {
 				ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_lfs_endpoint"), tplSettingsOptions, &form)
 				return
 			}
-			err = migrations.IsMigrateURLAllowed(ep.String(), ctx.User)
+			err = migrations.IsMigrateURLAllowed(ep.String(), ctx.Doer)
 			if err != nil {
 				ctx.Data["Err_LFSEndpoint"] = true
 				handleSettingRemoteAddrError(ctx, err, form)
@@ -329,7 +329,7 @@ func SettingsPost(ctx *context.Context) {
 
 		address, err := forms.ParseRemoteAddr(form.PushMirrorAddress, form.PushMirrorUsername, form.PushMirrorPassword)
 		if err == nil {
-			err = migrations.IsMigrateURLAllowed(address, ctx.User)
+			err = migrations.IsMigrateURLAllowed(address, ctx.Doer)
 		}
 		if err != nil {
 			ctx.Data["Err_PushMirrorAddress"] = true
@@ -516,7 +516,7 @@ func SettingsPost(ctx *context.Context) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 
 	case "admin":
-		if !ctx.User.IsAdmin {
+		if !ctx.Doer.IsAdmin {
 			ctx.Error(http.StatusForbidden)
 			return
 		}
@@ -536,7 +536,7 @@ func SettingsPost(ctx *context.Context) {
 		ctx.Redirect(ctx.Repo.RepoLink + "/settings")
 
 	case "admin_index":
-		if !ctx.User.IsAdmin {
+		if !ctx.Doer.IsAdmin {
 			ctx.Error(http.StatusForbidden)
 			return
 		}
@@ -648,7 +648,7 @@ func SettingsPost(ctx *context.Context) {
 		}
 
 		if newOwner.Type == user_model.UserTypeOrganization {
-			if !ctx.User.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.User.ID) {
+			if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !models.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) {
 				// The user shouldn't know about this organization
 				ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil)
 				return
@@ -661,7 +661,7 @@ func SettingsPost(ctx *context.Context) {
 			ctx.Repo.GitRepo = nil
 		}
 
-		if err := repo_service.StartRepositoryTransfer(ctx.User, newOwner, repo, nil); err != nil {
+		if err := repo_service.StartRepositoryTransfer(ctx.Doer, newOwner, repo, nil); err != nil {
 			if repo_model.IsErrRepoAlreadyExist(err) {
 				ctx.RenderWithErr(ctx.Tr("repo.settings.new_owner_has_same_repo"), tplSettingsOptions, nil)
 			} else if models.IsErrRepoTransferInProgress(err) {
@@ -724,7 +724,7 @@ func SettingsPost(ctx *context.Context) {
 			ctx.Repo.GitRepo.Close()
 		}
 
-		if err := repo_service.DeleteRepository(ctx, ctx.User, ctx.Repo.Repository, true); err != nil {
+		if err := repo_service.DeleteRepository(ctx, ctx.Doer, ctx.Repo.Repository, true); err != nil {
 			ctx.ServerError("DeleteRepository", err)
 			return
 		}
@@ -894,7 +894,7 @@ func CollaborationPost(ctx *context.Context) {
 	}
 
 	if setting.Service.EnableNotifyMail {
-		mailer.SendCollaboratorMail(u, ctx.User, ctx.Repo.Repository)
+		mailer.SendCollaboratorMail(u, ctx.Doer, ctx.Repo.Repository)
 	}
 
 	ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success"))
@@ -1127,7 +1127,7 @@ func DeployKeysPost(ctx *context.Context) {
 
 // DeleteDeployKey response for deleting a deploy key
 func DeleteDeployKey(ctx *context.Context) {
-	if err := asymkey_service.DeleteDeployKey(ctx.User, ctx.FormInt64("id")); err != nil {
+	if err := asymkey_service.DeleteDeployKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
 		ctx.Flash.Error("DeleteDeployKey: " + err.Error())
 	} else {
 		ctx.Flash.Success(ctx.Tr("repo.settings.deploy_key_deletion_success"))
diff --git a/routers/web/repo/setting_protected_branch.go b/routers/web/repo/setting_protected_branch.go
index 1435b820a..cd6cf3803 100644
--- a/routers/web/repo/setting_protected_branch.go
+++ b/routers/web/repo/setting_protected_branch.go
@@ -305,7 +305,7 @@ func RenameBranchPost(ctx *context.Context) {
 		return
 	}
 
-	msg, err := repository.RenameBranch(ctx.Repo.Repository, ctx.User, ctx.Repo.GitRepo, form.From, form.To)
+	msg, err := repository.RenameBranch(ctx.Repo.Repository, ctx.Doer, ctx.Repo.GitRepo, form.From, form.To)
 	if err != nil {
 		ctx.ServerError("RenameBranch", err)
 		return
diff --git a/routers/web/repo/topic.go b/routers/web/repo/topic.go
index a6a7ac6c8..efbfc62d5 100644
--- a/routers/web/repo/topic.go
+++ b/routers/web/repo/topic.go
@@ -15,7 +15,7 @@ import (
 
 // TopicsPost response for creating repository
 func TopicsPost(ctx *context.Context) {
-	if ctx.User == nil {
+	if ctx.Doer == nil {
 		ctx.JSON(http.StatusForbidden, map[string]interface{}{
 			"message": "Only owners could change the topics.",
 		})
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index 5293d3c6a..3bdcefa4c 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -559,7 +559,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
 		}
 		if !isLFSFile {
 			if ctx.Repo.CanEnableEditor() {
-				if lfsLock != nil && lfsLock.OwnerID != ctx.User.ID {
+				if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
 					ctx.Data["CanEditFile"] = false
 					ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
 				} else {
@@ -609,7 +609,7 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st
 	}
 
 	if ctx.Repo.CanEnableEditor() {
-		if lfsLock != nil && lfsLock.OwnerID != ctx.User.ID {
+		if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
 			ctx.Data["CanDeleteFile"] = false
 			ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
 		} else {
@@ -663,7 +663,7 @@ func checkHomeCodeViewable(ctx *context.Context) {
 
 		if ctx.IsSigned {
 			// Set repo notification-status read if unread
-			if err := models.SetRepoReadBy(ctx.Repo.Repository.ID, ctx.User.ID); err != nil {
+			if err := models.SetRepoReadBy(ctx.Repo.Repository.ID, ctx.Doer.ID); err != nil {
 				ctx.ServerError("ReadBy", err)
 				return
 			}
diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go
index 76ebd1c48..d457bcb19 100644
--- a/routers/web/repo/webhook.go
+++ b/routers/web/repo/webhook.go
@@ -85,7 +85,7 @@ func getOrgRepoCtx(ctx *context.Context) (*orgRepoCtx, error) {
 		}, nil
 	}
 
-	if ctx.User.IsAdmin {
+	if ctx.Doer.IsAdmin {
 		// Are we looking at default webhooks?
 		if ctx.Params(":configType") == "default-hooks" {
 			return &orgRepoCtx{
@@ -1258,7 +1258,7 @@ func TestWebhook(ctx *context.Context) {
 		}
 	}
 
-	apiUser := convert.ToUserWithAccessMode(ctx.User, perm.AccessModeNone)
+	apiUser := convert.ToUserWithAccessMode(ctx.Doer, perm.AccessModeNone)
 
 	apiCommit := &api.PayloadCommit{
 		ID:      commit.ID.String(),
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 633458081..bd148413d 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -47,7 +47,7 @@ func MustEnableWiki(ctx *context.Context) {
 		if log.IsTrace() {
 			log.Trace("Permission Denied: User %-v cannot read %-v or %-v of repo %-v\n"+
 				"User in repo has Permissions: %-+v",
-				ctx.User,
+				ctx.Doer,
 				unit.TypeWiki,
 				unit.TypeExternalWiki,
 				ctx.Repo.Repository,
@@ -658,7 +658,7 @@ func NewWikiPost(ctx *context.Context) {
 		form.Message = ctx.Tr("repo.editor.add", form.Title)
 	}
 
-	if err := wiki_service.AddWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil {
+	if err := wiki_service.AddWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil {
 		if models.IsErrWikiReservedName(err) {
 			ctx.Data["Err_Title"] = true
 			ctx.RenderWithErr(ctx.Tr("repo.wiki.reserved_page", wikiName), tplWikiNew, &form)
@@ -710,7 +710,7 @@ func EditWikiPost(ctx *context.Context) {
 		form.Message = ctx.Tr("repo.editor.update", form.Title)
 	}
 
-	if err := wiki_service.EditWikiPage(ctx, ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
+	if err := wiki_service.EditWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil {
 		ctx.ServerError("EditWikiPage", err)
 		return
 	}
@@ -725,7 +725,7 @@ func DeleteWikiPagePost(ctx *context.Context) {
 		wikiName = "Home"
 	}
 
-	if err := wiki_service.DeleteWikiPage(ctx, ctx.User, ctx.Repo.Repository, wikiName); err != nil {
+	if err := wiki_service.DeleteWikiPage(ctx, ctx.Doer, ctx.Repo.Repository, wikiName); err != nil {
 		ctx.ServerError("DeleteWikiPage", err)
 		return
 	}
diff --git a/routers/web/user/home.go b/routers/web/user/home.go
index 877aa4528..7489f08b1 100644
--- a/routers/web/user/home.go
+++ b/routers/web/user/home.go
@@ -46,7 +46,7 @@ const (
 
 // getDashboardContextUser finds out which context user dashboard is being viewed as .
 func getDashboardContextUser(ctx *context.Context) *user_model.User {
-	ctxUser := ctx.User
+	ctxUser := ctx.Doer
 	orgName := ctx.Params(":org")
 	if len(orgName) > 0 {
 		ctxUser = ctx.Org.Organization.AsUser()
@@ -54,7 +54,7 @@ func getDashboardContextUser(ctx *context.Context) *user_model.User {
 	}
 	ctx.Data["ContextUser"] = ctxUser
 
-	orgs, err := models.GetUserOrgsList(ctx.User)
+	orgs, err := models.GetUserOrgsList(ctx.Doer)
 	if err != nil {
 		ctx.ServerError("GetUserOrgsList", err)
 		return nil
@@ -88,7 +88,7 @@ func Dashboard(ctx *context.Context) {
 	}
 
 	if setting.Service.EnableUserHeatmap {
-		data, err := models.GetUserHeatmapDataByUserTeam(ctxUser, ctx.Org.Team, ctx.User)
+		data, err := models.GetUserHeatmapDataByUserTeam(ctxUser, ctx.Org.Team, ctx.Doer)
 		if err != nil {
 			ctx.ServerError("GetUserHeatmapDataByUserTeam", err)
 			return
@@ -103,7 +103,7 @@ func Dashboard(ctx *context.Context) {
 		if ctx.Org.Team != nil {
 			env = models.OrgFromUser(ctxUser).AccessibleTeamReposEnv(ctx.Org.Team)
 		} else {
-			env, err = models.OrgFromUser(ctxUser).AccessibleReposEnv(ctx.User.ID)
+			env, err = models.OrgFromUser(ctxUser).AccessibleReposEnv(ctx.Doer.ID)
 			if err != nil {
 				ctx.ServerError("AccessibleReposEnv", err)
 				return
@@ -133,7 +133,7 @@ func Dashboard(ctx *context.Context) {
 	ctx.Data["Feeds"], err = models.GetFeeds(ctx, models.GetFeedsOptions{
 		RequestedUser:   ctxUser,
 		RequestedTeam:   ctx.Org.Team,
-		Actor:           ctx.User,
+		Actor:           ctx.Doer,
 		IncludePrivate:  true,
 		OnlyPerformedBy: false,
 		IncludeDeleted:  false,
@@ -416,19 +416,19 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
 		IsArchived: util.OptionalBoolFalse,
 		Org:        org,
 		Team:       team,
-		User:       ctx.User,
+		User:       ctx.Doer,
 	}
 
 	switch filterMode {
 	case models.FilterModeAll:
 	case models.FilterModeAssign:
-		opts.AssigneeID = ctx.User.ID
+		opts.AssigneeID = ctx.Doer.ID
 	case models.FilterModeCreate:
-		opts.PosterID = ctx.User.ID
+		opts.PosterID = ctx.Doer.ID
 	case models.FilterModeMention:
-		opts.MentionedID = ctx.User.ID
+		opts.MentionedID = ctx.Doer.ID
 	case models.FilterModeReviewRequested:
-		opts.ReviewRequestedID = ctx.User.ID
+		opts.ReviewRequestedID = ctx.Doer.ID
 	}
 
 	// keyword holds the search term entered into the search field.
@@ -550,7 +550,7 @@ func buildIssueOverview(ctx *context.Context, unitType unit.Type) {
 	var issueStats *models.IssueStats
 	if !forceEmpty {
 		statsOpts := models.UserIssueStatsOptions{
-			UserID:     ctx.User.ID,
+			UserID:     ctx.Doer.ID,
 			FilterMode: filterMode,
 			IsPull:     isPullList,
 			IsClosed:   isShowClosed,
diff --git a/routers/web/user/home_test.go b/routers/web/user/home_test.go
index cd599abd0..bf78e00ad 100644
--- a/routers/web/user/home_test.go
+++ b/routers/web/user/home_test.go
@@ -26,7 +26,7 @@ func TestArchivedIssues(t *testing.T) {
 	ctx.Req.Form.Set("state", "open")
 
 	// Assume: User 30 has access to two Repos with Issues, one of the Repos being archived.
-	repos, _, _ := models.GetUserRepositories(&models.SearchRepoOptions{Actor: ctx.User})
+	repos, _, _ := models.GetUserRepositories(&models.SearchRepoOptions{Actor: ctx.Doer})
 	assert.Len(t, repos, 2)
 	IsArchived := make(map[int64]bool)
 	NumIssues := make(map[int64]int)
diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go
index 08cd1b8b3..04e987924 100644
--- a/routers/web/user/notification.go
+++ b/routers/web/user/notification.go
@@ -33,7 +33,7 @@ func GetNotificationCount(c *context.Context) {
 	}
 
 	c.Data["NotificationUnreadCount"] = func() int64 {
-		count, err := models.GetNotificationCount(c.User, models.NotificationStatusUnread)
+		count, err := models.GetNotificationCount(c.Doer, models.NotificationStatusUnread)
 		if err != nil {
 			c.ServerError("GetNotificationCount", err)
 			return -1
@@ -78,7 +78,7 @@ func getNotifications(c *context.Context) {
 		status = models.NotificationStatusUnread
 	}
 
-	total, err := models.GetNotificationCount(c.User, status)
+	total, err := models.GetNotificationCount(c.Doer, status)
 	if err != nil {
 		c.ServerError("ErrGetNotificationCount", err)
 		return
@@ -92,7 +92,7 @@ func getNotifications(c *context.Context) {
 	}
 
 	statuses := []models.NotificationStatus{status, models.NotificationStatusPinned}
-	notifications, err := models.NotificationsForUser(c.User, statuses, page, perPage)
+	notifications, err := models.NotificationsForUser(c.Doer, statuses, page, perPage)
 	if err != nil {
 		c.ServerError("ErrNotificationsForUser", err)
 		return
@@ -161,7 +161,7 @@ func NotificationStatusPost(c *context.Context) {
 		return
 	}
 
-	if _, err := models.SetNotificationStatus(notificationID, c.User, status); err != nil {
+	if _, err := models.SetNotificationStatus(notificationID, c.Doer, status); err != nil {
 		c.ServerError("SetNotificationStatus", err)
 		return
 	}
@@ -183,7 +183,7 @@ func NotificationStatusPost(c *context.Context) {
 
 // NotificationPurgePost is a route for 'purging' the list of notifications - marking all unread as read
 func NotificationPurgePost(c *context.Context) {
-	err := models.UpdateNotificationStatuses(c.User, models.NotificationStatusUnread, models.NotificationStatusRead)
+	err := models.UpdateNotificationStatuses(c.Doer, models.NotificationStatusUnread, models.NotificationStatusRead)
 	if err != nil {
 		c.ServerError("ErrUpdateNotificationStatuses", err)
 		return
diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go
index b84cee2b3..ca8011a6c 100644
--- a/routers/web/user/profile.go
+++ b/routers/web/user/profile.go
@@ -93,7 +93,7 @@ func Profile(ctx *context.Context) {
 	}
 
 	// check view permissions
-	if !models.IsUserVisibleToViewer(ctxUser, ctx.User) {
+	if !models.IsUserVisibleToViewer(ctxUser, ctx.Doer) {
 		ctx.NotFound("user", fmt.Errorf(uname))
 		return
 	}
@@ -127,8 +127,8 @@ func Profile(ctx *context.Context) {
 	}
 
 	var isFollowing bool
-	if ctx.User != nil && ctxUser != nil {
-		isFollowing = user_model.IsFollowing(ctx.User.ID, ctxUser.ID)
+	if ctx.Doer != nil && ctxUser != nil {
+		isFollowing = user_model.IsFollowing(ctx.Doer.ID, ctxUser.ID)
 	}
 
 	ctx.Data["Title"] = ctxUser.DisplayName()
@@ -138,7 +138,7 @@ func Profile(ctx *context.Context) {
 	ctx.Data["IsFollowing"] = isFollowing
 
 	if setting.Service.EnableUserHeatmap {
-		data, err := models.GetUserHeatmapDataByUser(ctxUser, ctx.User)
+		data, err := models.GetUserHeatmapDataByUser(ctxUser, ctx.Doer)
 		if err != nil {
 			ctx.ServerError("GetUserHeatmapDataByUser", err)
 			return
@@ -160,7 +160,7 @@ func Profile(ctx *context.Context) {
 		ctx.Data["RenderedDescription"] = content
 	}
 
-	showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID)
+	showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctxUser.ID)
 
 	orgs, err := models.FindOrgs(models.FindOrgOptions{
 		UserID:         ctxUser.ID,
@@ -172,7 +172,7 @@ func Profile(ctx *context.Context) {
 	}
 
 	ctx.Data["Orgs"] = orgs
-	ctx.Data["HasOrgsVisible"] = models.HasOrgsVisible(orgs, ctx.User)
+	ctx.Data["HasOrgsVisible"] = models.HasOrgsVisible(orgs, ctx.Doer)
 
 	tab := ctx.FormString("tab")
 	ctx.Data["TabName"] = tab
@@ -252,7 +252,7 @@ func Profile(ctx *context.Context) {
 	case "activity":
 		ctx.Data["Feeds"], err = models.GetFeeds(ctx, models.GetFeedsOptions{
 			RequestedUser:   ctxUser,
-			Actor:           ctx.User,
+			Actor:           ctx.Doer,
 			IncludePrivate:  showPrivate,
 			OnlyPerformedBy: true,
 			IncludeDeleted:  false,
@@ -269,7 +269,7 @@ func Profile(ctx *context.Context) {
 				PageSize: setting.UI.User.RepoPagingNum,
 				Page:     page,
 			},
-			Actor:              ctx.User,
+			Actor:              ctx.Doer,
 			Keyword:            keyword,
 			OrderBy:            orderBy,
 			Private:            ctx.IsSigned,
@@ -301,7 +301,7 @@ func Profile(ctx *context.Context) {
 				PageSize: setting.UI.User.RepoPagingNum,
 				Page:     page,
 			},
-			Actor:              ctx.User,
+			Actor:              ctx.Doer,
 			Keyword:            keyword,
 			OrderBy:            orderBy,
 			Private:            ctx.IsSigned,
@@ -323,7 +323,7 @@ func Profile(ctx *context.Context) {
 				PageSize: setting.UI.User.RepoPagingNum,
 				Page:     page,
 			},
-			Actor:              ctx.User,
+			Actor:              ctx.Doer,
 			Keyword:            keyword,
 			OwnerID:            ctxUser.ID,
 			OrderBy:            orderBy,
@@ -350,7 +350,7 @@ func Profile(ctx *context.Context) {
 	}
 	ctx.Data["Page"] = pager
 
-	ctx.Data["ShowUserEmail"] = len(ctxUser.Email) > 0 && ctx.IsSigned && (!ctxUser.KeepEmailPrivate || ctxUser.ID == ctx.User.ID)
+	ctx.Data["ShowUserEmail"] = len(ctxUser.Email) > 0 && ctx.IsSigned && (!ctxUser.KeepEmailPrivate || ctxUser.ID == ctx.Doer.ID)
 
 	ctx.HTML(http.StatusOK, tplProfile)
 }
@@ -365,9 +365,9 @@ func Action(ctx *context.Context) {
 	var err error
 	switch ctx.FormString("action") {
 	case "follow":
-		err = user_model.FollowUser(ctx.User.ID, u.ID)
+		err = user_model.FollowUser(ctx.Doer.ID, u.ID)
 	case "unfollow":
-		err = user_model.UnfollowUser(ctx.User.ID, u.ID)
+		err = user_model.UnfollowUser(ctx.Doer.ID, u.ID)
 	}
 
 	if err != nil {
diff --git a/routers/web/user/setting/account.go b/routers/web/user/setting/account.go
index 492b4f82c..468d5ca65 100644
--- a/routers/web/user/setting/account.go
+++ b/routers/web/user/setting/account.go
@@ -34,7 +34,7 @@ const (
 func Account(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsAccount"] = true
-	ctx.Data["Email"] = ctx.User.Email
+	ctx.Data["Email"] = ctx.Doer.Email
 
 	loadAccountData(ctx)
 
@@ -56,7 +56,7 @@ func AccountPost(ctx *context.Context) {
 
 	if len(form.Password) < setting.MinPasswordLength {
 		ctx.Flash.Error(ctx.Tr("auth.password_too_short", setting.MinPasswordLength))
-	} else if ctx.User.IsPasswordSet() && !ctx.User.ValidatePassword(form.OldPassword) {
+	} else if ctx.Doer.IsPasswordSet() && !ctx.Doer.ValidatePassword(form.OldPassword) {
 		ctx.Flash.Error(ctx.Tr("settings.password_incorrect"))
 	} else if form.Password != form.Retype {
 		ctx.Flash.Error(ctx.Tr("form.password_not_match"))
@@ -71,15 +71,15 @@ func AccountPost(ctx *context.Context) {
 		ctx.Flash.Error(errMsg)
 	} else {
 		var err error
-		if err = ctx.User.SetPassword(form.Password); err != nil {
+		if err = ctx.Doer.SetPassword(form.Password); err != nil {
 			ctx.ServerError("UpdateUser", err)
 			return
 		}
-		if err := user_model.UpdateUserCols(db.DefaultContext, ctx.User, "salt", "passwd_hash_algo", "passwd"); err != nil {
+		if err := user_model.UpdateUserCols(db.DefaultContext, ctx.Doer, "salt", "passwd_hash_algo", "passwd"); err != nil {
 			ctx.ServerError("UpdateUser", err)
 			return
 		}
-		log.Trace("User password updated: %s", ctx.User.Name)
+		log.Trace("User password updated: %s", ctx.Doer.Name)
 		ctx.Flash.Success(ctx.Tr("settings.change_password_success"))
 	}
 
@@ -99,50 +99,50 @@ func EmailPost(ctx *context.Context) {
 			return
 		}
 
-		log.Trace("Email made primary: %s", ctx.User.Name)
+		log.Trace("Email made primary: %s", ctx.Doer.Name)
 		ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 		return
 	}
 	// Send activation Email
 	if ctx.FormString("_method") == "SENDACTIVATION" {
 		var address string
-		if ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName) {
+		if ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName) {
 			log.Error("Send activation: activation still pending")
 			ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 			return
 		}
 
 		id := ctx.FormInt64("id")
-		email, err := user_model.GetEmailAddressByID(ctx.User.ID, id)
+		email, err := user_model.GetEmailAddressByID(ctx.Doer.ID, id)
 		if err != nil {
-			log.Error("GetEmailAddressByID(%d,%d) error: %v", ctx.User.ID, id, err)
+			log.Error("GetEmailAddressByID(%d,%d) error: %v", ctx.Doer.ID, id, err)
 			ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 			return
 		}
 		if email == nil {
-			log.Warn("Send activation failed: EmailAddress[%d] not found for user: %-v", id, ctx.User)
+			log.Warn("Send activation failed: EmailAddress[%d] not found for user: %-v", id, ctx.Doer)
 			ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 			return
 		}
 		if email.IsActivated {
-			log.Debug("Send activation failed: email %s is already activated for user: %-v", email.Email, ctx.User)
+			log.Debug("Send activation failed: email %s is already activated for user: %-v", email.Email, ctx.Doer)
 			ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 			return
 		}
 		if email.IsPrimary {
-			if ctx.User.IsActive && !setting.Service.RegisterEmailConfirm {
-				log.Debug("Send activation failed: email %s is already activated for user: %-v", email.Email, ctx.User)
+			if ctx.Doer.IsActive && !setting.Service.RegisterEmailConfirm {
+				log.Debug("Send activation failed: email %s is already activated for user: %-v", email.Email, ctx.Doer)
 				ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 				return
 			}
 			// Only fired when the primary email is inactive (Wrong state)
-			mailer.SendActivateAccountMail(ctx.Locale, ctx.User)
+			mailer.SendActivateAccountMail(ctx.Locale, ctx.Doer)
 		} else {
-			mailer.SendActivateEmailMail(ctx.User, email)
+			mailer.SendActivateEmailMail(ctx.Doer, email)
 		}
 		address = email.Email
 
-		if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
+		if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
 			log.Error("Set cache(MailResendLimit) fail: %v", err)
 		}
 		ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", address, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())))
@@ -155,16 +155,16 @@ func EmailPost(ctx *context.Context) {
 		if !(preference == user_model.EmailNotificationsEnabled ||
 			preference == user_model.EmailNotificationsOnMention ||
 			preference == user_model.EmailNotificationsDisabled) {
-			log.Error("Email notifications preference change returned unrecognized option %s: %s", preference, ctx.User.Name)
+			log.Error("Email notifications preference change returned unrecognized option %s: %s", preference, ctx.Doer.Name)
 			ctx.ServerError("SetEmailPreference", errors.New("option unrecognized"))
 			return
 		}
-		if err := user_model.SetEmailNotifications(ctx.User, preference); err != nil {
+		if err := user_model.SetEmailNotifications(ctx.Doer, preference); err != nil {
 			log.Error("Set Email Notifications failed: %v", err)
 			ctx.ServerError("SetEmailNotifications", err)
 			return
 		}
-		log.Trace("Email notifications preference made %s: %s", preference, ctx.User.Name)
+		log.Trace("Email notifications preference made %s: %s", preference, ctx.Doer.Name)
 		ctx.Flash.Success(ctx.Tr("settings.email_preference_set_success"))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/account")
 		return
@@ -178,7 +178,7 @@ func EmailPost(ctx *context.Context) {
 	}
 
 	email := &user_model.EmailAddress{
-		UID:         ctx.User.ID,
+		UID:         ctx.Doer.ID,
 		Email:       form.Email,
 		IsActivated: !setting.Service.RegisterEmailConfirm,
 	}
@@ -201,8 +201,8 @@ func EmailPost(ctx *context.Context) {
 
 	// Send confirmation email
 	if setting.Service.RegisterEmailConfirm {
-		mailer.SendActivateEmailMail(ctx.User, email)
-		if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
+		mailer.SendActivateEmailMail(ctx.Doer, email)
+		if err := ctx.Cache.Put("MailResendLimit_"+ctx.Doer.LowerName, ctx.Doer.LowerName, 180); err != nil {
 			log.Error("Set cache(MailResendLimit) fail: %v", err)
 		}
 		ctx.Flash.Info(ctx.Tr("settings.add_email_confirmation_sent", email.Email, timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, ctx.Locale.Language())))
@@ -216,11 +216,11 @@ func EmailPost(ctx *context.Context) {
 
 // DeleteEmail response for delete user's email
 func DeleteEmail(ctx *context.Context) {
-	if err := user_model.DeleteEmailAddress(&user_model.EmailAddress{ID: ctx.FormInt64("id"), UID: ctx.User.ID}); err != nil {
+	if err := user_model.DeleteEmailAddress(&user_model.EmailAddress{ID: ctx.FormInt64("id"), UID: ctx.Doer.ID}); err != nil {
 		ctx.ServerError("DeleteEmail", err)
 		return
 	}
-	log.Trace("Email address deleted: %s", ctx.User.Name)
+	log.Trace("Email address deleted: %s", ctx.Doer.Name)
 
 	ctx.Flash.Success(ctx.Tr("settings.email_deletion_success"))
 	ctx.JSON(http.StatusOK, map[string]interface{}{
@@ -233,7 +233,7 @@ func DeleteAccount(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsAccount"] = true
 
-	if _, _, err := auth.UserSignIn(ctx.User.Name, ctx.FormString("password")); err != nil {
+	if _, _, err := auth.UserSignIn(ctx.Doer.Name, ctx.FormString("password")); err != nil {
 		if user_model.IsErrUserNotExist(err) {
 			loadAccountData(ctx)
 
@@ -244,7 +244,7 @@ func DeleteAccount(ctx *context.Context) {
 		return
 	}
 
-	if err := user.DeleteUser(ctx.User); err != nil {
+	if err := user.DeleteUser(ctx.Doer); err != nil {
 		switch {
 		case models.IsErrUserOwnRepos(err):
 			ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
@@ -256,13 +256,13 @@ func DeleteAccount(ctx *context.Context) {
 			ctx.ServerError("DeleteUser", err)
 		}
 	} else {
-		log.Trace("Account deleted: %s", ctx.User.Name)
+		log.Trace("Account deleted: %s", ctx.Doer.Name)
 		ctx.Redirect(setting.AppSubURL + "/")
 	}
 }
 
 func loadAccountData(ctx *context.Context) {
-	emlist, err := user_model.GetEmailAddresses(ctx.User.ID)
+	emlist, err := user_model.GetEmailAddresses(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetEmailAddresses", err)
 		return
@@ -271,7 +271,7 @@ func loadAccountData(ctx *context.Context) {
 		user_model.EmailAddress
 		CanBePrimary bool
 	}
-	pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.User.LowerName)
+	pendingActivation := ctx.Cache.IsExist("MailResendLimit_" + ctx.Doer.LowerName)
 	emails := make([]*UserEmail, len(emlist))
 	for i, em := range emlist {
 		var email UserEmail
@@ -280,12 +280,12 @@ func loadAccountData(ctx *context.Context) {
 		emails[i] = &email
 	}
 	ctx.Data["Emails"] = emails
-	ctx.Data["EmailNotificationsPreference"] = ctx.User.EmailNotifications()
+	ctx.Data["EmailNotificationsPreference"] = ctx.Doer.EmailNotifications()
 	ctx.Data["ActivationsPending"] = pendingActivation
 	ctx.Data["CanAddEmails"] = !pendingActivation || !setting.Service.RegisterEmailConfirm
 
 	if setting.Service.UserDeleteWithCommentsMaxTime != 0 {
 		ctx.Data["UserDeleteWithCommentsMaxTime"] = setting.Service.UserDeleteWithCommentsMaxTime.String()
-		ctx.Data["UserDeleteWithComments"] = ctx.User.CreatedUnix.AsTime().Add(setting.Service.UserDeleteWithCommentsMaxTime).After(time.Now())
+		ctx.Data["UserDeleteWithComments"] = ctx.Doer.CreatedUnix.AsTime().Add(setting.Service.UserDeleteWithCommentsMaxTime).After(time.Now())
 	}
 }
diff --git a/routers/web/user/setting/adopt.go b/routers/web/user/setting/adopt.go
index 348705b74..ce2377a99 100644
--- a/routers/web/user/setting/adopt.go
+++ b/routers/web/user/setting/adopt.go
@@ -28,7 +28,7 @@ func AdoptOrDeleteRepository(ctx *context.Context) {
 	dir := ctx.FormString("id")
 	action := ctx.FormString("action")
 
-	ctxUser := ctx.User
+	ctxUser := ctx.Doer
 	root := user_model.UserPath(ctxUser.LowerName)
 
 	// check not a repo
diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go
index 20ffdfaf8..b0f599fc4 100644
--- a/routers/web/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
@@ -45,7 +45,7 @@ func ApplicationsPost(ctx *context.Context) {
 	}
 
 	t := &models.AccessToken{
-		UID:  ctx.User.ID,
+		UID:  ctx.Doer.ID,
 		Name: form.Name,
 	}
 
@@ -73,7 +73,7 @@ func ApplicationsPost(ctx *context.Context) {
 
 // DeleteApplication response for delete user access token
 func DeleteApplication(ctx *context.Context) {
-	if err := models.DeleteAccessTokenByID(ctx.FormInt64("id"), ctx.User.ID); err != nil {
+	if err := models.DeleteAccessTokenByID(ctx.FormInt64("id"), ctx.Doer.ID); err != nil {
 		ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
 	} else {
 		ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
@@ -85,7 +85,7 @@ func DeleteApplication(ctx *context.Context) {
 }
 
 func loadApplicationsData(ctx *context.Context) {
-	tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID})
+	tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.Doer.ID})
 	if err != nil {
 		ctx.ServerError("ListAccessTokens", err)
 		return
@@ -93,12 +93,12 @@ func loadApplicationsData(ctx *context.Context) {
 	ctx.Data["Tokens"] = tokens
 	ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
 	if setting.OAuth2.Enable {
-		ctx.Data["Applications"], err = auth.GetOAuth2ApplicationsByUserID(ctx.User.ID)
+		ctx.Data["Applications"], err = auth.GetOAuth2ApplicationsByUserID(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("GetOAuth2ApplicationsByUserID", err)
 			return
 		}
-		ctx.Data["Grants"], err = auth.GetOAuth2GrantsByUserID(ctx.User.ID)
+		ctx.Data["Grants"], err = auth.GetOAuth2GrantsByUserID(ctx.Doer.ID)
 		if err != nil {
 			ctx.ServerError("GetOAuth2GrantsByUserID", err)
 			return
diff --git a/routers/web/user/setting/keys.go b/routers/web/user/setting/keys.go
index f926c1f31..2cc627ecd 100644
--- a/routers/web/user/setting/keys.go
+++ b/routers/web/user/setting/keys.go
@@ -52,7 +52,7 @@ func KeysPost(ctx *context.Context) {
 	}
 	switch form.Type {
 	case "principal":
-		content, err := asymkey_model.CheckPrincipalKeyString(ctx.User, form.Content)
+		content, err := asymkey_model.CheckPrincipalKeyString(ctx.Doer, form.Content)
 		if err != nil {
 			if db.IsErrSSHDisabled(err) {
 				ctx.Flash.Info(ctx.Tr("settings.ssh_disabled"))
@@ -62,7 +62,7 @@ func KeysPost(ctx *context.Context) {
 			ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
 			return
 		}
-		if _, err = asymkey_model.AddPrincipalKey(ctx.User.ID, content, 0); err != nil {
+		if _, err = asymkey_model.AddPrincipalKey(ctx.Doer.ID, content, 0); err != nil {
 			ctx.Data["HasPrincipalError"] = true
 			switch {
 			case asymkey_model.IsErrKeyAlreadyExist(err), asymkey_model.IsErrKeyNameAlreadyUsed(err):
@@ -78,12 +78,12 @@ func KeysPost(ctx *context.Context) {
 		ctx.Flash.Success(ctx.Tr("settings.add_principal_success", form.Content))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
 	case "gpg":
-		token := asymkey_model.VerificationToken(ctx.User, 1)
-		lastToken := asymkey_model.VerificationToken(ctx.User, 0)
+		token := asymkey_model.VerificationToken(ctx.Doer, 1)
+		lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
 
-		keys, err := asymkey_model.AddGPGKey(ctx.User.ID, form.Content, token, form.Signature)
+		keys, err := asymkey_model.AddGPGKey(ctx.Doer.ID, form.Content, token, form.Signature)
 		if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
-			keys, err = asymkey_model.AddGPGKey(ctx.User.ID, form.Content, lastToken, form.Signature)
+			keys, err = asymkey_model.AddGPGKey(ctx.Doer.ID, form.Content, lastToken, form.Signature)
 		}
 		if err != nil {
 			ctx.Data["HasGPGError"] = true
@@ -125,12 +125,12 @@ func KeysPost(ctx *context.Context) {
 		ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", keyIDs))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
 	case "verify_gpg":
-		token := asymkey_model.VerificationToken(ctx.User, 1)
-		lastToken := asymkey_model.VerificationToken(ctx.User, 0)
+		token := asymkey_model.VerificationToken(ctx.Doer, 1)
+		lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
 
-		keyID, err := asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, token, form.Signature)
+		keyID, err := asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, token, form.Signature)
 		if err != nil && asymkey_model.IsErrGPGInvalidTokenSignature(err) {
-			keyID, err = asymkey_model.VerifyGPGKey(ctx.User.ID, form.KeyID, lastToken, form.Signature)
+			keyID, err = asymkey_model.VerifyGPGKey(ctx.Doer.ID, form.KeyID, lastToken, form.Signature)
 		}
 		if err != nil {
 			ctx.Data["HasGPGVerifyError"] = true
@@ -161,7 +161,7 @@ func KeysPost(ctx *context.Context) {
 			return
 		}
 
-		if _, err = asymkey_model.AddPublicKey(ctx.User.ID, form.Title, content, 0); err != nil {
+		if _, err = asymkey_model.AddPublicKey(ctx.Doer.ID, form.Title, content, 0); err != nil {
 			ctx.Data["HasSSHError"] = true
 			switch {
 			case asymkey_model.IsErrKeyAlreadyExist(err):
@@ -185,12 +185,12 @@ func KeysPost(ctx *context.Context) {
 		ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
 	case "verify_ssh":
-		token := asymkey_model.VerificationToken(ctx.User, 1)
-		lastToken := asymkey_model.VerificationToken(ctx.User, 0)
+		token := asymkey_model.VerificationToken(ctx.Doer, 1)
+		lastToken := asymkey_model.VerificationToken(ctx.Doer, 0)
 
-		fingerprint, err := asymkey_model.VerifySSHKey(ctx.User.ID, form.Fingerprint, token, form.Signature)
+		fingerprint, err := asymkey_model.VerifySSHKey(ctx.Doer.ID, form.Fingerprint, token, form.Signature)
 		if err != nil && asymkey_model.IsErrSSHInvalidTokenSignature(err) {
-			fingerprint, err = asymkey_model.VerifySSHKey(ctx.User.ID, form.Fingerprint, lastToken, form.Signature)
+			fingerprint, err = asymkey_model.VerifySSHKey(ctx.Doer.ID, form.Fingerprint, lastToken, form.Signature)
 		}
 		if err != nil {
 			ctx.Data["HasSSHVerifyError"] = true
@@ -217,7 +217,7 @@ func KeysPost(ctx *context.Context) {
 func DeleteKey(ctx *context.Context) {
 	switch ctx.FormString("type") {
 	case "gpg":
-		if err := asymkey_model.DeleteGPGKey(ctx.User, ctx.FormInt64("id")); err != nil {
+		if err := asymkey_model.DeleteGPGKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
 			ctx.Flash.Error("DeleteGPGKey: " + err.Error())
 		} else {
 			ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
@@ -234,13 +234,13 @@ func DeleteKey(ctx *context.Context) {
 			ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
 			return
 		}
-		if err := asymkey_service.DeletePublicKey(ctx.User, keyID); err != nil {
+		if err := asymkey_service.DeletePublicKey(ctx.Doer, keyID); err != nil {
 			ctx.Flash.Error("DeletePublicKey: " + err.Error())
 		} else {
 			ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
 		}
 	case "principal":
-		if err := asymkey_service.DeletePublicKey(ctx.User, ctx.FormInt64("id")); err != nil {
+		if err := asymkey_service.DeletePublicKey(ctx.Doer, ctx.FormInt64("id")); err != nil {
 			ctx.Flash.Error("DeletePublicKey: " + err.Error())
 		} else {
 			ctx.Flash.Success(ctx.Tr("settings.ssh_principal_deletion_success"))
@@ -255,7 +255,7 @@ func DeleteKey(ctx *context.Context) {
 }
 
 func loadKeysData(ctx *context.Context) {
-	keys, err := asymkey_model.ListPublicKeys(ctx.User.ID, db.ListOptions{})
+	keys, err := asymkey_model.ListPublicKeys(ctx.Doer.ID, db.ListOptions{})
 	if err != nil {
 		ctx.ServerError("ListPublicKeys", err)
 		return
@@ -269,18 +269,18 @@ func loadKeysData(ctx *context.Context) {
 	}
 	ctx.Data["ExternalKeys"] = externalKeys
 
-	gpgkeys, err := asymkey_model.ListGPGKeys(db.DefaultContext, ctx.User.ID, db.ListOptions{})
+	gpgkeys, err := asymkey_model.ListGPGKeys(db.DefaultContext, ctx.Doer.ID, db.ListOptions{})
 	if err != nil {
 		ctx.ServerError("ListGPGKeys", err)
 		return
 	}
 	ctx.Data["GPGKeys"] = gpgkeys
-	tokenToSign := asymkey_model.VerificationToken(ctx.User, 1)
+	tokenToSign := asymkey_model.VerificationToken(ctx.Doer, 1)
 
 	// generate a new aes cipher using the csrfToken
 	ctx.Data["TokenToSign"] = tokenToSign
 
-	principals, err := asymkey_model.ListPrincipalKeys(ctx.User.ID, db.ListOptions{})
+	principals, err := asymkey_model.ListPrincipalKeys(ctx.Doer.ID, db.ListOptions{})
 	if err != nil {
 		ctx.ServerError("ListPrincipalKeys", err)
 		return
diff --git a/routers/web/user/setting/oauth2.go b/routers/web/user/setting/oauth2.go
index 65d0924da..76c50852a 100644
--- a/routers/web/user/setting/oauth2.go
+++ b/routers/web/user/setting/oauth2.go
@@ -37,7 +37,7 @@ func OAuthApplicationsPost(ctx *context.Context) {
 	app, err := auth.CreateOAuth2Application(auth.CreateOAuth2ApplicationOptions{
 		Name:         form.Name,
 		RedirectURIs: []string{form.RedirectURI},
-		UserID:       ctx.User.ID,
+		UserID:       ctx.Doer.ID,
 	})
 	if err != nil {
 		ctx.ServerError("CreateOAuth2Application", err)
@@ -71,7 +71,7 @@ func OAuthApplicationsEdit(ctx *context.Context) {
 		ID:           ctx.ParamsInt64("id"),
 		Name:         form.Name,
 		RedirectURIs: []string{form.RedirectURI},
-		UserID:       ctx.User.ID,
+		UserID:       ctx.Doer.ID,
 	}); err != nil {
 		ctx.ServerError("UpdateOAuth2Application", err)
 		return
@@ -94,7 +94,7 @@ func OAuthApplicationsRegenerateSecret(ctx *context.Context) {
 		ctx.ServerError("GetOAuth2ApplicationByID", err)
 		return
 	}
-	if app.UID != ctx.User.ID {
+	if app.UID != ctx.Doer.ID {
 		ctx.NotFound("Application not found", nil)
 		return
 	}
@@ -119,7 +119,7 @@ func OAuth2ApplicationShow(ctx *context.Context) {
 		ctx.ServerError("GetOAuth2ApplicationByID", err)
 		return
 	}
-	if app.UID != ctx.User.ID {
+	if app.UID != ctx.Doer.ID {
 		ctx.NotFound("Application not found", nil)
 		return
 	}
@@ -129,11 +129,11 @@ func OAuth2ApplicationShow(ctx *context.Context) {
 
 // DeleteOAuth2Application deletes the given oauth2 application
 func DeleteOAuth2Application(ctx *context.Context) {
-	if err := auth.DeleteOAuth2Application(ctx.FormInt64("id"), ctx.User.ID); err != nil {
+	if err := auth.DeleteOAuth2Application(ctx.FormInt64("id"), ctx.Doer.ID); err != nil {
 		ctx.ServerError("DeleteOAuth2Application", err)
 		return
 	}
-	log.Trace("OAuth2 Application deleted: %s", ctx.User.Name)
+	log.Trace("OAuth2 Application deleted: %s", ctx.Doer.Name)
 
 	ctx.Flash.Success(ctx.Tr("settings.remove_oauth2_application_success"))
 	ctx.JSON(http.StatusOK, map[string]interface{}{
@@ -143,11 +143,11 @@ func DeleteOAuth2Application(ctx *context.Context) {
 
 // RevokeOAuth2Grant revokes the grant with the given id
 func RevokeOAuth2Grant(ctx *context.Context) {
-	if ctx.User.ID == 0 || ctx.FormInt64("id") == 0 {
+	if ctx.Doer.ID == 0 || ctx.FormInt64("id") == 0 {
 		ctx.ServerError("RevokeOAuth2Grant", fmt.Errorf("user id or grant id is zero"))
 		return
 	}
-	if err := auth.RevokeOAuth2Grant(ctx.FormInt64("id"), ctx.User.ID); err != nil {
+	if err := auth.RevokeOAuth2Grant(ctx.FormInt64("id"), ctx.Doer.ID); err != nil {
 		ctx.ServerError("RevokeOAuth2Grant", err)
 		return
 	}
diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go
index e77e02348..72cbf33e5 100644
--- a/routers/web/user/setting/profile.go
+++ b/routers/web/user/setting/profile.go
@@ -106,24 +106,24 @@ func ProfilePost(ctx *context.Context) {
 		return
 	}
 
-	if len(form.Name) != 0 && ctx.User.Name != form.Name {
-		log.Debug("Changing name for %s to %s", ctx.User.Name, form.Name)
-		if err := HandleUsernameChange(ctx, ctx.User, form.Name); err != nil {
+	if len(form.Name) != 0 && ctx.Doer.Name != form.Name {
+		log.Debug("Changing name for %s to %s", ctx.Doer.Name, form.Name)
+		if err := HandleUsernameChange(ctx, ctx.Doer, form.Name); err != nil {
 			ctx.Redirect(setting.AppSubURL + "/user/settings")
 			return
 		}
-		ctx.User.Name = form.Name
-		ctx.User.LowerName = strings.ToLower(form.Name)
+		ctx.Doer.Name = form.Name
+		ctx.Doer.LowerName = strings.ToLower(form.Name)
 	}
 
-	ctx.User.FullName = form.FullName
-	ctx.User.KeepEmailPrivate = form.KeepEmailPrivate
-	ctx.User.Website = form.Website
-	ctx.User.Location = form.Location
-	ctx.User.Description = form.Description
-	ctx.User.KeepActivityPrivate = form.KeepActivityPrivate
-	ctx.User.Visibility = form.Visibility
-	if err := user_model.UpdateUserSetting(ctx.User); err != nil {
+	ctx.Doer.FullName = form.FullName
+	ctx.Doer.KeepEmailPrivate = form.KeepEmailPrivate
+	ctx.Doer.Website = form.Website
+	ctx.Doer.Location = form.Location
+	ctx.Doer.Description = form.Description
+	ctx.Doer.KeepActivityPrivate = form.KeepActivityPrivate
+	ctx.Doer.Visibility = form.Visibility
+	if err := user_model.UpdateUserSetting(ctx.Doer); err != nil {
 		if _, ok := err.(user_model.ErrEmailAlreadyUsed); ok {
 			ctx.Flash.Error(ctx.Tr("form.email_been_used"))
 			ctx.Redirect(setting.AppSubURL + "/user/settings")
@@ -134,10 +134,10 @@ func ProfilePost(ctx *context.Context) {
 	}
 
 	// Update the language to the one we just set
-	middleware.SetLocaleCookie(ctx.Resp, ctx.User.Language, 0)
+	middleware.SetLocaleCookie(ctx.Resp, ctx.Doer.Language, 0)
 
-	log.Trace("User settings updated: %s", ctx.User.Name)
-	ctx.Flash.Success(i18n.Tr(ctx.User.Language, "settings.update_profile_success"))
+	log.Trace("User settings updated: %s", ctx.Doer.Name)
+	ctx.Flash.Success(i18n.Tr(ctx.Doer.Language, "settings.update_profile_success"))
 	ctx.Redirect(setting.AppSubURL + "/user/settings")
 }
 
@@ -195,7 +195,7 @@ func UpdateAvatarSetting(ctx *context.Context, form *forms.AvatarForm, ctxUser *
 // AvatarPost response for change user's avatar request
 func AvatarPost(ctx *context.Context) {
 	form := web.GetForm(ctx).(*forms.AvatarForm)
-	if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil {
+	if err := UpdateAvatarSetting(ctx, form, ctx.Doer); err != nil {
 		ctx.Flash.Error(err.Error())
 	} else {
 		ctx.Flash.Success(ctx.Tr("settings.update_avatar_success"))
@@ -206,7 +206,7 @@ func AvatarPost(ctx *context.Context) {
 
 // DeleteAvatar render delete avatar page
 func DeleteAvatar(ctx *context.Context) {
-	if err := user_service.DeleteAvatar(ctx.User); err != nil {
+	if err := user_service.DeleteAvatar(ctx.Doer); err != nil {
 		ctx.Flash.Error(err.Error())
 	}
 
@@ -223,7 +223,7 @@ func Organization(ctx *context.Context) {
 			PageSize: setting.UI.Admin.UserPagingNum,
 			Page:     ctx.FormInt("page"),
 		},
-		UserID:         ctx.User.ID,
+		UserID:         ctx.Doer.ID,
 		IncludePrivate: ctx.IsSigned,
 	}
 
@@ -268,7 +268,7 @@ func Repos(ctx *context.Context) {
 
 	adoptOrDelete := ctx.IsUserSiteAdmin() || (setting.Repository.AllowAdoptionOfUnadoptedRepositories && setting.Repository.AllowDeleteOfUnadoptedRepositories)
 
-	ctxUser := ctx.User
+	ctxUser := ctx.Doer
 	count := 0
 
 	if adoptOrDelete {
@@ -360,7 +360,7 @@ func Appearance(ctx *context.Context) {
 	ctx.Data["PageIsSettingsAppearance"] = true
 
 	var hiddenCommentTypes *big.Int
-	val, err := user_model.GetUserSetting(ctx.User.ID, user_model.SettingsKeyHiddenCommentTypes)
+	val, err := user_model.GetUserSetting(ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes)
 	if err != nil {
 		ctx.ServerError("GetUserSetting", err)
 		return
@@ -391,13 +391,13 @@ func UpdateUIThemePost(ctx *context.Context) {
 		return
 	}
 
-	if err := user_model.UpdateUserTheme(ctx.User, form.Theme); err != nil {
+	if err := user_model.UpdateUserTheme(ctx.Doer, form.Theme); err != nil {
 		ctx.Flash.Error(ctx.Tr("settings.theme_update_error"))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
 		return
 	}
 
-	log.Trace("Update user theme: %s", ctx.User.Name)
+	log.Trace("Update user theme: %s", ctx.Doer.Name)
 	ctx.Flash.Success(ctx.Tr("settings.theme_update_success"))
 	ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
 }
@@ -414,31 +414,31 @@ func UpdateUserLang(ctx *context.Context) {
 			ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
 			return
 		}
-		ctx.User.Language = form.Language
+		ctx.Doer.Language = form.Language
 	}
 
-	if err := user_model.UpdateUserSetting(ctx.User); err != nil {
+	if err := user_model.UpdateUserSetting(ctx.Doer); err != nil {
 		ctx.ServerError("UpdateUserSetting", err)
 		return
 	}
 
 	// Update the language to the one we just set
-	middleware.SetLocaleCookie(ctx.Resp, ctx.User.Language, 0)
+	middleware.SetLocaleCookie(ctx.Resp, ctx.Doer.Language, 0)
 
-	log.Trace("User settings updated: %s", ctx.User.Name)
-	ctx.Flash.Success(i18n.Tr(ctx.User.Language, "settings.update_language_success"))
+	log.Trace("User settings updated: %s", ctx.Doer.Name)
+	ctx.Flash.Success(i18n.Tr(ctx.Doer.Language, "settings.update_language_success"))
 	ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
 }
 
 // UpdateUserHiddenComments update a user's shown comment types
 func UpdateUserHiddenComments(ctx *context.Context) {
-	err := user_model.SetUserSetting(ctx.User.ID, user_model.SettingsKeyHiddenCommentTypes, forms.UserHiddenCommentTypesFromRequest(ctx).String())
+	err := user_model.SetUserSetting(ctx.Doer.ID, user_model.SettingsKeyHiddenCommentTypes, forms.UserHiddenCommentTypesFromRequest(ctx).String())
 	if err != nil {
 		ctx.ServerError("SetUserSetting", err)
 		return
 	}
 
-	log.Trace("User settings updated: %s", ctx.User.Name)
+	log.Trace("User settings updated: %s", ctx.Doer.Name)
 	ctx.Flash.Success(ctx.Tr("settings.saved_successfully"))
 	ctx.Redirect(setting.AppSubURL + "/user/settings/appearance")
 }
diff --git a/routers/web/user/setting/security/2fa.go b/routers/web/user/setting/security/2fa.go
index 98e1f9b08..5fd81bae4 100644
--- a/routers/web/user/setting/security/2fa.go
+++ b/routers/web/user/setting/security/2fa.go
@@ -29,7 +29,7 @@ func RegenerateScratchTwoFactor(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsSecurity"] = true
 
-	t, err := auth.GetTwoFactorByUID(ctx.User.ID)
+	t, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
 	if err != nil {
 		if auth.IsErrTwoFactorNotEnrolled(err) {
 			ctx.Flash.Error(ctx.Tr("settings.twofa_not_enrolled"))
@@ -59,7 +59,7 @@ func DisableTwoFactor(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsSecurity"] = true
 
-	t, err := auth.GetTwoFactorByUID(ctx.User.ID)
+	t, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
 	if err != nil {
 		if auth.IsErrTwoFactorNotEnrolled(err) {
 			ctx.Flash.Error(ctx.Tr("settings.twofa_not_enrolled"))
@@ -69,7 +69,7 @@ func DisableTwoFactor(ctx *context.Context) {
 		return
 	}
 
-	if err = auth.DeleteTwoFactorByID(t.ID, ctx.User.ID); err != nil {
+	if err = auth.DeleteTwoFactorByID(t.ID, ctx.Doer.ID); err != nil {
 		if auth.IsErrTwoFactorNotEnrolled(err) {
 			// There is a potential DB race here - we must have been disabled by another request in the intervening period
 			ctx.Flash.Success(ctx.Tr("settings.twofa_disabled"))
@@ -100,7 +100,7 @@ func twofaGenerateSecretAndQr(ctx *context.Context) bool {
 		otpKey, err = totp.Generate(totp.GenerateOpts{
 			SecretSize:  40,
 			Issuer:      issuer,
-			AccountName: ctx.User.Name,
+			AccountName: ctx.Doer.Name,
 		})
 		if err != nil {
 			ctx.ServerError("SettingsTwoFactor: totpGenerate Failed", err)
@@ -146,10 +146,10 @@ func EnrollTwoFactor(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsSecurity"] = true
 
-	t, err := auth.GetTwoFactorByUID(ctx.User.ID)
+	t, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
 	if t != nil {
 		// already enrolled - we should redirect back!
-		log.Warn("Trying to re-enroll %-v in twofa when already enrolled", ctx.User)
+		log.Warn("Trying to re-enroll %-v in twofa when already enrolled", ctx.Doer)
 		ctx.Flash.Error(ctx.Tr("settings.twofa_is_enrolled"))
 		ctx.Redirect(setting.AppSubURL + "/user/settings/security")
 		return
@@ -172,7 +172,7 @@ func EnrollTwoFactorPost(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("settings")
 	ctx.Data["PageIsSettingsSecurity"] = true
 
-	t, err := auth.GetTwoFactorByUID(ctx.User.ID)
+	t, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
 	if t != nil {
 		// already enrolled
 		ctx.Flash.Error(ctx.Tr("settings.twofa_is_enrolled"))
@@ -210,7 +210,7 @@ func EnrollTwoFactorPost(ctx *context.Context) {
 	}
 
 	t = &auth.TwoFactor{
-		UID: ctx.User.ID,
+		UID: ctx.Doer.ID,
 	}
 	err = t.SetSecret(secret)
 	if err != nil {
diff --git a/routers/web/user/setting/security/openid.go b/routers/web/user/setting/security/openid.go
index 1a15a2414..2ecc9b053 100644
--- a/routers/web/user/setting/security/openid.go
+++ b/routers/web/user/setting/security/openid.go
@@ -45,7 +45,7 @@ func OpenIDPost(ctx *context.Context) {
 	form.Openid = id
 	log.Trace("Normalized id: " + id)
 
-	oids, err := user_model.GetUserOpenIDs(ctx.User.ID)
+	oids, err := user_model.GetUserOpenIDs(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetUserOpenIDs", err)
 		return
@@ -89,7 +89,7 @@ func settingsOpenIDVerify(ctx *context.Context) {
 
 	log.Trace("Verified ID: " + id)
 
-	oid := &user_model.UserOpenID{UID: ctx.User.ID, URI: id}
+	oid := &user_model.UserOpenID{UID: ctx.Doer.ID, URI: id}
 	if err = user_model.AddUserOpenID(oid); err != nil {
 		if user_model.IsErrOpenIDAlreadyUsed(err) {
 			ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &forms.AddOpenIDForm{Openid: id})
@@ -98,7 +98,7 @@ func settingsOpenIDVerify(ctx *context.Context) {
 		ctx.ServerError("AddUserOpenID", err)
 		return
 	}
-	log.Trace("Associated OpenID %s to user %s", id, ctx.User.Name)
+	log.Trace("Associated OpenID %s to user %s", id, ctx.Doer.Name)
 	ctx.Flash.Success(ctx.Tr("settings.add_openid_success"))
 
 	ctx.Redirect(setting.AppSubURL + "/user/settings/security")
@@ -106,11 +106,11 @@ func settingsOpenIDVerify(ctx *context.Context) {
 
 // DeleteOpenID response for delete user's openid
 func DeleteOpenID(ctx *context.Context) {
-	if err := user_model.DeleteUserOpenID(&user_model.UserOpenID{ID: ctx.FormInt64("id"), UID: ctx.User.ID}); err != nil {
+	if err := user_model.DeleteUserOpenID(&user_model.UserOpenID{ID: ctx.FormInt64("id"), UID: ctx.Doer.ID}); err != nil {
 		ctx.ServerError("DeleteUserOpenID", err)
 		return
 	}
-	log.Trace("OpenID address deleted: %s", ctx.User.Name)
+	log.Trace("OpenID address deleted: %s", ctx.Doer.Name)
 
 	ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success"))
 	ctx.JSON(http.StatusOK, map[string]interface{}{
diff --git a/routers/web/user/setting/security/security.go b/routers/web/user/setting/security/security.go
index 67bbbf8b3..a87012c48 100644
--- a/routers/web/user/setting/security/security.go
+++ b/routers/web/user/setting/security/security.go
@@ -43,7 +43,7 @@ func DeleteAccountLink(ctx *context.Context) {
 	if id <= 0 {
 		ctx.Flash.Error("Account link id is not given")
 	} else {
-		if _, err := user_model.RemoveAccountLink(ctx.User, id); err != nil {
+		if _, err := user_model.RemoveAccountLink(ctx.Doer, id); err != nil {
 			ctx.Flash.Error("RemoveAccountLink: " + err.Error())
 		} else {
 			ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
@@ -56,28 +56,28 @@ func DeleteAccountLink(ctx *context.Context) {
 }
 
 func loadSecurityData(ctx *context.Context) {
-	enrolled, err := auth.HasTwoFactorByUID(ctx.User.ID)
+	enrolled, err := auth.HasTwoFactorByUID(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("SettingsTwoFactor", err)
 		return
 	}
 	ctx.Data["TOTPEnrolled"] = enrolled
 
-	credentials, err := auth.GetWebAuthnCredentialsByUID(ctx.User.ID)
+	credentials, err := auth.GetWebAuthnCredentialsByUID(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetWebAuthnCredentialsByUID", err)
 		return
 	}
 	ctx.Data["WebAuthnCredentials"] = credentials
 
-	tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID})
+	tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.Doer.ID})
 	if err != nil {
 		ctx.ServerError("ListAccessTokens", err)
 		return
 	}
 	ctx.Data["Tokens"] = tokens
 
-	accountLinks, err := user_model.ListAccountLinks(ctx.User)
+	accountLinks, err := user_model.ListAccountLinks(ctx.Doer)
 	if err != nil {
 		ctx.ServerError("ListAccountLinks", err)
 		return
@@ -109,7 +109,7 @@ func loadSecurityData(ctx *context.Context) {
 	}
 	ctx.Data["AccountLinks"] = sources
 
-	openid, err := user_model.GetUserOpenIDs(ctx.User.ID)
+	openid, err := user_model.GetUserOpenIDs(ctx.Doer.ID)
 	if err != nil {
 		ctx.ServerError("GetUserOpenIDs", err)
 		return
diff --git a/routers/web/user/setting/security/webauthn.go b/routers/web/user/setting/security/webauthn.go
index 7e2fc7283..bb2d1f733 100644
--- a/routers/web/user/setting/security/webauthn.go
+++ b/routers/web/user/setting/security/webauthn.go
@@ -28,7 +28,7 @@ func WebAuthnRegister(ctx *context.Context) {
 		return
 	}
 
-	cred, err := auth.GetWebAuthnCredentialByName(ctx.User.ID, form.Name)
+	cred, err := auth.GetWebAuthnCredentialByName(ctx.Doer.ID, form.Name)
 	if err != nil && !auth.IsErrWebAuthnCredentialNotExist(err) {
 		ctx.ServerError("GetWebAuthnCredentialsByUID", err)
 		return
@@ -44,7 +44,7 @@ func WebAuthnRegister(ctx *context.Context) {
 		return
 	}
 
-	credentialOptions, sessionData, err := wa.WebAuthn.BeginRegistration((*wa.User)(ctx.User))
+	credentialOptions, sessionData, err := wa.WebAuthn.BeginRegistration((*wa.User)(ctx.Doer))
 	if err != nil {
 		ctx.ServerError("Unable to BeginRegistration", err)
 		return
@@ -78,7 +78,7 @@ func WebauthnRegisterPost(ctx *context.Context) {
 	}()
 
 	// Verify that the challenge succeeded
-	cred, err := wa.WebAuthn.FinishRegistration((*wa.User)(ctx.User), *sessionData, ctx.Req)
+	cred, err := wa.WebAuthn.FinishRegistration((*wa.User)(ctx.Doer), *sessionData, ctx.Req)
 	if err != nil {
 		if pErr, ok := err.(*protocol.Error); ok {
 			log.Error("Unable to finish registration due to error: %v\nDevInfo: %s", pErr, pErr.DevInfo)
@@ -87,7 +87,7 @@ func WebauthnRegisterPost(ctx *context.Context) {
 		return
 	}
 
-	dbCred, err := auth.GetWebAuthnCredentialByName(ctx.User.ID, name)
+	dbCred, err := auth.GetWebAuthnCredentialByName(ctx.Doer.ID, name)
 	if err != nil && !auth.IsErrWebAuthnCredentialNotExist(err) {
 		ctx.ServerError("GetWebAuthnCredentialsByUID", err)
 		return
@@ -98,7 +98,7 @@ func WebauthnRegisterPost(ctx *context.Context) {
 	}
 
 	// Create the credential
-	_, err = auth.CreateCredential(ctx.User.ID, name, cred)
+	_, err = auth.CreateCredential(ctx.Doer.ID, name, cred)
 	if err != nil {
 		ctx.ServerError("CreateCredential", err)
 		return
@@ -111,7 +111,7 @@ func WebauthnRegisterPost(ctx *context.Context) {
 // WebauthnDelete deletes an security key by id
 func WebauthnDelete(ctx *context.Context) {
 	form := web.GetForm(ctx).(*forms.WebauthnDeleteForm)
-	if _, err := auth.DeleteCredential(form.ID, ctx.User.ID); err != nil {
+	if _, err := auth.DeleteCredential(form.ID, ctx.Doer.ID); err != nil {
 		ctx.ServerError("GetWebAuthnCredentialByID", err)
 		return
 	}
diff --git a/routers/web/user/task.go b/routers/web/user/task.go
index 4dbd1b853..fd561cdd4 100644
--- a/routers/web/user/task.go
+++ b/routers/web/user/task.go
@@ -15,7 +15,7 @@ import (
 
 // TaskStatus returns task's status
 func TaskStatus(ctx *context.Context) {
-	task, opts, err := models.GetMigratingTaskByID(ctx.ParamsInt64("task"), ctx.User.ID)
+	task, opts, err := models.GetMigratingTaskByID(ctx.ParamsInt64("task"), ctx.Doer.ID)
 	if err != nil {
 		if models.IsErrTaskDoesNotExist(err) {
 			ctx.JSON(http.StatusNotFound, map[string]interface{}{
diff --git a/services/lfs/locks.go b/services/lfs/locks.go
index 3839119b2..a96e931fd 100644
--- a/services/lfs/locks.go
+++ b/services/lfs/locks.go
@@ -170,7 +170,7 @@ func PostLockHandler(ctx *context.Context) {
 
 	lock, err := models.CreateLFSLock(repository, &models.LFSLock{
 		Path:    req.Path,
-		OwnerID: ctx.User.ID,
+		OwnerID: ctx.Doer.ID,
 	})
 	if err != nil {
 		if models.IsErrLFSLockAlreadyExist(err) {
@@ -187,7 +187,7 @@ func PostLockHandler(ctx *context.Context) {
 			})
 			return
 		}
-		log.Error("Unable to CreateLFSLock in repository %-v at %s for user %-v: Error: %v", repository, req.Path, ctx.User, err)
+		log.Error("Unable to CreateLFSLock in repository %-v at %s for user %-v: Error: %v", repository, req.Path, ctx.Doer, err)
 		ctx.JSON(http.StatusInternalServerError, api.LFSLockError{
 			Message: "internal server error : Internal Server Error",
 		})
@@ -249,7 +249,7 @@ func VerifyLockHandler(ctx *context.Context) {
 	lockOursListAPI := make([]*api.LFSLock, 0, len(lockList))
 	lockTheirsListAPI := make([]*api.LFSLock, 0, len(lockList))
 	for _, l := range lockList {
-		if l.OwnerID == ctx.User.ID {
+		if l.OwnerID == ctx.Doer.ID {
 			lockOursListAPI = append(lockOursListAPI, convert.ToLFSLock(l))
 		} else {
 			lockTheirsListAPI = append(lockTheirsListAPI, convert.ToLFSLock(l))
@@ -301,7 +301,7 @@ func UnLockHandler(ctx *context.Context) {
 		return
 	}
 
-	lock, err := models.DeleteLFSLockByID(ctx.ParamsInt64("lid"), repository, ctx.User, req.Force)
+	lock, err := models.DeleteLFSLockByID(ctx.ParamsInt64("lid"), repository, ctx.Doer, req.Force)
 	if err != nil {
 		if models.IsErrLFSUnauthorizedAction(err) {
 			ctx.Resp.Header().Set("WWW-Authenticate", "Basic realm=gitea-lfs")
@@ -310,7 +310,7 @@ func UnLockHandler(ctx *context.Context) {
 			})
 			return
 		}
-		log.Error("Unable to DeleteLFSLockByID[%d] by user %-v with force %t: Error: %v", ctx.ParamsInt64("lid"), ctx.User, req.Force, err)
+		log.Error("Unable to DeleteLFSLockByID[%d] by user %-v with force %t: Error: %v", ctx.ParamsInt64("lid"), ctx.Doer, req.Force, err)
 		ctx.JSON(http.StatusInternalServerError, api.LFSLockError{
 			Message: "unable to delete lock : Internal Server Error",
 		})
diff --git a/services/lfs/server.go b/services/lfs/server.go
index 7c3f88e57..633aa0a69 100644
--- a/services/lfs/server.go
+++ b/services/lfs/server.go
@@ -222,7 +222,7 @@ func BatchHandler(ctx *context.Context) {
 			}
 
 			if exists && meta == nil {
-				accessible, err := models.LFSObjectAccessible(ctx.User, p.Oid)
+				accessible, err := models.LFSObjectAccessible(ctx.Doer, p.Oid)
 				if err != nil {
 					log.Error("Unable to check if LFS MetaObject [%s] is accessible. Error: %v", p.Oid, err)
 					writeStatus(ctx, http.StatusInternalServerError)
@@ -296,7 +296,7 @@ func UploadHandler(ctx *context.Context) {
 
 	uploadOrVerify := func() error {
 		if exists {
-			accessible, err := models.LFSObjectAccessible(ctx.User, p.Oid)
+			accessible, err := models.LFSObjectAccessible(ctx.Doer, p.Oid)
 			if err != nil {
 				log.Error("Unable to check if LFS MetaObject [%s] is accessible. Error: %v", p.Oid, err)
 				return err
@@ -488,9 +488,9 @@ func authenticate(ctx *context.Context, repository *repo_model.Repository, autho
 	}
 
 	// ctx.IsSigned is unnecessary here, this will be checked in perm.CanAccess
-	perm, err := models.GetUserRepoPermission(repository, ctx.User)
+	perm, err := models.GetUserRepoPermission(repository, ctx.Doer)
 	if err != nil {
-		log.Error("Unable to GetUserRepoPermission for user %-v in repo %-v Error: %v", ctx.User, repository)
+		log.Error("Unable to GetUserRepoPermission for user %-v in repo %-v Error: %v", ctx.Doer, repository)
 		return false
 	}
 
@@ -505,7 +505,7 @@ func authenticate(ctx *context.Context, repository *repo_model.Repository, autho
 		log.Warn("Authentication failure for provided token with Error: %v", err)
 		return false
 	}
-	ctx.User = user
+	ctx.Doer = user
 	return true
 }