From 9ecd1977ad84a178c2a444608530a7969ce4c10c Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 16:52:45 +0800 Subject: [PATCH 01/28] add user activity feed api --- modules/structs/activity.go | 21 ++++++ routers/api/v1/activity/feeds.go | 68 +++++++++++++++++ routers/api/v1/api.go | 6 ++ routers/api/v1/swagger/activity.go | 15 ++++ services/convert/activity.go | 51 +++++++++++++ templates/swagger/v1_json.tmpl | 117 +++++++++++++++++++++++++++++ 6 files changed, 278 insertions(+) create mode 100644 modules/structs/activity.go create mode 100644 routers/api/v1/activity/feeds.go create mode 100644 routers/api/v1/swagger/activity.go create mode 100644 services/convert/activity.go diff --git a/modules/structs/activity.go b/modules/structs/activity.go new file mode 100644 index 0000000000000..f25262e349d1e --- /dev/null +++ b/modules/structs/activity.go @@ -0,0 +1,21 @@ +// 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"` // Reiciver user + 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"` +} diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go new file mode 100644 index 0000000000000..98206a4b9ae44 --- /dev/null +++ b/routers/api/v1/activity/feeds.go @@ -0,0 +1,68 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package activity + +import ( + "net/http" + + activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" +) + +func ListUserActivityFeeds(ctx *context.APIContext) { + // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds + // --- + // summary: List a user's activity feeds + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: username of user to get + // type: string + // required: true + // - name: only-performed-by + // in: query + // description: if true, only show actions performed by the requested user + // type: boolean + // - name: date + // in: query + // description: the date of the activities to be found, format is YYYY-MM-DD + // type: string + // format: date-time + // - 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" + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedUser: ctx.ContextUser, + Actor: ctx.Doer, + IncludePrivate: includePrivate, + OnlyPerformedBy: ctx.FormBool("only-performed-by"), + 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)) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8b13f5492c148..055afb5369dbe 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -82,6 +82,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/api/v1/activity" "code.gitea.io/gitea/routers/api/v1/activitypub" "code.gitea.io/gitea/routers/api/v1/admin" "code.gitea.io/gitea/routers/api/v1/misc" @@ -749,6 +750,11 @@ func Routes(ctx gocontext.Context) *web.Route { Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) m.Combo("/{id}").Delete(user.DeleteAccessToken) }, reqBasicAuth()) + + m.Group("/activities", func() { + m.Get("/feeds", activity.ListUserActivityFeeds) + }) + }, context_service.UserAssignmentAPI()) }) diff --git a/routers/api/v1/swagger/activity.go b/routers/api/v1/swagger/activity.go new file mode 100644 index 0000000000000..95e1ba903592e --- /dev/null +++ b/routers/api/v1/swagger/activity.go @@ -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"` +} diff --git a/services/convert/activity.go b/services/convert/activity.go new file mode 100644 index 0000000000000..bbf91c6ea0fc4 --- /dev/null +++ b/services/convert/activity.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package convert + +import ( + "context" + + activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" +) + +func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_model.User) *api.Activity { + p, err := access_model.GetUserRepoPermission(ctx, ac.Repo, doer) + if err != nil { + log.Error("GetUserRepoPermission[%d]: %v", ac.RepoID, err) + p.AccessMode = perm.AccessModeNone + } + + result := &api.Activity{ + ID: ac.ID, + UserID: ac.UserID, + ActUserID: ac.ActUserID, + ActUser: ToUser(ctx, ac.ActUser, doer), + RepoID: ac.RepoID, + Repo: ToRepo(ctx, ac.Repo, p.AccessMode), + CommentID: ac.CommentID, + RefName: ac.RefName, + IsPrivate: ac.IsPrivate, + Content: ac.Content, + Created: ac.CreatedUnix.AsTime(), + } + + if ac.Comment != nil { + result.Comment = ToComment(ctx, ac.Comment) + } + + return result +} + +func ToActivities(ctx context.Context, al activities_model.ActionList, doer *user_model.User) []*api.Activity { + result := make([]*api.Activity, 0, len(al)) + for _, ac := range al { + result = append(result, ToActivity(ctx, ac, doer)) + } + return result +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index fe3f31b13d5d6..3b844c2dc5592 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14304,6 +14304,57 @@ } } }, + "/users/{username}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "List a user's activity feeds", + "operationId": "userListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "username of user to get", + "name": "username", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "if true, only show actions performed by the requested user", + "name": "only-performed-by", + "in": "query" + }, + { + "type": "string", + "format": "date-time", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/users/{username}/followers": { "get": { "produces": [ @@ -14894,6 +14945,63 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "Activity": { + "type": "object", + "properties": { + "act_user": { + "$ref": "#/definitions/User" + }, + "act_user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "ActUserID" + }, + "comment": { + "$ref": "#/definitions/Comment" + }, + "comment_id": { + "type": "integer", + "format": "int64", + "x-go-name": "CommentID" + }, + "content": { + "type": "string", + "x-go-name": "Content" + }, + "created": { + "type": "string", + "format": "date-time", + "x-go-name": "Created" + }, + "id": { + "type": "integer", + "format": "int64", + "x-go-name": "ID" + }, + "is_private": { + "type": "boolean", + "x-go-name": "IsPrivate" + }, + "ref_name": { + "type": "string", + "x-go-name": "RefName" + }, + "repo": { + "$ref": "#/definitions/Repository" + }, + "repo_id": { + "type": "integer", + "format": "int64", + "x-go-name": "RepoID" + }, + "user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "UserID" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "ActivityPub": { "description": "ActivityPub type", "type": "object", @@ -20942,6 +21050,15 @@ } } }, + "ActivityFeedsList": { + "description": "ActivityFeedsList", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Activity" + } + } + }, "ActivityPub": { "description": "ActivityPub", "schema": { From 162efae1ebf8f3996e3b0c3afbce4920ee8603d8 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:06:58 +0800 Subject: [PATCH 02/28] fix date format --- routers/api/v1/activity/feeds.go | 2 +- templates/swagger/v1_json.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go index 98206a4b9ae44..2818e6feda366 100644 --- a/routers/api/v1/activity/feeds.go +++ b/routers/api/v1/activity/feeds.go @@ -32,7 +32,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // in: query // description: the date of the activities to be found, format is YYYY-MM-DD // type: string - // format: date-time + // format: date // - name: page // in: query // description: page number of results to return (1-based) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 3b844c2dc5592..dad86fc3bb566 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14330,7 +14330,7 @@ }, { "type": "string", - "format": "date-time", + "format": "date", "description": "the date of the activities to be found, format is YYYY-MM-DD", "name": "date", "in": "query" From 8da61207f09130bfb38ef355f4cb55f98fc752e8 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:09:52 +0800 Subject: [PATCH 03/28] fmt --- routers/api/v1/api.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 055afb5369dbe..5f028f2a74f7a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -754,7 +754,6 @@ func Routes(ctx gocontext.Context) *web.Route { m.Group("/activities", func() { m.Get("/feeds", activity.ListUserActivityFeeds) }) - }, context_service.UserAssignmentAPI()) }) From 722f410a44f9ea17abb77fbbfc996998ebb73984 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:35:35 +0800 Subject: [PATCH 04/28] fix typo --- modules/structs/activity.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/structs/activity.go b/modules/structs/activity.go index f25262e349d1e..a1e789da445a3 100644 --- a/modules/structs/activity.go +++ b/modules/structs/activity.go @@ -7,7 +7,7 @@ import "time" type Activity struct { ID int64 `json:"id"` - UserID int64 `json:"user_id"` // Reiciver user + UserID int64 `json:"user_id"` // Receiver user ActUserID int64 `json:"act_user_id"` ActUser *User `json:"act_user"` RepoID int64 `json:"repo_id"` From 91aad699513c4cec4b915a7edc5b5ba0b58257dc Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 18:21:16 +0800 Subject: [PATCH 05/28] add ListTeamActivityFeeds --- routers/api/v1/activity/feeds.go | 68 -------------------------------- routers/api/v1/api.go | 6 ++- routers/api/v1/org/team.go | 51 ++++++++++++++++++++++++ routers/api/v1/user/user.go | 55 ++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 47 ++++++++++++++++++++++ 5 files changed, 157 insertions(+), 70 deletions(-) delete mode 100644 routers/api/v1/activity/feeds.go diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go deleted file mode 100644 index 2818e6feda366..0000000000000 --- a/routers/api/v1/activity/feeds.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package activity - -import ( - "net/http" - - activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/routers/api/v1/utils" - "code.gitea.io/gitea/services/convert" -) - -func ListUserActivityFeeds(ctx *context.APIContext) { - // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds - // --- - // summary: List a user's activity feeds - // produces: - // - application/json - // parameters: - // - name: username - // in: path - // description: username of user to get - // type: string - // required: true - // - name: only-performed-by - // in: query - // description: if true, only show actions performed by the requested user - // type: boolean - // - name: date - // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD - // 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" - - includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - listOptions := utils.GetListOptions(ctx) - - opts := activities_model.GetFeedsOptions{ - RequestedUser: ctx.ContextUser, - Actor: ctx.Doer, - IncludePrivate: includePrivate, - OnlyPerformedBy: ctx.FormBool("only-performed-by"), - 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)) -} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 5f028f2a74f7a..75dfcc198db96 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -82,7 +82,6 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" - "code.gitea.io/gitea/routers/api/v1/activity" "code.gitea.io/gitea/routers/api/v1/activitypub" "code.gitea.io/gitea/routers/api/v1/admin" "code.gitea.io/gitea/routers/api/v1/misc" @@ -752,7 +751,7 @@ func Routes(ctx gocontext.Context) *web.Route { }, reqBasicAuth()) m.Group("/activities", func() { - m.Get("/feeds", activity.ListUserActivityFeeds) + m.Get("/feeds", user.ListUserActivityFeeds) }) }, context_service.UserAssignmentAPI()) }) @@ -1253,6 +1252,9 @@ func Routes(ctx gocontext.Context) *web.Route { Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository). Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo) }) + m.Group("/activities", func() { + m.Get("/feeds", org.ListTeamActivityFeeds) + }) }, orgAssignment(false, true), reqToken(""), reqTeamMembership()) m.Group("/admin", func() { diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 0c6926759a768..62fd09f7821ab 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -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" @@ -792,3 +793,53 @@ 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, format is YYYY-MM-DD + // 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" + + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, + IncludePrivate: true, // Team membership has been checked by reqTeamMembership middleware, so it should be true here. + 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)) +} diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 6fd4b3a95cf08..186142ff8e5ce 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -145,3 +145,58 @@ func GetUserHeatmapData(ctx *context.APIContext) { } ctx.JSON(http.StatusOK, heatmap) } + +func ListUserActivityFeeds(ctx *context.APIContext) { + // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds + // --- + // summary: List a user's activity feeds + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: username of user to get + // type: string + // required: true + // - name: only-performed-by + // in: query + // description: if true, only show actions performed by the requested user + // type: boolean + // - name: date + // in: query + // description: the date of the activities to be found, format is YYYY-MM-DD + // 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" + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedUser: ctx.ContextUser, + Actor: ctx.Doer, + IncludePrivate: includePrivate, + OnlyPerformedBy: ctx.FormBool("only-performed-by"), + 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)) +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index dad86fc3bb566..00808a339a4d1 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -12645,6 +12645,53 @@ } } }, + "/teams/{id}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization", + "" + ], + "summary": "List a team's activity feeds", + "operationId": "orgListTeamActivityFeeds", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "id of the team", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/teams/{id}/members": { "get": { "produces": [ From 244fd0e7bae0bf3767249b966692555cf417c65d Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 09:32:55 +0800 Subject: [PATCH 06/28] update swagger --- routers/api/v1/org/team.go | 2 +- templates/swagger/v1_json.tmpl | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 62fd09f7821ab..8cc1ed779debe 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -795,7 +795,7 @@ func SearchTeam(ctx *context.APIContext) { } func ListTeamActivityFeeds(ctx *context.APIContext) { - // swagger:operation GET /teams/{id}/activities/feeds organization orgListTeamActivityFeeds + // swagger:operation GET /teams/{id}/activities/feeds organization orgListTeamActivityFeeds // --- // summary: List a team's activity feeds // produces: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 00808a339a4d1..4650ed6db5340 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -12651,8 +12651,7 @@ "application/json" ], "tags": [ - "organization", - "" + "organization" ], "summary": "List a team's activity feeds", "operationId": "orgListTeamActivityFeeds", From 3c434433c713a01e2df8619fe0415d4a8f340a9a Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 13:51:32 +0800 Subject: [PATCH 07/28] add ListRepoActivityFeeds --- routers/api/v1/api.go | 3 ++ routers/api/v1/org/team.go | 7 +++-- routers/api/v1/repo/repo.go | 57 ++++++++++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 52 +++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 75dfcc198db96..8f16a45460b4b 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1176,6 +1176,9 @@ 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.Group("/activities", func() { + m.Get("/feeds", repo.ListRepoActivityFeeds) + }) }, repoAssignment()) }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 8cc1ed779debe..fef6b57d06819 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -827,9 +827,10 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ - RequestedTeam: ctx.Org.Team, - Actor: ctx.Doer, - IncludePrivate: true, // Team membership has been checked by reqTeamMembership middleware, so it should be true here. + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, + // Team membership has been checked by reqTeamMembership middleware, so IncludePrivate should be true here. + IncludePrivate: true, Date: ctx.FormString("date"), ListOptions: listOptions, } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 60e71495e87b8..48ace3a8e02ce 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -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" @@ -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)) +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4650ed6db5340..5357b13c24eb1 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2854,6 +2854,58 @@ } } }, + "/repos/{owner}/{repo}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "List a repo's activity feeds", + "operationId": "repoListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/repos/{owner}/{repo}/archive/{archive}": { "get": { "produces": [ From 70a634881043fa3ab730e1176168cbe49cbb840f Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 15:10:07 +0800 Subject: [PATCH 08/28] add OpType string --- models/activities/action.go | 61 ++++++++++++++++++++++++++++++++++ modules/structs/activity.go | 1 + routers/api/v1/api.go | 1 + routers/api/v1/org/team.go | 5 ++- services/convert/activity.go | 1 + templates/swagger/v1_json.tmpl | 4 +++ 6 files changed, 70 insertions(+), 3 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index 4111d8098b8ee..9214099ed90a6 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -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 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. diff --git a/modules/structs/activity.go b/modules/structs/activity.go index a1e789da445a3..6d2ee56b08570 100644 --- a/modules/structs/activity.go +++ b/modules/structs/activity.go @@ -8,6 +8,7 @@ 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"` diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8f16a45460b4b..e8cb342d9f496 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1176,6 +1176,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.Group("/activities", func() { m.Get("/feeds", repo.ListRepoActivityFeeds) }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index fef6b57d06819..1c1c368960503 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -827,9 +827,8 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ - RequestedTeam: ctx.Org.Team, - Actor: ctx.Doer, - // Team membership has been checked by reqTeamMembership middleware, so IncludePrivate should be true here. + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, IncludePrivate: true, Date: ctx.FormString("date"), ListOptions: listOptions, diff --git a/services/convert/activity.go b/services/convert/activity.go index bbf91c6ea0fc4..fbe3dff6ea4c9 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -24,6 +24,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod result := &api.Activity{ ID: ac.ID, UserID: ac.UserID, + OpType: ac.OpType.String(), ActUserID: ac.ActUserID, ActUser: ToUser(ctx, ac.ActUser, doer), RepoID: ac.RepoID, diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 5357b13c24eb1..bb9268a545937 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15080,6 +15080,10 @@ "type": "boolean", "x-go-name": "IsPrivate" }, + "op_type": { + "type": "string", + "x-go-name": "OpType" + }, "ref_name": { "type": "string", "x-go-name": "RefName" From 4e518f370f5c8969b8813b63f3342e40e42a1715 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:06:46 +0800 Subject: [PATCH 09/28] add ListOrgActivityFeeds --- routers/api/v1/api.go | 3 ++ routers/api/v1/org/org.go | 58 ++++++++++++++++++++++++++++++++++ services/convert/activity.go | 4 +-- templates/swagger/v1_json.tmpl | 45 ++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e8cb342d9f496..202d2451c9a1c 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1237,6 +1237,9 @@ func Routes(ctx gocontext.Context) *web.Route { Patch(bind(api.EditHookOption{}), org.EditHook). Delete(org.DeleteHook) }, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled()) + m.Group("/activities", func() { + m.Get("/feeds", org.ListOrgActivityFeeds) + }) }, orgAssignment(true)) m.Group("/teams/{teamid}", func() { m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam). diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 75420dcc43a8f..19ea70c0e1b56 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -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" @@ -370,3 +371,60 @@ 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, format is YYYY-MM-DD + // 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" + + org := organization.OrgFromUser(ctx.ContextUser) + isMember, err := org.IsOrgMember(ctx.Doer.ID) + if err != nil { + ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) + return + } + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || isMember) + 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)) +} diff --git a/services/convert/activity.go b/services/convert/activity.go index fbe3dff6ea4c9..86d0fa85459dd 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -7,7 +7,7 @@ import ( "context" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/perm" + perm_model "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -18,7 +18,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod p, err := access_model.GetUserRepoPermission(ctx, ac.Repo, doer) if err != nil { log.Error("GetUserRepoPermission[%d]: %v", ac.RepoID, err) - p.AccessMode = perm.AccessModeNone + p.AccessMode = perm_model.AccessModeNone } result := &api.Activity{ diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index bb9268a545937..d242098442450 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1411,6 +1411,51 @@ } } }, + "/orgs/{org}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "List an organization's activity feeds", + "operationId": "orgListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "name of the org", + "name": "org", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/orgs/{org}/hooks": { "get": { "produces": [ From 2eb0930cd183db3a6d8a4f212002d03799c865ab Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:33:16 +0800 Subject: [PATCH 10/28] fix org membership check --- routers/api/v1/org/org.go | 21 ++++++++++++++------- routers/api/v1/org/team.go | 2 +- routers/api/v1/user/user.go | 4 ++-- templates/swagger/v1_json.tmpl | 10 +++++----- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 19ea70c0e1b56..d582154d51c63 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -386,7 +386,7 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // required: true // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page @@ -401,14 +401,21 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // "200": // "$ref": "#/responses/ActivityFeedsList" - org := organization.OrgFromUser(ctx.ContextUser) - isMember, err := org.IsOrgMember(ctx.Doer.ID) - if err != nil { - ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) - return + 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 + } } - includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || isMember) listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 1c1c368960503..56f4d0f8d9e57 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -809,7 +809,7 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { // required: true // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 186142ff8e5ce..47a5682926d6b 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -155,7 +155,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // parameters: // - name: username // in: path - // description: username of user to get + // description: username of user // type: string // required: true // - name: only-performed-by @@ -164,7 +164,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // type: boolean // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d242098442450..df8bb9608c346 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1432,7 +1432,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -2927,7 +2927,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -12764,7 +12764,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -14460,7 +14460,7 @@ "parameters": [ { "type": "string", - "description": "username of user to get", + "description": "username of user", "name": "username", "in": "path", "required": true @@ -14474,7 +14474,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, From 2af7403ebf5a9e8fb69d0e2f95c4705e33875333 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:44:23 +0800 Subject: [PATCH 11/28] add 404 response --- routers/api/v1/org/org.go | 2 ++ routers/api/v1/org/team.go | 2 ++ routers/api/v1/user/user.go | 2 ++ services/convert/activity.go | 2 +- templates/swagger/v1_json.tmpl | 12 ++++++++++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index d582154d51c63..4e30ad17620f3 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -400,6 +400,8 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" includePrivate := false if ctx.IsSigned { diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 56f4d0f8d9e57..ecc3def936b02 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -823,6 +823,8 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" listOptions := utils.GetListOptions(ctx) diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 47a5682926d6b..314116962b559 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -178,6 +178,8 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) listOptions := utils.GetListOptions(ctx) diff --git a/services/convert/activity.go b/services/convert/activity.go index 86d0fa85459dd..2aaa86607b7e0 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -29,7 +29,6 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod ActUser: ToUser(ctx, ac.ActUser, doer), RepoID: ac.RepoID, Repo: ToRepo(ctx, ac.Repo, p.AccessMode), - CommentID: ac.CommentID, RefName: ac.RefName, IsPrivate: ac.IsPrivate, Content: ac.Content, @@ -37,6 +36,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod } if ac.Comment != nil { + result.CommentID = ac.CommentID result.Comment = ToComment(ctx, ac.Comment) } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index df8bb9608c346..9c71a10ee09af 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1452,6 +1452,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -2947,6 +2950,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -12784,6 +12790,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -14494,6 +14503,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } From 7be455d6a210878e6c7d893743ec7103ee5d6774 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:51:37 +0800 Subject: [PATCH 12/28] update swagger --- templates/swagger/v1_json.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 9c71a10ee09af..b31451180a480 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2910,7 +2910,7 @@ "tags": [ "repository" ], - "summary": "List a repo's activity feeds", + "summary": "List a repository's activity feeds", "operationId": "repoListActivityFeeds", "parameters": [ { From b47877c4abda8c1e2287e1b43787bcb9b8311919 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 16:52:45 +0800 Subject: [PATCH 13/28] add user activity feed api --- modules/structs/activity.go | 21 ++++++ routers/api/v1/activity/feeds.go | 68 +++++++++++++++++ routers/api/v1/api.go | 6 ++ routers/api/v1/swagger/activity.go | 15 ++++ services/convert/activity.go | 51 +++++++++++++ templates/swagger/v1_json.tmpl | 117 +++++++++++++++++++++++++++++ 6 files changed, 278 insertions(+) create mode 100644 modules/structs/activity.go create mode 100644 routers/api/v1/activity/feeds.go create mode 100644 routers/api/v1/swagger/activity.go create mode 100644 services/convert/activity.go diff --git a/modules/structs/activity.go b/modules/structs/activity.go new file mode 100644 index 0000000000000..f25262e349d1e --- /dev/null +++ b/modules/structs/activity.go @@ -0,0 +1,21 @@ +// 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"` // Reiciver user + 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"` +} diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go new file mode 100644 index 0000000000000..98206a4b9ae44 --- /dev/null +++ b/routers/api/v1/activity/feeds.go @@ -0,0 +1,68 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package activity + +import ( + "net/http" + + activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" +) + +func ListUserActivityFeeds(ctx *context.APIContext) { + // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds + // --- + // summary: List a user's activity feeds + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: username of user to get + // type: string + // required: true + // - name: only-performed-by + // in: query + // description: if true, only show actions performed by the requested user + // type: boolean + // - name: date + // in: query + // description: the date of the activities to be found, format is YYYY-MM-DD + // type: string + // format: date-time + // - 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" + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedUser: ctx.ContextUser, + Actor: ctx.Doer, + IncludePrivate: includePrivate, + OnlyPerformedBy: ctx.FormBool("only-performed-by"), + 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)) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8b13f5492c148..055afb5369dbe 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -82,6 +82,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" + "code.gitea.io/gitea/routers/api/v1/activity" "code.gitea.io/gitea/routers/api/v1/activitypub" "code.gitea.io/gitea/routers/api/v1/admin" "code.gitea.io/gitea/routers/api/v1/misc" @@ -749,6 +750,11 @@ func Routes(ctx gocontext.Context) *web.Route { Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) m.Combo("/{id}").Delete(user.DeleteAccessToken) }, reqBasicAuth()) + + m.Group("/activities", func() { + m.Get("/feeds", activity.ListUserActivityFeeds) + }) + }, context_service.UserAssignmentAPI()) }) diff --git a/routers/api/v1/swagger/activity.go b/routers/api/v1/swagger/activity.go new file mode 100644 index 0000000000000..95e1ba903592e --- /dev/null +++ b/routers/api/v1/swagger/activity.go @@ -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"` +} diff --git a/services/convert/activity.go b/services/convert/activity.go new file mode 100644 index 0000000000000..bbf91c6ea0fc4 --- /dev/null +++ b/services/convert/activity.go @@ -0,0 +1,51 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package convert + +import ( + "context" + + activities_model "code.gitea.io/gitea/models/activities" + "code.gitea.io/gitea/models/perm" + access_model "code.gitea.io/gitea/models/perm/access" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + api "code.gitea.io/gitea/modules/structs" +) + +func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_model.User) *api.Activity { + p, err := access_model.GetUserRepoPermission(ctx, ac.Repo, doer) + if err != nil { + log.Error("GetUserRepoPermission[%d]: %v", ac.RepoID, err) + p.AccessMode = perm.AccessModeNone + } + + result := &api.Activity{ + ID: ac.ID, + UserID: ac.UserID, + ActUserID: ac.ActUserID, + ActUser: ToUser(ctx, ac.ActUser, doer), + RepoID: ac.RepoID, + Repo: ToRepo(ctx, ac.Repo, p.AccessMode), + CommentID: ac.CommentID, + RefName: ac.RefName, + IsPrivate: ac.IsPrivate, + Content: ac.Content, + Created: ac.CreatedUnix.AsTime(), + } + + if ac.Comment != nil { + result.Comment = ToComment(ctx, ac.Comment) + } + + return result +} + +func ToActivities(ctx context.Context, al activities_model.ActionList, doer *user_model.User) []*api.Activity { + result := make([]*api.Activity, 0, len(al)) + for _, ac := range al { + result = append(result, ToActivity(ctx, ac, doer)) + } + return result +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index fe3f31b13d5d6..3b844c2dc5592 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14304,6 +14304,57 @@ } } }, + "/users/{username}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "user" + ], + "summary": "List a user's activity feeds", + "operationId": "userListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "username of user to get", + "name": "username", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "if true, only show actions performed by the requested user", + "name": "only-performed-by", + "in": "query" + }, + { + "type": "string", + "format": "date-time", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/users/{username}/followers": { "get": { "produces": [ @@ -14894,6 +14945,63 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "Activity": { + "type": "object", + "properties": { + "act_user": { + "$ref": "#/definitions/User" + }, + "act_user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "ActUserID" + }, + "comment": { + "$ref": "#/definitions/Comment" + }, + "comment_id": { + "type": "integer", + "format": "int64", + "x-go-name": "CommentID" + }, + "content": { + "type": "string", + "x-go-name": "Content" + }, + "created": { + "type": "string", + "format": "date-time", + "x-go-name": "Created" + }, + "id": { + "type": "integer", + "format": "int64", + "x-go-name": "ID" + }, + "is_private": { + "type": "boolean", + "x-go-name": "IsPrivate" + }, + "ref_name": { + "type": "string", + "x-go-name": "RefName" + }, + "repo": { + "$ref": "#/definitions/Repository" + }, + "repo_id": { + "type": "integer", + "format": "int64", + "x-go-name": "RepoID" + }, + "user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "UserID" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "ActivityPub": { "description": "ActivityPub type", "type": "object", @@ -20942,6 +21050,15 @@ } } }, + "ActivityFeedsList": { + "description": "ActivityFeedsList", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Activity" + } + } + }, "ActivityPub": { "description": "ActivityPub", "schema": { From 17e80fbfb9b2832a86e7b4600bbd5230092caa52 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:06:58 +0800 Subject: [PATCH 14/28] fix date format --- routers/api/v1/activity/feeds.go | 2 +- templates/swagger/v1_json.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go index 98206a4b9ae44..2818e6feda366 100644 --- a/routers/api/v1/activity/feeds.go +++ b/routers/api/v1/activity/feeds.go @@ -32,7 +32,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // in: query // description: the date of the activities to be found, format is YYYY-MM-DD // type: string - // format: date-time + // format: date // - name: page // in: query // description: page number of results to return (1-based) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 3b844c2dc5592..dad86fc3bb566 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -14330,7 +14330,7 @@ }, { "type": "string", - "format": "date-time", + "format": "date", "description": "the date of the activities to be found, format is YYYY-MM-DD", "name": "date", "in": "query" From 58c3029be492ff56492d27f8d4a0fdd65934cc4d Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:09:52 +0800 Subject: [PATCH 15/28] fmt --- routers/api/v1/api.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 055afb5369dbe..5f028f2a74f7a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -754,7 +754,6 @@ func Routes(ctx gocontext.Context) *web.Route { m.Group("/activities", func() { m.Get("/feeds", activity.ListUserActivityFeeds) }) - }, context_service.UserAssignmentAPI()) }) From bc546edbc44a2ff9d8f8789688b401b8b08f615d Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 17:35:35 +0800 Subject: [PATCH 16/28] fix typo --- modules/structs/activity.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/structs/activity.go b/modules/structs/activity.go index f25262e349d1e..a1e789da445a3 100644 --- a/modules/structs/activity.go +++ b/modules/structs/activity.go @@ -7,7 +7,7 @@ import "time" type Activity struct { ID int64 `json:"id"` - UserID int64 `json:"user_id"` // Reiciver user + UserID int64 `json:"user_id"` // Receiver user ActUserID int64 `json:"act_user_id"` ActUser *User `json:"act_user"` RepoID int64 `json:"repo_id"` From 688768201425ef73aa310cff23e9093f49be8073 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Wed, 15 Mar 2023 18:21:16 +0800 Subject: [PATCH 17/28] add ListTeamActivityFeeds --- routers/api/v1/activity/feeds.go | 68 -------------------------------- routers/api/v1/api.go | 6 ++- routers/api/v1/org/team.go | 51 ++++++++++++++++++++++++ routers/api/v1/user/user.go | 55 ++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 47 ++++++++++++++++++++++ 5 files changed, 157 insertions(+), 70 deletions(-) delete mode 100644 routers/api/v1/activity/feeds.go diff --git a/routers/api/v1/activity/feeds.go b/routers/api/v1/activity/feeds.go deleted file mode 100644 index 2818e6feda366..0000000000000 --- a/routers/api/v1/activity/feeds.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package activity - -import ( - "net/http" - - activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/modules/context" - "code.gitea.io/gitea/routers/api/v1/utils" - "code.gitea.io/gitea/services/convert" -) - -func ListUserActivityFeeds(ctx *context.APIContext) { - // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds - // --- - // summary: List a user's activity feeds - // produces: - // - application/json - // parameters: - // - name: username - // in: path - // description: username of user to get - // type: string - // required: true - // - name: only-performed-by - // in: query - // description: if true, only show actions performed by the requested user - // type: boolean - // - name: date - // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD - // 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" - - includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - listOptions := utils.GetListOptions(ctx) - - opts := activities_model.GetFeedsOptions{ - RequestedUser: ctx.ContextUser, - Actor: ctx.Doer, - IncludePrivate: includePrivate, - OnlyPerformedBy: ctx.FormBool("only-performed-by"), - 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)) -} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 5f028f2a74f7a..75dfcc198db96 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -82,7 +82,6 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" - "code.gitea.io/gitea/routers/api/v1/activity" "code.gitea.io/gitea/routers/api/v1/activitypub" "code.gitea.io/gitea/routers/api/v1/admin" "code.gitea.io/gitea/routers/api/v1/misc" @@ -752,7 +751,7 @@ func Routes(ctx gocontext.Context) *web.Route { }, reqBasicAuth()) m.Group("/activities", func() { - m.Get("/feeds", activity.ListUserActivityFeeds) + m.Get("/feeds", user.ListUserActivityFeeds) }) }, context_service.UserAssignmentAPI()) }) @@ -1253,6 +1252,9 @@ func Routes(ctx gocontext.Context) *web.Route { Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository). Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo) }) + m.Group("/activities", func() { + m.Get("/feeds", org.ListTeamActivityFeeds) + }) }, orgAssignment(false, true), reqToken(""), reqTeamMembership()) m.Group("/admin", func() { diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 0c6926759a768..62fd09f7821ab 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -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" @@ -792,3 +793,53 @@ 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, format is YYYY-MM-DD + // 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" + + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, + IncludePrivate: true, // Team membership has been checked by reqTeamMembership middleware, so it should be true here. + 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)) +} diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 6fd4b3a95cf08..186142ff8e5ce 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -145,3 +145,58 @@ func GetUserHeatmapData(ctx *context.APIContext) { } ctx.JSON(http.StatusOK, heatmap) } + +func ListUserActivityFeeds(ctx *context.APIContext) { + // swagger:operation GET /users/{username}/activities/feeds user userListActivityFeeds + // --- + // summary: List a user's activity feeds + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: username of user to get + // type: string + // required: true + // - name: only-performed-by + // in: query + // description: if true, only show actions performed by the requested user + // type: boolean + // - name: date + // in: query + // description: the date of the activities to be found, format is YYYY-MM-DD + // 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" + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) + listOptions := utils.GetListOptions(ctx) + + opts := activities_model.GetFeedsOptions{ + RequestedUser: ctx.ContextUser, + Actor: ctx.Doer, + IncludePrivate: includePrivate, + OnlyPerformedBy: ctx.FormBool("only-performed-by"), + 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)) +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index dad86fc3bb566..00808a339a4d1 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -12645,6 +12645,53 @@ } } }, + "/teams/{id}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization", + "" + ], + "summary": "List a team's activity feeds", + "operationId": "orgListTeamActivityFeeds", + "parameters": [ + { + "type": "integer", + "format": "int64", + "description": "id of the team", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/teams/{id}/members": { "get": { "produces": [ From 4d530cfe3919884a09718f29dd9ce55192438617 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 09:32:55 +0800 Subject: [PATCH 18/28] update swagger --- routers/api/v1/org/team.go | 2 +- templates/swagger/v1_json.tmpl | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 62fd09f7821ab..8cc1ed779debe 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -795,7 +795,7 @@ func SearchTeam(ctx *context.APIContext) { } func ListTeamActivityFeeds(ctx *context.APIContext) { - // swagger:operation GET /teams/{id}/activities/feeds organization orgListTeamActivityFeeds + // swagger:operation GET /teams/{id}/activities/feeds organization orgListTeamActivityFeeds // --- // summary: List a team's activity feeds // produces: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 00808a339a4d1..4650ed6db5340 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -12651,8 +12651,7 @@ "application/json" ], "tags": [ - "organization", - "" + "organization" ], "summary": "List a team's activity feeds", "operationId": "orgListTeamActivityFeeds", From 0939e1cd8ec18ecead973604a07055aff2334ea1 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 13:51:32 +0800 Subject: [PATCH 19/28] add ListRepoActivityFeeds --- routers/api/v1/api.go | 3 ++ routers/api/v1/org/team.go | 7 +++-- routers/api/v1/repo/repo.go | 57 ++++++++++++++++++++++++++++++++++ templates/swagger/v1_json.tmpl | 52 +++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 75dfcc198db96..8f16a45460b4b 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1176,6 +1176,9 @@ 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.Group("/activities", func() { + m.Get("/feeds", repo.ListRepoActivityFeeds) + }) }, repoAssignment()) }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 8cc1ed779debe..fef6b57d06819 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -827,9 +827,10 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ - RequestedTeam: ctx.Org.Team, - Actor: ctx.Doer, - IncludePrivate: true, // Team membership has been checked by reqTeamMembership middleware, so it should be true here. + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, + // Team membership has been checked by reqTeamMembership middleware, so IncludePrivate should be true here. + IncludePrivate: true, Date: ctx.FormString("date"), ListOptions: listOptions, } diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 60e71495e87b8..48ace3a8e02ce 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -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" @@ -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)) +} diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 4650ed6db5340..5357b13c24eb1 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2854,6 +2854,58 @@ } } }, + "/repos/{owner}/{repo}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "List a repo's activity feeds", + "operationId": "repoListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/repos/{owner}/{repo}/archive/{archive}": { "get": { "produces": [ From 5b0ce9508d54da7fa31611c23fd21f2e5ec4d1cf Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 15:10:07 +0800 Subject: [PATCH 20/28] add OpType string --- models/activities/action.go | 61 ++++++++++++++++++++++++++++++++++ modules/structs/activity.go | 1 + routers/api/v1/api.go | 1 + routers/api/v1/org/team.go | 5 ++- services/convert/activity.go | 1 + templates/swagger/v1_json.tmpl | 4 +++ 6 files changed, 70 insertions(+), 3 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index 4111d8098b8ee..9214099ed90a6 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -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 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. diff --git a/modules/structs/activity.go b/modules/structs/activity.go index a1e789da445a3..6d2ee56b08570 100644 --- a/modules/structs/activity.go +++ b/modules/structs/activity.go @@ -8,6 +8,7 @@ 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"` diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 8f16a45460b4b..e8cb342d9f496 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1176,6 +1176,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.Group("/activities", func() { m.Get("/feeds", repo.ListRepoActivityFeeds) }) diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index fef6b57d06819..1c1c368960503 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -827,9 +827,8 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ - RequestedTeam: ctx.Org.Team, - Actor: ctx.Doer, - // Team membership has been checked by reqTeamMembership middleware, so IncludePrivate should be true here. + RequestedTeam: ctx.Org.Team, + Actor: ctx.Doer, IncludePrivate: true, Date: ctx.FormString("date"), ListOptions: listOptions, diff --git a/services/convert/activity.go b/services/convert/activity.go index bbf91c6ea0fc4..fbe3dff6ea4c9 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -24,6 +24,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod result := &api.Activity{ ID: ac.ID, UserID: ac.UserID, + OpType: ac.OpType.String(), ActUserID: ac.ActUserID, ActUser: ToUser(ctx, ac.ActUser, doer), RepoID: ac.RepoID, diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 5357b13c24eb1..bb9268a545937 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -15080,6 +15080,10 @@ "type": "boolean", "x-go-name": "IsPrivate" }, + "op_type": { + "type": "string", + "x-go-name": "OpType" + }, "ref_name": { "type": "string", "x-go-name": "RefName" From 6a7c7dc67d2939eb943d85c363876df287ce4334 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:06:46 +0800 Subject: [PATCH 21/28] add ListOrgActivityFeeds --- routers/api/v1/api.go | 3 ++ routers/api/v1/org/org.go | 58 ++++++++++++++++++++++++++++++++++ services/convert/activity.go | 4 +-- templates/swagger/v1_json.tmpl | 45 ++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 2 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e8cb342d9f496..202d2451c9a1c 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1237,6 +1237,9 @@ func Routes(ctx gocontext.Context) *web.Route { Patch(bind(api.EditHookOption{}), org.EditHook). Delete(org.DeleteHook) }, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled()) + m.Group("/activities", func() { + m.Get("/feeds", org.ListOrgActivityFeeds) + }) }, orgAssignment(true)) m.Group("/teams/{teamid}", func() { m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam). diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 75420dcc43a8f..19ea70c0e1b56 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -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" @@ -370,3 +371,60 @@ 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, format is YYYY-MM-DD + // 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" + + org := organization.OrgFromUser(ctx.ContextUser) + isMember, err := org.IsOrgMember(ctx.Doer.ID) + if err != nil { + ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) + return + } + + includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || isMember) + 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)) +} diff --git a/services/convert/activity.go b/services/convert/activity.go index fbe3dff6ea4c9..86d0fa85459dd 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -7,7 +7,7 @@ import ( "context" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/perm" + perm_model "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -18,7 +18,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod p, err := access_model.GetUserRepoPermission(ctx, ac.Repo, doer) if err != nil { log.Error("GetUserRepoPermission[%d]: %v", ac.RepoID, err) - p.AccessMode = perm.AccessModeNone + p.AccessMode = perm_model.AccessModeNone } result := &api.Activity{ diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index bb9268a545937..d242098442450 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1411,6 +1411,51 @@ } } }, + "/orgs/{org}/activities/feeds": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "organization" + ], + "summary": "List an organization's activity feeds", + "operationId": "orgListActivityFeeds", + "parameters": [ + { + "type": "string", + "description": "name of the org", + "name": "org", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "date", + "description": "the date of the activities to be found, format is YYYY-MM-DD", + "name": "date", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/ActivityFeedsList" + } + } + } + }, "/orgs/{org}/hooks": { "get": { "produces": [ From 7f9ea9d197eca31388826be3694b72950190669b Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:33:16 +0800 Subject: [PATCH 22/28] fix org membership check --- routers/api/v1/org/org.go | 21 ++++++++++++++------- routers/api/v1/org/team.go | 2 +- routers/api/v1/user/user.go | 4 ++-- templates/swagger/v1_json.tmpl | 10 +++++----- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index 19ea70c0e1b56..d582154d51c63 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -386,7 +386,7 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // required: true // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page @@ -401,14 +401,21 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // "200": // "$ref": "#/responses/ActivityFeedsList" - org := organization.OrgFromUser(ctx.ContextUser) - isMember, err := org.IsOrgMember(ctx.Doer.ID) - if err != nil { - ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) - return + 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 + } } - includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || isMember) listOptions := utils.GetListOptions(ctx) opts := activities_model.GetFeedsOptions{ diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 1c1c368960503..56f4d0f8d9e57 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -809,7 +809,7 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { // required: true // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 186142ff8e5ce..47a5682926d6b 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -155,7 +155,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // parameters: // - name: username // in: path - // description: username of user to get + // description: username of user // type: string // required: true // - name: only-performed-by @@ -164,7 +164,7 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // type: boolean // - name: date // in: query - // description: the date of the activities to be found, format is YYYY-MM-DD + // description: the date of the activities to be found // type: string // format: date // - name: page diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index d242098442450..df8bb9608c346 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1432,7 +1432,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -2927,7 +2927,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -12764,7 +12764,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, @@ -14460,7 +14460,7 @@ "parameters": [ { "type": "string", - "description": "username of user to get", + "description": "username of user", "name": "username", "in": "path", "required": true @@ -14474,7 +14474,7 @@ { "type": "string", "format": "date", - "description": "the date of the activities to be found, format is YYYY-MM-DD", + "description": "the date of the activities to be found", "name": "date", "in": "query" }, From 5744f6d6984f2443e0fed08fd00d04688b0b8131 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:44:23 +0800 Subject: [PATCH 23/28] add 404 response --- routers/api/v1/org/org.go | 2 ++ routers/api/v1/org/team.go | 2 ++ routers/api/v1/user/user.go | 2 ++ services/convert/activity.go | 2 +- templates/swagger/v1_json.tmpl | 12 ++++++++++++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index d582154d51c63..4e30ad17620f3 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -400,6 +400,8 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" includePrivate := false if ctx.IsSigned { diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go index 56f4d0f8d9e57..ecc3def936b02 100644 --- a/routers/api/v1/org/team.go +++ b/routers/api/v1/org/team.go @@ -823,6 +823,8 @@ func ListTeamActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" listOptions := utils.GetListOptions(ctx) diff --git a/routers/api/v1/user/user.go b/routers/api/v1/user/user.go index 47a5682926d6b..314116962b559 100644 --- a/routers/api/v1/user/user.go +++ b/routers/api/v1/user/user.go @@ -178,6 +178,8 @@ func ListUserActivityFeeds(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/ActivityFeedsList" + // "404": + // "$ref": "#/responses/notFound" includePrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) listOptions := utils.GetListOptions(ctx) diff --git a/services/convert/activity.go b/services/convert/activity.go index 86d0fa85459dd..2aaa86607b7e0 100644 --- a/services/convert/activity.go +++ b/services/convert/activity.go @@ -29,7 +29,6 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod ActUser: ToUser(ctx, ac.ActUser, doer), RepoID: ac.RepoID, Repo: ToRepo(ctx, ac.Repo, p.AccessMode), - CommentID: ac.CommentID, RefName: ac.RefName, IsPrivate: ac.IsPrivate, Content: ac.Content, @@ -37,6 +36,7 @@ func ToActivity(ctx context.Context, ac *activities_model.Action, doer *user_mod } if ac.Comment != nil { + result.CommentID = ac.CommentID result.Comment = ToComment(ctx, ac.Comment) } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index df8bb9608c346..9c71a10ee09af 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1452,6 +1452,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -2947,6 +2950,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -12784,6 +12790,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -14494,6 +14503,9 @@ "responses": { "200": { "$ref": "#/responses/ActivityFeedsList" + }, + "404": { + "$ref": "#/responses/notFound" } } } From 3a5ece59c7963b0b2ad083d142e4e744691a8351 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Thu, 16 Mar 2023 16:51:37 +0800 Subject: [PATCH 24/28] update swagger --- templates/swagger/v1_json.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 9c71a10ee09af..b31451180a480 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -2910,7 +2910,7 @@ "tags": [ "repository" ], - "summary": "List a repo's activity feeds", + "summary": "List a repository's activity feeds", "operationId": "repoListActivityFeeds", "parameters": [ { From 7693df8d1d53d321b9d965464123e50269ac65f5 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Tue, 4 Apr 2023 10:08:52 +0800 Subject: [PATCH 25/28] use lower case action name --- models/activities/action.go | 56 ++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/models/activities/action.go b/models/activities/action.go index 9214099ed90a6..ca6692ab8ef2d 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -69,61 +69,61 @@ const ( func (at ActionType) String() string { switch at { case ActionCreateRepo: - return "CREATE_REPO" + return "create_repo" case ActionRenameRepo: - return "RENAME_REPO" + return "rename_repo" case ActionStarRepo: - return "STAR_REPO" + return "star_repo" case ActionWatchRepo: - return "WATCH_REPO" + return "watch_repo" case ActionCommitRepo: - return "COMMIT_REPO" + return "commit_repo" case ActionCreateIssue: - return "CREATE_ISSUE" + return "create_issue" case ActionCreatePullRequest: - return "CREATE_PULL_REQUEST" + return "create_pull_request" case ActionTransferRepo: - return "TRANSFER_REPO" + return "transfer_repo" case ActionPushTag: - return "PUSH_TAG" + return "push_tag" case ActionCommentIssue: - return "COMMENT_ISSUE" + return "comment_issue" case ActionMergePullRequest: - return "MERGE_PULL_REQUEST" + return "merge_pull_request" case ActionCloseIssue: - return "CLOSE_ISSUE" + return "close_issue" case ActionReopenIssue: - return "REOPEN_ISSUE" + return "reopen_issue" case ActionClosePullRequest: - return "CLOSE_PULL_REQUEST" + return "close_pull_request" case ActionReopenPullRequest: - return "REOPEN_PULL_REQUEST" + return "reopen_pull_request" case ActionDeleteTag: - return "DELETE_TAG" + return "delete_tag" case ActionDeleteBranch: - return "DELETE_BRANCH" + return "delete_branch" case ActionMirrorSyncPush: - return "MIRROR_SYNC_PUSH" + return "mirror_sync_push" case ActionMirrorSyncCreate: - return "MIRROR_SYNC_CREATE" + return "mirror_sync_create" case ActionMirrorSyncDelete: - return "MIRROR_SYNC_DELETE" + return "mirror_sync_delete" case ActionApprovePullRequest: - return "APPROVE_PULL_REQUEST" + return "approve_pull_request" case ActionRejectPullRequest: - return "REJECT_PULL_REQUEST" + return "reject_pull_request" case ActionCommentPull: - return "COMMENT_PULL" + return "comment_pull" case ActionPublishRelease: - return "PUBLISH_RELEASE" + return "publish_release" case ActionPullReviewDismissed: - return "PULL_REVIEW_DISMISSED" + return "pull_review_dismissed" case ActionPullRequestReadyForReview: - return "PULL_REQUEST_READY_FOR_REVIEW" + return "pull_request_ready_for_review" case ActionAutoMergePullRequest: - return "AUTO_MERGE_PULL_REQUEST" + return "auto_merge_pull_request" default: - return strconv.Itoa(int(at)) + return "action" + strconv.Itoa(int(at)) } } From c086ffb4fc430bdc9c904b68c8baf26ead0987ad Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Tue, 4 Apr 2023 10:12:33 +0800 Subject: [PATCH 26/28] improve routers --- routers/api/v1/api.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 202d2451c9a1c..b95b33d97a914 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -750,9 +750,8 @@ func Routes(ctx gocontext.Context) *web.Route { m.Combo("/{id}").Delete(user.DeleteAccessToken) }, reqBasicAuth()) - m.Group("/activities", func() { - m.Get("/feeds", user.ListUserActivityFeeds) - }) + m.Get("/activities/feeds", user.ListUserActivityFeeds) + }, context_service.UserAssignmentAPI()) }) @@ -1176,10 +1175,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.Group("/activities", func() { - m.Get("/feeds", repo.ListRepoActivityFeeds) - }) + m.Get("/activities/feeds", repo.ListRepoActivityFeeds) }, repoAssignment()) }) @@ -1237,9 +1233,7 @@ func Routes(ctx gocontext.Context) *web.Route { Patch(bind(api.EditHookOption{}), org.EditHook). Delete(org.DeleteHook) }, reqToken(auth_model.AccessTokenScopeAdminOrgHook), reqOrgOwnership(), reqWebhooksEnabled()) - m.Group("/activities", func() { - m.Get("/feeds", org.ListOrgActivityFeeds) - }) + m.Get("/activities/feeds", org.ListOrgActivityFeeds) }, orgAssignment(true)) m.Group("/teams/{teamid}", func() { m.Combo("").Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeam). @@ -1259,9 +1253,7 @@ func Routes(ctx gocontext.Context) *web.Route { Delete(reqToken(auth_model.AccessTokenScopeWriteOrg), org.RemoveTeamRepository). Get(reqToken(auth_model.AccessTokenScopeReadOrg), org.GetTeamRepo) }) - m.Group("/activities", func() { - m.Get("/feeds", org.ListTeamActivityFeeds) - }) + m.Get("/activities/feeds", org.ListTeamActivityFeeds) }, orgAssignment(false, true), reqToken(""), reqTeamMembership()) m.Group("/admin", func() { From 130b3eaa4a9403536429e637fc0bdd671ddb85a2 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Tue, 4 Apr 2023 10:16:24 +0800 Subject: [PATCH 27/28] remove empty line --- routers/api/v1/api.go | 1 - 1 file changed, 1 deletion(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index b95b33d97a914..54d0ab5f0fcc8 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -751,7 +751,6 @@ func Routes(ctx gocontext.Context) *web.Route { }, reqBasicAuth()) m.Get("/activities/feeds", user.ListUserActivityFeeds) - }, context_service.UserAssignmentAPI()) }) From 9939acbbff8e8fca635d88c2bc9457cb7531d628 Mon Sep 17 00:00:00 2001 From: Zettat123 Date: Tue, 4 Apr 2023 10:18:16 +0800 Subject: [PATCH 28/28] add separator --- models/activities/action.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/activities/action.go b/models/activities/action.go index ca6692ab8ef2d..f75ab559823d5 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -123,7 +123,7 @@ func (at ActionType) String() string { case ActionAutoMergePullRequest: return "auto_merge_pull_request" default: - return "action" + strconv.Itoa(int(at)) + return "action-" + strconv.Itoa(int(at)) } }