mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
Merge pull request #2386 from ywk253100/170525_log_pagination
Support pagination in GET recent logs API
This commit is contained in:
commit
0679796528
@ -861,24 +861,18 @@ paths:
|
||||
description: |
|
||||
This endpoint let user see the recent operation logs of the projects which he is member of
|
||||
parameters:
|
||||
- name: lines
|
||||
- name: page
|
||||
in: query
|
||||
type: integer
|
||||
format: int32
|
||||
required: false
|
||||
description: The number of logs to be shown, default is 10 if lines, start_time, end_time are not provided.
|
||||
- name: start_time
|
||||
description: The page nubmer, default is 1.
|
||||
- name: page_size
|
||||
in: query
|
||||
type: integer
|
||||
format: int64
|
||||
format: int32
|
||||
required: false
|
||||
description: The start time of logs to be shown in unix timestap
|
||||
- name: end_time
|
||||
in: query
|
||||
type: integer
|
||||
format: int64
|
||||
required: false
|
||||
description: The end time of logs to be shown in unix timestap
|
||||
description: The size of per page, default is 10, maximum is 100.
|
||||
tags:
|
||||
- Products
|
||||
responses:
|
||||
@ -889,7 +883,7 @@ paths:
|
||||
items:
|
||||
$ref: '#/definitions/AccessLog'
|
||||
400:
|
||||
description: Bad request because of invalid parameter of lines or start_time or end_time.
|
||||
description: Bad request because of invalid parameters.
|
||||
401:
|
||||
description: User need to login first.
|
||||
500:
|
||||
|
@ -15,8 +15,7 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/astaxie/beego/orm"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
)
|
||||
@ -29,155 +28,61 @@ func AddAccessLog(accessLog models.AccessLog) error {
|
||||
}
|
||||
|
||||
// GetTotalOfAccessLogs ...
|
||||
func GetTotalOfAccessLogs(query models.AccessLog) (int64, error) {
|
||||
o := GetOrmer()
|
||||
|
||||
queryParam := []interface{}{}
|
||||
|
||||
sql := `select count(*) from access_log al
|
||||
where al.project_id = ?`
|
||||
queryParam = append(queryParam, query.ProjectID)
|
||||
|
||||
sql += genFilterClauses(query, &queryParam)
|
||||
|
||||
var total int64
|
||||
if err := o.Raw(sql, queryParam).QueryRow(&total); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return total, nil
|
||||
func GetTotalOfAccessLogs(query *models.LogQueryParam) (int64, error) {
|
||||
return logQueryConditions(query).Count()
|
||||
}
|
||||
|
||||
//GetAccessLogs gets access logs according to different conditions
|
||||
func GetAccessLogs(query models.AccessLog, limit, offset int64) ([]models.AccessLog, error) {
|
||||
o := GetOrmer()
|
||||
func GetAccessLogs(query *models.LogQueryParam) ([]models.AccessLog, error) {
|
||||
qs := logQueryConditions(query).OrderBy("-op_time")
|
||||
|
||||
queryParam := []interface{}{}
|
||||
sql := `select al.log_id, al.username, al.repo_name,
|
||||
al.repo_tag, al.operation, al.op_time
|
||||
from access_log al
|
||||
where al.project_id = ? `
|
||||
queryParam = append(queryParam, query.ProjectID)
|
||||
if query != nil && query.Pagination != nil {
|
||||
size := query.Pagination.Size
|
||||
if size > 0 {
|
||||
qs = qs.Limit(size)
|
||||
|
||||
sql += genFilterClauses(query, &queryParam)
|
||||
|
||||
sql += ` order by al.op_time desc `
|
||||
|
||||
sql = paginateForRawSQL(sql, limit, offset)
|
||||
|
||||
logs := []models.AccessLog{}
|
||||
_, err := o.Raw(sql, queryParam).QueryRows(&logs)
|
||||
if err != nil {
|
||||
return logs, err
|
||||
}
|
||||
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func genFilterClauses(query models.AccessLog, queryParam *[]interface{}) string {
|
||||
sql := ""
|
||||
|
||||
if query.Username != "" {
|
||||
sql += ` and al.username like ? `
|
||||
*queryParam = append(*queryParam, "%"+escape(query.Username)+"%")
|
||||
}
|
||||
|
||||
if query.Operation != "" {
|
||||
sql += ` and al.operation = ? `
|
||||
*queryParam = append(*queryParam, query.Operation)
|
||||
}
|
||||
if query.RepoName != "" {
|
||||
sql += ` and al.repo_name = ? `
|
||||
*queryParam = append(*queryParam, query.RepoName)
|
||||
}
|
||||
if query.RepoTag != "" {
|
||||
sql += ` and al.repo_tag = ? `
|
||||
*queryParam = append(*queryParam, query.RepoTag)
|
||||
}
|
||||
if query.Keywords != "" {
|
||||
sql += ` and al.operation in ( `
|
||||
keywordList := strings.Split(query.Keywords, "/")
|
||||
num := len(keywordList)
|
||||
for i := 0; i < num; i++ {
|
||||
if keywordList[i] != "" {
|
||||
if i == num-1 {
|
||||
sql += `?)`
|
||||
} else {
|
||||
sql += `?,`
|
||||
}
|
||||
*queryParam = append(*queryParam, keywordList[i])
|
||||
page := query.Pagination.Page
|
||||
if page > 0 {
|
||||
qs = qs.Offset((page - 1) * size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if query.BeginTimestamp > 0 {
|
||||
sql += ` and al.op_time >= ? `
|
||||
*queryParam = append(*queryParam, query.BeginTime)
|
||||
}
|
||||
if query.EndTimestamp > 0 {
|
||||
sql += ` and al.op_time <= ? `
|
||||
*queryParam = append(*queryParam, query.EndTime)
|
||||
}
|
||||
|
||||
return sql
|
||||
logs := []models.AccessLog{}
|
||||
_, err := qs.All(&logs)
|
||||
return logs, err
|
||||
}
|
||||
|
||||
//GetRecentLogs returns recent logs according to parameters
|
||||
func GetRecentLogs(username string, linesNum int, startTime, endTime string) ([]models.AccessLog, error) {
|
||||
logs := []models.AccessLog{}
|
||||
func logQueryConditions(query *models.LogQueryParam) orm.QuerySeter {
|
||||
qs := GetOrmer().QueryTable(&models.AccessLog{})
|
||||
|
||||
isAdmin, err := IsAdminRole(username)
|
||||
if err != nil {
|
||||
return logs, err
|
||||
if query == nil {
|
||||
return qs
|
||||
}
|
||||
|
||||
queryParam := []interface{}{}
|
||||
sql := `select log_id, username, project_id, repo_name, repo_tag, GUID, operation, op_time
|
||||
from access_log `
|
||||
|
||||
hasWhere := false
|
||||
if !isAdmin {
|
||||
sql += ` where project_id in
|
||||
(select distinct project_id
|
||||
from project_member pm
|
||||
join user u
|
||||
on pm.user_id = u.user_id
|
||||
where u.username = ?) `
|
||||
queryParam = append(queryParam, username)
|
||||
hasWhere = true
|
||||
if len(query.ProjectIDs) > 0 {
|
||||
qs = qs.Filter("project_id__in", query.ProjectIDs)
|
||||
}
|
||||
if len(query.Username) != 0 {
|
||||
qs = qs.Filter("username__contains", query.Username)
|
||||
}
|
||||
if len(query.Repository) != 0 {
|
||||
qs = qs.Filter("repo_name", query.Repository)
|
||||
}
|
||||
if len(query.Tag) != 0 {
|
||||
qs = qs.Filter("repo_tag", query.Tag)
|
||||
}
|
||||
if len(query.Operations) > 0 {
|
||||
qs = qs.Filter("operation__in", query.Operations)
|
||||
}
|
||||
if query.BeginTime != nil {
|
||||
qs = qs.Filter("op_time__gte", query.BeginTime)
|
||||
}
|
||||
if query.EndTime != nil {
|
||||
qs = qs.Filter("op_time__lte", query.EndTime)
|
||||
}
|
||||
|
||||
if startTime != "" {
|
||||
if hasWhere {
|
||||
sql += " and op_time >= ?"
|
||||
} else {
|
||||
sql += " where op_time >= ?"
|
||||
hasWhere = true
|
||||
}
|
||||
|
||||
queryParam = append(queryParam, startTime)
|
||||
}
|
||||
|
||||
if endTime != "" {
|
||||
if hasWhere {
|
||||
sql += " and op_time <= ?"
|
||||
} else {
|
||||
sql += " where op_time <= ?"
|
||||
hasWhere = true
|
||||
}
|
||||
|
||||
queryParam = append(queryParam, endTime)
|
||||
}
|
||||
|
||||
sql += " order by op_time desc"
|
||||
if linesNum != 0 {
|
||||
sql += " limit ?"
|
||||
queryParam = append(queryParam, linesNum)
|
||||
}
|
||||
|
||||
_, err = GetOrmer().Raw(sql, queryParam).QueryRows(&logs)
|
||||
if err != nil {
|
||||
return logs, err
|
||||
}
|
||||
return logs, nil
|
||||
return qs
|
||||
}
|
||||
|
||||
// CountPull ...
|
||||
|
@ -570,11 +570,11 @@ func TestGetAccessLog(t *testing.T) {
|
||||
t.Errorf("failed to add access log: %v", err)
|
||||
}
|
||||
|
||||
queryAccessLog := models.AccessLog{
|
||||
Username: currentUser.Username,
|
||||
ProjectID: currentProject.ProjectID,
|
||||
query := &models.LogQueryParam{
|
||||
Username: currentUser.Username,
|
||||
ProjectIDs: []int64{currentProject.ProjectID},
|
||||
}
|
||||
accessLogs, err := GetAccessLogs(queryAccessLog, 1000, 0)
|
||||
accessLogs, err := GetAccessLogs(query)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in GetAccessLog: %v", err)
|
||||
}
|
||||
@ -587,11 +587,11 @@ func TestGetAccessLog(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTotalOfAccessLogs(t *testing.T) {
|
||||
queryAccessLog := models.AccessLog{
|
||||
Username: currentUser.Username,
|
||||
ProjectID: currentProject.ProjectID,
|
||||
query := &models.LogQueryParam{
|
||||
Username: currentUser.Username,
|
||||
ProjectIDs: []int64{currentProject.ProjectID},
|
||||
}
|
||||
total, err := GetTotalOfAccessLogs(queryAccessLog)
|
||||
total, err := GetTotalOfAccessLogs(query)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get total of access log: %v", err)
|
||||
}
|
||||
@ -617,7 +617,15 @@ func TestAddAccessLog(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in AddAccessLog: %v", err)
|
||||
}
|
||||
accessLogList, err = GetAccessLogs(accessLog, 1000, 0)
|
||||
|
||||
query := &models.LogQueryParam{
|
||||
Username: accessLog.Username,
|
||||
ProjectIDs: []int64{accessLog.ProjectID},
|
||||
Repository: accessLog.RepoName,
|
||||
Tag: accessLog.RepoTag,
|
||||
Operations: []string{accessLog.Operation},
|
||||
}
|
||||
accessLogList, err = GetAccessLogs(query)
|
||||
if err != nil {
|
||||
t.Errorf("Error occurred in GetAccessLog: %v", err)
|
||||
}
|
||||
@ -819,7 +827,7 @@ func TestGetProjects(t *testing.T) {
|
||||
|
||||
func TestGetPublicProjects(t *testing.T) {
|
||||
value := true
|
||||
projects, err := GetProjects(&models.QueryParam{
|
||||
projects, err := GetProjects(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
if err != nil {
|
||||
@ -953,16 +961,6 @@ func TestChangeUserProfile(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRecentLogs(t *testing.T) {
|
||||
logs, err := GetRecentLogs(currentUser.Username, 10, "2016-05-13 00:00:00", time.Now().String())
|
||||
if err != nil {
|
||||
t.Errorf("error occured in getting recent logs, error: %v", err)
|
||||
}
|
||||
if len(logs) <= 0 {
|
||||
t.Errorf("get logs error, expected: %d, actual: %d", 1, len(logs))
|
||||
}
|
||||
}
|
||||
|
||||
var targetID, policyID, policyID2, policyID3, jobID, jobID2, jobID3 int64
|
||||
|
||||
func TestAddRepTarget(t *testing.T) {
|
||||
|
@ -190,7 +190,7 @@ func GetHasReadPermProjects(username string) ([]*models.Project, error) {
|
||||
|
||||
// GetTotalOfProjects returns the total count of projects
|
||||
// according to the query conditions
|
||||
func GetTotalOfProjects(query *models.QueryParam) (int64, error) {
|
||||
func GetTotalOfProjects(query *models.ProjectQueryParam) (int64, error) {
|
||||
|
||||
var (
|
||||
owner string
|
||||
@ -210,7 +210,7 @@ func GetTotalOfProjects(query *models.QueryParam) (int64, error) {
|
||||
}
|
||||
}
|
||||
|
||||
sql, params := queryConditions(owner, name, public, member, role)
|
||||
sql, params := projectQueryConditions(owner, name, public, member, role)
|
||||
|
||||
sql = `select count(*) ` + sql
|
||||
|
||||
@ -220,7 +220,7 @@ func GetTotalOfProjects(query *models.QueryParam) (int64, error) {
|
||||
}
|
||||
|
||||
// GetProjects returns a project list according to the query conditions
|
||||
func GetProjects(query *models.QueryParam) ([]*models.Project, error) {
|
||||
func GetProjects(query *models.ProjectQueryParam) ([]*models.Project, error) {
|
||||
|
||||
var (
|
||||
owner string
|
||||
@ -246,7 +246,7 @@ func GetProjects(query *models.QueryParam) ([]*models.Project, error) {
|
||||
}
|
||||
}
|
||||
|
||||
sql, params := queryConditions(owner, name, public, member, role)
|
||||
sql, params := projectQueryConditions(owner, name, public, member, role)
|
||||
|
||||
sql = `select distinct p.project_id, p.name, p.public, p.owner_id,
|
||||
p.creation_time, p.update_time ` + sql
|
||||
@ -265,7 +265,7 @@ func GetProjects(query *models.QueryParam) ([]*models.Project, error) {
|
||||
return projects, err
|
||||
}
|
||||
|
||||
func queryConditions(owner, name string, public *bool, member string,
|
||||
func projectQueryConditions(owner, name string, public *bool, member string,
|
||||
role int) (string, []interface{}) {
|
||||
params := []interface{}{}
|
||||
|
||||
|
@ -30,8 +30,19 @@ type AccessLog struct {
|
||||
Operation string `orm:"column(operation)" json:"operation"`
|
||||
OpTime time.Time `orm:"column(op_time)" json:"op_time"`
|
||||
Keywords string `orm:"-" json:"keywords"`
|
||||
BeginTime time.Time `orm:"-"`
|
||||
BeginTimestamp int64 `orm:"-" json:"begin_timestamp"`
|
||||
EndTime time.Time `orm:"-"`
|
||||
EndTimestamp int64 `orm:"-" json:"end_timestamp"`
|
||||
}
|
||||
|
||||
// LogQueryParam is used to set query conditions when listing
|
||||
// access logs.
|
||||
type LogQueryParam struct {
|
||||
ProjectIDs []int64 // the IDs of projects to which the operation is done
|
||||
Username string // the operator's username of the log
|
||||
Repository string // repository name
|
||||
Tag string // tag name
|
||||
Operations []string // operations
|
||||
BeginTime *time.Time // the time after which the operation is done
|
||||
EndTime *time.Time // the time before which the operation is doen
|
||||
Pagination *Pagination // pagination information
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func (ps *ProjectSorter) Swap(i, j int) {
|
||||
ps.Projects[i], ps.Projects[j] = ps.Projects[j], ps.Projects[i]
|
||||
}
|
||||
|
||||
// QueryParam can be used to set query parameters when listing projects.
|
||||
// ProjectQueryParam can be used to set query parameters when listing projects.
|
||||
// The query condition will be set in the query if its corresponding field
|
||||
// is not nil. Leave it empty if you don't want to apply this condition.
|
||||
//
|
||||
@ -69,7 +69,7 @@ func (ps *ProjectSorter) Swap(i, j int) {
|
||||
// List all public projects the owner of which is user1: query := &QueryParam{Owner:"user1",Public:true}
|
||||
// List projects which user1 is member of: query := &QueryParam{Member:&Member{Name:"user1"}}
|
||||
// List projects which user1 is the project admin : query := &QueryParam{Memeber:&Member{Name:"user1",Role:1}}
|
||||
type QueryParam struct {
|
||||
type ProjectQueryParam struct {
|
||||
Name string // the name of project
|
||||
Owner string // the username of project owner
|
||||
Public *bool // the project is public or not, can be ture, false and nil
|
||||
|
@ -106,7 +106,7 @@ func (f *fakePM) Update(projectIDOrName interface{}, project *models.Project) er
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetAll(*models.QueryParam) ([]*models.Project, error) {
|
||||
func (f *fakePM) GetAll(*models.ProjectQueryParam) ([]*models.Project, error) {
|
||||
return []*models.Project{}, nil
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ func (f *fakePM) GetHasReadPerm(username ...string) ([]*models.Project, error) {
|
||||
}
|
||||
|
||||
// nil implement
|
||||
func (f *fakePM) GetTotal(*models.QueryParam) (int64, error) {
|
||||
func (f *fakePM) GetTotal(*models.ProjectQueryParam) (int64, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
|
@ -226,20 +226,14 @@ func (a testapi) StatisticGet(user usrInfo) (int, apilib.StatisticMap, error) {
|
||||
return httpStatusCode, successPayload, err
|
||||
}
|
||||
|
||||
func (a testapi) LogGet(user usrInfo, startTime, endTime, lines string) (int, []apilib.AccessLog, error) {
|
||||
func (a testapi) LogGet(user usrInfo) (int, []apilib.AccessLog, error) {
|
||||
_sling := sling.New().Get(a.basePath)
|
||||
|
||||
// create path and map variables
|
||||
path := "/api/logs/"
|
||||
fmt.Printf("logs path: %s\n", path)
|
||||
_sling = _sling.Path(path)
|
||||
type QueryParams struct {
|
||||
StartTime string `url:"start_time,omitempty"`
|
||||
EndTime string `url:"end_time,omitempty"`
|
||||
Lines string `url:"lines,omitempty"`
|
||||
}
|
||||
|
||||
_sling = _sling.QueryStruct(&QueryParams{StartTime: startTime, EndTime: endTime, Lines: lines})
|
||||
var successPayload []apilib.AccessLog
|
||||
code, body, err := request(_sling, jsonAcceptHeader, user)
|
||||
if 200 == code && nil == err {
|
||||
|
@ -15,18 +15,17 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
"fmt"
|
||||
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
"github.com/vmware/harbor/src/common/models"
|
||||
"github.com/vmware/harbor/src/common/utils/log"
|
||||
)
|
||||
|
||||
//LogAPI handles request api/logs
|
||||
type LogAPI struct {
|
||||
BaseController
|
||||
username string
|
||||
isSysAdmin bool
|
||||
}
|
||||
|
||||
//Prepare validates the URL and the user
|
||||
@ -36,53 +35,58 @@ func (l *LogAPI) Prepare() {
|
||||
l.HandleUnauthorized()
|
||||
return
|
||||
}
|
||||
l.username = l.SecurityCtx.GetUsername()
|
||||
l.isSysAdmin = l.SecurityCtx.IsSysAdmin()
|
||||
}
|
||||
|
||||
//Get returns the recent logs according to parameters
|
||||
func (l *LogAPI) Get() {
|
||||
var err error
|
||||
startTime := l.GetString("start_time")
|
||||
if len(startTime) != 0 {
|
||||
i, err := strconv.ParseInt(startTime, 10, 64)
|
||||
if err != nil {
|
||||
log.Errorf("Parse startTime to int error, err: %v", err)
|
||||
l.CustomAbort(http.StatusBadRequest, "startTime is not a valid integer")
|
||||
}
|
||||
startTime = time.Unix(i, 0).String()
|
||||
page, size := l.GetPaginationParams()
|
||||
query := &models.LogQueryParam{
|
||||
Pagination: &models.Pagination{
|
||||
Page: page,
|
||||
Size: size,
|
||||
},
|
||||
}
|
||||
|
||||
endTime := l.GetString("end_time")
|
||||
if len(endTime) != 0 {
|
||||
j, err := strconv.ParseInt(endTime, 10, 64)
|
||||
if !l.isSysAdmin {
|
||||
projects, err := l.ProjectMgr.GetByMember(l.username)
|
||||
if err != nil {
|
||||
log.Errorf("Parse endTime to int error, err: %v", err)
|
||||
l.CustomAbort(http.StatusBadRequest, "endTime is not a valid integer")
|
||||
l.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get projects of user %s: %v", l.username, err))
|
||||
return
|
||||
}
|
||||
endTime = time.Unix(j, 0).String()
|
||||
|
||||
if len(projects) == 0 {
|
||||
l.SetPaginationHeader(0, page, size)
|
||||
l.Data["json"] = nil
|
||||
l.ServeJSON()
|
||||
return
|
||||
}
|
||||
|
||||
ids := []int64{}
|
||||
for _, project := range projects {
|
||||
ids = append(ids, project.ProjectID)
|
||||
}
|
||||
query.ProjectIDs = ids
|
||||
}
|
||||
|
||||
var linesNum int
|
||||
lines := l.GetString("lines")
|
||||
if len(lines) != 0 {
|
||||
linesNum, err = strconv.Atoi(lines)
|
||||
if err != nil {
|
||||
log.Errorf("Get parameters error--lines, err: %v", err)
|
||||
l.CustomAbort(http.StatusBadRequest, "bad request of lines")
|
||||
}
|
||||
if linesNum <= 0 {
|
||||
log.Warning("lines must be a positive integer")
|
||||
l.CustomAbort(http.StatusBadRequest, "lines is 0 or negative")
|
||||
}
|
||||
} else if len(startTime) == 0 && len(endTime) == 0 {
|
||||
linesNum = 10
|
||||
}
|
||||
|
||||
var logList []models.AccessLog
|
||||
logList, err = dao.GetRecentLogs(l.SecurityCtx.GetUsername(), linesNum, startTime, endTime)
|
||||
total, err := dao.GetTotalOfAccessLogs(query)
|
||||
if err != nil {
|
||||
log.Errorf("Get recent logs error, err: %v", err)
|
||||
l.CustomAbort(http.StatusInternalServerError, "Internal error")
|
||||
l.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get total of access logs: %v", err))
|
||||
return
|
||||
}
|
||||
l.Data["json"] = logList
|
||||
|
||||
logs, err := dao.GetAccessLogs(query)
|
||||
if err != nil {
|
||||
l.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get access logs: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
l.SetPaginationHeader(total, page, size)
|
||||
|
||||
l.Data["json"] = logs
|
||||
l.ServeJSON()
|
||||
}
|
||||
|
@ -15,11 +15,11 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/vmware/harbor/tests/apitests/apilib"
|
||||
)
|
||||
|
||||
func TestLogGet(t *testing.T) {
|
||||
@ -29,12 +29,11 @@ func TestLogGet(t *testing.T) {
|
||||
apiTest := newHarborAPI()
|
||||
|
||||
//prepare for test
|
||||
|
||||
CommonAddUser()
|
||||
var project apilib.ProjectReq
|
||||
project.ProjectName = "my_project"
|
||||
project.Public = 1
|
||||
now := fmt.Sprintf("%v", time.Now().Unix())
|
||||
statusCode, result, err := apiTest.LogGet(*admin, "0", now, "1000")
|
||||
statusCode, result, err := apiTest.LogGet(*testUser)
|
||||
if err != nil {
|
||||
t.Error("Error while get log information", err.Error())
|
||||
t.Log(err)
|
||||
@ -46,7 +45,7 @@ func TestLogGet(t *testing.T) {
|
||||
fmt.Println("result", result)
|
||||
//add the project first.
|
||||
fmt.Println("add the project first.")
|
||||
reply, err := apiTest.ProjectsPost(*admin, project)
|
||||
reply, err := apiTest.ProjectsPost(*testUser, project)
|
||||
if err != nil {
|
||||
t.Error("Error while creat project", err.Error())
|
||||
t.Log(err)
|
||||
@ -54,8 +53,7 @@ func TestLogGet(t *testing.T) {
|
||||
assert.Equal(int(201), reply, "Case 2: Project creation status should be 201")
|
||||
}
|
||||
//case 1: right parameters, expect the right output
|
||||
now = fmt.Sprintf("%v", time.Now().Unix())
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "0", now, "1000")
|
||||
statusCode, result, err = apiTest.LogGet(*testUser)
|
||||
if err != nil {
|
||||
t.Error("Error while get log information", err.Error())
|
||||
t.Log(err)
|
||||
@ -71,64 +69,6 @@ func TestLogGet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
fmt.Println("log ", result)
|
||||
//case 2: wrong format of start_time parameter, expect the wrong output
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "ss", now, "3")
|
||||
if err != nil {
|
||||
t.Error("Error occured while get log information since the format of start_time parameter is not right.", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(int(400), statusCode, "Http status code should be 400")
|
||||
}
|
||||
|
||||
//case 3: wrong format of end_time parameter, expect the wrong output
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "0", "cc", "3")
|
||||
if err != nil {
|
||||
t.Error("Error occured while get log information since the format of end_time parameter is not right.", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(int(400), statusCode, "Http status code should be 400")
|
||||
}
|
||||
|
||||
//case 4: wrong format of lines parameter, expect the wrong output
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "0", now, "s")
|
||||
if err != nil {
|
||||
t.Error("Error occured while get log information since the format of lines parameter is not right.", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(int(400), statusCode, "Http status code should be 400")
|
||||
}
|
||||
|
||||
//case 5: wrong format of lines parameter, expect the wrong output
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "0", now, "-5")
|
||||
if err != nil {
|
||||
t.Error("Error occured while get log information since the format of lines parameter is not right.", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
assert.Equal(int(400), statusCode, "Http status code should be 400")
|
||||
}
|
||||
|
||||
//case 6: all parameters are null, expect the right output
|
||||
statusCode, result, err = apiTest.LogGet(*admin, "", "", "")
|
||||
if err != nil {
|
||||
t.Error("Error while get log information", err.Error())
|
||||
t.Log(err)
|
||||
} else {
|
||||
//default get 10 logs
|
||||
if logNum+1 >= 10 {
|
||||
logNum = 10
|
||||
} else {
|
||||
logNum++
|
||||
}
|
||||
assert.Equal(logNum, len(result), "lines of logs should be equal")
|
||||
num, index := getLog(result)
|
||||
if num != 1 {
|
||||
assert.Equal(1, num, "add my_project log number should be 1")
|
||||
} else {
|
||||
assert.Equal("my_project/", result[index].RepoName, "RepoName should be equal")
|
||||
assert.Equal("N/A", result[index].RepoTag, "RepoTag should be equal")
|
||||
assert.Equal("create", result[index].Operation, "Operation should be equal")
|
||||
}
|
||||
}
|
||||
|
||||
//get the project
|
||||
var projects []apilib.Project
|
||||
@ -144,7 +84,7 @@ func TestLogGet(t *testing.T) {
|
||||
|
||||
//delete the project
|
||||
projectID := strconv.Itoa(int(addProjectID))
|
||||
httpStatusCode, err = apiTest.ProjectsDelete(*admin, projectID)
|
||||
httpStatusCode, err = apiTest.ProjectsDelete(*testUser, projectID)
|
||||
if err != nil {
|
||||
t.Error("Error while delete project", err.Error())
|
||||
t.Log(err)
|
||||
@ -152,7 +92,7 @@ func TestLogGet(t *testing.T) {
|
||||
assert.Equal(int(200), httpStatusCode, "Case 1: Project creation status should be 200")
|
||||
//t.Log(result)
|
||||
}
|
||||
|
||||
CommonDelUser()
|
||||
fmt.Printf("\n")
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/harbor/src/common"
|
||||
"github.com/vmware/harbor/src/common/dao"
|
||||
@ -258,7 +259,7 @@ func projectContainsPolicy(id int64) (bool, error) {
|
||||
// TODO refacter pattern to:
|
||||
// /api/repositories?owner=xxx&name=xxx&public=true&member=xxx&role=1&page=1&size=3
|
||||
func (p *ProjectAPI) List() {
|
||||
query := &models.QueryParam{}
|
||||
query := &models.ProjectQueryParam{}
|
||||
|
||||
query.Name = p.GetString("project_name")
|
||||
public := p.GetString("is_public")
|
||||
@ -382,28 +383,49 @@ func (p *ProjectAPI) FilterAccessLog() {
|
||||
var query models.AccessLog
|
||||
p.DecodeJSONReq(&query)
|
||||
|
||||
query.ProjectID = p.project.ProjectID
|
||||
query.BeginTime = time.Unix(query.BeginTimestamp, 0)
|
||||
query.EndTime = time.Unix(query.EndTimestamp, 0)
|
||||
|
||||
page, pageSize := p.GetPaginationParams()
|
||||
|
||||
total, err := dao.GetTotalOfAccessLogs(query)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get total of access log: %v", err)
|
||||
p.CustomAbort(http.StatusInternalServerError, "")
|
||||
queryParm := &models.LogQueryParam{
|
||||
ProjectIDs: []int64{p.project.ProjectID},
|
||||
Username: query.Username,
|
||||
Repository: query.RepoName,
|
||||
Tag: query.RepoTag,
|
||||
}
|
||||
|
||||
logs, err := dao.GetAccessLogs(query, pageSize, pageSize*(page-1))
|
||||
if len(query.Keywords) > 0 {
|
||||
queryParm.Operations = strings.Split(query.Keywords, "/")
|
||||
}
|
||||
|
||||
if query.BeginTimestamp > 0 {
|
||||
beginTime := time.Unix(query.BeginTimestamp, 0)
|
||||
queryParm.BeginTime = &beginTime
|
||||
}
|
||||
|
||||
if query.EndTimestamp > 0 {
|
||||
endTime := time.Unix(query.EndTimestamp, 0)
|
||||
queryParm.EndTime = &endTime
|
||||
}
|
||||
|
||||
page, pageSize := p.GetPaginationParams()
|
||||
queryParm.Pagination = &models.Pagination{
|
||||
Page: page,
|
||||
Size: pageSize,
|
||||
}
|
||||
|
||||
total, err := dao.GetTotalOfAccessLogs(queryParm)
|
||||
if err != nil {
|
||||
log.Errorf("failed to get access log: %v", err)
|
||||
p.CustomAbort(http.StatusInternalServerError, "")
|
||||
p.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get total of access log: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
logs, err := dao.GetAccessLogs(queryParm)
|
||||
if err != nil {
|
||||
p.HandleInternalServerError(fmt.Sprintf(
|
||||
"failed to get access log: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
p.SetPaginationHeader(total, page, pageSize)
|
||||
|
||||
p.Data["json"] = logs
|
||||
|
||||
p.ServeJSON()
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,6 @@ func (s *StatisticAPI) Prepare() {
|
||||
// Get total projects and repos of the user
|
||||
func (s *StatisticAPI) Get() {
|
||||
statistic := map[string]int64{}
|
||||
|
||||
projects, err := s.ProjectMgr.GetPublic()
|
||||
if err != nil {
|
||||
s.HandleInternalServerError(fmt.Sprintf(
|
||||
@ -95,7 +94,7 @@ func (s *StatisticAPI) Get() {
|
||||
statistic[MRC] = n
|
||||
statistic[TRC] = n
|
||||
} else {
|
||||
projects, err := s.ProjectMgr.GetAll(&models.QueryParam{
|
||||
projects, err := s.ProjectMgr.GetAll(&models.ProjectQueryParam{
|
||||
Member: &models.Member{
|
||||
Name: s.username,
|
||||
},
|
||||
|
@ -107,7 +107,7 @@ func (p *ProjectManager) GetRoles(username string, projectIDOrName interface{})
|
||||
// GetPublic returns all public projects
|
||||
func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
|
||||
t := true
|
||||
return p.GetAll(&models.QueryParam{
|
||||
return p.GetAll(&models.ProjectQueryParam{
|
||||
Public: &t,
|
||||
})
|
||||
}
|
||||
@ -115,7 +115,7 @@ func (p *ProjectManager) GetPublic() ([]*models.Project, error) {
|
||||
// GetByMember returns all projects which the user is a member of
|
||||
func (p *ProjectManager) GetByMember(username string) (
|
||||
[]*models.Project, error) {
|
||||
return p.GetAll(&models.QueryParam{
|
||||
return p.GetAll(&models.ProjectQueryParam{
|
||||
Member: &models.Member{
|
||||
Name: username,
|
||||
},
|
||||
@ -190,13 +190,13 @@ func (p *ProjectManager) Update(projectIDOrName interface{},
|
||||
}
|
||||
|
||||
// GetAll returns a project list according to the query parameters
|
||||
func (p *ProjectManager) GetAll(query *models.QueryParam) (
|
||||
func (p *ProjectManager) GetAll(query *models.ProjectQueryParam) (
|
||||
[]*models.Project, error) {
|
||||
return dao.GetProjects(query)
|
||||
}
|
||||
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
func (p *ProjectManager) GetTotal(query *models.QueryParam) (
|
||||
func (p *ProjectManager) GetTotal(query *models.ProjectQueryParam) (
|
||||
int64, error) {
|
||||
return dao.GetTotalOfProjects(query)
|
||||
}
|
||||
|
@ -229,14 +229,14 @@ func TestGetTotal(t *testing.T) {
|
||||
defer pm.Delete(id)
|
||||
|
||||
// get by name
|
||||
total, err := pm.GetTotal(&models.QueryParam{
|
||||
total, err := pm.GetTotal(&models.ProjectQueryParam{
|
||||
Name: "get_total_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), total)
|
||||
|
||||
// get by owner
|
||||
total, err = pm.GetTotal(&models.QueryParam{
|
||||
total, err = pm.GetTotal(&models.ProjectQueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
@ -244,7 +244,7 @@ func TestGetTotal(t *testing.T) {
|
||||
|
||||
// get by public
|
||||
value := true
|
||||
total, err = pm.GetTotal(&models.QueryParam{
|
||||
total, err = pm.GetTotal(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
@ -263,14 +263,14 @@ func TestGetAll(t *testing.T) {
|
||||
defer pm.Delete(id)
|
||||
|
||||
// get by name
|
||||
projects, err := pm.GetAll(&models.QueryParam{
|
||||
projects, err := pm.GetAll(&models.ProjectQueryParam{
|
||||
Name: "get_all_test",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, id, projects[0].ProjectID)
|
||||
|
||||
// get by owner
|
||||
projects, err = pm.GetAll(&models.QueryParam{
|
||||
projects, err = pm.GetAll(&models.ProjectQueryParam{
|
||||
Owner: "admin",
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
@ -285,7 +285,7 @@ func TestGetAll(t *testing.T) {
|
||||
|
||||
// get by public
|
||||
value := true
|
||||
projects, err = pm.GetAll(&models.QueryParam{
|
||||
projects, err = pm.GetAll(&models.ProjectQueryParam{
|
||||
Public: &value,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
|
@ -33,9 +33,9 @@ type ProjectManager interface {
|
||||
Delete(projectIDOrName interface{}) error
|
||||
Update(projectIDOrName interface{}, project *models.Project) error
|
||||
// GetAll returns a project list according to the query parameters
|
||||
GetAll(query *models.QueryParam) ([]*models.Project, error)
|
||||
GetAll(query *models.ProjectQueryParam) ([]*models.Project, error)
|
||||
// GetTotal returns the total count according to the query parameters
|
||||
GetTotal(query *models.QueryParam) (int64, error)
|
||||
GetTotal(query *models.ProjectQueryParam) (int64, error)
|
||||
// GetHasReadPerm returns a project list which the user has read
|
||||
// permission of. The list should contains all public projects and
|
||||
// projects which the user is a member of if the username is not nil
|
||||
|
@ -67,7 +67,7 @@ export class AccessLogDefaultService extends AccessLogService {
|
||||
url = '/api/logs';
|
||||
}
|
||||
|
||||
return this.http.get(url+`?lines=${lines}`, HTTP_JSON_OPTIONS).toPromise()
|
||||
return this.http.get(url+`?page_size=${lines}`, HTTP_JSON_OPTIONS).toPromise()
|
||||
.then(response => response.json() as AccessLog[])
|
||||
.catch(error => Promise.reject(error));
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ export class AuditLogService {
|
||||
}
|
||||
|
||||
getRecentLogs(lines: number): Observable<AuditLog[]> {
|
||||
return this.http.get(logEndpoint + "?lines=" + lines, this.httpOptions)
|
||||
return this.http.get(logEndpoint + "?page_size=" + lines, this.httpOptions)
|
||||
.map(response => response.json() as AuditLog[])
|
||||
.catch(error => Observable.throw(error));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user