mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	Refactor web route handler (#33488)
This commit is contained in:
		| @@ -34,7 +34,7 @@ func Home(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx.SetPathParam("org", uname) | 	ctx.SetPathParam("org", uname) | ||||||
| 	context.HandleOrgAssignment(ctx) | 	context.OrgAssignment(context.OrgAssignmentOptions{})(ctx) | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -304,31 +304,6 @@ func CreatePost(ctx *context.Context) { | |||||||
| 	handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form) | 	handleCreateError(ctx, ctxUser, err, "CreatePost", tplCreate, &form) | ||||||
| } | } | ||||||
|  |  | ||||||
| const ( |  | ||||||
| 	tplWatchUnwatch templates.TplName = "repo/watch_unwatch" |  | ||||||
| 	tplStarUnstar   templates.TplName = "repo/star_unstar" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func acceptTransfer(ctx *context.Context) { |  | ||||||
| 	err := repo_service.AcceptTransferOwnership(ctx, ctx.Repo.Repository, ctx.Doer) |  | ||||||
| 	if err == nil { |  | ||||||
| 		ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success")) |  | ||||||
| 		ctx.Redirect(ctx.Repo.Repository.Link()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	handleActionError(ctx, err) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func rejectTransfer(ctx *context.Context) { |  | ||||||
| 	err := repo_service.RejectRepositoryTransfer(ctx, ctx.Repo.Repository, ctx.Doer) |  | ||||||
| 	if err == nil { |  | ||||||
| 		ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected")) |  | ||||||
| 		ctx.Redirect(ctx.Repo.Repository.Link()) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	handleActionError(ctx, err) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func handleActionError(ctx *context.Context, err error) { | func handleActionError(ctx *context.Context, err error) { | ||||||
| 	if errors.Is(err, user_model.ErrBlockedUser) { | 	if errors.Is(err, user_model.ErrBlockedUser) { | ||||||
| 		ctx.Flash.Error(ctx.Tr("repo.action.blocked_user")) | 		ctx.Flash.Error(ctx.Tr("repo.action.blocked_user")) | ||||||
| @@ -339,72 +314,6 @@ func handleActionError(ctx *context.Context, err error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Action response for actions to a repository |  | ||||||
| func Action(ctx *context.Context) { |  | ||||||
| 	var err error |  | ||||||
| 	switch ctx.PathParam("action") { |  | ||||||
| 	case "watch": |  | ||||||
| 		err = repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, true) |  | ||||||
| 	case "unwatch": |  | ||||||
| 		err = repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, false) |  | ||||||
| 	case "star": |  | ||||||
| 		err = repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, true) |  | ||||||
| 	case "unstar": |  | ||||||
| 		err = repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, false) |  | ||||||
| 	case "accept_transfer": |  | ||||||
| 		acceptTransfer(ctx) |  | ||||||
| 		return |  | ||||||
| 	case "reject_transfer": |  | ||||||
| 		rejectTransfer(ctx) |  | ||||||
| 		return |  | ||||||
| 	case "desc": // FIXME: this is not used |  | ||||||
| 		if !ctx.Repo.IsOwner() { |  | ||||||
| 			ctx.Error(http.StatusNotFound) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		ctx.Repo.Repository.Description = ctx.FormString("desc") |  | ||||||
| 		ctx.Repo.Repository.Website = ctx.FormString("site") |  | ||||||
| 		err = repo_service.UpdateRepository(ctx, ctx.Repo.Repository, false) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if err != nil { |  | ||||||
| 		handleActionError(ctx, err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch ctx.PathParam("action") { |  | ||||||
| 	case "watch", "unwatch": |  | ||||||
| 		ctx.Data["IsWatchingRepo"] = repo_model.IsWatching(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) |  | ||||||
| 	case "star", "unstar": |  | ||||||
| 		ctx.Data["IsStaringRepo"] = repo_model.IsStaring(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// see the `hx-trigger="refreshUserCards ..."` comments in tmpl |  | ||||||
| 	ctx.RespHeader().Add("hx-trigger", "refreshUserCards") |  | ||||||
|  |  | ||||||
| 	switch ctx.PathParam("action") { |  | ||||||
| 	case "watch", "unwatch", "star", "unstar": |  | ||||||
| 		// we have to reload the repository because NumStars or NumWatching (used in the templates) has just changed |  | ||||||
| 		ctx.Data["Repository"], err = repo_model.GetRepositoryByName(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.Name) |  | ||||||
| 		if err != nil { |  | ||||||
| 			ctx.ServerError(fmt.Sprintf("Action (%s)", ctx.PathParam("action")), err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	switch ctx.PathParam("action") { |  | ||||||
| 	case "watch", "unwatch": |  | ||||||
| 		ctx.HTML(http.StatusOK, tplWatchUnwatch) |  | ||||||
| 		return |  | ||||||
| 	case "star", "unstar": |  | ||||||
| 		ctx.HTML(http.StatusOK, tplStarUnstar) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx.RedirectToCurrentSite(ctx.FormString("redirect_to"), ctx.Repo.RepoLink) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // RedirectDownload return a file based on the following infos: | // RedirectDownload return a file based on the following infos: | ||||||
| func RedirectDownload(ctx *context.Context) { | func RedirectDownload(ctx *context.Context) { | ||||||
| 	var ( | 	var ( | ||||||
|   | |||||||
							
								
								
									
										31
									
								
								routers/web/repo/star.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								routers/web/repo/star.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // Copyright 2025 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package repo | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
|  | 	"code.gitea.io/gitea/modules/templates" | ||||||
|  | 	"code.gitea.io/gitea/services/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const tplStarUnstar templates.TplName = "repo/star_unstar" | ||||||
|  |  | ||||||
|  | func ActionStar(ctx *context.Context) { | ||||||
|  | 	err := repo_model.StarRepo(ctx, ctx.Doer, ctx.Repo.Repository, ctx.PathParam("action") == "star") | ||||||
|  | 	if err != nil { | ||||||
|  | 		handleActionError(ctx, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Data["IsStaringRepo"] = repo_model.IsStaring(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) | ||||||
|  | 	ctx.Data["Repository"], err = repo_model.GetRepositoryByName(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.Name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.ServerError("GetRepositoryByName", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	ctx.RespHeader().Add("hx-trigger", "refreshUserCards") // see the `hx-trigger="refreshUserCards ..."` comments in tmpl | ||||||
|  | 	ctx.HTML(http.StatusOK, tplStarUnstar) | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								routers/web/repo/transfer.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								routers/web/repo/transfer.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | // Copyright 2025 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package repo | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"code.gitea.io/gitea/services/context" | ||||||
|  | 	repo_service "code.gitea.io/gitea/services/repository" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func acceptTransfer(ctx *context.Context) { | ||||||
|  | 	err := repo_service.AcceptTransferOwnership(ctx, ctx.Repo.Repository, ctx.Doer) | ||||||
|  | 	if err == nil { | ||||||
|  | 		ctx.Flash.Success(ctx.Tr("repo.settings.transfer.success")) | ||||||
|  | 		ctx.Redirect(ctx.Repo.Repository.Link()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	handleActionError(ctx, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func rejectTransfer(ctx *context.Context) { | ||||||
|  | 	err := repo_service.RejectRepositoryTransfer(ctx, ctx.Repo.Repository, ctx.Doer) | ||||||
|  | 	if err == nil { | ||||||
|  | 		ctx.Flash.Success(ctx.Tr("repo.settings.transfer.rejected")) | ||||||
|  | 		ctx.Redirect(ctx.Repo.Repository.Link()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	handleActionError(ctx, err) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ActionTransfer(ctx *context.Context) { | ||||||
|  | 	switch ctx.PathParam("action") { | ||||||
|  | 	case "accept_transfer": | ||||||
|  | 		acceptTransfer(ctx) | ||||||
|  | 	case "reject_transfer": | ||||||
|  | 		rejectTransfer(ctx) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								routers/web/repo/watch.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								routers/web/repo/watch.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // Copyright 2025 The Gitea Authors. All rights reserved. | ||||||
|  | // SPDX-License-Identifier: MIT | ||||||
|  |  | ||||||
|  | package repo | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  |  | ||||||
|  | 	repo_model "code.gitea.io/gitea/models/repo" | ||||||
|  | 	"code.gitea.io/gitea/modules/templates" | ||||||
|  | 	"code.gitea.io/gitea/services/context" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const tplWatchUnwatch templates.TplName = "repo/watch_unwatch" | ||||||
|  |  | ||||||
|  | func ActionWatch(ctx *context.Context) { | ||||||
|  | 	err := repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, ctx.PathParam("action") == "watch") | ||||||
|  | 	if err != nil { | ||||||
|  | 		handleActionError(ctx, err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	ctx.Data["IsWatchingRepo"] = repo_model.IsWatching(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) | ||||||
|  | 	ctx.Data["Repository"], err = repo_model.GetRepositoryByName(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.Name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		ctx.ServerError("GetRepositoryByName", err) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	ctx.RespHeader().Add("hx-trigger", "refreshUserCards") // see the `hx-trigger="refreshUserCards ..."` comments in tmpl | ||||||
|  | 	ctx.HTML(http.StatusOK, tplWatchUnwatch) | ||||||
|  | } | ||||||
| @@ -313,8 +313,8 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb | |||||||
| 	ctx.Data["Page"] = pager | 	ctx.Data["Page"] = pager | ||||||
| } | } | ||||||
|  |  | ||||||
| // Action response for follow/unfollow user request | // ActionUserFollow is for follow/unfollow user request | ||||||
| func Action(ctx *context.Context) { | func ActionUserFollow(ctx *context.Context) { | ||||||
| 	var err error | 	var err error | ||||||
| 	switch ctx.FormString("action") { | 	switch ctx.FormString("action") { | ||||||
| 	case "follow": | 	case "follow": | ||||||
| @@ -339,6 +339,6 @@ func Action(ctx *context.Context) { | |||||||
| 		ctx.HTML(http.StatusOK, tplFollowUnfollow) | 		ctx.HTML(http.StatusOK, tplFollowUnfollow) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	log.Error("Failed to apply action %q: unsupport context user type: %s", ctx.FormString("action"), ctx.ContextUser.Type) | 	log.Error("Failed to apply action %q: unsupported context user type: %s", ctx.FormString("action"), ctx.ContextUser.Type) | ||||||
| 	ctx.Error(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action"))) | 	ctx.Error(http.StatusBadRequest, fmt.Sprintf("Action %q failed", ctx.FormString("action"))) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -822,7 +822,7 @@ func registerRoutes(m *web.Router) { | |||||||
| 		m.Methods("GET, OPTIONS", "/attachments/{uuid}", optionsCorsHandler(), repo.GetAttachment) | 		m.Methods("GET, OPTIONS", "/attachments/{uuid}", optionsCorsHandler(), repo.GetAttachment) | ||||||
| 	}, optSignIn) | 	}, optSignIn) | ||||||
|  |  | ||||||
| 	m.Post("/{username}", reqSignIn, context.UserAssignmentWeb(), user.Action) | 	m.Post("/{username}", reqSignIn, context.UserAssignmentWeb(), user.ActionUserFollow) | ||||||
|  |  | ||||||
| 	reqRepoAdmin := context.RequireRepoAdmin() | 	reqRepoAdmin := context.RequireRepoAdmin() | ||||||
| 	reqRepoCodeWriter := context.RequireUnitWriter(unit.TypeCode) | 	reqRepoCodeWriter := context.RequireUnitWriter(unit.TypeCode) | ||||||
| @@ -872,7 +872,7 @@ func registerRoutes(m *web.Router) { | |||||||
| 	m.Group("/org", func() { | 	m.Group("/org", func() { | ||||||
| 		m.Group("/{org}", func() { | 		m.Group("/{org}", func() { | ||||||
| 			m.Get("/members", org.Members) | 			m.Get("/members", org.Members) | ||||||
| 		}, context.OrgAssignment()) | 		}, context.OrgAssignment(context.OrgAssignmentOptions{})) | ||||||
| 	}, optSignIn) | 	}, optSignIn) | ||||||
| 	// end "/org": members | 	// end "/org": members | ||||||
|  |  | ||||||
| @@ -898,19 +898,20 @@ func registerRoutes(m *web.Router) { | |||||||
| 			m.Get("/milestones/{team}", reqMilestonesDashboardPageEnabled, user.Milestones) | 			m.Get("/milestones/{team}", reqMilestonesDashboardPageEnabled, user.Milestones) | ||||||
| 			m.Post("/members/action/{action}", org.MembersAction) | 			m.Post("/members/action/{action}", org.MembersAction) | ||||||
| 			m.Get("/teams", org.Teams) | 			m.Get("/teams", org.Teams) | ||||||
| 		}, context.OrgAssignment(true, false, true)) | 		}, context.OrgAssignment(context.OrgAssignmentOptions{RequireMember: true, RequireTeamMember: true})) | ||||||
|  |  | ||||||
| 		m.Group("/{org}", func() { | 		m.Group("/{org}", func() { | ||||||
| 			m.Get("/teams/{team}", org.TeamMembers) | 			m.Get("/teams/{team}", org.TeamMembers) | ||||||
| 			m.Get("/teams/{team}/repositories", org.TeamRepositories) | 			m.Get("/teams/{team}/repositories", org.TeamRepositories) | ||||||
| 			m.Post("/teams/{team}/action/{action}", org.TeamsAction) | 			m.Post("/teams/{team}/action/{action}", org.TeamsAction) | ||||||
| 			m.Post("/teams/{team}/action/repo/{action}", org.TeamsRepoAction) | 			m.Post("/teams/{team}/action/repo/{action}", org.TeamsRepoAction) | ||||||
| 		}, context.OrgAssignment(true, false, true)) | 		}, context.OrgAssignment(context.OrgAssignmentOptions{RequireMember: true, RequireTeamMember: true})) | ||||||
|  |  | ||||||
| 		// require admin permission | 		// require member/team-admin permission (old logic is: requireMember=true, requireTeamAdmin=true) | ||||||
|  | 		// but it doesn't seem right: requireTeamAdmin does nothing | ||||||
| 		m.Group("/{org}", func() { | 		m.Group("/{org}", func() { | ||||||
| 			m.Get("/teams/-/search", org.SearchTeam) | 			m.Get("/teams/-/search", org.SearchTeam) | ||||||
| 		}, context.OrgAssignment(true, false, false, true)) | 		}, context.OrgAssignment(context.OrgAssignmentOptions{RequireMember: true, RequireTeamAdmin: true})) | ||||||
|  |  | ||||||
| 		// require owner permission | 		// require owner permission | ||||||
| 		m.Group("/{org}", func() { | 		m.Group("/{org}", func() { | ||||||
| @@ -920,7 +921,7 @@ func registerRoutes(m *web.Router) { | |||||||
| 			m.Post("/teams/{team}/edit", web.Bind(forms.CreateTeamForm{}), org.EditTeamPost) | 			m.Post("/teams/{team}/edit", web.Bind(forms.CreateTeamForm{}), org.EditTeamPost) | ||||||
| 			m.Post("/teams/{team}/delete", org.DeleteTeam) | 			m.Post("/teams/{team}/delete", org.DeleteTeam) | ||||||
|  |  | ||||||
| 			m.Get("/worktime", context.OrgAssignment(false, true), org.Worktime) | 			m.Get("/worktime", context.OrgAssignment(context.OrgAssignmentOptions{RequireOwner: true}), org.Worktime) | ||||||
|  |  | ||||||
| 			m.Group("/settings", func() { | 			m.Group("/settings", func() { | ||||||
| 				m.Combo("").Get(org.Settings). | 				m.Combo("").Get(org.Settings). | ||||||
| @@ -989,7 +990,7 @@ func registerRoutes(m *web.Router) { | |||||||
| 					m.Post("", web.Bind(forms.BlockUserForm{}), org.BlockedUsersPost) | 					m.Post("", web.Bind(forms.BlockUserForm{}), org.BlockedUsersPost) | ||||||
| 				}) | 				}) | ||||||
| 			}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true)) | 			}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true)) | ||||||
| 		}, context.OrgAssignment(true, true)) | 		}, context.OrgAssignment(context.OrgAssignmentOptions{RequireOwner: true})) | ||||||
| 	}, reqSignIn) | 	}, reqSignIn) | ||||||
| 	// end "/org": most org routes | 	// end "/org": most org routes | ||||||
|  |  | ||||||
| @@ -1059,7 +1060,7 @@ func registerRoutes(m *web.Router) { | |||||||
| 		m.Group("", func() { | 		m.Group("", func() { | ||||||
| 			m.Get("/code", user.CodeSearch) | 			m.Get("/code", user.CodeSearch) | ||||||
| 		}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false), individualPermsChecker) | 		}, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false), individualPermsChecker) | ||||||
| 	}, optSignIn, context.UserAssignmentWeb(), context.OrgAssignment()) | 	}, optSignIn, context.UserAssignmentWeb(), context.OrgAssignment(context.OrgAssignmentOptions{})) | ||||||
| 	// end "/{username}/-": packages, projects, code | 	// end "/{username}/-": packages, projects, code | ||||||
|  |  | ||||||
| 	m.Group("/{username}/{reponame}/-", func() { | 	m.Group("/{username}/{reponame}/-", func() { | ||||||
| @@ -1603,9 +1604,9 @@ func registerRoutes(m *web.Router) { | |||||||
| 		m.Get("/stars", starsEnabled, repo.Stars) | 		m.Get("/stars", starsEnabled, repo.Stars) | ||||||
| 		m.Get("/watchers", repo.Watchers) | 		m.Get("/watchers", repo.Watchers) | ||||||
| 		m.Get("/search", reqUnitCodeReader, repo.Search) | 		m.Get("/search", reqUnitCodeReader, repo.Search) | ||||||
| 		m.Post("/action/{action:star|unstar}", reqSignIn, starsEnabled, repo.Action) | 		m.Post("/action/{action:star|unstar}", reqSignIn, starsEnabled, repo.ActionStar) | ||||||
| 		m.Post("/action/{action:watch|unwatch}", reqSignIn, repo.Action) | 		m.Post("/action/{action:watch|unwatch}", reqSignIn, repo.ActionWatch) | ||||||
| 		m.Post("/action/{action:accept_transfer|reject_transfer}", reqSignIn, repo.Action) | 		m.Post("/action/{action:accept_transfer|reject_transfer}", reqSignIn, repo.ActionTransfer) | ||||||
| 	}, optSignIn, context.RepoAssignment) | 	}, optSignIn, context.RepoAssignment) | ||||||
|  |  | ||||||
| 	common.AddOwnerRepoGitLFSRoutes(m, optSignInIgnoreCsrf, lfsServerEnabled) // "/{username}/{reponame}/{lfs-paths}": git-lfs support | 	common.AddOwnerRepoGitLFSRoutes(m, optSignInIgnoreCsrf, lfsServerEnabled) // "/{username}/{reponame}/{lfs-paths}": git-lfs support | ||||||
|   | |||||||
| @@ -62,217 +62,193 @@ func GetOrganizationByParams(ctx *Context) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // HandleOrgAssignment handles organization assignment | type OrgAssignmentOptions struct { | ||||||
| // args: requireMember, requireOwner, requireTeamMember, requireTeamAdmin | 	RequireMember     bool | ||||||
| func HandleOrgAssignment(ctx *Context, args ...bool) { | 	RequireOwner      bool | ||||||
| 	var ( | 	RequireTeamMember bool | ||||||
| 		requireMember     bool | 	RequireTeamAdmin  bool | ||||||
| 		requireOwner      bool | } | ||||||
| 		requireTeamMember bool |  | ||||||
| 		requireTeamAdmin  bool |  | ||||||
| 	) |  | ||||||
| 	if len(args) >= 1 { |  | ||||||
| 		requireMember = args[0] |  | ||||||
| 	} |  | ||||||
| 	if len(args) >= 2 { |  | ||||||
| 		requireOwner = args[1] |  | ||||||
| 	} |  | ||||||
| 	if len(args) >= 3 { |  | ||||||
| 		requireTeamMember = args[2] |  | ||||||
| 	} |  | ||||||
| 	if len(args) >= 4 { |  | ||||||
| 		requireTeamAdmin = args[3] |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var err error | // OrgAssignment returns a middleware to handle organization assignment | ||||||
|  | func OrgAssignment(opts OrgAssignmentOptions) func(ctx *Context) { | ||||||
| 	if ctx.ContextUser == nil { | 	return func(ctx *Context) { | ||||||
| 		// if Organization is not defined, get it from params | 		var err error | ||||||
| 		if ctx.Org.Organization == nil { | 		if ctx.ContextUser == nil { | ||||||
| 			GetOrganizationByParams(ctx) | 			// if Organization is not defined, get it from params | ||||||
| 			if ctx.Written() { | 			if ctx.Org.Organization == nil { | ||||||
| 				return | 				GetOrganizationByParams(ctx) | ||||||
|  | 				if ctx.Written() { | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} else if ctx.ContextUser.IsOrganization() { | ||||||
| 	} else if ctx.ContextUser.IsOrganization() { | 			ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser) | ||||||
| 		if ctx.Org == nil { | 		} else { | ||||||
| 			ctx.Org = &Organization{} | 			// ContextUser is an individual User | ||||||
| 		} |  | ||||||
| 		ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser) |  | ||||||
| 	} else { |  | ||||||
| 		// ContextUser is an individual User |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	org := ctx.Org.Organization |  | ||||||
|  |  | ||||||
| 	// Handle Visibility |  | ||||||
| 	if org.Visibility != structs.VisibleTypePublic && !ctx.IsSigned { |  | ||||||
| 		// We must be signed in to see limited or private organizations |  | ||||||
| 		ctx.NotFound("OrgAssignment", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if org.Visibility == structs.VisibleTypePrivate { |  | ||||||
| 		requireMember = true |  | ||||||
| 	} else if ctx.IsSigned && ctx.Doer.IsRestricted { |  | ||||||
| 		requireMember = true |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx.ContextUser = org.AsUser() |  | ||||||
| 	ctx.Data["Org"] = org |  | ||||||
|  |  | ||||||
| 	// Admin has super access. |  | ||||||
| 	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, ctx.Doer.ID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			ctx.ServerError("IsOwnedBy", err) |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if ctx.Org.IsOwner { | 		org := ctx.Org.Organization | ||||||
|  |  | ||||||
|  | 		// Handle Visibility | ||||||
|  | 		if org.Visibility != structs.VisibleTypePublic && !ctx.IsSigned { | ||||||
|  | 			// We must be signed in to see limited or private organizations | ||||||
|  | 			ctx.NotFound("OrgAssignment", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if org.Visibility == structs.VisibleTypePrivate { | ||||||
|  | 			opts.RequireMember = true | ||||||
|  | 		} else if ctx.IsSigned && ctx.Doer.IsRestricted { | ||||||
|  | 			opts.RequireMember = true | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		ctx.ContextUser = org.AsUser() | ||||||
|  | 		ctx.Data["Org"] = org | ||||||
|  |  | ||||||
|  | 		// Admin has super access. | ||||||
|  | 		if ctx.IsSigned && ctx.Doer.IsAdmin { | ||||||
|  | 			ctx.Org.IsOwner = true | ||||||
| 			ctx.Org.IsMember = true | 			ctx.Org.IsMember = true | ||||||
| 			ctx.Org.IsTeamMember = true | 			ctx.Org.IsTeamMember = true | ||||||
| 			ctx.Org.IsTeamAdmin = true | 			ctx.Org.IsTeamAdmin = true | ||||||
| 			ctx.Org.CanCreateOrgRepo = true | 			ctx.Org.CanCreateOrgRepo = true | ||||||
|  | 		} else if ctx.IsSigned { | ||||||
|  | 			ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.ServerError("IsOwnedBy", err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			if ctx.Org.IsOwner { | ||||||
|  | 				ctx.Org.IsMember = true | ||||||
|  | 				ctx.Org.IsTeamMember = true | ||||||
|  | 				ctx.Org.IsTeamAdmin = true | ||||||
|  | 				ctx.Org.CanCreateOrgRepo = true | ||||||
|  | 			} else { | ||||||
|  | 				ctx.Org.IsMember, err = org.IsOrgMember(ctx, ctx.Doer.ID) | ||||||
|  | 				if err != nil { | ||||||
|  | 					ctx.ServerError("IsOrgMember", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 				ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx, ctx.Doer.ID) | ||||||
|  | 				if err != nil { | ||||||
|  | 					ctx.ServerError("CanCreateOrgRepo", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			ctx.Org.IsMember, err = org.IsOrgMember(ctx, ctx.Doer.ID) | 			// Fake data. | ||||||
| 			if err != nil { | 			ctx.Data["SignedUser"] = &user_model.User{} | ||||||
| 				ctx.ServerError("IsOrgMember", err) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 			ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx, ctx.Doer.ID) |  | ||||||
| 			if err != nil { |  | ||||||
| 				ctx.ServerError("CanCreateOrgRepo", err) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} else { | 		if (opts.RequireMember && !ctx.Org.IsMember) || (opts.RequireOwner && !ctx.Org.IsOwner) { | ||||||
| 		// Fake data. | 			ctx.NotFound("OrgAssignment", err) | ||||||
| 		ctx.Data["SignedUser"] = &user_model.User{} | 			return | ||||||
| 	} | 		} | ||||||
| 	if (requireMember && !ctx.Org.IsMember) || | 		ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner | ||||||
| 		(requireOwner && !ctx.Org.IsOwner) { | 		ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember | ||||||
| 		ctx.NotFound("OrgAssignment", err) | 		ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled | ||||||
| 		return | 		ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||||
| 	} | 		ctx.Data["IsPublicMember"] = func(uid int64) bool { | ||||||
| 	ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner | 			is, _ := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, uid) | ||||||
| 	ctx.Data["IsOrganizationMember"] = ctx.Org.IsMember | 			return is | ||||||
| 	ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled | 		} | ||||||
| 	ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | 		ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo | ||||||
| 	ctx.Data["IsPublicMember"] = func(uid int64) bool { |  | ||||||
| 		is, _ := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, uid) |  | ||||||
| 		return is |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo |  | ||||||
|  |  | ||||||
| 	ctx.Org.OrgLink = org.AsUser().OrganisationLink() | 		ctx.Org.OrgLink = org.AsUser().OrganisationLink() | ||||||
| 	ctx.Data["OrgLink"] = ctx.Org.OrgLink | 		ctx.Data["OrgLink"] = ctx.Org.OrgLink | ||||||
|  |  | ||||||
| 	// Member | 		// Member | ||||||
| 	opts := &organization.FindOrgMembersOpts{ | 		findMembersOpts := &organization.FindOrgMembersOpts{ | ||||||
| 		Doer:         ctx.Doer, | 			Doer:         ctx.Doer, | ||||||
| 		OrgID:        org.ID, | 			OrgID:        org.ID, | ||||||
| 		IsDoerMember: ctx.Org.IsMember, | 			IsDoerMember: ctx.Org.IsMember, | ||||||
| 	} | 		} | ||||||
| 	ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts) | 		ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, findMembersOpts) | ||||||
| 	if err != nil { | 		if err != nil { | ||||||
| 		ctx.ServerError("CountOrgMembers", err) | 			ctx.ServerError("CountOrgMembers", err) | ||||||
| 		return | 			return | ||||||
| 	} | 		} | ||||||
|  |  | ||||||
| 	// Team. | 		// Team. | ||||||
| 	if ctx.Org.IsMember { | 		if ctx.Org.IsMember { | ||||||
| 		shouldSeeAllTeams := false | 			shouldSeeAllTeams := false | ||||||
| 		if ctx.Org.IsOwner { | 			if ctx.Org.IsOwner { | ||||||
| 			shouldSeeAllTeams = true | 				shouldSeeAllTeams = true | ||||||
| 		} else { | 			} else { | ||||||
| 			teams, err := org.GetUserTeams(ctx, ctx.Doer.ID) | 				teams, err := org.GetUserTeams(ctx, ctx.Doer.ID) | ||||||
| 			if err != nil { | 				if err != nil { | ||||||
| 				ctx.ServerError("GetUserTeams", err) | 					ctx.ServerError("GetUserTeams", err) | ||||||
| 				return | 					return | ||||||
|  | 				} | ||||||
|  | 				for _, team := range teams { | ||||||
|  | 					if team.IncludesAllRepositories && team.AccessMode >= perm.AccessModeAdmin { | ||||||
|  | 						shouldSeeAllTeams = true | ||||||
|  | 						break | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 			for _, team := range teams { | 			if shouldSeeAllTeams { | ||||||
| 				if team.IncludesAllRepositories && team.AccessMode >= perm.AccessModeAdmin { | 				ctx.Org.Teams, err = org.LoadTeams(ctx) | ||||||
| 					shouldSeeAllTeams = true | 				if err != nil { | ||||||
|  | 					ctx.ServerError("LoadTeams", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				ctx.Org.Teams, err = org.GetUserTeams(ctx, ctx.Doer.ID) | ||||||
|  | 				if err != nil { | ||||||
|  | 					ctx.ServerError("GetUserTeams", err) | ||||||
|  | 					return | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			ctx.Data["NumTeams"] = len(ctx.Org.Teams) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		teamName := ctx.PathParam("team") | ||||||
|  | 		if len(teamName) > 0 { | ||||||
|  | 			teamExists := false | ||||||
|  | 			for _, team := range ctx.Org.Teams { | ||||||
|  | 				if team.LowerName == strings.ToLower(teamName) { | ||||||
|  | 					teamExists = true | ||||||
|  | 					ctx.Org.Team = team | ||||||
|  | 					ctx.Org.IsTeamMember = true | ||||||
|  | 					ctx.Data["Team"] = ctx.Org.Team | ||||||
| 					break | 					break | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} |  | ||||||
| 		if shouldSeeAllTeams { | 			if !teamExists { | ||||||
| 			ctx.Org.Teams, err = org.LoadTeams(ctx) | 				ctx.NotFound("OrgAssignment", err) | ||||||
| 			if err != nil { |  | ||||||
| 				ctx.ServerError("LoadTeams", err) |  | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 		} else { |  | ||||||
| 			ctx.Org.Teams, err = org.GetUserTeams(ctx, ctx.Doer.ID) | 			ctx.Data["IsTeamMember"] = ctx.Org.IsTeamMember | ||||||
| 			if err != nil { | 			if opts.RequireTeamMember && !ctx.Org.IsTeamMember { | ||||||
| 				ctx.ServerError("GetUserTeams", err) | 				ctx.NotFound("OrgAssignment", err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			ctx.Org.IsTeamAdmin = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.AccessMode >= perm.AccessModeAdmin | ||||||
|  | 			ctx.Data["IsTeamAdmin"] = ctx.Org.IsTeamAdmin | ||||||
|  | 			if opts.RequireTeamAdmin && !ctx.Org.IsTeamAdmin { | ||||||
|  | 				ctx.NotFound("OrgAssignment", err) | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		ctx.Data["NumTeams"] = len(ctx.Org.Teams) | 		ctx.Data["ContextUser"] = ctx.ContextUser | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	teamName := ctx.PathParam("team") | 		ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects) | ||||||
| 	if len(teamName) > 0 { | 		ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages) | ||||||
| 		teamExists := false | 		ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode) | ||||||
| 		for _, team := range ctx.Org.Teams { |  | ||||||
| 			if team.LowerName == strings.ToLower(teamName) { | 		ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID) | ||||||
| 				teamExists = true | 		if len(ctx.ContextUser.Description) != 0 { | ||||||
| 				ctx.Org.Team = team | 			content, err := markdown.RenderString(markup.NewRenderContext(ctx), ctx.ContextUser.Description) | ||||||
| 				ctx.Org.IsTeamMember = true | 			if err != nil { | ||||||
| 				ctx.Data["Team"] = ctx.Org.Team | 				ctx.ServerError("RenderString", err) | ||||||
| 				break | 				return | ||||||
| 			} | 			} | ||||||
|  | 			ctx.Data["RenderedDescription"] = content | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if !teamExists { |  | ||||||
| 			ctx.NotFound("OrgAssignment", err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		ctx.Data["IsTeamMember"] = ctx.Org.IsTeamMember |  | ||||||
| 		if requireTeamMember && !ctx.Org.IsTeamMember { |  | ||||||
| 			ctx.NotFound("OrgAssignment", err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		ctx.Org.IsTeamAdmin = ctx.Org.Team.IsOwnerTeam() || ctx.Org.Team.AccessMode >= perm.AccessModeAdmin |  | ||||||
| 		ctx.Data["IsTeamAdmin"] = ctx.Org.IsTeamAdmin |  | ||||||
| 		if requireTeamAdmin && !ctx.Org.IsTeamAdmin { |  | ||||||
| 			ctx.NotFound("OrgAssignment", err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["ContextUser"] = ctx.ContextUser |  | ||||||
|  |  | ||||||
| 	ctx.Data["CanReadProjects"] = ctx.Org.CanReadUnit(ctx, unit.TypeProjects) |  | ||||||
| 	ctx.Data["CanReadPackages"] = ctx.Org.CanReadUnit(ctx, unit.TypePackages) |  | ||||||
| 	ctx.Data["CanReadCode"] = ctx.Org.CanReadUnit(ctx, unit.TypeCode) |  | ||||||
|  |  | ||||||
| 	ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID) |  | ||||||
| 	if len(ctx.ContextUser.Description) != 0 { |  | ||||||
| 		content, err := markdown.RenderString(markup.NewRenderContext(ctx), ctx.ContextUser.Description) |  | ||||||
| 		if err != nil { |  | ||||||
| 			ctx.ServerError("RenderString", err) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		ctx.Data["RenderedDescription"] = content |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // OrgAssignment returns a middleware to handle organization assignment |  | ||||||
| // args: requireMember, requireOwner, requireTeamMember, requireTeamAdmin |  | ||||||
| func OrgAssignment(args ...bool) func(ctx *Context) { |  | ||||||
| 	return func(ctx *Context) { |  | ||||||
| 		HandleOrgAssignment(ctx, args...) |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user