1// Copyright 2015 The Gogs Authors. All rights reserved. 2// Copyright 2020 The Gitea Authors. 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file. 5 6package user 7 8import ( 9 "net/http" 10 11 user_model "code.gitea.io/gitea/models/user" 12 "code.gitea.io/gitea/modules/context" 13 "code.gitea.io/gitea/modules/convert" 14 api "code.gitea.io/gitea/modules/structs" 15 "code.gitea.io/gitea/routers/api/v1/utils" 16) 17 18func responseAPIUsers(ctx *context.APIContext, users []*user_model.User) { 19 apiUsers := make([]*api.User, len(users)) 20 for i := range users { 21 apiUsers[i] = convert.ToUser(users[i], ctx.User) 22 } 23 ctx.JSON(http.StatusOK, &apiUsers) 24} 25 26func listUserFollowers(ctx *context.APIContext, u *user_model.User) { 27 users, err := user_model.GetUserFollowers(u, utils.GetListOptions(ctx)) 28 if err != nil { 29 ctx.Error(http.StatusInternalServerError, "GetUserFollowers", err) 30 return 31 } 32 33 ctx.SetTotalCountHeader(int64(u.NumFollowers)) 34 responseAPIUsers(ctx, users) 35} 36 37// ListMyFollowers list the authenticated user's followers 38func ListMyFollowers(ctx *context.APIContext) { 39 // swagger:operation GET /user/followers user userCurrentListFollowers 40 // --- 41 // summary: List the authenticated user's followers 42 // parameters: 43 // - name: page 44 // in: query 45 // description: page number of results to return (1-based) 46 // type: integer 47 // - name: limit 48 // in: query 49 // description: page size of results 50 // type: integer 51 // produces: 52 // - application/json 53 // responses: 54 // "200": 55 // "$ref": "#/responses/UserList" 56 57 listUserFollowers(ctx, ctx.User) 58} 59 60// ListFollowers list the given user's followers 61func ListFollowers(ctx *context.APIContext) { 62 // swagger:operation GET /users/{username}/followers user userListFollowers 63 // --- 64 // summary: List the given user's followers 65 // produces: 66 // - application/json 67 // parameters: 68 // - name: username 69 // in: path 70 // description: username of user 71 // type: string 72 // required: true 73 // - name: page 74 // in: query 75 // description: page number of results to return (1-based) 76 // type: integer 77 // - name: limit 78 // in: query 79 // description: page size of results 80 // type: integer 81 // responses: 82 // "200": 83 // "$ref": "#/responses/UserList" 84 85 u := GetUserByParams(ctx) 86 if ctx.Written() { 87 return 88 } 89 listUserFollowers(ctx, u) 90} 91 92func listUserFollowing(ctx *context.APIContext, u *user_model.User) { 93 users, err := user_model.GetUserFollowing(u, utils.GetListOptions(ctx)) 94 if err != nil { 95 ctx.Error(http.StatusInternalServerError, "GetUserFollowing", err) 96 return 97 } 98 99 ctx.SetTotalCountHeader(int64(u.NumFollowing)) 100 responseAPIUsers(ctx, users) 101} 102 103// ListMyFollowing list the users that the authenticated user is following 104func ListMyFollowing(ctx *context.APIContext) { 105 // swagger:operation GET /user/following user userCurrentListFollowing 106 // --- 107 // summary: List the users that the authenticated user is following 108 // parameters: 109 // - name: page 110 // in: query 111 // description: page number of results to return (1-based) 112 // type: integer 113 // - name: limit 114 // in: query 115 // description: page size of results 116 // type: integer 117 // produces: 118 // - application/json 119 // responses: 120 // "200": 121 // "$ref": "#/responses/UserList" 122 123 listUserFollowing(ctx, ctx.User) 124} 125 126// ListFollowing list the users that the given user is following 127func ListFollowing(ctx *context.APIContext) { 128 // swagger:operation GET /users/{username}/following user userListFollowing 129 // --- 130 // summary: List the users that the given user is following 131 // produces: 132 // - application/json 133 // parameters: 134 // - name: username 135 // in: path 136 // description: username of user 137 // type: string 138 // required: true 139 // - name: page 140 // in: query 141 // description: page number of results to return (1-based) 142 // type: integer 143 // - name: limit 144 // in: query 145 // description: page size of results 146 // type: integer 147 // responses: 148 // "200": 149 // "$ref": "#/responses/UserList" 150 151 u := GetUserByParams(ctx) 152 if ctx.Written() { 153 return 154 } 155 listUserFollowing(ctx, u) 156} 157 158func checkUserFollowing(ctx *context.APIContext, u *user_model.User, followID int64) { 159 if user_model.IsFollowing(u.ID, followID) { 160 ctx.Status(http.StatusNoContent) 161 } else { 162 ctx.NotFound() 163 } 164} 165 166// CheckMyFollowing whether the given user is followed by the authenticated user 167func CheckMyFollowing(ctx *context.APIContext) { 168 // swagger:operation GET /user/following/{username} user userCurrentCheckFollowing 169 // --- 170 // summary: Check whether a user is followed by the authenticated user 171 // parameters: 172 // - name: username 173 // in: path 174 // description: username of followed user 175 // type: string 176 // required: true 177 // responses: 178 // "204": 179 // "$ref": "#/responses/empty" 180 // "404": 181 // "$ref": "#/responses/notFound" 182 183 target := GetUserByParams(ctx) 184 if ctx.Written() { 185 return 186 } 187 checkUserFollowing(ctx, ctx.User, target.ID) 188} 189 190// CheckFollowing check if one user is following another user 191func CheckFollowing(ctx *context.APIContext) { 192 // swagger:operation GET /users/{follower}/following/{followee} user userCheckFollowing 193 // --- 194 // summary: Check if one user is following another user 195 // parameters: 196 // - name: follower 197 // in: path 198 // description: username of following user 199 // type: string 200 // required: true 201 // - name: followee 202 // in: path 203 // description: username of followed user 204 // type: string 205 // required: true 206 // responses: 207 // "204": 208 // "$ref": "#/responses/empty" 209 // "404": 210 // "$ref": "#/responses/notFound" 211 212 u := GetUserByParams(ctx) 213 if ctx.Written() { 214 return 215 } 216 target := GetUserByParamsName(ctx, ":target") 217 if ctx.Written() { 218 return 219 } 220 checkUserFollowing(ctx, u, target.ID) 221} 222 223// Follow follow a user 224func Follow(ctx *context.APIContext) { 225 // swagger:operation PUT /user/following/{username} user userCurrentPutFollow 226 // --- 227 // summary: Follow a user 228 // parameters: 229 // - name: username 230 // in: path 231 // description: username of user to follow 232 // type: string 233 // required: true 234 // responses: 235 // "204": 236 // "$ref": "#/responses/empty" 237 238 target := GetUserByParams(ctx) 239 if ctx.Written() { 240 return 241 } 242 if err := user_model.FollowUser(ctx.User.ID, target.ID); err != nil { 243 ctx.Error(http.StatusInternalServerError, "FollowUser", err) 244 return 245 } 246 ctx.Status(http.StatusNoContent) 247} 248 249// Unfollow unfollow a user 250func Unfollow(ctx *context.APIContext) { 251 // swagger:operation DELETE /user/following/{username} user userCurrentDeleteFollow 252 // --- 253 // summary: Unfollow a user 254 // parameters: 255 // - name: username 256 // in: path 257 // description: username of user to unfollow 258 // type: string 259 // required: true 260 // responses: 261 // "204": 262 // "$ref": "#/responses/empty" 263 264 target := GetUserByParams(ctx) 265 if ctx.Written() { 266 return 267 } 268 if err := user_model.UnfollowUser(ctx.User.ID, target.ID); err != nil { 269 ctx.Error(http.StatusInternalServerError, "UnfollowUser", err) 270 return 271 } 272 ctx.Status(http.StatusNoContent) 273} 274