change code for user and logapi

This commit is contained in:
wemeya 2016-05-25 14:21:01 +08:00
parent f3ae27649b
commit 25a88f8e29
7 changed files with 129 additions and 117 deletions

View File

@ -162,8 +162,8 @@ func (p *ProjectAPI) Get() {
p.ServeJSON() p.ServeJSON()
} }
// Put ... // ToggleProjectPublic handles request POST /api/projects/:id/toggle_project_public
func (p *ProjectAPI) Put() { func (p *ProjectAPI) ToggleProjectPublic() {
var req projectReq var req projectReq
var public int var public int
@ -252,5 +252,11 @@ func validateProjectReq(req projectReq) error {
if len(pn) > projectNameMaxLen { if len(pn) > projectNameMaxLen {
return fmt.Errorf("Project name is too long") return fmt.Errorf("Project name is too long")
} }
if isIllegalLength(req.ProjectName, 4, 30) {
return fmt.Errorf("project name is illegal in length. (greater than 4 or less than 30)")
}
if isContainIllegalChar(req.ProjectName, []string{"~", "-", "$", "\\", "[", "]", "{", "}", "(", ")", "&", "^", "%", "*", "<", ">", "\"", "'", "/", "?", "@"}) {
return fmt.Errorf("project name contains illegal characters")
}
return nil return nil
} }

View File

@ -16,8 +16,10 @@
package api package api
import ( import (
"fmt"
"net/http" "net/http"
"os" "os"
"regexp"
"strconv" "strconv"
"strings" "strings"
@ -133,14 +135,40 @@ func (ua *UserAPI) Get() {
} }
// Put ... // Put ...
func (ua *UserAPI) Put() { //currently only for toggle admin, so no request body func (ua *UserAPI) Put() {
ldapAdminUser := (ua.AuthMode == "ldap_auth" && ua.userID == 1 && ua.userID == ua.currentUserID)
if !(ua.AuthMode == "db_auth" || ldapAdminUser) {
ua.CustomAbort(http.StatusForbidden, "")
}
if !ua.IsAdmin { if !ua.IsAdmin {
log.Warningf("current user, id: %d does not have admin role, can not update other user's role", ua.currentUserID) if ua.userID != ua.currentUserID {
ua.RenderError(http.StatusForbidden, "User does not have admin role") log.Error("Guests can only change their own account.")
ua.CustomAbort(http.StatusForbidden, "Guests can only change their own account.")
}
}
user := models.User{UserID: ua.userID}
ua.DecodeJSONReq(&user)
err := commonValidate(user)
if err != nil {
log.Errorf("Bad request in change user profile: %v", err)
ua.RenderError(http.StatusBadRequest, "change user profile error:"+err.Error())
return return
} }
userQuery := models.User{UserID: ua.userID} emailExist, err := dao.UserExists(user, "email")
dao.ToggleUserAdminRole(userQuery) if err != nil {
log.Errorf("Error occurred in change user profile: %v", err)
ua.RenderError(http.StatusInternalServerError, "Internal error.")
return
}
if emailExist {
log.Warning("email has already been used!")
ua.CustomAbort(http.StatusForbidden, "email has already been used!")
}
if err := dao.ChangeUserProfile(user); err != nil {
log.Errorf("Failed to update user profile, error: %v", err)
ua.CustomAbort(http.StatusInternalServerError, err.Error())
}
} }
// Post ... // Post ...
@ -157,7 +185,22 @@ func (ua *UserAPI) Post() {
user := models.User{} user := models.User{}
ua.DecodeJSONReq(&user) ua.DecodeJSONReq(&user)
err := validate(user)
if err != nil {
log.Errorf("Bad request in Register: %v", err)
ua.RenderError(http.StatusBadRequest, "register error:"+err.Error())
return
}
userExist, err := dao.UserExists(user, "username")
if err != nil {
log.Errorf("Error occurred in Register: %v", err)
ua.RenderError(http.StatusInternalServerError, "Internal error.")
return
}
if userExist {
log.Warning("username has already been used!")
ua.CustomAbort(http.StatusForbidden, "username has already been used!")
}
userID, err := dao.Register(user) userID, err := dao.Register(user)
if err != nil { if err != nil {
log.Errorf("Error occurred in Register: %v", err) log.Errorf("Error occurred in Register: %v", err)
@ -228,23 +271,75 @@ func (ua *UserAPI) ChangePassword() {
} }
} }
// ChangeProfile handles PUT api/users/{}/profile // ToggleUserAdminRole handles Post api/users/{}/toggleadmin
func (ua *UserAPI) ChangeProfile() { func (ua *UserAPI) ToggleUserAdminRole() {
ldapAdminUser := (ua.AuthMode == "ldap_auth" && ua.userID == 1 && ua.userID == ua.currentUserID)
if !(ua.AuthMode == "db_auth" || ldapAdminUser) {
ua.CustomAbort(http.StatusForbidden, "")
}
if !ua.IsAdmin { if !ua.IsAdmin {
if ua.userID != ua.currentUserID { log.Warningf("current user, id: %d does not have admin role, can not update other user's role", ua.currentUserID)
log.Error("Guests can only change their own account.") ua.RenderError(http.StatusForbidden, "User does not have admin role")
ua.CustomAbort(http.StatusForbidden, "Guests can only change their own account.") return
}
userQuery := models.User{UserID: ua.userID}
if err := dao.ToggleUserAdminRole(userQuery); err != nil {
log.Errorf("Error occurred in ToggleUserAdminRole: %v", err)
ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
} }
} }
user := models.User{UserID: ua.userID}
ua.DecodeJSONReq(&user) func validate(user models.User) error {
if err := dao.ChangeUserProfile(user); err != nil {
log.Errorf("Failed to update user profile, error: %v", err) if isIllegalLength(user.Username, 0, 20) {
ua.CustomAbort(http.StatusInternalServerError, err.Error()) return fmt.Errorf("Username with illegal length.")
}
if isContainIllegalChar(user.Username, []string{",", "~", "#", "$", "%"}) {
return fmt.Errorf("Username contains illegal characters.")
}
if isIllegalLength(user.Password, 0, 20) {
return fmt.Errorf("Password with illegal length.")
}
if err := commonValidate(user); err != nil {
return err
}
return nil
}
//commonValidate validates information when user register or change their profile
func commonValidate(user models.User) error {
if len(user.Email) > 0 {
if m, _ := 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,}))$`, user.Email); !m {
return fmt.Errorf("Email with illegal format.")
} }
} }
if isIllegalLength(user.Realname, 0, 20) {
return fmt.Errorf("Realname with illegal length.")
}
if isContainIllegalChar(user.Realname, []string{",", "~", "#", "$", "%"}) {
return fmt.Errorf("Realname contains illegal characters.")
}
if isIllegalLength(user.Comment, -1, 30) {
return fmt.Errorf("Comment with illegal length.")
}
return nil
}
func isIllegalLength(s string, min int, max int) bool {
if min == -1 {
return (len(s) > max)
}
if max == -1 {
return (len(s) <= min)
}
return (len(s) < min || len(s) > max)
}
func isContainIllegalChar(s string, illegalChar []string) bool {
for _, c := range illegalChar {
if strings.Index(s, c) >= 0 {
return true
}
}
return false
}

View File

@ -19,7 +19,6 @@ import (
"net" "net"
"os" "os"
"strings"
"time" "time"
"github.com/astaxie/beego/orm" "github.com/astaxie/beego/orm"
@ -31,25 +30,6 @@ import (
// NonExistUserID : if a user does not exist, the ID of the user will be 0. // NonExistUserID : if a user does not exist, the ID of the user will be 0.
const NonExistUserID = 0 const NonExistUserID = 0
func isIllegalLength(s string, min int, max int) bool {
if min == -1 {
return (len(s) > max)
}
if max == -1 {
return (len(s) <= min)
}
return (len(s) < min || len(s) > max)
}
func isContainIllegalChar(s string, illegalChar []string) bool {
for _, c := range illegalChar {
if strings.Index(s, c) >= 0 {
return true
}
}
return false
}
// GenerateRandomString generates a random string // GenerateRandomString generates a random string
func GenerateRandomString() (string, error) { func GenerateRandomString() (string, error) {
o := orm.NewOrm() o := orm.NewOrm()

View File

@ -18,7 +18,6 @@ package dao
import ( import (
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
"errors"
"fmt" "fmt"
"time" "time"
@ -30,14 +29,6 @@ import (
// AddProject adds a project to the database along with project roles information and access log records. // AddProject adds a project to the database along with project roles information and access log records.
func AddProject(project models.Project) (int64, error) { func AddProject(project models.Project) (int64, error) {
if isIllegalLength(project.Name, 4, 30) {
return 0, errors.New("project name is illegal in length. (greater than 4 or less than 30)")
}
if isContainIllegalChar(project.Name, []string{"~", "-", "$", "\\", "[", "]", "{", "}", "(", ")", "&", "^", "%", "*", "<", ">", "\"", "'", "/", "?", "@"}) {
return 0, errors.New("project name contains illegal characters")
}
o := orm.NewOrm() o := orm.NewOrm()
p, err := o.Raw("insert into project (owner_id, name, creation_time, update_time, deleted, public) values (?, ?, ?, ?, ?, ?)").Prepare() p, err := o.Raw("insert into project (owner_id, name, creation_time, update_time, deleted, public) values (?, ?, ?, ?, ?, ?)").Prepare()

View File

@ -17,7 +17,6 @@ package dao
import ( import (
"errors" "errors"
"regexp"
"time" "time"
"github.com/vmware/harbor/models" "github.com/vmware/harbor/models"
@ -29,11 +28,6 @@ import (
// Register is used for user to register, the password is encrypted before the record is inserted into database. // Register is used for user to register, the password is encrypted before the record is inserted into database.
func Register(user models.User) (int64, error) { func Register(user models.User) (int64, error) {
err := validate(user)
if err != nil {
return 0, err
}
o := orm.NewOrm() o := orm.NewOrm()
p, err := o.Raw("insert into user (username, password, realname, email, comment, salt, sysadmin_flag, creation_time, update_time) values (?, ?, ?, ?, ?, ?, ?, ?, ?)").Prepare() p, err := o.Raw("insert into user (username, password, realname, email, comment, salt, sysadmin_flag, creation_time, update_time) values (?, ?, ?, ?, ?, ?, ?, ?, ?)").Prepare()
@ -61,56 +55,6 @@ func Register(user models.User) (int64, error) {
return userID, nil return userID, nil
} }
func validate(user models.User) error {
if isIllegalLength(user.Username, 0, 20) {
return errors.New("Username with illegal length.")
}
if isContainIllegalChar(user.Username, []string{",", "~", "#", "$", "%"}) {
return errors.New("Username contains illegal characters.")
}
if exist, _ := UserExists(models.User{Username: user.Username}, "username"); exist {
return errors.New("Username already exists.")
}
if isIllegalLength(user.Password, 0, 20) {
return errors.New("Password with illegal length.")
}
if err := commonValidate(user); err != nil {
return err
}
return nil
}
//commonValidate validates information when user register or change their profile
func commonValidate(user models.User) error {
if len(user.Email) > 0 {
if m, _ := 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,}))$`, user.Email); !m {
return errors.New("Email with illegal format.")
}
if exist, _ := UserExists(models.User{Email: user.Email}, "email"); exist {
return errors.New("Email already exists.")
}
} else {
return errors.New("Email can't be empty")
}
if isIllegalLength(user.Realname, 0, 20) {
return errors.New("Realname with illegal length.")
}
if isContainIllegalChar(user.Realname, []string{",", "~", "#", "$", "%"}) {
return errors.New("Realname contains illegal characters.")
}
if isIllegalLength(user.Comment, -1, 30) {
return errors.New("Comment with illegal length.")
}
return nil
}
// UserExists returns whether a user exists according username or Email. // UserExists returns whether a user exists according username or Email.
func UserExists(user models.User, target string) (bool, error) { func UserExists(user models.User, target string) (bool, error) {

View File

@ -233,13 +233,8 @@ func DeleteUser(userID int) error {
// ChangeUserProfile ... // ChangeUserProfile ...
func ChangeUserProfile(user models.User) error { func ChangeUserProfile(user models.User) error {
err := commonValidate(user)
if err != nil {
log.Errorf("user check failed! error: %v", err)
return err
}
o := orm.NewOrm() o := orm.NewOrm()
if _, err = o.Update(&user, "Email", "Realname", "Comment"); err != nil { if _, err := o.Update(&user, "Email", "Realname", "Comment"); err != nil {
log.Errorf("update user failed, error: %v", err) log.Errorf("update user failed, error: %v", err)
return err return err
} }

View File

@ -54,12 +54,13 @@ func initRouters() {
beego.Router("/api/search", &api.SearchAPI{}) beego.Router("/api/search", &api.SearchAPI{})
beego.Router("/api/projects/:pid/members/?:mid", &api.ProjectMemberAPI{}) beego.Router("/api/projects/:pid/members/?:mid", &api.ProjectMemberAPI{})
beego.Router("/api/projects/?:id", &api.ProjectAPI{}) beego.Router("/api/projects/?:id", &api.ProjectAPI{})
beego.Router("/api/projects/:id/toggle_project_public", &api.ProjectAPI{}, "post:ToggleProjectPublic")
beego.Router("/api/statistics", &api.StatisticAPI{}) beego.Router("/api/statistics", &api.StatisticAPI{})
beego.Router("/api/projects/:id/logs/filter", &api.ProjectAPI{}, "post:FilterAccessLog") beego.Router("/api/projects/:id/logs/filter", &api.ProjectAPI{}, "post:FilterAccessLog")
beego.Router("/api/users", &api.UserAPI{}) beego.Router("/api/users", &api.UserAPI{})
beego.Router("/api/users/?:id", &api.UserAPI{}) beego.Router("/api/users/?:id", &api.UserAPI{})
beego.Router("/api/users/:id/password", &api.UserAPI{}, "put:ChangePassword") beego.Router("/api/users/:id/password", &api.UserAPI{}, "put:ChangePassword")
beego.Router("/api/users/:id/profile", &api.UserAPI{}, "put:ChangeProfile") beego.Router("/api/users/:id/toggle_user_admin", &api.UserAPI{}, "post:ToggleUserAdminRole")
beego.Router("/api/repositories", &api.RepositoryAPI{}) beego.Router("/api/repositories", &api.RepositoryAPI{})
beego.Router("/api/repositories/tags", &api.RepositoryAPI{}, "get:GetTags") beego.Router("/api/repositories/tags", &api.RepositoryAPI{}, "get:GetTags")
beego.Router("/api/repositories/manifests", &api.RepositoryAPI{}, "get:GetManifests") beego.Router("/api/repositories/manifests", &api.RepositoryAPI{}, "get:GetManifests")