fix review
This commit is contained in:
parent
5620dd76fa
commit
2f7f1aab8a
7 changed files with 86 additions and 22 deletions
|
@ -72,6 +72,8 @@ var migrations = []*Migration{
|
||||||
NewMigration("Create the `federated_user` table", CreateFederatedUserTable),
|
NewMigration("Create the `federated_user` table", CreateFederatedUserTable),
|
||||||
// v17 -> v18
|
// v17 -> v18
|
||||||
NewMigration("Add `normalized_federated_uri` column to `user` table", AddNormalizedFederatedURIToUser),
|
NewMigration("Add `normalized_federated_uri` column to `user` table", AddNormalizedFederatedURIToUser),
|
||||||
|
// v18 -> v19
|
||||||
|
NewMigration("Create the `following_repo` table", CreateFollowingRepoTable),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||||
|
|
18
models/forgejo_migrations/v18.go
Normal file
18
models/forgejo_migrations/v18.go
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package forgejo_migrations //nolint:revive
|
||||||
|
|
||||||
|
import "xorm.io/xorm"
|
||||||
|
|
||||||
|
type FollowingRepo struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
RepoID int64 `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
|
||||||
|
ExternalID string `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
|
||||||
|
FederationHostID int64 `xorm:"UNIQUE(federation_repo_mapping) NOT NULL"`
|
||||||
|
URI string
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateFollowingRepoTable(x *xorm.Engine) error {
|
||||||
|
return x.Sync(new(FederatedUser))
|
||||||
|
}
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
|
|
||||||
ap "github.com/go-ap/activitypub"
|
ap "github.com/go-ap/activitypub"
|
||||||
|
@ -71,10 +70,6 @@ type PersonID struct {
|
||||||
|
|
||||||
// Factory function for PersonID. Created struct is asserted to be valid
|
// Factory function for PersonID. Created struct is asserted to be valid
|
||||||
func NewPersonID(uri, source string) (PersonID, error) {
|
func NewPersonID(uri, source string) (PersonID, error) {
|
||||||
// TODO: remove after test
|
|
||||||
//if !validation.IsValidExternalURL(uri) {
|
|
||||||
// return PersonId{}, fmt.Errorf("uri %s is not a valid external url", uri)
|
|
||||||
//}
|
|
||||||
result, err := newActorID(uri)
|
result, err := newActorID(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return PersonID{}, err
|
return PersonID{}, err
|
||||||
|
@ -126,16 +121,13 @@ type RepositoryID struct {
|
||||||
|
|
||||||
// Factory function for RepositoryID. Created struct is asserted to be valid.
|
// Factory function for RepositoryID. Created struct is asserted to be valid.
|
||||||
func NewRepositoryID(uri, source string) (RepositoryID, error) {
|
func NewRepositoryID(uri, source string) (RepositoryID, error) {
|
||||||
if !validation.IsAPIURL(uri) {
|
|
||||||
return RepositoryID{}, fmt.Errorf("uri %s is not a valid repo url on this host %s", uri, setting.AppURL+"api")
|
|
||||||
}
|
|
||||||
result, err := newActorID(uri)
|
result, err := newActorID(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RepositoryID{}, err
|
return RepositoryID{}, err
|
||||||
}
|
}
|
||||||
result.Source = source
|
result.Source = source
|
||||||
|
|
||||||
// validate Person specific path
|
// validate Person specific
|
||||||
repoID := RepositoryID{result}
|
repoID := RepositoryID{result}
|
||||||
if valid, err := validation.IsValid(repoID); !valid {
|
if valid, err := validation.IsValid(repoID); !valid {
|
||||||
return RepositoryID{}, err
|
return RepositoryID{}, err
|
||||||
|
|
|
@ -1131,7 +1131,6 @@ form.reach_limit_of_creation_1=Du hast bereits dein Limit von %d Repository erre
|
||||||
form.reach_limit_of_creation_n=Du hast bereits dein Limit von %d Repositorys erreicht.
|
form.reach_limit_of_creation_n=Du hast bereits dein Limit von %d Repositorys erreicht.
|
||||||
form.name_reserved=Der Repository-Name „%s“ ist reserviert.
|
form.name_reserved=Der Repository-Name „%s“ ist reserviert.
|
||||||
form.name_pattern_not_allowed=Das Muster „%s“ ist in Repository-Namen nicht erlaubt.
|
form.name_pattern_not_allowed=Das Muster „%s“ ist in Repository-Namen nicht erlaubt.
|
||||||
form.string_too_long=Der angegebene String ist länger als %d Zeichen.
|
|
||||||
|
|
||||||
need_auth=Authentifizierung
|
need_auth=Authentifizierung
|
||||||
migrate_options=Migrationsoptionen
|
migrate_options=Migrationsoptionen
|
||||||
|
@ -2061,10 +2060,6 @@ settings.collaboration.undefined=Nicht definiert
|
||||||
settings.hooks=Webhooks
|
settings.hooks=Webhooks
|
||||||
settings.githooks=Git-Hooks
|
settings.githooks=Git-Hooks
|
||||||
settings.basic_settings=Grundeinstellungen
|
settings.basic_settings=Grundeinstellungen
|
||||||
settings.federation_settings=Föderationseinstellungen
|
|
||||||
settings.federation_apapiurl=Föderierungs-URL dieses Repositories. Kopiere sie und füge sie in die Föderationseinstellungen eines anderen Repository ein als dem Repository folgendes Repository.
|
|
||||||
settings.federation_following_repos=URLs der Repos, die diesem Repo folgen. Getrennt mittels ";", keine Leerzeichen.
|
|
||||||
settings.federation_not_enabled=Föderierung ist auf deiner Instanz nicht aktiviert.
|
|
||||||
settings.mirror_settings=Spiegeleinstellungen
|
settings.mirror_settings=Spiegeleinstellungen
|
||||||
settings.mirror_settings.docs=Richte dein Repository so ein, dass es automatisch Commits, Tags und Branches mit einem anderen Repository synchronisieren kann.
|
settings.mirror_settings.docs=Richte dein Repository so ein, dass es automatisch Commits, Tags und Branches mit einem anderen Repository synchronisieren kann.
|
||||||
settings.mirror_settings.docs.disabled_pull_mirror.instructions=Richte dein Projekt so ein, dass es automatisch Commits, Tags und Branches in ein anderes Repository pusht. Pull-Spiegel wurden von deinem Website-Administrator deaktiviert.
|
settings.mirror_settings.docs.disabled_pull_mirror.instructions=Richte dein Projekt so ein, dass es automatisch Commits, Tags und Branches in ein anderes Repository pusht. Pull-Spiegel wurden von deinem Website-Administrator deaktiviert.
|
||||||
|
|
|
@ -391,22 +391,21 @@ func SettingsPost(ctx *context.Context) {
|
||||||
ctx.Flash.Info(ctx.Tr("repo.settings.federation_not_enabled"))
|
ctx.Flash.Info(ctx.Tr("repo.settings.federation_not_enabled"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// ToDo: Rename to followingRepos
|
followingRepos := strings.TrimSpace(form.FollowingRepos)
|
||||||
federationRepos := strings.TrimSpace(form.FederationRepos)
|
followingRepos = strings.TrimSuffix(followingRepos, ";")
|
||||||
federationRepos = strings.TrimSuffix(federationRepos, ";")
|
|
||||||
|
|
||||||
maxFollowingRepoStrLength := 2048
|
maxFollowingRepoStrLength := 2048
|
||||||
errs := validation.ValidateMaxLen(federationRepos, maxFollowingRepoStrLength, "federationRepos")
|
errs := validation.ValidateMaxLen(followingRepos, maxFollowingRepoStrLength, "federationRepos")
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
ctx.Data["ERR_FederationRepos"] = true
|
ctx.Data["ERR_FollowingRepos"] = true
|
||||||
ctx.Flash.Error(ctx.Tr("repo.form.string_too_long", maxFollowingRepoStrLength))
|
ctx.Flash.Error(ctx.Tr("repo.form.string_too_long", maxFollowingRepoStrLength))
|
||||||
ctx.Redirect(repo.Link() + "/settings")
|
ctx.Redirect(repo.Link() + "/settings")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
federationRepoSplit := []string{}
|
federationRepoSplit := []string{}
|
||||||
if federationRepos != "" {
|
if followingRepos != "" {
|
||||||
federationRepoSplit = strings.Split(federationRepos, ";")
|
federationRepoSplit = strings.Split(followingRepos, ";")
|
||||||
}
|
}
|
||||||
for idx, repo := range federationRepoSplit {
|
for idx, repo := range federationRepoSplit {
|
||||||
federationRepoSplit[idx] = strings.TrimSpace(repo)
|
federationRepoSplit[idx] = strings.TrimSpace(repo)
|
||||||
|
|
|
@ -114,7 +114,7 @@ type RepoSettingForm struct {
|
||||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
Description string `binding:"MaxSize(2048)"`
|
Description string `binding:"MaxSize(2048)"`
|
||||||
Website string `binding:"ValidUrl;MaxSize(1024)"`
|
Website string `binding:"ValidUrl;MaxSize(1024)"`
|
||||||
FederationRepos string
|
FollowingRepos string
|
||||||
Interval string
|
Interval string
|
||||||
MirrorAddress string
|
MirrorAddress string
|
||||||
MirrorUsername string
|
MirrorUsername string
|
||||||
|
|
|
@ -6,9 +6,11 @@ package integration
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/forgefed"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
unit_model "code.gitea.io/gitea/models/unit"
|
unit_model "code.gitea.io/gitea/models/unit"
|
||||||
|
@ -263,3 +265,59 @@ func TestProtectedBranch(t *testing.T) {
|
||||||
unittest.AssertCount(t, &git_model.ProtectedBranch{RuleName: "master", RepoID: repo.ID}, 1)
|
unittest.AssertCount(t, &git_model.ProtectedBranch{RuleName: "master", RepoID: repo.ID}, 1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRepoFollowing(t *testing.T) {
|
||||||
|
setting.Federation.Enabled = true
|
||||||
|
defer tests.PrepareTestEnv(t)()
|
||||||
|
defer func() {
|
||||||
|
setting.Federation.Enabled = false
|
||||||
|
}()
|
||||||
|
|
||||||
|
federatedRoutes := http.NewServeMux()
|
||||||
|
federatedRoutes.HandleFunc("/.well-known/nodeinfo",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo
|
||||||
|
responseBody := fmt.Sprintf(`{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host)
|
||||||
|
t.Logf("response: %s", responseBody)
|
||||||
|
// TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8
|
||||||
|
fmt.Fprint(res, responseBody)
|
||||||
|
})
|
||||||
|
federatedRoutes.HandleFunc("/api/v1/nodeinfo",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo
|
||||||
|
responseBody := fmt.Sprintf(`{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",` +
|
||||||
|
`"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},` +
|
||||||
|
`"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},` +
|
||||||
|
`"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`)
|
||||||
|
fmt.Fprint(res, responseBody)
|
||||||
|
})
|
||||||
|
federatedRoutes.HandleFunc("/",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
t.Errorf("Unhandled request: %q", req.URL.EscapedPath())
|
||||||
|
})
|
||||||
|
federatedSrv := httptest.NewServer(federatedRoutes)
|
||||||
|
defer federatedSrv.Close()
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1, OwnerID: user.ID})
|
||||||
|
session := loginUser(t, user.Name)
|
||||||
|
|
||||||
|
t.Run("Add a following repo", func(t *testing.T) {
|
||||||
|
defer tests.PrintCurrentTest(t)()
|
||||||
|
link := fmt.Sprintf("/%s/settings", repo.FullName())
|
||||||
|
|
||||||
|
req := NewRequestWithValues(t, "POST", link, map[string]string{
|
||||||
|
"_csrf": GetCSRF(t, session, link),
|
||||||
|
"action": "federation",
|
||||||
|
"following_repos": fmt.Sprintf("%s/api/v1/activitypub/repository-id/1", federatedSrv.URL),
|
||||||
|
})
|
||||||
|
session.MakeRequest(t, req, http.StatusSeeOther)
|
||||||
|
|
||||||
|
// Verify it was added.
|
||||||
|
federationHost := unittest.AssertExistsAndLoadBean(t, &forgefed.FederationHost{HostFqdn: "127.0.0.1"})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &repo_model.FollowingRepo{
|
||||||
|
ExternalID: "1",
|
||||||
|
FederationHostID: federationHost.ID,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue