From 878481b1284c338977ceaa615ff16e390e35472c Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Fri, 8 Oct 2021 17:17:38 +0200 Subject: [PATCH 01/45] Add API to get/edit wiki --- modules/convert/wiki.go | 44 +++++ modules/structs/repo_wiki.go | 41 +++++ routers/api/v1/api.go | 32 ++++ routers/api/v1/repo/wiki.go | 328 +++++++++++++++++++++++++++++++++++ 4 files changed, 445 insertions(+) create mode 100644 modules/convert/wiki.go create mode 100644 modules/structs/repo_wiki.go create mode 100644 routers/api/v1/repo/wiki.go diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go new file mode 100644 index 000000000000..cd19e72bc7f8 --- /dev/null +++ b/modules/convert/wiki.go @@ -0,0 +1,44 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package convert + +import ( + "time" + + "code.gitea.io/gitea/modules/git" + api "code.gitea.io/gitea/modules/structs" +) + +func ToWikiCommit(commit *git.Commit) *api.WikiCommit { + return &api.WikiCommit{ + ID: commit.ID.String(), + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: commit.Author.Name, + Email: commit.Author.Email, + }, + Date: commit.Author.When.Format(time.RFC3339), + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: commit.Committer.Name, + Email: commit.Committer.Email, + }, + Date: commit.Committer.When.Format(time.RFC3339), + }, + Message: commit.CommitMessage, + } +} + +func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList { + result := make([]*api.WikiCommit, len(commits)) + for i := range commits { + result[i] = ToWikiCommit(commits[i]) + } + return &api.WikiCommitList{ + WikiCommits: result, + Count: count, + } +} diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go new file mode 100644 index 000000000000..5826ddfd4c67 --- /dev/null +++ b/modules/structs/repo_wiki.go @@ -0,0 +1,41 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package structs + +type WikiCommit struct { + ID string `json:"sha"` + Author *CommitUser `json:"author"` + Committer *CommitUser `json:"commiter"` + Message string `json:"message"` +} + +type WikiPage struct { + *PageMeta + Title string `json:"title"` + Content string `json:"content"` + CommitCount int64 `json:"commit_count"` + LastCommit *WikiCommit `json:"last_commit"` + Sidebar string `json:"sidebar"` + Footer string `json:"footer"` +} + +// PageMeta wiki page meta information +type PageMeta struct { + Name string `json:"name"` + SubURL string `json:"suburl"` + Updated string `json:"updated"` +} + +// NewWikiForm form for creating wiki +type NewWikiForm struct { + Title string `json:"title"` + Content string `json:"content"` + Message string `json:"message"` +} + +type WikiCommitList struct { + WikiCommits []*WikiCommit `json:"commits"` + Count int64 `json:"count"` +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 0a967e3c5a78..44ad96427420 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -521,6 +521,29 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) { } } +func mustEnableWiki(ctx *context.APIContext) { + if !(ctx.Repo.CanRead(models.UnitTypeWiki)) { + /*if ctx.Repo.Repository.CanEnablePulls() && log.IsTrace() { + if ctx.IsSigned { + log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+ + "User in Repo has Permissions: %-+v", + ctx.User, + models.UnitTypePullRequests, + ctx.Repo.Repository, + ctx.Repo.Permission) + } else { + log.Trace("Permission Denied: Anonymous user cannot read %-v in Repo %-v\n"+ + "Anonymous user in Repo has Permissions: %-+v", + models.UnitTypePullRequests, + ctx.Repo.Repository, + ctx.Repo.Permission) + } + }*/ + ctx.NotFound() + return + } +} + func mustNotBeArchived(ctx *context.APIContext) { if ctx.Repo.Repository.IsArchived { ctx.NotFound() @@ -791,6 +814,15 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { m.Combo("").Get(repo.ListTrackedTimesByRepository) m.Combo("/{timetrackingusername}").Get(repo.ListTrackedTimesByUser) }, mustEnableIssues, reqToken()) + m.Group("/wiki", func() { + m.Combo("/page/{pageName}"). + Get(mustEnableWiki, repo.Wiki). + Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.NewWikiForm{}), repo.EditWiki). + Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) + m.Get("/revisions/{pageName}", mustEnableWiki, repo.WikiRevision) + m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.NewWikiForm{}), repo.NewWiki) + m.Get("/pages", mustEnableWiki, repo.WikiPages) + }) m.Group("/issues", func() { m.Combo("").Get(repo.ListIssues). Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go new file mode 100644 index 000000000000..00a3e12a6372 --- /dev/null +++ b/routers/api/v1/repo/wiki.go @@ -0,0 +1,328 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "io" + "net/http" + "net/url" + "time" + + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/convert" + "code.gitea.io/gitea/modules/git" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/web" + + "code.gitea.io/gitea/models" + //"code.gitea.io/gitea/modules/base" + //"code.gitea.io/gitea/modules/setting" + //"code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/util" + //"code.gitea.io/gitea/routers/common" + //"code.gitea.io/gitea/services/forms" + wiki_service "code.gitea.io/gitea/services/wiki" +) + +// NewWikiPost response for wiki create request +func NewWiki(ctx *context.APIContext) { + form := web.GetForm(ctx).(*api.NewWikiForm) + + if util.IsEmptyString(form.Title) { + ctx.Error(http.StatusBadRequest, "emptyTitle", nil) + return + } + + wikiName := wiki_service.NormalizeWikiName(form.Title) + + if len(form.Message) == 0 { + form.Message = ctx.Tr("repo.editor.add", form.Title) + } + + if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { + if models.IsErrWikiReservedName(err) { + ctx.Error(http.StatusBadRequest, "IsErrWikiReservedName", err) + } else if models.IsErrWikiAlreadyExist(err) { + ctx.Error(http.StatusBadRequest, "IsErrWikiAlreadyExists", err) + } else { + ctx.Error(http.StatusInternalServerError, "AddWikiPage", err) + } + return + } + + ctx.Status(http.StatusNoContent) +} + +// EditWikiPost response for wiki modify request +func EditWiki(ctx *context.APIContext) { + form := web.GetForm(ctx).(*api.NewWikiForm) + + oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) + newWikiName := wiki_service.NormalizeWikiName(form.Title) + + if len(form.Message) == 0 { + form.Message = ctx.Tr("repo.editor.update", form.Title) + } + + if len(newWikiName) == 0 { + newWikiName = oldWikiName + } + + if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { + ctx.Error(http.StatusInternalServerError, "EditWikiPage", err) + return + } + + ctx.Status(http.StatusNoContent) +} + +// DeleteWikiPage delete wiki page +func DeleteWikiPage(ctx *context.APIContext) { + wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) + if len(wikiName) == 0 { + wikiName = "Home" + } + + if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { + ctx.Error(http.StatusInternalServerError, "DeleteWikiPage", err) + return + } + + ctx.Status(http.StatusNoContent) +} + +// WikiPages get wiki pages list +func WikiPages(ctx *context.APIContext) { + wikiRepo, commit, err := findWikiRepoCommit(ctx) + if err != nil { + if wikiRepo != nil { + wikiRepo.Close() + } + return + } + defer func() { + if wikiRepo != nil { + wikiRepo.Close() + } + }() + + entries, err := commit.ListEntries() + if err != nil { + ctx.ServerError("ListEntries", err) + return + } + pages := make([]api.PageMeta, 0, len(entries)) + for _, entry := range entries { + if !entry.IsRegular() { + continue + } + c, err := wikiRepo.GetCommitByPath(entry.Name()) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetCommit", err) + return + } + wikiName, err := wiki_service.FilenameToName(entry.Name()) + if err != nil { + if models.IsErrWikiInvalidFileName(err) { + continue + } + ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) + return + } + pages = append(pages, api.PageMeta{ + Name: wikiName, + SubURL: wiki_service.NameToSubURL(wikiName), + Updated: c.Author.When.Format(time.RFC3339), + }) + } + + ctx.JSON(http.StatusOK, pages) +} + +// Wiki renders single wiki page +func Wiki(ctx *context.APIContext) { + wikiRepo, commit, err := findWikiRepoCommit(ctx) + if err != nil { + if wikiRepo != nil { + wikiRepo.Close() + } + if !git.IsErrNotExist(err) { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } + return + } + + // get requested pagename + pageName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) + if len(pageName) == 0 { + pageName = "Home" + } + + //lookup filename in wiki - get filecontent, gitTree entry , real filename + data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + if noEntry { + ctx.NotFound() + return + } + if entry == nil || ctx.Written() { + if wikiRepo != nil { + wikiRepo.Close() + } + ctx.NotFound() + return + } + + sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar") + if ctx.Written() { + if wikiRepo != nil { + wikiRepo.Close() + } + ctx.NotFound() + return + } + + footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer") + if ctx.Written() { + if wikiRepo != nil { + wikiRepo.Close() + } + ctx.NotFound() + return + } + + // get commit count - wiki revisions + commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename) + + wikiPath := entry.Name() + // Get last change information. + lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetCommitByPath", err) + return + } + + wikiPage := &api.WikiPage{ + PageMeta: &api.PageMeta{ + Name: pageName, + SubURL: wiki_service.NameToSubURL(pageName), + Updated: lastCommit.Author.When.Format(time.RFC3339), + }, + Content: string(data), + CommitCount: commitsCount, + LastCommit: convert.ToWikiCommit(lastCommit), + Sidebar: string(sidebarContent), + Footer: string(footerContent), + } + + ctx.JSON(http.StatusOK, wikiPage) +} + +// WikiRevision renders file revision list of wiki page +func WikiRevision(ctx *context.APIContext) { + wikiRepo, commit, err := findWikiRepoCommit(ctx) + if err != nil { + if wikiRepo != nil { + wikiRepo.Close() + } + if !git.IsErrNotExist(err) { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } + return + } + + // get requested pagename + pageName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) + if len(pageName) == 0 { + pageName = "Home" + } + + //lookup filename in wiki - get filecontent, gitTree entry , real filename + _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + if noEntry { + ctx.NotFound() + } + + // get commit count - wiki revisions + commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename) + + page := ctx.FormInt("page") + if page <= 1 { + page = 1 + } + + // get Commit Count + commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) + if err != nil { + if wikiRepo != nil { + wikiRepo.Close() + } + ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRangeNoFollow", err) + } + + ctx.JSON(http.StatusOK, convert.ToWikiCommitList(commitsHistory, commitsCount)) +} + +// findEntryForFile finds the tree entry for a target filepath. +func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) { + entry, err := commit.GetTreeEntryByPath(target) + if err != nil && !git.IsErrNotExist(err) { + return nil, err + } + if entry != nil { + return entry, nil + } + + // Then the unescaped, shortest alternative + var unescapedTarget string + if unescapedTarget, err = url.QueryUnescape(target); err != nil { + return nil, err + } + return commit.GetTreeEntryByPath(unescapedTarget) +} + +func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit, error) { + wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) + if err != nil { + ctx.Error(http.StatusInternalServerError, "OpenRepository", err) + return nil, nil, err + } + + commit, err := wikiRepo.GetBranchCommit("master") + if err != nil { + return wikiRepo, nil, err + } + return wikiRepo, commit, nil +} + +// wikiContentsByEntry returns the contents of the wiki page referenced by the +// given tree entry. Writes to ctx if an error occurs. +func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte { + reader, err := entry.Blob().DataAsync() + if err != nil { + ctx.Error(http.StatusInternalServerError, "Blob.Data", err) + return nil + } + defer reader.Close() + content, err := io.ReadAll(reader) + if err != nil { + ctx.Error(http.StatusInternalServerError, "ReadAll", err) + return nil + } + return content +} + +// wikiContentsByName returns the contents of a wiki page, along with a boolean +// indicating whether the page exists. Writes to ctx if an error occurs. +func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) { + pageFilename := wiki_service.NameToFilename(wikiName) + entry, err := findEntryForFile(commit, pageFilename) + if err != nil && !git.IsErrNotExist(err) { + ctx.Error(http.StatusInternalServerError, "findEntryForFile", err) + return nil, nil, "", false + } else if entry == nil { + return nil, nil, "", true + } + return wikiContentsByEntry(ctx, entry), entry, pageFilename, false +} From 7981a211eb31a9ca0fba0036d8d704ae334e1ba1 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 07:42:03 +0200 Subject: [PATCH 02/45] Add swagger docs, various improvements --- modules/convert/wiki.go | 2 + modules/structs/repo_wiki.go | 7 +- routers/api/v1/api.go | 4 +- routers/api/v1/repo/wiki.go | 169 ++++++++++++- routers/api/v1/swagger/options.go | 3 + routers/api/v1/swagger/repo.go | 21 ++ templates/swagger/v1_json.tmpl | 389 +++++++++++++++++++++++++++++- 7 files changed, 580 insertions(+), 15 deletions(-) diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go index cd19e72bc7f8..f59073d0c906 100644 --- a/modules/convert/wiki.go +++ b/modules/convert/wiki.go @@ -11,6 +11,7 @@ import ( api "code.gitea.io/gitea/modules/structs" ) +// ToWikiCommit convert a git commit into a WikiCommit func ToWikiCommit(commit *git.Commit) *api.WikiCommit { return &api.WikiCommit{ ID: commit.ID.String(), @@ -32,6 +33,7 @@ func ToWikiCommit(commit *git.Commit) *api.WikiCommit { } } +// ToWikiCommitList convert a list of git commits into a WikiCommitList func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList { result := make([]*api.WikiCommit, len(commits)) for i := range commits { diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index 5826ddfd4c67..ac31c9c0dc79 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -4,6 +4,7 @@ package structs +// WikiCommit page commit/revision type WikiCommit struct { ID string `json:"sha"` Author *CommitUser `json:"author"` @@ -11,6 +12,7 @@ type WikiCommit struct { Message string `json:"message"` } +// WikiPage a wiki page type WikiPage struct { *PageMeta Title string `json:"title"` @@ -28,13 +30,14 @@ type PageMeta struct { Updated string `json:"updated"` } -// NewWikiForm form for creating wiki -type NewWikiForm struct { +// CreateWikiPageOptions form for creating wiki +type CreateWikiPageOptions struct { Title string `json:"title"` Content string `json:"content"` Message string `json:"message"` } +// WikiCommitList commit/revision list type WikiCommitList struct { WikiCommits []*WikiCommit `json:"commits"` Count int64 `json:"count"` diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 44ad96427420..4907c059fa7d 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -817,10 +817,10 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { m.Group("/wiki", func() { m.Combo("/page/{pageName}"). Get(mustEnableWiki, repo.Wiki). - Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.NewWikiForm{}), repo.EditWiki). + Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWiki). Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) m.Get("/revisions/{pageName}", mustEnableWiki, repo.WikiRevision) - m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.NewWikiForm{}), repo.NewWiki) + m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWiki) m.Get("/pages", mustEnableWiki, repo.WikiPages) }) m.Group("/issues", func() { diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 00a3e12a6372..c9fa94673b92 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -17,18 +17,41 @@ import ( "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/models" - //"code.gitea.io/gitea/modules/base" - //"code.gitea.io/gitea/modules/setting" - //"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" - //"code.gitea.io/gitea/routers/common" - //"code.gitea.io/gitea/services/forms" wiki_service "code.gitea.io/gitea/services/wiki" ) -// NewWikiPost response for wiki create request +// NewWiki response for wiki create request func NewWiki(ctx *context.APIContext) { - form := web.GetForm(ctx).(*api.NewWikiForm) + // swagger:operation POST /repos/{owner}/{repo}/wiki/new repository repoCreateWikiPage + // --- + // summary: Create a wiki page + // consumes: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: body + // in: body + // schema: + // "$ref": "#/definitions/CreateWikiPageOptions" + // responses: + // "204": + // "$ref": "#/responses/empty" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/forbidden" + + form := web.GetForm(ctx).(*api.CreateWikiPageOptions) if util.IsEmptyString(form.Title) { ctx.Error(http.StatusBadRequest, "emptyTitle", nil) @@ -55,9 +78,42 @@ func NewWiki(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } -// EditWikiPost response for wiki modify request +// EditWiki response for wiki modify request func EditWiki(ctx *context.APIContext) { - form := web.GetForm(ctx).(*api.NewWikiForm) + // swagger:operation PATCH /repos/{owner}/{repo}/wiki/page/{pageName} repository repoEditWikiPage + // --- + // summary: Edit a wiki page + // consumes: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: pageName + // in: path + // description: name of the page + // type: string + // required: true + // - name: body + // in: body + // schema: + // "$ref": "#/definitions/CreateWikiPageOptions" + // responses: + // "204": + // "$ref": "#/responses/empty" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/forbidden" + + form := web.GetForm(ctx).(*api.CreateWikiPageOptions) oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) newWikiName := wiki_service.NormalizeWikiName(form.Title) @@ -80,6 +136,29 @@ func EditWiki(ctx *context.APIContext) { // DeleteWikiPage delete wiki page func DeleteWikiPage(ctx *context.APIContext) { + // swagger:operation DELETE /repos/{owner}/{repo}/wiki/page/{pageName} repository repoDeleteWikiPage + // --- + // summary: Delete a wiki page + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: pageName + // in: path + // description: name of the page + // type: string + // required: true + // responses: + // "204": + // "$ref": "#/responses/empty" + wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) if len(wikiName) == 0 { wikiName = "Home" @@ -95,6 +174,26 @@ func DeleteWikiPage(ctx *context.APIContext) { // WikiPages get wiki pages list func WikiPages(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/wiki/pages repository repoGetWikiPages + // --- + // summary: Get all wiki pages + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // responses: + // "201": + // "$ref": "#/responses/WikiPageList" + wikiRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { if wikiRepo != nil { @@ -141,8 +240,33 @@ func WikiPages(ctx *context.APIContext) { ctx.JSON(http.StatusOK, pages) } -// Wiki renders single wiki page +// Wiki get single wiki page func Wiki(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/wiki/page/{pageName} repository repoGetWikiPage + // --- + // summary: Get a wiki page + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: pageName + // in: path + // description: name of the page + // type: string + // required: true + // responses: + // "201": + // "$ref": "#/responses/WikiPage" + wikiRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { if wikiRepo != nil { @@ -221,6 +345,31 @@ func Wiki(ctx *context.APIContext) { // WikiRevision renders file revision list of wiki page func WikiRevision(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/wiki/revisions/{pageName} repository repoGetWikiPageRevisions + // --- + // summary: Get revisions of a wiki page + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: pageName + // in: path + // description: name of the page + // type: string + // required: true + // responses: + // "201": + // "$ref": "#/responses/WikiCommitList" + wikiRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { if wikiRepo != nil { diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index 3f0c6e2d524c..2bd43c618087 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -169,4 +169,7 @@ type swaggerParameterBodies struct { // in:body UserSettingsOptions api.UserSettingsOptions + + // in:body + CreateWikiPageOptions api.CreateWikiPageOptions } diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index ed5fe5169ee3..a1d3d7692812 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -323,3 +323,24 @@ type swaggerCombinedStatus struct { // in: body Body api.CombinedStatus `json:"body"` } + +// WikiPageList +// swagger:response WikiPageList +type WikiPageList struct { + // in:body + Body []api.PageMeta `json:"body"` +} + +// WikiPage +// swagger:response WikiPage +type WikiPage struct { + // in:body + Body api.WikiPage `json:"body"` +} + +// WikiCommitList +// swagger:response WikiCommitList +type WikiCommitList struct { + // in:body + Body api.WikiCommitList `json:"body"` +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index c6fa664af6d9..b004d3bbd699 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -9889,6 +9889,251 @@ } } }, + "/repos/{owner}/{repo}/wiki/new": { + "post": { + "consumes": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Create a wiki page", + "operationId": "repoCreateWikiPage", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/CreateWikiPageOptions" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "400": { + "$ref": "#/responses/error" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, + "/repos/{owner}/{repo}/wiki/page/{pageName}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Get a wiki page", + "operationId": "repoGetWikiPage", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the page", + "name": "pageName", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "$ref": "#/responses/WikiPage" + } + } + }, + "delete": { + "tags": [ + "repository" + ], + "summary": "Delete a wiki page", + "operationId": "repoDeleteWikiPage", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the page", + "name": "pageName", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + } + } + }, + "patch": { + "consumes": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Edit a wiki page", + "operationId": "repoEditWikiPage", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the page", + "name": "pageName", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/CreateWikiPageOptions" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "400": { + "$ref": "#/responses/error" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, + "/repos/{owner}/{repo}/wiki/pages": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Get all wiki pages", + "operationId": "repoGetWikiPages", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "$ref": "#/responses/WikiPageList" + } + } + } + }, + "/repos/{owner}/{repo}/wiki/revisions/{pageName}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Get revisions of a wiki page", + "operationId": "repoGetWikiPageRevisions", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the page", + "name": "pageName", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "$ref": "#/responses/WikiCommitList" + } + } + } + }, "/repos/{template_owner}/{template_repo}/generate": { "post": { "consumes": [ @@ -13627,6 +13872,25 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "CreateWikiPageOptions": { + "description": "CreateWikiPageOptions form for creating wiki", + "type": "object", + "properties": { + "content": { + "type": "string", + "x-go-name": "Content" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "title": { + "type": "string", + "x-go-name": "Title" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "Cron": { "description": "Cron represents a Cron task", "type": "object", @@ -15904,6 +16168,25 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "PageMeta": { + "description": "PageMeta wiki page meta information", + "type": "object", + "properties": { + "name": { + "type": "string", + "x-go-name": "Name" + }, + "suburl": { + "type": "string", + "x-go-name": "SubURL" + }, + "updated": { + "type": "string", + "x-go-name": "Updated" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "PayloadCommit": { "description": "PayloadCommit represents a commit", "type": "object", @@ -17310,6 +17593,89 @@ } }, "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "WikiCommit": { + "description": "WikiCommit page commit/revision", + "type": "object", + "properties": { + "author": { + "$ref": "#/definitions/CommitUser" + }, + "commiter": { + "$ref": "#/definitions/CommitUser" + }, + "message": { + "type": "string", + "x-go-name": "Message" + }, + "sha": { + "type": "string", + "x-go-name": "ID" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "WikiCommitList": { + "description": "WikiCommitList commit/revision list", + "type": "object", + "properties": { + "commits": { + "type": "array", + "items": { + "$ref": "#/definitions/WikiCommit" + }, + "x-go-name": "WikiCommits" + }, + "count": { + "type": "integer", + "format": "int64", + "x-go-name": "Count" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "WikiPage": { + "description": "WikiPage a wiki page", + "type": "object", + "properties": { + "commit_count": { + "type": "integer", + "format": "int64", + "x-go-name": "CommitCount" + }, + "content": { + "type": "string", + "x-go-name": "Content" + }, + "footer": { + "type": "string", + "x-go-name": "Footer" + }, + "last_commit": { + "$ref": "#/definitions/WikiCommit" + }, + "name": { + "type": "string", + "x-go-name": "Name" + }, + "sidebar": { + "type": "string", + "x-go-name": "Sidebar" + }, + "suburl": { + "type": "string", + "x-go-name": "SubURL" + }, + "title": { + "type": "string", + "x-go-name": "Title" + }, + "updated": { + "type": "string", + "x-go-name": "Updated" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" } }, "responses": { @@ -17997,6 +18363,27 @@ "$ref": "#/definitions/WatchInfo" } }, + "WikiCommitList": { + "description": "WikiCommitList", + "schema": { + "$ref": "#/definitions/WikiCommitList" + } + }, + "WikiPage": { + "description": "WikiPage", + "schema": { + "$ref": "#/definitions/WikiPage" + } + }, + "WikiPageList": { + "description": "WikiPageList", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/PageMeta" + } + } + }, "conflict": { "description": "APIConflict is a conflict empty response" }, @@ -18045,7 +18432,7 @@ "parameterBodies": { "description": "parameterBodies", "schema": { - "$ref": "#/definitions/UserSettingsOptions" + "$ref": "#/definitions/CreateWikiPageOptions" } }, "redirect": { From 48db90e7fad5b997e80099e59a7823e6c257d09a Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 07:42:28 +0200 Subject: [PATCH 03/45] fmt --- routers/api/v1/swagger/repo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index a1d3d7692812..01f0bddcaad6 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -335,7 +335,7 @@ type WikiPageList struct { // swagger:response WikiPage type WikiPage struct { // in:body - Body api.WikiPage `json:"body"` + Body api.WikiPage `json:"body"` } // WikiCommitList From 30a2377758f486d0bc614d1ad928600a0ba1643a Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 07:59:13 +0200 Subject: [PATCH 04/45] Fix lint and rm comment --- routers/api/v1/api.go | 16 ---------------- routers/api/v1/repo/wiki.go | 5 ++--- routers/api/v1/swagger/repo.go | 6 +++--- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 4907c059fa7d..00fa0c5691d5 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -523,22 +523,6 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) { func mustEnableWiki(ctx *context.APIContext) { if !(ctx.Repo.CanRead(models.UnitTypeWiki)) { - /*if ctx.Repo.Repository.CanEnablePulls() && log.IsTrace() { - if ctx.IsSigned { - log.Trace("Permission Denied: User %-v cannot read %-v in Repo %-v\n"+ - "User in Repo has Permissions: %-+v", - ctx.User, - models.UnitTypePullRequests, - ctx.Repo.Repository, - ctx.Repo.Permission) - } else { - log.Trace("Permission Denied: Anonymous user cannot read %-v in Repo %-v\n"+ - "Anonymous user in Repo has Permissions: %-+v", - models.UnitTypePullRequests, - ctx.Repo.Repository, - ctx.Repo.Permission) - } - }*/ ctx.NotFound() return } diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index c9fa94673b92..4451e0b20704 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -10,14 +10,13 @@ import ( "net/url" "time" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/web" - - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/web" wiki_service "code.gitea.io/gitea/services/wiki" ) diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index 01f0bddcaad6..e9cac44e0538 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -326,21 +326,21 @@ type swaggerCombinedStatus struct { // WikiPageList // swagger:response WikiPageList -type WikiPageList struct { +type swaggerWikiPageList struct { // in:body Body []api.PageMeta `json:"body"` } // WikiPage // swagger:response WikiPage -type WikiPage struct { +type swaggerWikiPage struct { // in:body Body api.WikiPage `json:"body"` } // WikiCommitList // swagger:response WikiCommitList -type WikiCommitList struct { +type swaggerWikiCommitList struct { // in:body Body api.WikiCommitList `json:"body"` } From 1312d581402b8e1a1c92f12e3f65a34328e58b99 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 08:40:34 +0200 Subject: [PATCH 05/45] Add page parameter --- routers/api/v1/repo/wiki.go | 4 ++++ templates/swagger/v1_json.tmpl | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 4451e0b20704..fe97b154e222 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -365,6 +365,10 @@ func WikiRevision(ctx *context.APIContext) { // description: name of the page // type: string // required: true + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer // responses: // "201": // "$ref": "#/responses/WikiCommitList" diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index b004d3bbd699..afb86831629d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -10125,6 +10125,12 @@ "name": "pageName", "in": "path", "required": true + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" } ], "responses": { From 7f5b4ef30b7ca8388446b7e50346b3eb38b4faac Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 08:59:13 +0200 Subject: [PATCH 06/45] Add pagination to pages --- routers/api/v1/repo/wiki.go | 25 +++++++++++++++++++++++-- templates/swagger/v1_json.tmpl | 12 ++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index fe97b154e222..91d08137ad0c 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -189,6 +189,14 @@ func WikiPages(ctx *context.APIContext) { // description: name of the repo // type: string // required: true + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "201": // "$ref": "#/responses/WikiPageList" @@ -206,14 +214,27 @@ func WikiPages(ctx *context.APIContext) { } }() + page := ctx.FormInt("page") + if page <= 1 { + page = 1 + } + + limit := ctx.FormInt("limit") + if limit <= 1 { + limit = 20 + } + + skip := (page - 1) * limit + max := page * limit + entries, err := commit.ListEntries() if err != nil { ctx.ServerError("ListEntries", err) return } pages := make([]api.PageMeta, 0, len(entries)) - for _, entry := range entries { - if !entry.IsRegular() { + for i, entry := range entries { + if i < skip || i >= max || !entry.IsRegular() { continue } c, err := wikiRepo.GetCommitByPath(entry.Name()) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index afb86831629d..d57084542896 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -10085,6 +10085,18 @@ "name": "repo", "in": "path", "required": true + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { From 58fb2f63d43a1fcfd160c701336b0ab44b1d24e9 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 11:24:01 +0200 Subject: [PATCH 07/45] Add tests --- integrations/api_wiki_test.go | 184 ++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 integrations/api_wiki_test.go diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go new file mode 100644 index 000000000000..ddcf8218e109 --- /dev/null +++ b/integrations/api_wiki_test.go @@ -0,0 +1,184 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package integrations + +import ( + "fmt" + "net/http" + "testing" + + //"code.gitea.io/gitea/models" + //"code.gitea.io/gitea/models/db" + api "code.gitea.io/gitea/modules/structs" + wiki_service "code.gitea.io/gitea/services/wiki" + + "github.com/stretchr/testify/assert" +) + +func TestAPIGetWikiPage(t *testing.T) { + defer prepareTestEnv(t)() + + username := "user2" + session := loginUser(t, username) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Home", username, "repo1") + + req := NewRequest(t, "GET", urlStr) + resp := session.MakeRequest(t, req, http.StatusOK) + var page *api.WikiPage + DecodeJSON(t, resp, &page) + + assert.Equal(t, &api.WikiPage{ + PageMeta: &api.PageMeta{ + Name: "Home", + SubURL: "Home", + Updated: "2017-11-26T20:31:18-08:00", + }, + Title: "", + Content: "# Home page\n\nThis is the home page!\n", + CommitCount: 1, + LastCommit: &api.WikiCommit{ + ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-26T20:31:18-08:00", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-26T20:31:18-08:00", + }, + Message: "Add Home.md\n", + }, + Sidebar: "", + Footer: "", + }, page) +} + +func TestAPIGetWikiPages(t *testing.T) { + defer prepareTestEnv(t)() + + username := "user2" + session := loginUser(t, username) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/pages", username, "repo1") + + req := NewRequest(t, "GET", urlStr) + resp := session.MakeRequest(t, req, http.StatusOK) + + var meta []*api.PageMeta + DecodeJSON(t, resp, &meta) + + dummymeta := []*api.PageMeta{ + &api.PageMeta{ + Name: "Home", + SubURL: "Home", + Updated: "2017-11-26T20:31:18-08:00", + }, + &api.PageMeta{ + Name: "Page With Image", + SubURL: "Page-With-Image", + Updated: "2019-01-24T20:41:55-05:00", + }, + &api.PageMeta{ + Name: "Page With Spaced Name", + SubURL: "Page-With-Spaced-Name", + Updated: "2019-01-24T20:39:51-05:00", + }, + &api.PageMeta{ + Name: "Unescaped File", + SubURL: "Unescaped-File", + Updated: "2021-07-19T18:42:46+02:00", + }, + } + + assert.Equal(t, dummymeta, meta) +} + +func TestAPINewWiki(t *testing.T) { + for _, title := range []string{ + "New page", + "&&&&", + } { + defer prepareTestEnv(t)() + username := "user2" + session := loginUser(t, username) + token := getTokenForLoggedInUser(t, session) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new?token=%s", username, "repo1", token) + + req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{ + Title: title, + Content: "Wiki page content for API unit tests", + Message: "", + }) + session.MakeRequest(t, req, http.StatusNoContent) + + urlStrGet := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/%s", username, "repo1", wiki_service.NormalizeWikiName(title)) + reqGet := NewRequest(t, "GET", urlStrGet) + session.MakeRequest(t, reqGet, http.StatusOK) + } +} + +func TestAPIEditWiki(t *testing.T) { + defer prepareTestEnv(t)() + username := "user2" + session := loginUser(t, username) + token := getTokenForLoggedInUser(t, session) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name?token=%s", username, "repo1", token) + + req := NewRequestWithJSON(t, "PATCH", urlStr, &api.CreateWikiPageOptions{ + Title: "edited title", + Content: "Edited wiki page content for API unit tests", + Message: "", + }) + session.MakeRequest(t, req, http.StatusNoContent) +} + +func TestAPIWikiRevisions(t *testing.T) { + defer prepareTestEnv(t)() + username := "user2" + session := loginUser(t, username) + + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/revisions/Home", username, "repo1") + + req := NewRequest(t, "GET", urlStr) + resp := session.MakeRequest(t, req, http.StatusOK) + + var revisions *api.WikiCommitList + DecodeJSON(t, resp, &revisions) + + dummyrevisions := &api.WikiCommitList{ + WikiCommits: []*api.WikiCommit{ + { + ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-26T20:31:18-08:00", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-26T20:31:18-08:00", + }, + Message: "Add Home.md\n", + }, + }, + Count: 1, + } + + assert.Equal(t, dummyrevisions, revisions) +} From 06bb4cf7ca79476c0c52624719f6f5105dbbcb49 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:35:57 +0200 Subject: [PATCH 08/45] fmt --- integrations/api_wiki_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index ddcf8218e109..fa8f337306ad 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -77,22 +77,22 @@ func TestAPIGetWikiPages(t *testing.T) { DecodeJSON(t, resp, &meta) dummymeta := []*api.PageMeta{ - &api.PageMeta{ + { Name: "Home", SubURL: "Home", Updated: "2017-11-26T20:31:18-08:00", }, - &api.PageMeta{ + { Name: "Page With Image", SubURL: "Page-With-Image", Updated: "2019-01-24T20:41:55-05:00", }, - &api.PageMeta{ + { Name: "Page With Spaced Name", SubURL: "Page-With-Spaced-Name", Updated: "2019-01-24T20:39:51-05:00", }, - &api.PageMeta{ + { Name: "Unescaped File", SubURL: "Unescaped-File", Updated: "2021-07-19T18:42:46+02:00", From c908b691eb7c4b31968b9330151d9aec53758b61 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:40:07 +0200 Subject: [PATCH 09/45] Update func names --- routers/api/v1/api.go | 6 +++--- routers/api/v1/repo/wiki.go | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 00fa0c5691d5..f0b5df8956c7 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -800,11 +800,11 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { }, mustEnableIssues, reqToken()) m.Group("/wiki", func() { m.Combo("/page/{pageName}"). - Get(mustEnableWiki, repo.Wiki). - Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWiki). + Get(mustEnableWiki, repo.GetWikiPage). + Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage). Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) m.Get("/revisions/{pageName}", mustEnableWiki, repo.WikiRevision) - m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWiki) + m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage) m.Get("/pages", mustEnableWiki, repo.WikiPages) }) m.Group("/issues", func() { diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 91d08137ad0c..479097cd8d5a 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -21,7 +21,7 @@ import ( ) // NewWiki response for wiki create request -func NewWiki(ctx *context.APIContext) { +func NewWikiPage(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/wiki/new repository repoCreateWikiPage // --- // summary: Create a wiki page @@ -78,7 +78,7 @@ func NewWiki(ctx *context.APIContext) { } // EditWiki response for wiki modify request -func EditWiki(ctx *context.APIContext) { +func EditWikiPage(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/wiki/page/{pageName} repository repoEditWikiPage // --- // summary: Edit a wiki page @@ -261,7 +261,7 @@ func WikiPages(ctx *context.APIContext) { } // Wiki get single wiki page -func Wiki(ctx *context.APIContext) { +func GetWikiPage(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/page/{pageName} repository repoGetWikiPage // --- // summary: Get a wiki page From d3ef69c5bd1db3b834eca037765aa450f0800975 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:44:17 +0200 Subject: [PATCH 10/45] Update error handling --- routers/api/v1/repo/wiki.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 479097cd8d5a..bbc5a0a587a5 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -292,7 +292,9 @@ func GetWikiPage(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - if !git.IsErrNotExist(err) { + if git.IsErrNotExist(err) { + ctx.NotFound(http.StatusInternalServerError, "GetBranchCommit", err) + } else { ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) } return @@ -399,7 +401,9 @@ func WikiRevision(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - if !git.IsErrNotExist(err) { + if git.IsErrNotExist(err) { + ctx.NotFound() + } else { ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) } return @@ -440,7 +444,7 @@ func WikiRevision(ctx *context.APIContext) { // findEntryForFile finds the tree entry for a target filepath. func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) { entry, err := commit.GetTreeEntryByPath(target) - if err != nil && !git.IsErrNotExist(err) { + if err != nil { return nil, err } if entry != nil { @@ -491,7 +495,7 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte { func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) { pageFilename := wiki_service.NameToFilename(wikiName) entry, err := findEntryForFile(commit, pageFilename) - if err != nil && !git.IsErrNotExist(err) { + if err != nil { ctx.Error(http.StatusInternalServerError, "findEntryForFile", err) return nil, nil, "", false } else if entry == nil { From 53f82fa897f92c26ee1acc97258a8977cf73e77c Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:50:42 +0200 Subject: [PATCH 11/45] Update type name --- integrations/api_wiki_test.go | 6 ++--- modules/structs/repo_wiki.go | 6 ++--- routers/api/v1/repo/wiki.go | 6 ++--- routers/api/v1/swagger/repo.go | 2 +- templates/swagger/v1_json.tmpl | 40 +++++++++++++++++----------------- 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index fa8f337306ad..85149644c101 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -31,7 +31,7 @@ func TestAPIGetWikiPage(t *testing.T) { DecodeJSON(t, resp, &page) assert.Equal(t, &api.WikiPage{ - PageMeta: &api.PageMeta{ + WikiPageMetaData: &api.WikiPageMetaData{ Name: "Home", SubURL: "Home", Updated: "2017-11-26T20:31:18-08:00", @@ -73,10 +73,10 @@ func TestAPIGetWikiPages(t *testing.T) { req := NewRequest(t, "GET", urlStr) resp := session.MakeRequest(t, req, http.StatusOK) - var meta []*api.PageMeta + var meta []*api.WikiPageMetaData DecodeJSON(t, resp, &meta) - dummymeta := []*api.PageMeta{ + dummymeta := []*api.WikiPageMetaData{ { Name: "Home", SubURL: "Home", diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index ac31c9c0dc79..29de0554004c 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -14,7 +14,7 @@ type WikiCommit struct { // WikiPage a wiki page type WikiPage struct { - *PageMeta + *WikiPageMetaData Title string `json:"title"` Content string `json:"content"` CommitCount int64 `json:"commit_count"` @@ -23,8 +23,8 @@ type WikiPage struct { Footer string `json:"footer"` } -// PageMeta wiki page meta information -type PageMeta struct { +// WikiPageMetaData wiki page meta information +type WikiPageMetaData struct { Name string `json:"name"` SubURL string `json:"suburl"` Updated string `json:"updated"` diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index bbc5a0a587a5..fd3892421a70 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -232,7 +232,7 @@ func WikiPages(ctx *context.APIContext) { ctx.ServerError("ListEntries", err) return } - pages := make([]api.PageMeta, 0, len(entries)) + pages := make([]api.WikiPageMetaData, 0, len(entries)) for i, entry := range entries { if i < skip || i >= max || !entry.IsRegular() { continue @@ -250,7 +250,7 @@ func WikiPages(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) return } - pages = append(pages, api.PageMeta{ + pages = append(pages, api.WikiPageMetaData{ Name: wikiName, SubURL: wiki_service.NameToSubURL(wikiName), Updated: c.Author.When.Format(time.RFC3339), @@ -350,7 +350,7 @@ func GetWikiPage(ctx *context.APIContext) { } wikiPage := &api.WikiPage{ - PageMeta: &api.PageMeta{ + WikiPageMetaData: &api.WikiPageMetaData{ Name: pageName, SubURL: wiki_service.NameToSubURL(pageName), Updated: lastCommit.Author.When.Format(time.RFC3339), diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go index e9cac44e0538..40aeca677de8 100644 --- a/routers/api/v1/swagger/repo.go +++ b/routers/api/v1/swagger/repo.go @@ -328,7 +328,7 @@ type swaggerCombinedStatus struct { // swagger:response WikiPageList type swaggerWikiPageList struct { // in:body - Body []api.PageMeta `json:"body"` + Body []api.WikiPageMetaData `json:"body"` } // WikiPage diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d57084542896..d1603f0515ec 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -16186,25 +16186,6 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, - "PageMeta": { - "description": "PageMeta wiki page meta information", - "type": "object", - "properties": { - "name": { - "type": "string", - "x-go-name": "Name" - }, - "suburl": { - "type": "string", - "x-go-name": "SubURL" - }, - "updated": { - "type": "string", - "x-go-name": "Updated" - } - }, - "x-go-package": "code.gitea.io/gitea/modules/structs" - }, "PayloadCommit": { "description": "PayloadCommit represents a commit", "type": "object", @@ -17694,6 +17675,25 @@ } }, "x-go-package": "code.gitea.io/gitea/modules/structs" + }, + "WikiPageMetaData": { + "description": "WikiPageMetaData wiki page meta information", + "type": "object", + "properties": { + "name": { + "type": "string", + "x-go-name": "Name" + }, + "suburl": { + "type": "string", + "x-go-name": "SubURL" + }, + "updated": { + "type": "string", + "x-go-name": "Updated" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" } }, "responses": { @@ -18398,7 +18398,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/definitions/PageMeta" + "$ref": "#/definitions/WikiPageMetaData" } } }, From 8600b8702383426c2c353872bed7c7f579fe428d Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:51:23 +0200 Subject: [PATCH 12/45] Fix lint --- routers/api/v1/repo/wiki.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index fd3892421a70..a6e24640ce2d 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -20,7 +20,7 @@ import ( wiki_service "code.gitea.io/gitea/services/wiki" ) -// NewWiki response for wiki create request +// NewWikiPage response for wiki create request func NewWikiPage(ctx *context.APIContext) { // swagger:operation POST /repos/{owner}/{repo}/wiki/new repository repoCreateWikiPage // --- @@ -77,7 +77,7 @@ func NewWikiPage(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } -// EditWiki response for wiki modify request +// EditWikiPage response for wiki modify request func EditWikiPage(ctx *context.APIContext) { // swagger:operation PATCH /repos/{owner}/{repo}/wiki/page/{pageName} repository repoEditWikiPage // --- @@ -260,7 +260,7 @@ func WikiPages(ctx *context.APIContext) { ctx.JSON(http.StatusOK, pages) } -// Wiki get single wiki page +// GetWikiPage get single wiki page func GetWikiPage(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/page/{pageName} repository repoGetWikiPage // --- From ceabfd7725d0f9866204152865c5d19ff12cdbaf Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:54:08 +0200 Subject: [PATCH 13/45] Don't delete Home --- routers/api/v1/repo/wiki.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index a6e24640ce2d..c310b297c106 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -160,7 +160,8 @@ func DeleteWikiPage(ctx *context.APIContext) { wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) if len(wikiName) == 0 { - wikiName = "Home" + ctx.Status(http.StatusBadRequest) + return } if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { From 23f647543079da0f64510085f0bd2b5ddfe06826 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 14:54:36 +0200 Subject: [PATCH 14/45] Update func name --- routers/api/v1/api.go | 2 +- routers/api/v1/repo/wiki.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index f0b5df8956c7..e7469d9242d6 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -805,7 +805,7 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) m.Get("/revisions/{pageName}", mustEnableWiki, repo.WikiRevision) m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage) - m.Get("/pages", mustEnableWiki, repo.WikiPages) + m.Get("/pages", mustEnableWiki, repo.ListWikiPages) }) m.Group("/issues", func() { m.Combo("").Get(repo.ListIssues). diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index c310b297c106..e8af0c5b2f0b 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -173,7 +173,7 @@ func DeleteWikiPage(ctx *context.APIContext) { } // WikiPages get wiki pages list -func WikiPages(ctx *context.APIContext) { +func ListWikiPages(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/pages repository repoGetWikiPages // --- // summary: Get all wiki pages From 77e42d589ba47d6230e21c13f347466db55c4040 Mon Sep 17 00:00:00 2001 From: qwerty287 <80460567+qwerty287@users.noreply.github.com> Date: Sat, 9 Oct 2021 14:57:51 +0200 Subject: [PATCH 15/45] Update routers/api/v1/repo/wiki.go Co-authored-by: delvh --- routers/api/v1/repo/wiki.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index e8af0c5b2f0b..b9e6ca62a4c5 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -209,11 +209,9 @@ func ListWikiPages(ctx *context.APIContext) { } return } - defer func() { - if wikiRepo != nil { - wikiRepo.Close() - } - }() + if wikiRepo != nil { + defer wikiRepo.Close() + } page := ctx.FormInt("page") if page <= 1 { From cfa63035763aec2c7162f7e46ae0a8e3cf6061c4 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 15:01:50 +0200 Subject: [PATCH 16/45] Remove unnecessary check --- routers/api/v1/repo/wiki.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index b9e6ca62a4c5..6c2048fdb596 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -301,9 +301,6 @@ func GetWikiPage(ctx *context.APIContext) { // get requested pagename pageName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) - if len(pageName) == 0 { - pageName = "Home" - } //lookup filename in wiki - get filecontent, gitTree entry , real filename data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) From 63ea38e530aa424efb7530fbb169835383b234e8 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 15:02:41 +0200 Subject: [PATCH 17/45] Fix lint --- routers/api/v1/repo/wiki.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 6c2048fdb596..df8d9620d62e 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -172,7 +172,7 @@ func DeleteWikiPage(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } -// WikiPages get wiki pages list +// ListWikiPages get wiki pages list func ListWikiPages(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/pages repository repoGetWikiPages // --- From 8d568a448e1d11d8373650d2442f28f776fa17da Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 18:11:49 +0200 Subject: [PATCH 18/45] Use English strings --- routers/api/v1/repo/wiki.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index df8d9620d62e..27955fa72119 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -5,6 +5,7 @@ package repo import ( + "fmt" "io" "net/http" "net/url" @@ -60,7 +61,7 @@ func NewWikiPage(ctx *context.APIContext) { wikiName := wiki_service.NormalizeWikiName(form.Title) if len(form.Message) == 0 { - form.Message = ctx.Tr("repo.editor.add", form.Title) + form.Message = fmt.Sprintf("Add '%s'", form.Title) } if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { @@ -118,7 +119,7 @@ func EditWikiPage(ctx *context.APIContext) { newWikiName := wiki_service.NormalizeWikiName(form.Title) if len(form.Message) == 0 { - form.Message = ctx.Tr("repo.editor.update", form.Title) + form.Message = fmt.Sprintf("Update '%s'", form.Title) } if len(newWikiName) == 0 { From bfbe3ac0fc23f444e0b67f3cf60288009bcb6ef9 Mon Sep 17 00:00:00 2001 From: qwerty287 <80460567+qwerty287@users.noreply.github.com> Date: Sat, 9 Oct 2021 18:14:32 +0200 Subject: [PATCH 19/45] Update integrations/api_wiki_test.go Co-authored-by: delvh --- integrations/api_wiki_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index 85149644c101..0fdc26927551 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -9,8 +9,6 @@ import ( "net/http" "testing" - //"code.gitea.io/gitea/models" - //"code.gitea.io/gitea/models/db" api "code.gitea.io/gitea/modules/structs" wiki_service "code.gitea.io/gitea/services/wiki" From 65d1951c47962392d2c53eff5dd17dc2689d9bff Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 18:16:45 +0200 Subject: [PATCH 20/45] Update func and test names --- integrations/api_wiki_test.go | 8 ++++---- routers/api/v1/api.go | 2 +- routers/api/v1/repo/wiki.go | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index 0fdc26927551..a50cca40ce53 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -60,7 +60,7 @@ func TestAPIGetWikiPage(t *testing.T) { }, page) } -func TestAPIGetWikiPages(t *testing.T) { +func TestAPIListWikiPages(t *testing.T) { defer prepareTestEnv(t)() username := "user2" @@ -100,7 +100,7 @@ func TestAPIGetWikiPages(t *testing.T) { assert.Equal(t, dummymeta, meta) } -func TestAPINewWiki(t *testing.T) { +func TestAPINewWikiPage(t *testing.T) { for _, title := range []string{ "New page", "&&&&", @@ -125,7 +125,7 @@ func TestAPINewWiki(t *testing.T) { } } -func TestAPIEditWiki(t *testing.T) { +func TestAPIEditWikiPage(t *testing.T) { defer prepareTestEnv(t)() username := "user2" session := loginUser(t, username) @@ -141,7 +141,7 @@ func TestAPIEditWiki(t *testing.T) { session.MakeRequest(t, req, http.StatusNoContent) } -func TestAPIWikiRevisions(t *testing.T) { +func TestAPIListPageRevisions(t *testing.T) { defer prepareTestEnv(t)() username := "user2" session := loginUser(t, username) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e7469d9242d6..f9adb45a0557 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -803,7 +803,7 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { Get(mustEnableWiki, repo.GetWikiPage). Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage). Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) - m.Get("/revisions/{pageName}", mustEnableWiki, repo.WikiRevision) + m.Get("/revisions/{pageName}", mustEnableWiki, repo.ListPageRevisions) m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage) m.Get("/pages", mustEnableWiki, repo.ListWikiPages) }) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 27955fa72119..9ec8e1379b8b 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -118,14 +118,14 @@ func EditWikiPage(ctx *context.APIContext) { oldWikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) newWikiName := wiki_service.NormalizeWikiName(form.Title) - if len(form.Message) == 0 { - form.Message = fmt.Sprintf("Update '%s'", form.Title) - } - if len(newWikiName) == 0 { newWikiName = oldWikiName } + if len(form.Message) == 0 { + form.Message = fmt.Sprintf("Update '%s'", newWikiName) + } + if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { ctx.Error(http.StatusInternalServerError, "EditWikiPage", err) return @@ -363,7 +363,7 @@ func GetWikiPage(ctx *context.APIContext) { } // WikiRevision renders file revision list of wiki page -func WikiRevision(ctx *context.APIContext) { +func ListPageRevisions(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/revisions/{pageName} repository repoGetWikiPageRevisions // --- // summary: Get revisions of a wiki page From 3027d3f326c645eebb53885d24c88f98cecd005f Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 18:30:37 +0200 Subject: [PATCH 21/45] Remove unsed check and avoid duplicated error reports --- routers/api/v1/repo/wiki.go | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 9ec8e1379b8b..d9925595acd4 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -160,10 +160,6 @@ func DeleteWikiPage(ctx *context.APIContext) { // "$ref": "#/responses/empty" wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) - if len(wikiName) == 0 { - ctx.Status(http.StatusBadRequest) - return - } if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteWikiPage", err) @@ -292,10 +288,12 @@ func GetWikiPage(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - if git.IsErrNotExist(err) { - ctx.NotFound(http.StatusInternalServerError, "GetBranchCommit", err) - } else { - ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + if !ctx.Written() { + if git.IsErrNotExist(err) { + ctx.NotFound(http.StatusInternalServerError, "GetBranchCommit", err) + } else { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } } return } @@ -305,15 +303,17 @@ func GetWikiPage(ctx *context.APIContext) { //lookup filename in wiki - get filecontent, gitTree entry , real filename data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) - if noEntry { + if noEntry && !ctx.Written() { ctx.NotFound() return } - if entry == nil || ctx.Written() { + if entry == nil { if wikiRepo != nil { wikiRepo.Close() } - ctx.NotFound() + if !ctx.Written() { + ctx.NotFound() + } return } @@ -322,7 +322,6 @@ func GetWikiPage(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - ctx.NotFound() return } @@ -331,7 +330,6 @@ func GetWikiPage(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - ctx.NotFound() return } @@ -398,10 +396,12 @@ func ListPageRevisions(ctx *context.APIContext) { if wikiRepo != nil { wikiRepo.Close() } - if git.IsErrNotExist(err) { - ctx.NotFound() - } else { - ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + if !ctx.Written() { + if git.IsErrNotExist(err) { + ctx.NotFound() + } else { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } } return } @@ -414,7 +414,7 @@ func ListPageRevisions(ctx *context.APIContext) { //lookup filename in wiki - get filecontent, gitTree entry , real filename _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) - if noEntry { + if noEntry && !ctx.Written() { ctx.NotFound() } From fc8443aaec4c73f3925a8866045f1444995e4b1c Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 9 Oct 2021 18:38:26 +0200 Subject: [PATCH 22/45] Improve error handling --- routers/api/v1/repo/wiki.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index d9925595acd4..af9726a77143 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -290,7 +290,7 @@ func GetWikiPage(ctx *context.APIContext) { } if !ctx.Written() { if git.IsErrNotExist(err) { - ctx.NotFound(http.StatusInternalServerError, "GetBranchCommit", err) + ctx.NotFound(err) } else { ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) } @@ -302,7 +302,7 @@ func GetWikiPage(ctx *context.APIContext) { pageName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) //lookup filename in wiki - get filecontent, gitTree entry , real filename - data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName, false) if noEntry && !ctx.Written() { ctx.NotFound() return @@ -317,7 +317,7 @@ func GetWikiPage(ctx *context.APIContext) { return } - sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar") + sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) if ctx.Written() { if wikiRepo != nil { wikiRepo.Close() @@ -325,7 +325,7 @@ func GetWikiPage(ctx *context.APIContext) { return } - footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer") + footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer", true) if ctx.Written() { if wikiRepo != nil { wikiRepo.Close() @@ -398,7 +398,7 @@ func ListPageRevisions(ctx *context.APIContext) { } if !ctx.Written() { if git.IsErrNotExist(err) { - ctx.NotFound() + ctx.NotFound(err) } else { ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) } @@ -413,7 +413,7 @@ func ListPageRevisions(ctx *context.APIContext) { } //lookup filename in wiki - get filecontent, gitTree entry , real filename - _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName) + _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName, false) if noEntry && !ctx.Written() { ctx.NotFound() } @@ -489,11 +489,13 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte { // wikiContentsByName returns the contents of a wiki page, along with a boolean // indicating whether the page exists. Writes to ctx if an error occurs. -func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string) ([]byte, *git.TreeEntry, string, bool) { +func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string, isSidebarOrFooter bool) ([]byte, *git.TreeEntry, string, bool) { pageFilename := wiki_service.NameToFilename(wikiName) entry, err := findEntryForFile(commit, pageFilename) if err != nil { - ctx.Error(http.StatusInternalServerError, "findEntryForFile", err) + if !isSidebarOrFooter { + ctx.NotFound(err) + } return nil, nil, "", false } else if entry == nil { return nil, nil, "", true From 1ea3fe118a62c3a3ff4f3d6d9a17f0cee66fa958 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 12:52:52 +0200 Subject: [PATCH 23/45] Return after error --- routers/api/v1/repo/wiki.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index af9726a77143..a86e75ca5681 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -414,8 +414,11 @@ func ListPageRevisions(ctx *context.APIContext) { //lookup filename in wiki - get filecontent, gitTree entry , real filename _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName, false) - if noEntry && !ctx.Written() { - ctx.NotFound() + if noEntry { + if !ctx.Written() { + ctx.NotFound() + } + return } // get commit count - wiki revisions @@ -433,6 +436,7 @@ func ListPageRevisions(ctx *context.APIContext) { wikiRepo.Close() } ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRangeNoFollow", err) + return } ctx.JSON(http.StatusOK, convert.ToWikiCommitList(commitsHistory, commitsCount)) From eefb617ab1095eb855fe12345e399562673963ec Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 13:49:13 +0200 Subject: [PATCH 24/45] Document 404 error --- routers/api/v1/repo/wiki.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index a86e75ca5681..adfd2d867c60 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -282,6 +282,8 @@ func GetWikiPage(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/WikiPage" + // "404": + // "$ref": "#/responses/notFound" wikiRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { @@ -390,6 +392,8 @@ func ListPageRevisions(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/WikiCommitList" + // "404": + // "$ref": "#/responses/notFound" wikiRepo, commit, err := findWikiRepoCommit(ctx) if err != nil { From b0ef9699f6bb393a72ddd3f5bff4a189d22685c0 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 13:49:50 +0200 Subject: [PATCH 25/45] Update swagger --- templates/swagger/v1_json.tmpl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d1603f0515ec..1bdde4591239 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -9971,6 +9971,9 @@ "responses": { "201": { "$ref": "#/responses/WikiPage" + }, + "404": { + "$ref": "#/responses/notFound" } } }, @@ -10148,6 +10151,9 @@ "responses": { "201": { "$ref": "#/responses/WikiCommitList" + }, + "404": { + "$ref": "#/responses/notFound" } } } From fd76be311ee1d50cc8889e519888e8efaf5c0f53 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 14:40:50 +0200 Subject: [PATCH 26/45] Fix lint --- routers/api/v1/repo/wiki.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index adfd2d867c60..9117e8ff411a 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -362,7 +362,7 @@ func GetWikiPage(ctx *context.APIContext) { ctx.JSON(http.StatusOK, wikiPage) } -// WikiRevision renders file revision list of wiki page +// ListPageRevisions renders file revision list of wiki page func ListPageRevisions(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/wiki/revisions/{pageName} repository repoGetWikiPageRevisions // --- From 7d04627fc093c6274881b19de854a309bfbb6f5e Mon Sep 17 00:00:00 2001 From: qwerty287 <80460567+qwerty287@users.noreply.github.com> Date: Sun, 10 Oct 2021 14:48:01 +0200 Subject: [PATCH 27/45] Apply suggestions from code review Co-authored-by: delvh --- routers/api/v1/repo/wiki.go | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 9117e8ff411a..74722d12418d 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -200,15 +200,13 @@ func ListWikiPages(ctx *context.APIContext) { // "$ref": "#/responses/WikiPageList" wikiRepo, commit, err := findWikiRepoCommit(ctx) - if err != nil { - if wikiRepo != nil { - wikiRepo.Close() - } - return - } if wikiRepo != nil { defer wikiRepo.Close() } + if err != nil { + ctx.Error(http.StatusInternalServerError, "findWikiRepoCommit", err) + return + } page := ctx.FormInt("page") if page <= 1 { @@ -286,10 +284,10 @@ func GetWikiPage(ctx *context.APIContext) { // "$ref": "#/responses/notFound" wikiRepo, commit, err := findWikiRepoCommit(ctx) + if wikiRepo != nil { + defer wikiRepo.Close() + } if err != nil { - if wikiRepo != nil { - wikiRepo.Close() - } if !ctx.Written() { if git.IsErrNotExist(err) { ctx.NotFound(err) @@ -310,9 +308,6 @@ func GetWikiPage(ctx *context.APIContext) { return } if entry == nil { - if wikiRepo != nil { - wikiRepo.Close() - } if !ctx.Written() { ctx.NotFound() } @@ -321,17 +316,11 @@ func GetWikiPage(ctx *context.APIContext) { sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) if ctx.Written() { - if wikiRepo != nil { - wikiRepo.Close() - } return } footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer", true) if ctx.Written() { - if wikiRepo != nil { - wikiRepo.Close() - } return } @@ -396,10 +385,10 @@ func ListPageRevisions(ctx *context.APIContext) { // "$ref": "#/responses/notFound" wikiRepo, commit, err := findWikiRepoCommit(ctx) + if wikiRepo != nil { + defer wikiRepo.Close() + } if err != nil { - if wikiRepo != nil { - wikiRepo.Close() - } if !ctx.Written() { if git.IsErrNotExist(err) { ctx.NotFound(err) @@ -436,9 +425,6 @@ func ListPageRevisions(ctx *context.APIContext) { // get Commit Count commitsHistory, err := wikiRepo.CommitsByFileAndRangeNoFollow("master", pageFilename, page) if err != nil { - if wikiRepo != nil { - wikiRepo.Close() - } ctx.Error(http.StatusInternalServerError, "CommitsByFileAndRangeNoFollow", err) return } From f9455bcd2f289a461045c6a39e6802707ad238a4 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 14:57:17 +0200 Subject: [PATCH 28/45] Document file encoding --- modules/structs/repo_wiki.go | 1 + templates/swagger/v1_json.tmpl | 1 + 2 files changed, 2 insertions(+) diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index 29de0554004c..fa74ac113f8d 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -33,6 +33,7 @@ type WikiPageMetaData struct { // CreateWikiPageOptions form for creating wiki type CreateWikiPageOptions struct { Title string `json:"title"` + // content must be UTF-8 encoded Content string `json:"content"` Message string `json:"message"` } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 1bdde4591239..71bc6a872e03 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -13901,6 +13901,7 @@ "type": "object", "properties": { "content": { + "description": "content must be UTF-8 encoded", "type": "string", "x-go-name": "Content" }, From e642b2b6564986d5d98866a318ed527230ec0ff2 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sun, 10 Oct 2021 15:06:02 +0200 Subject: [PATCH 29/45] fmt --- modules/structs/repo_wiki.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index fa74ac113f8d..480308a547e1 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -32,7 +32,7 @@ type WikiPageMetaData struct { // CreateWikiPageOptions form for creating wiki type CreateWikiPageOptions struct { - Title string `json:"title"` + Title string `json:"title"` // content must be UTF-8 encoded Content string `json:"content"` Message string `json:"message"` From ecc7ba6836c8b5648ab749d826fdd94c6d2c0fd9 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Mon, 18 Oct 2021 09:15:13 +0200 Subject: [PATCH 30/45] Apply suggestions --- routers/api/v1/repo/wiki.go | 169 +++++++++++++++++++-------------- templates/swagger/v1_json.tmpl | 23 +++-- 2 files changed, 114 insertions(+), 78 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 74722d12418d..f5da1b5de259 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -44,8 +44,8 @@ func NewWikiPage(ctx *context.APIContext) { // schema: // "$ref": "#/definitions/CreateWikiPageOptions" // responses: - // "204": - // "$ref": "#/responses/empty" + // "201": + // "$ref": "#/responses/WikiPage" // "400": // "$ref": "#/responses/error" // "403": @@ -75,7 +75,11 @@ func NewWikiPage(ctx *context.APIContext) { return } - ctx.Status(http.StatusNoContent) + wikiPage := getWikiPage(ctx, wikiName) + + if !ctx.Written() { + ctx.JSON(http.StatusCreated, wikiPage) + } } // EditWikiPage response for wiki modify request @@ -106,8 +110,8 @@ func EditWikiPage(ctx *context.APIContext) { // schema: // "$ref": "#/definitions/CreateWikiPageOptions" // responses: - // "204": - // "$ref": "#/responses/empty" + // "200": + // "$ref": "#/responses/WikiPage" // "400": // "$ref": "#/responses/error" // "403": @@ -131,7 +135,79 @@ func EditWikiPage(ctx *context.APIContext) { return } - ctx.Status(http.StatusNoContent) + wikiPage := getWikiPage(ctx, newWikiName) + + if !ctx.Written() { + ctx.JSON(http.StatusOK, wikiPage) + } +} + +func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { + page = wiki_service.NormalizeWikiName(page) + + wikiRepo, commit, err := findWikiRepoCommit(ctx) + if wikiRepo != nil { + defer wikiRepo.Close() + } + if err != nil { + if !ctx.Written() { + if git.IsErrNotExist(err) { + ctx.NotFound(err) + } else { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } + } + return nil + } + + //lookup filename in wiki - get filecontent, gitTree entry , real filename + data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, page, false) + if noEntry && !ctx.Written() { + ctx.NotFound() + return nil + } + if entry == nil { + if !ctx.Written() { + ctx.NotFound() + } + return nil + } + + sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) + if ctx.Written() { + return nil + } + + footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer", true) + if ctx.Written() { + return nil + } + + // get commit count - wiki revisions + commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename) + + wikiPath := entry.Name() + // Get last change information. + lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetCommitByPath", err) + return nil + } + + wikiPage := &api.WikiPage{ + WikiPageMetaData: &api.WikiPageMetaData{ + Name: page, + SubURL: wiki_service.NameToSubURL(page), + Updated: lastCommit.Author.When.Format(time.RFC3339), + }, + Content: string(data), + CommitCount: commitsCount, + LastCommit: convert.ToWikiCommit(lastCommit), + Sidebar: string(sidebarContent), + Footer: string(footerContent), + } + + return wikiPage } // DeleteWikiPage delete wiki page @@ -158,10 +234,18 @@ func DeleteWikiPage(ctx *context.APIContext) { // responses: // "204": // "$ref": "#/responses/empty" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" wikiName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) if err := wiki_service.DeleteWikiPage(ctx.User, ctx.Repo.Repository, wikiName); err != nil { + if err.Error() == "file does not exist" { + ctx.NotFound(err) + return + } ctx.Error(http.StatusInternalServerError, "DeleteWikiPage", err) return } @@ -196,8 +280,10 @@ func ListWikiPages(ctx *context.APIContext) { // description: page size of results // type: integer // responses: - // "201": + // "200": // "$ref": "#/responses/WikiPageList" + // "404": + // "$ref": "#/responses/notFound" wikiRepo, commit, err := findWikiRepoCommit(ctx) if wikiRepo != nil { @@ -278,77 +364,18 @@ func GetWikiPage(ctx *context.APIContext) { // type: string // required: true // responses: - // "201": + // "200": // "$ref": "#/responses/WikiPage" // "404": // "$ref": "#/responses/notFound" - wikiRepo, commit, err := findWikiRepoCommit(ctx) - if wikiRepo != nil { - defer wikiRepo.Close() - } - if err != nil { - if !ctx.Written() { - if git.IsErrNotExist(err) { - ctx.NotFound(err) - } else { - ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) - } - } - return - } - // get requested pagename pageName := wiki_service.NormalizeWikiName(ctx.Params(":pageName")) - //lookup filename in wiki - get filecontent, gitTree entry , real filename - data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName, false) - if noEntry && !ctx.Written() { - ctx.NotFound() - return - } - if entry == nil { - if !ctx.Written() { - ctx.NotFound() - } - return - } - - sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) - if ctx.Written() { - return - } - - footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer", true) - if ctx.Written() { - return - } - - // get commit count - wiki revisions - commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename) - - wikiPath := entry.Name() - // Get last change information. - lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) - if err != nil { - ctx.Error(http.StatusInternalServerError, "GetCommitByPath", err) - return - } - - wikiPage := &api.WikiPage{ - WikiPageMetaData: &api.WikiPageMetaData{ - Name: pageName, - SubURL: wiki_service.NameToSubURL(pageName), - Updated: lastCommit.Author.When.Format(time.RFC3339), - }, - Content: string(data), - CommitCount: commitsCount, - LastCommit: convert.ToWikiCommit(lastCommit), - Sidebar: string(sidebarContent), - Footer: string(footerContent), + wikiPage := getWikiPage(ctx, pageName) + if !ctx.Written() { + ctx.JSON(http.StatusOK, wikiPage) } - - ctx.JSON(http.StatusOK, wikiPage) } // ListPageRevisions renders file revision list of wiki page @@ -379,7 +406,7 @@ func ListPageRevisions(ctx *context.APIContext) { // description: page number of results to return (1-based) // type: integer // responses: - // "201": + // "200": // "$ref": "#/responses/WikiCommitList" // "404": // "$ref": "#/responses/notFound" diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index a6210bd7684b..8dbbdcc7b0cc 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -9923,8 +9923,8 @@ } ], "responses": { - "204": { - "$ref": "#/responses/empty" + "201": { + "$ref": "#/responses/WikiPage" }, "400": { "$ref": "#/responses/error" @@ -9969,7 +9969,7 @@ } ], "responses": { - "201": { + "200": { "$ref": "#/responses/WikiPage" }, "404": { @@ -10009,6 +10009,12 @@ "responses": { "204": { "$ref": "#/responses/empty" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "404": { + "$ref": "#/responses/notFound" } } }, @@ -10052,8 +10058,8 @@ } ], "responses": { - "204": { - "$ref": "#/responses/empty" + "200": { + "$ref": "#/responses/WikiPage" }, "400": { "$ref": "#/responses/error" @@ -10103,8 +10109,11 @@ } ], "responses": { - "201": { + "200": { "$ref": "#/responses/WikiPageList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -10149,7 +10158,7 @@ } ], "responses": { - "201": { + "200": { "$ref": "#/responses/WikiCommitList" }, "404": { From 34c6d719e6f63cc8f192e8e053b771445f03c984 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Mon, 18 Oct 2021 09:32:19 +0200 Subject: [PATCH 31/45] Use convert --- modules/convert/wiki.go | 26 ++++++++++++++++++++++++++ routers/api/v1/repo/wiki.go | 21 ++------------------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go index f59073d0c906..260e5e5612e5 100644 --- a/modules/convert/wiki.go +++ b/modules/convert/wiki.go @@ -9,6 +9,7 @@ import ( "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + wiki_service "code.gitea.io/gitea/services/wiki" ) // ToWikiCommit convert a git commit into a WikiCommit @@ -44,3 +45,28 @@ func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList { Count: count, } } + +// ToWikiPage converts different data to a WikiPage +func ToWikiPage(page string, lastCommit *git.Commit, commitsCount int64, data string, sidebarContent string, footerContent string) *api.WikiPage { + return &api.WikiPage{ + WikiPageMetaData: &api.WikiPageMetaData{ + Name: page, + SubURL: wiki_service.NameToSubURL(page), + Updated: lastCommit.Author.When.Format(time.RFC3339), + }, + Content: data, + CommitCount: commitsCount, + LastCommit: ToWikiCommit(lastCommit), + Sidebar: sidebarContent, + Footer: footerContent, + } +} + +// ToWikiPageMetaData converts meta information to a WikiPageMetaData +func ToWikiPageMetaData(page string, updated string) api.WikiPageMetaData { + return api.WikiPageMetaData{ + Name: page, + SubURL: wiki_service.NameToSubURL(page), + Updated: updated, + } +} diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index f5da1b5de259..28769247aa1d 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -194,20 +194,7 @@ func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { return nil } - wikiPage := &api.WikiPage{ - WikiPageMetaData: &api.WikiPageMetaData{ - Name: page, - SubURL: wiki_service.NameToSubURL(page), - Updated: lastCommit.Author.When.Format(time.RFC3339), - }, - Content: string(data), - CommitCount: commitsCount, - LastCommit: convert.ToWikiCommit(lastCommit), - Sidebar: string(sidebarContent), - Footer: string(footerContent), - } - - return wikiPage + return convert.ToWikiPage(page, lastCommit, commitsCount, string(data), string(sidebarContent), string(footerContent)) } // DeleteWikiPage delete wiki page @@ -330,11 +317,7 @@ func ListWikiPages(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) return } - pages = append(pages, api.WikiPageMetaData{ - Name: wikiName, - SubURL: wiki_service.NameToSubURL(wikiName), - Updated: c.Author.When.Format(time.RFC3339), - }) + pages = append(pages, convert.ToWikiPageMetaData(wikiName, c.Author.When.Format(time.RFC3339))) } ctx.JSON(http.StatusOK, pages) From be93b48a6e35d40df63b1550eb64a45fa9af443b Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Mon, 18 Oct 2021 13:13:12 +0200 Subject: [PATCH 32/45] Fix integration test --- integrations/api_wiki_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index a50cca40ce53..a43cfa108f25 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -10,7 +10,6 @@ import ( "testing" api "code.gitea.io/gitea/modules/structs" - wiki_service "code.gitea.io/gitea/services/wiki" "github.com/stretchr/testify/assert" ) @@ -117,11 +116,7 @@ func TestAPINewWikiPage(t *testing.T) { Content: "Wiki page content for API unit tests", Message: "", }) - session.MakeRequest(t, req, http.StatusNoContent) - - urlStrGet := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/%s", username, "repo1", wiki_service.NormalizeWikiName(title)) - reqGet := NewRequest(t, "GET", urlStrGet) - session.MakeRequest(t, reqGet, http.StatusOK) + session.MakeRequest(t, req, http.StatusCreated) } } @@ -138,7 +133,7 @@ func TestAPIEditWikiPage(t *testing.T) { Content: "Edited wiki page content for API unit tests", Message: "", }) - session.MakeRequest(t, req, http.StatusNoContent) + session.MakeRequest(t, req, http.StatusOK) } func TestAPIListPageRevisions(t *testing.T) { From 952beefc037d8926748f9546a53653df68593865 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 10:57:00 +0200 Subject: [PATCH 33/45] simplify permissions --- routers/api/v1/api.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 4624f1d49df0..70d7cb40f888 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -800,13 +800,13 @@ func Routes(sessioner func(http.Handler) http.Handler) *web.Route { }, mustEnableIssues, reqToken()) m.Group("/wiki", func() { m.Combo("/page/{pageName}"). - Get(mustEnableWiki, repo.GetWikiPage). - Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage). - Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), repo.DeleteWikiPage) - m.Get("/revisions/{pageName}", mustEnableWiki, repo.ListPageRevisions) - m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage) - m.Get("/pages", mustEnableWiki, repo.ListWikiPages) - }) + Get(repo.GetWikiPage). + Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage). + Delete(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), repo.DeleteWikiPage) + m.Get("/revisions/{pageName}", repo.ListPageRevisions) + m.Post("/new", mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), bind(api.CreateWikiPageOptions{}), repo.NewWikiPage) + m.Get("/pages", repo.ListWikiPages) + }, mustEnableWiki) m.Group("/issues", func() { m.Combo("").Get(repo.ListIssues). Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue) From 3b5d5ffed8c6995a21d145fd23fa22a89ee8851e Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 10:57:30 +0200 Subject: [PATCH 34/45] unify duplicate key Title/Name --- integrations/api_wiki_test.go | 11 +++++------ modules/convert/wiki.go | 4 ++-- modules/structs/repo_wiki.go | 5 +++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index a43cfa108f25..aba2686291c0 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -29,11 +29,10 @@ func TestAPIGetWikiPage(t *testing.T) { assert.Equal(t, &api.WikiPage{ WikiPageMetaData: &api.WikiPageMetaData{ - Name: "Home", + Title: "Home", SubURL: "Home", Updated: "2017-11-26T20:31:18-08:00", }, - Title: "", Content: "# Home page\n\nThis is the home page!\n", CommitCount: 1, LastCommit: &api.WikiCommit{ @@ -75,22 +74,22 @@ func TestAPIListWikiPages(t *testing.T) { dummymeta := []*api.WikiPageMetaData{ { - Name: "Home", + Title: "Home", SubURL: "Home", Updated: "2017-11-26T20:31:18-08:00", }, { - Name: "Page With Image", + Title: "Page With Image", SubURL: "Page-With-Image", Updated: "2019-01-24T20:41:55-05:00", }, { - Name: "Page With Spaced Name", + Title: "Page With Spaced Name", SubURL: "Page-With-Spaced-Name", Updated: "2019-01-24T20:39:51-05:00", }, { - Name: "Unescaped File", + Title: "Unescaped File", SubURL: "Unescaped-File", Updated: "2021-07-19T18:42:46+02:00", }, diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go index 260e5e5612e5..980190787a5c 100644 --- a/modules/convert/wiki.go +++ b/modules/convert/wiki.go @@ -50,7 +50,7 @@ func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList { func ToWikiPage(page string, lastCommit *git.Commit, commitsCount int64, data string, sidebarContent string, footerContent string) *api.WikiPage { return &api.WikiPage{ WikiPageMetaData: &api.WikiPageMetaData{ - Name: page, + Title: page, SubURL: wiki_service.NameToSubURL(page), Updated: lastCommit.Author.When.Format(time.RFC3339), }, @@ -65,7 +65,7 @@ func ToWikiPage(page string, lastCommit *git.Commit, commitsCount int64, data st // ToWikiPageMetaData converts meta information to a WikiPageMetaData func ToWikiPageMetaData(page string, updated string) api.WikiPageMetaData { return api.WikiPageMetaData{ - Name: page, + Title: page, SubURL: wiki_service.NameToSubURL(page), Updated: updated, } diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index 480308a547e1..eb03d7ddfa79 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -15,7 +15,6 @@ type WikiCommit struct { // WikiPage a wiki page type WikiPage struct { *WikiPageMetaData - Title string `json:"title"` Content string `json:"content"` CommitCount int64 `json:"commit_count"` LastCommit *WikiCommit `json:"last_commit"` @@ -25,16 +24,18 @@ type WikiPage struct { // WikiPageMetaData wiki page meta information type WikiPageMetaData struct { - Name string `json:"name"` + Title string `json:"title"` SubURL string `json:"suburl"` Updated string `json:"updated"` } // CreateWikiPageOptions form for creating wiki type CreateWikiPageOptions struct { + // page title. leave empty to keep unchanged Title string `json:"title"` // content must be UTF-8 encoded Content string `json:"content"` + // commit message summarizing the change Message string `json:"message"` } From 89bbcfaba02e165627455e24e94fc5f55bcb0073 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 11:36:30 +0200 Subject: [PATCH 35/45] improve types & return UTC timestamps --- modules/convert/wiki.go | 30 +++++++++++++----------------- modules/structs/repo_wiki.go | 8 +++++--- routers/api/v1/repo/wiki.go | 9 ++++----- 3 files changed, 22 insertions(+), 25 deletions(-) diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go index 980190787a5c..a22697bf9914 100644 --- a/modules/convert/wiki.go +++ b/modules/convert/wiki.go @@ -21,50 +21,46 @@ func ToWikiCommit(commit *git.Commit) *api.WikiCommit { Name: commit.Author.Name, Email: commit.Author.Email, }, - Date: commit.Author.When.Format(time.RFC3339), + Date: commit.Author.When.UTC().Format(time.RFC3339), }, Committer: &api.CommitUser{ Identity: api.Identity{ Name: commit.Committer.Name, Email: commit.Committer.Email, }, - Date: commit.Committer.When.Format(time.RFC3339), + Date: commit.Committer.When.UTC().Format(time.RFC3339), }, Message: commit.CommitMessage, } } // ToWikiCommitList convert a list of git commits into a WikiCommitList -func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList { +func ToWikiCommitList(commits []*git.Commit, total int64) *api.WikiCommitList { result := make([]*api.WikiCommit, len(commits)) for i := range commits { result[i] = ToWikiCommit(commits[i]) } return &api.WikiCommitList{ WikiCommits: result, - Count: count, + Count: total, } } // ToWikiPage converts different data to a WikiPage -func ToWikiPage(page string, lastCommit *git.Commit, commitsCount int64, data string, sidebarContent string, footerContent string) *api.WikiPage { +func ToWikiPage(title string, lastCommit *git.Commit, commitsCount int64, content []byte, sidebarContent []byte, footerContent []byte) *api.WikiPage { return &api.WikiPage{ - WikiPageMetaData: &api.WikiPageMetaData{ - Title: page, - SubURL: wiki_service.NameToSubURL(page), - Updated: lastCommit.Author.When.Format(time.RFC3339), - }, - Content: data, - CommitCount: commitsCount, - LastCommit: ToWikiCommit(lastCommit), - Sidebar: sidebarContent, - Footer: footerContent, + WikiPageMetaData: ToWikiPageMetaData(title, lastCommit.Author.When), + Content: string(content), + CommitCount: commitsCount, + LastCommit: ToWikiCommit(lastCommit), + Sidebar: string(sidebarContent), + Footer: string(footerContent), } } // ToWikiPageMetaData converts meta information to a WikiPageMetaData -func ToWikiPageMetaData(page string, updated string) api.WikiPageMetaData { - return api.WikiPageMetaData{ +func ToWikiPageMetaData(page string, updated time.Time) *api.WikiPageMetaData { + return &api.WikiPageMetaData{ Title: page, SubURL: wiki_service.NameToSubURL(page), Updated: updated, diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index eb03d7ddfa79..dba881c037f2 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -4,6 +4,8 @@ package structs +import "time" + // WikiCommit page commit/revision type WikiCommit struct { ID string `json:"sha"` @@ -24,9 +26,9 @@ type WikiPage struct { // WikiPageMetaData wiki page meta information type WikiPageMetaData struct { - Title string `json:"title"` - SubURL string `json:"suburl"` - Updated string `json:"updated"` + Title string `json:"title"` + SubURL string `json:"suburl"` + Updated time.Time `json:"updated"` } // CreateWikiPageOptions form for creating wiki diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 28769247aa1d..17da2bd57627 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -9,7 +9,6 @@ import ( "io" "net/http" "net/url" - "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/context" @@ -161,7 +160,7 @@ func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { } //lookup filename in wiki - get filecontent, gitTree entry , real filename - data, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, page, false) + content, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, page, false) if noEntry && !ctx.Written() { ctx.NotFound() return nil @@ -194,7 +193,7 @@ func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { return nil } - return convert.ToWikiPage(page, lastCommit, commitsCount, string(data), string(sidebarContent), string(footerContent)) + return convert.ToWikiPage(page, lastCommit, commitsCount, content, sidebarContent, footerContent) } // DeleteWikiPage delete wiki page @@ -299,7 +298,7 @@ func ListWikiPages(ctx *context.APIContext) { ctx.ServerError("ListEntries", err) return } - pages := make([]api.WikiPageMetaData, 0, len(entries)) + pages := make([]*api.WikiPageMetaData, 0, len(entries)) for i, entry := range entries { if i < skip || i >= max || !entry.IsRegular() { continue @@ -317,7 +316,7 @@ func ListWikiPages(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) return } - pages = append(pages, convert.ToWikiPageMetaData(wikiName, c.Author.When.Format(time.RFC3339))) + pages = append(pages, convert.ToWikiPageMetaData(wikiName, c.Author.When.UTC())) } ctx.JSON(http.StatusOK, pages) From 546a56589a43c8056c87a8ba71604e98f893c861 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 12:00:18 +0200 Subject: [PATCH 36/45] improve types pt.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add WikiPageMetaData.LastCommit - add WikiPageMetaData.HTMLURL - replace WikiPageMetaData.Updated with .LastCommit.Committer.Created also delete convert.ToWikiPage(), as it received too many arguments and only had one callsite anyway. sorry for bad advice earlier 🙃 --- integrations/api_wiki_test.go | 129 ++++++++++++++++++++++++++-------- modules/convert/wiki.go | 24 +++---- modules/structs/repo_wiki.go | 18 +++-- routers/api/v1/repo/wiki.go | 16 +++-- 4 files changed, 128 insertions(+), 59 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index aba2686291c0..1c6b16c163c2 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -5,6 +5,7 @@ package integrations import ( + "encoding/base64" "fmt" "net/http" "testing" @@ -30,31 +31,31 @@ func TestAPIGetWikiPage(t *testing.T) { assert.Equal(t, &api.WikiPage{ WikiPageMetaData: &api.WikiPageMetaData{ Title: "Home", + HTMLURL: "http://localhost:3003/user2/repo1/wiki/Home", SubURL: "Home", - Updated: "2017-11-26T20:31:18-08:00", - }, - Content: "# Home page\n\nThis is the home page!\n", - CommitCount: 1, - LastCommit: &api.WikiCommit{ - ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", - Author: &api.CommitUser{ - Identity: api.Identity{ - Name: "Ethan Koenig", - Email: "ethantkoenig@gmail.com", + LastCommit: &api.WikiCommit{ + ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-27T04:31:18Z", }, - Date: "2017-11-26T20:31:18-08:00", - }, - Committer: &api.CommitUser{ - Identity: api.Identity{ - Name: "Ethan Koenig", - Email: "ethantkoenig@gmail.com", + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-27T04:31:18Z", }, - Date: "2017-11-26T20:31:18-08:00", + Message: "Add Home.md\n", }, - Message: "Add Home.md\n", }, - Sidebar: "", - Footer: "", + Content: base64.RawStdEncoding.EncodeToString([]byte("# Home page\n\nThis is the home page!\n")), + CommitCount: 1, + Sidebar: "", + Footer: "", }, page) } @@ -75,23 +76,95 @@ func TestAPIListWikiPages(t *testing.T) { dummymeta := []*api.WikiPageMetaData{ { Title: "Home", + HTMLURL: "http://localhost:3003/user2/repo1/wiki/Home", SubURL: "Home", - Updated: "2017-11-26T20:31:18-08:00", + LastCommit: &api.WikiCommit{ + ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-27T04:31:18Z", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Ethan Koenig", + Email: "ethantkoenig@gmail.com", + }, + Date: "2017-11-27T04:31:18Z", + }, + Message: "Add Home.md\n", + }, }, { Title: "Page With Image", + HTMLURL: "http://localhost:3003/user2/repo1/wiki/Page-With-Image", SubURL: "Page-With-Image", - Updated: "2019-01-24T20:41:55-05:00", + LastCommit: &api.WikiCommit{ + ID: "0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Gabriel Silva SimĂ”es", + Email: "simoes.sgabriel@gmail.com", + }, + Date: "2019-01-25T01:41:55Z", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Gabriel Silva SimĂ”es", + Email: "simoes.sgabriel@gmail.com", + }, + Date: "2019-01-25T01:41:55Z", + }, + Message: "Add jpeg.jpg and page with image\n", + }, }, { Title: "Page With Spaced Name", + HTMLURL: "http://localhost:3003/user2/repo1/wiki/Page-With-Spaced-Name", SubURL: "Page-With-Spaced-Name", - Updated: "2019-01-24T20:39:51-05:00", + LastCommit: &api.WikiCommit{ + ID: "c10d10b7e655b3dab1f53176db57c8219a5488d6", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "Gabriel Silva SimĂ”es", + Email: "simoes.sgabriel@gmail.com", + }, + Date: "2019-01-25T01:39:51Z", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "Gabriel Silva SimĂ”es", + Email: "simoes.sgabriel@gmail.com", + }, + Date: "2019-01-25T01:39:51Z", + }, + Message: "Add page with spaced name\n", + }, }, { Title: "Unescaped File", + HTMLURL: "http://localhost:3003/user2/repo1/wiki/Unescaped-File", SubURL: "Unescaped-File", - Updated: "2021-07-19T18:42:46+02:00", + LastCommit: &api.WikiCommit{ + ID: "0dca5bd9b5d7ef937710e056f575e86c0184ba85", + Author: &api.CommitUser{ + Identity: api.Identity{ + Name: "6543", + Email: "6543@obermui.de", + }, + Date: "2021-07-19T16:42:46Z", + }, + Committer: &api.CommitUser{ + Identity: api.Identity{ + Name: "6543", + Email: "6543@obermui.de", + }, + Date: "2021-07-19T16:42:46Z", + }, + Message: "add unescaped file\n", + }, }, } @@ -112,7 +185,7 @@ func TestAPINewWikiPage(t *testing.T) { req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{ Title: title, - Content: "Wiki page content for API unit tests", + Content: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")), Message: "", }) session.MakeRequest(t, req, http.StatusCreated) @@ -129,7 +202,7 @@ func TestAPIEditWikiPage(t *testing.T) { req := NewRequestWithJSON(t, "PATCH", urlStr, &api.CreateWikiPageOptions{ Title: "edited title", - Content: "Edited wiki page content for API unit tests", + Content: base64.StdEncoding.EncodeToString([]byte("Edited wiki page content for API unit tests")), Message: "", }) session.MakeRequest(t, req, http.StatusOK) @@ -157,14 +230,14 @@ func TestAPIListPageRevisions(t *testing.T) { Name: "Ethan Koenig", Email: "ethantkoenig@gmail.com", }, - Date: "2017-11-26T20:31:18-08:00", + Date: "2017-11-27T04:31:18Z", }, Committer: &api.CommitUser{ Identity: api.Identity{ Name: "Ethan Koenig", Email: "ethantkoenig@gmail.com", }, - Date: "2017-11-26T20:31:18-08:00", + Date: "2017-11-27T04:31:18Z", }, Message: "Add Home.md\n", }, diff --git a/modules/convert/wiki.go b/modules/convert/wiki.go index a22697bf9914..9563f1544eca 100644 --- a/modules/convert/wiki.go +++ b/modules/convert/wiki.go @@ -7,8 +7,10 @@ package convert import ( "time" + "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" wiki_service "code.gitea.io/gitea/services/wiki" ) @@ -46,23 +48,13 @@ func ToWikiCommitList(commits []*git.Commit, total int64) *api.WikiCommitList { } } -// ToWikiPage converts different data to a WikiPage -func ToWikiPage(title string, lastCommit *git.Commit, commitsCount int64, content []byte, sidebarContent []byte, footerContent []byte) *api.WikiPage { - return &api.WikiPage{ - WikiPageMetaData: ToWikiPageMetaData(title, lastCommit.Author.When), - Content: string(content), - CommitCount: commitsCount, - LastCommit: ToWikiCommit(lastCommit), - Sidebar: string(sidebarContent), - Footer: string(footerContent), - } -} - // ToWikiPageMetaData converts meta information to a WikiPageMetaData -func ToWikiPageMetaData(page string, updated time.Time) *api.WikiPageMetaData { +func ToWikiPageMetaData(title string, lastCommit *git.Commit, repo *models.Repository) *api.WikiPageMetaData { + suburl := wiki_service.NameToSubURL(title) return &api.WikiPageMetaData{ - Title: page, - SubURL: wiki_service.NameToSubURL(page), - Updated: updated, + Title: title, + HTMLURL: util.URLJoin(repo.HTMLURL(), "wiki", suburl), + SubURL: suburl, + LastCommit: ToWikiCommit(lastCommit), } } diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index dba881c037f2..1a2be835379a 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -4,8 +4,6 @@ package structs -import "time" - // WikiCommit page commit/revision type WikiCommit struct { ID string `json:"sha"` @@ -17,18 +15,18 @@ type WikiCommit struct { // WikiPage a wiki page type WikiPage struct { *WikiPageMetaData - Content string `json:"content"` - CommitCount int64 `json:"commit_count"` - LastCommit *WikiCommit `json:"last_commit"` - Sidebar string `json:"sidebar"` - Footer string `json:"footer"` + Content string `json:"content"` + CommitCount int64 `json:"commit_count"` + Sidebar string `json:"sidebar"` + Footer string `json:"footer"` } // WikiPageMetaData wiki page meta information type WikiPageMetaData struct { - Title string `json:"title"` - SubURL string `json:"suburl"` - Updated time.Time `json:"updated"` + Title string `json:"title"` + HTMLURL string `json:"html_url"` + SubURL string `json:"suburl"` + LastCommit *WikiCommit `json:"last_commit"` } // CreateWikiPageOptions form for creating wiki diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 17da2bd57627..81bd2e532354 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -141,8 +141,8 @@ func EditWikiPage(ctx *context.APIContext) { } } -func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { - page = wiki_service.NormalizeWikiName(page) +func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { + title = wiki_service.NormalizeWikiName(title) wikiRepo, commit, err := findWikiRepoCommit(ctx) if wikiRepo != nil { @@ -160,7 +160,7 @@ func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { } //lookup filename in wiki - get filecontent, gitTree entry , real filename - content, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, page, false) + content, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, title, false) if noEntry && !ctx.Written() { ctx.NotFound() return nil @@ -193,7 +193,13 @@ func getWikiPage(ctx *context.APIContext, page string) *api.WikiPage { return nil } - return convert.ToWikiPage(page, lastCommit, commitsCount, content, sidebarContent, footerContent) + return &api.WikiPage{ + WikiPageMetaData: convert.ToWikiPageMetaData(title, lastCommit, ctx.Repo.Repository), + Content: string(content), + CommitCount: commitsCount, + Sidebar: string(sidebarContent), + Footer: string(footerContent), + } } // DeleteWikiPage delete wiki page @@ -316,7 +322,7 @@ func ListWikiPages(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "WikiFilenameToName", err) return } - pages = append(pages, convert.ToWikiPageMetaData(wikiName, c.Author.When.UTC())) + pages = append(pages, convert.ToWikiPageMetaData(wikiName, c, ctx.Repo.Repository)) } ctx.JSON(http.StatusOK, pages) From f88605baf1416a6782511593505397b574616fbf Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 22:49:07 +0200 Subject: [PATCH 37/45] WikiPage.Content is base64 encoded --- modules/structs/repo_wiki.go | 2 +- routers/api/v1/repo/wiki.go | 37 ++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index 1a2be835379a..18e51bbf5296 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -33,7 +33,7 @@ type WikiPageMetaData struct { type CreateWikiPageOptions struct { // page title. leave empty to keep unchanged Title string `json:"title"` - // content must be UTF-8 encoded + // content must be base64 encoded Content string `json:"content"` // commit message summarizing the change Message string `json:"message"` diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 81bd2e532354..6868eb08d740 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -5,8 +5,8 @@ package repo import ( + "encoding/base64" "fmt" - "io" "net/http" "net/url" @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/git" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" @@ -63,6 +64,13 @@ func NewWikiPage(ctx *context.APIContext) { form.Message = fmt.Sprintf("Add '%s'", form.Title) } + content, err := base64.StdEncoding.DecodeString(form.Content) + if err != nil { + ctx.Error(http.StatusBadRequest, "invalid base64 encoding of content", err) + return + } + form.Content = string(content) + if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { if models.IsErrWikiReservedName(err) { ctx.Error(http.StatusBadRequest, "IsErrWikiReservedName", err) @@ -129,6 +137,13 @@ func EditWikiPage(ctx *context.APIContext) { form.Message = fmt.Sprintf("Update '%s'", newWikiName) } + content, err := base64.StdEncoding.DecodeString(form.Content) + if err != nil { + ctx.Error(http.StatusBadRequest, "invalid base64 encoding of content", err) + return + } + form.Content = string(content) + if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { ctx.Error(http.StatusInternalServerError, "EditWikiPage", err) return @@ -480,18 +495,16 @@ func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit, } // wikiContentsByEntry returns the contents of the wiki page referenced by the -// given tree entry. Writes to ctx if an error occurs. -func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) []byte { - reader, err := entry.Blob().DataAsync() - if err != nil { - ctx.Error(http.StatusInternalServerError, "Blob.Data", err) - return nil +// given tree entry, encoded with base64. Writes to ctx if an error occurs. +func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string { + blob := entry.Blob() + if blob.Size() > setting.API.DefaultMaxBlobSize { + return "" } - defer reader.Close() - content, err := io.ReadAll(reader) + content, err := blob.GetBlobContentBase64() if err != nil { - ctx.Error(http.StatusInternalServerError, "ReadAll", err) - return nil + ctx.Error(http.StatusInternalServerError, "GetBlobContentBase64", err) + return "" } return content } @@ -509,5 +522,5 @@ func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName st } else if entry == nil { return nil, nil, "", true } - return wikiContentsByEntry(ctx, entry), entry, pageFilename, false + return []byte(wikiContentsByEntry(ctx, entry)), pageFilename } From cafbea48327352b5df7491fa1be7878cd0c687f8 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 22:49:55 +0200 Subject: [PATCH 38/45] simplify error handling in wikiContentsByName() --- routers/api/v1/repo/wiki.go | 52 ++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 6868eb08d740..634baf2603bb 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -174,25 +174,18 @@ func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { return nil } - //lookup filename in wiki - get filecontent, gitTree entry , real filename - content, entry, pageFilename, noEntry := wikiContentsByName(ctx, commit, title, false) - if noEntry && !ctx.Written() { - ctx.NotFound() - return nil - } - if entry == nil { - if !ctx.Written() { - ctx.NotFound() - } + //lookup filename in wiki - get filecontent, real filename + content, pageFilename := wikiContentsByName(ctx, commit, title, false) + if ctx.Written() { return nil } - sidebarContent, _, _, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) + sidebarContent, _ := wikiContentsByName(ctx, commit, "_Sidebar", true) if ctx.Written() { return nil } - footerContent, _, _, _ := wikiContentsByName(ctx, commit, "_Footer", true) + footerContent, _ := wikiContentsByName(ctx, commit, "_Footer", true) if ctx.Written() { return nil } @@ -200,9 +193,8 @@ func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { // get commit count - wiki revisions commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename) - wikiPath := entry.Name() // Get last change information. - lastCommit, err := wikiRepo.GetCommitByPath(wikiPath) + lastCommit, err := wikiRepo.GetCommitByPath(pageFilename) if err != nil { ctx.Error(http.StatusInternalServerError, "GetCommitByPath", err) return nil @@ -210,10 +202,10 @@ func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { return &api.WikiPage{ WikiPageMetaData: convert.ToWikiPageMetaData(title, lastCommit, ctx.Repo.Repository), - Content: string(content), + Content: content, CommitCount: commitsCount, - Sidebar: string(sidebarContent), - Footer: string(footerContent), + Sidebar: sidebarContent, + Footer: footerContent, } } @@ -436,11 +428,8 @@ func ListPageRevisions(ctx *context.APIContext) { } //lookup filename in wiki - get filecontent, gitTree entry , real filename - _, _, pageFilename, noEntry := wikiContentsByName(ctx, commit, pageName, false) - if noEntry { - if !ctx.Written() { - ctx.NotFound() - } + _, pageFilename := wikiContentsByName(ctx, commit, pageName, false) + if ctx.Written() { return } @@ -480,6 +469,8 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) return commit.GetTreeEntryByPath(unescapedTarget) } +// findWikiRepoCommit opens the wiki repo and returns the latest commit. +// The caller is responsible for closing the returned repo again func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit, error) { wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) if err != nil { @@ -511,16 +502,19 @@ func wikiContentsByEntry(ctx *context.APIContext, entry *git.TreeEntry) string { // wikiContentsByName returns the contents of a wiki page, along with a boolean // indicating whether the page exists. Writes to ctx if an error occurs. -func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string, isSidebarOrFooter bool) ([]byte, *git.TreeEntry, string, bool) { +func wikiContentsByName(ctx *context.APIContext, commit *git.Commit, wikiName string, isSidebarOrFooter bool) (string, string) { pageFilename := wiki_service.NameToFilename(wikiName) entry, err := findEntryForFile(commit, pageFilename) + if err != nil { - if !isSidebarOrFooter { - ctx.NotFound(err) + if git.IsErrNotExist(err) { + if !isSidebarOrFooter { + ctx.NotFound() + } + } else { + ctx.ServerError("findEntryForFile", err) } - return nil, nil, "", false - } else if entry == nil { - return nil, nil, "", true + return "", "" } - return []byte(wikiContentsByEntry(ctx, entry)), pageFilename + return wikiContentsByEntry(ctx, entry), pageFilename } From 490a168d0f75419d3f0dca4fa7398d0815acbfb9 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 23:21:59 +0200 Subject: [PATCH 39/45] update swagger --- templates/swagger/v1_json.tmpl | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 8dbbdcc7b0cc..e0d2d3a10b8f 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -13949,15 +13949,17 @@ "type": "object", "properties": { "content": { - "description": "content must be UTF-8 encoded", + "description": "content must be base64 encoded", "type": "string", "x-go-name": "Content" }, "message": { + "description": "commit message summarizing the change", "type": "string", "x-go-name": "Message" }, "title": { + "description": "page title. leave empty to keep unchanged", "type": "string", "x-go-name": "Title" } @@ -17732,13 +17734,13 @@ "type": "string", "x-go-name": "Footer" }, + "html_url": { + "type": "string", + "x-go-name": "HTMLURL" + }, "last_commit": { "$ref": "#/definitions/WikiCommit" }, - "name": { - "type": "string", - "x-go-name": "Name" - }, "sidebar": { "type": "string", "x-go-name": "Sidebar" @@ -17750,10 +17752,6 @@ "title": { "type": "string", "x-go-name": "Title" - }, - "updated": { - "type": "string", - "x-go-name": "Updated" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" @@ -17762,17 +17760,20 @@ "description": "WikiPageMetaData wiki page meta information", "type": "object", "properties": { - "name": { + "html_url": { "type": "string", - "x-go-name": "Name" + "x-go-name": "HTMLURL" + }, + "last_commit": { + "$ref": "#/definitions/WikiCommit" }, "suburl": { "type": "string", "x-go-name": "SubURL" }, - "updated": { + "title": { "type": "string", - "x-go-name": "Updated" + "x-go-name": "Title" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" From ab649d4bca9d8d19b67bf25cf9c5d1442198d232 Mon Sep 17 00:00:00 2001 From: Norwin Date: Tue, 19 Oct 2021 23:54:18 +0200 Subject: [PATCH 40/45] fix & DRY findWikiRepoCommit() error handling ListWikiPages() previously wrote error twice when repo wiki didn't exist --- routers/api/v1/repo/wiki.go | 52 ++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 634baf2603bb..3a3d591beecb 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -159,18 +159,11 @@ func EditWikiPage(ctx *context.APIContext) { func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { title = wiki_service.NormalizeWikiName(title) - wikiRepo, commit, err := findWikiRepoCommit(ctx) + wikiRepo, commit := findWikiRepoCommit(ctx) if wikiRepo != nil { defer wikiRepo.Close() } - if err != nil { - if !ctx.Written() { - if git.IsErrNotExist(err) { - ctx.NotFound(err) - } else { - ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) - } - } + if ctx.Written() { return nil } @@ -284,12 +277,11 @@ func ListWikiPages(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - wikiRepo, commit, err := findWikiRepoCommit(ctx) + wikiRepo, commit := findWikiRepoCommit(ctx) if wikiRepo != nil { defer wikiRepo.Close() } - if err != nil { - ctx.Error(http.StatusInternalServerError, "findWikiRepoCommit", err) + if ctx.Written() { return } @@ -297,10 +289,9 @@ func ListWikiPages(ctx *context.APIContext) { if page <= 1 { page = 1 } - limit := ctx.FormInt("limit") if limit <= 1 { - limit = 20 + limit = setting.API.DefaultPagingNum } skip := (page - 1) * limit @@ -406,18 +397,11 @@ func ListPageRevisions(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - wikiRepo, commit, err := findWikiRepoCommit(ctx) + wikiRepo, commit := findWikiRepoCommit(ctx) if wikiRepo != nil { defer wikiRepo.Close() } - if err != nil { - if !ctx.Written() { - if git.IsErrNotExist(err) { - ctx.NotFound(err) - } else { - ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) - } - } + if ctx.Written() { return } @@ -469,20 +453,30 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error) return commit.GetTreeEntryByPath(unescapedTarget) } -// findWikiRepoCommit opens the wiki repo and returns the latest commit. +// findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error. // The caller is responsible for closing the returned repo again -func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit, error) { +func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) { wikiRepo, err := git.OpenRepository(ctx.Repo.Repository.WikiPath()) if err != nil { - ctx.Error(http.StatusInternalServerError, "OpenRepository", err) - return nil, nil, err + + if git.IsErrNotExist(err) || err.Error() == "no such file or directory" { + ctx.NotFound(err) + } else { + ctx.Error(http.StatusInternalServerError, "OpenRepository", err) + } + return nil, nil } commit, err := wikiRepo.GetBranchCommit("master") if err != nil { - return wikiRepo, nil, err + if git.IsErrNotExist(err) { + ctx.NotFound(err) + } else { + ctx.Error(http.StatusInternalServerError, "GetBranchCommit", err) + } + return wikiRepo, nil } - return wikiRepo, commit, nil + return wikiRepo, commit } // wikiContentsByEntry returns the contents of the wiki page referenced by the From 40e399f4249d7db028db262226d1ff2adcd19408 Mon Sep 17 00:00:00 2001 From: Norwin Date: Wed, 20 Oct 2021 11:11:49 +0200 Subject: [PATCH 41/45] rename Content -> ContentBase64 --- integrations/api_wiki_test.go | 16 +++++++++------- modules/structs/repo_wiki.go | 13 +++++++------ routers/api/v1/repo/wiki.go | 14 +++++++------- templates/swagger/v1_json.tmpl | 7 ++++--- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index 1c6b16c163c2..b48fd12f15d4 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -52,7 +52,9 @@ func TestAPIGetWikiPage(t *testing.T) { Message: "Add Home.md\n", }, }, - Content: base64.RawStdEncoding.EncodeToString([]byte("# Home page\n\nThis is the home page!\n")), + ContentBase64: base64.RawStdEncoding.EncodeToString( + []byte("# Home page\n\nThis is the home page!\n"), + ), CommitCount: 1, Sidebar: "", Footer: "", @@ -184,9 +186,9 @@ func TestAPINewWikiPage(t *testing.T) { urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/new?token=%s", username, "repo1", token) req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateWikiPageOptions{ - Title: title, - Content: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")), - Message: "", + Title: title, + ContentBase64: base64.StdEncoding.EncodeToString([]byte("Wiki page content for API unit tests")), + Message: "", }) session.MakeRequest(t, req, http.StatusCreated) } @@ -201,9 +203,9 @@ func TestAPIEditWikiPage(t *testing.T) { urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/wiki/page/Page-With-Spaced-Name?token=%s", username, "repo1", token) req := NewRequestWithJSON(t, "PATCH", urlStr, &api.CreateWikiPageOptions{ - Title: "edited title", - Content: base64.StdEncoding.EncodeToString([]byte("Edited wiki page content for API unit tests")), - Message: "", + Title: "edited title", + ContentBase64: base64.StdEncoding.EncodeToString([]byte("Edited wiki page content for API unit tests")), + Message: "", }) session.MakeRequest(t, req, http.StatusOK) } diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index 18e51bbf5296..fb0cdb8e02ec 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -15,10 +15,11 @@ type WikiCommit struct { // WikiPage a wiki page type WikiPage struct { *WikiPageMetaData - Content string `json:"content"` - CommitCount int64 `json:"commit_count"` - Sidebar string `json:"sidebar"` - Footer string `json:"footer"` + // Page content, base64 encoded + ContentBase64 string `json:"content"` + CommitCount int64 `json:"commit_count"` + Sidebar string `json:"sidebar"` + Footer string `json:"footer"` } // WikiPageMetaData wiki page meta information @@ -34,8 +35,8 @@ type CreateWikiPageOptions struct { // page title. leave empty to keep unchanged Title string `json:"title"` // content must be base64 encoded - Content string `json:"content"` - // commit message summarizing the change + ContentBase64 string `json:"content"` + // optional commit message summarizing the change Message string `json:"message"` } diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go index 3a3d591beecb..f8969067be27 100644 --- a/routers/api/v1/repo/wiki.go +++ b/routers/api/v1/repo/wiki.go @@ -64,14 +64,14 @@ func NewWikiPage(ctx *context.APIContext) { form.Message = fmt.Sprintf("Add '%s'", form.Title) } - content, err := base64.StdEncoding.DecodeString(form.Content) + content, err := base64.StdEncoding.DecodeString(form.ContentBase64) if err != nil { ctx.Error(http.StatusBadRequest, "invalid base64 encoding of content", err) return } - form.Content = string(content) + form.ContentBase64 = string(content) - if err := wiki_service.AddWikiPage(ctx.User, ctx.Repo.Repository, wikiName, form.Content, form.Message); err != nil { + if err := wiki_service.AddWikiPage(ctx.User, 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) { @@ -137,14 +137,14 @@ func EditWikiPage(ctx *context.APIContext) { form.Message = fmt.Sprintf("Update '%s'", newWikiName) } - content, err := base64.StdEncoding.DecodeString(form.Content) + content, err := base64.StdEncoding.DecodeString(form.ContentBase64) if err != nil { ctx.Error(http.StatusBadRequest, "invalid base64 encoding of content", err) return } - form.Content = string(content) + form.ContentBase64 = string(content) - if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.Content, form.Message); err != nil { + if err := wiki_service.EditWikiPage(ctx.User, ctx.Repo.Repository, oldWikiName, newWikiName, form.ContentBase64, form.Message); err != nil { ctx.Error(http.StatusInternalServerError, "EditWikiPage", err) return } @@ -195,7 +195,7 @@ func getWikiPage(ctx *context.APIContext, title string) *api.WikiPage { return &api.WikiPage{ WikiPageMetaData: convert.ToWikiPageMetaData(title, lastCommit, ctx.Repo.Repository), - Content: content, + ContentBase64: content, CommitCount: commitsCount, Sidebar: sidebarContent, Footer: footerContent, diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index e0d2d3a10b8f..22cca49ce502 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -13951,10 +13951,10 @@ "content": { "description": "content must be base64 encoded", "type": "string", - "x-go-name": "Content" + "x-go-name": "ContentBase64" }, "message": { - "description": "commit message summarizing the change", + "description": "optional commit message summarizing the change", "type": "string", "x-go-name": "Message" }, @@ -17727,8 +17727,9 @@ "x-go-name": "CommitCount" }, "content": { + "description": "Page content, base64 encoded", "type": "string", - "x-go-name": "Content" + "x-go-name": "ContentBase64" }, "footer": { "type": "string", From 933697d54270a98354baed6695254fc1a0ee32b0 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Thu, 21 Oct 2021 15:13:48 +0200 Subject: [PATCH 42/45] Fix test --- integrations/api_wiki_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index b48fd12f15d4..200a782ce86a 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -31,7 +31,7 @@ func TestAPIGetWikiPage(t *testing.T) { assert.Equal(t, &api.WikiPage{ WikiPageMetaData: &api.WikiPageMetaData{ Title: "Home", - HTMLURL: "http://localhost:3003/user2/repo1/wiki/Home", + HTMLURL: "http://localhost:3001/user2/repo1/wiki/Home", SubURL: "Home", LastCommit: &api.WikiCommit{ ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", @@ -78,7 +78,7 @@ func TestAPIListWikiPages(t *testing.T) { dummymeta := []*api.WikiPageMetaData{ { Title: "Home", - HTMLURL: "http://localhost:3003/user2/repo1/wiki/Home", + HTMLURL: "http://localhost:3001/user2/repo1/wiki/Home", SubURL: "Home", LastCommit: &api.WikiCommit{ ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", @@ -101,7 +101,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Page With Image", - HTMLURL: "http://localhost:3003/user2/repo1/wiki/Page-With-Image", + HTMLURL: "http://localhost:3001/user2/repo1/wiki/Page-With-Image", SubURL: "Page-With-Image", LastCommit: &api.WikiCommit{ ID: "0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3", @@ -124,7 +124,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Page With Spaced Name", - HTMLURL: "http://localhost:3003/user2/repo1/wiki/Page-With-Spaced-Name", + HTMLURL: "http://localhost:3001/user2/repo1/wiki/Page-With-Spaced-Name", SubURL: "Page-With-Spaced-Name", LastCommit: &api.WikiCommit{ ID: "c10d10b7e655b3dab1f53176db57c8219a5488d6", @@ -147,7 +147,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Unescaped File", - HTMLURL: "http://localhost:3003/user2/repo1/wiki/Unescaped-File", + HTMLURL: "http://localhost:3001/user2/repo1/wiki/Unescaped-File", SubURL: "Unescaped-File", LastCommit: &api.WikiCommit{ ID: "0dca5bd9b5d7ef937710e056f575e86c0184ba85", From 75922f7f18b28412d340fc2e6e6bd07d21d7f59a Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Fri, 22 Oct 2021 16:40:02 +0200 Subject: [PATCH 43/45] Fix tests --- integrations/api_wiki_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/integrations/api_wiki_test.go b/integrations/api_wiki_test.go index 200a782ce86a..3b768b94d80e 100644 --- a/integrations/api_wiki_test.go +++ b/integrations/api_wiki_test.go @@ -31,7 +31,7 @@ func TestAPIGetWikiPage(t *testing.T) { assert.Equal(t, &api.WikiPage{ WikiPageMetaData: &api.WikiPageMetaData{ Title: "Home", - HTMLURL: "http://localhost:3001/user2/repo1/wiki/Home", + HTMLURL: page.HTMLURL, SubURL: "Home", LastCommit: &api.WikiCommit{ ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", @@ -78,7 +78,7 @@ func TestAPIListWikiPages(t *testing.T) { dummymeta := []*api.WikiPageMetaData{ { Title: "Home", - HTMLURL: "http://localhost:3001/user2/repo1/wiki/Home", + HTMLURL: meta[0].HTMLURL, SubURL: "Home", LastCommit: &api.WikiCommit{ ID: "2c54faec6c45d31c1abfaecdab471eac6633738a", @@ -101,7 +101,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Page With Image", - HTMLURL: "http://localhost:3001/user2/repo1/wiki/Page-With-Image", + HTMLURL: meta[1].HTMLURL, SubURL: "Page-With-Image", LastCommit: &api.WikiCommit{ ID: "0cf15c3f66ec8384480ed9c3cf87c9e97fbb0ec3", @@ -124,7 +124,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Page With Spaced Name", - HTMLURL: "http://localhost:3001/user2/repo1/wiki/Page-With-Spaced-Name", + HTMLURL: meta[2].HTMLURL, SubURL: "Page-With-Spaced-Name", LastCommit: &api.WikiCommit{ ID: "c10d10b7e655b3dab1f53176db57c8219a5488d6", @@ -147,7 +147,7 @@ func TestAPIListWikiPages(t *testing.T) { }, { Title: "Unescaped File", - HTMLURL: "http://localhost:3001/user2/repo1/wiki/Unescaped-File", + HTMLURL: meta[3].HTMLURL, SubURL: "Unescaped-File", LastCommit: &api.WikiCommit{ ID: "0dca5bd9b5d7ef937710e056f575e86c0184ba85", From daf8ee07a5d0219eddfabd80ba149a507f27cec2 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 23 Oct 2021 13:19:56 +0200 Subject: [PATCH 44/45] Update var name --- modules/structs/repo_wiki.go | 4 ++-- templates/swagger/v1_json.tmpl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index fb0cdb8e02ec..e7edf0fef1dc 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -16,7 +16,7 @@ type WikiCommit struct { type WikiPage struct { *WikiPageMetaData // Page content, base64 encoded - ContentBase64 string `json:"content"` + ContentBase64 string `json:"content_base64"` CommitCount int64 `json:"commit_count"` Sidebar string `json:"sidebar"` Footer string `json:"footer"` @@ -35,7 +35,7 @@ type CreateWikiPageOptions struct { // page title. leave empty to keep unchanged Title string `json:"title"` // content must be base64 encoded - ContentBase64 string `json:"content"` + ContentBase64 string `json:"content_base64"` // optional commit message summarizing the change Message string `json:"message"` } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 22cca49ce502..3ba5d5150884 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -13948,7 +13948,7 @@ "description": "CreateWikiPageOptions form for creating wiki", "type": "object", "properties": { - "content": { + "content_base64": { "description": "content must be base64 encoded", "type": "string", "x-go-name": "ContentBase64" @@ -17726,7 +17726,7 @@ "format": "int64", "x-go-name": "CommitCount" }, - "content": { + "content_base64": { "description": "Page content, base64 encoded", "type": "string", "x-go-name": "ContentBase64" From 7105721b417166132af4698ae96f1c25b99a2d2a Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Sat, 23 Oct 2021 14:32:31 +0200 Subject: [PATCH 45/45] suburl -> sub_url --- modules/structs/repo_wiki.go | 2 +- templates/swagger/v1_json.tmpl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/structs/repo_wiki.go b/modules/structs/repo_wiki.go index e7edf0fef1dc..09e21387df49 100644 --- a/modules/structs/repo_wiki.go +++ b/modules/structs/repo_wiki.go @@ -26,7 +26,7 @@ type WikiPage struct { type WikiPageMetaData struct { Title string `json:"title"` HTMLURL string `json:"html_url"` - SubURL string `json:"suburl"` + SubURL string `json:"sub_url"` LastCommit *WikiCommit `json:"last_commit"` } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 3ba5d5150884..6bbc0934811b 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -17746,7 +17746,7 @@ "type": "string", "x-go-name": "Sidebar" }, - "suburl": { + "sub_url": { "type": "string", "x-go-name": "SubURL" }, @@ -17768,7 +17768,7 @@ "last_commit": { "$ref": "#/definitions/WikiCommit" }, - "suburl": { + "sub_url": { "type": "string", "x-go-name": "SubURL" },