summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/error.go14
-rw-r--r--models/migrations/migrations.go4
-rw-r--r--models/migrations/v15.go30
-rw-r--r--models/org.go4
-rw-r--r--models/user.go17
-rw-r--r--modules/auth/admin.go27
-rw-r--r--options/locale/locale_en-US.ini2
-rw-r--r--routers/admin/users.go1
-rw-r--r--routers/org/org.go8
-rw-r--r--templates/admin/user/edit.tmpl6
-rw-r--r--templates/base/head.tmpl2
11 files changed, 96 insertions, 19 deletions
diff --git a/models/error.go b/models/error.go
index d11a9eeb1f..f0f3bd1f76 100644
--- a/models/error.go
+++ b/models/error.go
@@ -123,6 +123,20 @@ func (err ErrUserHasOrgs) Error() string {
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
}
+// ErrUserNotAllowedCreateOrg represents a "UserNotAllowedCreateOrg" kind of error.
+type ErrUserNotAllowedCreateOrg struct {
+}
+
+// IsErrUserNotAllowedCreateOrg checks if an error is an ErrUserNotAllowedCreateOrg.
+func IsErrUserNotAllowedCreateOrg(err error) bool {
+ _, ok := err.(ErrUserNotAllowedCreateOrg)
+ return ok
+}
+
+func (err ErrUserNotAllowedCreateOrg) Error() string {
+ return fmt.Sprintf("user is not allowed to create organizations")
+}
+
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
type ErrReachLimitOfRepo struct {
Limit int
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index 66f80dac30..69408a071d 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -76,8 +76,10 @@ var migrations = []Migration{
// v13 -> v14:v0.9.87
NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
-
+ // v14
NewMigration("create user column diff view style", createUserColumnDiffViewStyle),
+ // v15
+ NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn),
}
// Migrate database to current version
diff --git a/models/migrations/v15.go b/models/migrations/v15.go
new file mode 100644
index 0000000000..90fc22c6d3
--- /dev/null
+++ b/models/migrations/v15.go
@@ -0,0 +1,30 @@
+// Copyright 2016 Gitea. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package migrations
+
+import (
+ "fmt"
+
+ "github.com/go-xorm/xorm"
+)
+
+// UserV15 describes the added field for User
+type UserV15 struct {
+ AllowCreateOrganization bool
+}
+
+// TableName will be invoked by XORM to customrize the table name
+func (*UserV15) TableName() string {
+ return "user"
+}
+
+func createAllowCreateOrganizationColumn(x *xorm.Engine) error {
+ if err := x.Sync2(new(UserV15)); err != nil {
+ return fmt.Errorf("Sync2: %v", err)
+ } else if _, err = x.Where("type=0").Cols("allow_create_organization").Update(&UserV15{AllowCreateOrganization: true}); err != nil {
+ return fmt.Errorf("set allow_create_organization: %v", err)
+ }
+ return nil
+}
diff --git a/models/org.go b/models/org.go
index 172295e7ae..881b8bfc7e 100644
--- a/models/org.go
+++ b/models/org.go
@@ -97,6 +97,10 @@ func (org *User) RemoveOrgRepo(repoID int64) error {
// CreateOrganization creates record of a new organization.
func CreateOrganization(org, owner *User) (err error) {
+ if !owner.CanCreateOrganization() {
+ return ErrUserNotAllowedCreateOrg{}
+ }
+
if err = IsUsableUsername(org.Name); err != nil {
return err
}
diff --git a/models/user.go b/models/user.go
index d48397ef7e..9f19b1c84e 100644
--- a/models/user.go
+++ b/models/user.go
@@ -102,11 +102,12 @@ type User struct {
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
// Permissions
- IsActive bool // Activate primary email
- IsAdmin bool
- AllowGitHook bool
- AllowImportLocal bool // Allow migrate repository by local path
- ProhibitLogin bool
+ IsActive bool // Activate primary email
+ IsAdmin bool
+ AllowGitHook bool
+ AllowImportLocal bool // Allow migrate repository by local path
+ AllowCreateOrganization bool `xorm:"DEFAULT true"`
+ ProhibitLogin bool
// Avatar
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
@@ -210,6 +211,11 @@ func (u *User) CanCreateRepo() bool {
return u.NumRepos < u.MaxRepoCreation
}
+// CanCreateOrganization returns true if user can create organisation.
+func (u *User) CanCreateOrganization() bool {
+ return u.IsAdmin || u.AllowCreateOrganization
+}
+
// CanEditGitHook returns true if user can edit Git hooks.
func (u *User) CanEditGitHook() bool {
return u.IsAdmin || u.AllowGitHook
@@ -611,6 +617,7 @@ func CreateUser(u *User) (err error) {
return err
}
u.EncodePasswd()
+ u.AllowCreateOrganization = true
u.MaxRepoCreation = -1
sess := x.NewSession()
diff --git a/modules/auth/admin.go b/modules/auth/admin.go
index 033dfe9388..76b2bd0c89 100644
--- a/modules/auth/admin.go
+++ b/modules/auth/admin.go
@@ -27,19 +27,20 @@ func (f *AdminCreateUserForm) Validate(ctx *macaron.Context, errs binding.Errors
// AdminEditUserForm form for admin to create user
type AdminEditUserForm struct {
- LoginType string `binding:"Required"`
- LoginName string
- FullName string `binding:"MaxSize(100)"`
- Email string `binding:"Required;Email;MaxSize(254)"`
- Password string `binding:"MaxSize(255)"`
- Website string `binding:"MaxSize(50)"`
- Location string `binding:"MaxSize(50)"`
- MaxRepoCreation int
- Active bool
- Admin bool
- AllowGitHook bool
- AllowImportLocal bool
- ProhibitLogin bool
+ LoginType string `binding:"Required"`
+ LoginName string
+ FullName string `binding:"MaxSize(100)"`
+ Email string `binding:"Required;Email;MaxSize(254)"`
+ Password string `binding:"MaxSize(255)"`
+ Website string `binding:"MaxSize(50)"`
+ Location string `binding:"MaxSize(50)"`
+ MaxRepoCreation int
+ Active bool
+ Admin bool
+ AllowGitHook bool
+ AllowImportLocal bool
+ AllowCreateOrganization bool
+ ProhibitLogin bool
}
// Validate validates form fields
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index da2db622c5..6a8edad79e 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -844,6 +844,7 @@ team_permission_desc = What permission level should this team have?
form.name_reserved = Organization name '%s' is reserved.
form.name_pattern_not_allowed = Organization name pattern '%s' is not allowed.
+form.create_org_not_allowed = This user is not allowed to create an organization.
settings = Settings
settings.options = Options
@@ -994,6 +995,7 @@ users.prohibit_login = This account is prohibited to login
users.is_admin = This account has administrator permissions
users.allow_git_hook = This account has permissions to create Git hooks
users.allow_import_local = This account has permissions to import local repositories
+users.allow_create_organization = This account has permissions to create Organizations
users.update_profile = Update Account Profile
users.delete_account = Delete This Account
users.still_own_repo = This account still has ownership over at least one repository, you have to delete or transfer them first.
diff --git a/routers/admin/users.go b/routers/admin/users.go
index 782012d95d..c02f366f66 100644
--- a/routers/admin/users.go
+++ b/routers/admin/users.go
@@ -214,6 +214,7 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
u.IsAdmin = form.Admin
u.AllowGitHook = form.AllowGitHook
u.AllowImportLocal = form.AllowImportLocal
+ u.AllowCreateOrganization = form.AllowCreateOrganization
u.ProhibitLogin = form.ProhibitLogin
if err := models.UpdateUser(u); err != nil {
diff --git a/routers/org/org.go b/routers/org/org.go
index 579a2917b4..d0988bfcf5 100644
--- a/routers/org/org.go
+++ b/routers/org/org.go
@@ -5,6 +5,8 @@
package org
import (
+ "errors"
+
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/auth"
"code.gitea.io/gitea/modules/base"
@@ -21,6 +23,10 @@ const (
// Create render the page for create organization
func Create(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("new_org")
+ if !ctx.User.CanCreateOrganization() {
+ ctx.Handle(500, "Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
+ return
+ }
ctx.HTML(200, tplCreateOrg)
}
@@ -48,6 +54,8 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(models.ErrNameReserved).Name), tplCreateOrg, &form)
case models.IsErrNamePatternNotAllowed(err):
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
+ case models.IsErrUserNotAllowedCreateOrg(err):
+ ctx.RenderWithErr(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
default:
ctx.Handle(500, "CreateOrganization", err)
}
diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl
index bed3097a50..91fbf781f3 100644
--- a/templates/admin/user/edit.tmpl
+++ b/templates/admin/user/edit.tmpl
@@ -97,6 +97,12 @@
<input name="allow_import_local" type="checkbox" {{if .User.CanImportLocal}}checked{{end}}>
</div>
</div>
+ <div class="inline field">
+ <div class="ui checkbox">
+ <label><strong>{{.i18n.Tr "admin.users.allow_create_organization"}}</strong></label>
+ <input name="allow_create_organization" type="checkbox" {{if .User.CanCreateOrganization}}checked{{end}}>
+ </div>
+ </div>
<div class="ui divider"></div>
diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl
index fe14742510..847503022e 100644
--- a/templates/base/head.tmpl
+++ b/templates/base/head.tmpl
@@ -94,9 +94,11 @@
<a class="item" href="{{AppSubUrl}}/repo/migrate">
<i class="octicon octicon-repo-clone"></i> {{.i18n.Tr "new_migrate"}}
</a>
+ {{if .SignedUser.CanCreateOrganization}}
<a class="item" href="{{AppSubUrl}}/org/create">
<i class="octicon octicon-organization"></i> {{.i18n.Tr "new_org"}}
</a>
+ {{end}}
</div><!-- end content create new menu -->
</div><!-- end dropdown menu create new -->