Merge remote-tracking branch 'hupstream/dev' into dev

This commit is contained in:
Henry Zhang 2016-10-25 22:37:26 +08:00
commit 4653f48a8f
25 changed files with 291 additions and 113 deletions

21
.gitignore vendored
View File

@ -1,13 +1,14 @@
harbor
Deploy/config/registry/config.yml
Deploy/config/ui/env
Deploy/config/ui/app.conf
Deploy/config/db/env
Deploy/config/jobservice/env
Deploy/config/nginx/nginx.conf
Deploy/config/nginx/cert/*
Deploy/ui/harbor_ui
Deploy/jobservice/harbor_jobservice
ui/ui
make/common/config/registry/config.yml
make/common/config/ui/env
make/common/config/ui/app.conf
make/common/config/db/env
make/common/config/jobservice/env
make/common/config/nginx/nginx.conf
make/common/config/nginx/cert/*
make/dev/ui/harbor_ui
make/dev//jobservice/harbor_jobservice
src/ui/ui
src/jobservice/jobservice
*.pyc
jobservice/test

View File

@ -28,7 +28,6 @@
# for example: make package_online -e \
# REGISTRYSERVER=reg-bj.eng.vmware.com \
# REGISTRYPROJECTNAME=harborrelease
# note**: DONT add "/" on end of REGISTRYSERVER.
#
# package_offline:
# prepare offline install package
@ -62,6 +61,9 @@
# note**: If commit new code to github, the git commit TAG will \
# change. Better use this commond clean previous images and \
# files with specific TAG.
# By default DEVFLAG=true, if you want to release new version of Harbor, \
# should setting the flag to false.
# make XXXX -e DEVFLAG=flase
SHELL := /bin/bash
BUILDPATH=$(CURDIR)
@ -75,6 +77,7 @@ BASEIMAGE=photon
COMPILETAG=compile_normal
REGISTRYSERVER=
REGISTRYPROJECTNAME=vmware
DEVFLAG=true
# docker parameters
DOCKERCMD=$(shell which docker)
@ -96,11 +99,13 @@ GODEP=$(GOTEST) -i
GOFMT=gofmt -w
GOBUILDIMAGE=reg.mydomain.com/library/harborgo[:tag]
GOBUILDPATH=$(GOBASEPATH)/harbor
GOBUILDPATH_UI=$(GOBUILDPATH)/ui
GOBUILDPATH_JOBSERVICE=$(GOBUILDPATH)/jobservice
GOIMAGEBUILDCMD=/usr/local/go/bin/go
GOIMAGEBUILD=$(GOIMAGEBUILDCMD) build
GOBUILDPATH_UI=$(GOBUILDPATH)/src/ui
GOBUILDPATH_JOBSERVICE=$(GOBUILDPATH)/src/jobservice
GOBUILDMAKEPATH=$(GOBUILDPATH)/make
GOBUILDMAKEPATH_UI=$(GOBUILDMAKEPATH)/ui
GOBUILDMAKEPATH_JOBSERVICE=$(GOBUILDMAKEPATH)/jobservice
GOBUILDMAKEPATH_UI=$(GOBUILDMAKEPATH)/dev/ui
GOBUILDMAKEPATH_JOBSERVICE=$(GOBUILDMAKEPATH)/dev/jobservice
# binary
UISOURCECODE=$(SRCPATH)/ui
@ -128,10 +133,10 @@ DOCKERFILEPATH_DB=$(DOCKERFILEPATH_COMMON)/db
DOCKERFILENAME_DB=Dockerfile
# docker image name
DOCKERIMAGENAME_UI=$(REGISTRYPROJECTNAME)/harbor-ui
DOCKERIMAGENAME_JOBSERVICE=$(REGISTRYPROJECTNAME)/harbor-jobservice
DOCKERIMAGENAME_LOG=$(REGISTRYPROJECTNAME)/harbor-log
DOCKERIMAGENAME_DB=$(REGISTRYPROJECTNAME)/harbor-db
DOCKERIMAGENAME_UI=vmware/harbor-ui
DOCKERIMAGENAME_JOBSERVICE=vmware/harbor-jobservice
DOCKERIMAGENAME_LOG=vmware/harbor-log
DOCKERIMAGENAME_DB=vmware/harbor-db
# docker-compose files
@ -143,7 +148,12 @@ VERSIONFILEPATH=$(SRCPATH)/ui/views/sections
VERSIONFILENAME=header-content.htm
GITCMD=$(shell which git)
GITTAG=$(GITCMD) describe --tags
VERSIONTAG=$(shell $(GITTAG))
ifeq ($(DEVFLAG), true)
VERSIONTAG=dev
else
VERSIONTAG=$(shell $(GITTAG))
endif
SEDCMD=$(shell which sed)
# package
@ -186,11 +196,11 @@ compile_golangimage:
@echo "compiling binary for ui (golang image)..."
@echo $(GOBASEPATH)
@echo $(GOBUILDPATH)
$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_UI) $(GOBUILDIMAGE) $(GOBUILD) -v -o $(GOBUILDMAKEPATH_UI)/$(UIBINARYNAME)
$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_UI) $(GOBUILDIMAGE) $(GOIMAGEBUILD) -v -o $(GOBUILDMAKEPATH_UI)/$(UIBINARYNAME)
@echo "Done."
@echo "compiling binary for jobservice (golang image)..."
$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_JOBSERVICE) $(GOBUILDIMAGE) $(GOBUILD) -v -o $(GOBUILDMAKEPATH_JOBSERVICE)/$(JOBSERVICEBINARYNAME)
$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_JOBSERVICE) $(GOBUILDIMAGE) $(GOIMAGEBUILD) -v -o $(GOBUILDMAKEPATH_JOBSERVICE)/$(JOBSERVICEBINARYNAME)
@echo "Done."
compile:check_environment $(COMPILETAG)
@ -209,10 +219,10 @@ build_common: prepare version
$(DOCKERPULL) nginx:1.9
build_photon: build_common
make -f $(MAKEFILEPATH_PHOTON)/Makefile build
make -f $(MAKEFILEPATH_PHOTON)/Makefile build -e DEVFLAG=$(DEVFLAG)
build_ubuntu: build_common
make -f $(MAKEFILEPATH_UBUNTU)/Makefile build
make -f $(MAKEFILEPATH_UBUNTU)/Makefile build -e DEVFLAG=$(DEVFLAG)
build: build_$(BASEIMAGE)
@ -230,8 +240,10 @@ install: compile build modify_composefile
package_online: modify_composefile
@echo "packing online package ..."
@cp -r make $(HARBORPKG)
@$(SEDCMD) -i 's/image\: vmware/image\: $(REGISTRYSERVER)\/$(REGISTRYPROJECTNAME)/' $(HARBORPKG)/docker-compose.$(VERSIONTAG).yml
@if [ -n "$(REGISTRYSERVER)" ] ; then \
$(SEDCMD) -i 's/image\: vmware/image\: $(REGISTRYSERVER)\/$(REGISTRYPROJECTNAME)/' \
$(HARBORPKG)/docker-compose.$(VERSIONTAG).yml ; \
fi
@cp LICENSE $(HARBORPKG)/LICENSE
@cp NOTICE $(HARBORPKG)/NOTICE
@$(TARCMD) -zcvf harbor-online-installer-$(VERSIONTAG).tgz \
@ -258,7 +270,7 @@ package_offline: compile build modify_composefile
$(DOCKERIMAGENAME_LOG):$(VERSIONTAG) \
$(DOCKERIMAGENAME_DB):$(VERSIONTAG) \
$(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) \
nginx:1.9.0 registry:2.5.0
nginx:1.9 registry:2.5.0
@$(TARCMD) -zcvf harbor-offline-installer-$(VERSIONTAG).tgz \
--exclude=$(HARBORPKG)/common/db --exclude=$(HARBORPKG)/ubuntu \
@ -274,10 +286,10 @@ package_offline: compile build modify_composefile
pushimage:
@echo "pushing harbor images ..."
@$(DOCKERTAG) $(DOCKERIMAGENAME_UI):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG)
@$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG) \
$(DOCKERTAG) $(DOCKERIMAGENAME_UI):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG)
$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG) \
$(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER)
@$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG)
$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_UI):$(VERSIONTAG)
@$(DOCKERTAG) $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG)
@$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) \
@ -315,8 +327,8 @@ cleanimage:
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_DB):$(VERSIONTAG)
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG)
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_LOG):$(VERSIONTAG)
- $(DOCKERRMIMAGE) -f registry:2.5.0
- $(DOCKERRMIMAGE) -f nginx:1.9
#- $(DOCKERRMIMAGE) -f registry:2.5.0
#- $(DOCKERRMIMAGE) -f nginx:1.9
cleandockercomposefile:
@echo "cleaning $(DOCKERCOMPOSEFILEPATH)/docker-compose.$(VERSIONTAG).yml"
@ -333,9 +345,17 @@ cleanpackage:
then rm $(BUILDPATH)/harbor-online-installer-$(VERSIONTAG).tgz ; fi
@if [ -f $(BUILDPATH)/harbor-offline-installer-$(VERSIONTAG).tgz ] ; \
then rm $(BUILDPATH)/harbor-offline-installer-$(VERSIONTAG).tgz ; fi
.PHONY: clean
clean: cleanbinary cleanimage cleandockercomposefile cleanversiontag cleanpackage
all: install
.PHONY: cleanall
cleanall: cleanbinary cleanimage cleandockercomposefile cleanversiontag cleanpackage
clean:
@echo " make cleanall: remove binary, Harbor images, specific version docker-compose"
@echo " file, specific version tag, online and offline install package"
@echo " make cleanbinary: remove ui and jobservice binary"
@echo " make cleanimage: remove Harbor images"
@echo " make cleandockercomposefile: remove specific version docker-compose"
@echo " make cleanversiontag: cleanpackageremove specific version tag"
@echo " make cleanpackage: remove online and offline install package"
all: install

View File

@ -69,7 +69,7 @@ function check_golang {
fi
# docker has been installed and check its version
if [[ $(go version) =~ (([0-9]+).([0-9]+).([0-9]+)) ]]
if [[ $(go version) =~ (([0-9]+)\.([0-9]+)([\.0-9]*)) ]]
then
golang_version=${BASH_REMATCH[1]}
golang_version_part1=${BASH_REMATCH[2]}
@ -97,7 +97,7 @@ function check_docker {
fi
# docker has been installed and check its version
if [[ $(docker --version) =~ (([0-9]+).([0-9]+).([0-9]+)) ]]
if [[ $(docker --version) =~ (([0-9]+)\.([0-9]+)([\.0-9]*)) ]]
then
docker_version=${BASH_REMATCH[1]}
docker_version_part1=${BASH_REMATCH[2]}
@ -125,7 +125,7 @@ function check_dockercompose {
fi
# docker-compose has been installed, check its version
if [[ $(docker-compose --version) =~ (([0-9]+).([0-9]+).([0-9]+)) ]]
if [[ $(docker-compose --version) =~ (([0-9]+)\.([0-9]+)([\.0-9]*)) ]]
then
docker_compose_version=${BASH_REMATCH[1]}
docker_compose_version_part1=${BASH_REMATCH[2]}

Binary file not shown.

View File

@ -2,17 +2,18 @@
#
# Targets:
#
# build: build harbor photon images
# build: build harbor ubuntu images
# clean: clean ui and jobservice harbor images
# common
SHELL := /bin/bash
BUILDPATH=$(CURDIR)
DEPLOYPATH=$(BUILDPATH)/make
DEPLOYDEVPATH=$(DEPLOYPATH)/dev
MAKEPATH=$(BUILDPATH)/make
MAKEDEVPATH=$(MAKEPATH)/dev
SRCPATH=./src
TOOLSPATH=$(BUILDPATH)/tools
CHECKENVCMD=checkenv.sh
DEVFLAG=true
# docker parameters
DOCKERCMD=$(shell which docker)
@ -22,14 +23,14 @@ DOCKERIMASES=$(DOCKERCMD) images
# binary
UISOURCECODE=$(SRCPATH)/ui
UIBINARYPATH=$(DEPLOYDEVPATH)/ui
UIBINARYPATH=$(MAKEDEVPATH)/ui
UIBINARYNAME=harbor_ui
JOBSERVICESOURCECODE=$(SRCPATH)/jobservice
JOBSERVICEBINARYPATH=$(DEPLOYDEVPATH)/jobservice
JOBSERVICEBINARYPATH=$(MAKEDEVPATH)/jobservice
JOBSERVICEBINARYNAME=harbor_jobservice
# photon dockerfile
DOCKERFILEPATH=$(DEPLOYPATH)/photon
# ubuntu dockerfile
DOCKERFILEPATH=$(MAKEPATH)/ubuntu
DOCKERFILEPATH_UI=$(DOCKERFILEPATH)/ui
DOCKERFILENAME_UI=Dockerfile
DOCKERIMAGENAME_UI=vmware/harbor-ui
@ -45,26 +46,30 @@ VERSIONFILEPATH=$(SRCPATH)/views/sections
VERSIONFILENAME=header-content.htm
GITCMD=$(shell which git)
GITTAG=$(GITCMD) describe --tags
VERSIONTAG=$(shell $(GITTAG))
ifeq ($(DEVFLAG), true)
VERSIONTAG=dev
else
VERSIONTAG=$(shell $(GITTAG))
endif
check_environment:
@$(TOOLSPATH)/$(CHECKENVCMD)
@$(MAKEPATH)/$(CHECKENVCMD)
build:
@echo "building ui container for photon..."
build:
@echo "building ui container for ubuntu..."
$(DOCKERBUILD) -f $(DOCKERFILEPATH_UI)/$(DOCKERFILENAME_UI) -t $(DOCKERIMAGENAME_UI):$(VERSIONTAG) .
@echo "Done."
@echo "building jobservice container for photon..."
@echo "building jobservice container for ubuntu..."
$(DOCKERBUILD) -f $(DOCKERFILEPATH_JOBSERVICE)/$(DOCKERFILENAME_JOBSERVICE) -t $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) .
@echo "Done."
@echo "building log container for photon..."
@echo "building log container for ubuntu..."
$(DOCKERBUILD) -f $(DOCKERFILEPATH_LOG)/$(DOCKERFILENAME_LOG) -t $(DOCKERIMAGENAME_LOG):$(VERSIONTAG) .
@echo "Done."
cleanimage:
@echo "cleaning image for photon..."
@echo "cleaning image for ubuntu..."
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_UI):$(VERSIONTAG)
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG)
- $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_LOG):$(VERSIONTAG)

View File

@ -8,11 +8,12 @@
# common
SHELL := /bin/bash
BUILDPATH=$(CURDIR)
DEPLOYPATH=$(BUILDPATH)/make
DEPLOYDEVPATH=$(DEPLOYPATH)/dev
MAKEPATH=$(BUILDPATH)/make
MAKEDEVPATH=$(MAKEPATH)/dev
SRCPATH=./src
TOOLSPATH=$(BUILDPATH)/tools
CHECKENVCMD=checkenv.sh
DEVFLAG=true
# docker parameters
DOCKERCMD=$(shell which docker)
@ -22,14 +23,14 @@ DOCKERIMASES=$(DOCKERCMD) images
# binary
UISOURCECODE=$(SRCPATH)/ui
UIBINARYPATH=$(DEPLOYDEVPATH)/ui
UIBINARYPATH=$(MAKEDEVPATH)/ui
UIBINARYNAME=harbor_ui
JOBSERVICESOURCECODE=$(SRCPATH)/jobservice
JOBSERVICEBINARYPATH=$(DEPLOYDEVPATH)/jobservice
JOBSERVICEBINARYPATH=$(MAKEDEVPATH)/jobservice
JOBSERVICEBINARYNAME=harbor_jobservice
# ubuntu dockerfile
DOCKERFILEPATH=$(DEPLOYPATH)/ubuntu
DOCKERFILEPATH=$(MAKEPATH)/ubuntu
DOCKERFILEPATH_UI=$(DOCKERFILEPATH)/ui
DOCKERFILENAME_UI=Dockerfile
DOCKERIMAGENAME_UI=vmware/harbor-ui
@ -45,12 +46,16 @@ VERSIONFILEPATH=$(SRCPATH)/views/sections
VERSIONFILENAME=header-content.htm
GITCMD=$(shell which git)
GITTAG=$(GITCMD) describe --tags
VERSIONTAG=$(shell $(GITTAG))
ifeq ($(DEVFLAG), true)
VERSIONTAG=dev
else
VERSIONTAG=$(shell $(GITTAG))
endif
check_environment:
@$(TOOLSPATH)/$(CHECKENVCMD)
@$(MAKEPATH)/$(CHECKENVCMD)
build:
build:
@echo "building ui container for ubuntu..."
$(DOCKERBUILD) -f $(DOCKERFILEPATH_UI)/$(DOCKERFILENAME_UI) -t $(DOCKERIMAGENAME_UI):$(VERSIONTAG) .
@echo "Done."

View File

@ -428,7 +428,13 @@ func TestResetUserPassword(t *testing.T) {
}
func TestChangeUserPassword(t *testing.T) {
err := ChangeUserPassword(models.User{UserID: currentUser.UserID, Password: "NewHarborTester12345", Salt: currentUser.Salt})
user := models.User{UserID: currentUser.UserID}
query, err := GetUser(user)
if err != nil {
t.Errorf("Error occurred when get user salt")
}
currentUser.Salt = query.Salt
err = ChangeUserPassword(models.User{UserID: currentUser.UserID, Password: "NewHarborTester12345", Salt: currentUser.Salt})
if err != nil {
t.Errorf("Error occurred in ChangeUserPassword: %v", err)
}
@ -444,7 +450,14 @@ func TestChangeUserPassword(t *testing.T) {
}
func TestChangeUserPasswordWithOldPassword(t *testing.T) {
err := ChangeUserPassword(models.User{UserID: currentUser.UserID, Password: "NewerHarborTester12345", Salt: currentUser.Salt}, "NewHarborTester12345")
user := models.User{UserID: currentUser.UserID}
query, err := GetUser(user)
if err != nil {
t.Errorf("Error occurred when get user salt")
}
currentUser.Salt = query.Salt
err = ChangeUserPassword(models.User{UserID: currentUser.UserID, Password: "NewerHarborTester12345", Salt: currentUser.Salt}, "NewHarborTester12345")
if err != nil {
t.Errorf("Error occurred in ChangeUserPassword: %v", err)
}

View File

@ -137,11 +137,12 @@ func ChangeUserPassword(u models.User, oldPassword ...string) (err error) {
o := GetOrmer()
var r sql.Result
salt := utils.GenerateRandomString()
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()
r, err = o.Raw(`update user set password=?, salt=? where user_id=?`, utils.Encrypt(u.Password, salt), salt, u.UserID).Exec()
} else {
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()
r, err = o.Raw(`update user set password=?, salt=? where user_id=? and password = ?`, utils.Encrypt(u.Password, salt), salt, u.UserID, utils.Encrypt(oldPassword[0], u.Salt)).Exec()
}
if err != nil {

View File

@ -35,7 +35,7 @@ type User struct {
// RoleList []Role `json:"role_list"`
HasAdminRole int `orm:"column(sysadmin_flag)" json:"has_admin_role"`
ResetUUID string `orm:"column(reset_uuid)" json:"reset_uuid"`
Salt string `orm:"column(salt)"`
Salt string `orm:"column(salt)" json:"-"`
CreationTime time.Time `orm:"creation_time" json:"creation_time"`
UpdateTime time.Time `orm:"update_time" json:"update_time"`
}

View File

@ -34,8 +34,8 @@ func CommonAddUser() {
commonUser := models.User{
Username: TestUserName,
Email: TestUserPwd,
Password: TestUserEmail,
Password: TestUserPwd,
Email: TestUserEmail,
}
_, _ = dao.Register(commonUser)

View File

@ -12,8 +12,8 @@ import (
"github.com/vmware/harbor/src/common/dao"
"github.com/vmware/harbor/src/common/models"
"github.com/vmware/harbor/tests/apitests/apilib"
"github.com/vmware/harbor/src/common/utils"
"github.com/vmware/harbor/tests/apitests/apilib"
// "strconv"
// "strings"
@ -285,7 +285,7 @@ func (a testapi) ProjectsGetByPID(projectID string) (int, apilib.Project, error)
}
//Search projects by projectName and isPublic
func (a testapi) ProjectsGet(projectName string, isPublic int32) (int, []apilib.Project, error) {
func (a testapi) ProjectsGet(projectName string, isPublic int32, authInfo ...usrInfo) (int, []apilib.Project, error) {
_sling := sling.New().Get(a.basePath)
//create api path
@ -299,7 +299,15 @@ func (a testapi) ProjectsGet(projectName string, isPublic int32) (int, []apilib.
var successPayload []apilib.Project
httpStatusCode, body, err := request(_sling, jsonAcceptHeader)
var httpStatusCode int
var err error
var body []byte
if len(authInfo) > 0 {
httpStatusCode, body, err = request(_sling, jsonAcceptHeader, authInfo[0])
} else {
httpStatusCode, body, err = request(_sling, jsonAcceptHeader)
}
if err == nil && httpStatusCode == 200 {
err = json.Unmarshal(body, &successPayload)
}

View File

@ -30,8 +30,7 @@ func TestLogGet(t *testing.T) {
}
logNum := len(result)
logID := result[0].LogId
fmt.Println(result)
fmt.Println("result", result)
//add the project first.
fmt.Println("add the project first.")
reply, err := apiTest.ProjectsPost(*admin, project)
@ -48,12 +47,16 @@ func TestLogGet(t *testing.T) {
t.Log(err)
} else {
assert.Equal(logNum+1, len(result), "lines of logs should be equal")
assert.Equal(int32(logID+1), result[0].LogId, "LogId should be equal")
assert.Equal("my_project/", result[0].RepoName, "RepoName should be equal")
assert.Equal("N/A", result[0].RepoTag, "RepoTag should be equal")
assert.Equal("create", result[0].Operation, "Operation should be equal")
num, index := getLog(result)
if num != 1 {
assert.Equal(1, num, "add my_project log number should be 1")
} else {
assert.Equal("my_project/", result[index].RepoName, "RepoName should be equal")
assert.Equal("N/A", result[index].RepoTag, "RepoTag should be equal")
assert.Equal("create", result[index].Operation, "Operation should be equal")
}
}
fmt.Println("log ", result)
//case 2: wrong format of start_time parameter, expect the wrong output
now = fmt.Sprintf("%v", time.Now().Unix())
statusCode, result, err = apiTest.LogGet(*admin, "ss", now, "3")
@ -103,13 +106,17 @@ func TestLogGet(t *testing.T) {
if logNum+1 >= 10 {
logNum = 10
} else {
logNum += 1
logNum++
}
assert.Equal(logNum, len(result), "lines of logs should be equal")
assert.Equal(int32(logID+1), result[0].LogId, "LogId should be equal")
assert.Equal("my_project/", result[0].RepoName, "RepoName should be equal")
assert.Equal("N/A", result[0].RepoTag, "RepoTag should be equal")
assert.Equal("create", result[0].Operation, "Operation should be equal")
num, index := getLog(result)
if num != 1 {
assert.Equal(1, num, "add my_project log number should be 1")
} else {
assert.Equal("my_project/", result[index].RepoName, "RepoName should be equal")
assert.Equal("N/A", result[index].RepoTag, "RepoTag should be equal")
assert.Equal("create", result[index].Operation, "Operation should be equal")
}
}
//get the project
@ -138,3 +145,14 @@ func TestLogGet(t *testing.T) {
fmt.Printf("\n")
}
func getLog(result []apilib.AccessLog) (int, int) {
var num, index int
for i := 0; i < len(result); i++ {
if result[i].RepoName == "my_project/" {
num++
index = i
}
}
return num, index
}

View File

@ -286,6 +286,13 @@ func (p *ProjectAPI) List() {
if public != 1 {
if isAdmin {
projectList[i].Role = models.PROJECTADMIN
} else {
roles, err := dao.GetUserProjectRoles(p.userID, projectList[i].ProjectID)
if err != nil {
log.Errorf("failed to get user's project role: %v", err)
p.CustomAbort(http.StatusInternalServerError, "")
}
projectList[i].Role = roles[0].RoleID
}
if projectList[i].Role == models.PROJECTADMIN {
projectList[i].Togglable = true

View File

@ -13,7 +13,7 @@ var addProject *apilib.ProjectReq
var addPID int
func InitAddPro() {
addProject = &apilib.ProjectReq{"test_project", 1}
addProject = &apilib.ProjectReq{"add_project", 1}
}
func TestAddProject(t *testing.T) {
@ -106,7 +106,49 @@ func TestProGetByName(t *testing.T) {
} else {
assert.Equal(int(401), httpStatusCode, "httpStatusCode should be 200")
}
fmt.Printf("\n")
//-------------------case 3 : check admin project role------------------------//
httpStatusCode, result, err = apiTest.ProjectsGet(addProject.ProjectName, 0, *admin)
if err != nil {
t.Error("Error while search project by proName and isPublic", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal(int32(1), result[0].Public, "Public is wrong")
assert.Equal(int32(1), result[0].CurrentUserRoleId, "User project role is wrong")
}
//-------------------case 4 : add project member and check his role ------------------------//
CommonAddUser()
roles := &apilib.RoleParam{[]int32{2}, TestUserName}
projectID := strconv.Itoa(addPID)
httpStatusCode, err = apiTest.AddProjectMember(*admin, projectID, *roles)
if err != nil {
t.Error("Error whihle add project role member", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
httpStatusCode, result, err = apiTest.ProjectsGet(addProject.ProjectName, 0, *testUser)
if err != nil {
t.Error("Error while search project by proName and isPublic", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
assert.Equal(addProject.ProjectName, result[0].ProjectName, "Project name is wrong")
assert.Equal(int32(1), result[0].Public, "Public is wrong")
assert.Equal(int32(2), result[0].CurrentUserRoleId, "User project role is wrong")
}
id := strconv.Itoa(CommonGetUserID())
httpStatusCode, err = apiTest.DeleteProjectMember(*admin, projectID, id)
if err != nil {
t.Error("Error whihle add project role member", err.Error())
t.Log(err)
} else {
assert.Equal(int(200), httpStatusCode, "httpStatusCode should be 200")
}
CommonDelUser()
}
//Get project by proID

View File

@ -23,10 +23,10 @@ import (
"strconv"
"strings"
"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"
)
// UserAPI handles request to /api/users/{}
@ -152,7 +152,7 @@ func (ua *UserAPI) Put() {
ua.DecodeJSONReq(&user)
err := commonValidate(user)
if err != nil {
log.Warning("Bad request in change user profile: %v", err)
log.Warningf("Bad request in change user profile: %v", err)
ua.RenderError(http.StatusBadRequest, "change user profile error:"+err.Error())
return
}
@ -200,7 +200,7 @@ func (ua *UserAPI) Post() {
ua.DecodeJSONReq(&user)
err := validate(user)
if err != nil {
log.Warning("Bad request in Register: %v", err)
log.Warningf("Bad request in Register: %v", err)
ua.RenderError(http.StatusBadRequest, "register error:"+err.Error())
return
}

View File

@ -354,6 +354,16 @@ func TestUsersUpdatePassword(t *testing.T) {
assert.Equal(200, code, "Get users status should be 200")
testUser0002.Password = password.NewPassword
testUser0002Auth.Passwd = password.NewPassword
//TODO: verify the new password takes effect
}
//case 6: update user2 password setting the new password same as the old
password.OldPassword = password.NewPassword
code, err = apiTest.UsersUpdatePassword(testUser0002ID, password, *admin)
if err != nil {
t.Error("Error occured while change user profile", err.Error())
t.Log(err)
} else {
assert.Equal(200, code, "When new password is same as old, update user password status should be 200")
}
}

View File

@ -26,35 +26,26 @@
var vm = this;
vm.isAdmin = (vm.hasAdminRole === 1);
vm.enabled = vm.isAdmin ? 0 : 1;
vm.toggle = toggle;
vm.editable = (vm.currentUser.user_id !== Number(vm.userId));
function toggle() {
ToggleAdminService(vm.userId, vm.enabled)
ToggleAdminService(vm.userId, vm.isAdmin ? 0 : 1)
.success(toggleAdminSuccess)
.error(toggleAdminFailed);
}
function toggleAdminSuccess(data, status) {
if(vm.isAdmin) {
vm.isAdmin = false;
}else{
vm.isAdmin = true;
}
console.log('Toggled userId:' + vm.userId + ' to admin:' + vm.isAdmin);
vm.isAdmin = !vm.isAdmin;
}
function toggleAdminFailed(data, status) {
console.log('Failed to toggle admin:' + data);
vm.isAdmin = !vm.isAdmin;
$scope.$emit('modalTitle', $filter('tr')('error'));
$scope.$emit('modalMessage', $filter('tr')('failed_to_toggle_admin'));
$scope.$emit('raiseError', true);
if(vm.isAdmin) {
vm.isAdmin = false;
}else{
vm.isAdmin = true;
}
console.log('Failed to toggle admin:' + data);
}
}

View File

@ -0,0 +1,44 @@
/*
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.
*/
(function() {
'use strict';
angular
.module('harbor.validator')
.directive('email', email);
email.$inject = ['EMAIL_REGEXP'];
function email(EMAIL_REGEXP) {
var directive = {
'require' : 'ngModel',
'link': link
};
return directive;
function link (scope, element, attrs, ctrl) {
ctrl.$validators.email = validator;
function validator(modelValue, viewValue) {
return EMAIL_REGEXP.test(modelValue);
}
}
}
})();

