Skip to content

Add API for License templates #23009

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

Merged
merged 3 commits into from
Apr 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 16 additions & 0 deletions modules/structs/miscellaneous.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,22 @@ type ServerVersion struct {
Version string `json:"version"`
}

// LicensesListEntry is used for the API
type LicensesTemplateListEntry struct {
Key string `json:"key"`
Name string `json:"name"`
URL string `json:"url"`
}

// LicensesInfo contains information about a License
type LicenseTemplateInfo struct {
Key string `json:"key"`
Name string `json:"name"`
URL string `json:"url"`
Implementation string `json:"implementation"`
Body string `json:"body"`
}

// APIError is an api error with a message
type APIError struct {
Message string `json:"message"`
Expand Down
2 changes: 2 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,8 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Post("/markup", bind(api.MarkupOption{}), misc.Markup)
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
m.Post("/markdown/raw", misc.MarkdownRaw)
m.Get("/licenses", misc.ListLicenseTemplates)
m.Get("/licenses/{name}", misc.GetLicenseTemplateInfo)
m.Group("/settings", func() {
m.Get("/ui", settings.GetGeneralUISettings)
m.Get("/api", settings.GetGeneralAPISettings)
Expand Down
76 changes: 76 additions & 0 deletions routers/api/v1/misc/licenses.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package misc

import (
"fmt"
"net/http"
"net/url"

"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/options"
repo_module "code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/util"
)

// Returns a list of all License templates
func ListLicenseTemplates(ctx *context.APIContext) {
// swagger:operation GET /licenses miscellaneous listLicenseTemplates
// ---
// summary: Returns a list of all license templates
// produces:
// - application/json
// responses:
// "200":
// "$ref": "#/responses/LicenseTemplateList"
response := make([]api.LicensesTemplateListEntry, len(repo_module.Licenses))
for i, license := range repo_module.Licenses {
response[i] = api.LicensesTemplateListEntry{
Key: license,
Name: license,
URL: fmt.Sprintf("%sapi/v1/licenses/%s", setting.AppURL, url.PathEscape(license)),
}
}
ctx.JSON(http.StatusOK, response)
}

// Returns information about a gitignore template
func GetLicenseTemplateInfo(ctx *context.APIContext) {
// swagger:operation GET /licenses/{name} miscellaneous getLicenseTemplateInfo
// ---
// summary: Returns information about a license template
// produces:
// - application/json
// parameters:
// - name: name
// in: path
// description: name of the license
// type: string
// required: true
// responses:
// "200":
// "$ref": "#/responses/LicenseTemplateInfo"
// "404":
// "$ref": "#/responses/notFound"
name := util.PathJoinRelX(ctx.Params("name"))

text, err := options.License(name)
if err != nil {
ctx.NotFound()
return
}

response := api.LicenseTemplateInfo{
Key: name,
Name: name,
URL: fmt.Sprintf("%sapi/v1/licenses/%s", setting.AppURL, url.PathEscape(name)),
Body: string(text),
// This is for combatibilty with the GitHub API. This Text is for some reason added to each License response.
Implementation: "Create a text file (typically named LICENSE or LICENSE.txt) in the root of your source code and copy the text of the license into the file",
}

ctx.JSON(http.StatusOK, response)
}
14 changes: 14 additions & 0 deletions routers/api/v1/swagger/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ type swaggerResponseServerVersion struct {
Body api.ServerVersion `json:"body"`
}

// LicenseTemplateList
// swagger:response LicenseTemplateList
type swaggerResponseLicensesTemplateList struct {
// in:body
Body []api.LicensesTemplateListEntry `json:"body"`
}

// LicenseTemplateInfo
// swagger:response LicenseTemplateInfo
type swaggerResponseLicenseTemplateInfo struct {
// in:body
Body api.LicenseTemplateInfo `json:"body"`
}

// StringSlice
// swagger:response StringSlice
type swaggerResponseStringSlice struct {
Expand Down
107 changes: 107 additions & 0 deletions templates/swagger/v1_json.tmpl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions tests/integration/api_license_templates_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package integration

import (
"fmt"
"net/http"
"net/url"
"testing"

"code.gitea.io/gitea/modules/options"
repo_module "code.gitea.io/gitea/modules/repository"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"

"github.com/stretchr/testify/assert"
)

func TestAPIListLicenseTemplates(t *testing.T) {
defer tests.PrepareTestEnv(t)()

req := NewRequest(t, "GET", "/api/v1/licenses")
resp := MakeRequest(t, req, http.StatusOK)

// This tests if the API returns a list of strings
var licenseList []api.LicensesTemplateListEntry
DecodeJSON(t, resp, &licenseList)
}

func TestAPIGetLicenseTemplateInfo(t *testing.T) {
defer tests.PrepareTestEnv(t)()

// If Gitea has for some reason no License templates, we need to skip this test
if len(repo_module.Licenses) == 0 {
return
}

// Use the first template for the test
licenseName := repo_module.Licenses[0]

urlStr := fmt.Sprintf("/api/v1/licenses/%s", url.PathEscape(licenseName))
req := NewRequest(t, "GET", urlStr)
resp := MakeRequest(t, req, http.StatusOK)

var licenseInfo api.LicenseTemplateInfo
DecodeJSON(t, resp, &licenseInfo)

// We get the text of the template here
text, _ := options.License(licenseName)

assert.Equal(t, licenseInfo.Key, licenseName)
assert.Equal(t, licenseInfo.Name, licenseName)
assert.Equal(t, licenseInfo.Body, string(text))
}