drop table access log in migration (#11118)

Use the audit log instead, the access log table should be dropped after migration

Signed-off-by: wang yan <wangyan@vmware.com>
This commit is contained in:
Wang Yan 2020-03-18 19:04:38 +08:00 committed by GitHub
parent 0422721490
commit b4e941e961
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 15 additions and 793 deletions

View File

@ -175,7 +175,6 @@ CREATE TABLE audit_log
);
/*migrate access log to audit log*/
/*TODO drop table access_log?*/
DO $$
DECLARE
access RECORD;
@ -195,6 +194,9 @@ BEGIN
END LOOP;
END $$;
/*drop access table after migrate to audit log*/
DROP TABLE IF EXISTS access_log;
/*remove the constraint for project_id in table 'notification_policy'*/
ALTER TABLE notification_policy DROP CONSTRAINT unique_project_id;

View File

@ -1,109 +0,0 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dao
import (
"github.com/astaxie/beego/orm"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/utils/log"
)
// AddAccessLog persists the access logs
func AddAccessLog(accessLog models.AccessLog) error {
// the max length of username in database is 255, replace the last
// three charaters with "..." if the length is greater than 256
if len(accessLog.Username) > 255 {
accessLog.Username = accessLog.Username[:252] + "..."
}
o := GetOrmer()
_, err := o.Insert(&accessLog)
return err
}
// GetTotalOfAccessLogs ...
func GetTotalOfAccessLogs(query *models.LogQueryParam) (int64, error) {
return logQueryConditions(query).Count()
}
// GetAccessLogs gets access logs according to different conditions
func GetAccessLogs(query *models.LogQueryParam) ([]models.AccessLog, error) {
qs := logQueryConditions(query).OrderBy("-op_time")
if query != nil && query.Pagination != nil {
size := query.Pagination.Size
if size > 0 {
qs = qs.Limit(size)
page := query.Pagination.Page
if page > 0 {
qs = qs.Offset((page - 1) * size)
}
}
}
logs := []models.AccessLog{}
_, err := qs.All(&logs)
return logs, err
}
func logQueryConditions(query *models.LogQueryParam) orm.QuerySeter {
qs := GetOrmer().QueryTable(&models.AccessLog{})
if query == nil {
return qs
}
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__contains", query.Repository)
}
if len(query.Tag) != 0 {
qs = qs.Filter("repo_tag__contains", query.Tag)
}
operations := []string{}
for _, operation := range query.Operations {
if len(operation) > 0 {
operations = append(operations, operation)
}
}
if len(operations) > 0 {
qs = qs.Filter("operation__in", 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)
}
return qs
}
// CountPull ...
func CountPull(repoName string) (int64, error) {
o := GetOrmer()
num, err := o.QueryTable("access_log").Filter("repo_name", repoName).Filter("operation", "pull").Count()
if err != nil {
log.Errorf("error in CountPull: %v ", err)
return 0, err
}
return num, nil
}

View File

