Compare commits

...

5 Commits

4 changed files with 50 additions and 36 deletions

View File

@ -33,33 +33,29 @@ func IsPinned(ctx context.Context, userID, repoID int64) bool {
}
func PinRepo(ctx context.Context, doer *user_model.User, repo *Repository, pin bool) error {
ctx, commiter, err := db.TxContext(ctx)
if err != nil {
return err
}
return db.WithTx(ctx, func(ctx context.Context) error {
pinned := IsPinned(ctx, doer.ID, repo.ID)
defer commiter.Close()
pinned := IsPinned(ctx, doer.ID, repo.ID)
if pin {
// Already pinned, nothing to do
if pinned {
return nil
}
if pin {
// Already pinned, nothing to do
if pinned {
return nil
if err := db.Insert(ctx, &Pin{UID: doer.ID, RepoID: repo.ID}); err != nil {
return err
}
} else {
// Not pinned, nothing to do
if !pinned {
return nil
}
if _, err := db.DeleteByBean(ctx, &Pin{UID: doer.ID, RepoID: repo.ID}); err != nil {
return err
}
}
if err = db.Insert(ctx, &Pin{UID: doer.ID, RepoID: repo.ID}); err != nil {
return err
}
} else {
// Not pinned, nothing to do
if !pinned {
return nil
}
if _, err = db.DeleteByBean(ctx, &Pin{UID: doer.ID, RepoID: repo.ID}); err != nil {
return err
}
}
return commiter.Commit()
return nil
})
}

View File

@ -85,6 +85,10 @@ func GetPinnedRepos(ctx context.Context, opts *PinnedReposOptions) (RepositoryLi
return db.Find[Repository](ctx, opts)
}
func CountPinnedRepos(ctx context.Context, opts *PinnedReposOptions) (int64, error) {
return db.Count[Repository](ctx, opts)
}
type WatchedReposOptions struct {
db.ListOptions
WatcherID int64

View File

@ -797,6 +797,7 @@ func Home(ctx *context.Context) {
err := loadPinData(ctx)
if err != nil {
ctx.ServerError("loadPinData", err)
return
}
}
@ -1186,7 +1187,10 @@ func loadPinData(ctx *context.Context) error {
}
ctx.Data["IsPinningRepo"] = repo_model.IsPinned(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID)
ctx.Data["CanPinRepo"] = user_service.CanPin(ctx, ctx.Doer, ctx.Repo.Repository)
ctx.Data["CanPinRepo"], err = user_service.CanPin(ctx, ctx.Doer, ctx.Repo.Repository)
if err != nil {
return err
}
if ctx.Repo.Repository.Owner.IsOrganization() {
org := organization.OrgFromUser(ctx.Repo.Repository.Owner)
@ -1199,7 +1203,10 @@ func loadPinData(ctx *context.Context) error {
if isAdmin {
ctx.Data["CanUserPinToOrg"] = true
ctx.Data["IsOrgPinningRepo"] = repo_model.IsPinned(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
ctx.Data["CanOrgPinRepo"] = user_service.CanPin(ctx, ctx.Repo.Repository.Owner, ctx.Repo.Repository)
ctx.Data["CanOrgPinRepo"], err = user_service.CanPin(ctx, ctx.Repo.Repository.Owner, ctx.Repo.Repository)
if err != nil {
return err
}
}
}

View File

@ -14,24 +14,27 @@ import (
"code.gitea.io/gitea/services/context"
)
const maxPins = 6
// Check if a user have a new pinned repo in it's profile, meaning that it
// has permissions to pin said repo and also has enough space on the pinned list.
func CanPin(ctx *context.Context, u *user_model.User, r *repo_model.Repository) bool {
repos, err := repo_model.GetPinnedRepos(*ctx, &repo_model.PinnedReposOptions{
func CanPin(ctx *context.Context, u *user_model.User, r *repo_model.Repository) (bool, error) {
count, err := repo_model.CountPinnedRepos(*ctx, &repo_model.PinnedReposOptions{
ListOptions: db.ListOptions{
ListAll: true,
},
PinnerID: u.ID,
})
if err != nil {
ctx.ServerError("GetPinnedRepos", err)
return false
}
if len(repos) >= 6 {
return false
ctx.ServerError("CountPinnedRepos", err)
return false, err
}
return HasPermsToPin(ctx, u, r)
if count >= maxPins {
return false, nil
}
return HasPermsToPin(ctx, u, r), nil
}
// Checks if the user has permission to have the repo pinned in it's profile.
@ -136,7 +139,11 @@ func PinRepo(ctx *context.Context, doer *user_model.User, repo *repo_model.Repos
}
if pin {
if !CanPin(ctx, targetUser, repo) {
canPin, err := CanPin(ctx, targetUser, repo)
if err != nil {
return err
}
if !canPin {
return errors.New("user cannot pin this repository")
}
}