mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-09-12 18:03:57 +02:00
The global wiki editability can be set via the web UI, this patch makes it possible to set the same thing via the API too. This is accomplished by adjusting the GET and PATCH handlers of the `/api/v1/repos/{owner}/{repo}` route. The first will include the property when checking the repo's settings, the second allows a repo admin to change the setting too. Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
253 lines
9.5 KiB
Go
253 lines
9.5 KiB
Go
// Copyright 2020 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package convert
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models"
|
|
"code.gitea.io/gitea/models/db"
|
|
"code.gitea.io/gitea/models/perm"
|
|
access_model "code.gitea.io/gitea/models/perm/access"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
unit_model "code.gitea.io/gitea/models/unit"
|
|
"code.gitea.io/gitea/modules/log"
|
|
api "code.gitea.io/gitea/modules/structs"
|
|
)
|
|
|
|
// ToRepo converts a Repository to api.Repository
|
|
func ToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission) *api.Repository {
|
|
return innerToRepo(ctx, repo, permissionInRepo, false)
|
|
}
|
|
|
|
func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInRepo access_model.Permission, isParent bool) *api.Repository {
|
|
var parent *api.Repository
|
|
|
|
if permissionInRepo.Units == nil && permissionInRepo.UnitsMode == nil {
|
|
// If Units and UnitsMode are both nil, it means that it's a hard coded permission,
|
|
// like access_model.Permission{AccessMode: perm.AccessModeAdmin}.
|
|
// So we need to load units for the repo, or UnitAccessMode will always return perm.AccessModeNone.
|
|
_ = repo.LoadUnits(ctx) // the error is not important, so ignore it
|
|
permissionInRepo.Units = repo.Units
|
|
}
|
|
|
|
cloneLink := repo.CloneLink()
|
|
permission := &api.Permission{
|
|
Admin: permissionInRepo.AccessMode >= perm.AccessModeAdmin,
|
|
Push: permissionInRepo.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeWrite,
|
|
Pull: permissionInRepo.UnitAccessMode(unit_model.TypeCode) >= perm.AccessModeRead,
|
|
}
|
|
if !isParent {
|
|
err := repo.GetBaseRepo(ctx)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if repo.BaseRepo != nil {
|
|
// FIXME: The permission of the parent repo is not correct.
|
|
// It's the permission of the current repo, so it's probably different from the parent repo.
|
|
// But there isn't a good way to get the permission of the parent repo, because the doer is not passed in.
|
|
// Use the permission of the current repo to keep the behavior consistent with the old API.
|
|
// Maybe the right way is setting the permission of the parent repo to nil, empty is better than wrong.
|
|
parent = innerToRepo(ctx, repo.BaseRepo, permissionInRepo, true)
|
|
}
|
|
}
|
|
|
|
// check enabled/disabled units
|
|
hasIssues := false
|
|
var externalTracker *api.ExternalTracker
|
|
var internalTracker *api.InternalTracker
|
|
if unit, err := repo.GetUnit(ctx, unit_model.TypeIssues); err == nil {
|
|
config := unit.IssuesConfig()
|
|
hasIssues = true
|
|
internalTracker = &api.InternalTracker{
|
|
EnableTimeTracker: config.EnableTimetracker,
|
|
AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
|
|
EnableIssueDependencies: config.EnableDependencies,
|
|
}
|
|
} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalTracker); err == nil {
|
|
config := unit.ExternalTrackerConfig()
|
|
hasIssues = true
|
|
externalTracker = &api.ExternalTracker{
|
|
ExternalTrackerURL: config.ExternalTrackerURL,
|
|
ExternalTrackerFormat: config.ExternalTrackerFormat,
|
|
ExternalTrackerStyle: config.ExternalTrackerStyle,
|
|
ExternalTrackerRegexpPattern: config.ExternalTrackerRegexpPattern,
|
|
}
|
|
}
|
|
hasWiki := false
|
|
globallyEditableWiki := false
|
|
var externalWiki *api.ExternalWiki
|
|
if wikiUnit, err := repo.GetUnit(ctx, unit_model.TypeWiki); err == nil {
|
|
hasWiki = true
|
|
if wikiUnit.DefaultPermissions == repo_model.UnitAccessModeWrite {
|
|
globallyEditableWiki = true
|
|
}
|
|
} else if unit, err := repo.GetUnit(ctx, unit_model.TypeExternalWiki); err == nil {
|
|
hasWiki = true
|
|
config := unit.ExternalWikiConfig()
|
|
externalWiki = &api.ExternalWiki{
|
|
ExternalWikiURL: config.ExternalWikiURL,
|
|
}
|
|
}
|
|
hasPullRequests := false
|
|
ignoreWhitespaceConflicts := false
|
|
allowMerge := false
|
|
allowRebase := false
|
|
allowRebaseMerge := false
|
|
allowSquash := false
|
|
allowFastForwardOnly := false
|
|
allowRebaseUpdate := false
|
|
defaultDeleteBranchAfterMerge := false
|
|
defaultMergeStyle := repo_model.MergeStyleMerge
|
|
defaultAllowMaintainerEdit := false
|
|
if unit, err := repo.GetUnit(ctx, unit_model.TypePullRequests); err == nil {
|
|
config := unit.PullRequestsConfig()
|
|
hasPullRequests = true
|
|
ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
|
|
allowMerge = config.AllowMerge
|
|
allowRebase = config.AllowRebase
|
|
allowRebaseMerge = config.AllowRebaseMerge
|
|
allowSquash = config.AllowSquash
|
|
allowFastForwardOnly = config.AllowFastForwardOnly
|
|
allowRebaseUpdate = config.AllowRebaseUpdate
|
|
defaultDeleteBranchAfterMerge = config.DefaultDeleteBranchAfterMerge
|
|
defaultMergeStyle = config.GetDefaultMergeStyle()
|
|
defaultAllowMaintainerEdit = config.DefaultAllowMaintainerEdit
|
|
}
|
|
hasProjects := false
|
|
if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil {
|
|
hasProjects = true
|
|
}
|
|
|
|
hasReleases := false
|
|
if _, err := repo.GetUnit(ctx, unit_model.TypeReleases); err == nil {
|
|
hasReleases = true
|
|
}
|
|
|
|
hasPackages := false
|
|
if _, err := repo.GetUnit(ctx, unit_model.TypePackages); err == nil {
|
|
hasPackages = true
|
|
}
|
|
|
|
hasActions := false
|
|
if _, err := repo.GetUnit(ctx, unit_model.TypeActions); err == nil {
|
|
hasActions = true
|
|
}
|
|
|
|
if err := repo.LoadOwner(ctx); err != nil {
|
|
return nil
|
|
}
|
|
|
|
numReleases, _ := db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{
|
|
IncludeDrafts: false,
|
|
IncludeTags: false,
|
|
RepoID: repo.ID,
|
|
})
|
|
|
|
mirrorInterval := ""
|
|
var mirrorUpdated time.Time
|
|
if repo.IsMirror {
|
|
pullMirror, err := repo_model.GetMirrorByRepoID(ctx, repo.ID)
|
|
if err == nil {
|
|
mirrorInterval = pullMirror.Interval.String()
|
|
mirrorUpdated = pullMirror.UpdatedUnix.AsTime()
|
|
}
|
|
}
|
|
|
|
var transfer *api.RepoTransfer
|
|
if repo.Status == repo_model.RepositoryPendingTransfer {
|
|
t, err := models.GetPendingRepositoryTransfer(ctx, repo)
|
|
if err != nil && !models.IsErrNoPendingTransfer(err) {
|
|
log.Warn("GetPendingRepositoryTransfer: %v", err)
|
|
} else {
|
|
if err := t.LoadAttributes(ctx); err != nil {
|
|
log.Warn("LoadAttributes of RepoTransfer: %v", err)
|
|
} else {
|
|
transfer = ToRepoTransfer(ctx, t)
|
|
}
|
|
}
|
|
}
|
|
|
|
var language string
|
|
if repo.PrimaryLanguage != nil {
|
|
language = repo.PrimaryLanguage.Language
|
|
}
|
|
|
|
repoAPIURL := repo.APIURL()
|
|
|
|
return &api.Repository{
|
|
ID: repo.ID,
|
|
Owner: ToUserWithAccessMode(ctx, repo.Owner, permissionInRepo.AccessMode),
|
|
Name: repo.Name,
|
|
FullName: repo.FullName(),
|
|
Description: repo.Description,
|
|
Private: repo.IsPrivate,
|
|
Template: repo.IsTemplate,
|
|
Empty: repo.IsEmpty,
|
|
Archived: repo.IsArchived,
|
|
Size: int(repo.Size / 1024),
|
|
Fork: repo.IsFork,
|
|
Parent: parent,
|
|
Mirror: repo.IsMirror,
|
|
HTMLURL: repo.HTMLURL(),
|
|
URL: repoAPIURL,
|
|
SSHURL: cloneLink.SSH,
|
|
CloneURL: cloneLink.HTTPS,
|
|
OriginalURL: repo.SanitizedOriginalURL(),
|
|
Website: repo.Website,
|
|
Language: language,
|
|
LanguagesURL: repoAPIURL + "/languages",
|
|
Stars: repo.NumStars,
|
|
Forks: repo.NumForks,
|
|
Watchers: repo.NumWatches,
|
|
OpenIssues: repo.NumOpenIssues,
|
|
OpenPulls: repo.NumOpenPulls,
|
|
Releases: int(numReleases),
|
|
DefaultBranch: repo.DefaultBranch,
|
|
Created: repo.CreatedUnix.AsTime(),
|
|
Updated: repo.UpdatedUnix.AsTime(),
|
|
ArchivedAt: repo.ArchivedUnix.AsTime(),
|
|
Permissions: permission,
|
|
HasIssues: hasIssues,
|
|
ExternalTracker: externalTracker,
|
|
InternalTracker: internalTracker,
|
|
HasWiki: hasWiki,
|
|
WikiBranch: repo.WikiBranch,
|
|
GloballyEditableWiki: globallyEditableWiki,
|
|
HasProjects: hasProjects,
|
|
HasReleases: hasReleases,
|
|
HasPackages: hasPackages,
|
|
HasActions: hasActions,
|
|
ExternalWiki: externalWiki,
|
|
HasPullRequests: hasPullRequests,
|
|
IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts,
|
|
AllowMerge: allowMerge,
|
|
AllowRebase: allowRebase,
|
|
AllowRebaseMerge: allowRebaseMerge,
|
|
AllowSquash: allowSquash,
|
|
AllowFastForwardOnly: allowFastForwardOnly,
|
|
AllowRebaseUpdate: allowRebaseUpdate,
|
|
DefaultDeleteBranchAfterMerge: defaultDeleteBranchAfterMerge,
|
|
DefaultMergeStyle: string(defaultMergeStyle),
|
|
DefaultAllowMaintainerEdit: defaultAllowMaintainerEdit,
|
|
AvatarURL: repo.AvatarLink(ctx),
|
|
Internal: !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
|
|
MirrorInterval: mirrorInterval,
|
|
MirrorUpdated: mirrorUpdated,
|
|
RepoTransfer: transfer,
|
|
}
|
|
}
|
|
|
|
// ToRepoTransfer convert a models.RepoTransfer to a structs.RepeTransfer
|
|
func ToRepoTransfer(ctx context.Context, t *models.RepoTransfer) *api.RepoTransfer {
|
|
teams, _ := ToTeams(ctx, t.Teams, false)
|
|
|
|
return &api.RepoTransfer{
|
|
Doer: ToUser(ctx, t.Doer, nil),
|
|
Recipient: ToUser(ctx, t.Recipient, nil),
|
|
Teams: teams,
|
|
}
|
|
}
|