From d56bb7420184c0c2f451f4bcaa96c9b3b00c393d Mon Sep 17 00:00:00 2001 From: techknowlogick Date: Tue, 14 Mar 2023 03:54:40 -0400 Subject: [PATCH] add admin API email endpoints (#22792) add email endpoint to admin API to ensure API parity with admin dashboard. --- modules/structs/user_email.go | 3 ++ routers/api/v1/admin/email.go | 87 ++++++++++++++++++++++++++++++++++ routers/api/v1/api.go | 4 ++ services/convert/convert.go | 11 +++++ templates/swagger/v1_json.tmpl | 83 ++++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+) create mode 100644 routers/api/v1/admin/email.go diff --git a/modules/structs/user_email.go b/modules/structs/user_email.go index 6a11e040af..9319667e8f 100644 --- a/modules/structs/user_email.go +++ b/modules/structs/user_email.go @@ -1,4 +1,5 @@ // Copyright 2015 The Gogs Authors. All rights reserved. +// Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package structs @@ -9,6 +10,8 @@ type Email struct { Email string `json:"email"` Verified bool `json:"verified"` Primary bool `json:"primary"` + UserID int64 `json:"user_id"` + UserName string `json:"username"` } // CreateEmailOption options when creating email addresses diff --git a/routers/api/v1/admin/email.go b/routers/api/v1/admin/email.go new file mode 100644 index 0000000000..8d0491e070 --- /dev/null +++ b/routers/api/v1/admin/email.go @@ -0,0 +1,87 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package admin + +import ( + "net/http" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/context" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" +) + +// GetAllEmails +func GetAllEmails(ctx *context.APIContext) { + // swagger:operation GET /admin/emails admin adminGetAllEmails + // --- + // summary: List all emails + // produces: + // - application/json + // parameters: + // - 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/EmailList" + // "403": + // "$ref": "#/responses/forbidden" + + listOptions := utils.GetListOptions(ctx) + + emails, maxResults, err := user_model.SearchEmails(&user_model.SearchEmailOptions{ + Keyword: ctx.Params(":email"), + ListOptions: listOptions, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetAllEmails", err) + return + } + + results := make([]*api.Email, len(emails)) + for i := range emails { + results[i] = convert.ToEmailSearch(emails[i]) + } + + ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) + ctx.SetTotalCountHeader(maxResults) + ctx.JSON(http.StatusOK, &results) +} + +// SearchEmail +func SearchEmail(ctx *context.APIContext) { + // swagger:operation GET /admin/emails/search admin adminSearchEmails + // --- + // summary: Search all emails + // produces: + // - application/json + // parameters: + // - name: q + // in: query + // description: keyword + // type: string + // - 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/EmailList" + // "403": + // "$ref": "#/responses/forbidden" + + ctx.SetParams(":email", ctx.FormTrim("q")) + GetAllEmails(ctx) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 7001dc72ac..5c32164fa7 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1260,6 +1260,10 @@ func Routes(ctx gocontext.Context) *web.Route { m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser) }, context_service.UserAssignmentAPI()) }) + m.Group("/emails", func() { + m.Get("", admin.GetAllEmails) + m.Get("/search", admin.SearchEmail) + }) m.Group("/unadopted", func() { m.Get("", admin.ListUnadoptedRepositories) m.Post("/{username}/{reponame}", admin.AdoptRepository) diff --git a/services/convert/convert.go b/services/convert/convert.go index 5f2100a039..bce0e7ba21 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -38,6 +38,17 @@ func ToEmail(email *user_model.EmailAddress) *api.Email { } } +// ToEmail convert models.EmailAddress to api.Email +func ToEmailSearch(email *user_model.SearchEmailResult) *api.Email { + return &api.Email{ + Email: email.Email, + Verified: email.IsActivated, + Primary: email.IsPrimary, + UserID: email.UID, + UserName: email.Name, + } +} + // ToBranch convert a git.Commit and git.Branch to an api.Branch func ToBranch(ctx context.Context, repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *git_model.ProtectedBranch, user *user_model.User, isRepoAdmin bool) (*api.Branch, error) { if bp == nil { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 7dc7f563c2..9c89b21fca 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -138,6 +138,80 @@ } } }, + "/admin/emails": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "List all emails", + "operationId": "adminGetAllEmails", + "parameters": [ + { + "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/EmailList" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, + "/admin/emails/search": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Search all emails", + "operationId": "adminSearchEmails", + "parameters": [ + { + "type": "string", + "description": "keyword", + "name": "q", + "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/EmailList" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, "/admin/hooks": { "get": { "produces": [ @@ -16999,6 +17073,15 @@ "type": "boolean", "x-go-name": "Primary" }, + "user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "UserID" + }, + "username": { + "type": "string", + "x-go-name": "UserName" + }, "verified": { "type": "boolean", "x-go-name": "Verified"