mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-23 10:45:45 +01:00
change code for user and logapi
This commit is contained in:
parent
f3ae27649b
commit
25a88f8e29
@ -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
|
||||||
}
|
}
|
||||||
|
139
api/user.go
139
api/user.go
@ -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}
|
||||||
user := models.User{UserID: ua.userID}
|
if err := dao.ToggleUserAdminRole(userQuery); err != nil {
|
||||||
ua.DecodeJSONReq(&user)
|
log.Errorf("Error occurred in ToggleUserAdminRole: %v", err)
|
||||||
if err := dao.ChangeUserProfile(user); err != nil {
|
ua.CustomAbort(http.StatusInternalServerError, "Internal error.")
|
||||||
log.Errorf("Failed to update user profile, error: %v", err)
|
|
||||||
ua.CustomAbort(http.StatusInternalServerError, err.Error())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validate(user models.User) error {
|
||||||
|
|
||||||
|
if isIllegalLength(user.Username, 0, 20) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
20
dao/base.go
20
dao/base.go
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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) {
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func ListUsers(query models.User) ([]models.User, error) {
|
|||||||
func ToggleUserAdminRole(u models.User) error {
|
func ToggleUserAdminRole(u models.User) error {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
|
||||||
sql := `update user set sysadmin_flag =not sysadmin_flag where user_id = ?`
|
sql := `update user set sysadmin_flag = not sysadmin_flag where user_id = ?`
|
||||||
|
|
||||||
r, err := o.Raw(sql, u.UserID).Exec()
|
r, err := o.Raw(sql, u.UserID).Exec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user