code.gitea.io/gitea@v1.22.3/routers/api/v1/user/watch.go (about) 1 // Copyright 2016 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package user 5 6 import ( 7 "errors" 8 "net/http" 9 10 access_model "code.gitea.io/gitea/models/perm/access" 11 repo_model "code.gitea.io/gitea/models/repo" 12 user_model "code.gitea.io/gitea/models/user" 13 api "code.gitea.io/gitea/modules/structs" 14 "code.gitea.io/gitea/routers/api/v1/utils" 15 "code.gitea.io/gitea/services/context" 16 "code.gitea.io/gitea/services/convert" 17 ) 18 19 // getWatchedRepos returns the repos that the user with the specified userID is watching 20 func getWatchedRepos(ctx *context.APIContext, user *user_model.User, private bool) ([]*api.Repository, int64, error) { 21 watchedRepos, total, err := repo_model.GetWatchedRepos(ctx, &repo_model.WatchedReposOptions{ 22 ListOptions: utils.GetListOptions(ctx), 23 WatcherID: user.ID, 24 IncludePrivate: private, 25 }) 26 if err != nil { 27 return nil, 0, err 28 } 29 30 repos := make([]*api.Repository, len(watchedRepos)) 31 for i, watched := range watchedRepos { 32 permission, err := access_model.GetUserRepoPermission(ctx, watched, user) 33 if err != nil { 34 return nil, 0, err 35 } 36 repos[i] = convert.ToRepo(ctx, watched, permission) 37 } 38 return repos, total, nil 39 } 40 41 // GetWatchedRepos returns the repos that the user specified in ctx is watching 42 func GetWatchedRepos(ctx *context.APIContext) { 43 // swagger:operation GET /users/{username}/subscriptions user userListSubscriptions 44 // --- 45 // summary: List the repositories watched by a user 46 // produces: 47 // - application/json 48 // parameters: 49 // - name: username 50 // type: string 51 // in: path 52 // description: username of the user 53 // required: true 54 // - name: page 55 // in: query 56 // description: page number of results to return (1-based) 57 // type: integer 58 // - name: limit 59 // in: query 60 // description: page size of results 61 // type: integer 62 // responses: 63 // "200": 64 // "$ref": "#/responses/RepositoryList" 65 // "404": 66 // "$ref": "#/responses/notFound" 67 68 private := ctx.ContextUser.ID == ctx.Doer.ID 69 repos, total, err := getWatchedRepos(ctx, ctx.ContextUser, private) 70 if err != nil { 71 ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) 72 } 73 74 ctx.SetTotalCountHeader(total) 75 ctx.JSON(http.StatusOK, &repos) 76 } 77 78 // GetMyWatchedRepos returns the repos that the authenticated user is watching 79 func GetMyWatchedRepos(ctx *context.APIContext) { 80 // swagger:operation GET /user/subscriptions user userCurrentListSubscriptions 81 // --- 82 // summary: List repositories watched by the authenticated user 83 // produces: 84 // - application/json 85 // parameters: 86 // - name: page 87 // in: query 88 // description: page number of results to return (1-based) 89 // type: integer 90 // - name: limit 91 // in: query 92 // description: page size of results 93 // type: integer 94 // responses: 95 // "200": 96 // "$ref": "#/responses/RepositoryList" 97 98 repos, total, err := getWatchedRepos(ctx, ctx.Doer, true) 99 if err != nil { 100 ctx.Error(http.StatusInternalServerError, "getWatchedRepos", err) 101 } 102 103 ctx.SetTotalCountHeader(total) 104 ctx.JSON(http.StatusOK, &repos) 105 } 106 107 // IsWatching returns whether the authenticated user is watching the repo 108 // specified in ctx 109 func IsWatching(ctx *context.APIContext) { 110 // swagger:operation GET /repos/{owner}/{repo}/subscription repository userCurrentCheckSubscription 111 // --- 112 // summary: Check if the current user is watching a repo 113 // parameters: 114 // - name: owner 115 // in: path 116 // description: owner of the repo 117 // type: string 118 // required: true 119 // - name: repo 120 // in: path 121 // description: name of the repo 122 // type: string 123 // required: true 124 // responses: 125 // "200": 126 // "$ref": "#/responses/WatchInfo" 127 // "404": 128 // description: User is not watching this repo or repo do not exist 129 130 if repo_model.IsWatching(ctx, ctx.Doer.ID, ctx.Repo.Repository.ID) { 131 ctx.JSON(http.StatusOK, api.WatchInfo{ 132 Subscribed: true, 133 Ignored: false, 134 Reason: nil, 135 CreatedAt: ctx.Repo.Repository.CreatedUnix.AsTime(), 136 URL: subscriptionURL(ctx.Repo.Repository), 137 RepositoryURL: ctx.Repo.Repository.APIURL(), 138 }) 139 } else { 140 ctx.NotFound() 141 } 142 } 143 144 // Watch the repo specified in ctx, as the authenticated user 145 func Watch(ctx *context.APIContext) { 146 // swagger:operation PUT /repos/{owner}/{repo}/subscription repository userCurrentPutSubscription 147 // --- 148 // summary: Watch a repo 149 // parameters: 150 // - name: owner 151 // in: path 152 // description: owner of the repo 153 // type: string 154 // required: true 155 // - name: repo 156 // in: path 157 // description: name of the repo 158 // type: string 159 // required: true 160 // responses: 161 // "200": 162 // "$ref": "#/responses/WatchInfo" 163 // "403": 164 // "$ref": "#/responses/forbidden" 165 // "404": 166 // "$ref": "#/responses/notFound" 167 168 err := repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, true) 169 if err != nil { 170 if errors.Is(err, user_model.ErrBlockedUser) { 171 ctx.Error(http.StatusForbidden, "BlockedUser", err) 172 } else { 173 ctx.Error(http.StatusInternalServerError, "WatchRepo", err) 174 } 175 return 176 } 177 ctx.JSON(http.StatusOK, api.WatchInfo{ 178 Subscribed: true, 179 Ignored: false, 180 Reason: nil, 181 CreatedAt: ctx.Repo.Repository.CreatedUnix.AsTime(), 182 URL: subscriptionURL(ctx.Repo.Repository), 183 RepositoryURL: ctx.Repo.Repository.APIURL(), 184 }) 185 } 186 187 // Unwatch the repo specified in ctx, as the authenticated user 188 func Unwatch(ctx *context.APIContext) { 189 // swagger:operation DELETE /repos/{owner}/{repo}/subscription repository userCurrentDeleteSubscription 190 // --- 191 // summary: Unwatch a repo 192 // parameters: 193 // - name: owner 194 // in: path 195 // description: owner of the repo 196 // type: string 197 // required: true 198 // - name: repo 199 // in: path 200 // description: name of the repo 201 // type: string 202 // required: true 203 // responses: 204 // "204": 205 // "$ref": "#/responses/empty" 206 // "404": 207 // "$ref": "#/responses/notFound" 208 209 err := repo_model.WatchRepo(ctx, ctx.Doer, ctx.Repo.Repository, false) 210 if err != nil { 211 ctx.Error(http.StatusInternalServerError, "UnwatchRepo", err) 212 return 213 } 214 ctx.Status(http.StatusNoContent) 215 } 216 217 // subscriptionURL returns the URL of the subscription API endpoint of a repo 218 func subscriptionURL(repo *repo_model.Repository) string { 219 return repo.APIURL() + "/subscription" 220 }