Rewrite createPullRequest and add createPersonFromIRI

This commit is contained in:
Anthony Wang 2022-11-27 02:05:36 +00:00
parent c982b67626
commit a666eefe8f
No known key found for this signature in database
GPG Key ID: 42A5B952E6DD8D38
5 changed files with 98 additions and 52 deletions

View File

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/forgefed"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/activitypub"
ap "github.com/go-ap/activitypub"
@ -51,7 +52,7 @@ func AuthorizeInteraction(ctx *context.Context) {
ctx.ServerError("PersonIRIToName", err)
return
}
ctx.Redirect(name)
ctx.Redirect(setting.AppSubURL + name)
case forgefed.RepositoryType:
// Federated repository
err = forgefed.OnRepository(object, func(r *forgefed.Repository) error {
@ -66,7 +67,7 @@ func AuthorizeInteraction(ctx *context.Context) {
ctx.ServerError("RepositoryIRIToName", err)
return
}
ctx.Redirect(username + "/" + reponame)
ctx.Redirect(setting.AppSubURL + username + "/" + reponame)
case forgefed.TicketType:
// Federated issue or pull request
err = forgefed.OnTicket(object, func(t *forgefed.Ticket) error {
@ -81,7 +82,7 @@ func AuthorizeInteraction(ctx *context.Context) {
ctx.ServerError("TicketIRIToName", err)
return
}
ctx.Redirect(username + "/" + reponame + "/issues/" + strconv.FormatInt(idx, 10))
ctx.Redirect(setting.AppSubURL + username + "/" + reponame + "/issues/" + strconv.FormatInt(idx, 10))
default:
ctx.ServerError("Not implemented", err)
return

View File

@ -91,9 +91,8 @@ func createPerson(ctx context.Context, person *ap.Person) error {
return user_model.SetUserSetting(user.ID, user_model.UserActivityPubPubPem, person.PublicKey.PublicKeyPem)
}
// Create a new federated repo from a Repository object
func createRepository(ctx context.Context, repository *forgefed.Repository) error {
ownerURL, err := url.Parse(repository.AttributedTo.GetLink().String())
func createPersonFromIRI(ctx context.Context, personIRI ap.IRI) error {
ownerURL, err := url.Parse(personIRI.String())
if err != nil {
return err
}
@ -102,6 +101,7 @@ func createRepository(ctx context.Context, repository *forgefed.Repository) erro
if err != nil {
return err
}
// Parse person object
ap.ItemTyperFunc = forgefed.GetItemByType
ap.JSONItemUnmarshal = forgefed.JSONUnmarshalerFn
@ -110,12 +110,17 @@ func createRepository(ctx context.Context, repository *forgefed.Repository) erro
if err != nil {
return err
}
// Create federated user
err = createPerson(ctx, object.(*ap.Person))
return createPerson(ctx, object.(*ap.Person))
}
// Create a new federated repo from a Repository object
func createRepository(ctx context.Context, repository *forgefed.Repository) error {
err := createPersonFromIRI(ctx, repository.AttributedTo.GetLink())
if err != nil {
return err
}
user, err := activitypub.PersonIRIToUser(ctx, repository.AttributedTo.GetLink())
if err != nil {
return err
@ -145,17 +150,8 @@ func createRepository(ctx context.Context, repository *forgefed.Repository) erro
return nil
}
// Create a ticket
func createTicket(ctx context.Context, ticket *forgefed.Ticket) error {
if ticket.Origin != nil {
return createPullRequest(ctx, ticket)
}
return createIssue(ctx, ticket)
}
// Create an issue
func createIssue(ctx context.Context, ticket *forgefed.Ticket) error {
repoURL, err := url.Parse(ticket.Context.GetLink().String())
func createRepositoryFromIRI(ctx context.Context, repoIRI ap.IRI) error {
repoURL, err := url.Parse(repoIRI.String())
if err != nil {
return err
}
@ -164,6 +160,7 @@ func createIssue(ctx context.Context, ticket *forgefed.Ticket) error {
if err != nil {
return err
}
// Parse repository object
ap.ItemTyperFunc = forgefed.GetItemByType
ap.JSONItemUnmarshal = forgefed.JSONUnmarshalerFn
@ -172,10 +169,24 @@ func createIssue(ctx context.Context, ticket *forgefed.Ticket) error {
if err != nil {
return err
}
// Create federated repo
err = forgefed.OnRepository(object, func(r *forgefed.Repository) error {
return forgefed.OnRepository(object, func(r *forgefed.Repository) error {
return createRepository(ctx, r)
})
}
// Create a ticket
func createTicket(ctx context.Context, ticket *forgefed.Ticket) error {
if ticket.Origin != nil && ticket.Target != nil {
return createPullRequest(ctx, ticket)
}
return createIssue(ctx, ticket)
}
// Create an issue
func createIssue(ctx context.Context, ticket *forgefed.Ticket) error {
err := createRepositoryFromIRI(ctx, ticket.Context.GetLink())
if err != nil {
return err
}
@ -194,53 +205,62 @@ func createIssue(ctx context.Context, ticket *forgefed.Ticket) error {
return err
}
issue := &issues_model.Issue{
Index: idx,
Index: idx, // This doesn't seem to work?
RepoID: repo.ID,
Repo: repo,
Title: ticket.Summary.String(),
PosterID: user.ID,
Poster: user,
Content: ticket.Content.String(),
IsClosed: ticket.IsResolved,
}
return issue_service.NewIssue(repo, issue, nil, nil, nil)
}
// Create a pull request
func createPullRequest(ctx context.Context, ticket *forgefed.Ticket) error {
// TODO: Clean this up
actorUser, err := activitypub.PersonIRIToUser(ctx, ticket.AttributedTo.GetLink())
err := createRepositoryFromIRI(ctx, ticket.Context.GetLink())
if err != nil {
return err
}
// TODO: The IRI processing stuff should be moved to iri.go
originIRI := ticket.Origin.GetLink()
originIRISplit := strings.Split(originIRI.String(), "/")
originInstance := originIRISplit[2]
originUsername := originIRISplit[3]
originReponame := originIRISplit[4]
originBranch := originIRISplit[len(originIRISplit)-1]
originRepo, _ := repo_model.GetRepositoryByOwnerAndName(originUsername+"@"+originInstance, originReponame)
targetIRI := ticket.Target.GetLink()
targetIRISplit := strings.Split(targetIRI.String(), "/")
// targetInstance := targetIRISplit[2]
targetUsername := targetIRISplit[3]
targetReponame := targetIRISplit[4]
targetBranch := targetIRISplit[len(targetIRISplit)-1]
targetRepo, _ := repo_model.GetRepositoryByOwnerAndName(targetUsername, targetReponame)
prIssue := &issues_model.Issue{
RepoID: targetRepo.ID,
Title: "Hello from test.exozy.me!", // Don't hardcode, get the title from the Ticket object
PosterID: actorUser.ID,
Poster: actorUser,
IsPull: true,
Content: "🎉", // TODO: Get content from Ticket object
user, err := activitypub.PersonIRIToUser(ctx, ticket.AttributedTo.GetLink())
if err != nil {
return err
}
// Extract origin and target repos
originUsername, originReponame, originBranch, err := activitypub.BranchIRIToName(ticket.Origin.GetLink())
if err != nil {
return err
}
originRepo, err := repo_model.GetRepositoryByOwnerAndName(originUsername, originReponame)
if err != nil {
return err
}
targetUsername, targetReponame, targetBranch, err := activitypub.BranchIRIToName(ticket.Target.GetLink())
if err != nil {
return err
}
targetRepo, err := repo_model.GetRepositoryByOwnerAndName(targetUsername, targetReponame)
if err != nil {
return err
}
idx, err := strconv.ParseInt(ticket.Name.String()[1:], 10, 64)
if err != nil {
return err
}
prIssue := &issues_model.Issue{
Index: idx,
RepoID: targetRepo.ID,
Title: ticket.Summary.String(),
PosterID: user.ID,
Poster: user,
IsPull: true,
Content: ticket.Content.String(),
IsClosed: ticket.IsResolved,
}
pr := &issues_model.PullRequest{
HeadRepoID: originRepo.ID,
BaseRepoID: targetRepo.ID,
@ -251,12 +271,16 @@ func createPullRequest(ctx context.Context, ticket *forgefed.Ticket) error {
MergeBase: "",
Type: issues_model.PullRequestGitea,
}
return pull_service.NewPullRequest(ctx, targetRepo, prIssue, []int64{}, []string{}, pr, []int64{})
}
// Create a comment
func createComment(ctx context.Context, note *ap.Note) error {
err := createPersonFromIRI(ctx, note.AttributedTo.GetLink())
if err != nil {
return err
}
actorUser, err := activitypub.PersonIRIToUser(ctx, note.AttributedTo.GetLink())
if err != nil {
return err

View File

@ -78,6 +78,8 @@ func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, er
return
}
// 4. Create a federated user for the actor
// TODO: This is a very bad place for creating federated users
// We end up creating way more users than necessary!
var person ap.Person
err = person.UnmarshalJSON(b)
if err != nil {

View File

@ -65,9 +65,9 @@ func Ticket(ctx *context.APIContext) {
return
}
ticket.Name = ap.NaturalLanguageValuesNew()
// Setting a NaturalLanguageValue to a number causes go-ap's JSON parsing to do weird things
// Workaround: set it to #1 instead of 1
ticket.Name = ap.NaturalLanguageValuesNew()
err = ticket.Name.Set("en", ap.Content("#"+ctx.Params("id")))
if err != nil {
ctx.ServerError("Set Name", err)

View File

@ -83,7 +83,7 @@ func RepositoryIRIToRepository(ctx context.Context, repoIRI ap.IRI) (*repo_model
func TicketIRIToName(ticketIRI ap.IRI) (string, string, int64, error) {
ticketIRISplit := strings.Split(ticketIRI.String(), "/")
if len(ticketIRISplit) < 5 {
return "", "", 0, errors.New("not a Ticket actor IRI")
return "", "", 0, errors.New("not a Ticket object IRI")
}
instance := ticketIRISplit[2]
@ -100,3 +100,22 @@ func TicketIRIToName(ticketIRI ap.IRI) (string, string, int64, error) {
// Remote repo
return username + "@" + instance, reponame, idx, nil
}
// Returns the owner, repo name, and idx of a Branch object IRI
func BranchIRIToName(ticketIRI ap.IRI) (string, string, string, error) {
ticketIRISplit := strings.Split(ticketIRI.String(), "/")
if len(ticketIRISplit) < 5 {
return "", "", "", errors.New("not a Branch object IRI")
}
instance := ticketIRISplit[2]
username := ticketIRISplit[len(ticketIRISplit)-3]
reponame := ticketIRISplit[len(ticketIRISplit)-2]
branch := ticketIRISplit[len(ticketIRISplit)-1]
if instance == setting.Domain {
// Local repo
return username, reponame, branch, nil
}
// Remote repo
return username + "@" + instance, reponame, branch, nil
}