Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API to get/edit wiki #17278

Merged
merged 63 commits into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
878481b
Add API to get/edit wiki
qwerty287 Oct 8, 2021
7981a21
Add swagger docs, various improvements
qwerty287 Oct 9, 2021
48db90e
fmt
qwerty287 Oct 9, 2021
30a2377
Fix lint and rm comment
qwerty287 Oct 9, 2021
1312d58
Add page parameter
qwerty287 Oct 9, 2021
7f5b4ef
Add pagination to pages
qwerty287 Oct 9, 2021
ba25936
Merge branch 'main' into wiki-api
qwerty287 Oct 9, 2021
58fb2f6
Add tests
qwerty287 Oct 9, 2021
06bb4cf
fmt
qwerty287 Oct 9, 2021
c908b69
Update func names
qwerty287 Oct 9, 2021
d3ef69c
Update error handling
qwerty287 Oct 9, 2021
53f82fa
Update type name
qwerty287 Oct 9, 2021
8600b87
Fix lint
qwerty287 Oct 9, 2021
ceabfd7
Don't delete Home
qwerty287 Oct 9, 2021
23f6475
Update func name
qwerty287 Oct 9, 2021
77e42d5
Update routers/api/v1/repo/wiki.go
qwerty287 Oct 9, 2021
cfa6303
Remove unnecessary check
qwerty287 Oct 9, 2021
63ea38e
Fix lint
qwerty287 Oct 9, 2021
8d568a4
Use English strings
qwerty287 Oct 9, 2021
bfbe3ac
Update integrations/api_wiki_test.go
qwerty287 Oct 9, 2021
65d1951
Update func and test names
qwerty287 Oct 9, 2021
3027d3f
Remove unsed check and avoid duplicated error reports
qwerty287 Oct 9, 2021
fc8443a
Improve error handling
qwerty287 Oct 9, 2021
1ea3fe1
Return after error
qwerty287 Oct 10, 2021
eefb617
Document 404 error
qwerty287 Oct 10, 2021
b0ef969
Update swagger
qwerty287 Oct 10, 2021
fd76be3
Fix lint
qwerty287 Oct 10, 2021
adbaf41
Merge branch 'main' into wiki-api
qwerty287 Oct 10, 2021
7d04627
Apply suggestions from code review
qwerty287 Oct 10, 2021
f9455bc
Document file encoding
qwerty287 Oct 10, 2021
e642b2b
fmt
qwerty287 Oct 10, 2021
21e9e70
Merge branch 'main' into wiki-api
qwerty287 Oct 15, 2021
0e1e979
Merge branch 'main' into wiki-api
qwerty287 Oct 16, 2021
40962d6
Merge branch 'main' into wiki-api
qwerty287 Oct 16, 2021
9a1590c
Merge branch 'main' into wiki-api
qwerty287 Oct 17, 2021
f26b52b
Merge branch 'main' into wiki-api
qwerty287 Oct 17, 2021
ecc7ba6
Apply suggestions
qwerty287 Oct 18, 2021
34c6d71
Use convert
qwerty287 Oct 18, 2021
3b50c27
Merge branch 'main' into wiki-api
qwerty287 Oct 18, 2021
be93b48
Fix integration test
qwerty287 Oct 18, 2021
952beef
simplify permissions
noerw Oct 19, 2021
3b5d5ff
unify duplicate key Title/Name
noerw Oct 19, 2021
89bbcfa
improve types & return UTC timestamps
noerw Oct 19, 2021
546a565
improve types pt.2
noerw Oct 19, 2021
f88605b
WikiPage.Content is base64 encoded
noerw Oct 19, 2021
cafbea4
simplify error handling in wikiContentsByName()
noerw Oct 19, 2021
490a168
update swagger
noerw Oct 19, 2021
ab649d4
fix & DRY findWikiRepoCommit() error handling
noerw Oct 19, 2021
afd51f4
Merge branch 'main' into wiki-api
qwerty287 Oct 20, 2021
40e399f
rename Content -> ContentBase64
noerw Oct 20, 2021
d84e39d
Merge branch 'main' into wiki-api
6543 Oct 20, 2021
804458c
Merge branch 'main' into wiki-api
qwerty287 Oct 21, 2021
3a82d12
Merge pull request #1 from noerw/wiki-api
qwerty287 Oct 21, 2021
c67eff3
Merge branch 'main' into wiki-api
qwerty287 Oct 21, 2021
933697d
Fix test
qwerty287 Oct 21, 2021
2ac6b9a
Merge branch 'main' into wiki-api
qwerty287 Oct 22, 2021
75922f7
Fix tests
qwerty287 Oct 22, 2021
daf8ee0
Update var name
qwerty287 Oct 23, 2021
7105721
suburl -> sub_url
qwerty287 Oct 23, 2021
d78f2d8
Merge branch 'main' into wiki-api
qwerty287 Oct 23, 2021
1de0d03
Merge branch 'main' into wiki-api
qwerty287 Oct 23, 2021
d141619
Merge branch 'main' into wiki-api
zeripath Oct 24, 2021
6425a28
Merge branch 'main' into wiki-api
wxiaoguang Oct 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 182 additions & 0 deletions integrations/api_wiki_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// 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"

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{
WikiPageMetaData: &api.WikiPageMetaData{
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 TestAPIListWikiPages(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.WikiPageMetaData
DecodeJSON(t, resp, &meta)

dummymeta := []*api.WikiPageMetaData{
{
Name: "Home",
SubURL: "Home",
Updated: "2017-11-26T20:31:18-08:00",
},
{
Name: "Page With Image",
SubURL: "Page-With-Image",
Updated: "2019-01-24T20:41:55-05:00",
},
{
Name: "Page With Spaced Name",
SubURL: "Page-With-Spaced-Name",
Updated: "2019-01-24T20:39:51-05:00",
},
{
Name: "Unescaped File",
SubURL: "Unescaped-File",
Updated: "2021-07-19T18:42:46+02:00",
},
}

assert.Equal(t, dummymeta, meta)
}

func TestAPINewWikiPage(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 TestAPIEditWikiPage(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 TestAPIListPageRevisions(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)
}
46 changes: 46 additions & 0 deletions modules/convert/wiki.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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"
)

// ToWikiCommit convert a git commit into a WikiCommit
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,
}
}

// ToWikiCommitList convert a list of git commits into a WikiCommitList
func ToWikiCommitList(commits []*git.Commit, count int64) *api.WikiCommitList {
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
result := make([]*api.WikiCommit, len(commits))
for i := range commits {
result[i] = ToWikiCommit(commits[i])
}
return &api.WikiCommitList{
WikiCommits: result,
Count: count,
}
}
45 changes: 45 additions & 0 deletions modules/structs/repo_wiki.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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

// WikiCommit page commit/revision
type WikiCommit struct {
ID string `json:"sha"`
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
Author *CommitUser `json:"author"`
Committer *CommitUser `json:"commiter"`
Message string `json:"message"`
}

// 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"`
Sidebar string `json:"sidebar"`
Footer string `json:"footer"`
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
}

// WikiPageMetaData wiki page meta information
type WikiPageMetaData struct {
Name string `json:"name"`
SubURL string `json:"suburl"`
Updated string `json:"updated"`
}

// 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"`
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
}

// WikiCommitList commit/revision list
type WikiCommitList struct {
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
WikiCommits []*WikiCommit `json:"commits"`
Count int64 `json:"count"`
}
16 changes: 16 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,13 @@ func mustEnableIssuesOrPulls(ctx *context.APIContext) {
}
}

func mustEnableWiki(ctx *context.APIContext) {
if !(ctx.Repo.CanRead(models.UnitTypeWiki)) {
ctx.NotFound()
return
}
}

func mustNotBeArchived(ctx *context.APIContext) {
if ctx.Repo.Repository.IsArchived {
ctx.NotFound()
Expand Down Expand Up @@ -791,6 +798,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.GetWikiPage).
Patch(mustNotBeArchived, reqRepoWriter(models.UnitTypeWiki), mustEnableWiki, reqToken(), bind(api.CreateWikiPageOptions{}), repo.EditWikiPage).
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
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)
})
qwerty287 marked this conversation as resolved.
Show resolved Hide resolved
m.Group("/issues", func() {
m.Combo("").Get(repo.ListIssues).
Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), repo.CreateIssue)
Expand Down
Loading