Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add activity feeds API #23494

Merged
merged 30 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9ecd197
add user activity feed api
Zettat123 Mar 15, 2023
162efae
fix date format
Zettat123 Mar 15, 2023
8da6120
fmt
Zettat123 Mar 15, 2023
722f410
fix typo
Zettat123 Mar 15, 2023
91aad69
add ListTeamActivityFeeds
Zettat123 Mar 15, 2023
244fd0e
update swagger
Zettat123 Mar 16, 2023
3c43443
add ListRepoActivityFeeds
Zettat123 Mar 16, 2023
70a6348
add OpType string
Zettat123 Mar 16, 2023
4e518f3
add ListOrgActivityFeeds
Zettat123 Mar 16, 2023
2eb0930
fix org membership check
Zettat123 Mar 16, 2023
2af7403
add 404 response
Zettat123 Mar 16, 2023
7be455d
update swagger
Zettat123 Mar 16, 2023
b47877c
add user activity feed api
Zettat123 Mar 15, 2023
17e80fb
fix date format
Zettat123 Mar 15, 2023
58c3029
fmt
Zettat123 Mar 15, 2023
bc546ed
fix typo
Zettat123 Mar 15, 2023
6887682
add ListTeamActivityFeeds
Zettat123 Mar 15, 2023
4d530cf
update swagger
Zettat123 Mar 16, 2023
0939e1c
add ListRepoActivityFeeds
Zettat123 Mar 16, 2023
5b0ce95
add OpType string
Zettat123 Mar 16, 2023
6a7c7dc
add ListOrgActivityFeeds
Zettat123 Mar 16, 2023
7f9ea9d
fix org membership check
Zettat123 Mar 16, 2023
5744f6d
add 404 response
Zettat123 Mar 16, 2023
3a5ece5
update swagger
Zettat123 Mar 16, 2023
52d96b8
Merge branch 'feat/activity-feed-api' of github.com:Zettat123/gitea i…
Zettat123 Apr 1, 2023
7693df8
use lower case action name
Zettat123 Apr 4, 2023
c086ffb
improve routers
Zettat123 Apr 4, 2023
130b3ea
remove empty line
Zettat123 Apr 4, 2023
9939acb
add separator
Zettat123 Apr 4, 2023
b824e7c
Merge branch 'main' into feat/activity-feed-api
lunny Apr 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions models/activities/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,67 @@ const (
ActionAutoMergePullRequest // 27
)

func (at ActionType) String() string {
switch at {
case ActionCreateRepo:
return "create_repo"
case ActionRenameRepo:
return "rename_repo"
case ActionStarRepo:
return "star_repo"
case ActionWatchRepo:
return "watch_repo"
case ActionCommitRepo:
return "commit_repo"
case ActionCreateIssue:
return "create_issue"
case ActionCreatePullRequest:
return "create_pull_request"
case ActionTransferRepo:
return "transfer_repo"
case ActionPushTag:
return "push_tag"
case ActionCommentIssue:
return "comment_issue"
case ActionMergePullRequest:
return "merge_pull_request"
case ActionCloseIssue:
return "close_issue"
case ActionReopenIssue:
return "reopen_issue"
case ActionClosePullRequest:
return "close_pull_request"
case ActionReopenPullRequest:
return "reopen_pull_request"
case ActionDeleteTag:
return "delete_tag"
case ActionDeleteBranch:
return "delete_branch"
case ActionMirrorSyncPush:
return "mirror_sync_push"
case ActionMirrorSyncCreate:
return "mirror_sync_create"
case ActionMirrorSyncDelete:
return "mirror_sync_delete"
case ActionApprovePullRequest:
return "approve_pull_request"
case ActionRejectPullRequest:
return "reject_pull_request"
case ActionCommentPull:
return "comment_pull"
case ActionPublishRelease:
return "publish_release"
case ActionPullReviewDismissed:
return "pull_review_dismissed"
case ActionPullRequestReadyForReview:
return "pull_request_ready_for_review"
case ActionAutoMergePullRequest:
return "auto_merge_pull_request"
default:
return "action-" + strconv.Itoa(int(at))
}
}

// Action represents user operation type and other information to
// repository. It implemented interface base.Actioner so that can be
// used in template render.
Expand Down
22 changes: 22 additions & 0 deletions modules/structs/activity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package structs

import "time"

type Activity struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id"` // Receiver user
OpType string `json:"op_type"`
ActUserID int64 `json:"act_user_id"`
ActUser *User `json:"act_user"`
RepoID int64 `json:"repo_id"`
Repo *Repository `json:"repo"`
CommentID int64 `json:"comment_id"`
Comment *Comment `json:"comment"`
RefName string `json:"ref_name"`
IsPrivate bool `json:"is_private"`
Content string `json:"content"`
Created time.Time `json:"created"`
}
5 changes: 5 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,8 @@ func Routes(ctx gocontext.Context) *web.Route {
Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken)
m.Combo("/{id}").Delete(user.DeleteAccessToken)
}, reqBasicAuth())

m.Get("/activities/feeds", user.ListUserActivityFeeds)
}, context_service.UserAssignmentAPI())
})

Expand Down Expand Up @@ -1177,6 +1179,7 @@ func Routes(ctx gocontext.Context) *web.Route {
m.Get("/issue_config", context.ReferencesGitRepo(), repo.GetIssueConfig)
m.Get("/issue_config/validate", context.ReferencesGitRepo(), repo.ValidateIssueConfig)
m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages)
m.Get("/activities/feeds", repo.ListRepoActivityFeeds)
}, repoAssignment())
})

