Skip to content

Commit c0904f1

Browse files
Schwobalandlunny
authored andcommitted
Restrict creating organisations by user (#193)
* restrict creating organizations based on right on user * revert bindata.go * reverse vendor lib * revert goimports change * set AllowCreateOrganization default value to true * revert locale * added default value for AllowCreateOrganization * fix typo in migration-comment * fix comment * add coments in migration
1 parent b75450a commit c0904f1

File tree

11 files changed

+96
-19
lines changed

11 files changed

+96
-19
lines changed

models/error.go

+14
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,20 @@ func (err ErrUserHasOrgs) Error() string {
123123
return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID)
124124
}
125125

126+
// ErrUserNotAllowedCreateOrg represents a "UserNotAllowedCreateOrg" kind of error.
127+
type ErrUserNotAllowedCreateOrg struct {
128+
}
129+
130+
// IsErrUserNotAllowedCreateOrg checks if an error is an ErrUserNotAllowedCreateOrg.
131+
func IsErrUserNotAllowedCreateOrg(err error) bool {
132+
_, ok := err.(ErrUserNotAllowedCreateOrg)
133+
return ok
134+
}
135+
136+
func (err ErrUserNotAllowedCreateOrg) Error() string {
137+
return fmt.Sprintf("user is not allowed to create organizations")
138+
}
139+
126140
// ErrReachLimitOfRepo represents a "ReachLimitOfRepo" kind of error.
127141
type ErrReachLimitOfRepo struct {
128142
Limit int

models/migrations/migrations.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,10 @@ var migrations = []Migration{
7676

7777
// v13 -> v14:v0.9.87
7878
NewMigration("set comment updated with created", setCommentUpdatedWithCreated),
79-
79+
// v14
8080
NewMigration("create user column diff view style", createUserColumnDiffViewStyle),
81+
// v15
82+
NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn),
8183
}
8284

8385
// Migrate database to current version

models/migrations/v15.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2016 Gitea. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/go-xorm/xorm"
11+
)
12+
13+
// UserV15 describes the added field for User
14+
type UserV15 struct {
15+
AllowCreateOrganization bool
16+
}
17+
18+
// TableName will be invoked by XORM to customrize the table name
19+
func (*UserV15) TableName() string {
20+
return "user"
21+
}
22+
23+
func createAllowCreateOrganizationColumn(x *xorm.Engine) error {
24+
if err := x.Sync2(new(UserV15)); err != nil {
25+
return fmt.Errorf("Sync2: %v", err)
26+
} else if _, err = x.Where("type=0").Cols("allow_create_organization").Update(&UserV15{AllowCreateOrganization: true}); err != nil {
27+
return fmt.Errorf("set allow_create_organization: %v", err)
28+
}
29+
return nil
30+
}

models/org.go

+4
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ func (org *User) RemoveOrgRepo(repoID int64) error {
9797

9898
// CreateOrganization creates record of a new organization.
9999
func CreateOrganization(org, owner *User) (err error) {
100+
if !owner.CanCreateOrganization() {
101+
return ErrUserNotAllowedCreateOrg{}
102+
}
103+
100104
if err = IsUsableUsername(org.Name); err != nil {
101105
return err
102106
}

models/user.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,12 @@ type User struct {
102102
MaxRepoCreation int `xorm:"NOT NULL DEFAULT -1"`
103103

104104
// Permissions
105-
IsActive bool // Activate primary email
106-
IsAdmin bool
107-
AllowGitHook bool
108-
AllowImportLocal bool // Allow migrate repository by local path
109-
ProhibitLogin bool
105+
IsActive bool // Activate primary email
106+
IsAdmin bool
107+
AllowGitHook bool
108+
AllowImportLocal bool // Allow migrate repository by local path
109+
AllowCreateOrganization bool `xorm:"DEFAULT true"`
110+
ProhibitLogin bool
110111

111112
// Avatar
112113
Avatar string `xorm:"VARCHAR(2048) NOT NULL"`
@@ -210,6 +211,11 @@ func (u *User) CanCreateRepo() bool {
210211
return u.NumRepos < u.MaxRepoCreation
211212
}
212213

214+
// CanCreateOrganization returns true if user can create organisation.
215+
func (u *User) CanCreateOrganization() bool {
216+
return u.IsAdmin || u.AllowCreateOrganization
217+
}
218+
213219
// CanEditGitHook returns true if user can edit Git hooks.
214220
func (u *User) CanEditGitHook() bool {
215221
return u.IsAdmin || u.AllowGitHook
@@ -611,6 +617,7 @@ func CreateUser(u *User) (err error) {
611617
return err
612618
}
613619
u.EncodePasswd()
620+
u.AllowCreateOrganization = true
614621
u.MaxRepoCreation = -1
615622

616623
sess := x.NewSession()

modules/auth/admin.go

+14-13
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@ func (f *AdminCreateUserForm) Validate(ctx *macaron.Context, errs binding.Errors
2727

2828
// AdminEditUserForm form for admin to create user
2929
type AdminEditUserForm struct {
30-
LoginType string `binding:"Required"`
31-
LoginName string
32-
FullName string `binding:"MaxSize(100)"`
33-
Email string `binding:"Required;Email;MaxSize(254)"`
34-
Password string `binding:"MaxSize(255)"`
35-
Website string `binding:"MaxSize(50)"`
36-
Location string `binding:"MaxSize(50)"`
37-
MaxRepoCreation int
38-
Active bool
39-
Admin bool
40-
AllowGitHook bool
41-
AllowImportLocal bool
42-
ProhibitLogin bool
30+
LoginType string `binding:"Required"`
31+
LoginName string
32+
FullName string `binding:"MaxSize(100)"`
33+
Email string `binding:"Required;Email;MaxSize(254)"`
34+
Password string `binding:"MaxSize(255)"`
35+
Website string `binding:"MaxSize(50)"`
36+
Location string `binding:"MaxSize(50)"`
37+
MaxRepoCreation int
38+
Active bool
39+
Admin bool
40+
AllowGitHook bool
41+
AllowImportLocal bool
42+
AllowCreateOrganization bool
43+
ProhibitLogin bool
4344
}
4445

4546
// Validate validates form fields

options/locale/locale_en-US.ini

+2
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,7 @@ team_permission_desc = What permission level should this team have?
844844
845845
form.name_reserved = Organization name '%s' is reserved.
846846
form.name_pattern_not_allowed = Organization name pattern '%s' is not allowed.
847+
form.create_org_not_allowed = This user is not allowed to create an organization.
847848
848849
settings = Settings
849850
settings.options = Options
@@ -994,6 +995,7 @@ users.prohibit_login = This account is prohibited to login
994995
users.is_admin = This account has administrator permissions
995996
users.allow_git_hook = This account has permissions to create Git hooks
996997
users.allow_import_local = This account has permissions to import local repositories
998+
users.allow_create_organization = This account has permissions to create Organizations
997999
users.update_profile = Update Account Profile
9981000
users.delete_account = Delete This Account
9991001
users.still_own_repo = This account still has ownership over at least one repository, you have to delete or transfer them first.

routers/admin/users.go

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ func EditUserPost(ctx *context.Context, form auth.AdminEditUserForm) {
214214
u.IsAdmin = form.Admin
215215
u.AllowGitHook = form.AllowGitHook
216216
u.AllowImportLocal = form.AllowImportLocal
217+
u.AllowCreateOrganization = form.AllowCreateOrganization
217218
u.ProhibitLogin = form.ProhibitLogin
218219

219220
if err := models.UpdateUser(u); err != nil {

routers/org/org.go

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
package org
66

77
import (
8+
"errors"
9+
810
"code.gitea.io/gitea/models"
911
"code.gitea.io/gitea/modules/auth"
1012
"code.gitea.io/gitea/modules/base"
@@ -21,6 +23,10 @@ const (
2123
// Create render the page for create organization
2224
func Create(ctx *context.Context) {
2325
ctx.Data["Title"] = ctx.Tr("new_org")
26+
if !ctx.User.CanCreateOrganization() {
27+
ctx.Handle(500, "Not allowed", errors.New(ctx.Tr("org.form.create_org_not_allowed")))
28+
return
29+
}
2430
ctx.HTML(200, tplCreateOrg)
2531
}
2632

@@ -48,6 +54,8 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) {
4854
ctx.RenderWithErr(ctx.Tr("org.form.name_reserved", err.(models.ErrNameReserved).Name), tplCreateOrg, &form)
4955
case models.IsErrNamePatternNotAllowed(err):
5056
ctx.RenderWithErr(ctx.Tr("org.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplCreateOrg, &form)
57+
case models.IsErrUserNotAllowedCreateOrg(err):
58+
ctx.RenderWithErr(ctx.Tr("org.form.create_org_not_allowed"), tplCreateOrg, &form)
5159
default:
5260
ctx.Handle(500, "CreateOrganization", err)
5361
}

templates/admin/user/edit.tmpl

+6
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@
9797
<input name="allow_import_local" type="checkbox" {{if .User.CanImportLocal}}checked{{end}}>
9898
</div>
9999
</div>
100+
<div class="inline field">
101+
<div class="ui checkbox">
102+
<label><strong>{{.i18n.Tr "admin.users.allow_create_organization"}}</strong></label>
103+
<input name="allow_create_organization" type="checkbox" {{if .User.CanCreateOrganization}}checked{{end}}>
104+
</div>
105+
</div>
100106

101107
<div class="ui divider"></div>
102108

templates/base/head.tmpl

+2
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@
9494
<a class="item" href="{{AppSubUrl}}/repo/migrate">
9595
<i class="octicon octicon-repo-clone"></i> {{.i18n.Tr "new_migrate"}}
9696
</a>
97+
{{if .SignedUser.CanCreateOrganization}}
9798
<a class="item" href="{{AppSubUrl}}/org/create">
9899
<i class="octicon octicon-organization"></i> {{.i18n.Tr "new_org"}}
99100
</a>
101+
{{end}}
100102
</div><!-- end content create new menu -->
101103
</div><!-- end dropdown menu create new -->
102104

0 commit comments

Comments
 (0)