mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 18:25:56 +01:00
Add users search API
Signed-off-by: He Weiwei <hweiwei@vmware.com>
This commit is contained in:
parent
62bb10d2e4
commit
20556aebd2
@ -748,6 +748,45 @@ paths:
|
|||||||
description: User need to log in first.
|
description: User need to log in first.
|
||||||
'500':
|
'500':
|
||||||
description: Internal errors.
|
description: Internal errors.
|
||||||
|
/users/search:
|
||||||
|
get:
|
||||||
|
summary: Search users by username, email
|
||||||
|
description: |
|
||||||
|
This endpoint is to search the users by username, email.
|
||||||
|
parameters:
|
||||||
|
- name: username
|
||||||
|
in: query
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
description: Username for filtering results.
|
||||||
|
- name: email
|
||||||
|
in: query
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
description: Email for filtering results.
|
||||||
|
- name: page
|
||||||
|
in: query
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
required: false
|
||||||
|
description: 'The page nubmer, default is 1.'
|
||||||
|
- name: page_size
|
||||||
|
in: query
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
required: false
|
||||||
|
description: The size of per page.
|
||||||
|
tags:
|
||||||
|
- Products
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Search users by username, email successfully.
|
||||||
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/definitions/UserSearch'
|
||||||
|
'500':
|
||||||
|
description: Unexpected internal errors.
|
||||||
'/users/{user_id}':
|
'/users/{user_id}':
|
||||||
get:
|
get:
|
||||||
summary: Get a user's profile.
|
summary: Get a user's profile.
|
||||||
@ -3485,6 +3524,15 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
update_time:
|
update_time:
|
||||||
type: string
|
type: string
|
||||||
|
UserSearch:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
user_id:
|
||||||
|
type: integer
|
||||||
|
format: int
|
||||||
|
description: The ID of the user.
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
Password:
|
Password:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
|
@ -102,6 +102,7 @@ func init() {
|
|||||||
beego.Router("/api/projects/:id", &ProjectAPI{}, "delete:Delete;get:Get;put:Put")
|
beego.Router("/api/projects/:id", &ProjectAPI{}, "delete:Delete;get:Get;put:Put")
|
||||||
beego.Router("/api/users/:id", &UserAPI{}, "get:Get")
|
beego.Router("/api/users/:id", &UserAPI{}, "get:Get")
|
||||||
beego.Router("/api/users", &UserAPI{}, "get:List;post:Post;delete:Delete;put:Put")
|
beego.Router("/api/users", &UserAPI{}, "get:List;post:Post;delete:Delete;put:Put")
|
||||||
|
beego.Router("/api/users/search", &UserAPI{}, "get:Search")
|
||||||
beego.Router("/api/users/:id([0-9]+)/password", &UserAPI{}, "put:ChangePassword")
|
beego.Router("/api/users/:id([0-9]+)/password", &UserAPI{}, "put:ChangePassword")
|
||||||
beego.Router("/api/users/:id/permissions", &UserAPI{}, "get:ListUserPermissions")
|
beego.Router("/api/users/:id/permissions", &UserAPI{}, "get:ListUserPermissions")
|
||||||
beego.Router("/api/users/:id/sysadmin", &UserAPI{}, "put:ToggleUserAdminRole")
|
beego.Router("/api/users/:id/sysadmin", &UserAPI{}, "put:ToggleUserAdminRole")
|
||||||
@ -913,6 +914,25 @@ func (a testapi) UsersGet(userName string, authInfo usrInfo) (int, []apilib.User
|
|||||||
return httpStatusCode, successPayLoad, err
|
return httpStatusCode, successPayLoad, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search registered users of Harbor.
|
||||||
|
func (a testapi) UsersSearch(userName string, authInfo ...usrInfo) (int, []apilib.UserSearch, error) {
|
||||||
|
_sling := sling.New().Get(a.basePath)
|
||||||
|
// create path and map variables
|
||||||
|
path := "/api/users/search"
|
||||||
|
_sling = _sling.Path(path)
|
||||||
|
// body params
|
||||||
|
type QueryParams struct {
|
||||||
|
UserName string `url:"username, omitempty"`
|
||||||
|
}
|
||||||
|
_sling = _sling.QueryStruct(&QueryParams{UserName: userName})
|
||||||
|
httpStatusCode, body, err := request(_sling, jsonAcceptHeader, authInfo...)
|
||||||
|
var successPayLoad []apilib.UserSearch
|
||||||
|
if 200 == httpStatusCode && nil == err {
|
||||||
|
err = json.Unmarshal(body, &successPayLoad)
|
||||||
|
}
|
||||||
|
return httpStatusCode, successPayLoad, err
|
||||||
|
}
|
||||||
|
|
||||||
// Get registered users by userid.
|
// Get registered users by userid.
|
||||||
func (a testapi) UsersGetByID(userName string, authInfo usrInfo, userID int) (int, apilib.User, error) {
|
func (a testapi) UsersGetByID(userName string, authInfo usrInfo, userID int) (int, apilib.User, error) {
|
||||||
_sling := sling.New().Get(a.basePath)
|
_sling := sling.New().Get(a.basePath)
|
||||||
|
@ -46,6 +46,11 @@ type passwordReq struct {
|
|||||||
NewPassword string `json:"new_password"`
|
NewPassword string `json:"new_password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type userSearch struct {
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare validates the URL and parms
|
// Prepare validates the URL and parms
|
||||||
func (ua *UserAPI) Prepare() {
|
func (ua *UserAPI) Prepare() {
|
||||||
ua.BaseController.Prepare()
|
ua.BaseController.Prepare()
|
||||||
@ -166,6 +171,40 @@ func (ua *UserAPI) List() {
|
|||||||
ua.ServeJSON()
|
ua.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search ...
|
||||||
|
func (ua *UserAPI) Search() {
|
||||||
|
page, size := ua.GetPaginationParams()
|
||||||
|
query := &models.UserQuery{
|
||||||
|
Username: ua.GetString("username"),
|
||||||
|
Email: ua.GetString("email"),
|
||||||
|
Pagination: &models.Pagination{
|
||||||
|
Page: page,
|
||||||
|
Size: size,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
total, err := dao.GetTotalOfUsers(query)
|
||||||
|
if err != nil {
|
||||||
|
ua.HandleInternalServerError(fmt.Sprintf("failed to get total of users: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
users, err := dao.ListUsers(query)
|
||||||
|
if err != nil {
|
||||||
|
ua.HandleInternalServerError(fmt.Sprintf("failed to get users: %v", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var userSearches []userSearch
|
||||||
|
for _, user := range users {
|
||||||
|
userSearches = append(userSearches, userSearch{UserID: user.UserID, Username: user.Username})
|
||||||
|
}
|
||||||
|
|
||||||
|
ua.SetPaginationHeader(total, page, size)
|
||||||
|
ua.Data["json"] = userSearches
|
||||||
|
ua.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
// Put ...
|
// Put ...
|
||||||
func (ua *UserAPI) Put() {
|
func (ua *UserAPI) Put() {
|
||||||
if !ua.modifiable() {
|
if !ua.modifiable() {
|
||||||
|
@ -208,6 +208,35 @@ func TestUsersGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUsersSearch(t *testing.T) {
|
||||||
|
|
||||||
|
fmt.Println("Testing User Search")
|
||||||
|
assert := assert.New(t)
|
||||||
|
apiTest := newHarborAPI()
|
||||||
|
|
||||||
|
testUser0002.Username = "testUser0002"
|
||||||
|
// case 1: Search user2 without auth, expect 401
|
||||||
|
|
||||||
|
testUser0002Auth = &usrInfo{"testUser0002", "testUser0002"}
|
||||||
|
code, users, err := apiTest.UsersSearch(testUser0002.Username)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occurred while search users", err.Error())
|
||||||
|
t.Log(err)
|
||||||
|
} else {
|
||||||
|
assert.Equal(401, code, "Search users status should be 401")
|
||||||
|
}
|
||||||
|
// case 2: Search user2 with with common auth, expect 200
|
||||||
|
code, users, err = apiTest.UsersSearch(testUser0002.Username, *testUser0002Auth)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occurred while search users", err.Error())
|
||||||
|
t.Log(err)
|
||||||
|
} else {
|
||||||
|
assert.Equal(200, code, "Search users status should be 200")
|
||||||
|
assert.Equal(1, len(users), "Search users record should be 1 ")
|
||||||
|
testUser0002ID = users[0].UserID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUsersGetByID(t *testing.T) {
|
func TestUsersGetByID(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println("Testing User GetByID")
|
fmt.Println("Testing User GetByID")
|
||||||
|
@ -45,6 +45,7 @@ func initRouters() {
|
|||||||
|
|
||||||
beego.Router("/api/users/:id", &api.UserAPI{}, "get:Get;delete:Delete;put:Put")
|
beego.Router("/api/users/:id", &api.UserAPI{}, "get:Get;delete:Delete;put:Put")
|
||||||
beego.Router("/api/users", &api.UserAPI{}, "get:List;post:Post")
|
beego.Router("/api/users", &api.UserAPI{}, "get:List;post:Post")
|
||||||
|
beego.Router("/api/users/search", &api.UserAPI{}, "get:Search")
|
||||||
beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword")
|
beego.Router("/api/users/:id([0-9]+)/password", &api.UserAPI{}, "put:ChangePassword")
|
||||||
beego.Router("/api/users/:id/permissions", &api.UserAPI{}, "get:ListUserPermissions")
|
beego.Router("/api/users/:id/permissions", &api.UserAPI{}, "get:ListUserPermissions")
|
||||||
beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")
|
beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")
|
||||||
|
@ -54,6 +54,12 @@ type User struct {
|
|||||||
UpdateTime string `json:"update_time,omitempty"`
|
UpdateTime string `json:"update_time,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserSearch the user search type
|
||||||
|
type UserSearch struct {
|
||||||
|
UserID int `json:"user_id,omitempty"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// Permission the permission type
|
// Permission the permission type
|
||||||
type Permission struct {
|
type Permission struct {
|
||||||
Resource string `json:"resource,omitempty"`
|
Resource string `json:"resource,omitempty"`
|
||||||
|
Loading…
Reference in New Issue
Block a user