| @@ -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) | |||
| } | |||
| @@ -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 | |||
| } | |||
| @@ -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() | |||
| @@ -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 { | |||
| @@ -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{}{ | |||
| @@ -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) | |||
| } | |||
| @@ -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()) | |||
| }) | |||
| } | |||
| @@ -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 | |||