View File

@ -20,5 +20,7 @@
.module('harbor.validator')
.constant('INVALID_CHARS', [",","~","#", "$", "%"])
.constant('PASSWORD_REGEXP', /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).{8,20}$/)
.constant('PROJECT_REGEXP', /^[a-z0-9](?:-*[a-z0-9])*(?:[._][a-z0-9](?:-*[a-z0-9])*)*$/);
.constant('PROJECT_REGEXP', /^[a-z0-9](?:-*[a-z0-9])*(?:[._][a-z0-9](?:-*[a-z0-9])*)*$/)
.constant('EMAIL_REGEXP', /^(([^<>()[\]\.,;:\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,}))$/);
})();

View File

@ -20,9 +20,9 @@
.module('harbor.session')
.controller('CurrentUserController', CurrentUserController);
CurrentUserController.$inject = ['$scope', 'CurrentUserService', 'currentUser', '$window', '$document'];
CurrentUserController.$inject = ['$scope', 'CurrentUserService', 'currentUser', '$window', '$document', 'LogOutService'];
function CurrentUserController($scope, CurrentUserService, currentUser, $window, $document) {
function CurrentUserController($scope, CurrentUserService, currentUser, $window, $document, LogOutService) {
var vm = this;
@ -32,16 +32,27 @@
function getCurrentUserComplete(response) {
if(angular.isDefined(response)) {
currentUser.set(response.data);
if(location.pathname === '/') {
currentUser.set(response.data);
if(location.pathname === '/') {
$window.location.href = '/dashboard';
}
}
}
function getCurrentUserFailed(e){
console.log('No session of current user.');
console.log('Failed to get current user:' + e);
LogOutService()
.success(logOutSuccess)
.error(logOutFailed);
}
function logOutSuccess(data, status) {
currentUser.unset();
}
function logOutFailed(data, status) {
console.log('Failed to log out:' + data);
}
}
})();

