Unknwon 9 роки тому
батько
коміт
978dc00305

+ 20 - 0
models/error.go

@@ -528,3 +528,23 @@ func IsErrAttachmentNotExist(err error) bool {
 func (err ErrAttachmentNotExist) Error() string {
 	return fmt.Sprintf("attachment does not exist [id: %d, uuid: %s]", err.ID, err.UUID)
 }
+
+//    _____          __  .__                   __  .__               __  .__
+//   /  _  \  __ ___/  |_|  |__   ____   _____/  |_|__| ____ _____ _/  |_|__| ____   ____
+//  /  /_\  \|  |  \   __\  |  \_/ __ \ /    \   __\  |/ ___\\__  \\   __\  |/  _ \ /    \
+// /    |    \  |  /|  | |   Y  \  ___/|   |  \  | |  \  \___ / __ \|  | |  (  <_> )   |  \
+// \____|__  /____/ |__| |___|  /\___  >___|  /__| |__|\___  >____  /__| |__|\____/|___|  /
+//         \/                 \/     \/     \/             \/     \/                    \/
+
+type ErrAuthenticationNotExist struct {
+	ID int64
+}
+
+func IsErrAuthenticationNotExist(err error) bool {
+	_, ok := err.(ErrAuthenticationNotExist)
+	return ok
+}
+
+func (err ErrAuthenticationNotExist) Error() string {
+	return fmt.Sprintf("Authentication does not exist [id: %d]", err.ID)
+}

+ 2 - 2
models/login.go

@@ -36,7 +36,6 @@ const (
 
 var (
 	ErrAuthenticationAlreadyExist = errors.New("Authentication already exist")
-	ErrAuthenticationNotExist     = errors.New("Authentication does not exist")
 	ErrAuthenticationUserUsed     = errors.New("Authentication has been used by some users")
 )
 
@@ -191,13 +190,14 @@ func LoginSources() ([]*LoginSource, error) {
 	return auths, x.Find(&auths)
 }
 
+// GetLoginSourceByID returns login source by given ID.
 func GetLoginSourceByID(id int64) (*LoginSource, error) {
 	source := new(LoginSource)
 	has, err := x.Id(id).Get(source)
 	if err != nil {
 		return nil, err
 	} else if !has {
-		return nil, ErrAuthenticationNotExist
+		return nil, ErrAuthenticationNotExist{id}
 	}
 	return source, nil
 }

+ 12 - 10
models/publickey.go

@@ -460,7 +460,7 @@ func DeletePublicKey(doer *User, id int64) (err error) {
 	}
 
 	// Check if user has access to delete this key.
-	if doer.Id != key.OwnerID {
+	if !doer.IsAdmin && doer.Id != key.OwnerID {
 		return ErrKeyAccessDenied{doer.Id, key.ID, "public"}
 	}
 
@@ -672,15 +672,17 @@ func DeleteDeployKey(doer *User, id int64) error {
 	}
 
 	// Check if user has access to delete this key.
-	repo, err := GetRepositoryByID(key.RepoID)
-	if err != nil {
-		return fmt.Errorf("GetRepositoryByID: %v", err)
-	}
-	yes, err := HasAccess(doer, repo, ACCESS_MODE_ADMIN)
-	if err != nil {
-		return fmt.Errorf("HasAccess: %v", err)
-	} else if !yes {
-		return ErrKeyAccessDenied{doer.Id, key.ID, "deploy"}
+	if !doer.IsAdmin {
+		repo, err := GetRepositoryByID(key.RepoID)
+		if err != nil {
+			return fmt.Errorf("GetRepositoryByID: %v", err)
+		}
+		yes, err := HasAccess(doer, repo, ACCESS_MODE_ADMIN)
+		if err != nil {
+			return fmt.Errorf("HasAccess: %v", err)
+		} else if !yes {
+			return ErrKeyAccessDenied{doer.Id, key.ID, "deploy"}
+		}
 	}
 
 	sess := x.NewSession()

+ 2 - 2
modules/auth/auth_form.go

@@ -18,7 +18,7 @@ type AuthenticationForm struct {
 	BindDN            string
 	BindPassword      string
 	UserBase          string
-	UserDN            string `form:"user_dn"`
+	UserDN            string
 	AttributeUsername string
 	AttributeName     string
 	AttributeSurname  string
@@ -32,7 +32,7 @@ type AuthenticationForm struct {
 	AllowedDomains    string
 	TLS               bool
 	SkipVerify        bool
-	PAMServiceName    string `form:"pam_service_name"`
+	PAMServiceName    string
 }
 
 func (f *AuthenticationForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

+ 3 - 3
routers/admin/users.go

@@ -121,7 +121,7 @@ func NewUserPost(ctx *middleware.Context, form auth.AdminCrateUserForm) {
 		}
 		return
 	}
-	log.Trace("Account created by admin(%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
 
 	// Send e-mail notification.
 	if form.SendNotify && setting.MailService != nil {
@@ -224,7 +224,7 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) {
 		}
 		return
 	}
-	log.Trace("Account profile updated by admin(%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
 
 	ctx.Flash.Success(ctx.Tr("admin.users.update_profile_success"))
 	ctx.Redirect(setting.AppSubUrl + "/admin/users/" + ctx.Params(":userid"))
@@ -254,7 +254,7 @@ func DeleteUser(ctx *middleware.Context) {
 		}
 		return
 	}
-	log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name)
+	log.Trace("Account deleted by admin (%s): %s", ctx.User.Name, u.Name)
 
 	ctx.Flash.Success(ctx.Tr("admin.users.deletion_success"))
 	ctx.JSON(200, map[string]interface{}{

+ 148 - 0
routers/api/v1/admin/users.go

@@ -0,0 +1,148 @@
+// Copyright 2015 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package admin
+
+import (
+	api "github.com/gogits/go-gogs-client"
+
+	"github.com/gogits/gogs/models"
+	"github.com/gogits/gogs/modules/log"
+	"github.com/gogits/gogs/modules/mailer"
+	"github.com/gogits/gogs/modules/middleware"
+	"github.com/gogits/gogs/modules/setting"
+	"github.com/gogits/gogs/routers/api/v1/user"
+	to "github.com/gogits/gogs/routers/api/v1/utils"
+)
+
+func parseLoginSource(ctx *middleware.Context, u *models.User, sourceID int64, loginName string) {
+	if sourceID == 0 {
+		return
+	}
+
+	source, err := models.GetLoginSourceByID(sourceID)
+	if err != nil {
+		if models.IsErrAuthenticationNotExist(err) {
+			ctx.APIError(422, "", err)
+		} else {
+			ctx.APIError(500, "GetLoginSourceByID", err)
+		}
+		return
+	}
+
+	u.LoginType = source.Type
+	u.LoginSource = source.ID
+	u.LoginName = loginName
+}
+
+func CreateUser(ctx *middleware.Context, form api.CreateUserOption) {
+	u := &models.User{
+		Name:      form.Username,
+		Email:     form.Email,
+		Passwd:    form.Password,
+		IsActive:  true,
+		LoginType: models.PLAIN,
+	}
+
+	parseLoginSource(ctx, u, form.SourceID, form.LoginName)
+	if ctx.Written() {
+		return
+	}
+
+	if err := models.CreateUser(u); err != nil {
+		if models.IsErrUserAlreadyExist(err) ||
+			models.IsErrEmailAlreadyUsed(err) ||
+			models.IsErrNameReserved(err) ||
+			models.IsErrNamePatternNotAllowed(err) {
+			ctx.APIError(422, "", err)
+		} else {
+			ctx.APIError(500, "CreateUser", err)
+		}
+		return
+	}
+	log.Trace("Account created by admin (%s): %s", ctx.User.Name, u.Name)
+
+	// Send e-mail notification.
+	if form.SendNotify && setting.MailService != nil {
+		mailer.SendRegisterNotifyMail(ctx.Context, u)
+	}
+
+	ctx.JSON(201, to.ApiUser(u))
+}
+
+func EditUser(ctx *middleware.Context, form api.EditUserOption) {
+	u := user.GetUserByParams(ctx)
+	if ctx.Written() {
+		return
+	}
+
+	parseLoginSource(ctx, u, form.SourceID, form.LoginName)
+	if ctx.Written() {
+		return
+	}
+
+	if len(form.Password) > 0 {
+		u.Passwd = form.Password
+		u.Salt = models.GetUserSalt()
+		u.EncodePasswd()
+	}
+
+	u.LoginName = form.LoginName
+	u.FullName = form.FullName
+	u.Email = form.Email
+	u.Website = form.Website
+	u.Location = form.Location
+	if form.Active != nil {
+		u.IsActive = *form.Active
+	}
+	if form.Admin != nil {
+		u.IsAdmin = *form.Admin
+	}
+	if form.AllowGitHook != nil {
+		u.AllowGitHook = *form.AllowGitHook
+	}
+	if form.AllowImportLocal != nil {
+		u.AllowImportLocal = *form.AllowImportLocal
+	}
+
+	if err := models.UpdateUser(u); err != nil {
+		if models.IsErrEmailAlreadyUsed(err) {
+			ctx.APIError(422, "", err)
+		} else {
+			ctx.APIError(500, "UpdateUser", err)
+		}
+		return
+	}
+	log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
+
+	ctx.JSON(200, to.ApiUser(u))
+}
+
+func DeleteUser(ctx *middleware.Context) {
+	u := user.GetUserByParams(ctx)
+	if ctx.Written() {
+		return
+	}
+
+	if err := models.DeleteUser(u); err != nil {
+		if models.IsErrUserOwnRepos(err) ||
+			models.IsErrUserHasOrgs(err) {
+			ctx.APIError(422, "", err)
+		} else {
+			ctx.APIError(500, "DeleteUser", err)
+		}
+		return
+	}
+	log.Trace("Account deleted by admin(%s): %s", ctx.User.Name, u.Name)
+
+	ctx.Status(204)
+}
+
+func CreatePublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
+	u := user.GetUserByParams(ctx)
+	if ctx.Written() {
+		return
+	}
+	user.CreateUserPublicKey(ctx, form, u.Id)
+}

+ 14 - 2
routers/api/v1/api.go

@@ -15,6 +15,7 @@ import (
 	"github.com/gogits/gogs/models"
 	"github.com/gogits/gogs/modules/auth"
 	"github.com/gogits/gogs/modules/middleware"
+	"github.com/gogits/gogs/routers/api/v1/admin"
 	"github.com/gogits/gogs/routers/api/v1/misc"
 	"github.com/gogits/gogs/routers/api/v1/repo"
 	"github.com/gogits/gogs/routers/api/v1/user"
@@ -132,8 +133,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 
 		m.Group("/users", func() {
 			m.Group("/:username", func() {
-				m.Combo("/keys").Get(user.ListPublicKeys).
-					Post(ReqAdmin(), user.CreateUserPublicKey)
+				m.Get("/keys", user.ListPublicKeys)
 			})
 		}, ReqToken())
 
@@ -179,5 +179,17 @@ func RegisterRoutes(m *macaron.Macaron) {
 		m.Any("/*", func(ctx *middleware.Context) {
 			ctx.Error(404)
 		})
+
+		m.Group("/admin", func() {
+			m.Group("/users", func() {
+				m.Post("", bind(api.CreateUserOption{}), admin.CreateUser)
+
+				m.Group("/:username", func() {
+					m.Combo("").Patch(bind(api.EditUserOption{}), admin.EditUser).
+						Delete(admin.DeleteUser)
+					m.Post("/keys", admin.CreatePublicKey)
+				})
+			})
+		}, ReqAdmin())
 	})
 }

+ 6 - 13
routers/api/v1/user/keys.go

@@ -14,7 +14,8 @@ import (
 	to "github.com/gogits/gogs/routers/api/v1/utils"
 )
 
-func getUserByParams(ctx *middleware.Context) *models.User {
+// GetUserByParams returns user whose name is presented in URL paramenter.
+func GetUserByParams(ctx *middleware.Context) *models.User {
 	user, err := models.GetUserByName(ctx.Params(":username"))
 	if err != nil {
 		if models.IsErrUserNotExist(err) {
@@ -54,7 +55,7 @@ func ListMyPublicKeys(ctx *middleware.Context) {
 
 // https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#list-public-keys-for-a-user
 func ListPublicKeys(ctx *middleware.Context) {
-	user := getUserByParams(ctx)
+	user := GetUserByParams(ctx)
 	if ctx.Written() {
 		return
 	}
@@ -77,7 +78,8 @@ func GetPublicKey(ctx *middleware.Context) {
 	ctx.JSON(200, to.ApiPublicKey(apiLink, key))
 }
 
-func createUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption, uid int64) {
+// CreateUserPublicKey creates new public key to given user by ID.
+func CreateUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption, uid int64) {
 	content, err := models.CheckPublicKeyString(form.Key)
 	if err != nil {
 		repo.HandleCheckKeyStringError(ctx, err)
@@ -93,18 +95,9 @@ func createUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption, uid
 	ctx.JSON(201, to.ApiPublicKey(apiLink, key))
 }
 
-// https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key-for-user
-func CreateUserPublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
-	user := getUserByParams(ctx)
-	if ctx.Written() {
-		return
-	}
-	createUserPublicKey(ctx, form, user.Id)
-}
-
 // https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#create-a-public-key
 func CreatePublicKey(ctx *middleware.Context, form api.CreateKeyOption) {
-	createUserPublicKey(ctx, form, ctx.User.Id)
+	CreateUserPublicKey(ctx, form, ctx.User.Id)
 }
 
 // https://github.com/gogits/go-gogs-client/wiki/Users-Public-Keys#delete-a-public-key