You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

user.go 9.5 kB

API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
API add/generalize pagination (#9452) * paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <6543@obermui.de> Co-Authored-By: zeripath <art27@cantab.net> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <matti@mdranta.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: zeripath <art27@cantab.net>
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package admin
  6. import (
  7. "errors"
  8. "net/http"
  9. "code.gitea.io/gitea/models"
  10. "code.gitea.io/gitea/modules/context"
  11. "code.gitea.io/gitea/modules/convert"
  12. "code.gitea.io/gitea/modules/log"
  13. "code.gitea.io/gitea/modules/password"
  14. api "code.gitea.io/gitea/modules/structs"
  15. "code.gitea.io/gitea/routers/api/v1/user"
  16. "code.gitea.io/gitea/routers/api/v1/utils"
  17. "code.gitea.io/gitea/services/mailer"
  18. )
  19. func parseLoginSource(ctx *context.APIContext, u *models.User, sourceID int64, loginName string) {
  20. if sourceID == 0 {
  21. return
  22. }
  23. source, err := models.GetLoginSourceByID(sourceID)
  24. if err != nil {
  25. if models.IsErrLoginSourceNotExist(err) {
  26. ctx.Error(http.StatusUnprocessableEntity, "", err)
  27. } else {
  28. ctx.Error(http.StatusInternalServerError, "GetLoginSourceByID", err)
  29. }
  30. return
  31. }
  32. u.LoginType = source.Type
  33. u.LoginSource = source.ID
  34. u.LoginName = loginName
  35. }
  36. // CreateUser create a user
  37. func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
  38. // swagger:operation POST /admin/users admin adminCreateUser
  39. // ---
  40. // summary: Create a user
  41. // consumes:
  42. // - application/json
  43. // produces:
  44. // - application/json
  45. // parameters:
  46. // - name: body
  47. // in: body
  48. // schema:
  49. // "$ref": "#/definitions/CreateUserOption"
  50. // responses:
  51. // "201":
  52. // "$ref": "#/responses/User"
  53. // "400":
  54. // "$ref": "#/responses/error"
  55. // "403":
  56. // "$ref": "#/responses/forbidden"
  57. // "422":
  58. // "$ref": "#/responses/validationError"
  59. u := &models.User{
  60. Name: form.Username,
  61. FullName: form.FullName,
  62. Email: form.Email,
  63. Passwd: form.Password,
  64. MustChangePassword: true,
  65. IsActive: true,
  66. LoginType: models.LoginPlain,
  67. }
  68. if form.MustChangePassword != nil {
  69. u.MustChangePassword = *form.MustChangePassword
  70. }
  71. parseLoginSource(ctx, u, form.SourceID, form.LoginName)
  72. if ctx.Written() {
  73. return
  74. }
  75. if !password.IsComplexEnough(form.Password) {
  76. err := errors.New("PasswordComplexity")
  77. ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
  78. return
  79. }
  80. if err := models.CreateUser(u); err != nil {
  81. if models.IsErrUserAlreadyExist(err) ||
  82. models.IsErrEmailAlreadyUsed(err) ||
  83. models.IsErrNameReserved(err) ||
  84. models.IsErrNamePatternNotAllowed(err) {
  85. ctx.Error(http.StatusUnprocessableEntity, "", err)
  86. } else {
  87. ctx.Error(http.StatusInternalServerError, "CreateUser", err)
  88. }
  89. return
  90. }
  91. log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
  92. // Send email notification.
  93. if form.SendNotify {
  94. mailer.SendRegisterNotifyMail(ctx.Locale, u)
  95. }
  96. ctx.JSON(http.StatusCreated, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
  97. }
  98. // EditUser api for modifying a user's information
  99. func EditUser(ctx *context.APIContext, form api.EditUserOption) {
  100. // swagger:operation PATCH /admin/users/{username} admin adminEditUser
  101. // ---
  102. // summary: Edit an existing user
  103. // consumes:
  104. // - application/json
  105. // produces:
  106. // - application/json
  107. // parameters:
  108. // - name: username
  109. // in: path
  110. // description: username of user to edit
  111. // type: string
  112. // required: true
  113. // - name: body
  114. // in: body
  115. // schema:
  116. // "$ref": "#/definitions/EditUserOption"
  117. // responses:
  118. // "200":
  119. // "$ref": "#/responses/User"
  120. // "403":
  121. // "$ref": "#/responses/forbidden"
  122. // "422":
  123. // "$ref": "#/responses/validationError"
  124. u := user.GetUserByParams(ctx)
  125. if ctx.Written() {
  126. return
  127. }
  128. parseLoginSource(ctx, u, form.SourceID, form.LoginName)
  129. if ctx.Written() {
  130. return
  131. }
  132. if len(form.Password) > 0 {
  133. if !password.IsComplexEnough(form.Password) {
  134. err := errors.New("PasswordComplexity")
  135. ctx.Error(http.StatusBadRequest, "PasswordComplexity", err)
  136. return
  137. }
  138. var err error
  139. if u.Salt, err = models.GetUserSalt(); err != nil {
  140. ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
  141. return
  142. }
  143. u.HashPassword(form.Password)
  144. }
  145. if form.MustChangePassword != nil {
  146. u.MustChangePassword = *form.MustChangePassword
  147. }
  148. u.LoginName = form.LoginName
  149. u.FullName = form.FullName
  150. u.Email = form.Email
  151. u.Website = form.Website
  152. u.Location = form.Location
  153. if form.Active != nil {
  154. u.IsActive = *form.Active
  155. }
  156. if form.Admin != nil {
  157. u.IsAdmin = *form.Admin
  158. }
  159. if form.AllowGitHook != nil {
  160. u.AllowGitHook = *form.AllowGitHook
  161. }
  162. if form.AllowImportLocal != nil {
  163. u.AllowImportLocal = *form.AllowImportLocal
  164. }
  165. if form.MaxRepoCreation != nil {
  166. u.MaxRepoCreation = *form.MaxRepoCreation
  167. }
  168. if form.AllowCreateOrganization != nil {
  169. u.AllowCreateOrganization = *form.AllowCreateOrganization
  170. }
  171. if form.ProhibitLogin != nil {
  172. u.ProhibitLogin = *form.ProhibitLogin
  173. }
  174. if err := models.UpdateUser(u); err != nil {
  175. if models.IsErrEmailAlreadyUsed(err) {
  176. ctx.Error(http.StatusUnprocessableEntity, "", err)
  177. } else {
  178. ctx.Error(http.StatusInternalServerError, "UpdateUser", err)
  179. }
  180. return
  181. }
  182. log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
  183. ctx.JSON(http.StatusOK, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
  184. }
  185. // DeleteUser api for deleting a user
  186. func DeleteUser(ctx *context.APIContext) {
  187. // swagger:operation DELETE /admin/users/{username} admin adminDeleteUser
  188. // ---
  189. // summary: Delete a user
  190. // produces:
  191. // - application/json
  192. // parameters:
  193. // - name: username
  194. // in: path
  195. // description: username of user to delete
  196. // type: string
  197. // required: true
  198. // responses:
  199. // "204":
  200. // "$ref": "#/responses/empty"
  201. // "403":
  202. // "$ref": "#/responses/forbidden"
  203. // "422":
  204. // "$ref": "#/responses/validationError"
  205. u := user.GetUserByParams(ctx)
  206. if ctx.Written() {
  207. return
  208. }
  209. if err := models.DeleteUser(u); err != nil {
  210. if models.IsErrUserOwnRepos(err) ||
  211. models.IsErrUserHasOrgs(err) {
  212. ctx.Error(http.StatusUnprocessableEntity, "", err)
  213. } else {
  214. ctx.Error(http.StatusInternalServerError, "DeleteUser", err)
  215. }
  216. return
  217. }
  218. log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name)
  219. ctx.Status(http.StatusNoContent)
  220. }
  221. // CreatePublicKey api for creating a public key to a user
  222. func CreatePublicKey(ctx *context.APIContext, form api.CreateKeyOption) {
  223. // swagger:operation POST /admin/users/{username}/keys admin adminCreatePublicKey
  224. // ---
  225. // summary: Add a public key on behalf of a user
  226. // consumes:
  227. // - application/json
  228. // produces:
  229. // - application/json
  230. // parameters:
  231. // - name: username
  232. // in: path
  233. // description: username of the user
  234. // type: string
  235. // required: true
  236. // - name: key
  237. // in: body
  238. // schema:
  239. // "$ref": "#/definitions/CreateKeyOption"
  240. // responses:
  241. // "201":
  242. // "$ref": "#/responses/PublicKey"
  243. // "403":
  244. // "$ref": "#/responses/forbidden"
  245. // "422":
  246. // "$ref": "#/responses/validationError"
  247. u := user.GetUserByParams(ctx)
  248. if ctx.Written() {
  249. return
  250. }
  251. user.CreateUserPublicKey(ctx, form, u.ID)
  252. }
  253. // DeleteUserPublicKey api for deleting a user's public key
  254. func DeleteUserPublicKey(ctx *context.APIContext) {
  255. // swagger:operation DELETE /admin/users/{username}/keys/{id} admin adminDeleteUserPublicKey
  256. // ---
  257. // summary: Delete a user's public key
  258. // produces:
  259. // - application/json
  260. // parameters:
  261. // - name: username
  262. // in: path
  263. // description: username of user
  264. // type: string
  265. // required: true
  266. // - name: id
  267. // in: path
  268. // description: id of the key to delete
  269. // type: integer
  270. // format: int64
  271. // required: true
  272. // responses:
  273. // "204":
  274. // "$ref": "#/responses/empty"
  275. // "403":
  276. // "$ref": "#/responses/forbidden"
  277. // "404":
  278. // "$ref": "#/responses/notFound"
  279. u := user.GetUserByParams(ctx)
  280. if ctx.Written() {
  281. return
  282. }
  283. if err := models.DeletePublicKey(u, ctx.ParamsInt64(":id")); err != nil {
  284. if models.IsErrKeyNotExist(err) {
  285. ctx.NotFound()
  286. } else if models.IsErrKeyAccessDenied(err) {
  287. ctx.Error(http.StatusForbidden, "", "You do not have access to this key")
  288. } else {
  289. ctx.Error(http.StatusInternalServerError, "DeleteUserPublicKey", err)
  290. }
  291. return
  292. }
  293. log.Trace("Key deleted by admin(%s): %s", ctx.User.Name, u.Name)
  294. ctx.Status(http.StatusNoContent)
  295. }
  296. //GetAllUsers API for getting information of all the users
  297. func GetAllUsers(ctx *context.APIContext) {
  298. // swagger:operation GET /admin/users admin adminGetAllUsers
  299. // ---
  300. // summary: List all users
  301. // produces:
  302. // - application/json
  303. // parameters:
  304. // - name: page
  305. // in: query
  306. // description: page number of results to return (1-based)
  307. // type: integer
  308. // - name: limit
  309. // in: query
  310. // description: page size of results, maximum page size is 50
  311. // type: integer
  312. // responses:
  313. // "200":
  314. // "$ref": "#/responses/UserList"
  315. // "403":
  316. // "$ref": "#/responses/forbidden"
  317. users, _, err := models.SearchUsers(&models.SearchUserOptions{
  318. Type: models.UserTypeIndividual,
  319. OrderBy: models.SearchOrderByAlphabetically,
  320. ListOptions: utils.GetListOptions(ctx),
  321. })
  322. if err != nil {
  323. ctx.Error(http.StatusInternalServerError, "GetAllUsers", err)
  324. return
  325. }
  326. results := make([]*api.User, len(users))
  327. for i := range users {
  328. results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin)
  329. }
  330. ctx.JSON(http.StatusOK, &results)
  331. }