View File

@ -29,7 +29,7 @@
<div class="form-group">
<label for="email" class="col-sm-3 control-label">// 'email' | tr //:</label>
<div class="col-sm-7">
<input type="email" class="form-control" id="email" ng-model="user.email" name="uEmail" required>
<input type="text" class="form-control" id="email" ng-model="user.email" name="uEmail" required email>
<div class="error-message" ng-messages="form.uEmail.$touched && form.uEmail.$error">
<span ng-message="required">// 'email_is_required' | tr //</span>
<span ng-message="email">// 'email_content_illegal' | tr //</span>

View File

@ -24,7 +24,7 @@
<div class="form-group">
<label for="email" class="col-sm-3 control-label">// 'email' | tr //:</label>
<div class="col-sm-7">
<input type="email" class="form-control" id="email" ng-model="user.email" ng-model-options="{ debounce: 500 }" ng-change="vm.reset()" name="uEmail" required data-target="email">
<input type="text" class="form-control" id="email" ng-model="user.email" ng-model-options="{ debounce: 500 }" ng-change="vm.reset()" name="uEmail" required data-target="email" email>
<div class="error-message">
<div ng-messages="(form.$submitted || form.uEmail.$touched) && form.uEmail.$error">
<span ng-message="required">// 'email_is_required' | tr //</span>

View File

@ -127,6 +127,7 @@
<script src="/static/resources/js/components/validator/user-exist.validator.js"></script>
<script src="/static/resources/js/components/validator/invalid-chars.validator.js"></script>
<script src="/static/resources/js/components/validator/project-name.validator.js"></script>
<script src="/static/resources/js/components/validator/email.validator.js"></script>
<script src="/static/resources/js/components/search/search.module.js"></script>
<script src="/static/resources/js/components/search/search.directive.js"></script>

View File

@ -45,12 +45,11 @@
<div class="form-group">
<label for="email" class="col-sm-3 control-label">// 'email' | tr //:</label>
<div class="col-sm-7">
<input type="email" class="form-control" id="email" ng-model="user.email" name="uEmail" ng-model-options="{ updateOn: 'blur' }" required user-exists data-target="email" maxlength="50">
<div class="error-message" ng-messages="(form.$submitted || form.uEmail.$touched) &&form.uEmail.$error">
<input type="text" class="form-control" id="email" ng-model="user.email" name="uEmail" ng-model-options="{ updateOn: 'blur' }" required user-exists data-target="email" email>
<div class="error-message" ng-messages="(form.$submitted || form.uEmail.$touched) && form.uEmail.$error">
<span ng-message="required">// 'email_is_required' | tr //</span>
<span ng-message="email">// 'email_content_illegal' | tr //</span>
<span ng-message="userExists">// 'email_has_been_taken' | tr //</span>
<span ng-message="maxlength">// 'email_is_too_long' | tr //</span>
</div>
<p class="help-block small-size-fonts">// 'email_desc' | tr //</p>
</div>