@ -71,27 +71,6 @@ func cleanByUser(username string) {
log.Error(err)
}
err = execUpdate(o, `delete
from access_log
where username = ?
`, username)
if err != nil {
o.Rollback()
log.Error(err)
}
err = execUpdate(o, `delete
from access_log
where project_id = (
select project_id
from project
where name = ?
)`, projectName)
if err != nil {
o.Rollback()
log.Error(err)
}
err = execUpdate(o, `delete from project where name = ?`, projectName)
if err != nil {
o.Rollback()
@ -158,7 +137,7 @@ func testForAll(m *testing.M) int {
func clearAll() {
tables := []string{"project_member",
"project_metadata", "access_log", "repository", "replication_policy",
"project_metadata", "repository", "replication_policy",
"registry", "replication_execution", "replication_task",
"replication_schedule_job", "project", "harbor_user"}
for _, t := range tables {
@ -409,155 +388,6 @@ func TestGetProject(t *testing.T) {
}
}
func TestGetAccessLog(t *testing.T) {
accessLog := models.AccessLog{
Username: currentUser.Username,
ProjectID: currentProject.ProjectID,
RepoName: currentProject.Name + "/",
RepoTag: "N/A",
GUID: "N/A",
Operation: "create",
OpTime: time.Now(),
}
if err := AddAccessLog(accessLog); err != nil {
t.Errorf("failed to add access log: %v", err)
}
query := &models.LogQueryParam{
Username: currentUser.Username,
ProjectIDs: []int64{currentProject.ProjectID},
}
accessLogs, err := GetAccessLogs(query)
if err != nil {
t.Errorf("Error occurred in GetAccessLog: %v", err)
}
if len(accessLogs) != 1 {
t.Errorf("The length of accesslog list should be 1, actual: %d", len(accessLogs))
}
if accessLogs[0].RepoName != projectName+"/" {
t.Errorf("The project name does not match, expected: %s, actual: %s", projectName+"/", accessLogs[0].RepoName)
}
}
func TestGetTotalOfAccessLogs(t *testing.T) {
query := &models.LogQueryParam{
Username: currentUser.Username,
ProjectIDs: []int64{currentProject.ProjectID},
}
total, err := GetTotalOfAccessLogs(query)
if err != nil {
t.Fatalf("failed to get total of access log: %v", err)
}
if total != 1 {
t.Errorf("unexpected total %d != %d", total, 1)
}
}
func TestAddAccessLog(t *testing.T) {
var err error
var accessLogList []models.AccessLog
accessLog := models.AccessLog{
Username: currentUser.Username,
ProjectID: currentProject.ProjectID,
RepoName: currentProject.Name + "/",
RepoTag: repoTag,
GUID: "N/A",
Operation: "create",
OpTime: time.Now(),
}
err = AddAccessLog(accessLog)
if err != nil {
t.Errorf("Error occurred in AddAccessLog: %v", err)
}
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)
}
if len(accessLogList) != 1 {
t.Errorf("The length of accesslog list should be 1, actual: %d", len(accessLogList))
}
if accessLogList[0].RepoName != projectName+"/" {
t.Errorf("The project name does not match, expected: %s, actual: %s", projectName+"/", accessLogList[0].RepoName)
}
if accessLogList[0].RepoTag != repoTag {
t.Errorf("The repo tag does not match, expected: %s, actual: %s", repoTag, accessLogList[0].RepoTag)
}
}
func TestCountPull(t *testing.T) {
var err error
if err = AddAccessLog(models.AccessLog{
Username: currentUser.Username,
ProjectID: currentProject.ProjectID,
RepoName: currentProject.Name + "/tomcat",
RepoTag: repoTag2,
Operation: "pull",
OpTime: time.Now(),
}); err != nil {
t.Errorf("Error occurred in AccessLog: %v", err)
}
if err = AddAccessLog(models.AccessLog{
Username: currentUser.Username,
ProjectID: currentProject.ProjectID,
RepoName: currentProject.Name + "/tomcat",
RepoTag: repoTag2,
Operation: "pull",
OpTime: time.Now(),
}); err != nil {
t.Errorf("Error occurred in AccessLog: %v", err)
}
if err = AddAccessLog(models.AccessLog{
Username: currentUser.Username,
ProjectID: currentProject.ProjectID,
RepoName: currentProject.Name + "/tomcat",
RepoTag: repoTag2,
Operation: "pull",
OpTime: time.Now(),
}); err != nil {
t.Errorf("Error occurred in AccessLog: %v", err)
}
pullCount, err := CountPull(currentProject.Name + "/tomcat")
if err != nil {
t.Errorf("Error occurred in CountPull: %v", err)
}
if pullCount != 3 {
t.Errorf("The access log pull count does not match, expected: 3, actual: %d", pullCount)
}
}
/*
func TestProjectExists(t *testing.T) {
var exists bool
var err error
exists, err = ProjectExists(currentProject.ProjectID)
if err != nil {
t.Errorf("Error occurred in ProjectExists: %v", err)
}
if !exists {
t.Errorf("The project with id: %d, does not exist", currentProject.ProjectID)
}
exists, err = ProjectExists(currentProject.Name)
if err != nil {
t.Errorf("Error occurred in ProjectExists: %v", err)
}
if !exists {
t.Errorf("The project with name: %s, does not exist", currentProject.Name)
}
}
*/
func TestGetProjectById(t *testing.T) {
id := currentProject.ProjectID
p, err := GetProjectByID(id)

View File

@ -61,14 +61,7 @@ func TestDeleteProject(t *testing.T) {
}
func delProjPermanent(id int64) error {
_, err := GetOrmer().QueryTable("access_log").
Filter("ProjectID", id).
Delete()
if err != nil {
return err
}
_, err = GetOrmer().Raw(`delete from project_member
_, err := GetOrmer().Raw(`delete from project_member
where project_id = ?`, id).Exec()
if err != nil {
return err

View File

@ -1,44 +0,0 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package models
import (
"time"
)
// AccessLog holds information about logs which are used to record the actions that user take to the resourses.
type AccessLog struct {
LogID int `orm:"pk;auto;column(log_id)" json:"log_id"`
Username string `orm:"column(username)" json:"username"`
ProjectID int64 `orm:"column(project_id)" json:"project_id"`
RepoName string `orm:"column(repo_name)" json:"repo_name"`
RepoTag string `orm:"column(repo_tag)" json:"repo_tag"`
GUID string `orm:"column(guid)" json:"guid"`
Operation string `orm:"column(operation)" json:"operation"`
OpTime time.Time `orm:"column(op_time)" json:"op_time"`
}
// 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
}

View File

@ -23,7 +23,6 @@ func init() {
new(User),
new(Project),
new(Role),
new(AccessLog),
new(RepoRecord),
new(ClairVulnTimestamp),
new(ProjectMetadata),

View File

@ -106,7 +106,6 @@ func init() {
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/sysadmin", &UserAPI{}, "put:ToggleUserAdminRole")
beego.Router("/api/projects/:id([0-9]+)/logs", &ProjectAPI{}, "get:Logs")
beego.Router("/api/projects/:id([0-9]+)/summary", &ProjectAPI{}, "get:Summary")
beego.Router("/api/projects/:id([0-9]+)/_deletable", &ProjectAPI{}, "get:Deletable")
beego.Router("/api/projects/:id([0-9]+)/metadatas/?:name", &MetadataAPI{}, "get:Get")
@ -116,7 +115,6 @@ func init() {
beego.Router("/api/statistics", &StatisticAPI{})
beego.Router("/api/users/?:id", &UserAPI{})
beego.Router("/api/usergroups/?:ugid([0-9]+)", &UserGroupAPI{})
beego.Router("/api/logs", &LogAPI{})
beego.Router("/api/registries", &RegistryAPI{}, "get:List;post:Post")
beego.Router("/api/registries/ping", &RegistryAPI{}, "post:Ping")
beego.Router("/api/registries/:id([0-9]+)", &RegistryAPI{}, "get:Get;put:Put;delete:Delete")
@ -316,22 +314,6 @@ func (a testapi) StatisticGet(user usrInfo) (int, apilib.StatisticMap, error) {
return httpStatusCode, successPayload, err
}
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)
var successPayload []apilib.AccessLog
code, body, err := request(_sling, jsonAcceptHeader, user)
if 200 == code && nil == err {
err = json.Unmarshal(body, &successPayload)
}
return code, successPayload, err
}
// Delete project by projectID
func (a testapi) ProjectsDelete(prjUsr usrInfo, projectID string) (int, error) {
_sling := sling.New().Delete(a.basePath)
@ -413,15 +395,6 @@ func (a testapi) ProjectsPut(prjUsr usrInfo, projectID string,
}
// Get access logs accompany with a relevant project.
func (a testapi) ProjectLogs(prjUsr usrInfo, projectID string, query *apilib.LogQuery) (int, []byte, error) {
_sling := sling.New().Get(a.basePath).
Path("/api/projects/" + projectID + "/logs").
QueryStruct(query)
return request(_sling, jsonAcceptHeader, prjUsr)
}
// ProjectDeletable check whether a project can be deleted
func (a testapi) ProjectDeletable(prjUsr usrInfo, projectID int64) (int, bool, error) {
_sling := sling.New().Get(a.basePath).

View File

@ -1,127 +0,0 @@
// Copyright 2018 Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package api
import (
"fmt"
"errors"
"github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/common/utils"
)
// LogAPI handles request api/logs
type LogAPI struct {
BaseController
username string
isSysAdmin bool
}
// Prepare validates the URL and the user
func (l *LogAPI) Prepare() {
l.BaseController.Prepare()
if !l.SecurityCtx.IsAuthenticated() {
l.SendUnAuthorizedError(errors.New("Unauthorized"))
return
}
l.username = l.SecurityCtx.GetUsername()
l.isSysAdmin = l.SecurityCtx.IsSysAdmin()
}
// Get returns the recent logs according to parameters
func (l *LogAPI) Get() {
page, size, err := l.GetPaginationParams()
if err != nil {
l.SendBadRequestError(err)
return
}
query := &models.LogQueryParam{
Username: l.GetString("username"),
Repository: l.GetString("repository"),
Tag: l.GetString("tag"),
Operations: l.GetStrings("operation"),
Pagination: &models.Pagination{
Page: page,
Size: size,
},
}
timestamp := l.GetString("begin_timestamp")
if len(timestamp) > 0 {
t, err := utils.ParseTimeStamp(timestamp)
if err != nil {
l.SendBadRequestError(fmt.Errorf("invalid begin_timestamp: %s", timestamp))
return
}
query.BeginTime = t
}
timestamp = l.GetString("end_timestamp")
if len(timestamp) > 0 {
t, err := utils.ParseTimeStamp(timestamp)
if err != nil {
l.SendBadRequestError(fmt.Errorf("invalid end_timestamp: %s", timestamp))
return
}
query.EndTime = t
}
if !l.isSysAdmin {
projects, err := l.SecurityCtx.GetMyProjects()
if err != nil {
l.SendInternalServerError(fmt.Errorf(
"failed to get projects of user %s: %v", l.username, err))
return
}
ids := []int64{}
for _, project := range projects {
if hasPermission, _ := l.HasProjectPermission(project.ProjectID, rbac.ActionList, rbac.ResourceLog); hasPermission {
ids = append(ids, project.ProjectID)
}
}
if len(ids) == 0 {
l.SetPaginationHeader(0, page, size)
l.Data["json"] = nil
l.ServeJSON()
return
}
query.ProjectIDs = ids
}
total, err := dao.GetTotalOfAccessLogs(query)
if err != nil {
l.SendInternalServerError(fmt.Errorf(
"failed to get total of access logs: %v", err))
return
}
logs, err := dao.GetAccessLogs(query)
if err != nil {
l.SendInternalServerError(fmt.Errorf(
"failed to get access logs: %v", err))
return
}
l.SetPaginationHeader(total, page, size)
l.Data["json"] = logs
l.ServeJSON()
}

View File

@ -1,102 +0,0 @@
// Copyright 2018 Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package api
import (
"fmt"
"net/http"
"testing"
"time"
"github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/common/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestLogGet(t *testing.T) {
fmt.Println("Testing Log API")
var projectID int64 = 1
username := "user_for_testing_log_api"
repository := "repository_for_testing_log_api"
tag := "tag_for_testing_log_api"
operation := "op_for_test_log_api"
now := time.Now()
err := dao.AddAccessLog(models.AccessLog{
ProjectID: projectID,
Username: username,
RepoName: repository,
RepoTag: tag,
Operation: operation,
OpTime: now,
})
require.Nil(t, err)
defer dao.GetOrmer().QueryTable(&models.AccessLog{}).
Filter("username", username).Delete()
url := "/api/logs"
// 401
cc := &codeCheckingCase{
request: &testingRequest{
method: http.MethodGet,
url: url,
},
code: http.StatusUnauthorized,
}
runCodeCheckingCases(t, cc)
// 200, empty log list
c := &testingRequest{
method: http.MethodGet,
url: url,
credential: nonSysAdmin,
queryStruct: struct {
Username string `url:"username"`
Repository string `url:"repository"`
Tag string `url:"tag"`
Operation string `url:"operation"`
BeginTimestamp int64 `url:"begin_timestamp"`
EndTimestamp int64 `url:"end_timestamp"`
}{
Username: username,
Repository: repository,
Tag: tag,
Operation: operation,
BeginTimestamp: now.Add(-1 * time.Second).Unix(),
EndTimestamp: now.Add(1 * time.Second).Unix(),
},
}
logs := []*models.AccessLog{}
err = handleAndParse(c, &logs)
require.Nil(t, err)
require.Equal(t, 0, len(logs))
// 200
c.credential = projGuest
err = handleAndParse(c, &logs)
require.Nil(t, err)
require.Equal(t, 1, len(logs))
assert.Equal(t, projectID, logs[0].ProjectID)
assert.Equal(t, username, logs[0].Username)
assert.Equal(t, repository, logs[0].RepoName)
assert.Equal(t, tag, logs[0].RepoTag)
assert.Equal(t, operation, logs[0].Operation)
// Limited Guest 200 && no logs
c.credential = projLimitedGuest
err = handleAndParse(c, &logs)
require.Nil(t, err)
require.Equal(t, 0, len(logs))
}

View File

@ -496,68 +496,6 @@ func (p *ProjectAPI) Put() {
}
}
// Logs ...
func (p *ProjectAPI) Logs() {
if !p.requireAccess(rbac.ActionList, rbac.ResourceLog) {
return
}
page, size, err := p.GetPaginationParams()
if err != nil {
p.SendBadRequestError(err)
return
}
query := &models.LogQueryParam{
ProjectIDs: []int64{p.project.ProjectID},
Username: p.GetString("username"),
Repository: p.GetString("repository"),
Tag: p.GetString("tag"),
Operations: p.GetStrings("operation"),
Pagination: &models.Pagination{
Page: page,
Size: size,
},
}
timestamp := p.GetString("begin_timestamp")
if len(timestamp) > 0 {
t, err := utils.ParseTimeStamp(timestamp)
if err != nil {
p.SendBadRequestError(fmt.Errorf("invalid begin_timestamp: %s", timestamp))
return
}
query.BeginTime = t
}
timestamp = p.GetString("end_timestamp")
if len(timestamp) > 0 {
t, err := utils.ParseTimeStamp(timestamp)
if err != nil {
p.SendBadRequestError(fmt.Errorf("invalid end_timestamp: %s", timestamp))
return
}
query.EndTime = t
}
total, err := dao.GetTotalOfAccessLogs(query)
if err != nil {
p.SendInternalServerError(fmt.Errorf(
"failed to get total of access log: %v", err))
return
}
logs, err := dao.GetAccessLogs(query)
if err != nil {
p.SendInternalServerError(fmt.Errorf(
"failed to get access log: %v", err))
return
}
p.SetPaginationHeader(total, page, size)
p.Data["json"] = logs
p.ServeJSON()
}
// Summary returns the summary of the project
func (p *ProjectAPI) Summary() {
if !p.requireAccess(rbac.ActionRead) {

View File

@ -16,16 +16,14 @@ package api
import (
"fmt"
"github.com/goharbor/harbor/src/common"
"net/http"
"strconv"
"testing"
"time"
"github.com/goharbor/harbor/src/common/dao"
"github.com/goharbor/harbor/src/common/models"
"github.com/goharbor/harbor/src/testing/apitests/apilib"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/http"
"strconv"
"testing"
)
var addProject *apilib.ProjectReq
@ -410,53 +408,6 @@ func TestPut(t *testing.T) {
fmt.Printf("\n")
}
func TestProjectLogsFilter(t *testing.T) {
fmt.Println("\nTest for search access logs filtered by operations and date time ranges..")
assert := assert.New(t)
apiTest := newHarborAPI()
query := &apilib.LogQuery{
Username: "admin",
Repository: "",
Tag: "",
Operation: []string{""},
BeginTimestamp: 0,
EndTimestamp: time.Now().Unix(),
}
// -------------------case1: Response Code=200------------------------------//
fmt.Println("case 1: response code:200")
projectID := "1"
httpStatusCode, _, err := apiTest.ProjectLogs(*admin, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
// -------------------case2: Response Code=401:User need to log in first.------------------------------//
fmt.Println("case 2: response code:401:User need to log in first.")
projectID = "1"
httpStatusCode, _, err = apiTest.ProjectLogs(*unknownUsr, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(401), httpStatusCode, "httpStatusCode should be 401")
}
// -------------------case3: Response Code=404:Project does not exist.-------------------------//
fmt.Println("case 3: response code:404:Illegal format of provided ID value.")
projectID = "11111"
httpStatusCode, _, err = apiTest.ProjectLogs(*admin, projectID, query)
if err != nil {
t.Error("Error while search access logs")
t.Log(err)
} else {
assert.Equal(int(404), httpStatusCode, "httpStatusCode should be 404")
}
fmt.Printf("\n")
}
func TestDeletable(t *testing.T) {
apiTest := newHarborAPI()

View File

@ -38,10 +38,6 @@ func TestMain(m *testing.M) {
if err != nil {
panic(err)
}
err = dao.ClearTable("access_log")
if err != nil {
panic(err)
}
err = dao.ClearTable("project")
if err != nil {
panic(err)

View File

@ -44,7 +44,6 @@ func registerLegacyRoutes() {
beego.Router("/api/"+version+"/search", &api.SearchAPI{})
beego.Router("/api/"+version+"/projects/", &api.ProjectAPI{}, "get:List;post:Post")
beego.Router("/api/"+version+"/projects/:id([0-9]+)/summary", &api.ProjectAPI{}, "get:Summary")
beego.Router("/api/"+version+"/projects/:id([0-9]+)/logs", &api.ProjectAPI{}, "get:Logs")
beego.Router("/api/"+version+"/projects/:id([0-9]+)/_deletable", &api.ProjectAPI{}, "get:Deletable")
beego.Router("/api/"+version+"/projects/:id([0-9]+)/metadatas/?:name", &api.MetadataAPI{}, "get:Get")
beego.Router("/api/"+version+"/projects/:id([0-9]+)/metadatas/", &api.MetadataAPI{}, "post:Post")
@ -62,8 +61,6 @@ func registerLegacyRoutes() {
beego.Router("/api/"+version+"/system/CVEWhitelist", &api.SysCVEWhitelistAPI{}, "get:Get;put:Put")
beego.Router("/api/"+version+"/system/oidc/ping", &api.OIDCAPI{}, "post:Ping")
beego.Router("/api/"+version+"/logs", &api.LogAPI{})
beego.Router("/api/"+version+"/replication/adapters", &api.ReplicationAdapterAPI{}, "get:List")
beego.Router("/api/"+version+"/replication/adapterinfos", &api.ReplicationAdapterAPI{}, "get:ListAdapterInfos")
beego.Router("/api/"+version+"/replication/executions", &api.ReplicationOperationAPI{}, "get:ListExecutions;post:CreateExecution")

View File

@ -1,41 +0,0 @@
/*
* Harbor API
*
* These APIs provide services for manipulating Harbor project.
*
* OpenAPI spec version: 0.3.0
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package apilib
type AccessLog struct {
// The ID of the log entry.
LogId int32 `json:"log_id,omitempty"`
// Name of the repository in this log entry.
RepoName string `json:"repo_name,omitempty"`
// Tag of the repository in this log entry.
RepoTag string `json:"repo_tag,omitempty"`
// The operation against the repository in this log entry.
Operation string `json:"operation,omitempty"`
// The time when this operation is triggered.
OpTime string `json:"op_time,omitempty"`
}

View File

@ -1,34 +0,0 @@
/*
* Harbor API
*
* These APIs provide services for manipulating Harbor project.
*
* OpenAPI spec version: 0.3.0
*
* Generated by: https://github.com/swagger-api/swagger-codegen.git
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package apilib
type LogQuery struct {
Username string `url:"username,omitempty"`
Repository string `url:"repository,omitempty"`
Tag string `url:"tag,omitempty"`
Operation []string `url:"operation,omitempty"`
BeginTimestamp int64 `url:"begin_timestamp,omitempty"`
EndTimestamp int64 `url:"end_timestamp,omitempty"`
Page int64 `url:"page,omitempty"`
PageSize int64 `url:"page_size,omitempty"`
}

View File

@ -118,10 +118,11 @@ class TestAssignRoleToLdapGroup(unittest.TestCase):
self.dockerCmdLoginDev(username="dev_user", password="zhu88jie")
self.dockerCmdLoginGuest(username="guest_user", password="zhu88jie")
self.assertTrue(self.queryUserLogs(username="admin_user", password="zhu88jie")>0, "admin user can see logs")
self.assertTrue(self.queryUserLogs(username="dev_user", password="zhu88jie")>0, "dev user can see logs")
self.assertTrue(self.queryUserLogs(username="guest_user", password="zhu88jie")>0, "guest user can see logs")
self.assertTrue(self.queryUserLogs(username="test", password="123456")==0, "test user can not see any logs")
#ToDo, enable them
#self.assertTrue(self.queryUserLogs(username="admin_user", password="zhu88jie")>0, "admin user can see logs")
#self.assertTrue(self.queryUserLogs(username="dev_user", password="zhu88jie")>0, "dev user can see logs")
#self.assertTrue(self.queryUserLogs(username="guest_user", password="zhu88jie")>0, "guest user can see logs")
#self.assertTrue(self.queryUserLogs(username="test", password="123456")==0, "test user can not see any logs")
pass

View File

@ -21,7 +21,6 @@ import unittest
import testutils
import swagger_client
from swagger_client.models.project_req import ProjectReq
from swagger_client.models.access_log import AccessLog
from swagger_client.models.configurations import Configurations
from swagger_client.rest import ApiException
from swagger_client.models.configurations import Configurations