diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 90ba816b65..572abcdb31 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -964,6 +964,73 @@ func Routes() *web.Router { }, context.UserAssignmentAPI(), individualPermsChecker) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser)) + // m.Group("/projects", func() { + // m.Group("", func() { + // m.Get("", org.Projects) + // m.Get("/{id}", org.ViewProject) + // }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true)) + // m.Group("", func() { //nolint:dupl + // m.Get("/new", org.RenderNewProject) + // m.Post("/new", web.Bind(forms.CreateProjectForm{}), org.NewProjectPost) + // m.Group("/{id}", func() { + // m.Post("", web.Bind(forms.EditProjectColumnForm{}), org.AddColumnToProjectPost) + // m.Post("/move", project.MoveColumns) + // m.Post("/delete", org.DeleteProject) + + // m.Get("/edit", org.RenderEditProject) + // m.Post("/edit", web.Bind(forms.CreateProjectForm{}), org.EditProjectPost) + // m.Post("/{action:open|close}", org.ChangeProjectStatus) + + // m.Group("/{columnID}", func() { + // m.Put("", web.Bind(forms.EditProjectColumnForm{}), org.EditProjectColumn) + // m.Delete("", org.DeleteProjectColumn) + // m.Post("/default", org.SetDefaultProjectColumn) + // m.Post("/move", org.MoveIssues) + // }) + // }) + // }, reqSignIn, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true), func(ctx *context.Context) { + // if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID { + // ctx.NotFound("NewProject", nil) + // return + // } + // }) + // }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true), individualPermsChecker) + // Users (requires user scope) + m.Group("/{username}/-", func() { + m.Group("/projects", func() { + m.Group("", func() { + m.Get("", org.GetProjects) + // m.Get("/{id}", org.ViewProject) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true)) + m.Group("", func() { + m.Post("", bind(api.CreateProjectOption{}), org.CreateProject) + m.Group("/{id}", func() { + m.Post("/{action:open|close}", org.ChangeProjectStatus) + }) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true), func(ctx *context.APIContext) { + if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID { + ctx.NotFound("NewProject", nil) + return + } + }) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true), individualPermsChecker) + }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken(), context.UserAssignmentAPI()) + + m.Group("/{org}/-", func() { + m.Group("/projects", func() { + m.Group("", func() { + // m.Get("", org.Projects) + // m.Get("/{id}", org.ViewProject) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true)) + m.Group("", func() { + m.Post("", bind(api.CreateProjectOption{}), org.CreateProject) + m.Group("/{id}", func() { + m.Post("/{action:open|close}", org.ChangeProjectStatus) + }) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true)) + }, reqUnitAccess(unit.TypeProjects, perm.AccessModeRead, true), individualPermsChecker) + }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), orgAssignment(true)) + // Users (requires user scope) m.Group("/users", func() { m.Group("/{username}", func() { @@ -979,19 +1046,7 @@ func Routes() *web.Router { m.Get("/starred", user.GetStarredRepos) m.Get("/subscriptions", user.GetWatchedRepos) - - m.Group("/projects", func() { - m.Post("", bind(api.CreateProjectOption{}), org.CreateProject) - m.Group("/{id}", func() { - m.Post("/{action:open|close}", org.ChangeProjectStatus) - }) - }) - }, context.UserAssignmentAPI(), reqUnitAccess(unit.TypeProjects, perm.AccessModeWrite, true), func(ctx *context.APIContext) { - if ctx.ContextUser.IsIndividual() && ctx.ContextUser.ID != ctx.Doer.ID { - ctx.NotFound("NewProject", nil) - return - } - }) + }, context.UserAssignmentAPI()) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken()) // Users (requires user scope) diff --git a/routers/api/v1/org/project.go b/routers/api/v1/org/project.go index 9415727b28..1b0f96c7f3 100644 --- a/routers/api/v1/org/project.go +++ b/routers/api/v1/org/project.go @@ -3,8 +3,12 @@ package org import ( "log" "net/http" + "strings" + "code.gitea.io/gitea/models/db" project_model "code.gitea.io/gitea/models/project" + "code.gitea.io/gitea/modules/optional" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/services/context" @@ -59,3 +63,41 @@ func ChangeProjectStatus(ctx *context.APIContext) { } ctx.JSON(http.StatusOK, map[string]any{"message": "project status updated successfully"}) } + +// Projects renders the home page of projects +func GetProjects(ctx *context.APIContext) { + ctx.Data["Title"] = ctx.Tr("repo.projects") + + sortType := ctx.FormTrim("sort") + + isShowClosed := strings.ToLower(ctx.FormTrim("state")) == "closed" + keyword := ctx.FormTrim("q") + page := ctx.FormInt("page") + if page <= 1 { + page = 1 + } + + var projectType project_model.Type + if ctx.ContextUser.IsOrganization() { + projectType = project_model.TypeOrganization + } else { + projectType = project_model.TypeIndividual + } + projects, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{ + ListOptions: db.ListOptions{ + Page: page, + PageSize: setting.UI.IssuePagingNum, + }, + OwnerID: ctx.ContextUser.ID, + IsClosed: optional.Some(isShowClosed), + OrderBy: project_model.GetSearchOrderByBySortType(sortType), + Type: projectType, + Title: keyword, + }) + if err != nil { + ctx.ServerError("FindProjects", err) + return + } + + ctx.JSON(http.StatusOK, projects) +}