diff options
author | Lunny Xiao <xiaolunwen@gmail.com> | 2022-08-25 10:31:57 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-25 10:31:57 +0800 |
commit | 1d8543e7db58d7c4973758e47f005c4d8bd7d7a3 (patch) | |
tree | b60c99e2dfd69ccb998f8a0829d98d7cadcf0d6b /modules | |
parent | 4a4bfafa238bf48851f8c11fa3701bd42b912475 (diff) | |
download | gitea-1d8543e7db58d7c4973758e47f005c4d8bd7d7a3.tar.gz gitea-1d8543e7db58d7c4973758e47f005c4d8bd7d7a3.zip |
Move some files into models' sub packages (#20262)
* Move some files into models' sub packages
* Move functions
* merge main branch
* Fix check
* fix check
* Fix some tests
* Fix lint
* Fix lint
* Revert lint changes
* Fix error comments
* Fix lint
Co-authored-by: 6543 <6543@obermui.de>
Diffstat (limited to 'modules')
24 files changed, 629 insertions, 164 deletions
diff --git a/modules/context/repo.go b/modules/context/repo.go index ea40542069..1e0f6461a2 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -118,7 +118,8 @@ type CanCommitToBranchResults struct { } // CanCommitToBranch returns true if repository is editable and user has proper access level -// and branch is not protected for push +// +// and branch is not protected for push func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.User) (CanCommitToBranchResults, error) { protectedBranch, err := git_model.GetProtectedBranchBy(ctx, r.Repository.ID, r.BranchName) if err != nil { @@ -523,14 +524,14 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) { ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL } - ctx.Data["NumTags"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ + ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ IncludeTags: true, }) if err != nil { ctx.ServerError("GetReleaseCountByRepoID", err) return } - ctx.Data["NumReleases"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{}) + ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{}) if err != nil { ctx.ServerError("GetReleaseCountByRepoID", err) return diff --git a/modules/convert/notification.go b/modules/convert/notification.go index 1efba5745c..55f782f8f6 100644 --- a/modules/convert/notification.go +++ b/modules/convert/notification.go @@ -7,17 +7,17 @@ package convert import ( "net/url" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/perm" api "code.gitea.io/gitea/modules/structs" ) // ToNotificationThread convert a Notification to api.NotificationThread -func ToNotificationThread(n *models.Notification) *api.NotificationThread { +func ToNotificationThread(n *activities_model.Notification) *api.NotificationThread { result := &api.NotificationThread{ ID: n.ID, - Unread: !(n.Status == models.NotificationStatusRead || n.Status == models.NotificationStatusPinned), - Pinned: n.Status == models.NotificationStatusPinned, + Unread: !(n.Status == activities_model.NotificationStatusRead || n.Status == activities_model.NotificationStatusPinned), + Pinned: n.Status == activities_model.NotificationStatusPinned, UpdatedAt: n.UpdatedUnix.AsTime(), URL: n.APIURL(), } @@ -34,7 +34,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread { // handle Subject switch n.Source { - case models.NotificationSourceIssue: + case activities_model.NotificationSourceIssue: result.Subject = &api.NotificationSubject{Type: api.NotifySubjectIssue} if n.Issue != nil { result.Subject.Title = n.Issue.Title @@ -47,7 +47,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread { result.Subject.LatestCommentHTMLURL = comment.HTMLURL() } } - case models.NotificationSourcePullRequest: + case activities_model.NotificationSourcePullRequest: result.Subject = &api.NotificationSubject{Type: api.NotifySubjectPull} if n.Issue != nil { result.Subject.Title = n.Issue.Title @@ -65,7 +65,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread { result.Subject.State = "merged" } } - case models.NotificationSourceCommit: + case activities_model.NotificationSourceCommit: url := n.Repository.HTMLURL() + "/commit/" + url.PathEscape(n.CommitID) result.Subject = &api.NotificationSubject{ Type: api.NotifySubjectCommit, @@ -73,7 +73,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread { URL: url, HTMLURL: url, } - case models.NotificationSourceRepository: + case activities_model.NotificationSourceRepository: result.Subject = &api.NotificationSubject{ Type: api.NotifySubjectRepository, Title: n.Repository.FullName(), @@ -87,7 +87,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread { } // ToNotifications convert list of Notification to api.NotificationThread list -func ToNotifications(nl models.NotificationList) []*api.NotificationThread { +func ToNotifications(nl activities_model.NotificationList) []*api.NotificationThread { result := make([]*api.NotificationThread, 0, len(nl)) for _, n := range nl { result = append(result, ToNotificationThread(n)) diff --git a/modules/convert/release.go b/modules/convert/release.go index 955d3ff05f..5fc95dab72 100644 --- a/modules/convert/release.go +++ b/modules/convert/release.go @@ -5,13 +5,12 @@ package convert import ( - "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" api "code.gitea.io/gitea/modules/structs" ) -// ToRelease convert a models.Release to api.Release -func ToRelease(r *models.Release) *api.Release { +// ToRelease convert a repo_model.Release to api.Release +func ToRelease(r *repo_model.Release) *api.Release { assets := make([]*api.Attachment, 0) for _, att := range r.Attachments { assets = append(assets, ToReleaseAttachment(att)) diff --git a/modules/convert/repository.go b/modules/convert/repository.go index d333c124b5..f853163848 100644 --- a/modules/convert/repository.go +++ b/modules/convert/repository.go @@ -102,7 +102,7 @@ func innerToRepo(repo *repo_model.Repository, mode perm.AccessMode, isParent boo return nil } - numReleases, _ := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false}) + numReleases, _ := repo_model.GetReleaseCountByRepoID(repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false}) mirrorInterval := "" var mirrorUpdated time.Time diff --git a/modules/doctor/dbconsistency.go b/modules/doctor/dbconsistency.go index f8b62e898a..7ae349908e 100644 --- a/modules/doctor/dbconsistency.go +++ b/modules/doctor/dbconsistency.go @@ -7,7 +7,7 @@ package doctor import ( "context" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/migrations" @@ -121,8 +121,8 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er // find null archived repositories { Name: "Repositories with is_archived IS NULL", - Counter: models.CountNullArchivedRepository, - Fixer: models.FixNullArchivedRepository, + Counter: repo_model.CountNullArchivedRepository, + Fixer: repo_model.FixNullArchivedRepository, FixedMessage: "Fixed", }, // find label comments with empty labels @@ -148,8 +148,8 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er }, { Name: "Action with created_unix set as an empty string", - Counter: models.CountActionCreatedUnixString, - Fixer: models.FixActionCreatedUnixString, + Counter: activities_model.CountActionCreatedUnixString, + Fixer: activities_model.FixActionCreatedUnixString, FixedMessage: "Set to zero", }, } diff --git a/modules/doctor/usertype.go b/modules/doctor/usertype.go index 34e12afe72..166e38bd24 100644 --- a/modules/doctor/usertype.go +++ b/modules/doctor/usertype.go @@ -7,19 +7,19 @@ package doctor import ( "context" - "code.gitea.io/gitea/models" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" ) func checkUserType(ctx context.Context, logger log.Logger, autofix bool) error { - count, err := models.CountWrongUserType() + count, err := user_model.CountWrongUserType() if err != nil { logger.Critical("Error: %v whilst counting wrong user types") return err } if count > 0 { if autofix { - if count, err = models.FixWrongUserType(); err != nil { + if count, err = user_model.FixWrongUserType(); err != nil { logger.Critical("Error: %v whilst fixing wrong user types") return err } diff --git a/modules/eventsource/manager_run.go b/modules/eventsource/manager_run.go index 06d48454fd..44e878fd4e 100644 --- a/modules/eventsource/manager_run.go +++ b/modules/eventsource/manager_run.go @@ -8,7 +8,7 @@ import ( "context" "time" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/modules/convert" "code.gitea.io/gitea/modules/graceful" @@ -72,7 +72,7 @@ loop: now := timeutil.TimeStampNow().Add(-2) - uidCounts, err := models.GetUIDsAndNotificationCounts(then, now) + uidCounts, err := activities_model.GetUIDsAndNotificationCounts(then, now) if err != nil { log.Error("Unable to get UIDcounts: %v", err) } diff --git a/modules/metrics/collector.go b/modules/metrics/collector.go index 069633a565..dcd80b05a9 100755 --- a/modules/metrics/collector.go +++ b/modules/metrics/collector.go @@ -5,7 +5,7 @@ package metrics import ( - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "github.com/prometheus/client_golang/prometheus" ) @@ -225,7 +225,7 @@ func (c Collector) Describe(ch chan<- *prometheus.Desc) { // Collect returns the metrics with values func (c Collector) Collect(ch chan<- prometheus.Metric) { - stats := models.GetStatistic() + stats := activities_model.GetStatistic() ch <- prometheus.MustNewConstMetric( c.Accesses, diff --git a/modules/notification/action/action.go b/modules/notification/action/action.go index e438f41485..d3ff8b156e 100644 --- a/modules/notification/action/action.go +++ b/modules/notification/action/action.go @@ -9,7 +9,7 @@ import ( "path" "strings" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" @@ -45,10 +45,10 @@ func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*u } repo := issue.Repo - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: issue.Poster.ID, ActUser: issue.Poster, - OpType: models.ActionCreateIssue, + OpType: activities_model.ActionCreateIssue, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Title), RepoID: repo.ID, Repo: repo, @@ -62,7 +62,7 @@ func (a *actionNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*u func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, closeOrReopen bool) { // Compose comment action, could be plain comment, close or reopen issue/pull request. // This object will be used to notify watchers in the end of function. - act := &models.Action{ + act := &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, Content: fmt.Sprintf("%d|%s", issue.Index, ""), @@ -74,19 +74,19 @@ func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *i } // Check comment type. if closeOrReopen { - act.OpType = models.ActionCloseIssue + act.OpType = activities_model.ActionCloseIssue if issue.IsPull { - act.OpType = models.ActionClosePullRequest + act.OpType = activities_model.ActionClosePullRequest } } else { - act.OpType = models.ActionReopenIssue + act.OpType = activities_model.ActionReopenIssue if issue.IsPull { - act.OpType = models.ActionReopenPullRequest + act.OpType = activities_model.ActionReopenPullRequest } } // Notify watchers for whatever action comes in, ignore if no action type. - if err := models.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(act); err != nil { log.Error("NotifyWatchers: %v", err) } } @@ -95,7 +95,7 @@ func (a *actionNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *i func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User, ) { - act := &models.Action{ + act := &activities_model.Action{ ActUserID: doer.ID, ActUser: doer, RepoID: issue.Repo.ID, @@ -116,13 +116,13 @@ func (a *actionNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *r act.Content = fmt.Sprintf("%d|%s", issue.Index, truncatedContent) if issue.IsPull { - act.OpType = models.ActionCommentPull + act.OpType = activities_model.ActionCommentPull } else { - act.OpType = models.ActionCommentIssue + act.OpType = activities_model.ActionCommentIssue } // Notify watchers for whatever action comes in, ignore if no action type. - if err := models.NotifyWatchers(act); err != nil { + if err := activities_model.NotifyWatchers(act); err != nil { log.Error("NotifyWatchers: %v", err) } } @@ -141,10 +141,10 @@ func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, me return } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: pull.Issue.Poster.ID, ActUser: pull.Issue.Poster, - OpType: models.ActionCreatePullRequest, + OpType: activities_model.ActionCreatePullRequest, Content: fmt.Sprintf("%d|%s", pull.Issue.Index, pull.Issue.Title), RepoID: pull.Issue.Repo.ID, Repo: pull.Issue.Repo, @@ -155,10 +155,10 @@ func (a *actionNotifier) NotifyNewPullRequest(pull *issues_model.PullRequest, me } func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *repo_model.Repository, oldRepoName string) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionRenameRepo, + OpType: activities_model.ActionRenameRepo, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -169,10 +169,10 @@ func (a *actionNotifier) NotifyRenameRepository(doer *user_model.User, repo *rep } func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *repo_model.Repository, oldOwnerName string) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionTransferRepo, + OpType: activities_model.ActionTransferRepo, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -183,10 +183,10 @@ func (a *actionNotifier) NotifyTransferRepository(doer *user_model.User, repo *r } func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo *repo_model.Repository) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionCreateRepo, + OpType: activities_model.ActionCreateRepo, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -196,10 +196,10 @@ func (a *actionNotifier) NotifyCreateRepository(doer, u *user_model.User, repo * } func (a *actionNotifier) NotifyForkRepository(doer *user_model.User, oldRepo, repo *repo_model.Repository) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionCreateRepo, + OpType: activities_model.ActionCreateRepo, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -221,15 +221,15 @@ func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r return } - actions := make([]*models.Action, 0, 10) + actions := make([]*activities_model.Action, 0, 10) for _, lines := range review.CodeComments { for _, comments := range lines { for _, comm := range comments { - actions = append(actions, &models.Action{ + actions = append(actions, &activities_model.Action{ ActUserID: review.Reviewer.ID, ActUser: review.Reviewer, Content: fmt.Sprintf("%d|%s", review.Issue.Index, strings.Split(comm.Content, "\n")[0]), - OpType: models.ActionCommentPull, + OpType: activities_model.ActionCommentPull, RepoID: review.Issue.RepoID, Repo: review.Issue.Repo, IsPrivate: review.Issue.Repo.IsPrivate, @@ -241,7 +241,7 @@ func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r } if review.Type != issues_model.ReviewTypeComment || strings.TrimSpace(comment.Content) != "" { - action := &models.Action{ + action := &activities_model.Action{ ActUserID: review.Reviewer.ID, ActUser: review.Reviewer, Content: fmt.Sprintf("%d|%s", review.Issue.Index, strings.Split(comment.Content, "\n")[0]), @@ -254,26 +254,26 @@ func (a *actionNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r switch review.Type { case issues_model.ReviewTypeApprove: - action.OpType = models.ActionApprovePullRequest + action.OpType = activities_model.ActionApprovePullRequest case issues_model.ReviewTypeReject: - action.OpType = models.ActionRejectPullRequest + action.OpType = activities_model.ActionRejectPullRequest default: - action.OpType = models.ActionCommentPull + action.OpType = activities_model.ActionCommentPull } actions = append(actions, action) } - if err := models.NotifyWatchersActions(actions); err != nil { + if err := activities_model.NotifyWatchersActions(actions); err != nil { log.Error("notify watchers '%d/%d': %v", review.Reviewer.ID, review.Issue.RepoID, err) } } func (*actionNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer *user_model.User) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionMergePullRequest, + OpType: activities_model.ActionMergePullRequest, Content: fmt.Sprintf("%d|%s", pr.Issue.Index, pr.Issue.Title), RepoID: pr.Issue.Repo.ID, Repo: pr.Issue.Repo, @@ -288,10 +288,10 @@ func (*actionNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *i if len(review.OriginalAuthor) > 0 { reviewerName = review.OriginalAuthor } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, - OpType: models.ActionPullReviewDismissed, + OpType: activities_model.ActionPullReviewDismissed, Content: fmt.Sprintf("%d|%s|%s", review.Issue.Index, reviewerName, comment.Content), RepoID: review.Issue.Repo.ID, Repo: review.Issue.Repo, @@ -310,19 +310,19 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m return } - opType := models.ActionCommitRepo + opType := activities_model.ActionCommitRepo // Check it's tag push or branch. if opts.IsTag() { - opType = models.ActionPushTag + opType = activities_model.ActionPushTag if opts.IsDelRef() { - opType = models.ActionDeleteTag + opType = activities_model.ActionDeleteTag } } else if opts.IsDelRef() { - opType = models.ActionDeleteBranch + opType = activities_model.ActionDeleteBranch } - if err = models.NotifyWatchers(&models.Action{ + if err = activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: pusher.ID, ActUser: pusher, OpType: opType, @@ -337,12 +337,12 @@ func (a *actionNotifier) NotifyPushCommits(pusher *user_model.User, repo *repo_m } func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - opType := models.ActionCommitRepo + opType := activities_model.ActionCommitRepo if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -356,12 +356,12 @@ func (a *actionNotifier) NotifyCreateRef(doer *user_model.User, repo *repo_model } func (a *actionNotifier) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - opType := models.ActionDeleteBranch + opType := activities_model.ActionDeleteBranch if refType == "tag" { // has sent same action in `NotifyPushCommits`, so skip it. return } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: doer.ID, ActUser: doer, OpType: opType, @@ -381,10 +381,10 @@ func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *re return } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: repo.OwnerID, ActUser: repo.MustOwner(), - OpType: models.ActionMirrorSyncPush, + OpType: activities_model.ActionMirrorSyncPush, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -396,10 +396,10 @@ func (a *actionNotifier) NotifySyncPushCommits(pusher *user_model.User, repo *re } func (a *actionNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: repo.OwnerID, ActUser: repo.MustOwner(), - OpType: models.ActionMirrorSyncCreate, + OpType: activities_model.ActionMirrorSyncCreate, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -410,10 +410,10 @@ func (a *actionNotifier) NotifySyncCreateRef(doer *user_model.User, repo *repo_m } func (a *actionNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) { - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: repo.OwnerID, ActUser: repo.MustOwner(), - OpType: models.ActionMirrorSyncDelete, + OpType: activities_model.ActionMirrorSyncDelete, RepoID: repo.ID, Repo: repo, IsPrivate: repo.IsPrivate, @@ -423,15 +423,15 @@ func (a *actionNotifier) NotifySyncDeleteRef(doer *user_model.User, repo *repo_m } } -func (a *actionNotifier) NotifyNewRelease(rel *models.Release) { +func (a *actionNotifier) NotifyNewRelease(rel *repo_model.Release) { if err := rel.LoadAttributes(); err != nil { log.Error("NotifyNewRelease: %v", err) return } - if err := models.NotifyWatchers(&models.Action{ + if err := activities_model.NotifyWatchers(&activities_model.Action{ ActUserID: rel.PublisherID, ActUser: rel.Publisher, - OpType: models.ActionPublishRelease, + OpType: activities_model.ActionPublishRelease, RepoID: rel.RepoID, Repo: rel.Repo, IsPrivate: rel.Repo.IsPrivate, diff --git a/modules/notification/action/action_test.go b/modules/notification/action/action_test.go index f6de0d6759..79a938d6cd 100644 --- a/modules/notification/action/action_test.go +++ b/modules/notification/action/action_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -35,8 +35,8 @@ func TestRenameRepoAction(t *testing.T) { repo.Name = newRepoName repo.LowerName = strings.ToLower(newRepoName) - actionBean := &models.Action{ - OpType: models.ActionRenameRepo, + actionBean := &activities_model.Action{ + OpType: activities_model.ActionRenameRepo, ActUserID: user.ID, ActUser: user, RepoID: repo.ID, @@ -49,5 +49,5 @@ func TestRenameRepoAction(t *testing.T) { NewNotifier().NotifyRenameRepository(user, repo, oldRepoName) unittest.AssertExistsAndLoadBean(t, actionBean) - unittest.CheckConsistencyFor(t, &models.Action{}) + unittest.CheckConsistencyFor(t, &activities_model.Action{}) } diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go index 31fa8f5f18..541731ddbf 100644 --- a/modules/notification/base/notifier.go +++ b/modules/notification/base/notifier.go @@ -5,7 +5,6 @@ package base import ( - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -46,9 +45,9 @@ type Notifier interface { issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User) NotifyUpdateComment(*user_model.User, *issues_model.Comment, string) NotifyDeleteComment(*user_model.User, *issues_model.Comment) - NotifyNewRelease(rel *models.Release) - NotifyUpdateRelease(doer *user_model.User, rel *models.Release) - NotifyDeleteRelease(doer *user_model.User, rel *models.Release) + NotifyNewRelease(rel *repo_model.Release) + NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) + NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) NotifyPushCommits(pusher *user_model.User, repo *repo_model.Repository, opts *repository.PushUpdateOptions, commits *repository.PushCommits) NotifyCreateRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) NotifyDeleteRef(doer *user_model.User, repo *repo_model.Repository, refType, refFullName string) diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go index d336f09301..4f382b3d01 100644 --- a/modules/notification/base/null.go +++ b/modules/notification/base/null.go @@ -5,7 +5,6 @@ package base import ( - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -80,15 +79,15 @@ func (*NullNotifier) NotifyDeleteComment(doer *user_model.User, c *issues_model. } // NotifyNewRelease places a place holder function -func (*NullNotifier) NotifyNewRelease(rel *models.Release) { +func (*NullNotifier) NotifyNewRelease(rel *repo_model.Release) { } // NotifyUpdateRelease places a place holder function -func (*NullNotifier) NotifyUpdateRelease(doer *user_model.User, rel *models.Release) { +func (*NullNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { } // NotifyDeleteRelease places a place holder function -func (*NullNotifier) NotifyDeleteRelease(doer *user_model.User, rel *models.Release) { +func (*NullNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { } // NotifyIssueChangeMilestone places a place holder function diff --git a/modules/notification/mail/mail.go b/modules/notification/mail/mail.go index 5085656c14..100b4eb36f 100644 --- a/modules/notification/mail/mail.go +++ b/modules/notification/mail/mail.go @@ -7,7 +7,7 @@ package mail import ( "fmt" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -35,15 +35,15 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *rep ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyCreateIssueComment Issue[%d] #%d in [%d]", issue.ID, issue.Index, issue.RepoID)) defer finished() - var act models.ActionType + var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { - act = models.ActionCloseIssue + act = activities_model.ActionCloseIssue } else if comment.Type == issues_model.CommentTypeReopen { - act = models.ActionReopenIssue + act = activities_model.ActionReopenIssue } else if comment.Type == issues_model.CommentTypeComment { - act = models.ActionCommentIssue + act = activities_model.ActionCommentIssue } else if comment.Type == issues_model.CommentTypeCode { - act = models.ActionCommentIssue + act = activities_model.ActionCommentIssue } else if comment.Type == issues_model.CommentTypePullRequestPush { act = 0 } @@ -54,24 +54,24 @@ func (m *mailNotifier) NotifyCreateIssueComment(doer *user_model.User, repo *rep } func (m *mailNotifier) NotifyNewIssue(issue *issues_model.Issue, mentions []*user_model.User) { - if err := mailer.MailParticipants(issue, issue.Poster, models.ActionCreateIssue, mentions); err != nil { + if err := mailer.MailParticipants(issue, issue.Poster, activities_model.ActionCreateIssue, mentions); err != nil { log.Error("MailParticipants: %v", err) } } func (m *mailNotifier) NotifyIssueChangeStatus(doer *user_model.User, issue *issues_model.Issue, actionComment *issues_model.Comment, isClosed bool) { - var actionType models.ActionType + var actionType activities_model.ActionType if issue.IsPull { if isClosed { - actionType = models.ActionClosePullRequest + actionType = activities_model.ActionClosePullRequest } else { - actionType = models.ActionReopenPullRequest + actionType = activities_model.ActionReopenPullRequest } } else { if isClosed { - actionType = models.ActionCloseIssue + actionType = activities_model.ActionCloseIssue } else { - actionType = models.ActionReopenIssue + actionType = activities_model.ActionReopenIssue } } @@ -86,14 +86,14 @@ func (m *mailNotifier) NotifyIssueChangeTitle(doer *user_model.User, issue *issu return } if issue.IsPull && issues_model.HasWorkInProgressPrefix(oldTitle) && !issue.PullRequest.IsWorkInProgress() { - if err := mailer.MailParticipants(issue, doer, models.ActionPullRequestReadyForReview, nil); err != nil { + if err := mailer.MailParticipants(issue, doer, activities_model.ActionPullRequestReadyForReview, nil); err != nil { log.Error("MailParticipants: %v", err) } } } func (m *mailNotifier) NotifyNewPullRequest(pr *issues_model.PullRequest, mentions []*user_model.User) { - if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, models.ActionCreatePullRequest, mentions); err != nil { + if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, activities_model.ActionCreatePullRequest, mentions); err != nil { log.Error("MailParticipants: %v", err) } } @@ -102,13 +102,13 @@ func (m *mailNotifier) NotifyPullRequestReview(pr *issues_model.PullRequest, r * ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRequestReview Pull[%d] #%d in [%d]", pr.ID, pr.Index, pr.BaseRepoID)) defer finished() - var act models.ActionType + var act activities_model.ActionType if comment.Type == issues_model.CommentTypeClose { - act = models.ActionCloseIssue + act = activities_model.ActionCloseIssue } else if comment.Type == issues_model.CommentTypeReopen { - act = models.ActionReopenIssue + act = activities_model.ActionReopenIssue } else if comment.Type == issues_model.CommentTypeComment { - act = models.ActionCommentPull + act = activities_model.ActionCommentPull } if err := mailer.MailParticipantsComment(ctx, comment, act, pr.Issue, mentions); err != nil { log.Error("MailParticipantsComment: %v", err) @@ -148,7 +148,7 @@ func (m *mailNotifier) NotifyMergePullRequest(pr *issues_model.PullRequest, doer log.Error("pr.LoadIssue: %v", err) return } - if err := mailer.MailParticipants(pr.Issue, doer, models.ActionMergePullRequest, nil); err != nil { + if err := mailer.MailParticipants(pr.Issue, doer, activities_model.ActionMergePullRequest, nil); err != nil { log.Error("MailParticipants: %v", err) } } @@ -184,12 +184,12 @@ func (m *mailNotifier) NotifyPullRevieweDismiss(doer *user_model.User, review *i ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyPullRevieweDismiss Review[%d] in Issue[%d]", review.ID, review.IssueID)) defer finished() - if err := mailer.MailParticipantsComment(ctx, comment, models.ActionPullReviewDismissed, review.Issue, nil); err != nil { + if err := mailer.MailParticipantsComment(ctx, comment, activities_model.ActionPullReviewDismissed, review.Issue, nil); err != nil { log.Error("MailParticipantsComment: %v", err) } } -func (m *mailNotifier) NotifyNewRelease(rel *models.Release) { +func (m *mailNotifier) NotifyNewRelease(rel *repo_model.Release) { ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("mailNotifier.NotifyNewRelease rel[%d]%s in [%d]", rel.ID, rel.Title, rel.RepoID)) defer finished() diff --git a/modules/notification/notification.go b/modules/notification/notification.go index bdfed90b78..713cc72aac 100644 --- a/modules/notification/notification.go +++ b/modules/notification/notification.go @@ -5,7 +5,6 @@ package notification import ( - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" repo_model "code.gitea.io/gitea/models/repo" @@ -142,21 +141,21 @@ func NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) { } // NotifyNewRelease notifies new release to notifiers -func NotifyNewRelease(rel *models.Release) { +func NotifyNewRelease(rel *repo_model.Release) { for _, notifier := range notifiers { notifier.NotifyNewRelease(rel) } } // NotifyUpdateRelease notifies update release to notifiers -func NotifyUpdateRelease(doer *user_model.User, rel *models.Release) { +func NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { notifier.NotifyUpdateRelease(doer, rel) } } // NotifyDeleteRelease notifies delete release to notifiers -func NotifyDeleteRelease(doer *user_model.User, rel *models.Release) { +func NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { for _, notifier := range notifiers { notifier.NotifyDeleteRelease(doer, rel) } diff --git a/modules/notification/ui/ui.go b/modules/notification/ui/ui.go index 74866a3363..5e5196a70a 100644 --- a/modules/notification/ui/ui.go +++ b/modules/notification/ui/ui.go @@ -5,7 +5,7 @@ package ui import ( - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" @@ -42,7 +42,7 @@ func NewNotifier() base.Notifier { func (ns *notificationService) handle(data ...queue.Data) []queue.Data { for _, datum := range data { opts := datum.(issueNotificationOpts) - if err := models.CreateOrUpdateIssueNotifications(opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { + if err := activities_model.CreateOrUpdateIssueNotifications(opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { log.Error("Was unable to create issue notification: %v", err) } } @@ -237,7 +237,7 @@ func (ns *notificationService) NotifyPullReviewRequest(doer *user_model.User, is } func (ns *notificationService) NotifyRepoPendingTransfer(doer, newOwner *user_model.User, repo *repo_model.Repository) { - if err := models.CreateRepoTransferNotification(doer, newOwner, repo); err != nil { + if err := activities_model.CreateRepoTransferNotification(doer, newOwner, repo); err != nil { log.Error("NotifyRepoPendingTransfer: %v", err) } } diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go index be71d18fda..ed3b53e3e7 100644 --- a/modules/notification/webhook/webhook.go +++ b/modules/notification/webhook/webhook.go @@ -7,7 +7,6 @@ package webhook import ( "fmt" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" packages_model "code.gitea.io/gitea/models/packages" @@ -797,7 +796,7 @@ func (m *webhookNotifier) NotifyDeleteRef(pusher *user_model.User, repo *repo_mo } } -func sendReleaseHook(doer *user_model.User, rel *models.Release, action api.HookReleaseAction) { +func sendReleaseHook(doer *user_model.User, rel *repo_model.Release, action api.HookReleaseAction) { if err := rel.LoadAttributes(); err != nil { log.Error("LoadAttributes: %v", err) return @@ -814,15 +813,15 @@ func sendReleaseHook(doer *user_model.User, rel *models.Release, action api.Hook } } -func (m *webhookNotifier) NotifyNewRelease(rel *models.Release) { +func (m *webhookNotifier) NotifyNewRelease(rel *repo_model.Release) { sendReleaseHook(rel.Publisher, rel, api.HookReleasePublished) } -func (m *webhookNotifier) NotifyUpdateRelease(doer *user_model.User, rel *models.Release) { +func (m *webhookNotifier) NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release) { sendReleaseHook(doer, rel, api.HookReleaseUpdated) } -func (m *webhookNotifier) NotifyDeleteRelease(doer *user_model.User, rel *models.Release) { +func (m *webhookNotifier) NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release) { sendReleaseHook(doer, rel, api.HookReleaseDeleted) } diff --git a/modules/repository/collaborator.go b/modules/repository/collaborator.go new file mode 100644 index 0000000000..9d20a25890 --- /dev/null +++ b/modules/repository/collaborator.go @@ -0,0 +1,43 @@ +// Copyright 2022 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repository + +import ( + "context" + + "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" + user_model "code.gitea.io/gitea/models/user" +) + +func addCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error { + collaboration := &repo_model.Collaboration{ + RepoID: repo.ID, + UserID: u.ID, + } + + has, err := db.GetByBean(ctx, collaboration) + if err != nil { + return err + } else if has { + return nil + } + collaboration.Mode = perm.AccessModeWrite + + if err = db.Insert(ctx, collaboration); err != nil { + return err + } + + return access_model.RecalculateUserAccess(ctx, repo, u.ID) +} + +// AddCollaborator adds new collaboration to a repository with default access mode. +func AddCollaborator(repo *repo_model.Repository, u *user_model.User) error { + return db.WithTx(func(ctx context.Context) error { + return addCollaborator(ctx, repo, u) + }) +} diff --git a/modules/repository/collaborator_test.go b/modules/repository/collaborator_test.go new file mode 100644 index 0000000000..1b927aa3b6 --- /dev/null +++ b/modules/repository/collaborator_test.go @@ -0,0 +1,281 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repository + +import ( + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/organization" + perm_model "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + + "github.com/stretchr/testify/assert" +) + +func TestRepository_AddCollaborator(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + testSuccess := func(repoID, userID int64) { + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) + assert.NoError(t, repo.GetOwner(db.DefaultContext)) + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}) + assert.NoError(t, AddCollaborator(repo, user)) + unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID}) + } + testSuccess(1, 4) + testSuccess(1, 4) + testSuccess(3, 4) +} + +func TestRepoPermissionPublicNonOrgRepo(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + // public non-organization repo + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) + assert.NoError(t, repo.LoadUnits(db.DefaultContext)) + + // plain user + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // change to collaborator + assert.NoError(t, AddCollaborator(repo, user)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // collaborator + collaborator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, collaborator) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // owner + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // admin + admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } +} + +func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + // private non-organization repo + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + assert.NoError(t, repo.LoadUnits(db.DefaultContext)) + + // plain user + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.False(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // change to collaborator to default write access + assert.NoError(t, AddCollaborator(repo, user)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // owner + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // admin + admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } +} + +func TestRepoPermissionPublicOrgRepo(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + // public organization repo + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32}) + assert.NoError(t, repo.LoadUnits(db.DefaultContext)) + + // plain user + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // change to collaborator to default write access + assert.NoError(t, AddCollaborator(repo, user)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // org member team owner + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // org member team tester + member := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, member) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + } + assert.True(t, perm.CanWrite(unit.TypeIssues)) + assert.False(t, perm.CanWrite(unit.TypeCode)) + + // admin + admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } +} + +func TestRepoPermissionPrivateOrgRepo(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + // private organization repo + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24}) + assert.NoError(t, repo.LoadUnits(db.DefaultContext)) + + // plain user + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5}) + perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.False(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // change to collaborator to default write access + assert.NoError(t, AddCollaborator(repo, user)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + assert.NoError(t, repo_model.ChangeCollaborationAccessMode(repo, user.ID, perm_model.AccessModeRead)) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.False(t, perm.CanWrite(unit.Type)) + } + + // org member team owner + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // update team information and then check permission + team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}) + err = organization.UpdateTeamUnits(team, nil) + assert.NoError(t, err) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } + + // org member team tester + tester := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, tester) + assert.NoError(t, err) + assert.True(t, perm.CanWrite(unit.TypeIssues)) + assert.False(t, perm.CanWrite(unit.TypeCode)) + assert.False(t, perm.CanRead(unit.TypeCode)) + + // org member team reviewer + reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 20}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, reviewer) + assert.NoError(t, err) + assert.False(t, perm.CanRead(unit.TypeIssues)) + assert.False(t, perm.CanWrite(unit.TypeCode)) + assert.True(t, perm.CanRead(unit.TypeCode)) + + // admin + admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin) + assert.NoError(t, err) + for _, unit := range repo.Units { + assert.True(t, perm.CanRead(unit.Type)) + assert.True(t, perm.CanWrite(unit.Type)) + } +} diff --git a/modules/repository/create.go b/modules/repository/create.go index 9204d7e422..7a25323def 100644 --- a/modules/repository/create.go +++ b/modules/repository/create.go @@ -13,11 +13,16 @@ import ( "unicode/utf8" "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" + "code.gitea.io/gitea/models/organization" + "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/models/webhook" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -25,8 +30,150 @@ import ( "code.gitea.io/gitea/modules/util" ) +// CreateRepositoryByExample creates a repository for the user/organization. +func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt bool) (err error) { + if err = repo_model.IsUsableRepoName(repo.Name); err != nil { + return err + } + + has, err := repo_model.IsRepositoryExist(ctx, u, repo.Name) + if err != nil { + return fmt.Errorf("IsRepositoryExist: %v", err) + } else if has { + return repo_model.ErrRepoAlreadyExist{ + Uname: u.Name, + Name: repo.Name, + } + } + + repoPath := repo_model.RepoPath(u.Name, repo.Name) + isExist, err := util.IsExist(repoPath) + if err != nil { + log.Error("Unable to check if %s exists. Error: %v", repoPath, err) + return err + } + if !overwriteOrAdopt && isExist { + log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath) + return repo_model.ErrRepoFilesAlreadyExist{ + Uname: u.Name, + Name: repo.Name, + } + } + + if err = db.Insert(ctx, repo); err != nil { + return err + } + if err = repo_model.DeleteRedirect(ctx, u.ID, repo.Name); err != nil { + return err + } + + // insert units for repo + units := make([]repo_model.RepoUnit, 0, len(unit.DefaultRepoUnits)) + for _, tp := range unit.DefaultRepoUnits { + if tp == unit.TypeIssues { + units = append(units, repo_model.RepoUnit{ + RepoID: repo.ID, + Type: tp, + Config: &repo_model.IssuesConfig{ + EnableTimetracker: setting.Service.DefaultEnableTimetracking, + AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime, + EnableDependencies: setting.Service.DefaultEnableDependencies, + }, + }) + } else if tp == unit.TypePullRequests { + units = append(units, repo_model.RepoUnit{ + RepoID: repo.ID, + Type: tp, + Config: &repo_model.PullRequestsConfig{AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle), AllowRebaseUpdate: true}, + }) + } else { + units = append(units, repo_model.RepoUnit{ + RepoID: repo.ID, + Type: tp, + }) + } + } + + if err = db.Insert(ctx, units); err != nil { + return err + } + + // Remember visibility preference. + u.LastRepoVisibility = repo.IsPrivate + if err = user_model.UpdateUserCols(ctx, u, "last_repo_visibility"); err != nil { + return fmt.Errorf("UpdateUserCols: %v", err) + } + + if err = user_model.IncrUserRepoNum(ctx, u.ID); err != nil { + return fmt.Errorf("IncrUserRepoNum: %v", err) + } + u.NumRepos++ + + // Give access to all members in teams with access to all repositories. + if u.IsOrganization() { + teams, err := organization.FindOrgTeams(ctx, u.ID) + if err != nil { + return fmt.Errorf("FindOrgTeams: %v", err) + } + for _, t := range teams { + if t.IncludesAllRepositories { + if err := models.AddRepository(ctx, t, repo); err != nil { + return fmt.Errorf("AddRepository: %v", err) + } + } + } + + if isAdmin, err := access_model.IsUserRepoAdmin(ctx, repo, doer); err != nil { + return fmt.Errorf("IsUserRepoAdmin: %v", err) + } else if !isAdmin { + // Make creator repo admin if it wasn't assigned automatically + if err = addCollaborator(ctx, repo, doer); err != nil { + return fmt.Errorf("addCollaborator: %v", err) + } + if err = repo_model.ChangeCollaborationAccessModeCtx(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil { + return fmt.Errorf("ChangeCollaborationAccessModeCtx: %v", err) + } + } + } else if err = access_model.RecalculateAccesses(ctx, repo); err != nil { + // Organization automatically called this in AddRepository method. + return fmt.Errorf("RecalculateAccesses: %v", err) + } + + if setting.Service.AutoWatchNewRepos { + if err = repo_model.WatchRepo(ctx, doer.ID, repo.ID, true); err != nil { + return fmt.Errorf("WatchRepo: %v", err) + } + } + + if err = webhook.CopyDefaultWebhooksToRepo(ctx, repo.ID); err != nil { + return fmt.Errorf("CopyDefaultWebhooksToRepo: %v", err) + } + + return nil +} + +// CreateRepoOptions contains the create repository options +type CreateRepoOptions struct { + Name string + Description string + OriginalURL string + GitServiceType api.GitServiceType + Gitignores string + IssueLabels string + License string + Readme string + DefaultBranch string + IsPrivate bool + IsMirror bool + IsTemplate bool + AutoInit bool + Status repo_model.RepositoryStatus + TrustModel repo_model.TrustModelType + MirrorInterval string +} + // CreateRepository creates a repository for the user/organization. -func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) (*repo_model.Repository, error) { +func CreateRepository(doer, u *user_model.User, opts CreateRepoOptions) (*repo_model.Repository, error) { if !doer.IsAdmin && !u.CanCreateRepo() { return nil, repo_model.ErrReachLimitOfRepo{ Limit: u.MaxRepoCreation, @@ -66,7 +213,7 @@ func CreateRepository(doer, u *user_model.User, opts models.CreateRepoOptions) ( var rollbackRepo *repo_model.Repository if err := db.WithTx(func(ctx context.Context) error { - if err := models.CreateRepository(ctx, doer, u, repo, false); err != nil { + if err := CreateRepositoryByExample(ctx, doer, u, repo, false); err != nil { return err } @@ -220,7 +367,7 @@ func UpdateRepository(ctx context.Context, repo *repo_model.Repository, visibili // If repo has become private, we need to set its actions to private. if repo.IsPrivate { - _, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&models.Action{ + _, err = e.Where("repo_id = ?", repo.ID).Cols("is_private").Update(&activities_model.Action{ IsPrivate: true, }) if err != nil { diff --git a/modules/repository/create_test.go b/modules/repository/create_test.go index 39f8b11356..3040782845 100644 --- a/modules/repository/create_test.go +++ b/modules/repository/create_test.go @@ -9,6 +9,7 @@ import ( "testing" "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" @@ -56,7 +57,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { // Create repos. repoIds := make([]int64, 0) for i := 0; i < 3; i++ { - r, err := CreateRepository(user, org.AsUser(), models.CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)}) + r, err := CreateRepository(user, org.AsUser(), CreateRepoOptions{Name: fmt.Sprintf("repo-%d", i)}) assert.NoError(t, err, "CreateRepository %d", i) if r != nil { repoIds = append(repoIds, r.ID) @@ -118,7 +119,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { } // Create repo and check teams repositories. - r, err := CreateRepository(user, org.AsUser(), models.CreateRepoOptions{Name: "repo-last"}) + r, err := CreateRepository(user, org.AsUser(), CreateRepoOptions{Name: "repo-last"}) assert.NoError(t, err, "CreateRepository last") if r != nil { repoIds = append(repoIds, r.ID) @@ -162,7 +163,7 @@ func TestUpdateRepositoryVisibilityChanged(t *testing.T) { assert.NoError(t, err) // Check visibility of action has become private - act := models.Action{} + act := activities_model.Action{} _, err = db.GetEngine(db.DefaultContext).ID(3).Get(&act) assert.NoError(t, err) diff --git a/modules/repository/generate.go b/modules/repository/generate.go index 8f7b4c885d..4d76d33993 100644 --- a/modules/repository/generate.go +++ b/modules/repository/generate.go @@ -15,7 +15,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -321,7 +320,7 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ TrustModel: templateRepo.TrustModel, } - if err = models.CreateRepository(ctx, doer, owner, generateRepo, false); err != nil { + if err = CreateRepositoryByExample(ctx, doer, owner, generateRepo, false); err != nil { return nil, err } diff --git a/modules/repository/init.go b/modules/repository/init.go index e984697cda..37ed0748b4 100644 --- a/modules/repository/init.go +++ b/modules/repository/init.go @@ -15,7 +15,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" @@ -214,7 +213,7 @@ func LoadRepoConfig() { Licenses = sortedLicenses } -func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts models.CreateRepoOptions) error { +func prepareRepoCommit(ctx context.Context, repo *repo_model.Repository, tmpDir, repoPath string, opts CreateRepoOptions) error { commitTimeStr := time.Now().Format(time.RFC3339) authorSig := repo.Owner.NewGitSig() @@ -387,7 +386,7 @@ func checkInitRepository(ctx context.Context, owner, name string) (err error) { } // InitRepository initializes README and .gitignore if needed. -func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts models.CreateRepoOptions) (err error) { +func initRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts CreateRepoOptions) (err error) { if err = checkInitRepository(ctx, repo.OwnerName, repo.Name); err != nil { return err } diff --git a/modules/repository/repo.go b/modules/repository/repo.go index 436045146a..48c3edf60f 100644 --- a/modules/repository/repo.go +++ b/modules/repository/repo.go @@ -13,7 +13,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" "code.gitea.io/gitea/models/organization" @@ -31,8 +30,8 @@ import ( ) /* - GitHub, GitLab, Gogs: *.wiki.git - BitBucket: *.git/wiki +GitHub, GitLab, Gogs: *.wiki.git +BitBucket: *.git/wiki */ var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"} @@ -277,14 +276,14 @@ func SyncReleasesWithTags(repo *repo_model.Repository, gitRepo *git.Repository) } existingRelTags := make(map[string]struct{}) - opts := models.FindReleasesOptions{ + opts := repo_model.FindReleasesOptions{ IncludeDrafts: true, IncludeTags: true, ListOptions: db.ListOptions{PageSize: 50}, } for page := 1; ; page++ { opts.Page = page - rels, err := models.GetReleasesByRepoID(repo.ID, opts) + rels, err := repo_model.GetReleasesByRepoID(repo.ID, opts) if err != nil { return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) } @@ -300,7 +299,7 @@ func SyncReleasesWithTags(repo *repo_model.Repository, gitRepo *git.Repository) return fmt.Errorf("unable to GetTagCommitID for %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) } if git.IsErrNotExist(err) || commitID != rel.Sha1 { - if err := models.PushUpdateDeleteTag(repo, rel.TagName); err != nil { + if err := repo_model.PushUpdateDeleteTag(repo, rel.TagName); err != nil { return fmt.Errorf("unable to PushUpdateDeleteTag: %q in Repo[%d:%s/%s]: %w", rel.TagName, repo.ID, repo.OwnerName, repo.Name, err) } } else { @@ -359,7 +358,7 @@ func PushUpdateAddTag(repo *repo_model.Repository, gitRepo *git.Repository, tagN return fmt.Errorf("unable to get CommitsCount: %w", err) } - rel := models.Release{ + rel := repo_model.Release{ RepoID: repo.ID, TagName: tagName, LowerTagName: strings.ToLower(tagName), @@ -372,7 +371,7 @@ func PushUpdateAddTag(repo *repo_model.Repository, gitRepo *git.Repository, tagN rel.PublisherID = author.ID } - return models.SaveOrUpdateTag(repo, &rel) + return repo_model.SaveOrUpdateTag(repo, &rel) } // StoreMissingLfsObjectsInRepository downloads missing LFS objects @@ -489,14 +488,14 @@ func pullMirrorReleaseSync(repo *repo_model.Repository, gitRepo *git.Repository) // // clear out existing releases // - if _, err := db.DeleteByBean(ctx, &models.Release{RepoID: repo.ID}); err != nil { + if _, err := db.DeleteByBean(ctx, &repo_model.Release{RepoID: repo.ID}); err != nil { return fmt.Errorf("unable to clear releases for pull-mirror Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) } // // make release set identical to upstream tags // for _, tag := range tags { - release := models.Release{ + release := repo_model.Release{ RepoID: repo.ID, TagName: tag.Name, LowerTagName: strings.ToLower(tag.Name), diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 10b7022ea6..48b62403a0 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -24,7 +24,7 @@ import ( "time" "unicode" - "code.gitea.io/gitea/models" + activities_model "code.gitea.io/gitea/models/activities" "code.gitea.io/gitea/models/avatars" issues_model "code.gitea.io/gitea/models/issues" "code.gitea.io/gitea/models/organization" @@ -655,7 +655,7 @@ func Avatar(item interface{}, others ...interface{}) template.HTML { } // AvatarByAction renders user avatars from action. args: action, size (int), class (string) -func AvatarByAction(action *models.Action, others ...interface{}) template.HTML { +func AvatarByAction(action *activities_model.Action, others ...interface{}) template.HTML { action.LoadActUser() return Avatar(action.ActUser, others...) } @@ -854,7 +854,7 @@ func IsMultilineCommitMessage(msg string) bool { // Actioner describes an action type Actioner interface { - GetOpType() models.ActionType + GetOpType() activities_model.ActionType GetActUserName() string GetRepoUserName() string GetRepoName() string @@ -867,33 +867,33 @@ type Actioner interface { } // ActionIcon accepts an action operation type and returns an icon class name. -func ActionIcon(opType models.ActionType) string { +func ActionIcon(opType activities_model.ActionType) string { switch opType { - case models.ActionCreateRepo, models.ActionTransferRepo, models.ActionRenameRepo: + case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo: return "repo" - case models.ActionCommitRepo, models.ActionPushTag, models.ActionDeleteTag, models.ActionDeleteBranch: + case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch: return "git-commit" - case models.ActionCreateIssue: + case activities_model.ActionCreateIssue: return "issue-opened" - case models.ActionCreatePullRequest: + case activities_model.ActionCreatePullRequest: return "git-pull-request" - case models.ActionCommentIssue, models.ActionCommentPull: + case activities_model.ActionCommentIssue, activities_model.ActionCommentPull: return "comment-discussion" - case models.ActionMergePullRequest: + case activities_model.ActionMergePullRequest: return "git-merge" - case models.ActionCloseIssue, models.ActionClosePullRequest: + case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest: return "issue-closed" - case models.ActionReopenIssue, models.ActionReopenPullRequest: + case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: return "issue-reopened" - case models.ActionMirrorSyncPush, models.ActionMirrorSyncCreate, models.ActionMirrorSyncDelete: + case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete: return "mirror" - case models.ActionApprovePullRequest: + case activities_model.ActionApprovePullRequest: return "check" - case models.ActionRejectPullRequest: + case activities_model.ActionRejectPullRequest: return "diff" - case models.ActionPublishRelease: + case activities_model.ActionPublishRelease: return "tag" - case models.ActionPullReviewDismissed: + case activities_model.ActionPullReviewDismissed: return "x" default: return "question" |