Expand Down Expand Up @@ -1234,6 +1237,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Patch(bind(api.EditHookOption{}), org.EditHook).
Delete(org.DeleteHook)
}, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled())
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
}, orgAssignment(true))
m.Group("/teams/{teamid}", func() {
m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam).
Expand All @@ -1253,6 +1257,7 @@ func Routes(ctx gocontext.Context) *web.Route {
Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository).
Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo)
})
m.Get("/activities/feeds", org.ListTeamActivityFeeds)
}, orgAssignment(false, true), reqToken(""), reqTeamMembership())

m.Group("/admin", func() {
Expand Down
67 changes: 67 additions & 0 deletions routers/api/v1/org/org.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package org
import (
"net/http"

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"
Expand Down Expand Up @@ -370,3 +371,69 @@ func Delete(ctx *context.APIContext) {
}
ctx.Status(http.StatusNoContent)
}

func ListOrgActivityFeeds(ctx *context.APIContext) {
// swagger:operation GET /orgs/{org}/activities/feeds organization orgListActivityFeeds
// ---
// summary: List an organization's activity feeds
// produces:
// - application/json
// parameters:
// - name: org
// in: path
// description: name of the org
// type: string
// required: true
// - name: date
// in: query
// description: the date of the activities to be found
// type: string
// format: date
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/ActivityFeedsList"
// "404":
// "$ref": "#/responses/notFound"

includePrivate := false
if ctx.IsSigned {
if ctx.Doer.IsAdmin {
includePrivate = true
} else {
org := organization.OrgFromUser(ctx.ContextUser)
isMember, err := org.IsOrgMember(ctx.Doer.ID)
if err != nil {
ctx.Error(http.StatusInternalServerError, "IsOrgMember", err)
return
}
includePrivate = isMember
lunny marked this conversation as resolved.
Show resolved Hide resolved
}
}

listOptions := utils.GetListOptions(ctx)

opts := activities_model.GetFeedsOptions{
RequestedUser: ctx.ContextUser,
Actor: ctx.Doer,
IncludePrivate: includePrivate,
Date: ctx.FormString("date"),
ListOptions: listOptions,
}

feeds, count, err := activities_model.GetFeeds(ctx, opts)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetFeeds", err)
return
}
ctx.SetTotalCountHeader(count)

ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
}
53 changes: 53 additions & 0 deletions routers/api/v1/org/team.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"

"code.gitea.io/gitea/models"
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
access_model "code.gitea.io/gitea/models/perm/access"
Expand Down Expand Up @@ -792,3 +793,55 @@ func SearchTeam(ctx *context.APIContext) {
"data": apiTeams,
})
}

func ListTeamActivityFeeds(ctx *context.APIContext) {
// swagger:operation GET /teams/{id}/activities/feeds organization orgListTeamActivityFeeds
// ---
// summary: List a team's activity feeds
// produces:
// - application/json
// parameters:
// - name: id
// in: path
// description: id of the team
// type: integer
// format: int64
// required: true
// - name: date
// in: query
// description: the date of the activities to be found
// type: string
// format: date
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/ActivityFeedsList"
// "404":
// "$ref": "#/responses/notFound"

listOptions := utils.GetListOptions(ctx)

opts := activities_model.GetFeedsOptions{
RequestedTeam: ctx.Org.Team,
Actor: ctx.Doer,
IncludePrivate: true,
Date: ctx.FormString("date"),
ListOptions: listOptions,
}

feeds, count, err := activities_model.GetFeeds(ctx, opts)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetFeeds", err)
return
}
ctx.SetTotalCountHeader(count)

ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
}
57 changes: 57 additions & 0 deletions routers/api/v1/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"strings"
"time"

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"
Expand Down Expand Up @@ -1199,3 +1200,59 @@ func ValidateIssueConfig(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, api.IssueConfigValidation{Valid: false, Message: err.Error()})
}
}

func ListRepoActivityFeeds(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/activities/feeds repository repoListActivityFeeds
// ---
// summary: List a repository's activity feeds
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: date
// in: query
// description: the date of the activities to be found
// type: string
// format: date
// - name: page
// in: query
// description: page number of results to return (1-based)
// type: integer
// - name: limit
// in: query
// description: page size of results
// type: integer
// responses:
// "200":
// "$ref": "#/responses/ActivityFeedsList"
// "404":
// "$ref": "#/responses/notFound"

listOptions := utils.GetListOptions(ctx)

opts := activities_model.GetFeedsOptions{
RequestedRepo: ctx.Repo.Repository,
Actor: ctx.Doer,
IncludePrivate: true,
Date: ctx.FormString("date"),
ListOptions: listOptions,
}

feeds, count, err := activities_model.GetFeeds(ctx, opts)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetFeeds", err)
return
}
ctx.SetTotalCountHeader(count)

ctx.JSON(http.StatusOK, convert.ToActivities(ctx, feeds, ctx.Doer))
}
15 changes: 15 additions & 0 deletions routers/api/v1/swagger/activity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package swagger

import (
api "code.gitea.io/gitea/modules/structs"
)

// ActivityFeedsList
// swagger:response ActivityFeedsList
type swaggerActivityFeedsList struct {
// in:body
Body []api.Activity `json:"body"`
}
Loading