From 3be9cca0f557c57514f1664285c03de606020be8 Mon Sep 17 00:00:00 2001 From: Wenkai Yin Date: Wed, 3 May 2017 10:43:57 +0800 Subject: [PATCH] delete column user_id from table accesslog --- make/common/db/registry.sql | 3 +- make/common/db/registry_sqlite.sql | 3 +- src/common/dao/accesslog.go | 67 ++++++---------------- src/common/dao/dao_test.go | 90 +++++++++++++++--------------- src/common/dao/project.go | 8 +-- src/common/models/accesslog.go | 13 ++--- src/ui/api/log.go | 12 +++- src/ui/api/project.go | 34 ++++++++++- src/ui/api/repository.go | 14 ++++- src/ui/service/notification.go | 15 ++++- tools/migration/changelog.md | 3 + 11 files changed, 144 insertions(+), 118 deletions(-) diff --git a/make/common/db/registry.sql b/make/common/db/registry.sql index cb4e91cc8..0f7038c0e 100644 --- a/make/common/db/registry.sql +++ b/make/common/db/registry.sql @@ -99,7 +99,7 @@ insert into project_member (project_id, user_id, role, creation_time, update_tim create table access_log ( log_id int NOT NULL AUTO_INCREMENT, - user_id int NOT NULL, + username varchar (32) NOT NULL, project_id int NOT NULL, repo_name varchar (256), repo_tag varchar (128), @@ -108,7 +108,6 @@ create table access_log ( op_time timestamp, primary key (log_id), INDEX pid_optime (project_id, op_time), - FOREIGN KEY (user_id) REFERENCES user(user_id), FOREIGN KEY (project_id) REFERENCES project (project_id) ); diff --git a/make/common/db/registry_sqlite.sql b/make/common/db/registry_sqlite.sql index 497565ee6..280745567 100644 --- a/make/common/db/registry_sqlite.sql +++ b/make/common/db/registry_sqlite.sql @@ -96,14 +96,13 @@ insert into project_member (project_id, user_id, role, creation_time, update_tim create table access_log ( log_id INTEGER PRIMARY KEY, - user_id int NOT NULL, + username varchar (32) NOT NULL, project_id int NOT NULL, repo_name varchar (256), repo_tag varchar (128), GUID varchar(64), operation varchar(20) NOT NULL, op_time timestamp, - FOREIGN KEY (user_id) REFERENCES user(user_id), FOREIGN KEY (project_id) REFERENCES project (project_id) ); diff --git a/src/common/dao/accesslog.go b/src/common/dao/accesslog.go index f0e7b1a3c..9470213bd 100644 --- a/src/common/dao/accesslog.go +++ b/src/common/dao/accesslog.go @@ -16,7 +16,6 @@ package dao import ( "strings" - "time" "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils/log" @@ -25,17 +24,7 @@ import ( // AddAccessLog persists the access logs func AddAccessLog(accessLog models.AccessLog) error { o := GetOrmer() - p, err := o.Raw(`insert into access_log - (user_id, project_id, repo_name, repo_tag, guid, operation, op_time) - values (?, ?, ?, ?, ?, ?, ?)`).Prepare() - if err != nil { - return err - } - defer p.Close() - - _, err = p.Exec(accessLog.UserID, accessLog.ProjectID, accessLog.RepoName, accessLog.RepoTag, - accessLog.GUID, accessLog.Operation, time.Now()) - + _, err := o.Insert(&accessLog) return err } @@ -49,14 +38,6 @@ func GetTotalOfAccessLogs(query models.AccessLog) (int64, error) { where al.project_id = ?` queryParam = append(queryParam, query.ProjectID) - if query.Username != "" { - sql = `select count(*) from access_log al - left join user u - on al.user_id = u.user_id - where al.project_id = ? and u.username like ? ` - queryParam = append(queryParam, "%"+escape(query.Username)+"%") - } - sql += genFilterClauses(query, &queryParam) var total int64 @@ -71,19 +52,12 @@ func GetAccessLogs(query models.AccessLog, limit, offset int64) ([]models.Access o := GetOrmer() queryParam := []interface{}{} - sql := `select al.log_id, u.username, al.repo_name, + sql := `select al.log_id, al.username, al.repo_name, al.repo_tag, al.operation, al.op_time from access_log al - left join user u - on al.user_id = u.user_id where al.project_id = ? ` queryParam = append(queryParam, query.ProjectID) - if query.Username != "" { - sql += ` and u.username like ? ` - queryParam = append(queryParam, "%"+escape(query.Username)+"%") - } - sql += genFilterClauses(query, &queryParam) sql += ` order by al.op_time desc ` @@ -102,6 +76,11 @@ func GetAccessLogs(query models.AccessLog, limit, offset int64) ([]models.Access 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) @@ -141,42 +120,28 @@ func genFilterClauses(query models.AccessLog, queryParam *[]interface{}) string return sql } -// AccessLog ... -func AccessLog(username, projectName, repoName, repoTag, action string) error { - o := GetOrmer() - sql := "insert into access_log (user_id, project_id, repo_name, repo_tag, operation, op_time) " + - "select (select user_id as user_id from user where username=?), " + - "(select project_id as project_id from project where name=?), ?, ?, ?, ? " - _, err := o.Raw(sql, username, projectName, repoName, repoTag, action, time.Now()).Exec() - - if err != nil { - log.Errorf("error in AccessLog: %v ", err) - } - return err -} - //GetRecentLogs returns recent logs according to parameters -func GetRecentLogs(userID, linesNum int, startTime, endTime string) ([]models.AccessLog, error) { +func GetRecentLogs(username string, linesNum int, startTime, endTime string) ([]models.AccessLog, error) { logs := []models.AccessLog{} - isAdmin, err := IsAdminRole(userID) + isAdmin, err := IsAdminRole(username) if err != nil { return logs, err } queryParam := []interface{}{} - sql := `select log_id, access_log.user_id, project_id, repo_name, repo_tag, GUID, operation, op_time, username - from access_log - join user - on access_log.user_id=user.user_id ` + 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 - where user_id = ?) ` - queryParam = append(queryParam, userID) + from project_member pm + join user u + on pm.user_id = u.user_id + where u.username = ?) ` + queryParam = append(queryParam, username) hasWhere = true } diff --git a/src/common/dao/dao_test.go b/src/common/dao/dao_test.go index a8cd269d2..de270dc85 100644 --- a/src/common/dao/dao_test.go +++ b/src/common/dao/dao_test.go @@ -73,11 +73,8 @@ func clearUp(username string) { err = execUpdate(o, `delete from access_log - where user_id = ( - select user_id - from user - where username = ? - )`, username) + where username = ? + `, username) if err != nil { o.Rollback() log.Error(err) @@ -559,8 +556,22 @@ 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) + } + queryAccessLog := models.AccessLog{ - UserID: currentUser.UserID, + Username: currentUser.Username, ProjectID: currentProject.ProjectID, } accessLogs, err := GetAccessLogs(queryAccessLog, 1000, 0) @@ -577,7 +588,7 @@ func TestGetAccessLog(t *testing.T) { func TestGetTotalOfAccessLogs(t *testing.T) { queryAccessLog := models.AccessLog{ - UserID: currentUser.UserID, + Username: currentUser.Username, ProjectID: currentProject.ProjectID, } total, err := GetTotalOfAccessLogs(queryAccessLog) @@ -594,7 +605,7 @@ func TestAddAccessLog(t *testing.T) { var err error var accessLogList []models.AccessLog accessLog := models.AccessLog{ - UserID: currentUser.UserID, + Username: currentUser.Username, ProjectID: currentProject.ProjectID, RepoName: currentProject.Name + "/", RepoTag: repoTag, @@ -621,47 +632,38 @@ func TestAddAccessLog(t *testing.T) { } } -func TestAccessLog(t *testing.T) { - var err error - var accessLogList []models.AccessLog - accessLog := models.AccessLog{ - UserID: currentUser.UserID, - ProjectID: currentProject.ProjectID, - RepoName: currentProject.Name + "/", - RepoTag: repoTag2, - Operation: "create", - } - err = AccessLog(currentUser.Username, currentProject.Name, currentProject.Name+"/", repoTag2, "create") - if err != nil { - t.Errorf("Error occurred in AccessLog: %v", err) - } - accessLogList, err = GetAccessLogs(accessLog, 1000, 0) - 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 != repoTag2 { - t.Errorf("The repo tag does not match, expected: %s, actual: %s", repoTag2, accessLogList[0].RepoTag) - } -} - func TestCountPull(t *testing.T) { var err error - err = AccessLog(currentUser.Username, currentProject.Name, currentProject.Name+"/tomcat", repoTag2, "pull") - if err != nil { + 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) } - err = AccessLog(currentUser.Username, currentProject.Name, currentProject.Name+"/tomcat", repoTag2, "pull") - if err != nil { + + 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) } - err = AccessLog(currentUser.Username, currentProject.Name, currentProject.Name+"/tomcat", repoTag2, "pull") - if err != nil { + + 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) } @@ -973,7 +975,7 @@ func TestChangeUserProfile(t *testing.T) { } func TestGetRecentLogs(t *testing.T) { - logs, err := GetRecentLogs(currentUser.UserID, 10, "2016-05-13 00:00:00", time.Now().String()) + 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) } diff --git a/src/common/dao/project.go b/src/common/dao/project.go index 3cfdff0f6..f0c5aaf3b 100644 --- a/src/common/dao/project.go +++ b/src/common/dao/project.go @@ -45,13 +45,7 @@ func AddProject(project models.Project) (int64, error) { return 0, err } - if err = AddProjectMember(projectID, project.OwnerID, models.PROJECTADMIN); err != nil { - return projectID, err - } - - accessLog := models.AccessLog{UserID: project.OwnerID, ProjectID: projectID, RepoName: project.Name + "/", RepoTag: "N/A", GUID: "N/A", Operation: "create", OpTime: time.Now()} - err = AddAccessLog(accessLog) - + err = AddProjectMember(projectID, project.OwnerID, models.PROJECTADMIN) return projectID, err } diff --git a/src/common/models/accesslog.go b/src/common/models/accesslog.go index 54d1f4ec6..52a447a33 100644 --- a/src/common/models/accesslog.go +++ b/src/common/models/accesslog.go @@ -21,17 +21,16 @@ import ( // 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"` - UserID int `orm:"column(user_id)" json:"user_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"` - Username string `json:"username"` - Keywords string `json:"keywords"` - BeginTime time.Time - BeginTimestamp int64 `json:"begin_timestamp"` - EndTime time.Time - EndTimestamp int64 `json:"end_timestamp"` + 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"` } diff --git a/src/ui/api/log.go b/src/ui/api/log.go index 59275e287..b92f44150 100644 --- a/src/ui/api/log.go +++ b/src/ui/api/log.go @@ -19,10 +19,10 @@ import ( "strconv" "time" + "github.com/vmware/harbor/src/common/api" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" "github.com/vmware/harbor/src/common/utils/log" - "github.com/vmware/harbor/src/common/api" ) //LogAPI handles request api/logs @@ -75,8 +75,16 @@ func (l *LogAPI) Get() { linesNum = 10 } + user, err := dao.GetUser(models.User{ + UserID: l.userID, + }) + if err != nil { + log.Errorf("failed to get user by user ID %d: %v", l.userID, err) + l.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + var logList []models.AccessLog - logList, err = dao.GetRecentLogs(l.userID, linesNum, startTime, endTime) + logList, err = dao.GetRecentLogs(user.Username, linesNum, startTime, endTime) if err != nil { log.Errorf("Get recent logs error, err: %v", err) l.CustomAbort(http.StatusInternalServerError, "Internal error") diff --git a/src/ui/api/project.go b/src/ui/api/project.go index d24230a43..b151d3097 100644 --- a/src/ui/api/project.go +++ b/src/ui/api/project.go @@ -118,6 +118,29 @@ func (p *ProjectAPI) Post() { } return } + + user, err := dao.GetUser(models.User{ + UserID: p.userID, + }) + if err != nil { + log.Errorf("failed to get user by ID %d: %v", p.userID, err) + p.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + + accessLog := models.AccessLog{ + Username: user.Username, + ProjectID: projectID, + RepoName: project.Name + "/", + RepoTag: "N/A", + GUID: "N/A", + Operation: "create", + OpTime: time.Now(), + } + if err = dao.AddAccessLog(accessLog); err != nil { + log.Errorf("failed to add access log: %v", err) + p.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + p.Redirect(http.StatusCreated, strconv.FormatInt(projectID, 10)) } @@ -200,12 +223,21 @@ func (p *ProjectAPI) Delete() { } go func() { + user, err := dao.GetUser(models.User{ + UserID: userID, + }) + if err != nil { + log.Errorf("failed to get user by ID %d: %v", userID, err) + p.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) + } + if err := dao.AddAccessLog(models.AccessLog{ - UserID: userID, + Username: user.Username, ProjectID: p.projectID, RepoName: p.projectName + "/", RepoTag: "N/A", Operation: "delete", + OpTime: time.Now(), }); err != nil { log.Errorf("failed to add access log: %v", err) } diff --git a/src/ui/api/repository.go b/src/ui/api/repository.go index 2b6300dad..b9d83b1e1 100644 --- a/src/ui/api/repository.go +++ b/src/ui/api/repository.go @@ -267,7 +267,19 @@ func (ra *RepositoryAPI) Delete() { go TriggerReplicationByRepository(repoName, []string{t}, models.RepOpDelete) go func(tag string) { - if err := dao.AccessLog(user, projectName, repoName, tag, "delete"); err != nil { + project, err := dao.GetProjectByName(projectName) + if err != nil { + log.Errorf("failed to get project by name %s: %v", projectName, err) + return + } + if err := dao.AddAccessLog(models.AccessLog{ + Username: user, + ProjectID: project.ProjectID, + RepoName: repoName, + RepoTag: tag, + Operation: "delete", + OpTime: time.Now(), + }); err != nil { log.Errorf("failed to add access log: %v", err) } }(t) diff --git a/src/ui/service/notification.go b/src/ui/service/notification.go index 285c52cc4..b9bcbadee 100644 --- a/src/ui/service/notification.go +++ b/src/ui/service/notification.go @@ -18,6 +18,7 @@ import ( "encoding/json" "regexp" "strings" + "time" "github.com/vmware/harbor/src/common/dao" "github.com/vmware/harbor/src/common/models" @@ -65,7 +66,19 @@ func (n *NotificationHandler) Post() { } go func() { - if err := dao.AccessLog(user, project, repository, tag, action); err != nil { + pro, err := dao.GetProjectByName(project) + if err != nil { + log.Errorf("failed to get project by name %s: %v", project, err) + return + } + if err := dao.AddAccessLog(models.AccessLog{ + Username: user, + ProjectID: pro.ProjectID, + RepoName: repository, + RepoTag: tag, + Operation: action, + OpTime: time.Now(), + }); err != nil { log.Errorf("failed to add access log: %v", err) } }() diff --git a/tools/migration/changelog.md b/tools/migration/changelog.md index 1ced7351a..a0851ebe1 100644 --- a/tools/migration/changelog.md +++ b/tools/migration/changelog.md @@ -41,3 +41,6 @@ Changelog for harbor database schema ## 1.2.0 - delete column `owner_id` from table `repository` + - delete column `user_id` from table `access_log` + - delete foreign key (user_id) references user(user_id)from table `access_log` + - add column `username` varchar (32) to table `access_log` \ No newline at end of file