Merge pull request #3 from reasonerjt/master

sync code from personal repo
This commit is contained in:
reasonerjt 2016-02-24 14:40:16 +08:00
commit 2bdf12e2b4
29 changed files with 485 additions and 411 deletions

View File

@ -15,12 +15,10 @@ http {
upstream registry { upstream registry {
server registry:5000; server registry:5000;
# check interval=2000 rise=1 fall=1 timeout=5000 type=tcp;
} }
upstream ui { upstream ui {
server ui:80; server ui:80;
# check interval=2000 rise=1 fall=1 timeout=5000 type=tcp;
} }

View File

@ -39,20 +39,20 @@ ui:
- ./config/ui/app.conf:/etc/ui/app.conf - ./config/ui/app.conf:/etc/ui/app.conf
- ./config/ui/private_key.pem:/etc/ui/private_key.pem - ./config/ui/private_key.pem:/etc/ui/private_key.pem
links: links:
- registry:registry - registry
- mysql:mysql - mysql
- log - log
log_driver: "syslog" log_driver: "syslog"
log_opt: log_opt:
syslog-address: "tcp://127.0.0.1:1514" syslog-address: "tcp://127.0.0.1:1514"
syslog-tag: "ui" syslog-tag: "ui"
roxy: proxy:
image: library/nginx:1.9 image: library/nginx:1.9
volumes: volumes:
- ./config/nginx/nginx.conf:/etc/nginx/nginx.conf - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf
links: links:
- ui:ui - ui
- registry:registry - registry
- log - log
ports: ports:
- 80:80 - 80:80

View File

@ -1,23 +1,18 @@
FROM library/ubuntu:14.04 FROM library/ubuntu:14.04
# run logrotate hourly # run logrotate hourly, disable imklog model, provides TCP/UDP syslog reception
RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/ 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 # logrotate configuration file for docker
ADD logrotate_docker.conf /etc/logrotate.d/ 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 # rsyslog configuration file for docker
ADD rsyslog_docker.conf /etc/rsyslog.d/ ADD rsyslog_docker.conf /etc/rsyslog.d/
@ -26,3 +21,4 @@ VOLUME /var/log/docker/
EXPOSE 514 EXPOSE 514
CMD cron && chown -R syslog:syslog /var/log/docker/ && rsyslogd -n CMD cron && chown -R syslog:syslog /var/log/docker/ && rsyslogd -n

View File

@ -14,8 +14,8 @@ WORKDIR /go/src/github.com/vmware/harbor
ENV GO15VENDOREXPERIMENT 1 ENV GO15VENDOREXPERIMENT 1
RUN go get -d github.com/docker/distribution \ RUN go get -d github.com/docker/distribution \
&& go get -d github.com/docker/libtrust \ && go get -d github.com/docker/libtrust \
&& go get -d github.com/go-sql-driver/mysql && go get -d github.com/go-sql-driver/mysql \
RUN go install -v -a && go install -v -a
ENV MYSQL_USR root \ ENV MYSQL_USR root \
MYSQL_PWD root \ MYSQL_PWD root \
@ -23,7 +23,6 @@ ENV MYSQL_USR root \
MYSQL_PORT_3306_TCP_PORT 3306 \ MYSQL_PORT_3306_TCP_PORT 3306 \
REGISTRY_URL localhost:5000 REGISTRY_URL localhost:5000
COPY conf /go/bin/conf
COPY views /go/bin/views COPY views /go/bin/views
COPY static /go/bin/static COPY static /go/bin/static

View File

@ -9,7 +9,6 @@ ENV REGISTRY_URL localhost:5000
RUN apt-get update -qqy && apt-get install -qqy libldap2-dev RUN apt-get update -qqy && apt-get install -qqy libldap2-dev
ADD harbor /go/bin/harbor ADD harbor /go/bin/harbor
ADD conf /go/bin/conf
ADD views /go/bin/views ADD views /go/bin/views
ADD static /go/bin/static ADD static /go/bin/static

View File

@ -40,7 +40,7 @@ func (b *BaseAPI) DecodeJsonReq(v interface{}) {
err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<32), v) err := json.Unmarshal(b.Ctx.Input.CopyBody(1<<32), v)
if err != nil { if err != nil {
beego.Error("Error while decoding the json request:", err) 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") sessionUserId := b.GetSession("userId")
if sessionUserId == nil { if sessionUserId == nil {
beego.Warning("No user id in session, canceling request") beego.Warning("No user id in session, canceling request")
b.CustomAbort(401, "") b.CustomAbort(http.StatusUnauthorized, "")
} }
userId := sessionUserId.(int) userId := sessionUserId.(int)
u, err := dao.GetUser(models.User{UserId: userId}) u, err := dao.GetUser(models.User{UserId: userId})
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) beego.Error("Error occurred in GetUser:", err)
b.CustomAbort(500, "Internal error.") b.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if u == nil { if u == nil {
beego.Warning("User was deleted already, user id: ", userId, " canceling request.") beego.Warning("User was deleted already, user id: ", userId, " canceling request.")
b.CustomAbort(401, "") b.CustomAbort(http.StatusUnauthorized, "")
} }
return userId return userId
} }

View File

@ -17,6 +17,7 @@ package api
import ( import (
"fmt" "fmt"
"log" "log"
"net/http"
"github.com/vmware/harbor/dao" "github.com/vmware/harbor/dao"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
@ -48,15 +49,15 @@ func (p *ProjectAPI) Prepare() {
p.projectId, err = strconv.ParseInt(id_str, 10, 64) p.projectId, err = strconv.ParseInt(id_str, 10, 64)
if err != nil { if err != nil {
log.Printf("Error parsing project id: %s, error: %v", id_str, err) 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) exist, err := dao.ProjectExists(p.projectId)
if err != nil { if err != nil {
log.Printf("Error occurred in ProjectExists: %v", err) log.Printf("Error occurred in ProjectExists: %v", err)
p.CustomAbort(500, "Internal error.") p.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if !exist { 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) err := validateProjectReq(req)
if err != nil { if err != nil {
beego.Error("Invalid project request, error: ", err) 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 return
} }
projectName := req.ProjectName projectName := req.ProjectName
@ -80,14 +81,14 @@ func (p *ProjectAPI) Post() {
beego.Error("Error happened checking project existence in db:", err, ", project name:", projectName) beego.Error("Error happened checking project existence in db:", err, ", project name:", projectName)
} }
if exist { if exist {
p.RenderError(409, "") p.RenderError(http.StatusConflict, "")
return return
} }
project := models.Project{OwnerId: p.userId, Name: projectName, CreationTime: time.Now(), Public: public} project := models.Project{OwnerId: p.userId, Name: projectName, CreationTime: time.Now(), Public: public}
err = dao.AddProject(project) err = dao.AddProject(project)
if err != nil { if err != nil {
beego.Error("Failed to add project, error: %v", err) 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) result, err := dao.ProjectExists(projectName)
if err != nil { if err != nil {
beego.Error("Error while communicating with DB: ", err) 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 return
} }
if !result { if !result {
p.RenderError(404, "") p.RenderError(http.StatusNotFound, "")
return return
} }
} }
@ -117,7 +118,7 @@ func (p *ProjectAPI) Get() {
projectList, err := dao.QueryProject(queryProject) projectList, err := dao.QueryProject(queryProject)
if err != nil { if err != nil {
beego.Error("Error occurred in QueryProject:", err) 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++ { for i := 0; i < len(projectList); i++ {
if isProjectAdmin(p.userId, projectList[i].ProjectId) { 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) projectId, err := strconv.ParseInt(p.Ctx.Input.Param(":id"), 10, 64)
if err != nil { if err != nil {
beego.Error("Error parsing project id:", projectId, ", error: ", err) beego.Error("Error parsing project id:", projectId, ", error: ", err)
p.RenderError(400, "invalid project id") p.RenderError(http.StatusBadRequest, "invalid project id")
return return
} }
@ -145,13 +146,13 @@ func (p *ProjectAPI) Put() {
} }
if !isProjectAdmin(p.userId, projectId) { if !isProjectAdmin(p.userId, projectId) {
beego.Warning("Current user, id:", p.userId, ", does not have project admin role for project, id:", 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 return
} }
err = dao.ToggleProjectPublicity(p.projectId, public) err = dao.ToggleProjectPublicity(p.projectId, public)
if err != nil { if err != nil {
beego.Error("Error while updating project, project id:", projectId, ", error:", err) 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")
} }
} }
@ -162,14 +163,18 @@ func (p *ProjectAPI) FilterAccessLog() {
username := filter.Username username := filter.Username
keywords := filter.Keywords 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) accessLogList, err := dao.GetAccessLogs(query)
if err != nil { if err != nil {
log.Printf("Error occurred in GetAccessLogs: %v", err) log.Printf("Error occurred in GetAccessLogs: %v", err)
p.CustomAbort(500, "Internal error.") p.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
p.Data["json"] = accessLogList p.Data["json"] = accessLogList
p.ServeJSON() p.ServeJSON()

View File

@ -15,12 +15,13 @@
package api package api
import ( import (
"net/http"
"strconv"
"github.com/vmware/harbor/dao" "github.com/vmware/harbor/dao"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/astaxie/beego" "github.com/astaxie/beego"
"strconv"
) )
type ProjectMemberAPI struct { type ProjectMemberAPI struct {
@ -40,18 +41,18 @@ func (pma *ProjectMemberAPI) Prepare() {
pid, err := strconv.ParseInt(pma.Ctx.Input.Param(":pid"), 10, 64) pid, err := strconv.ParseInt(pma.Ctx.Input.Param(":pid"), 10, 64)
if err != nil { if err != nil {
beego.Error("Error parsing project id:", pid, ", error:", err) beego.Error("Error parsing project id:", pid, ", error:", err)
pma.CustomAbort(400, "invalid project Id") pma.CustomAbort(http.StatusBadRequest, "invalid project Id")
return return
} }
p, err := dao.GetProjectById(models.Project{ProjectId: pid}) p, err := dao.GetProjectById(models.Project{ProjectId: pid})
if err != nil { if err != nil {
beego.Error("Error occurred in GetProjectById:", err) beego.Error("Error occurred in GetProjectById:", err)
pma.CustomAbort(500, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if p == nil { if p == nil {
beego.Warning("Project with id:", pid, "does not exist.") 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.project = p
pma.currentUserId = pma.ValidateUser() pma.currentUserId = pma.ValidateUser()
@ -64,7 +65,7 @@ func (pma *ProjectMemberAPI) Prepare() {
memberId, err := strconv.Atoi(mid) memberId, err := strconv.Atoi(mid)
if err != nil { if err != nil {
beego.Error("Invalid member Id, error:", err) beego.Error("Invalid member Id, error:", err)
pma.CustomAbort(400, "Invalid member id") pma.CustomAbort(http.StatusBadRequest, "Invalid member id")
} }
pma.memberId = memberId pma.memberId = memberId
} }
@ -74,7 +75,7 @@ func (pma *ProjectMemberAPI) Get() {
pid := pma.project.ProjectId pid := pma.project.ProjectId
if !CheckProjectPermission(pma.currentUserId, pid) { if !CheckProjectPermission(pma.currentUserId, pid) {
beego.Warning("Current user, user id :", pma.currentUserId, "does not have permission for project, id:", 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 return
} }
if pma.memberId == 0 { //member id not set return list of the members 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) userList, err := dao.GetUserByProject(queryProject, queryUser)
if err != nil { if err != nil {
beego.Error("Failed to query database for member list, error:", err) 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 return
} }
pma.Data["json"] = userList pma.Data["json"] = userList
@ -92,14 +93,14 @@ func (pma *ProjectMemberAPI) Get() {
roleList, err := dao.GetUserProjectRoles(models.User{UserId: pma.memberId}, pid) roleList, err := dao.GetUserProjectRoles(models.User{UserId: pma.memberId}, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) 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 //return empty role list to indicate if a user is not a member
result := make(map[string]interface{}) result := make(map[string]interface{})
user, err := dao.GetUser(models.User{UserId: pma.memberId}) user, err := dao.GetUser(models.User{UserId: pma.memberId})
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) 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_name"] = user.Username
result["user_id"] = pma.memberId result["user_id"] = pma.memberId
@ -115,11 +116,11 @@ func (pma *ProjectMemberAPI) Post() {
rolelist, err := dao.GetUserProjectRoles(userQuery, pid) rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(500, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if len(rolelist) == 0 { if len(rolelist) == 0 {
beego.Warning("Current user, id:", pma.currentUserId, "does not have project admin role for project, id:", pid) 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 return
} }
var req memberReq var req memberReq
@ -128,17 +129,17 @@ func (pma *ProjectMemberAPI) Post() {
userId := CheckUserExists(username) userId := CheckUserExists(username)
if userId <= 0 { if userId <= 0 {
beego.Warning("User does not exist, user name:", username) 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 return
} }
rolelist, err = dao.GetUserProjectRoles(models.User{UserId: userId}, pid) rolelist, err = dao.GetUserProjectRoles(models.User{UserId: userId}, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(500, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if len(rolelist) > 0 { if len(rolelist) > 0 {
beego.Warning("user is already added to project, user id:", userId, ", project id:", pid) 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 return
} }
@ -146,7 +147,7 @@ func (pma *ProjectMemberAPI) Post() {
err = dao.AddUserProjectRole(userId, pid, int(rid)) err = dao.AddUserProjectRole(userId, pid, int(rid))
if err != nil { if err != nil {
beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", userId, ", role id:", rid) 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 return
} }
} }
@ -159,11 +160,11 @@ func (pma *ProjectMemberAPI) Put() {
rolelist, err := dao.GetUserProjectRoles(userQuery, pid) rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
pma.CustomAbort(500, "Internal error.") pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if len(rolelist) == 0 { if len(rolelist) == 0 {
beego.Warning("Current user, id:", pma.currentUserId, ", does not have project admin role for project, id:", pid) 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 return
} }
var req memberReq var req memberReq
@ -171,7 +172,7 @@ func (pma *ProjectMemberAPI) Put() {
roleList, err := dao.GetUserProjectRoles(models.User{UserId: mid}, pid) roleList, err := dao.GetUserProjectRoles(models.User{UserId: mid}, pid)
if len(roleList) == 0 { if len(roleList) == 0 {
beego.Warning("User is not in project, user id:", mid, ", project id:", pid) 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 return
} }
//TODO: delete and insert should in one transaction //TODO: delete and insert should in one transaction
@ -179,7 +180,7 @@ func (pma *ProjectMemberAPI) Put() {
err = dao.DeleteUserProjectRoles(mid, pid) err = dao.DeleteUserProjectRoles(mid, pid)
if err != nil { if err != nil {
beego.Error("Failed to delete project roles for user, user id:", mid, ", project id: ", pid, ", error: ", err) 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 return
} }
//insert roles in request //insert roles in request
@ -187,7 +188,7 @@ func (pma *ProjectMemberAPI) Put() {
err = dao.AddUserProjectRole(mid, pid, int(rid)) err = dao.AddUserProjectRole(mid, pid, int(rid))
if err != nil { if err != nil {
beego.Error("Failed to update DB to add project user role, project id:", pid, ", user id:", mid, ", role id:", rid) 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 return
} }
} }
@ -200,13 +201,13 @@ func (pma *ProjectMemberAPI) Delete() {
rolelist, err := dao.GetUserProjectRoles(userQuery, pid) rolelist, err := dao.GetUserProjectRoles(userQuery, pid)
if len(rolelist) == 0 { if len(rolelist) == 0 {
beego.Warning("Current user, id:", pma.currentUserId, ", does not have project admin role for project, id:", pid) 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 return
} }
err = dao.DeleteUserProjectRoles(mid, pid) err = dao.DeleteUserProjectRoles(mid, pid)
if err != nil { if err != nil {
beego.Error("Failed to delete project roles for user, user id:", mid, ", project id:", pid, ", error:", err) 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 return
} }
} }

View File

@ -16,6 +16,7 @@ package api
import ( import (
"encoding/json" "encoding/json"
"net/http"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -56,28 +57,28 @@ func (ra *RepositoryAPI) Get() {
projectId, err0 := ra.GetInt64("project_id") projectId, err0 := ra.GetInt64("project_id")
if err0 != nil { if err0 != nil {
beego.Error("Failed to get project id, error:", err0) beego.Error("Failed to get project id, error:", err0)
ra.RenderError(400, "Invalid project id") ra.RenderError(http.StatusBadRequest, "Invalid project id")
return return
} }
projectQuery := models.Project{ProjectId: projectId} projectQuery := models.Project{ProjectId: projectId}
p, err := dao.GetProjectById(projectQuery) p, err := dao.GetProjectById(projectQuery)
if err != nil { if err != nil {
beego.Error("Error occurred in GetProjectById:", err) beego.Error("Error occurred in GetProjectById:", err)
ra.CustomAbort(500, "Internal error.") ra.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if p == nil { if p == nil {
beego.Warning("Project with Id:", projectId, ", does not exist", projectId) beego.Warning("Project with Id:", projectId, ", does not exist", projectId)
ra.RenderError(404, "") ra.RenderError(http.StatusNotFound, "")
return return
} }
if p.Public == 0 && !CheckProjectPermission(ra.userId, projectId) { if p.Public == 0 && !CheckProjectPermission(ra.userId, projectId) {
ra.RenderError(403, "") ra.RenderError(http.StatusForbidden, "")
return return
} }
repoList, err := svc_utils.GetRepoFromCache() repoList, err := svc_utils.GetRepoFromCache()
if err != nil { if err != nil {
beego.Error("Failed to get repo from cache, error:", err) 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 projectName := p.Name
q := ra.GetString("q") 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) result, err := svc_utils.RegistryApiGet(svc_utils.BuildRegistryUrl(repoName, "tags", "list"), ra.username)
if err != nil { if err != nil {
beego.Error("Failed to get repo tags, repo name:", repoName, ", error: ", err) 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 { } else {
t := Tag{} t := Tag{}
json.Unmarshal(result, &t) 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) result, err := svc_utils.RegistryApiGet(svc_utils.BuildRegistryUrl(repoName, "manifests", tag), ra.username)
if err != nil { if err != nil {
beego.Error("Failed to get manifests for repo, repo name:", repoName, ", tag:", tag, ", error:", err) 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 return
} else { } else {
mani := Manifest{} mani := Manifest{}
err = json.Unmarshal(result, &mani) err = json.Unmarshal(result, &mani)
if err != nil { if err != nil {
beego.Error("Failed to decode json from response for manifests, repo name:", repoName, ", tag:", tag, ", error:", err) 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 return
} else { } else {
v1Compatibility := mani.History[0].V1Compatibility v1Compatibility := mani.History[0].V1Compatibility
@ -161,7 +162,7 @@ func (ra *RepositoryAPI) GetManifests() {
err = json.Unmarshal([]byte(v1Compatibility), &item) err = json.Unmarshal([]byte(v1Compatibility), &item)
if err != nil { if err != nil {
beego.Error("Failed to decode V1 field for repo, repo name:", repoName, ", tag:", tag, ", error:", err) 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 return
} else { } else {
item.CreatedStr = item.Created.Format("2006-01-02 15:04:05") item.CreatedStr = item.Created.Format("2006-01-02 15:04:05")

View File

@ -15,6 +15,7 @@
package api package api
import ( import (
"net/http"
"sort" "sort"
"strings" "strings"
@ -44,7 +45,7 @@ func (n *SearchAPI) Get() {
projects, err := dao.QueryRelevantProjects(userId) projects, err := dao.QueryRelevantProjects(userId)
if err != nil { if err != nil {
beego.Error("Failed to get projects of user id:", userId, ", error:", err) 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} projectSorter := &utils.ProjectSorter{Projects: projects}
sort.Sort(projectSorter) sort.Sort(projectSorter)
@ -66,7 +67,7 @@ func (n *SearchAPI) Get() {
repositories, err2 := svc_utils.GetRepoFromCache() repositories, err2 := svc_utils.GetRepoFromCache()
if err2 != nil { if err2 != nil {
beego.Error("Failed to get repos from cache, error :", err2) 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) sort.Strings(repositories)
repositoryResult := filterRepositories(repositories, projects, keyword) repositoryResult := filterRepositories(repositories, projects, keyword)

View File

@ -15,6 +15,7 @@
package api package api
import ( import (
"net/http"
"strconv" "strconv"
"github.com/vmware/harbor/dao" "github.com/vmware/harbor/dao"
@ -40,17 +41,17 @@ func (ua *UserAPI) Prepare() {
ua.userId, err = strconv.Atoi(id) ua.userId, err = strconv.Atoi(id)
if err != nil { if err != nil {
beego.Error("Invalid user id, error:", err) 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} userQuery := models.User{UserId: ua.userId}
u, err := dao.GetUser(userQuery) u, err := dao.GetUser(userQuery)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) beego.Error("Error occurred in GetUser:", err)
ua.CustomAbort(500, "Internal error.") ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if u == nil { if u == nil {
beego.Error("User with Id:", ua.userId, "does not exist") 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) exist, err := dao.IsAdminRole(ua.currentUid)
if err != nil { if err != nil {
beego.Error("Error occurred in IsAdminRole:", err) 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 ua.userId == 0 { //list users
if !exist { if !exist {
beego.Error("Current user, id:", ua.currentUid, ", does not have admin role, can not list users") 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 return
} }
username := ua.GetString("username") username := ua.GetString("username")
@ -76,7 +77,7 @@ func (ua *UserAPI) Get() {
userList, err := dao.ListUsers(userQuery) userList, err := dao.ListUsers(userQuery)
if err != nil { if err != nil {
beego.Error("Failed to get data from database, error:", err) 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 return
} }
ua.Data["json"] = userList ua.Data["json"] = userList
@ -86,12 +87,12 @@ func (ua *UserAPI) Get() {
u, err := dao.GetUser(userQuery) u, err := dao.GetUser(userQuery)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) beego.Error("Error occurred in GetUser:", err)
ua.CustomAbort(500, "Internal error.") ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
ua.Data["json"] = u ua.Data["json"] = u
} else { } else {
beego.Error("Current user, id:", ua.currentUid, "does not have admin role, can not view other user's detail") 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 return
} }
ua.ServeJSON() 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) exist, err := dao.IsAdminRole(ua.currentUid)
if err != nil { if err != nil {
beego.Error("Error occurred in IsAdminRole:", err) beego.Error("Error occurred in IsAdminRole:", err)
ua.CustomAbort(500, "Internal error.") ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if !exist { if !exist {
beego.Warning("current user, id:", ua.currentUid, ", does not have admin role, can not update other user's role") 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 return
} }
userQuery := models.User{UserId: ua.userId} userQuery := models.User{UserId: ua.userId}
@ -116,17 +117,17 @@ func (ua *UserAPI) Delete() {
exist, err := dao.IsAdminRole(ua.currentUid) exist, err := dao.IsAdminRole(ua.currentUid)
if err != nil { if err != nil {
beego.Error("Error occurred in IsAdminRole:", err) beego.Error("Error occurred in IsAdminRole:", err)
ua.CustomAbort(500, "Internal error.") ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if !exist { if !exist {
beego.Warning("current user, id:", ua.currentUid, ", does not have admin role, can not remove user") 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 return
} }
err = dao.DeleteUser(ua.userId) err = dao.DeleteUser(ua.userId)
if err != nil { if err != nil {
beego.Error("Failed to delete data from database, error:", err) 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 return
} }
} }

View File

@ -1,9 +0,0 @@
appname = harbor
runmode = dev
[lang]
types = en-US|zh-CN
names = en-US|zh-CN
[dev]
httpport = 80

View File

@ -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-----

View File

@ -15,6 +15,7 @@
package controllers package controllers
import ( import (
"log"
"os" "os"
"strings" "strings"
@ -114,6 +115,16 @@ var langTypes []*langType
func init() { 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) beego.AddFuncMap("i18n", i18n.Tr)
langs := strings.Split(beego.AppConfig.String("lang::types"), "|") langs := strings.Split(beego.AppConfig.String("lang::types"), "|")
@ -134,7 +145,6 @@ func init() {
for _, lang := range langs { for _, lang := range langs {
if err := i18n.SetMessage(lang, "static/i18n/"+"locale_"+lang+".ini"); err != nil { if err := i18n.SetMessage(lang, "static/i18n/"+"locale_"+lang+".ini"); err != nil {
beego.Error("Fail to set message file:" + err.Error()) beego.Error("Fail to set message file:" + err.Error())
return
} }
} }
} }

View File

@ -15,6 +15,7 @@
package controllers package controllers
import ( import (
"net/http"
"net/url" "net/url"
"os" "os"
@ -68,7 +69,7 @@ func (idc *ItemDetailController) Get() {
projectId, _ := idc.GetInt64("project_id") projectId, _ := idc.GetInt64("project_id")
if CheckPublicProject(projectId) == false && (sessionUserId == nil || !CheckProjectRole(sessionUserId.(int), projectId)) { 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} projectQuery := models.Project{ProjectId: projectId}
@ -76,11 +77,11 @@ func (idc *ItemDetailController) Get() {
if err != nil { if err != nil {
beego.Error("Error occurred in GetProjectById:", err) beego.Error("Error occurred in GetProjectById:", err)
idc.CustomAbort(500, "Internal error.") idc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if project == nil { if project == nil {
idc.Redirect("/signIn", 302) idc.Redirect("/signIn", http.StatusFound)
} }
idc.Data["ProjectId"] = project.ProjectId idc.Data["ProjectId"] = project.ProjectId
@ -94,7 +95,7 @@ func (idc *ItemDetailController) Get() {
roleList, err := dao.GetUserProjectRoles(models.User{UserId: sessionUserId.(int)}, projectId) roleList, err := dao.GetUserProjectRoles(models.User{UserId: sessionUserId.(int)}, projectId)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUserProjectRoles:", err) beego.Error("Error occurred in GetUserProjectRoles:", err)
idc.CustomAbort(500, "Internal error.") idc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if len(roleList) > 0 { if len(roleList) > 0 {
idc.Data["RoleId"] = roleList[0].RoleId idc.Data["RoleId"] = roleList[0].RoleId

View File

@ -15,6 +15,8 @@
package controllers package controllers
import ( import (
"net/http"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/vmware/harbor/opt_auth" "github.com/vmware/harbor/opt_auth"
@ -45,11 +47,11 @@ func (c *CommonController) Login() {
user, err := opt_auth.Login(models.AuthModel{principal, password}) user, err := opt_auth.Login(models.AuthModel{principal, password})
if err != nil { if err != nil {
beego.Error("Error occurred in UserLogin:", err) beego.Error("Error occurred in UserLogin:", err)
c.CustomAbort(500, "Internal error.") c.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if user == nil { if user == nil {
c.CustomAbort(401, "") c.CustomAbort(http.StatusUnauthorized, "")
} }
c.SetSession("userId", user.UserId) c.SetSession("userId", user.UserId)
@ -62,7 +64,7 @@ func (c *CommonController) SwitchLanguage() {
c.SetSession("lang", lang) c.SetSession("lang", lang)
c.Data["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() { func (c *CommonController) Logout() {

View File

@ -16,6 +16,7 @@ package controllers
import ( import (
"bytes" "bytes"
"net/http"
"os" "os"
"regexp" "regexp"
"text/template" "text/template"
@ -34,7 +35,7 @@ type ChangePasswordController struct {
func (cpc *ChangePasswordController) Get() { func (cpc *ChangePasswordController) Get() {
sessionUserId := cpc.GetSession("userId") sessionUserId := cpc.GetSession("userId")
if sessionUserId == nil { if sessionUserId == nil {
cpc.Redirect("/signIn", 302) cpc.Redirect("/signIn", http.StatusFound)
} }
cpc.Data["Username"] = cpc.GetSession("username") cpc.Data["Username"] = cpc.GetSession("username")
cpc.ForwardTo("page_title_change_password", "change-password") cpc.ForwardTo("page_title_change_password", "change-password")
@ -43,32 +44,40 @@ func (cpc *ChangePasswordController) Get() {
func (cpc *CommonController) UpdatePassword() { func (cpc *CommonController) UpdatePassword() {
sessionUserId := cpc.GetSession("userId") sessionUserId := cpc.GetSession("userId")
sessionUsername := cpc.GetSession("username")
if sessionUserId == nil || sessionUsername == nil { if sessionUserId == nil {
beego.Warning("User does not login.") beego.Warning("User does not login.")
cpc.CustomAbort(401, "please_login_first") cpc.CustomAbort(http.StatusUnauthorized, "please_login_first")
} }
oldPassword := cpc.GetString("old_password") 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(http.StatusBadRequest, "Old password is blank")
}
queryUser := models.User{UserId: sessionUserId.(int), Password: oldPassword}
user, err := dao.CheckUserPassword(queryUser) user, err := dao.CheckUserPassword(queryUser)
if err != nil { if err != nil {
beego.Error("Error occurred in CheckUserPassword:", err) beego.Error("Error occurred in CheckUserPassword:", err)
cpc.CustomAbort(500, "Internal error.") cpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if user == nil { if user == nil {
beego.Warning("Password input is not correct") 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") password := cpc.GetString("password")
if password != "" { if password != "" {
updateUser := models.User{UserId: sessionUserId.(int), Username: sessionUsername.(string), Password: password, Salt: user.Salt} updateUser := models.User{UserId: sessionUserId.(int), Password: password, Salt: user.Salt}
dao.ChangeUserPassword(updateUser) err = dao.ChangeUserPassword(updateUser, oldPassword)
if err != nil {
beego.Error("Error occurred in ChangeUserPassword:", err)
cpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
}
} else { } else {
cpc.CustomAbort(404, "please_input_new_password") cpc.CustomAbort(http.StatusBadRequest, "please_input_new_password")
} }
} }
@ -90,22 +99,26 @@ func (fpc *CommonController) SendEmail() {
email := fpc.GetString("email") 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(http.StatusBadRequest, "email_content_illegal")
} else {
queryUser := models.User{Email: email} queryUser := models.User{Email: email}
exist, err := dao.UserExists(queryUser, "email") exist, err := dao.UserExists(queryUser, "email")
if err != nil { if err != nil {
beego.Error("Error occurred in UserExists:", err) beego.Error("Error occurred in UserExists:", err)
fpc.CustomAbort(500, "Internal error.") fpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if !exist { 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") messageTemplate, err := template.ParseFiles("views/reset-password-mail.tpl")
if err != nil { if err != nil {
beego.Error("Parse email template file failed:", err) beego.Error("Parse email template file failed:", err)
fpc.CustomAbort(500, err.Error()) fpc.CustomAbort(http.StatusInternalServerError, err.Error())
} }
message := new(bytes.Buffer) message := new(bytes.Buffer)
@ -117,7 +130,7 @@ func (fpc *CommonController) SendEmail() {
uuid, err := dao.GenerateRandomString() uuid, err := dao.GenerateRandomString()
if err != nil { if err != nil {
beego.Error("Error occurred in GenerateRandomString:", err) beego.Error("Error occurred in GenerateRandomString:", err)
fpc.CustomAbort(500, "Internal error.") fpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
err = messageTemplate.Execute(message, MessageDetail{ err = messageTemplate.Execute(message, MessageDetail{
Hint: fpc.Tr("reset_email_hint"), Hint: fpc.Tr("reset_email_hint"),
@ -127,13 +140,13 @@ func (fpc *CommonController) SendEmail() {
if err != nil { if err != nil {
beego.Error("message template error:", err) beego.Error("message template error:", err)
fpc.CustomAbort(500, "internal_error") fpc.CustomAbort(http.StatusInternalServerError, "internal_error")
} }
config, err := beego.AppConfig.GetSection("mail") config, err := beego.AppConfig.GetSection("mail")
if err != nil { if err != nil {
beego.Error("Can not load app.conf:", err) beego.Error("Can not load app.conf:", err)
fpc.CustomAbort(500, "internal_error") fpc.CustomAbort(http.StatusInternalServerError, "internal_error")
} }
mail := utils.Mail{ mail := utils.Mail{
@ -146,14 +159,12 @@ func (fpc *CommonController) SendEmail() {
if err != nil { if err != nil {
beego.Error("send email failed:", err) 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} user := models.User{ResetUuid: uuid, Email: email}
dao.UpdateUserResetUuid(user) dao.UpdateUserResetUuid(user)
} else {
fpc.CustomAbort(409, "email_content_illegal")
} }
} }
@ -164,39 +175,55 @@ type ResetPasswordController struct {
func (rpc *ResetPasswordController) Get() { func (rpc *ResetPasswordController) Get() {
q := rpc.GetString("q") resetUuid := rpc.GetString("reset_uuid")
queryUser := models.User{ResetUuid: q} if resetUuid == "" {
beego.Error("Reset uuid is blank.")
rpc.Redirect("/", http.StatusFound)
}
queryUser := models.User{ResetUuid: resetUuid}
user, err := dao.GetUser(queryUser) user, err := dao.GetUser(queryUser)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) beego.Error("Error occurred in GetUser:", err)
rpc.CustomAbort(500, "Internal error.") rpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
if user != nil { if user != nil {
rpc.Data["ResetUuid"] = user.ResetUuid rpc.Data["ResetUuid"] = user.ResetUuid
rpc.ForwardTo("page_title_reset_password", "reset-password") rpc.ForwardTo("page_title_reset_password", "reset-password")
} else { } else {
rpc.Redirect("/", 302) rpc.Redirect("/", http.StatusFound)
} }
} }
func (rpc *CommonController) ResetPassword() { func (rpc *CommonController) ResetPassword() {
resetUuid := rpc.GetString("reset_uuid") resetUuid := rpc.GetString("reset_uuid")
if resetUuid == "" {
rpc.CustomAbort(http.StatusBadRequest, "Reset uuid is blank.")
}
queryUser := models.User{ResetUuid: resetUuid} queryUser := models.User{ResetUuid: resetUuid}
user, err := dao.GetUser(queryUser) user, err := dao.GetUser(queryUser)
if err != nil { if err != nil {
beego.Error("Error occurred in GetUser:", err) 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(http.StatusBadRequest, "User does not exist")
} }
password := rpc.GetString("password") password := rpc.GetString("password")
if password != "" { if password != "" {
user.Password = password user.Password = password
dao.ResetUserPassword(*user) err = dao.ResetUserPassword(*user)
if err != nil {
beego.Error("Error occurred in ResetUserPassword:", err)
rpc.CustomAbort(http.StatusInternalServerError, "Internal error.")
}
} else { } else {
rpc.CustomAbort(404, "password_is_required") rpc.CustomAbort(http.StatusBadRequest, "password_is_required")
} }
} }

View File

@ -15,6 +15,7 @@
package controllers package controllers
import ( import (
"net/http"
"os" "os"
"strings" "strings"
@ -33,7 +34,7 @@ func (rc *RegisterController) Get() {
if authMode == "" || authMode == "db_auth" { if authMode == "" || authMode == "db_auth" {
rc.ForwardTo("page_title_registration", "register") rc.ForwardTo("page_title_registration", "register")
} else { } else {
rc.Redirect("/signIn", 404) rc.Redirect("/signIn", http.StatusNotFound)
} }
} }
@ -49,7 +50,7 @@ func (rc *CommonController) SignUp() {
_, err := dao.Register(user) _, err := dao.Register(user)
if err != nil { if err != nil {
beego.Error("Error occurred in Register:", err) 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) exist, err := dao.UserExists(user, target)
if err != nil { if err != nil {
beego.Error("Error occurred in UserExists:", err) beego.Error("Error occurred in UserExists:", err)
rc.CustomAbort(500, "Internal error.") rc.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
rc.Data["json"] = exist rc.Data["json"] = exist
rc.ServeJSON() rc.ServeJSON()

View File

@ -73,13 +73,13 @@ func GetAccessLogs(accessLog models.AccessLog) ([]models.AccessLog, error) {
} }
} }
} }
if accessLog.BeginTime != "" { if accessLog.BeginTimestamp > 0 {
sql += ` and a.op_time >= str_to_date(?, '%Y-%m-%d %H:%i:%s') ` sql += ` and a.op_time >= ? `
queryParam = append(queryParam, accessLog.BeginTime+" 00:00:00.000000") queryParam = append(queryParam, accessLog.BeginTime)
} }
if accessLog.EndTime != "" { if accessLog.EndTimestamp > 0 {
sql += ` and a.op_time <= str_to_date(?, '%Y-%m-%d %H:%i:%s') ` sql += ` and a.op_time <= ? `
queryParam = append(queryParam, accessLog.EndTime+" 23:59:59.99999") queryParam = append(queryParam, accessLog.EndTime)
} }
sql += ` order by a.op_time desc ` sql += ` order by a.op_time desc `

View File

@ -50,18 +50,17 @@ func isContainIllegalChar(s string, illegalChar []string) bool {
func GenerateRandomString() (string, error) { func GenerateRandomString() (string, error) {
o := orm.NewOrm() o := orm.NewOrm()
var salt string var uuid string
err := o.Raw(`select uuid() as uuid`).QueryRow(&salt) err := o.Raw(`select uuid() as uuid`).QueryRow(&uuid)
if err != nil { if err != nil {
return "", err return "", err
} }
return salt, nil return uuid, nil
} }
func init() { func InitDB() {
orm.RegisterDriver("mysql", orm.DRMySQL) orm.RegisterDriver("mysql", orm.DRMySQL)
addr := os.Getenv("MYSQL_HOST") addr := os.Getenv("MYSQL_HOST")
if len(addr) == 0 { if len(addr) == 0 {
addr = os.Getenv("MYSQL_PORT_3306_TCP_ADDR") addr = os.Getenv("MYSQL_PORT_3306_TCP_ADDR")
@ -112,8 +111,11 @@ func init() {
}() }()
select { select {
case <-ch: case <-ch:
case <-time.After(30 * time.Second): case <-time.After(60 * time.Second):
panic("Failed to connect to DB after 30 seconds") panic("Failed to connect to DB after 60 seconds")
}
err := orm.RegisterDataBase("default", "mysql", db_str)
if err != nil {
panic(err)
} }
orm.RegisterDataBase("default", "mysql", db_str)
} }

View File

@ -15,6 +15,9 @@
package dao package dao
import ( import (
"database/sql"
"errors"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/vmware/harbor/utils" "github.com/vmware/harbor/utils"
@ -133,15 +136,44 @@ func ToggleUserAdminRole(u models.User) error {
return err return err
} }
func ChangeUserPassword(u models.User) error { func ChangeUserPassword(u models.User, oldPassword ...string) error {
o := orm.NewOrm() 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() var err 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.
_, 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.")
}
return err return err
} }
func ResetUserPassword(u models.User) error { func ResetUserPassword(u models.User) error {
o := orm.NewOrm() 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 err != nil {
return err
}
if count == 0 {
return errors.New("No record be changed, reset password failed.")
}
return err return err
} }

12
main.go
View File

@ -38,7 +38,7 @@ func updateInitPassword(userId int, password string) error {
queryUser := models.User{UserId: userId} queryUser := models.User{UserId: userId}
user, err := dao.GetUser(queryUser) user, err := dao.GetUser(queryUser)
if err != nil { if err != nil {
log.Println("Failed to get user in initial password, userId:", userId) log.Println("Failed to get user, userId:", userId)
return err return err
} }
if user == nil { if user == nil {
@ -67,15 +67,7 @@ func updateInitPassword(userId int, password string) error {
func main() { func main() {
beego.BConfig.WebConfig.Session.SessionOn = true beego.BConfig.WebConfig.Session.SessionOn = true
dao.InitDB()
//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")) updateInitPassword(ADMIN_USER_ID, os.Getenv("HARBOR_ADMIN_PASSWORD"))
beego.Run() beego.Run()
} }

View File

@ -26,10 +26,11 @@ type AccessLog struct {
Guid string Guid string
Operation string Operation string
OpTime time.Time OpTime time.Time
OpTimeStr string
Username string Username string
Keywords string Keywords string
BeginTime string
EndTime string BeginTime time.Time
BeginTimestamp int64
EndTime time.Time
EndTimestamp int64
} }

View File

@ -16,6 +16,7 @@ package service
import ( import (
"log" "log"
"net/http"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"github.com/vmware/harbor/opt_auth" "github.com/vmware/harbor/opt_auth"
@ -46,7 +47,7 @@ func (a *AuthController) Auth() {
if len(scope) == 0 && !authenticated { if len(scope) == 0 && !authenticated {
log.Printf("login request with invalid credentials") log.Printf("login request with invalid credentials")
a.CustomAbort(401, "") a.CustomAbort(http.StatusUnauthorized, "")
} }
access := svc_utils.GetResourceActions(scope) access := svc_utils.GetResourceActions(scope)
for _, a := range access { 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) rawToken, err := svc_utils.MakeToken(username, service, access)
if err != nil { if err != nil {
log.Printf("Failed to make token, error: %v", err) log.Printf("Failed to make token, error: %v", err)
writer.WriteHeader(500) writer.WriteHeader(http.StatusInternalServerError)
return return
} }
tk := make(map[string]string) tk := make(map[string]string)

View File

@ -50,9 +50,9 @@ func RegistryApiGet(url, username string) ([]byte, error) {
return nil, err return nil, err
} }
defer response.Body.Close() defer response.Body.Close()
if response.StatusCode == 200 { if response.StatusCode == http.StatusOK {
return result, nil return result, nil
} else if response.StatusCode == 401 { } else if response.StatusCode == http.StatusUnauthorized {
authenticate := response.Header.Get("WWW-Authenticate") authenticate := response.Header.Get("WWW-Authenticate")
str := strings.Split(authenticate, " ")[1] str := strings.Split(authenticate, " ")[1]
log.Println("url: " + url) log.Println("url: " + url)
@ -94,7 +94,7 @@ func RegistryApiGet(url, username string) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if response.StatusCode != 200 { if response.StatusCode != http.StatusOK {
errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode) errMsg := fmt.Sprintf("Unexpected return code from registry: %d", response.StatusCode)
log.Printf(errMsg) log.Printf(errMsg)
return nil, fmt.Errorf(errMsg) return nil, fmt.Errorf(errMsg)

View File

@ -374,24 +374,38 @@ jQuery(function(){
listUser(username); 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(){ $("#btnFilterLog").on("click", function(){
var projectId = $("#projectId").val(); var projectId = $("#projectId").val();
var username = $("#txtSearchUserName").val(); var username = $("#txtSearchUserName").val();
var beginTime = ""; var beginTimestamp = 0;
var endTime = ""; var endTimestamp = 0;
if($("#begindatepicker").val() != ""){ if($("#begindatepicker").val() != ""){
beginTime = moment(new Date($("#begindatepicker").val())).format("YYYY-MM-DD"); beginTimestamp = toUTCSeconds($("#begindatepicker").val(), 0, 0, 0);
} }
if($("#enddatepicker").val() != ""){ if($("#enddatepicker").val() != ""){
endTime = moment(new Date($("#enddatepicker").val())).format("YYYY-MM-DD"); endTimestamp = toUTCSeconds($("#enddatepicker").val(), 23, 59, 59);
} }
new AjaxUtil({ new AjaxUtil({
url: "/api/projects/" + projectId + "/logs/filter", 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", type: "post",
success: function(data, status, xhr){ success: function(data, status, xhr){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){

View File

@ -15,8 +15,8 @@
package test package test
import ( import (
"flag"
"fmt" "fmt"
// "fmt"
"log" "log"
"os" "os"
"testing" "testing"
@ -85,9 +85,7 @@ func clearUp(username string) {
} }
const USERNAME string = "Tester01" const USERNAME string = "Tester01"
const PROJECT_NAME string = "test_project" const PROJECT_NAME string = "test_project"
const SYS_ADMIN int = 1 const SYS_ADMIN int = 1
const PROJECT_ADMIN int = 2 const PROJECT_ADMIN int = 2
const DEVELOPER int = 3 const DEVELOPER int = 3
@ -98,35 +96,37 @@ const PUBLICITY_OFF = 0
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
//Create a custom flag set, let user to provide DB related configures for testing. dbHost := os.Getenv("DB_HOST")
fs := flag.NewFlagSet("DB related configures", 0) if len(dbHost) == 0 {
log.Fatalf("environment variable DB_HOST is not set")
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 := os.Getenv("DB_USR")
dbUser := fs.String("db_user", "root", "Username for logging in a test DB.") if len(dbUser) == 0 {
dbPassword := fs.String("db_password", "root", "Password for logging in a test DB.") log.Fatalf("environment variable DB_USR is not set")
}
fs.Parse([]string{"db_ip", "db_port", "db_user", "db_password"}) dbPort := os.Getenv("DB_PORT")
if len(dbPort) == 0 {
if fs.NFlag() == 0 { log.Fatalf("environment variable DB_PORT is not set")
fs.PrintDefaults() }
fmt.Println("Now, use DEFAULT values if omit to set all of flags.") dbPassword := os.Getenv("DB_PWD")
if len(dbPassword) == 0 {
log.Fatalf("environment variable DB_PWD is not set")
} }
if fs.Parsed() { fmt.Printf("DB_HOST: %s, DB_USR: %s, DB_PORT: %s, DB_PWD: %s\n", dbHost, dbUser, dbPort, dbPassword)
clearUp(USERNAME) os.Setenv("MYSQL_PORT_3306_TCP_ADDR", dbHost)
os.Setenv("MYSQL_PORT_3306_TCP_PORT", dbPort)
os.Setenv("MYSQL_PORT_3306_TCP_ADDR", *dbIp) os.Setenv("MYSQL_USR", dbUser)
os.Setenv("MYSQL_PORT_3306_TCP_PORT", *dbPort) os.Setenv("MYSQL_PWD", dbPassword)
os.Setenv("MYSQL_USR", *dbUser)
os.Setenv("MYSQL_PWD", *dbPassword)
os.Setenv("AUTH_MODE", "db_auth") os.Setenv("AUTH_MODE", "db_auth")
dao.InitDB()
clearUp(USERNAME)
os.Exit(m.Run()) os.Exit(m.Run())
}
} }
func ExampleRegister() { func TestRegister(t *testing.T) {
user := models.User{ user := models.User{
Username: USERNAME, Username: USERNAME,
@ -138,7 +138,7 @@ func ExampleRegister() {
_, err := dao.Register(user) _, err := dao.Register(user)
if err != nil { if err != nil {
log.Printf("Error occurred in Register: %v", err) t.Errorf("Error occurred in Register: %v", err)
} }
//Check if user registered successfully. //Check if user registered successfully.
@ -147,41 +147,46 @@ func ExampleRegister() {
} }
newUser, err := dao.GetUser(queryUser) newUser, err := dao.GetUser(queryUser)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetUser: %v", err) t.Errorf("Error occurred in GetUser: %v", err)
} }
fmt.Println(newUser.Username) if newUser.Username != USERNAME {
fmt.Println(newUser.Email) t.Errorf("Username does not match, expected: %s, actual: %s", USERNAME, newUser.Username)
// Output: }
// Tester01 if newUser.Email != "tester01@vmware.com" {
// 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 exists bool
var err error var err error
exists, err = dao.UserExists(models.User{Username: "Tester01"}, "username") exists, err = dao.UserExists(models.User{Username: USERNAME}, "username")
fmt.Println(exists)
if err != nil { 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") exists, err = dao.UserExists(models.User{Email: "tester01@vmware.com"}, "email")
fmt.Println(exists)
if err != nil { 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: func TestLoginByUserName(t *testing.T) {
//true
//true
}
func ExampleLoginByUserName() {
userQuery := models.User{ userQuery := models.User{
Username: USERNAME, Username: USERNAME,
@ -190,18 +195,18 @@ func ExampleLoginByUserName() {
loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Username, userQuery.Password}) loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Username, userQuery.Password})
if err != nil { if err != nil {
log.Fatalf("Error occurred in LoginByDb: %v", err) t.Errorf("Error occurred in LoginByDb: %v", err)
} }
if loginUser == nil { 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) if loginUser.Username != USERNAME {
// Output: t.Errorf("User's username does not match after login, expected: %s, actual: %s", USERNAME, loginUser.Username)
// Tester01 }
} }
func ExampleLoginByEmail() { func TestLoginByEmail(t *testing.T) {
userQuery := models.User{ userQuery := models.User{
Email: "tester01@vmware.com", Email: "tester01@vmware.com",
@ -210,105 +215,136 @@ func ExampleLoginByEmail() {
loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Email, userQuery.Password}) loginUser, err := dao.LoginByDb(models.AuthModel{userQuery.Email, userQuery.Password})
if err != nil { if err != nil {
log.Fatalf("Error occurred in LoginByDb: %v", err) t.Errorf("Error occurred in LoginByDb: %v", err)
} }
if loginUser == nil { 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 var currentUser *models.User
func ExampleGetUser() { func TestGetUser(t *testing.T) {
queryUser := models.User{ queryUser := models.User{
Username: USERNAME, Username: USERNAME,
} }
var err error var err error
currentUser, err = dao.GetUser(queryUser) currentUser, err = dao.GetUser(queryUser)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetUser", err) t.Errorf("Error occurred in GetUser: %v", err)
} }
if currentUser == nil { 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() { func TestListUsers(t *testing.T) {
users, err := dao.ListUsers(models.User{Username: "tester01"}) users, err := dao.ListUsers(models.User{})
if err != nil { if err != nil {
log.Fatalf("Error occurred in ListUsers: %v", err) t.Errorf("Error occurred in ListUsers: %v", err)
}
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)
}
} }
for _, u := range users { func TestResetUserPassword(t *testing.T) {
fmt.Println(u.Username)
}
//Output:
//Tester01
}
func ExampleResetUserPassword() {
uuid, err := dao.GenerateRandomString() uuid, err := dao.GenerateRandomString()
if err != nil { 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}) err = dao.UpdateUserResetUuid(models.User{ResetUuid: uuid, Email: currentUser.Email})
if err != nil { 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}) err = dao.ResetUserPassword(models.User{UserId: currentUser.UserId, Password: "HarborTester12345", ResetUuid: uuid, Salt: currentUser.Salt})
if err != nil { 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"}) loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "HarborTester12345"})
if err != nil { if err != nil {
log.Fatalf("Error occurred in LoginByDb: %v", err) t.Errorf("Error occurred in LoginByDb: %v", err)
} }
fmt.Println(loginedUser.Username) if loginedUser.Username != USERNAME {
//Output: t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username)
//Tester01 }
} }
func ExampleChangeUserPassword() { func TestChangeUserPassword(t *testing.T) {
err := dao.ChangeUserPassword(models.User{UserId: currentUser.UserId, Password: "NewHarborTester12345", Salt: currentUser.Salt}) err := dao.ChangeUserPassword(models.User{UserId: currentUser.UserId, Password: "NewHarborTester12345", Salt: currentUser.Salt})
if err != nil { 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"}) loginedUser, err := dao.LoginByDb(models.AuthModel{Principal: currentUser.Username, Password: "NewHarborTester12345"})
if err != nil { if err != nil {
log.Fatalf("Error occurred in LoginByDb: %v", err) t.Errorf("Error occurred in LoginByDb: %v", err)
} }
fmt.Println(loginedUser.Username) if loginedUser.Username != USERNAME {
//Output: t.Errorf("The username returned by Login does not match, expected: %s, acutal: %s", USERNAME, loginedUser.Username)
//Tester01 }
} }
func ExampleQueryRelevantProjectsWhenNoProjectAdded() { 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 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) projects, err := dao.QueryRelevantProjects(currentUser.UserId)
if err != nil { if err != nil {
log.Fatalf("Error occurred in QueryRelevantProjects: %v", err) t.Errorf("Error occurred in QueryRelevantProjects: %v", err)
} }
fmt.Println(len(projects)) if len(projects) != 1 {
for _, p := range projects { t.Errorf("Expected only one project in DB, but actual: %d", len(projects))
fmt.Println(p.Name) }
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{ project := models.Project{
OwnerId: currentUser.UserId, OwnerId: currentUser.UserId,
@ -319,35 +355,32 @@ func ExampleAddProject() {
err := dao.AddProject(project) err := dao.AddProject(project)
if err != nil { 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) newProject, err := dao.GetProjectByName(PROJECT_NAME)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetProjectByName: %v", err) t.Errorf("Error occurred in GetProjectByName: %v", err)
} }
if newProject == nil { 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 var currentProject *models.Project
func ExampleGetProject() { func TestGetProject(t *testing.T) {
var err error var err error
currentProject, err = dao.GetProjectByName(PROJECT_NAME) currentProject, err = dao.GetProjectByName(PROJECT_NAME)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetProjectByName: %v", err) t.Errorf("Error occurred in GetProjectByName: %v", err)
} }
if currentProject == nil { 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 { func getProjectRole(projectId int64) []models.Role {
@ -358,89 +391,86 @@ func getProjectRole(projectId int64) []models.Role {
left join role r on pr.role_id = r.role_id left join role r on pr.role_id = r.role_id
where project_id = ?`, projectId).QueryRows(&r) where project_id = ?`, projectId).QueryRows(&r)
if err != nil { 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 return r
} }
func ExampleCheckProjectRoles() { func TestCheckProjectRoles(t *testing.T) {
r := getProjectRole(currentProject.ProjectId) r := getProjectRole(currentProject.ProjectId)
fmt.Println(len(r)) if len(r) != 3 {
t.Errorf("The length of project roles is not 3")
for _, pr := range r { }
fmt.Println(pr.RoleId, pr.Name) 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 func TestGetAccessLog(t *testing.T) {
//2 projectAdmin
//3 developer
//4 guest
}
func ExampleGetAccessLog() {
queryAccessLog := models.AccessLog{ queryAccessLog := models.AccessLog{
UserId: currentUser.UserId, UserId: currentUser.UserId,
ProjectId: currentProject.ProjectId, ProjectId: currentProject.ProjectId,
} }
accessLogs, err := dao.GetAccessLogs(queryAccessLog) accessLogs, err := dao.GetAccessLogs(queryAccessLog)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetAccessLog: %v", err) t.Errorf("Error occurred in GetAccessLog: %v", err)
} }
fmt.Println(len(accessLogs)) if len(accessLogs) != 1 {
for _, log := range accessLogs { t.Errorf("The length of accesslog list should be 1, actual: %d", len(accessLogs))
fmt.Println(log.Operation, log.RepoName) }
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 exists bool
var err error var err error
exists, err = dao.ProjectExists(currentProject.ProjectId) exists, err = dao.ProjectExists(currentProject.ProjectId)
fmt.Println(exists)
if err != nil { 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) exists, err = dao.ProjectExists(currentProject.Name)
fmt.Println(exists)
if err != nil { 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) err := dao.ToggleProjectPublicity(currentProject.ProjectId, PUBLICITY_ON)
if err != nil { 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) currentProject, err = dao.GetProjectByName(PROJECT_NAME)
if err != nil { 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) err = dao.ToggleProjectPublicity(currentProject.ProjectId, PUBLICITY_OFF)
if err != nil { 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) currentProject, err = dao.GetProjectByName(PROJECT_NAME)
if err != nil { if err != nil {
log.Fatalf("Error occurred in GetProjectByName: %v", err) t.Errorf("Error occurred in GetProjectByName: %v", err)
} }
fmt.Println(currentProject.Public) if currentProject.Public != PUBLICITY_OFF {
//Output: t.Errorf("project, id: %d, its publicity is not off", currentProject.ProjectId)
//1 }
//0
} }
func getUserProjectRole(projectId int64, userId int) []models.Role { func getUserProjectRole(projectId int64, userId int) []models.Role {
@ -457,99 +487,83 @@ func getUserProjectRole(projectId int64, userId int) []models.Role {
return r return r
} }
func ExampleGetUserProjectRole() { func TestGetUserProjectRole(t *testing.T) {
r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId) r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId)
//Get the size of current user project role. //Get the size of current user project role.
fmt.Println(len(r)) 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))
//Iterating current user project role info.
for _, upr := range r {
fmt.Println(upr.RoleId, upr.Name)
} }
//Output: if r[0].Name != "projectAdmin" {
//1 t.Errorf("the expected rolename is: projectAdmin, actual: %s", r[0].Name)
//2 projectAdmin }
} }
func ExampleProjectPermission() { func TestProjectPermission(t *testing.T) {
roleCode, err := dao.GetPermission(currentUser.Username, currentProject.Name) roleCode, err := dao.GetPermission(currentUser.Username, currentProject.Name)
if err != nil { 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) projects, err := dao.QueryRelevantProjects(currentUser.UserId)
if err != nil { if err != nil {
log.Fatalf("Error occurred in QueryRelevantProjects: %v", err) t.Errorf("Error occurred in QueryRelevantProjects: %v", err)
} }
fmt.Println(len(projects)) if len(projects) != 2 {
for _, p := range projects { t.Errorf("Expected length of relevant projects is 2, but actual: %d, the projects: %+v", len(projects), projects)
fmt.Println(p.Name) }
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) err := dao.AddUserProjectRole(currentUser.UserId, currentProject.ProjectId, DEVELOPER)
if err != nil { 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) r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId)
//Get the size of current user project role info. //Get the size of current user project role info.
fmt.Println(len(r)) if len(r) != 2 {
t.Errorf("Expected length of role list is 2, actual: %d", len(r))
//Iterating current user project role.
for _, upr := range r {
fmt.Println(upr.RoleId, upr.Name)
} }
//Output: if r[1].RoleId != 3 {
//2 t.Errorf("Expected role id of the second role in list is 3, actual: %d", r[1].RoleId)
//2 projectAdmin }
//3 developer
} }
func ExampleDeleteUserProjectRole() { func TestDeleteUserProjectRole(t *testing.T) {
err := dao.DeleteUserProjectRoles(currentUser.UserId, currentProject.ProjectId) err := dao.DeleteUserProjectRoles(currentUser.UserId, currentProject.ProjectId)
if err != nil { 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) r := getUserProjectRole(currentProject.ProjectId, currentUser.UserId)
//Get the size of current user project role. //Get the size of current user project role.
fmt.Println(len(r)) if len(r) != 0 {
t.Errorf("Expected role list length is 0, actual: %d, role list: %+v", len(r), r)
//Iterating current user project role info. }
for _, upr := range r {
fmt.Println(upr.RoleId, upr.Name)
} }
//Output: func TestDeleteUser(t *testing.T) {
//0
}
func ExampleDeleteUser() {
err := dao.DeleteUser(currentUser.UserId) err := dao.DeleteUser(currentUser.UserId)
if err != nil { if err != nil {
log.Fatalf("Error occurred in DeleteUser: %v", err) t.Errorf("Error occurred in DeleteUser: %v", err)
} }
user, err := dao.GetUser(*currentUser) user, err := dao.GetUser(*currentUser)
if err != nil { 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:
//<nil>
} }

View File

@ -55,9 +55,9 @@ func HttpGet(url, sessionId, username, password string) ([]byte, error) {
return nil, err return nil, err
} }
defer response.Body.Close() defer response.Body.Close()
if response.StatusCode == 200 { if response.StatusCode == http.StatusOK {
return result, nil return result, nil
} else if response.StatusCode == 401 { } else if response.StatusCode == http.StatusUnauthorized {
authenticate := response.Header.Get("WWW-Authenticate") authenticate := response.Header.Get("WWW-Authenticate")
str := strings.Split(authenticate, " ")[1] str := strings.Split(authenticate, " ")[1]
beego.Trace("url: " + url) beego.Trace("url: " + url)
@ -106,7 +106,7 @@ func HttpGet(url, sessionId, username, password string) ([]byte, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
if response.StatusCode == 200 { if response.StatusCode == http.StatusOK {
tt := make(map[string]string) tt := make(map[string]string)
json.Unmarshal(result, &tt) json.Unmarshal(result, &tt)
request, err = http.NewRequest("GET", url, nil) request, err = http.NewRequest("GET", url, nil)

View File

@ -16,6 +16,6 @@
<html> <html>
<body> <body>
<p>{{.Hint}}:</p> <p>{{.Hint}}:</p>
<a href="{{.Url}}/resetPassword?q={{.Uuid}}">{{.Url}}/resetPassword?q={{.Uuid}}</a> <a href="{{.Url}}/resetPassword?reset_uuid={{.Uuid}}">{{.Url}}/resetPassword?reset_uuid={{.Uuid}}</a>
</body> </body>
</html> </html>