mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-28 02:40:38 +00:00
Add Swift login endpoint (#32693)
Fix #32683 This PR adds the login endpoint and fixes the documentation links. (cherry picked from commit 136408307c6de7aac2ab5476f8cddf90f39355dc) Conflicts: routers/api/packages/api.go trivial context conflicts
This commit is contained in:
parent
48131547a1
commit
0786ddc5de
3 changed files with 76 additions and 42 deletions
|
@ -693,40 +693,46 @@ func CommonRoutes() *web.Route {
|
||||||
}, reqPackageAccess(perm.AccessModeWrite))
|
}, reqPackageAccess(perm.AccessModeWrite))
|
||||||
}, reqPackageAccess(perm.AccessModeRead))
|
}, reqPackageAccess(perm.AccessModeRead))
|
||||||
r.Group("/swift", func() {
|
r.Group("/swift", func() {
|
||||||
r.Group("/{scope}/{name}", func() {
|
r.Group("", func() { // Needs to be unauthenticated.
|
||||||
r.Group("", func() {
|
r.Post("", swift.CheckAuthenticate)
|
||||||
r.Get("", swift.EnumeratePackageVersions)
|
r.Post("/login", swift.CheckAuthenticate)
|
||||||
r.Get(".json", swift.EnumeratePackageVersions)
|
})
|
||||||
}, swift.CheckAcceptMediaType(swift.AcceptJSON))
|
r.Group("", func() {
|
||||||
r.Group("/{version}", func() {
|
r.Group("/{scope}/{name}", func() {
|
||||||
r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
|
r.Group("", func() {
|
||||||
r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), enforcePackagesQuota(), swift.UploadPackageFile)
|
r.Get("", swift.EnumeratePackageVersions)
|
||||||
r.Get("", func(ctx *context.Context) {
|
r.Get(".json", swift.EnumeratePackageVersions)
|
||||||
// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
|
}, swift.CheckAcceptMediaType(swift.AcceptJSON))
|
||||||
|
r.Group("/{version}", func() {
|
||||||
|
r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest)
|
||||||
|
r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), enforcePackagesQuota(), swift.UploadPackageFile)
|
||||||
|
r.Get("", func(ctx *context.Context) {
|
||||||
|
// Can't use normal routes here: https://github.com/go-chi/chi/issues/781
|
||||||
|
|
||||||
version := ctx.Params("version")
|
version := ctx.Params("version")
|
||||||
if strings.HasSuffix(version, ".zip") {
|
if strings.HasSuffix(version, ".zip") {
|
||||||
swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
|
swift.CheckAcceptMediaType(swift.AcceptZip)(ctx)
|
||||||
if ctx.Written() {
|
if ctx.Written() {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
ctx.SetParams("version", version[:len(version)-4])
|
||||||
|
swift.DownloadPackageFile(ctx)
|
||||||
|
} else {
|
||||||
|
swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
|
||||||
|
if ctx.Written() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(version, ".json") {
|
||||||
|
ctx.SetParams("version", version[:len(version)-5])
|
||||||
|
}
|
||||||
|
swift.PackageVersionMetadata(ctx)
|
||||||
}
|
}
|
||||||
ctx.SetParams("version", version[:len(version)-4])
|
})
|
||||||
swift.DownloadPackageFile(ctx)
|
|
||||||
} else {
|
|
||||||
swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx)
|
|
||||||
if ctx.Written() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(version, ".json") {
|
|
||||||
ctx.SetParams("version", version[:len(version)-5])
|
|
||||||
}
|
|
||||||
swift.PackageVersionMetadata(ctx)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
|
||||||
r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers)
|
}, reqPackageAccess(perm.AccessModeRead))
|
||||||
}, reqPackageAccess(perm.AccessModeRead))
|
})
|
||||||
r.Group("/vagrant", func() {
|
r.Group("/vagrant", func() {
|
||||||
r.Group("/authenticate", func() {
|
r.Group("/authenticate", func() {
|
||||||
r.Get("", vagrant.CheckAuthenticate)
|
r.Get("", vagrant.CheckAuthenticate)
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/hashicorp/go-version"
|
"github.com/hashicorp/go-version"
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
const (
|
const (
|
||||||
AcceptJSON = "application/vnd.swift.registry.v1+json"
|
AcceptJSON = "application/vnd.swift.registry.v1+json"
|
||||||
AcceptSwift = "application/vnd.swift.registry.v1+swift"
|
AcceptSwift = "application/vnd.swift.registry.v1+swift"
|
||||||
|
@ -35,9 +35,9 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#361-package-scope
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#361-package-scope
|
||||||
scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
|
scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`)
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#362-package-name
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#362-package-name
|
||||||
namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
|
namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ type headers struct {
|
||||||
Link string
|
Link string
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
||||||
if h.ContentType != "" {
|
if h.ContentType != "" {
|
||||||
resp.Header().Set("Content-Type", h.ContentType)
|
resp.Header().Set("Content-Type", h.ContentType)
|
||||||
|
@ -69,7 +69,7 @@ func setResponseHeaders(resp http.ResponseWriter, h *headers) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#33-error-handling
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#33-error-handling
|
||||||
func apiError(ctx *context.Context, status int, obj any) {
|
func apiError(ctx *context.Context, status int, obj any) {
|
||||||
// https://www.rfc-editor.org/rfc/rfc7807
|
// https://www.rfc-editor.org/rfc/rfc7807
|
||||||
type Problem struct {
|
type Problem struct {
|
||||||
|
@ -91,7 +91,7 @@ func apiError(ctx *context.Context, status int, obj any) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#35-api-versioning
|
||||||
func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
|
func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
accept := ctx.Req.Header.Get("Accept")
|
accept := ctx.Req.Header.Get("Accept")
|
||||||
|
@ -101,6 +101,16 @@ func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/PackageRegistryUsage.md#registry-authentication
|
||||||
|
func CheckAuthenticate(ctx *context.Context) {
|
||||||
|
if ctx.Doer == nil {
|
||||||
|
apiError(ctx, http.StatusUnauthorized, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
func buildPackageID(scope, name string) string {
|
func buildPackageID(scope, name string) string {
|
||||||
return scope + "." + name
|
return scope + "." + name
|
||||||
}
|
}
|
||||||
|
@ -113,7 +123,7 @@ type EnumeratePackageVersionsResponse struct {
|
||||||
Releases map[string]Release `json:"releases"`
|
Releases map[string]Release `json:"releases"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#41-list-package-releases
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#41-list-package-releases
|
||||||
func EnumeratePackageVersions(ctx *context.Context) {
|
func EnumeratePackageVersions(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -170,7 +180,7 @@ type PackageVersionMetadataResponse struct {
|
||||||
Metadata *swift_module.SoftwareSourceCode `json:"metadata"`
|
Metadata *swift_module.SoftwareSourceCode `json:"metadata"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-2
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-2
|
||||||
func PackageVersionMetadata(ctx *context.Context) {
|
func PackageVersionMetadata(ctx *context.Context) {
|
||||||
id := buildPackageID(ctx.Params("scope"), ctx.Params("name"))
|
id := buildPackageID(ctx.Params("scope"), ctx.Params("name"))
|
||||||
|
|
||||||
|
@ -228,7 +238,7 @@ func PackageVersionMetadata(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#43-fetch-manifest-for-a-package-release
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#43-fetch-manifest-for-a-package-release
|
||||||
func DownloadManifest(ctx *context.Context) {
|
func DownloadManifest(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -280,7 +290,7 @@ func DownloadManifest(ctx *context.Context) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-6
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-6
|
||||||
func UploadPackageFile(ctx *context.Context) {
|
func UploadPackageFile(ctx *context.Context) {
|
||||||
packageScope := ctx.Params("scope")
|
packageScope := ctx.Params("scope")
|
||||||
packageName := ctx.Params("name")
|
packageName := ctx.Params("name")
|
||||||
|
@ -379,7 +389,7 @@ func UploadPackageFile(ctx *context.Context) {
|
||||||
ctx.Status(http.StatusCreated)
|
ctx.Status(http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-4
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-4
|
||||||
func DownloadPackageFile(ctx *context.Context) {
|
func DownloadPackageFile(ctx *context.Context) {
|
||||||
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version"))
|
pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -420,7 +430,7 @@ type LookupPackageIdentifiersResponse struct {
|
||||||
Identifiers []string `json:"identifiers"`
|
Identifiers []string `json:"identifiers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-5
|
// https://github.com/swiftlang/swift-package-manager/blob/main/Documentation/PackageRegistry/Registry.md#endpoint-5
|
||||||
func LookupPackageIdentifiers(ctx *context.Context) {
|
func LookupPackageIdentifiers(ctx *context.Context) {
|
||||||
url := ctx.FormTrim("url")
|
url := ctx.FormTrim("url")
|
||||||
if url == "" {
|
if url == "" {
|
||||||
|
|
|
@ -43,6 +43,24 @@ func TestPackageSwift(t *testing.T) {
|
||||||
|
|
||||||
url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
|
url := fmt.Sprintf("/api/packages/%s/swift", user.Name)
|
||||||
|
|
||||||
|
t.Run("CheckLogin", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
req := NewRequestWithBody(t, "POST", url, strings.NewReader(""))
|
||||||
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url, strings.NewReader("")).
|
||||||
|
AddBasicAuth(user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader(""))
|
||||||
|
MakeRequest(t, req, http.StatusUnauthorized)
|
||||||
|
|
||||||
|
req = NewRequestWithBody(t, "POST", url+"/login", strings.NewReader("")).
|
||||||
|
AddBasicAuth(user.Name)
|
||||||
|
MakeRequest(t, req, http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
t.Run("CheckAcceptMediaType", func(t *testing.T) {
|
t.Run("CheckAcceptMediaType", func(t *testing.T) {
|
||||||
defer tests.PrintCurrentTest(t)()
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue