mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	api(refactor): minimize number of endpoints to 2 by refactoring current logic
This commit is contained in:
		@@ -138,7 +138,6 @@ func sudo() func(ctx *context.APIContext) {
 | 
				
			|||||||
func repoAssignment() func(ctx *context.APIContext) {
 | 
					func repoAssignment() func(ctx *context.APIContext) {
 | 
				
			||||||
	return func(ctx *context.APIContext) {
 | 
						return func(ctx *context.APIContext) {
 | 
				
			||||||
		userName := ctx.PathParam("username")
 | 
							userName := ctx.PathParam("username")
 | 
				
			||||||
		orgName := ctx.PathParam("org")
 | 
					 | 
				
			||||||
		repoName := ctx.PathParam("reponame")
 | 
							repoName := ctx.PathParam("reponame")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var (
 | 
							var (
 | 
				
			||||||
@@ -147,7 +146,6 @@ func repoAssignment() func(ctx *context.APIContext) {
 | 
				
			|||||||
		)
 | 
							)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Check if the user is the same as the repository owner.
 | 
							// Check if the user is the same as the repository owner.
 | 
				
			||||||
		if userName != "" {
 | 
					 | 
				
			||||||
		if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
 | 
							if ctx.IsSigned && ctx.Doer.LowerName == strings.ToLower(userName) {
 | 
				
			||||||
			owner = ctx.Doer
 | 
								owner = ctx.Doer
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
@@ -167,28 +165,6 @@ func repoAssignment() func(ctx *context.APIContext) {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if orgName != "" {
 | 
					 | 
				
			||||||
			org, err := organization.GetOrgByName(ctx, orgName)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				if organization.IsErrOrgNotExist(err) {
 | 
					 | 
				
			||||||
					redirectUserID, err := user_model.LookupUserRedirect(ctx, orgName)
 | 
					 | 
				
			||||||
					if err == nil {
 | 
					 | 
				
			||||||
						context.RedirectToUser(ctx.Base, orgName, redirectUserID)
 | 
					 | 
				
			||||||
					} else if user_model.IsErrUserRedirectNotExist(err) {
 | 
					 | 
				
			||||||
						ctx.NotFound()
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			ctx.Org.Organization = org
 | 
					 | 
				
			||||||
			owner = org.AsUser()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ctx.Repo.Owner = owner
 | 
							ctx.Repo.Owner = owner
 | 
				
			||||||
		ctx.ContextUser = owner
 | 
							ctx.ContextUser = owner
 | 
				
			||||||
@@ -390,11 +366,13 @@ func reqOwner() func(ctx *context.APIContext) {
 | 
				
			|||||||
// reqSelfOrAdmin doer should be the same as the contextUser or site admin
 | 
					// reqSelfOrAdmin doer should be the same as the contextUser or site admin
 | 
				
			||||||
func reqSelfOrAdmin() func(ctx *context.APIContext) {
 | 
					func reqSelfOrAdmin() func(ctx *context.APIContext) {
 | 
				
			||||||
	return func(ctx *context.APIContext) {
 | 
						return func(ctx *context.APIContext) {
 | 
				
			||||||
 | 
							if ctx.ContextUser.IsIndividual() {
 | 
				
			||||||
			if !ctx.IsUserSiteAdmin() && ctx.ContextUser != ctx.Doer {
 | 
								if !ctx.IsUserSiteAdmin() && ctx.ContextUser != ctx.Doer {
 | 
				
			||||||
				ctx.Error(http.StatusForbidden, "reqSelfOrAdmin", "doer should be the site admin or be same as the contextUser")
 | 
									ctx.Error(http.StatusForbidden, "reqSelfOrAdmin", "doer should be the site admin or be same as the contextUser")
 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// reqAdmin user should be an owner or a collaborator with admin write of a repository, or site admin
 | 
					// reqAdmin user should be an owner or a collaborator with admin write of a repository, or site admin
 | 
				
			||||||
@@ -591,24 +569,24 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
 | 
				
			|||||||
	return func(ctx *context.APIContext) {
 | 
						return func(ctx *context.APIContext) {
 | 
				
			||||||
		ctx.Org = new(context.APIOrganization)
 | 
							ctx.Org = new(context.APIOrganization)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var err error
 | 
							if ctx.ContextUser == nil {
 | 
				
			||||||
		if assignOrg {
 | 
								if ctx.Org.Organization == nil {
 | 
				
			||||||
			ctx.Org.Organization, err = organization.GetOrgByName(ctx, ctx.PathParam(":org"))
 | 
									getOrganizationByParams(ctx)
 | 
				
			||||||
			if err != nil {
 | 
									ctx.ContextUser = ctx.Org.Organization.AsUser()
 | 
				
			||||||
				if organization.IsErrOrgNotExist(err) {
 | 
					 | 
				
			||||||
					redirectUserID, err := user_model.LookupUserRedirect(ctx, ctx.PathParam(":org"))
 | 
					 | 
				
			||||||
					if err == nil {
 | 
					 | 
				
			||||||
						context.RedirectToUser(ctx.Base, ctx.PathParam(":org"), redirectUserID)
 | 
					 | 
				
			||||||
					} else if user_model.IsErrUserRedirectNotExist(err) {
 | 
					 | 
				
			||||||
						ctx.NotFound("GetOrgByName", err)
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
				} else {
 | 
							} else if ctx.ContextUser.IsOrganization() {
 | 
				
			||||||
					ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
 | 
								if ctx.Org == nil {
 | 
				
			||||||
 | 
									ctx.Org = &context.APIOrganization{}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								ctx.Org.Organization = (*organization.Organization)(ctx.ContextUser)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// ContextUser is an individual User
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							if assignOrg {
 | 
				
			||||||
 | 
								getOrganizationByParams(ctx)
 | 
				
			||||||
			ctx.ContextUser = ctx.Org.Organization.AsUser()
 | 
								ctx.ContextUser = ctx.Org.Organization.AsUser()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -626,6 +604,29 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getOrganizationByParams(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						orgName := ctx.PathParam(":org")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Org.Organization, err = organization.GetOrgByName(ctx, orgName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if organization.IsErrOrgNotExist(err) {
 | 
				
			||||||
 | 
								redirectUserID, err := user_model.LookupUserRedirect(ctx, ctx.PathParam(":org"))
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									context.RedirectToUser(ctx.Base, ctx.PathParam(":org"), redirectUserID)
 | 
				
			||||||
 | 
								} else if user_model.IsErrUserRedirectNotExist(err) {
 | 
				
			||||||
 | 
									ctx.NotFound("GetOrgByName", err)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									ctx.Error(http.StatusInternalServerError, "LookupUserRedirect", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusInternalServerError, "GetOrgByName", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mustEnableRepoProjects(ctx *context.APIContext) {
 | 
					func mustEnableRepoProjects(ctx *context.APIContext) {
 | 
				
			||||||
	if unit.TypeProjects.UnitGlobalDisabled() {
 | 
						if unit.TypeProjects.UnitGlobalDisabled() {
 | 
				
			||||||
		ctx.NotFound("EnableRepoProjects", nil)
 | 
							ctx.NotFound("EnableRepoProjects", nil)
 | 
				
			||||||
@@ -1018,7 +1019,7 @@ func Routes() *web.Router {
 | 
				
			|||||||
		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser))
 | 
							}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Users (requires user scope)
 | 
							// Users (requires user scope)
 | 
				
			||||||
		m.Group("users/{username}/-", func() {
 | 
							m.Group("/{username}/-", func() {
 | 
				
			||||||
			m.Group("/projects", func() {
 | 
								m.Group("/projects", func() {
 | 
				
			||||||
				m.Group("", func() {
 | 
									m.Group("", func() {
 | 
				
			||||||
					m.Get("", org.GetProjects)
 | 
										m.Get("", org.GetProjects)
 | 
				
			||||||
@@ -1041,13 +1042,13 @@ func Routes() *web.Router {
 | 
				
			|||||||
							m.Post("/move", org.MoveIssues)
 | 
												m.Post("/move", org.MoveIssues)
 | 
				
			||||||
						})
 | 
											})
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				}, reqSelfOrAdmin())
 | 
									}, reqSelfOrAdmin(), reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true))
 | 
				
			||||||
			}, individualPermsChecker)
 | 
								}, individualPermsChecker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken(), context.UserAssignmentAPI())
 | 
							}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), reqToken(), context.UserAssignmentAPI(), orgAssignment(), reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Users (requires user scope)
 | 
							// Users (requires user scope)
 | 
				
			||||||
		m.Group("users/{username}/{reponame}", func() {
 | 
							m.Group("/{username}/{reponame}", func() {
 | 
				
			||||||
			m.Group("/projects", func() {
 | 
								m.Group("/projects", func() {
 | 
				
			||||||
				m.Group("", func() {
 | 
									m.Group("", func() {
 | 
				
			||||||
					m.Get("", repo.GetProjects)
 | 
										m.Get("", repo.GetProjects)
 | 
				
			||||||
@@ -1076,67 +1077,7 @@ func Routes() *web.Router {
 | 
				
			|||||||
			m.Group("/{type:issues|pulls}", func() {
 | 
								m.Group("/{type:issues|pulls}", func() {
 | 
				
			||||||
				m.Post("/projects", reqRepoWriterOr(unit.TypeIssues, unit.TypePullRequests), reqRepoWriter(unit.TypeProjects), repo.UpdateIssueProject)
 | 
									m.Post("/projects", reqRepoWriterOr(unit.TypeIssues, unit.TypePullRequests), reqRepoWriter(unit.TypeProjects), repo.UpdateIssueProject)
 | 
				
			||||||
			}, individualPermsChecker)
 | 
								}, individualPermsChecker)
 | 
				
			||||||
		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryRepository), reqToken(), repoAssignment(), reqRepoReader(unit.TypeProjects), mustEnableRepoProjects)
 | 
							}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization, auth_model.AccessTokenScopeCategoryRepository), reqToken(), repoAssignment(), reqRepoReader(unit.TypeProjects), mustEnableRepoProjects)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Organizations (requires orgs scope)
 | 
					 | 
				
			||||||
		m.Group("orgs/{org}/-", func() {
 | 
					 | 
				
			||||||
			m.Group("/projects", func() {
 | 
					 | 
				
			||||||
				m.Group("", func() {
 | 
					 | 
				
			||||||
					m.Get("", org.GetProjects)
 | 
					 | 
				
			||||||
					m.Get("/{id}", org.GetProject)
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				m.Group("", func() {
 | 
					 | 
				
			||||||
					m.Post("", bind(api.CreateProjectOption{}), org.CreateProject)
 | 
					 | 
				
			||||||
					m.Group("/{id}", func() {
 | 
					 | 
				
			||||||
						m.Post("", bind(api.EditProjectColumnOption{}), org.AddColumnToProject)
 | 
					 | 
				
			||||||
						m.Delete("", org.DeleteProject)
 | 
					 | 
				
			||||||
						m.Put("", bind(api.CreateProjectOption{}), org.EditProject)
 | 
					 | 
				
			||||||
						m.Post("/move", project.MoveColumns)
 | 
					 | 
				
			||||||
						m.Post("/{action:open|close}", org.ChangeProjectStatus)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						m.Group("/{columnID}", func() {
 | 
					 | 
				
			||||||
							m.Put("", bind(api.EditProjectColumnOption{}), org.EditProjectColumn)
 | 
					 | 
				
			||||||
							m.Delete("", org.DeleteProjectColumn)
 | 
					 | 
				
			||||||
							m.Post("/default", org.SetDefaultProjectColumn)
 | 
					 | 
				
			||||||
							m.Post("/move", org.MoveIssues)
 | 
					 | 
				
			||||||
						})
 | 
					 | 
				
			||||||
					})
 | 
					 | 
				
			||||||
				}, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true))
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), orgAssignment(true), reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Organizations (requires orgs scope)
 | 
					 | 
				
			||||||
		m.Group("orgs/{org}/{reponame}", func() {
 | 
					 | 
				
			||||||
			m.Group("/projects", func() {
 | 
					 | 
				
			||||||
				m.Group("", func() {
 | 
					 | 
				
			||||||
					m.Get("", repo.GetProjects)
 | 
					 | 
				
			||||||
					m.Get("/{id}", repo.GetProject)
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				m.Group("", func() {
 | 
					 | 
				
			||||||
					m.Post("", bind(api.CreateProjectOption{}), repo.CreateProject)
 | 
					 | 
				
			||||||
					m.Group("/{id}", func() {
 | 
					 | 
				
			||||||
						m.Post("", bind(api.EditProjectColumnOption{}), repo.AddColumnToProject)
 | 
					 | 
				
			||||||
						m.Delete("", repo.DeleteProject)
 | 
					 | 
				
			||||||
						m.Put("", bind(api.CreateProjectOption{}), repo.EditProject)
 | 
					 | 
				
			||||||
						m.Post("/move", project.MoveColumns)
 | 
					 | 
				
			||||||
						m.Post("/{action:open|close}", repo.ChangeProjectStatus)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
						m.Group("/{columnID}", func() {
 | 
					 | 
				
			||||||
							m.Put("", bind(api.EditProjectColumnOption{}), repo.EditProjectColumn)
 | 
					 | 
				
			||||||
							m.Delete("", repo.DeleteProjectColumn)
 | 
					 | 
				
			||||||
							m.Post("/default", repo.SetDefaultProjectColumn)
 | 
					 | 
				
			||||||
							m.Post("/move", repo.MoveIssues)
 | 
					 | 
				
			||||||
						})
 | 
					 | 
				
			||||||
					})
 | 
					 | 
				
			||||||
				}, reqRepoWriter(unit.TypeProjects), mustNotBeArchived)
 | 
					 | 
				
			||||||
			})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			m.Group("/{type:issues|pulls}", func() {
 | 
					 | 
				
			||||||
				m.Post("/projects", reqRepoWriterOr(unit.TypeIssues, unit.TypePullRequests), reqRepoWriter(unit.TypeProjects), repo.UpdateIssueProject)
 | 
					 | 
				
			||||||
			}, reqRepoWriter(unit.TypeProjects), mustNotBeArchived)
 | 
					 | 
				
			||||||
		}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization, auth_model.AccessTokenScopeCategoryRepository), reqToken(), repoAssignment(), reqRepoReader(unit.TypeProjects), mustEnableRepoProjects)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Users (requires user scope)
 | 
							// Users (requires user scope)
 | 
				
			||||||
		m.Group("/users", func() {
 | 
							m.Group("/users", func() {
 | 
				
			||||||
@@ -1672,6 +1613,7 @@ func Routes() *web.Router {
 | 
				
			|||||||
		m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
 | 
							m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
 | 
				
			||||||
		m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
 | 
							m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
 | 
				
			||||||
		m.Group("/orgs/{org}", func() {
 | 
							m.Group("/orgs/{org}", func() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			m.Combo("").Get(org.Get).
 | 
								m.Combo("").Get(org.Get).
 | 
				
			||||||
				Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
 | 
									Patch(reqToken(), reqOrgOwnership(), bind(api.EditOrgOption{}), org.Edit).
 | 
				
			||||||
				Delete(reqToken(), reqOrgOwnership(), org.Delete)
 | 
									Delete(reqToken(), reqOrgOwnership(), org.Delete)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -72,7 +72,6 @@ func GetProjects(ctx *context.APIContext) {
 | 
				
			|||||||
	ctx.JSON(http.StatusOK, convert.ToProjects(ctx, projects))
 | 
						ctx.JSON(http.StatusOK, convert.ToProjects(ctx, projects))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Send issues as well
 | 
					 | 
				
			||||||
// GetProject returns a project by ID
 | 
					// GetProject returns a project by ID
 | 
				
			||||||
func GetProject(ctx *context.APIContext) {
 | 
					func GetProject(ctx *context.APIContext) {
 | 
				
			||||||
	project, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64(":id"))
 | 
						project, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64(":id"))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,7 +66,6 @@ func GetProjects(ctx *context.APIContext) {
 | 
				
			|||||||
	ctx.JSON(http.StatusOK, convert.ToProjects(ctx, projects))
 | 
						ctx.JSON(http.StatusOK, convert.ToProjects(ctx, projects))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Send issues as well
 | 
					 | 
				
			||||||
// GetProject returns a project by ID
 | 
					// GetProject returns a project by ID
 | 
				
			||||||
func GetProject(ctx *context.APIContext) {
 | 
					func GetProject(ctx *context.APIContext) {
 | 
				
			||||||
	project, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64(":id"))
 | 
						project, err := project_model.GetProjectByID(ctx, ctx.PathParamInt64(":id"))
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user