From fd8c7a6405ef11d124acbafe31e94535f2f459ac Mon Sep 17 00:00:00 2001 From: kunw Date: Fri, 19 Feb 2016 12:34:18 +0800 Subject: [PATCH 01/15] fixed query dates params of access log filter --- api/project.go | 10 +++++++--- dao/access_log.go | 12 ++++++------ models/access_log.go | 9 +++++---- static/resources/js/item-detail.js | 24 +++++++++++++++++++----- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/api/project.go b/api/project.go index 9c711e17d..73fa4ae70 100644 --- a/api/project.go +++ b/api/project.go @@ -162,10 +162,14 @@ func (p *ProjectAPI) FilterAccessLog() { username := filter.Username keywords := filter.Keywords - beginTime := filter.BeginTime - endTime := filter.EndTime - query := models.AccessLog{ProjectId: p.projectId, Username: "%" + username + "%", Keywords: keywords, BeginTime: beginTime, EndTime: endTime} + beginTime := time.Unix(filter.BeginTimestamp, 0) + endTime := time.Unix(filter.EndTimestamp, 0) + + query := models.AccessLog{ProjectId: p.projectId, Username: "%" + username + "%", Keywords: keywords, BeginTime: beginTime, BeginTimestamp: filter.BeginTimestamp, EndTime: endTime, EndTimestamp: filter.EndTimestamp} + + log.Printf("Query AccessLog: begin: %v, end: %v, keywords: %s", query.BeginTime, query.EndTime, query.Keywords) + accessLogList, err := dao.GetAccessLogs(query) if err != nil { log.Printf("Error occurred in GetAccessLogs: %v", err) diff --git a/dao/access_log.go b/dao/access_log.go index 4e99cfdb8..5860a30c3 100644 --- a/dao/access_log.go +++ b/dao/access_log.go @@ -73,13 +73,13 @@ func GetAccessLogs(accessLog models.AccessLog) ([]models.AccessLog, error) { } } } - if accessLog.BeginTime != "" { - sql += ` and a.op_time >= str_to_date(?, '%Y-%m-%d %H:%i:%s') ` - queryParam = append(queryParam, accessLog.BeginTime+" 00:00:00.000000") + if accessLog.BeginTimestamp > 0 { + sql += ` and a.op_time >= ? ` + queryParam = append(queryParam, accessLog.BeginTime) } - if accessLog.EndTime != "" { - sql += ` and a.op_time <= str_to_date(?, '%Y-%m-%d %H:%i:%s') ` - queryParam = append(queryParam, accessLog.EndTime+" 23:59:59.99999") + if accessLog.EndTimestamp > 0 { + sql += ` and a.op_time <= ? ` + queryParam = append(queryParam, accessLog.EndTime) } sql += ` order by a.op_time desc ` diff --git a/models/access_log.go b/models/access_log.go index 7c980103d..a167d70de 100644 --- a/models/access_log.go +++ b/models/access_log.go @@ -26,10 +26,11 @@ type AccessLog struct { Guid string Operation string OpTime time.Time - OpTimeStr string - Username string Keywords string - BeginTime string - EndTime string + + BeginTime time.Time + BeginTimestamp int64 + EndTime time.Time + EndTimestamp int64 } diff --git a/static/resources/js/item-detail.js b/static/resources/js/item-detail.js index d2ff211bb..764df0fe6 100644 --- a/static/resources/js/item-detail.js +++ b/static/resources/js/item-detail.js @@ -374,24 +374,38 @@ jQuery(function(){ listUser(username); }); + function toUTCSeconds(date, hour, min, sec) { + var t = new Date(date); + t.setHours(hour); + t.setMinutes(min); + t.setSeconds(sec); + var utcTime = new Date(t.getUTCFullYear(), + t.getUTCMonth(), + t.getUTCDate(), + t.getUTCHours(), + t.getUTCMinutes(), + t.getUTCSeconds()); + return utcTime.getTime() / 1000; + } + $("#btnFilterLog").on("click", function(){ var projectId = $("#projectId").val(); var username = $("#txtSearchUserName").val(); - var beginTime = ""; - var endTime = ""; + var beginTimestamp = 0; + var endTimestamp = 0; if($("#begindatepicker").val() != ""){ - beginTime = moment(new Date($("#begindatepicker").val())).format("YYYY-MM-DD"); + beginTimestamp = toUTCSeconds($("#begindatepicker").val(), 0, 0, 0); } if($("#enddatepicker").val() != ""){ - endTime = moment(new Date($("#enddatepicker").val())).format("YYYY-MM-DD"); + endTimestamp = toUTCSeconds($("#enddatepicker").val(), 23, 59, 59); } new AjaxUtil({ url: "/api/projects/" + projectId + "/logs/filter", - data:{"username":username, "project_id" : projectId, "keywords" : getKeyWords() , "beginTime" : beginTime, "endTime" : endTime}, + data:{"username":username, "project_id" : projectId, "keywords" : getKeyWords() , "beginTimestamp" : beginTimestamp, "endTimestamp" : endTimestamp}, type: "post", success: function(data, status, xhr){ if(xhr && xhr.status == 200){ From 0740076f8f8a3d2127b45961ca5b4151866a2211 Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Mon, 22 Feb 2016 10:46:09 +0800 Subject: [PATCH 02/15] remove conf directory --- Dockerfile | 5 ++--- conf/app.conf | 9 --------- conf/private_key.pem | 15 --------------- 3 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 conf/app.conf delete mode 100644 conf/private_key.pem diff --git a/Dockerfile b/Dockerfile index 468612f62..525c9de88 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,8 +14,8 @@ WORKDIR /go/src/github.com/vmware/harbor ENV GO15VENDOREXPERIMENT 1 RUN go get -d github.com/docker/distribution \ && go get -d github.com/docker/libtrust \ - && go get -d github.com/go-sql-driver/mysql -RUN go install -v -a + && go get -d github.com/go-sql-driver/mysql \ + && go install -v -a ENV MYSQL_USR root \ MYSQL_PWD root \ @@ -23,7 +23,6 @@ ENV MYSQL_USR root \ MYSQL_PORT_3306_TCP_PORT 3306 \ REGISTRY_URL localhost:5000 -COPY conf /go/bin/conf COPY views /go/bin/views COPY static /go/bin/static diff --git a/conf/app.conf b/conf/app.conf deleted file mode 100644 index c80279df4..000000000 --- a/conf/app.conf +++ /dev/null @@ -1,9 +0,0 @@ -appname = harbor -runmode = dev - -[lang] -types = en-US|zh-CN -names = en-US|zh-CN - -[dev] -httpport = 80 \ No newline at end of file diff --git a/conf/private_key.pem b/conf/private_key.pem deleted file mode 100644 index 6c68cacb3..000000000 --- a/conf/private_key.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXQIBAAKBgQClak/4HO7EeLU0w/BhtVENPLOqU0AP2QjVUdg1qhNiDWVrbWx9 -KYHqz5Kn0n2+fxdZo3o7ZY5/2+hhgkKh1z6Kge9XGgune6z4fx2J/X2Se8WsGeQU -TiND8ngSnsCANtYFwW50SbUZPtyf5XjAfKRofZem51OxbxzN3217L/ubKwIDAQAB -AoGBAITMMuNYJwAogCGaZHOs4yMjZoIJT9bpQMQxbsi2f9UqOA/ky0I4foqKloyQ -2k6DLbXTHqBsydgwLgGKWAAiE5xIR2bPMUNSLgjbA2eLly3aOR/0FJ5n09k2EmGg -Am7tLP+6yneXWKVi3HI3NzXriVjWK94WHGGC1b9F+n5CY/2RAkEA1d62OJUNve2k -IY6/b6T0BdssFo3VFcm22vnayEL/wcYrnRfF9Pb5wM4HUUqwVelKTouivXg60GNK -ZKYAx5CtHwJBAMYAEf5u0CQ/8URcwBuMkm0LzK4AM2x1nGs7gIxAEFhu1Z4xPjVe -MtIxuHhDhlLvD760uccmo5yE72QJ1ZrYBHUCQQCAxLZMPRpoB4QyHEOREe1G9V6H -OeBZXPk2wQcEWqqo3gt2a1DqHCXl+2aWgHTJVUxDHHngwFoRDCdHkFeZ0LcbAkAj -T8/luI2WaXD16DS6tQ9IM1qFjbOeHDuRRENgv+wqWVnvpIibq/kUU5m6mRBTqh78 -u+6F/fYf6/VluftGalAhAkAukdMtt+sksq2e7Qw2dRr5GXtXjt+Otjj0NaJENmWk -a7SgAs34EOWtbd0XGYpZFrg134MzQGbweFeEUTj++e8p ------END RSA PRIVATE KEY----- From dadb52323b9fafc0d117fc33fb83c79dd024903d Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Mon, 22 Feb 2016 13:20:17 +0800 Subject: [PATCH 03/15] fix typo --- Deploy/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Deploy/docker-compose.yml b/Deploy/docker-compose.yml index f377d8ea5..acecce1ec 100644 --- a/Deploy/docker-compose.yml +++ b/Deploy/docker-compose.yml @@ -46,7 +46,7 @@ ui: log_opt: syslog-address: "tcp://127.0.0.1:1514" syslog-tag: "ui" -roxy: +proxy: image: library/nginx:1.9 volumes: - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf From 9d103d3b09661dfe35ceb6943c6982e49a3ca46f Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Tue, 23 Feb 2016 12:16:36 +0800 Subject: [PATCH 04/15] reload config before initialization of controllers --- controllers/base.go | 12 +++++++++++- main.go | 7 ------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/controllers/base.go b/controllers/base.go index 1f95f830e..9f9046b0f 100644 --- a/controllers/base.go +++ b/controllers/base.go @@ -15,6 +15,7 @@ package controllers import ( + "log" "os" "strings" @@ -114,6 +115,16 @@ var langTypes []*langType func init() { + //conf/app.conf -> os.Getenv("config_path") + configPath := os.Getenv("CONFIG_PATH") + if len(configPath) != 0 { + log.Printf("Config path: %s", configPath) + beego.AppConfigPath = configPath + if err := beego.ParseConfig(); err != nil { + beego.Warning("Failed to parse config file: ", configPath, "error: ", err) + } + } + beego.AddFuncMap("i18n", i18n.Tr) langs := strings.Split(beego.AppConfig.String("lang::types"), "|") @@ -134,7 +145,6 @@ func init() { for _, lang := range langs { if err := i18n.SetMessage(lang, "static/i18n/"+"locale_"+lang+".ini"); err != nil { beego.Error("Fail to set message file:" + err.Error()) - return } } } diff --git a/main.go b/main.go index 86e8ee87d..189cb8400 100644 --- a/main.go +++ b/main.go @@ -68,13 +68,6 @@ func main() { beego.BConfig.WebConfig.Session.SessionOn = true - //conf/app.conf -> os.Getenv("config_path") - configPath := os.Getenv("CONFIG_PATH") - if len(configPath) != 0 { - beego.Debug(fmt.Sprintf("Config path: %s", configPath)) - beego.AppConfigPath = configPath - } - updateInitPassword(ADMIN_USER_ID, os.Getenv("HARBOR_ADMIN_PASSWORD")) beego.Run() From dae7881088da61f2789e440a420931f5b3e8219f Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Tue, 23 Feb 2016 12:42:22 +0800 Subject: [PATCH 05/15] refine --- Deploy/config/nginx/nginx.conf | 2 -- Deploy/docker-compose.yml | 8 ++++---- dao/base.go | 34 +++++++++++++++++----------------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/Deploy/config/nginx/nginx.conf b/Deploy/config/nginx/nginx.conf index 3941e94fa..8168137ea 100644 --- a/Deploy/config/nginx/nginx.conf +++ b/Deploy/config/nginx/nginx.conf @@ -15,12 +15,10 @@ http { upstream registry { server registry:5000; -# check interval=2000 rise=1 fall=1 timeout=5000 type=tcp; } upstream ui { server ui:80; -# check interval=2000 rise=1 fall=1 timeout=5000 type=tcp; } diff --git a/Deploy/docker-compose.yml b/Deploy/docker-compose.yml index acecce1ec..0c03ae7b3 100644 --- a/Deploy/docker-compose.yml +++ b/Deploy/docker-compose.yml @@ -39,8 +39,8 @@ ui: - ./config/ui/app.conf:/etc/ui/app.conf - ./config/ui/private_key.pem:/etc/ui/private_key.pem links: - - registry:registry - - mysql:mysql + - registry + - mysql - log log_driver: "syslog" log_opt: @@ -51,8 +51,8 @@ proxy: volumes: - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf links: - - ui:ui - - registry:registry + - ui + - registry - log ports: - 80:80 diff --git a/dao/base.go b/dao/base.go index d6e8f37a9..db3a08899 100644 --- a/dao/base.go +++ b/dao/base.go @@ -1,16 +1,16 @@ /* - Copyright (c) 2016 VMware, Inc. All Rights Reserved. - 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. + Copyright (c) 2016 VMware, Inc. All Rights Reserved. + 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 @@ -50,12 +50,12 @@ func isContainIllegalChar(s string, illegalChar []string) bool { func GenerateRandomString() (string, error) { o := orm.NewOrm() - var salt string - err := o.Raw(`select uuid() as uuid`).QueryRow(&salt) + var uuid string + err := o.Raw(`select uuid() as uuid`).QueryRow(&uuid) if err != nil { return "", err } - return salt, nil + return uuid, nil } @@ -112,8 +112,8 @@ func init() { }() select { case <-ch: - case <-time.After(30 * time.Second): - panic("Failed to connect to DB after 30 seconds") + case <-time.After(60 * time.Second): + panic("Failed to connect to DB after 60 seconds") } orm.RegisterDataBase("default", "mysql", db_str) } From 65e010d56ef9b2535bd67406dd125ef6445793c3 Mon Sep 17 00:00:00 2001 From: xiahaoshawn Date: Tue, 23 Feb 2016 13:23:41 +0800 Subject: [PATCH 06/15] Update Dockerfile.offline delete "ADD conf /go/bin/conf" as conf directory is not exist --- Dockerfile.offline | 1 - 1 file changed, 1 deletion(-) diff --git a/Dockerfile.offline b/Dockerfile.offline index 4f03681ac..34d56c25f 100644 --- a/Dockerfile.offline +++ b/Dockerfile.offline @@ -9,7 +9,6 @@ ENV REGISTRY_URL localhost:5000 RUN apt-get update -qqy && apt-get install -qqy libldap2-dev ADD harbor /go/bin/harbor -ADD conf /go/bin/conf ADD views /go/bin/views ADD static /go/bin/static From 25347a10379068a9cd402722e21faeccfd60cbf9 Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Tue, 23 Feb 2016 20:49:59 +0800 Subject: [PATCH 07/15] ut rework --- dao/base.go | 8 +- main.go | 3 +- tests/dao_test.go | 387 ++++++++++++++++++++++------------------------ 3 files changed, 191 insertions(+), 207 deletions(-) diff --git a/dao/base.go b/dao/base.go index db3a08899..90ba82143 100644 --- a/dao/base.go +++ b/dao/base.go @@ -59,9 +59,8 @@ func GenerateRandomString() (string, error) { } -func init() { +func InitDB() { orm.RegisterDriver("mysql", orm.DRMySQL) - addr := os.Getenv("MYSQL_HOST") if len(addr) == 0 { addr = os.Getenv("MYSQL_PORT_3306_TCP_ADDR") @@ -115,5 +114,8 @@ func init() { case <-time.After(60 * time.Second): panic("Failed to connect to DB after 60 seconds") } - orm.RegisterDataBase("default", "mysql", db_str) + err := orm.RegisterDataBase("default", "mysql", db_str) + if err != nil { + panic(err) + } } diff --git a/main.go b/main.go index 189cb8400..c6a69c8c2 100644 --- a/main.go +++ b/main.go @@ -67,8 +67,7 @@ func updateInitPassword(userId int, password string) error { func main() { beego.BConfig.WebConfig.Session.SessionOn = true - + dao.InitDB() updateInitPassword(ADMIN_USER_ID, os.Getenv("HARBOR_ADMIN_PASSWORD")) - beego.Run() } diff --git a/tests/dao_test.go b/tests/dao_test.go index 9d39b3037..bbea5fc53 100644 --- a/tests/dao_test.go +++ b/tests/dao_test.go @@ -15,8 +15,7 @@ package test import ( - "flag" - "fmt" + // "fmt" "log" "os" "testing" @@ -85,9 +84,7 @@ func clearUp(username string) { } const USERNAME string = "Tester01" - const PROJECT_NAME string = "test_project" - const SYS_ADMIN int = 1 const PROJECT_ADMIN int = 2 const DEVELOPER int = 3 @@ -98,35 +95,35 @@ const PUBLICITY_OFF = 0 func TestMain(m *testing.M) { - //Create a custom flag set, let user to provide DB related configures for testing. - fs := flag.NewFlagSet("DB related configures", 0) - - dbIp := fs.String("db_ip", "localhost", "IP address for connecting a test DB.") - dbPort := fs.String("db_port", "3306", "Port number for connecting a test DB.") - dbUser := fs.String("db_user", "root", "Username for logging in a test DB.") - dbPassword := fs.String("db_password", "root", "Password for logging in a test DB.") - - fs.Parse([]string{"db_ip", "db_port", "db_user", "db_password"}) - - if fs.NFlag() == 0 { - fs.PrintDefaults() - fmt.Println("Now, use DEFAULT values if omit to set all of flags.") + dbHost := os.Getenv("DB_HOST") + if len(dbHost) == 0 { + log.Fatalf("environment variable DB_HOST is not set") + } + dbUser := os.Getenv("DB_USR") + if len(dbUser) == 0 { + log.Fatalf("environment variable DB_USR is not set") + } + dbPort := os.Getenv("DB_PORT") + if len(dbPort) == 0 { + log.Fatalf("environment variable DB_PWD is not set") + } + dbPassword := os.Getenv("DB_PWD") + if len(dbPassword) == 0 { + log.Fatalf("environment variable DB_PWD is not set") } - if fs.Parsed() { + os.Setenv("MYSQL_PORT_3306_TCP_ADDR", dbHost) + os.Setenv("MYSQL_PORT_3306_TCP_PORT", dbPort) + os.Setenv("MYSQL_USR", dbUser) + os.Setenv("MYSQL_PWD", dbPassword) + os.Setenv("AUTH_MODE", "db_auth") + dao.InitDB() + clearUp(USERNAME) + os.Exit(m.Run()) - clearUp(USERNAME) - - os.Setenv("MYSQL_PORT_3306_TCP_ADDR", *dbIp) - os.Setenv("MYSQL_PORT_3306_TCP_PORT", *dbPort) - os.Setenv("MYSQL_USR", *dbUser) - os.Setenv("MYSQL_PWD", *dbPassword) - os.Setenv("AUTH_MODE", "db_auth") - os.Exit(m.Run()) - } } -func ExampleRegister() { +func TestRegister(t *testing.T) { user := models.User{ Username: USERNAME, @@ -138,7 +135,7 @@ func ExampleRegister() { _, err := dao.Register(user) if err != nil { - log.Printf("Error occurred in Register: %v", err) + t.Errorf("Error occurred in Register: %v", err) } //Check if user registered successfully. @@ -147,41 +144,46 @@ func ExampleRegister() { } newUser, err := dao.GetUser(queryUser) if err != nil { - log.Fatalf("Error occurred in GetUser: %v", err) + t.Errorf("Error occurred in GetUser: %v", err) } - fmt.Println(newUser.Username) - fmt.Println(newUser.Email) - // Output: - // Tester01 - // tester01@vmware.com - + if newUser.Username != USERNAME { + t.Errorf("Username does not match, expected: %s, actual: %s", USERNAME, newUser.Username) + } + if newUser.Email != "tester01@vmware.com" { + t.Errorf("Email does not match, expected: %s, actual: %s", "tester01@vmware.com", newUser.Email) + } } -func ExampleUserExists() { +func TestUserExists(t *testing.T) { var exists bool var err error - exists, err = dao.UserExists(models.User{Username: "Tester01"}, "username") - fmt.Println(exists) - + exists, err = dao.UserExists(models.User{Username: USERNAME}, "username") if err != nil { - log.Fatalf("Error occurred in UserExists: %v", err) + t.Errorf("Error occurred in UserExists: %v", err) + } + if !exists { + t.Errorf("User %s was inserted but does not exist", USERNAME) } exists, err = dao.UserExists(models.User{Email: "tester01@vmware.com"}, "email") - fmt.Println(exists) if err != nil { - log.Fatalf("Error occurred in UserExists: %v", err) + t.Errorf("Error occurred in UserExists: %v", err) + } + if !exists { + t.Errorf("User with email %s inserted but does not exist", "tester01@vmware.com") + } + exists, err = dao.UserExists(models.User{Username: "NOTHERE"}, "username") + if err != nil { + t.Errorf("Error occurred in UserExists: %v", err) + } + if exists { + t.Errorf("User %s was not inserted but does exist", "NOTHERE") } - - //Output: - //true - //true - } -func ExampleLoginByUserName() { +func TestLoginByUserName(t *testing.T) { userQuery := models.User{ Username: USERNAME, @@ -190,18 +192,18 @@ func ExampleLoginByUserName() { loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Username, userQuery.Password}) if err != nil { - log.Fatalf("Error occurred in LoginByDb: %v", err) + t.Errorf("Error occurred in LoginByDb: %v", err) } if loginUser == nil { - log.Fatalf("No found for user logined by username and password: %v", userQuery) + t.Errorf("No found for user logined by username and password: %v", userQuery) } - fmt.Println(loginUser.Username) - // Output: - // Tester01 + if loginUser.Username != USERNAME { + t.Errorf("User's username does not match after login, expected: %s, actual: %s", USERNAME, loginUser.Username) + } } -func ExampleLoginByEmail() { +func TestLoginByEmail(t *testing.T) { userQuery := models.User{ Email: "tester01@vmware.com", @@ -210,105 +212,108 @@ func ExampleLoginByEmail() { loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Email, userQuery.Password}) if err != nil { - log.Fatalf("Error occurred in LoginByDb: %v", err) + t.Errorf("Error occurred in LoginByDb: %v", err) } if loginUser == nil { - log.Fatalf("No found for user logined by email and password : %v", userQuery) + t.Errorf("No found for user logined by email and password : %v", userQuery) + } + if loginUser.Username != USERNAME { + t.Errorf("User's username does not match after login, expected: %s, actual: %s", USERNAME, loginUser.Username) } - fmt.Println(loginUser.Username) - // Output: - // Tester01 } var currentUser *models.User -func ExampleGetUser() { +func TestGetUser(t *testing.T) { queryUser := models.User{ Username: USERNAME, } var err error currentUser, err = dao.GetUser(queryUser) if err != nil { - log.Fatalf("Error occurred in GetUser", err) + t.Errorf("Error occurred in GetUser: %v", err) } if currentUser == nil { - log.Fatalf("No user found queried by username: %v", queryUser) + t.Errorf("No user found queried by user query: %+v", queryUser) + } + if currentUser.Email != "tester01@vmware.com" { + t.Errorf("the user's email does not match, expected: tester01@vmware.com, actual: %s", currentUser.Email) } - fmt.Println(currentUser.Username) - //Output: - //Tester01 } -func ExampleListUsers() { - users, err := dao.ListUsers(models.User{Username: "tester01"}) +func TestListUsers(t *testing.T) { + users, err := dao.ListUsers(models.User{}) if err != nil { - log.Fatalf("Error occurred in ListUsers: %v", err) + t.Errorf("Error occurred in ListUsers: %v", err) } - - for _, u := range users { - fmt.Println(u.Username) + if len(users) != 1 { + t.Errorf("Expect one user in list, but the acutal length is %d, the list: %+v", len(users), users) + } + users2, err := dao.ListUsers(models.User{Username: USERNAME}) + if len(users2) != 1 { + t.Errorf("Expect one user in list, but the acutal length is %d, the list: %+v", len(users), users) + } + if users2[0].Username != USERNAME { + t.Errorf("The username in result list does not match, expected: %s, actual: %s", USERNAME, users2[0].Username) } - //Output: - //Tester01 } -func ExampleResetUserPassword() { +func TestResetUserPassword(t *testing.T) { uuid, err := dao.GenerateRandomString() if err != nil { - log.Fatalf("Error occurred in GenerateRandomString: %v", err) + t.Errorf("Error occurred in GenerateRandomString: %v", err) } err = dao.UpdateUserResetUuid(models.User{ResetUuid: uuid, Email: currentUser.Email}) if err != nil { - log.Fatalf("Error occurred in UpdateUserResetUuid: %v", err) + t.Errorf("Error occurred in UpdateUserResetUuid: %v", err) } err = dao.ResetUserPassword(models.User{UserId: currentUser.UserId, Password: "HarborTester12345", ResetUuid: uuid, Salt: currentUser.Salt}) if err != nil { - log.Fatalf("Error occurred in ResetUserPassword: %v", err) + t.Errorf("Error occurred in ResetUserPassword: %v", err) } loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "HarborTester12345"}) if err != nil { - log.Fatalf("Error occurred in LoginByDb: %v", err) + t.Errorf("Error occurred in LoginByDb: %v", err) } - fmt.Println(loginedUser.Username) - //Output: - //Tester01 + if loginedUser.Username != USERNAME { + t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username) + } } -func ExampleChangeUserPassword() { +func TestChangeUserPassword(t *testing.T) { err := dao.ChangeUserPassword(models.User{UserId: currentUser.UserId, Password: "NewHarborTester12345", Salt: currentUser.Salt}) if err != nil { - log.Fatalf("Error occurred in ChangeUserPassword: %v", err) + t.Errorf("Error occurred in ChangeUserPassword: %v", err) } loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "NewHarborTester12345"}) if err != nil { - log.Fatalf("Error occurred in LoginByDb: %v", err) + t.Errorf("Error occurred in LoginByDb: %v", err) } - fmt.Println(loginedUser.Username) - //Output: - //Tester01 + if loginedUser.Username != USERNAME { + t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username) + } } -func ExampleQueryRelevantProjectsWhenNoProjectAdded() { +func TestQueryRelevantProjectsWhenNoProjectAdded(t *testing.T) { projects, err := dao.QueryRelevantProjects(currentUser.UserId) if err != nil { - log.Fatalf("Error occurred in QueryRelevantProjects: %v", err) + t.Errorf("Error occurred in QueryRelevantProjects: %v", err) } - fmt.Println(len(projects)) - for _, p := range projects { - fmt.Println(p.Name) + if len(projects) != 1 { + t.Errorf("Expected only one project in DB, but actual: %d", len(projects)) + } + if projects[0].Name != "library" { + t.Errorf("There name of the project does not match, expected: %s, actual: %s", "library", projects[0].Name) } - //Output: - //1 - //library } -func ExampleAddProject() { +func TestAddProject(t *testing.T) { project := models.Project{ OwnerId: currentUser.UserId, @@ -319,134 +324,128 @@ func ExampleAddProject() { err := dao.AddProject(project) if err != nil { - log.Fatalf("Error occurred in AddProject: %v", err) + t.Errorf("Error occurred in AddProject: %v", err) } newProject, err := dao.GetProjectByName(PROJECT_NAME) if err != nil { - log.Fatalf("Error occurred in GetProjectByName: %v", err) + t.Errorf("Error occurred in GetProjectByName: %v", err) } if newProject == nil { - log.Fatalf("No project found queried by project name: %v", PROJECT_NAME) + t.Errorf("No project found queried by project name: %v", PROJECT_NAME) } - fmt.Println(newProject.Name) - //Output: - //test_project } var currentProject *models.Project -func ExampleGetProject() { +func TestGetProject(t *testing.T) { var err error currentProject, err = dao.GetProjectByName(PROJECT_NAME) if err != nil { - log.Fatalf("Error occurred in GetProjectByName: %v", err) + t.Errorf("Error occurred in GetProjectByName: %v", err) } if currentProject == nil { - log.Fatalf("No project found queried by project name: %v", PROJECT_NAME) + t.Errorf("No project found queried by project name: %v", PROJECT_NAME) + } + if currentProject.Name != PROJECT_NAME { + t.Errorf("Project name does not match, expected: %s, actual: %s", PROJECT_NAME, currentProject.Name) } - fmt.Println(currentProject.Name) - //Output: - //test_project } func getProjectRole(projectId int64) []models.Role { o := orm.NewOrm() var r []models.Role _, err := o.Raw(`select r.role_id, r.name - from project_role pr + from project_role pr left join role r on pr.role_id = r.role_id where project_id = ?`, projectId).QueryRows(&r) if err != nil { - log.Fatalf("Error occurred in querying project_role: %v", err) + log.Printf("Error occurred in querying project_role: %v", err) } return r } -func ExampleCheckProjectRoles() { +func TestCheckProjectRoles(t *testing.T) { r := getProjectRole(currentProject.ProjectId) - fmt.Println(len(r)) - - for _, pr := range r { - fmt.Println(pr.RoleId, pr.Name) + if len(r) != 3 { + t.Errorf("The length of project roles is not 3") + } + if r[1].RoleId != 3 { + t.Errorf("The role id does not match, expected: 3, acutal: %d", r[1].RoleId) + } + if r[1].Name != "developer" { + t.Errorf("The name of role id: 3 should be developer, actual:%s", r[1].Name) } - - //Output: 3 - //2 projectAdmin - //3 developer - //4 guest - } -func ExampleGetAccessLog() { +func TestGetAccessLog(t *testing.T) { queryAccessLog := models.AccessLog{ UserId: currentUser.UserId, ProjectId: currentProject.ProjectId, } accessLogs, err := dao.GetAccessLogs(queryAccessLog) if err != nil { - log.Fatalf("Error occurred in GetAccessLog: %v", err) + t.Errorf("Error occurred in GetAccessLog: %v", err) } - fmt.Println(len(accessLogs)) - for _, log := range accessLogs { - fmt.Println(log.Operation, log.RepoName) + if len(accessLogs) != 1 { + t.Errorf("The length of accesslog list should be 1, actual: %d", len(accessLogs)) + } + if accessLogs[0].RepoName != PROJECT_NAME { + t.Errorf("The project name does not match, expected: %s, actual: %s", PROJECT_NAME, accessLogs[0].RepoName) } - //Output: - //1 - //create test_project/ } -func ExampleProjectExists() { +func TestProjectExists(t *testing.T) { var exists bool var err error exists, err = dao.ProjectExists(currentProject.ProjectId) - fmt.Println(exists) if err != nil { - log.Fatalf("Error occurred in ProjectExists: %v", err) + t.Errorf("Error occurred in ProjectExists: %v", err) + } + if !exists { + t.Errorf("The project with id: %d, does not exist", currentProject.ProjectId) } exists, err = dao.ProjectExists(currentProject.Name) - fmt.Println(exists) if err != nil { - log.Fatalf("Error occurred in ProjectExists: %v", err) + t.Errorf("Error occurred in ProjectExists: %v", err) + } + if !exists { + t.Errorf("The project with name: %s, does not exist", currentProject.Name) } - //Output: - //true - //true - } -func ExampleToggleProjectPublicity() { +func TestToggleProjectPublicity(t *testing.T) { err := dao.ToggleProjectPublicity(currentProject.ProjectId, PUBLICITY_ON) if err != nil { - log.Fatalf("Error occurred in ToggleProjectPublicity: %v", err) + t.Errorf("Error occurred in ToggleProjectPublicity: %v", err) } currentProject, err = dao.GetProjectByName(PROJECT_NAME) if err != nil { - log.Fatalf("Error occurred in GetProjectByName: %v", err) + t.Errorf("Error occurred in GetProjectByName: %v", err) + } + if currentProject.Public != PUBLICITY_ON { + t.Errorf("project, id: %d, its publicity is not on", currentProject.ProjectId) } - fmt.Println(currentProject.Public) - err = dao.ToggleProjectPublicity(currentProject.ProjectId, PUBLICITY_OFF) if err != nil { - log.Fatalf("Error occurred in ToggleProjectPublicity: %v", err) + t.Errorf("Error occurred in ToggleProjectPublicity: %v", err) } currentProject, err = dao.GetProjectByName(PROJECT_NAME) if err != nil { - log.Fatalf("Error occurred in GetProjectByName: %v", err) + t.Errorf("Error occurred in GetProjectByName: %v", err) } - fmt.Println(currentProject.Public) - //Output: - //1 - //0 + if currentProject.Public != PUBLICITY_OFF { + t.Errorf("project, id: %d, its publicity is not off", currentProject.ProjectId) + } } func getUserProjectRole(projectId int64, userId int) []models.Role { o := orm.NewOrm() var r []models.Role - _, err := o.Raw(`select r.role_id, r.name + _, err := o.Raw(`select r.role_id, r.name from user_project_role upr left join project_role pr on upr.pr_id = pr.pr_id left join role r on r.role_id = pr.role_id @@ -457,99 +456,83 @@ func getUserProjectRole(projectId int64, userId int) []models.Role { return r } -func ExampleGetUserProjectRole() { +func TestGetUserProjectRole(t *testing.T) { r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId) //Get the size of current user project role. - fmt.Println(len(r)) - - //Iterating current user project role info. - for _, upr := range r { - fmt.Println(upr.RoleId, upr.Name) + if len(r) != 1 { + t.Errorf("The user, id: %d, should only have one role in project, id: %d, but actual: %d", currentUser.UserId, currentProject.ProjectId, len(r)) } - //Output: - //1 - //2 projectAdmin + if r[0].Name != "projectAdmin" { + t.Errorf("the expected rolename is: projectAdmin, actual: %s", r[0].Name) + } } -func ExampleProjectPermission() { +func TestProjectPermission(t *testing.T) { roleCode, err := dao.GetPermission(currentUser.Username, currentProject.Name) if err != nil { - log.Fatalf("Error occurred in GetPermission: %v", err) + t.Errorf("Error occurred in GetPermission: %v", err) + } + if roleCode != "MDRWS" { + t.Errorf("The expected role code is MDRWS,but actual: %s", roleCode) } - fmt.Println(roleCode) - //Output: - //MDRWS } -func ExampleQueryRelevantProjects() { +func TestQueryRelevantProjects(t *testing.T) { projects, err := dao.QueryRelevantProjects(currentUser.UserId) if err != nil { - log.Fatalf("Error occurred in QueryRelevantProjects: %v", err) + t.Errorf("Error occurred in QueryRelevantProjects: %v", err) } - fmt.Println(len(projects)) - for _, p := range projects { - fmt.Println(p.Name) + if len(projects) != 2 { + t.Errorf("Expected length of relevant projects is 2, but actual: %d, the projects: %+v", len(projects), projects) + } + if projects[1].Name != PROJECT_NAME { + t.Errorf("Expected project name in the list: %s, actual: %s", PROJECT_NAME, projects[1].Name) } - //Output: - //2 - //library - //test_project } -func ExampleAssignUserProjectRole() { +func TestAssignUserProjectRole(t *testing.T) { err := dao.AddUserProjectRole(currentUser.UserId, currentProject.ProjectId, DEVELOPER) if err != nil { - log.Fatalf("Error occurred in AddUserProjectRole: %v", err) + t.Errorf("Error occurred in AddUserProjectRole: %v", err) } r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId) //Get the size of current user project role info. - fmt.Println(len(r)) - - //Iterating current user project role. - for _, upr := range r { - fmt.Println(upr.RoleId, upr.Name) + if len(r) != 2 { + t.Errorf("Expected length of role list is 2, actual: %d", len(r)) } - //Output: - //2 - //2 projectAdmin - //3 developer + if r[1].RoleId != 3 { + t.Errorf("Expected role id of the second role in list is 3, actual: %d", r[1].RoleId) + } } -func ExampleDeleteUserProjectRole() { +func TestDeleteUserProjectRole(t *testing.T) { err := dao.DeleteUserProjectRoles(currentUser.UserId, currentProject.ProjectId) if err != nil { - log.Fatalf("Error occurred in DeleteUserProjectRoles: %v", err) + t.Errorf("Error occurred in DeleteUserProjectRoles: %v", err) } r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId) - //Get the size of current user project role. - fmt.Println(len(r)) - - //Iterating current user project role info. - for _, upr := range r { - fmt.Println(upr.RoleId, upr.Name) + if len(r) != 0 { + t.Errorf("Expected role list length is 0, actual: %d, role list: %+v", len(r), r) } - - //Output: - //0 } -func ExampleDeleteUser() { +func TestDeleteUser(t *testing.T) { err := dao.DeleteUser(currentUser.UserId) if err != nil { - log.Fatalf("Error occurred in DeleteUser: %v", err) + t.Errorf("Error occurred in DeleteUser: %v", err) } user, err := dao.GetUser(*currentUser) if err != nil { - log.Fatalf("Error occurred in GetUser: %v", err) + t.Errorf("Error occurred in GetUser: %v", err) + } + if user != nil { + t.Error("user is not nil after deletion, user: %+v", user) } - fmt.Println(user) - //Output: - // } From fc2fda0efef3e9c3a185267f71e9589ed9f4a3a8 Mon Sep 17 00:00:00 2001 From: wknet123 Date: Wed, 24 Feb 2016 04:02:08 +0800 Subject: [PATCH 08/15] fixed codes about changing password processes. --- controllers/password.go | 46 ++++++++++++++++++++++++++--------- dao/user.go | 15 +++++++++--- main.go | 2 +- views/reset-password-mail.tpl | 2 +- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/controllers/password.go b/controllers/password.go index e6211d413..b0ab637e3 100644 --- a/controllers/password.go +++ b/controllers/password.go @@ -43,15 +43,19 @@ func (cpc *ChangePasswordController) Get() { func (cpc *CommonController) UpdatePassword() { sessionUserId := cpc.GetSession("userId") - sessionUsername := cpc.GetSession("username") - if sessionUserId == nil || sessionUsername == nil { + if sessionUserId == nil { beego.Warning("User does not login.") cpc.CustomAbort(401, "please_login_first") } oldPassword := cpc.GetString("old_password") - queryUser := models.User{UserId: sessionUserId.(int), Username: sessionUsername.(string), Password: oldPassword} + if oldPassword == "" { + beego.Error("Old password is blank") + cpc.CustomAbort(400, "Old password is blank") + } + + queryUser := models.User{UserId: sessionUserId.(int), Password: oldPassword} user, err := dao.CheckUserPassword(queryUser) if err != nil { beego.Error("Error occurred in CheckUserPassword:", err) @@ -65,10 +69,14 @@ func (cpc *CommonController) UpdatePassword() { password := cpc.GetString("password") if password != "" { - updateUser := models.User{UserId: sessionUserId.(int), Username: sessionUsername.(string), Password: password, Salt: user.Salt} - dao.ChangeUserPassword(updateUser) + updateUser := models.User{UserId: sessionUserId.(int), Password: password, Salt: user.Salt} + err = dao.ChangeUserPassword(updateUser, oldPassword) + if err != nil { + beego.Error("Error occurred in ChangeUserPassword:", err) + cpc.CustomAbort(500, "Internal error.") + } } else { - cpc.CustomAbort(404, "please_input_new_password") + cpc.CustomAbort(400, "please_input_new_password") } } @@ -90,7 +98,11 @@ func (fpc *CommonController) SendEmail() { email := fpc.GetString("email") - if ok, _ := regexp.MatchString(`^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`, email); ok { + pass, _ := regexp.MatchString(`^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`, email) + + if !pass { + fpc.CustomAbort(400, "email_content_illegal") + } else { queryUser := models.User{Email: email} exist, err := dao.UserExists(queryUser, "email") @@ -152,8 +164,6 @@ func (fpc *CommonController) SendEmail() { user := models.User{ResetUuid: uuid, Email: email} dao.UpdateUserResetUuid(user) - } else { - fpc.CustomAbort(409, "email_content_illegal") } } @@ -164,8 +174,13 @@ type ResetPasswordController struct { func (rpc *ResetPasswordController) Get() { - q := rpc.GetString("q") - queryUser := models.User{ResetUuid: q} + resetUuid := rpc.GetString("reset_uuid") + if resetUuid == "" { + beego.Error("Reset uuid is blank.") + rpc.Redirect("/", 302) + } + + queryUser := models.User{ResetUuid: resetUuid} user, err := dao.GetUser(queryUser) if err != nil { beego.Error("Error occurred in GetUser:", err) @@ -183,6 +198,9 @@ func (rpc *ResetPasswordController) Get() { func (rpc *CommonController) ResetPassword() { resetUuid := rpc.GetString("reset_uuid") + if resetUuid == "" { + rpc.CustomAbort(400, "Reset uuid is blank.") + } queryUser := models.User{ResetUuid: resetUuid} user, err := dao.GetUser(queryUser) @@ -190,6 +208,10 @@ func (rpc *CommonController) ResetPassword() { beego.Error("Error occurred in GetUser:", err) rpc.CustomAbort(500, "Internal error.") } + if user == nil { + beego.Error("User does not exist") + rpc.CustomAbort(400, "User does not exist") + } password := rpc.GetString("password") @@ -197,6 +219,6 @@ func (rpc *CommonController) ResetPassword() { user.Password = password dao.ResetUserPassword(*user) } else { - rpc.CustomAbort(404, "password_is_required") + rpc.CustomAbort(400, "password_is_required") } } diff --git a/dao/user.go b/dao/user.go index e215712f4..085cddbe0 100644 --- a/dao/user.go +++ b/dao/user.go @@ -15,6 +15,8 @@ package dao import ( + "errors" + "github.com/vmware/harbor/models" "github.com/vmware/harbor/utils" @@ -133,15 +135,22 @@ func ToggleUserAdminRole(u models.User) error { return err } -func ChangeUserPassword(u models.User) error { +func ChangeUserPassword(u models.User, oldPassword string) error { o := orm.NewOrm() - _, err := o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() + _, err := o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword, u.Salt)).Exec() return err } func ResetUserPassword(u models.User) error { o := orm.NewOrm() - _, err := o.Raw(`update user set password=?, reset_uuid=? where reset_uuid=?`, utils.Encrypt(u.Password, u.Salt), "", u.ResetUuid).Exec() + r, err := o.Raw(`update user set password=?, reset_uuid=? where reset_uuid=?`, utils.Encrypt(u.Password, u.Salt), "", u.ResetUuid).Exec() + if err != nil { + return err + } + count, err := r.RowsAffected() + if count == 0 { + return errors.New("No record be changed.") + } return err } diff --git a/main.go b/main.go index 189cb8400..686b6a355 100644 --- a/main.go +++ b/main.go @@ -52,7 +52,7 @@ func updateInitPassword(userId int, password string) error { } user.Salt = salt user.Password = password - err = dao.ChangeUserPassword(*user) + err = dao.ChangeUserPassword(*user, password) if err != nil { log.Printf("Failed to update user encrypted password, userId: %d, err: %v", userId, err) return err diff --git a/views/reset-password-mail.tpl b/views/reset-password-mail.tpl index 35b9c6976..e79cdfddb 100644 --- a/views/reset-password-mail.tpl +++ b/views/reset-password-mail.tpl @@ -16,6 +16,6 @@

{{.Hint}}:

- {{.Url}}/resetPassword?q={{.Uuid}} + {{.Url}}/resetPassword?reset_uuid={{.Uuid}} \ No newline at end of file From 9bfb566f5e774d6f5592377a4be38edc1ba29a22 Mon Sep 17 00:00:00 2001 From: ywk253100 Date: Wed, 24 Feb 2016 10:30:13 +0800 Subject: [PATCH 09/15] Update Dockerfile --- Deploy/log/Dockerfile | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/Deploy/log/Dockerfile b/Deploy/log/Dockerfile index b7aaa2fc8..8d998367f 100644 --- a/Deploy/log/Dockerfile +++ b/Deploy/log/Dockerfile @@ -1,23 +1,19 @@ FROM library/ubuntu:14.04 -# run logrotate hourly -RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/ + +# run logrotate hourly, disable imklog model, provides TCP/UDP syslog reception +RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/ \ + && sed 's/$ModLoad imklog/#$ModLoad imklog/' -i /etc/rsyslog.conf \ + && sed 's/$KLogPermitNonKernelFacility on/#$KLogPermitNonKernelFacility on/' -i /etc/rsyslog.conf \ + && sed 's/#$ModLoad imudp/$ModLoad imudp/' -i /etc/rsyslog.conf \ + && sed 's/#$UDPServerRun 514/$UDPServerRun 514/' -i /etc/rsyslog.conf \ + && sed 's/#$ModLoad imtcp/$ModLoad imtcp/' -i /etc/rsyslog.conf \ + && sed 's/#$InputTCPServerRun 514/$InputTCPServerRun 514/' -i /etc/rsyslog.conf \ + && rm /etc/rsyslog.d/* # logrotate configuration file for docker ADD logrotate_docker.conf /etc/logrotate.d/ -#disable imklog model -RUN sed 's/$ModLoad imklog/#$ModLoad imklog/' -i /etc/rsyslog.conf -RUN sed 's/$KLogPermitNonKernelFacility on/#$KLogPermitNonKernelFacility on/' -i /etc/rsyslog.conf - -# provides TCP/UDP syslog reception -RUN sed 's/#$ModLoad imudp/$ModLoad imudp/' -i /etc/rsyslog.conf -RUN sed 's/#$UDPServerRun 514/$UDPServerRun 514/' -i /etc/rsyslog.conf -RUN sed 's/#$ModLoad imtcp/$ModLoad imtcp/' -i /etc/rsyslog.conf -RUN sed 's/#$InputTCPServerRun 514/$InputTCPServerRun 514/' -i /etc/rsyslog.conf - -RUN rm /etc/rsyslog.d/* - # rsyslog configuration file for docker ADD rsyslog_docker.conf /etc/rsyslog.d/ @@ -26,3 +22,4 @@ VOLUME /var/log/docker/ EXPOSE 514 CMD cron && chown -R syslog:syslog /var/log/docker/ && rsyslogd -n + From e58c137912f6575c2d12d45afec900b6e1764c80 Mon Sep 17 00:00:00 2001 From: ywk253100 Date: Wed, 24 Feb 2016 10:30:33 +0800 Subject: [PATCH 10/15] Update Dockerfile --- Deploy/log/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Deploy/log/Dockerfile b/Deploy/log/Dockerfile index 8d998367f..246746c6b 100644 --- a/Deploy/log/Dockerfile +++ b/Deploy/log/Dockerfile @@ -1,6 +1,5 @@ FROM library/ubuntu:14.04 - # run logrotate hourly, disable imklog model, provides TCP/UDP syslog reception RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/ \ && sed 's/$ModLoad imklog/#$ModLoad imklog/' -i /etc/rsyslog.conf \ From abd0695f8255a577e21c56c302a672e8e9bdf8f2 Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Wed, 24 Feb 2016 10:53:25 +0800 Subject: [PATCH 11/15] ut rework --- tests/dao_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/dao_test.go b/tests/dao_test.go index bbea5fc53..9a40b7753 100644 --- a/tests/dao_test.go +++ b/tests/dao_test.go @@ -105,7 +105,7 @@ func TestMain(m *testing.M) { } dbPort := os.Getenv("DB_PORT") if len(dbPort) == 0 { - log.Fatalf("environment variable DB_PWD is not set") + log.Fatalf("environment variable DB_PORT is not set") } dbPassword := os.Getenv("DB_PWD") if len(dbPassword) == 0 { @@ -390,8 +390,8 @@ func TestGetAccessLog(t *testing.T) { if len(accessLogs) != 1 { t.Errorf("The length of accesslog list should be 1, actual: %d", len(accessLogs)) } - if accessLogs[0].RepoName != PROJECT_NAME { - t.Errorf("The project name does not match, expected: %s, actual: %s", PROJECT_NAME, accessLogs[0].RepoName) + if accessLogs[0].RepoName != PROJECT_NAME+"/" { + t.Errorf("The project name does not match, expected: %s, actual: %s", PROJECT_NAME+"/", accessLogs[0].RepoName) } } From ea063c13dfb1dfa615e30a61d1a679f9433ea9c1 Mon Sep 17 00:00:00 2001 From: wknet123 Date: Wed, 24 Feb 2016 18:58:28 +0800 Subject: [PATCH 12/15] fixed no need to provide old password when initialization. --- dao/user.go | 12 ++++++++++-- main.go | 4 ++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dao/user.go b/dao/user.go index 085cddbe0..bddc90a67 100644 --- a/dao/user.go +++ b/dao/user.go @@ -135,9 +135,17 @@ func ToggleUserAdminRole(u models.User) error { return err } -func ChangeUserPassword(u models.User, oldPassword string) error { +func ChangeUserPassword(u models.User, oldPassword ...string) error { o := orm.NewOrm() - _, err := o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword, u.Salt)).Exec() + //In some cases, it may no need to check old password, just as Linux change password polies. + var err error + if len(oldPassword) == 0 { + _, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() + } else if len(oldPassword) == 1 { + _, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword[0], u.Salt)).Exec() + } else { + err = errors.New("Wrong numbers of params.") + } return err } diff --git a/main.go b/main.go index 686b6a355..17a00e069 100644 --- a/main.go +++ b/main.go @@ -38,7 +38,7 @@ func updateInitPassword(userId int, password string) error { queryUser := models.User{UserId: userId} user, err := dao.GetUser(queryUser) if err != nil { - log.Println("Failed to get user in initial password, userId:", userId) + log.Println("Failed to get user's initial password, userId:", userId) return err } if user == nil { @@ -52,7 +52,7 @@ func updateInitPassword(userId int, password string) error { } user.Salt = salt user.Password = password - err = dao.ChangeUserPassword(*user, password) + err = dao.ChangeUserPassword(*user) if err != nil { log.Printf("Failed to update user encrypted password, userId: %d, err: %v", userId, err) return err From be07274e331f6698c00cb3b0917a04a3bb98bac4 Mon Sep 17 00:00:00 2001 From: wknet123 Date: Wed, 24 Feb 2016 20:44:46 +0800 Subject: [PATCH 13/15] added checking affected count in changing password, added ut for changing password with old password. --- controllers/password.go | 6 +++++- dao/user.go | 16 +++++++++++----- main.go | 2 +- tests/dao_test.go | 15 +++++++++++++++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/controllers/password.go b/controllers/password.go index b0ab637e3..9ecc6d713 100644 --- a/controllers/password.go +++ b/controllers/password.go @@ -217,7 +217,11 @@ func (rpc *CommonController) ResetPassword() { if password != "" { user.Password = password - dao.ResetUserPassword(*user) + err = dao.ResetUserPassword(*user) + if err != nil { + beego.Error("Error occurred in ResetUserPassword:", err) + rpc.CustomAbort(500, "Internal error.") + } } else { rpc.CustomAbort(400, "password_is_required") } diff --git a/dao/user.go b/dao/user.go index bddc90a67..730b8f7e1 100644 --- a/dao/user.go +++ b/dao/user.go @@ -15,6 +15,7 @@ package dao import ( + "database/sql" "errors" "github.com/vmware/harbor/models" @@ -137,14 +138,19 @@ func ToggleUserAdminRole(u models.User) error { func ChangeUserPassword(u models.User, oldPassword ...string) error { o := orm.NewOrm() - //In some cases, it may no need to check old password, just as Linux change password polies. var err error + var r sql.Result if len(oldPassword) == 0 { - _, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() + //In some cases, it may no need to check old password, just as Linux change password policies. + r, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() } else if len(oldPassword) == 1 { - _, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword[0], u.Salt)).Exec() + r, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword[0], u.Salt)).Exec() } else { - err = errors.New("Wrong numbers of params.") + return errors.New("Wrong numbers of params.") + } + count, err := r.RowsAffected() + if count == 0 { + return errors.New("No record be changed, change password failed.") } return err } @@ -157,7 +163,7 @@ func ResetUserPassword(u models.User) error { } count, err := r.RowsAffected() if count == 0 { - return errors.New("No record be changed.") + return errors.New("No record be changed, reset password failed.") } return err } diff --git a/main.go b/main.go index d2a813237..531372297 100644 --- a/main.go +++ b/main.go @@ -38,7 +38,7 @@ func updateInitPassword(userId int, password string) error { queryUser := models.User{UserId: userId} user, err := dao.GetUser(queryUser) if err != nil { - log.Println("Failed to get user's initial password, userId:", userId) + log.Println("Failed to get user, userId:", userId) return err } if user == nil { diff --git a/tests/dao_test.go b/tests/dao_test.go index 9a40b7753..9abcecad0 100644 --- a/tests/dao_test.go +++ b/tests/dao_test.go @@ -300,6 +300,21 @@ func TestChangeUserPassword(t *testing.T) { } } +func TestChangeUserPasswordWithOldPassword(t *testing.T) { + err := dao.ChangeUserPassword(models.User{UserId: currentUser.UserId, Password: "NewerHarborTester12345", Salt: currentUser.Salt}, "NewHarborTester12345") + if err != nil { + t.Errorf("Error occurred in ChangeUserPassword: %v", err) + } + loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "NewerHarborTester12345"}) + if err != nil { + t.Errorf("Error occurred in LoginByDb: %v", err) + } + + if loginedUser.Username != USERNAME { + t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username) + } +} + func TestQueryRelevantProjectsWhenNoProjectAdded(t *testing.T) { projects, err := dao.QueryRelevantProjects(currentUser.UserId) if err != nil { From 273aea3c6d0232b3f47a8f38738416cb43132ad8 Mon Sep 17 00:00:00 2001 From: wknet123 Date: Wed, 24 Feb 2016 21:36:45 +0800 Subject: [PATCH 14/15] refined error check in changing and resetting password, added ut for changing password with incorrect old password. --- dao/user.go | 19 ++++++++++++++----- tests/dao_test.go | 18 +++++++++++++++++- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/dao/user.go b/dao/user.go index 730b8f7e1..a0a259cc5 100644 --- a/dao/user.go +++ b/dao/user.go @@ -142,16 +142,22 @@ func ChangeUserPassword(u models.User, oldPassword ...string) error { var r sql.Result if len(oldPassword) == 0 { //In some cases, it may no need to check old password, just as Linux change password policies. - r, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() + _, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId).Exec() } else if len(oldPassword) == 1 { r, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, u.Salt), u.Salt, u.UserId, utils.Encrypt(oldPassword[0], u.Salt)).Exec() + if err != nil { + return err + } + count, err := r.RowsAffected() + if err != nil { + return err + } + if count == 0 { + return errors.New("No record be changed, change password failed.") + } } else { return errors.New("Wrong numbers of params.") } - count, err := r.RowsAffected() - if count == 0 { - return errors.New("No record be changed, change password failed.") - } return err } @@ -162,6 +168,9 @@ func ResetUserPassword(u models.User) error { return err } count, err := r.RowsAffected() + if err != nil { + return err + } if count == 0 { return errors.New("No record be changed, reset password failed.") } diff --git a/tests/dao_test.go b/tests/dao_test.go index 9abcecad0..0179da876 100644 --- a/tests/dao_test.go +++ b/tests/dao_test.go @@ -15,6 +15,7 @@ package test import ( + "fmt" // "fmt" "log" "os" @@ -112,6 +113,8 @@ func TestMain(m *testing.M) { log.Fatalf("environment variable DB_PWD is not set") } + fmt.Printf("DB_HOST: %s, DB_USR: %s, DB_PORT: %s, DB_PWD: %s\n", dbHost, dbUser, dbPort, dbPassword) + os.Setenv("MYSQL_PORT_3306_TCP_ADDR", dbHost) os.Setenv("MYSQL_PORT_3306_TCP_PORT", dbPort) os.Setenv("MYSQL_USR", dbUser) @@ -309,12 +312,25 @@ func TestChangeUserPasswordWithOldPassword(t *testing.T) { if err != nil { t.Errorf("Error occurred in LoginByDb: %v", err) } - if loginedUser.Username != USERNAME { t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username) } } +func TestChangeUserPasswordWithIncorrectOldPassword(t *testing.T) { + err := dao.ChangeUserPassword(models.User{UserId: currentUser.UserId, Password: "NNewerHarborTester12345", Salt: currentUser.Salt}, "WrongNewerHarborTester12345") + if err == nil { + t.Errorf("Error does not occurred due to old password is incorrect.") + } + loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "NNewerHarborTester12345"}) + if err != nil { + t.Errorf("Error occurred in LoginByDb: %v", err) + } + if loginedUser != nil { + t.Errorf("The login user is not nil, acutal: %+v", loginedUser) + } +} + func TestQueryRelevantProjectsWhenNoProjectAdded(t *testing.T) { projects, err := dao.QueryRelevantProjects(currentUser.UserId) if err != nil { From ecedb882a1d5466108ddd4e0e834ddba3844e087 Mon Sep 17 00:00:00 2001 From: Tan Jiang Date: Wed, 24 Feb 2016 14:31:52 +0800 Subject: [PATCH 15/15] replace status codes with constants in net/http --- api/base.go | 8 +++--- api/project.go | 27 ++++++++++--------- api/project_member.go | 47 +++++++++++++++++---------------- api/repository.go | 19 ++++++------- api/search.go | 5 ++-- api/user.go | 27 ++++++++++--------- controllers/item_detail.go | 9 ++++--- controllers/login.go | 8 +++--- controllers/password.go | 47 +++++++++++++++++---------------- controllers/register.go | 7 ++--- service/auth.go | 5 ++-- service/utils/registry_utils.go | 6 ++--- utils/registry_utils.go | 6 ++--- 13 files changed, 116 insertions(+), 105 deletions(-) diff --git a/api/base.go b/api/base.go index 92578bb78..2262bb3ac 100644 --- a/api/base.go +++ b/api/base.go @@ -40,7 +40,7 @@ func (b *BaseAPI) DecodeJsonReq(v interface{}) { err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<32), v) if err != nil { beego.Error("Error while decoding the json request:", err) - b.CustomAbort(400, "Invalid json request") + b.CustomAbort(http.StatusBadRequest, "Invalid json request") } } @@ -49,17 +49,17 @@ func (b *BaseAPI) ValidateUser() int { sessionUserId := b.GetSession("userId") if sessionUserId == nil { beego.Warning("No user id in session, canceling request") - b.CustomAbort(401, "") + b.CustomAbort(http.StatusUnauthorized, "") } userId := sessionUserId.(int) u, err := dao.GetUser(models.User{UserId: userId}) if err != nil { beego.Error("Error occurred in GetUser:", err) - b.CustomAbort(500, "Internal error.") + b.CustomAbort(http.StatusInternalServerError, "Internal error.") } if u == nil { beego.Warning("User was deleted already, user id: ", userId, " canceling request.") - b.CustomAbort(401, "") + b.CustomAbort(http.StatusUnauthorized, "") } return userId } diff --git a/api/project.go b/api/project.go index 73fa4ae70..42944ef51 100644 --- a/api/project.go +++ b/api/project.go @@ -17,6 +17,7 @@ package api import ( "fmt" "log" + "net/http" "github.com/vmware/harbor/dao" "github.com/vmware/harbor/models" @@ -48,15 +49,15 @@ func (p *ProjectAPI) Prepare() { p.projectId, err = strconv.ParseInt(id_str, 10, 64) if err != nil { log.Printf("Error parsing project id: %s, error: %v", id_str, err) - p.CustomAbort(400, "invalid project id") + p.CustomAbort(http.StatusBadRequest, "invalid project id") } exist, err := dao.ProjectExists(p.projectId) if err != nil { log.Printf("Error occurred in ProjectExists: %v", err) - p.CustomAbort(500, "Internal error.") + p.CustomAbort(http.StatusInternalServerError, "Internal error.") } if !exist { - p.CustomAbort(404, fmt.Sprintf("project does not exist, id: %v", p.projectId)) + p.CustomAbort(http.StatusNotFound, fmt.Sprintf("project does not exist, id: %v", p.projectId)) } } } @@ -71,7 +72,7 @@ func (p *ProjectAPI) Post() { err := validateProjectReq(req) if err != nil { beego.Error("Invalid project request, error: ", err) - p.RenderError(400, "Invalid request for creating project") + p.RenderError(http.StatusBadRequest, "Invalid request for creating project") return } projectName := req.ProjectName @@ -80,14 +81,14 @@ func (p *ProjectAPI) Post() { beego.Error("Error happened checking project existence in db:", err, ", project name:", projectName) } if exist { - p.RenderError(409, "") + p.RenderError(http.StatusConflict, "") return } project := models.Project{OwnerId: p.userId, Name: projectName, CreationTime: time.Now(), Public: public} err = dao.AddProject(project) if err != nil { beego.Error("Failed to add project, error: %v", err) - p.RenderError(500, "Failed to add project") + p.RenderError(http.StatusInternalServerError, "Failed to add project") } } @@ -96,11 +97,11 @@ func (p *ProjectAPI) Head() { result, err := dao.ProjectExists(projectName) if err != nil { beego.Error("Error while communicating with DB: ", err) - p.RenderError(500, "Error while communicating with DB") + p.RenderError(http.StatusInternalServerError, "Error while communicating with DB") return } if !result { - p.RenderError(404, "") + p.RenderError(http.StatusNotFound, "") return } } @@ -117,7 +118,7 @@ func (p *ProjectAPI) Get() { projectList, err := dao.QueryProject(queryProject) if err != nil { beego.Error("Error occurred in QueryProject:", err) - p.CustomAbort(500, "Internal error.") + p.CustomAbort(http.StatusInternalServerError, "Internal error.") } for i := 0; i < len(projectList); i++ { if isProjectAdmin(p.userId, projectList[i].ProjectId) { @@ -135,7 +136,7 @@ func (p *ProjectAPI) Put() { projectId, err := strconv.ParseInt(p.Ctx.Input.Param(":id"), 10, 64) if err != nil { beego.Error("Error parsing project id:", projectId, ", error: ", err) - p.RenderError(400, "invalid project id") + p.RenderError(http.StatusBadRequest, "invalid project id") return } @@ -145,13 +146,13 @@ func (p *ProjectAPI) Put() { } if !isProjectAdmin(p.userId, projectId) { beego.Warning("Current user, id:", p.userId, ", does not have project admin role for project, id:", projectId) - p.RenderError(403, "") + p.RenderError(http.StatusForbidden, "") return } err = dao.ToggleProjectPublicity(p.projectId, public) if err != nil { beego.Error("Error while updating project, project id:", projectId, ", error:", err) - p.RenderError(500, "Failed to update project") + p.RenderError(http.StatusInternalServerError, "Failed to update project") } } @@ -173,7 +174,7 @@ func (p *ProjectAPI) FilterAccessLog() { accessLogList, err := dao.GetAccessLogs(query) if err != nil { log.Printf("Error occurred in GetAccessLogs: %v", err) - p.CustomAbort(500, "Internal error.") + p.CustomAbort(http.StatusInternalServerError, "Internal error.") } p.Data["json"] = accessLogList p.ServeJSON() diff --git a/api/project_member.go b/api/project_member.go index b387958e7..37185ad31 100644 --- a/api/project_member.go +++ b/api/project_member.go @@ -15,12 +15,13 @@ package api import ( + "net/http" + "strconv" + "github.com/vmware/harbor/dao" "github.com/vmware/harbor/models" "github.com/astaxie/beego" - - "strconv" ) type ProjectMemberAPI struct { @@ -40,18 +41,18 @@ func (pma *ProjectMemberAPI) Prepare() { pid, err := strconv.ParseInt(pma.Ctx.Input.Param(":pid"), 10, 64) if err != nil { beego.Error("Error parsing project id:", pid, ", error:", err) - pma.CustomAbort(400, "invalid project Id") + pma.CustomAbort(http.StatusBadRequest, "invalid project Id") return } p, err := dao.GetProjectById(models.Project{ProjectId: pid}) if err != nil { beego.Error("Error occurred in GetProjectById:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } if p == nil { beego.Warning("Project with id:", pid, "does not exist.") - pma.CustomAbort(404, "Project does not exist") + pma.CustomAbort(http.StatusNotFound, "Project does not exist") } pma.project = p pma.currentUserId = pma.ValidateUser() @@ -64,7 +65,7 @@ func (pma *ProjectMemberAPI) Prepare() { memberId, err := strconv.Atoi(mid) if err != nil { beego.Error("Invalid member Id, error:", err) - pma.CustomAbort(400, "Invalid member id") + pma.CustomAbort(http.StatusBadRequest, "Invalid member id") } pma.memberId = memberId } @@ -74,7 +75,7 @@ func (pma *ProjectMemberAPI) Get() { pid := pma.project.ProjectId if !CheckProjectPermission(pma.currentUserId, pid) { beego.Warning("Current user, user id :", pma.currentUserId, "does not have permission for project, id:", pid) - pma.RenderError(403, "") + pma.RenderError(http.StatusForbidden, "") return } if pma.memberId == 0 { //member id not set return list of the members @@ -84,7 +85,7 @@ func (pma *ProjectMemberAPI) Get() { userList, err := dao.GetUserByProject(queryProject, queryUser) if err != nil { beego.Error("Failed to query database for member list, error:", err) - pma.RenderError(500, "Internal Server Error") + pma.RenderError(http.StatusInternalServerError, "Internal Server Error") return } pma.Data["json"] = userList @@ -92,14 +93,14 @@ func (pma *ProjectMemberAPI) Get() { roleList, err := dao.GetUserProjectRoles(models.User{UserId: pma.memberId}, pid) if err != nil { beego.Error("Error occurred in GetUserProjectRoles:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } //return empty role list to indicate if a user is not a member result := make(map[string]interface{}) user, err := dao.GetUser(models.User{UserId: pma.memberId}) if err != nil { beego.Error("Error occurred in GetUser:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } result["user_name"] = user.Username result["user_id"] = pma.memberId @@ -115,11 +116,11 @@ func (pma *ProjectMemberAPI) Post() { rolelist, err := dao.GetUserProjectRoles(userQuery, pid) if err != nil { beego.Error("Error occurred in GetUserProjectRoles:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } if len(rolelist) == 0 { beego.Warning("Current user, id:", pma.currentUserId, "does not have project admin role for project, id:", pid) - pma.RenderError(403, "") + pma.RenderError(http.StatusForbidden, "") return } var req memberReq @@ -128,17 +129,17 @@ func (pma *ProjectMemberAPI) Post() { userId := CheckUserExists(username) if userId <= 0 { beego.Warning("User does not exist, user name:", username) - pma.RenderError(404, "User does not exist") + pma.RenderError(http.StatusNotFound, "User does not exist") return } rolelist, err = dao.GetUserProjectRoles(models.User{UserId: userId}, pid) if err != nil { beego.Error("Error occurred in GetUserProjectRoles:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } if len(rolelist) > 0 { beego.Warning("user is already added to project, user id:", userId, ", project id:", pid) - pma.RenderError(409, "user is ready in project") + pma.RenderError(http.StatusConflict, "user is ready in project") return } @@ -146,7 +147,7 @@ func (pma *ProjectMemberAPI) Post() { err = dao.AddUserProjectRole(userId, pid, int(rid)) if err != nil { beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", userId, ", role id:", rid) - pma.RenderError(500, "Failed to update data in database") + pma.RenderError(http.StatusInternalServerError, "Failed to update data in database") return } } @@ -159,11 +160,11 @@ func (pma *ProjectMemberAPI) Put() { rolelist, err := dao.GetUserProjectRoles(userQuery, pid) if err != nil { beego.Error("Error occurred in GetUserProjectRoles:", err) - pma.CustomAbort(500, "Internal error.") + pma.CustomAbort(http.StatusInternalServerError, "Internal error.") } if len(rolelist) == 0 { beego.Warning("Current user, id:", pma.currentUserId, ", does not have project admin role for project, id:", pid) - pma.RenderError(403, "") + pma.RenderError(http.StatusForbidden, "") return } var req memberReq @@ -171,7 +172,7 @@ func (pma *ProjectMemberAPI) Put() { roleList, err := dao.GetUserProjectRoles(models.User{UserId: mid}, pid) if len(roleList) == 0 { beego.Warning("User is not in project, user id:", mid, ", project id:", pid) - pma.RenderError(404, "user not exist in project") + pma.RenderError(http.StatusNotFound, "user not exist in project") return } //TODO: delete and insert should in one transaction @@ -179,7 +180,7 @@ func (pma *ProjectMemberAPI) Put() { err = dao.DeleteUserProjectRoles(mid, pid) if err != nil { beego.Error("Failed to delete project roles for user, user id:", mid, ", project id: ", pid, ", error: ", err) - pma.RenderError(500, "Failed to update data in DB") + pma.RenderError(http.StatusInternalServerError, "Failed to update data in DB") return } //insert roles in request @@ -187,7 +188,7 @@ func (pma *ProjectMemberAPI) Put() { err = dao.AddUserProjectRole(mid, pid, int(rid)) if err != nil { beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", mid, ", role id:", rid) - pma.RenderError(500, "Failed to update data in database") + pma.RenderError(http.StatusInternalServerError, "Failed to update data in database") return } } @@ -200,13 +201,13 @@ func (pma *ProjectMemberAPI) Delete() { rolelist, err := dao.GetUserProjectRoles(userQuery, pid) if len(rolelist) == 0 { beego.Warning("Current user, id:", pma.currentUserId, ", does not have project admin role for project, id:", pid) - pma.RenderError(403, "") + pma.RenderError(http.StatusForbidden, "") return } err = dao.DeleteUserProjectRoles(mid, pid) if err != nil { beego.Error("Failed to delete project roles for user, user id:", mid, ", project id:", pid, ", error:", err) - pma.RenderError(500, "Failed to update data in DB") + pma.RenderError(http.StatusInternalServerError, "Failed to update data in DB") return } } diff --git a/api/repository.go b/api/repository.go index 284a73515..918724638 100644 --- a/api/repository.go +++ b/api/repository.go @@ -16,6 +16,7 @@ package api import ( "encoding/json" + "net/http" "strconv" "strings" "time" @@ -56,28 +57,28 @@ func (ra *RepositoryAPI) Get() { projectId, err0 := ra.GetInt64("project_id") if err0 != nil { beego.Error("Failed to get project id, error:", err0) - ra.RenderError(400, "Invalid project id") + ra.RenderError(http.StatusBadRequest, "Invalid project id") return } projectQuery := models.Project{ProjectId: projectId} p, err := dao.GetProjectById(projectQuery) if err != nil { beego.Error("Error occurred in GetProjectById:", err) - ra.CustomAbort(500, "Internal error.") + ra.CustomAbort(http.StatusInternalServerError, "Internal error.") } if p == nil { beego.Warning("Project with Id:", projectId, ", does not exist", projectId) - ra.RenderError(404, "") + ra.RenderError(http.StatusNotFound, "") return } if p.Public == 0 && !CheckProjectPermission(ra.userId, projectId) { - ra.RenderError(403, "") + ra.RenderError(http.StatusForbidden, "") return } repoList, err := svc_utils.GetRepoFromCache() if err != nil { beego.Error("Failed to get repo from cache, error:", err) - ra.RenderError(500, "internal sever error") + ra.RenderError(http.StatusInternalServerError, "internal sever error") } projectName := p.Name q := ra.GetString("q") @@ -127,7 +128,7 @@ func (ra *RepositoryAPI) GetTags() { result, err := svc_utils.RegistryApiGet(svc_utils.BuildRegistryUrl(repoName, "tags", "list"), ra.username) if err != nil { beego.Error("Failed to get repo tags, repo name:", repoName, ", error: ", err) - ra.RenderError(500, "Failed to get repo tags") + ra.RenderError(http.StatusInternalServerError, "Failed to get repo tags") } else { t := Tag{} json.Unmarshal(result, &t) @@ -146,14 +147,14 @@ func (ra *RepositoryAPI) GetManifests() { result, err := svc_utils.RegistryApiGet(svc_utils.BuildRegistryUrl(repoName, "manifests", tag), ra.username) if err != nil { beego.Error("Failed to get manifests for repo, repo name:", repoName, ", tag:", tag, ", error:", err) - ra.RenderError(500, "Internal Server Error") + ra.RenderError(http.StatusInternalServerError, "Internal Server Error") return } else { mani := Manifest{} err = json.Unmarshal(result, &mani) if err != nil { beego.Error("Failed to decode json from response for manifests, repo name:", repoName, ", tag:", tag, ", error:", err) - ra.RenderError(500, "Internal Server Error") + ra.RenderError(http.StatusInternalServerError, "Internal Server Error") return } else { v1Compatibility := mani.History[0].V1Compatibility @@ -161,7 +162,7 @@ func (ra *RepositoryAPI) GetManifests() { err = json.Unmarshal([]byte(v1Compatibility), &item) if err != nil { beego.Error("Failed to decode V1 field for repo, repo name:", repoName, ", tag:", tag, ", error:", err) - ra.RenderError(500, "Internal Server Error") + ra.RenderError(http.StatusInternalServerError, "Internal Server Error") return } else { item.CreatedStr = item.Created.Format("2006-01-02 15:04:05") diff --git a/api/search.go b/api/search.go index 805647596..e0d7348bc 100644 --- a/api/search.go +++ b/api/search.go @@ -15,6 +15,7 @@ package api import ( + "net/http" "sort" "strings" @@ -44,7 +45,7 @@ func (n *SearchAPI) Get() { projects, err := dao.QueryRelevantProjects(userId) if err != nil { beego.Error("Failed to get projects of user id:", userId, ", error:", err) - n.CustomAbort(500, "Failed to get project search result") + n.CustomAbort(http.StatusInternalServerError, "Failed to get project search result") } projectSorter := &utils.ProjectSorter{Projects: projects} sort.Sort(projectSorter) @@ -66,7 +67,7 @@ func (n *SearchAPI) Get() { repositories, err2 := svc_utils.GetRepoFromCache() if err2 != nil { beego.Error("Failed to get repos from cache, error :", err2) - n.CustomAbort(500, "Failed to get repositories search result") + n.CustomAbort(http.StatusInternalServerError, "Failed to get repositories search result") } sort.Strings(repositories) repositoryResult := filterRepositories(repositories, projects, keyword) diff --git a/api/user.go b/api/user.go index 2df9bf454..1c3fcbc13 100644 --- a/api/user.go +++ b/api/user.go @@ -15,6 +15,7 @@ package api import ( + "net/http" "strconv" "github.com/vmware/harbor/dao" @@ -40,17 +41,17 @@ func (ua *UserAPI) Prepare() { ua.userId, err = strconv.Atoi(id) if err != nil { beego.Error("Invalid user id, error:", err) - ua.CustomAbort(400, "Invalid user Id") + ua.CustomAbort(http.StatusBadRequest, "Invalid user Id") } userQuery := models.User{UserId: ua.userId} u, err := dao.GetUser(userQuery) if err != nil { beego.Error("Error occurred in GetUser:", err) - ua.CustomAbort(500, "Internal error.") + ua.CustomAbort(http.StatusInternalServerError, "Internal error.") } if u == nil { beego.Error("User with Id:", ua.userId, "does not exist") - ua.CustomAbort(404, "") + ua.CustomAbort(http.StatusNotFound, "") } } } @@ -59,13 +60,13 @@ func (ua *UserAPI) Get() { exist, err := dao.IsAdminRole(ua.currentUid) if err != nil { beego.Error("Error occurred in IsAdminRole:", err) - ua.CustomAbort(500, "Internal error.") + ua.CustomAbort(http.StatusInternalServerError, "Internal error.") } if ua.userId == 0 { //list users if !exist { beego.Error("Current user, id:", ua.currentUid, ", does not have admin role, can not list users") - ua.RenderError(403, "User does not have admin role") + ua.RenderError(http.StatusForbidden, "User does not have admin role") return } username := ua.GetString("username") @@ -76,7 +77,7 @@ func (ua *UserAPI) Get() { userList, err := dao.ListUsers(userQuery) if err != nil { beego.Error("Failed to get data from database, error:", err) - ua.RenderError(500, "Failed to query from database") + ua.RenderError(http.StatusInternalServerError, "Failed to query from database") return } ua.Data["json"] = userList @@ -86,12 +87,12 @@ func (ua *UserAPI) Get() { u, err := dao.GetUser(userQuery) if err != nil { beego.Error("Error occurred in GetUser:", err) - ua.CustomAbort(500, "Internal error.") + ua.CustomAbort(http.StatusInternalServerError, "Internal error.") } ua.Data["json"] = u } else { beego.Error("Current user, id:", ua.currentUid, "does not have admin role, can not view other user's detail") - ua.RenderError(403, "User does not have admin role") + ua.RenderError(http.StatusForbidden, "User does not have admin role") return } ua.ServeJSON() @@ -101,11 +102,11 @@ func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body exist, err := dao.IsAdminRole(ua.currentUid) if err != nil { beego.Error("Error occurred in IsAdminRole:", err) - ua.CustomAbort(500, "Internal error.") + ua.CustomAbort(http.StatusInternalServerError, "Internal error.") } if !exist { beego.Warning("current user, id:", ua.currentUid, ", does not have admin role, can not update other user's role") - ua.RenderError(403, "User does not have admin role") + ua.RenderError(http.StatusForbidden, "User does not have admin role") return } userQuery := models.User{UserId: ua.userId} @@ -116,17 +117,17 @@ func (ua *UserAPI) Delete() { exist, err := dao.IsAdminRole(ua.currentUid) if err != nil { beego.Error("Error occurred in IsAdminRole:", err) - ua.CustomAbort(500, "Internal error.") + ua.CustomAbort(http.StatusInternalServerError, "Internal error.") } if !exist { beego.Warning("current user, id:", ua.currentUid, ", does not have admin role, can not remove user") - ua.RenderError(403, "User does not have admin role") + ua.RenderError(http.StatusForbidden, "User does not have admin role") return } err = dao.DeleteUser(ua.userId) if err != nil { beego.Error("Failed to delete data from database, error:", err) - ua.RenderError(500, "Failed to delete User") + ua.RenderError(http.StatusInternalServerError, "Failed to delete User") return } } diff --git a/controllers/item_detail.go b/controllers/item_detail.go index 391fbc04e..34761fce4 100644 --- a/controllers/item_detail.go +++ b/controllers/item_detail.go @@ -15,6 +15,7 @@ package controllers import ( + "net/http" "net/url" "os" @@ -68,7 +69,7 @@ func (idc *ItemDetailController) Get() { projectId, _ := idc.GetInt64("project_id") if CheckPublicProject(projectId) == false && (sessionUserId == nil || !CheckProjectRole(sessionUserId.(int), projectId)) { - idc.Redirect("/signIn?uri="+url.QueryEscape(idc.Ctx.Input.URI()), 302) + idc.Redirect("/signIn?uri="+url.QueryEscape(idc.Ctx.Input.URI()), http.StatusFound) } projectQuery := models.Project{ProjectId: projectId} @@ -76,11 +77,11 @@ func (idc *ItemDetailController) Get() { if err != nil { beego.Error("Error occurred in GetProjectById:", err) - idc.CustomAbort(500, "Internal error.") + idc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if project == nil { - idc.Redirect("/signIn", 302) + idc.Redirect("/signIn", http.StatusFound) } idc.Data["ProjectId"] = project.ProjectId @@ -94,7 +95,7 @@ func (idc *ItemDetailController) Get() { roleList, err := dao.GetUserProjectRoles(models.User{UserId: sessionUserId.(int)}, projectId) if err != nil { beego.Error("Error occurred in GetUserProjectRoles:", err) - idc.CustomAbort(500, "Internal error.") + idc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if len(roleList) > 0 { idc.Data["RoleId"] = roleList[0].RoleId diff --git a/controllers/login.go b/controllers/login.go index d907018d4..0839e483b 100644 --- a/controllers/login.go +++ b/controllers/login.go @@ -15,6 +15,8 @@ package controllers import ( + "net/http" + "github.com/vmware/harbor/models" "github.com/vmware/harbor/opt_auth" @@ -45,11 +47,11 @@ func (c *CommonController) Login() { user, err := opt_auth.Login(models.AuthModel{principal, password}) if err != nil { beego.Error("Error occurred in UserLogin:", err) - c.CustomAbort(500, "Internal error.") + c.CustomAbort(http.StatusInternalServerError, "Internal error.") } if user == nil { - c.CustomAbort(401, "") + c.CustomAbort(http.StatusUnauthorized, "") } c.SetSession("userId", user.UserId) @@ -62,7 +64,7 @@ func (c *CommonController) SwitchLanguage() { c.SetSession("lang", lang) c.Data["Lang"] = lang } - c.Redirect(c.Ctx.Request.Header.Get("Referer"), 302) + c.Redirect(c.Ctx.Request.Header.Get("Referer"), http.StatusFound) } func (c *CommonController) Logout() { diff --git a/controllers/password.go b/controllers/password.go index 9ecc6d713..aede09a0d 100644 --- a/controllers/password.go +++ b/controllers/password.go @@ -16,6 +16,7 @@ package controllers import ( "bytes" + "net/http" "os" "regexp" "text/template" @@ -34,7 +35,7 @@ type ChangePasswordController struct { func (cpc *ChangePasswordController) Get() { sessionUserId := cpc.GetSession("userId") if sessionUserId == nil { - cpc.Redirect("/signIn", 302) + cpc.Redirect("/signIn", http.StatusFound) } cpc.Data["Username"] = cpc.GetSession("username") cpc.ForwardTo("page_title_change_password", "change-password") @@ -46,25 +47,25 @@ func (cpc *CommonController) UpdatePassword() { if sessionUserId == nil { beego.Warning("User does not login.") - cpc.CustomAbort(401, "please_login_first") + cpc.CustomAbort(http.StatusUnauthorized, "please_login_first") } oldPassword := cpc.GetString("old_password") if oldPassword == "" { beego.Error("Old password is blank") - cpc.CustomAbort(400, "Old password is blank") + cpc.CustomAbort(http.StatusBadRequest, "Old password is blank") } queryUser := models.User{UserId: sessionUserId.(int), Password: oldPassword} user, err := dao.CheckUserPassword(queryUser) if err != nil { beego.Error("Error occurred in CheckUserPassword:", err) - cpc.CustomAbort(500, "Internal error.") + cpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if user == nil { beego.Warning("Password input is not correct") - cpc.CustomAbort(403, "old_password_is_not_correct") + cpc.CustomAbort(http.StatusForbidden, "old_password_is_not_correct") } password := cpc.GetString("password") @@ -73,10 +74,10 @@ func (cpc *CommonController) UpdatePassword() { err = dao.ChangeUserPassword(updateUser, oldPassword) if err != nil { beego.Error("Error occurred in ChangeUserPassword:", err) - cpc.CustomAbort(500, "Internal error.") + cpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } } else { - cpc.CustomAbort(400, "please_input_new_password") + cpc.CustomAbort(http.StatusBadRequest, "please_input_new_password") } } @@ -101,23 +102,23 @@ func (fpc *CommonController) SendEmail() { pass, _ := regexp.MatchString(`^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`, email) if !pass { - fpc.CustomAbort(400, "email_content_illegal") + fpc.CustomAbort(http.StatusBadRequest, "email_content_illegal") } else { queryUser := models.User{Email: email} exist, err := dao.UserExists(queryUser, "email") if err != nil { beego.Error("Error occurred in UserExists:", err) - fpc.CustomAbort(500, "Internal error.") + fpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if !exist { - fpc.CustomAbort(404, "email_does_not_exist") + fpc.CustomAbort(http.StatusNotFound, "email_does_not_exist") } messageTemplate, err := template.ParseFiles("views/reset-password-mail.tpl") if err != nil { beego.Error("Parse email template file failed:", err) - fpc.CustomAbort(500, err.Error()) + fpc.CustomAbort(http.StatusInternalServerError, err.Error()) } message := new(bytes.Buffer) @@ -129,7 +130,7 @@ func (fpc *CommonController) SendEmail() { uuid, err := dao.GenerateRandomString() if err != nil { beego.Error("Error occurred in GenerateRandomString:", err) - fpc.CustomAbort(500, "Internal error.") + fpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } err = messageTemplate.Execute(message, MessageDetail{ Hint: fpc.Tr("reset_email_hint"), @@ -139,13 +140,13 @@ func (fpc *CommonController) SendEmail() { if err != nil { beego.Error("message template error:", err) - fpc.CustomAbort(500, "internal_error") + fpc.CustomAbort(http.StatusInternalServerError, "internal_error") } config, err := beego.AppConfig.GetSection("mail") if err != nil { beego.Error("Can not load app.conf:", err) - fpc.CustomAbort(500, "internal_error") + fpc.CustomAbort(http.StatusInternalServerError, "internal_error") } mail := utils.Mail{ @@ -158,7 +159,7 @@ func (fpc *CommonController) SendEmail() { if err != nil { beego.Error("send email failed:", err) - fpc.CustomAbort(500, "send_email_failed") + fpc.CustomAbort(http.StatusInternalServerError, "send_email_failed") } user := models.User{ResetUuid: uuid, Email: email} @@ -177,21 +178,21 @@ func (rpc *ResetPasswordController) Get() { resetUuid := rpc.GetString("reset_uuid") if resetUuid == "" { beego.Error("Reset uuid is blank.") - rpc.Redirect("/", 302) + rpc.Redirect("/", http.StatusFound) } queryUser := models.User{ResetUuid: resetUuid} user, err := dao.GetUser(queryUser) if err != nil { beego.Error("Error occurred in GetUser:", err) - rpc.CustomAbort(500, "Internal error.") + rpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if user != nil { rpc.Data["ResetUuid"] = user.ResetUuid rpc.ForwardTo("page_title_reset_password", "reset-password") } else { - rpc.Redirect("/", 302) + rpc.Redirect("/", http.StatusFound) } } @@ -199,18 +200,18 @@ func (rpc *CommonController) ResetPassword() { resetUuid := rpc.GetString("reset_uuid") if resetUuid == "" { - rpc.CustomAbort(400, "Reset uuid is blank.") + rpc.CustomAbort(http.StatusBadRequest, "Reset uuid is blank.") } queryUser := models.User{ResetUuid: resetUuid} user, err := dao.GetUser(queryUser) if err != nil { beego.Error("Error occurred in GetUser:", err) - rpc.CustomAbort(500, "Internal error.") + rpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } if user == nil { beego.Error("User does not exist") - rpc.CustomAbort(400, "User does not exist") + rpc.CustomAbort(http.StatusBadRequest, "User does not exist") } password := rpc.GetString("password") @@ -220,9 +221,9 @@ func (rpc *CommonController) ResetPassword() { err = dao.ResetUserPassword(*user) if err != nil { beego.Error("Error occurred in ResetUserPassword:", err) - rpc.CustomAbort(500, "Internal error.") + rpc.CustomAbort(http.StatusInternalServerError, "Internal error.") } } else { - rpc.CustomAbort(400, "password_is_required") + rpc.CustomAbort(http.StatusBadRequest, "password_is_required") } } diff --git a/controllers/register.go b/controllers/register.go index 244770419..7f8553ae5 100644 --- a/controllers/register.go +++ b/controllers/register.go @@ -15,6 +15,7 @@ package controllers import ( + "net/http" "os" "strings" @@ -33,7 +34,7 @@ func (rc *RegisterController) Get() { if authMode == "" || authMode == "db_auth" { rc.ForwardTo("page_title_registration", "register") } else { - rc.Redirect("/signIn", 404) + rc.Redirect("/signIn", http.StatusNotFound) } } @@ -49,7 +50,7 @@ func (rc *CommonController) SignUp() { _, err := dao.Register(user) if err != nil { beego.Error("Error occurred in Register:", err) - rc.CustomAbort(500, "Internal error.") + rc.CustomAbort(http.StatusInternalServerError, "Internal error.") } } @@ -68,7 +69,7 @@ func (rc *CommonController) UserExists() { exist, err := dao.UserExists(user, target) if err != nil { beego.Error("Error occurred in UserExists:", err) - rc.CustomAbort(500, "Internal error.") + rc.CustomAbort(http.StatusInternalServerError, "Internal error.") } rc.Data["json"] = exist rc.ServeJSON() diff --git a/service/auth.go b/service/auth.go index f405ee9ce..bfa3dfd68 100644 --- a/service/auth.go +++ b/service/auth.go @@ -16,6 +16,7 @@ package service import ( "log" + "net/http" "github.com/vmware/harbor/models" "github.com/vmware/harbor/opt_auth" @@ -46,7 +47,7 @@ func (a *AuthController) Auth() { if len(scope) == 0 && !authenticated { log.Printf("login request with invalid credentials") - a.CustomAbort(401, "") + a.CustomAbort(http.StatusUnauthorized, "") } access := svc_utils.GetResourceActions(scope) for _, a := range access { @@ -61,7 +62,7 @@ func (a *AuthController) serveToken(username, service string, access []*token.Re rawToken, err := svc_utils.MakeToken(username, service, access) if err != nil { log.Printf("Failed to make token, error: %v", err) - writer.WriteHeader(500) + writer.WriteHeader(http.StatusInternalServerError) return } tk := make(map[string]string) diff --git a/service/utils/registry_utils.go b/service/utils/registry_utils.go index 8c8892d5b..aa5def9e6 100644 --- a/service/utils/registry_utils.go +++ b/service/utils/registry_utils.go @@ -50,9 +50,9 @@ func RegistryApiGet(url, username string) ([]byte, error) { return nil, err } defer response.Body.Close() - if response.StatusCode == 200 { + if response.StatusCode == http.StatusOK { return result, nil - } else if response.StatusCode == 401 { + } else if response.StatusCode == http.StatusUnauthorized { authenticate := response.Header.Get("WWW-Authenticate") str := strings.Split(authenticate, " ")[1] log.Println("url: " + url) @@ -94,7 +94,7 @@ func RegistryApiGet(url, username string) ([]byte, error) { if err != nil { return nil, err } - if response.StatusCode != 200 { + if response.StatusCode != http.StatusOK { errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode) log.Printf(errMsg) return nil, fmt.Errorf(errMsg) diff --git a/utils/registry_utils.go b/utils/registry_utils.go index 22e1fe455..13f989a2e 100644 --- a/utils/registry_utils.go +++ b/utils/registry_utils.go @@ -55,9 +55,9 @@ func HttpGet(url, sessionId, username, password string) ([]byte, error) { return nil, err } defer response.Body.Close() - if response.StatusCode == 200 { + if response.StatusCode == http.StatusOK { return result, nil - } else if response.StatusCode == 401 { + } else if response.StatusCode == http.StatusUnauthorized { authenticate := response.Header.Get("WWW-Authenticate") str := strings.Split(authenticate, " ")[1] beego.Trace("url: " + url) @@ -106,7 +106,7 @@ func HttpGet(url, sessionId, username, password string) ([]byte, error) { if err != nil { return nil, err } - if response.StatusCode == 200 { + if response.StatusCode == http.StatusOK { tt := make(map[string]string) json.Unmarshal(result, &tt) request, err = http.NewRequest("GET", url, nil)