Browse Source

db: add tests for repos (#6112)

* Add Repos.create method

* Fix repo name error handling

* Fix all compile errors

* Update github.com/go-macaron/captcha to fix http issue

* Add repos tests
ᴜɴᴋɴᴡᴏɴ 4 years ago
parent
commit
fa497b1633

+ 4 - 7
conf/locale/locale_en-US.ini

@@ -263,8 +263,7 @@ following = Following
 follow = Follow
 unfollow = Unfollow
 
-form.name_reserved = Username '%s' is reserved.
-form.name_pattern_not_allowed = Username pattern '%s' is not allowed.
+form.name_not_allowed = User name or pattern %q is not allowed.
 
 [settings]
 profile = Profile
@@ -430,8 +429,7 @@ repo_description_helper = Description of repository. Maximum 512 characters leng
 repo_description_length = Available characters
 
 form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
-form.name_reserved = Repository name '%s' is reserved.
-form.name_pattern_not_allowed = Repository name pattern '%s' is not allowed.
+form.name_not_allowed = Repository name or pattern %q is not allowed.
 
 need_auth = Need Authorization
 migrate_type = Migration Type
@@ -935,9 +933,8 @@ team_name_helper = You'll use this name to mention this team in conversations.
 team_desc_helper = What is this team all about?
 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.team_name_reserved = Team name '%s' is reserved.
+form.name_not_allowed = Organization name or pattern %q is not allowed.
+form.team_name_not_allowed = Team name or pattern %q is not allowed.
 
 settings = Settings
 settings.options = Options

+ 1 - 1
go.mod

@@ -9,7 +9,7 @@ require (
 	github.com/fatih/color v1.9.0 // indirect
 	github.com/go-macaron/binding v1.1.0
 	github.com/go-macaron/cache v0.0.0-20190810181446-10f7c57e2196
-	github.com/go-macaron/captcha v0.0.0-20190813234938-24f40749f36d
+	github.com/go-macaron/captcha v0.2.0
 	github.com/go-macaron/csrf v0.0.0-20190812063352-946f6d303a4c
 	github.com/go-macaron/gzip v0.0.0-20160222043647-cad1c6580a07
 	github.com/go-macaron/i18n v0.5.0

+ 2 - 0
go.sum

@@ -58,6 +58,8 @@ github.com/go-macaron/cache v0.0.0-20190810181446-10f7c57e2196 h1:fqWZxyMLF6RVGm
 github.com/go-macaron/cache v0.0.0-20190810181446-10f7c57e2196/go.mod h1:O6fSdaYZbGh4clVMGMGO5k2KbMO0Cz8YdBnPrD0I8dM=
 github.com/go-macaron/captcha v0.0.0-20190813234938-24f40749f36d h1:aSJXLVjEjbLeHo8aCTDcD3/gMWizaRjMBb3VCsEWEHs=
 github.com/go-macaron/captcha v0.0.0-20190813234938-24f40749f36d/go.mod h1:lmhlZnu9cTRGNQEkSh1qZi2IK3HJH4Z1MXkg6ARQKZA=
+github.com/go-macaron/captcha v0.2.0 h1:d38eYDDF8tdqoM0hJbk+Jb7WQGWlwYNnQwRqLRmSk1Y=
+github.com/go-macaron/captcha v0.2.0/go.mod h1:lmhlZnu9cTRGNQEkSh1qZi2IK3HJH4Z1MXkg6ARQKZA=
 github.com/go-macaron/csrf v0.0.0-20190812063352-946f6d303a4c h1:kFFz1OpaH3+efG7RA33z+D0piwpA/a3x/Zn2d8z9rfw=
 github.com/go-macaron/csrf v0.0.0-20190812063352-946f6d303a4c/go.mod h1:FX53Xq0NNlUj0E5in5J8Dq5nrbdK3ZyDIy6y5VWOiUo=
 github.com/go-macaron/gzip v0.0.0-20160222043647-cad1c6580a07 h1:YSIA98PevNf1NtCa/J6cz7gjzpz99WVAOa9Eg0klKps=

File diff suppressed because it is too large
+ 2 - 2
internal/assets/conf/conf_gen.go


+ 0 - 40
internal/db/error.go

@@ -8,32 +8,6 @@ import (
 	"fmt"
 )
 
-type ErrNameReserved struct {
-	Name string
-}
-
-func IsErrNameReserved(err error) bool {
-	_, ok := err.(ErrNameReserved)
-	return ok
-}
-
-func (err ErrNameReserved) Error() string {
-	return fmt.Sprintf("name is reserved [name: %s]", err.Name)
-}
-
-type ErrNamePatternNotAllowed struct {
-	Pattern string
-}
-
-func IsErrNamePatternNotAllowed(err error) bool {
-	_, ok := err.(ErrNamePatternNotAllowed)
-	return ok
-}
-
-func (err ErrNamePatternNotAllowed) Error() string {
-	return fmt.Sprintf("name pattern is not allowed [pattern: %s]", err.Pattern)
-}
-
 //  ____ ___
 // |    |   \______ ___________
 // |    |   /  ___// __ \_  __ \
@@ -245,20 +219,6 @@ func (err ErrLastOrgOwner) Error() string {
 //  |____|_  /\___  >   __/ \____/____  >__||__|  \____/|__|   / ____|
 //         \/     \/|__|              \/                       \/
 
-type ErrRepoAlreadyExist struct {
-	Uname string
-	Name  string
-}
-
-func IsErrRepoAlreadyExist(err error) bool {
-	_, ok := err.(ErrRepoAlreadyExist)
-	return ok
-}
-
-func (err ErrRepoAlreadyExist) Error() string {
-	return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name)
-}
-
 type ErrInvalidCloneAddr struct {
 	IsURLError         bool
 	IsInvalidPath      bool

+ 0 - 11
internal/db/errors/user.go

@@ -8,17 +8,6 @@ import (
 	"fmt"
 )
 
-type EmptyName struct{}
-
-func IsEmptyName(err error) bool {
-	_, ok := err.(EmptyName)
-	return ok
-}
-
-func (err EmptyName) Error() string {
-	return "empty name"
-}
-
 type UserNotKeyOwner struct {
 	KeyID int64
 }

+ 1 - 1
internal/db/org_team.go

@@ -217,7 +217,7 @@ var reservedTeamNames = []string{"new"}
 
 // IsUsableTeamName return an error if given name is a reserved name or pattern.
 func IsUsableTeamName(name string) error {
-	return isUsableName(reservedTeamNames, nil, name)
+	return isNameAllowed(reservedTeamNames, nil, name)
 }
 
 // NewTeam creates a record of new team.

+ 31 - 54
internal/db/repo.go

@@ -148,14 +148,14 @@ func NewRepoContext() {
 // Repository contains information of a repository.
 type Repository struct {
 	ID              int64
-	OwnerID         int64  `xorm:"UNIQUE(s)"`
-	Owner           *User  `xorm:"-" json:"-"`
-	LowerName       string `xorm:"UNIQUE(s) INDEX NOT NULL"`
-	Name            string `xorm:"INDEX NOT NULL"`
-	Description     string `xorm:"VARCHAR(512)"`
+	OwnerID         int64  `xorm:"UNIQUE(s)" gorm:"UNIQUE_INDEX:s"`
+	Owner           *User  `xorm:"-" gorm:"-" json:"-"`
+	LowerName       string `xorm:"UNIQUE(s) INDEX NOT NULL" gorm:"UNIQUE_INDEX:s"`
+	Name            string `xorm:"INDEX NOT NULL" gorm:"NOT NULL"`
+	Description     string `xorm:"VARCHAR(512)" gorm:"TYPE:VARCHAR(512)"`
 	Website         string
 	DefaultBranch   string
-	Size            int64 `xorm:"NOT NULL DEFAULT 0"`
+	Size            int64 `xorm:"NOT NULL DEFAULT 0" gorm:"NOT NULL;DEFAULT:0"`
 	UseCustomAvatar bool
 
 	// Counters
@@ -164,44 +164,44 @@ type Repository struct {
 	NumForks            int
 	NumIssues           int
 	NumClosedIssues     int
-	NumOpenIssues       int `xorm:"-" json:"-"`
+	NumOpenIssues       int `xorm:"-" gorm:"-" json:"-"`
 	NumPulls            int
 	NumClosedPulls      int
-	NumOpenPulls        int `xorm:"-" json:"-"`
-	NumMilestones       int `xorm:"NOT NULL DEFAULT 0"`
-	NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0"`
-	NumOpenMilestones   int `xorm:"-" json:"-"`
-	NumTags             int `xorm:"-" json:"-"`
+	NumOpenPulls        int `xorm:"-" gorm:"-" json:"-"`
+	NumMilestones       int `xorm:"NOT NULL DEFAULT 0" gorm:"NOT NULL;DEFAULT:0"`
+	NumClosedMilestones int `xorm:"NOT NULL DEFAULT 0" gorm:"NOT NULL;DEFAULT:0"`
+	NumOpenMilestones   int `xorm:"-" gorm:"-" json:"-"`
+	NumTags             int `xorm:"-" gorm:"-" json:"-"`
 
 	IsPrivate bool
 	IsBare    bool
 
 	IsMirror bool
-	*Mirror  `xorm:"-" json:"-"`
+	*Mirror  `xorm:"-" gorm:"-" json:"-"`
 
 	// Advanced settings
-	EnableWiki            bool `xorm:"NOT NULL DEFAULT true"`
+	EnableWiki            bool `xorm:"NOT NULL DEFAULT true" gorm:"NOT NULL;DEFAULT:TRUE"`
 	AllowPublicWiki       bool
 	EnableExternalWiki    bool
 	ExternalWikiURL       string
-	EnableIssues          bool `xorm:"NOT NULL DEFAULT true"`
+	EnableIssues          bool `xorm:"NOT NULL DEFAULT true" gorm:"NOT NULL;DEFAULT:TRUE"`
 	AllowPublicIssues     bool
 	EnableExternalTracker bool
 	ExternalTrackerURL    string
 	ExternalTrackerFormat string
 	ExternalTrackerStyle  string
-	ExternalMetas         map[string]string `xorm:"-" json:"-"`
-	EnablePulls           bool              `xorm:"NOT NULL DEFAULT true"`
-	PullsIgnoreWhitespace bool              `xorm:"NOT NULL DEFAULT false"`
-	PullsAllowRebase      bool              `xorm:"NOT NULL DEFAULT false"`
+	ExternalMetas         map[string]string `xorm:"-" gorm:"-" json:"-"`
+	EnablePulls           bool              `xorm:"NOT NULL DEFAULT true" gorm:"NOT NULL;DEFAULT:TRUE"`
+	PullsIgnoreWhitespace bool              `xorm:"NOT NULL DEFAULT false" gorm:"NOT NULL;DEFAULT:FALSE"`
+	PullsAllowRebase      bool              `xorm:"NOT NULL DEFAULT false" gorm:"NOT NULL;DEFAULT:FALSE"`
 
-	IsFork   bool `xorm:"NOT NULL DEFAULT false"`
+	IsFork   bool `xorm:"NOT NULL DEFAULT false" gorm:"NOT NULL;DEFAULT:FALSE"`
 	ForkID   int64
-	BaseRepo *Repository `xorm:"-" json:"-"`
+	BaseRepo *Repository `xorm:"-" gorm:"-" json:"-"`
 
-	Created     time.Time `xorm:"-" json:"-"`
+	Created     time.Time `xorm:"-" gorm:"-" json:"-"`
 	CreatedUnix int64
-	Updated     time.Time `xorm:"-" json:"-"`
+	Updated     time.Time `xorm:"-" gorm:"-" json:"-"`
 	UpdatedUnix int64
 }
 
@@ -210,10 +210,6 @@ func (repo *Repository) BeforeInsert() {
 	repo.UpdatedUnix = repo.CreatedUnix
 }
 
-func (repo *Repository) BeforeUpdate() {
-	repo.UpdatedUnix = time.Now().Unix()
-}
-
 func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
 	switch colName {
 	case "default_branch":
@@ -1057,13 +1053,13 @@ var (
 	reservedRepoPatterns = []string{"*.git", "*.wiki"}
 )
 
-// IsUsableRepoName return an error if given name is a reserved name or pattern.
-func IsUsableRepoName(name string) error {
-	return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
+// isRepoNameAllowed return an error if given name is a reserved name or pattern for repositories.
+func isRepoNameAllowed(name string) error {
+	return isNameAllowed(reservedRepoNames, reservedRepoPatterns, name)
 }
 
 func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err error) {
-	if err = IsUsableRepoName(repo.Name); err != nil {
+	if err = isRepoNameAllowed(repo.Name); err != nil {
 		return err
 	}
 
@@ -1071,7 +1067,7 @@ func createRepository(e *xorm.Session, doer, owner *User, repo *Repository) (err
 	if err != nil {
 		return fmt.Errorf("IsRepositoryExist: %v", err)
 	} else if has {
-		return ErrRepoAlreadyExist{owner.Name, repo.Name}
+		return ErrRepoAlreadyExist{args: errutil.Args{"ownerID": owner.ID, "name": repo.Name}}
 	}
 
 	if _, err = e.Insert(repo); err != nil {
@@ -1266,7 +1262,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
 	if err != nil {
 		return fmt.Errorf("IsRepositoryExist: %v", err)
 	} else if has {
-		return ErrRepoAlreadyExist{newOwnerName, repo.Name}
+		return ErrRepoAlreadyExist{args: errutil.Args{"ownerName": newOwnerName, "name": repo.Name}}
 	}
 
 	sess := x.NewSession()
@@ -1384,7 +1380,7 @@ func deleteRepoLocalCopy(repo *Repository) {
 func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error) {
 	oldRepoName = strings.ToLower(oldRepoName)
 	newRepoName = strings.ToLower(newRepoName)
-	if err = IsUsableRepoName(newRepoName); err != nil {
+	if err = isRepoNameAllowed(newRepoName); err != nil {
 		return err
 	}
 
@@ -1392,7 +1388,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
 	if err != nil {
 		return fmt.Errorf("IsRepositoryExist: %v", err)
 	} else if has {
-		return ErrRepoAlreadyExist{u.Name, newRepoName}
+		return ErrRepoAlreadyExist{args: errutil.Args{"ownerID": u.ID, "name": newRepoName}}
 	}
 
 	repo, err := GetRepositoryByName(u.ID, oldRepoName)
@@ -1647,25 +1643,6 @@ func GetRepositoryByRef(ref string) (*Repository, error) {
 	return GetRepositoryByName(user.ID, repoName)
 }
 
-var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
-
-type ErrRepoNotExist struct {
-	args map[string]interface{}
-}
-
-func IsErrRepoNotExist(err error) bool {
-	_, ok := err.(ErrRepoNotExist)
-	return ok
-}
-
-func (err ErrRepoNotExist) Error() string {
-	return fmt.Sprintf("repository does not exist: %v", err.args)
-}
-
-func (ErrRepoNotExist) NotFound() bool {
-	return true
-}
-
 // GetRepositoryByName returns the repository by given name under user if exists.
 // Deprecated: Use Repos.GetByName instead.
 func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {

+ 100 - 0
internal/db/repos.go

@@ -5,9 +5,13 @@
 package db
 
 import (
+	"fmt"
 	"strings"
+	"time"
 
 	"github.com/jinzhu/gorm"
+
+	"gogs.io/gogs/internal/errutil"
 )
 
 // ReposStore is the persistent interface for repositories.
@@ -21,10 +25,106 @@ type ReposStore interface {
 
 var Repos ReposStore
 
+// NOTE: This is a GORM create hook.
+func (r *Repository) BeforeCreate() {
+	r.CreatedUnix = gorm.NowFunc().Unix()
+}
+
+// NOTE: This is a GORM update hook.
+func (r *Repository) BeforeUpdate() {
+	r.UpdatedUnix = gorm.NowFunc().Unix()
+}
+
+// NOTE: This is a GORM query hook.
+func (r *Repository) AfterFind() {
+	r.Created = time.Unix(r.CreatedUnix, 0).Local()
+	r.Updated = time.Unix(r.UpdatedUnix, 0).Local()
+}
+
+var _ ReposStore = (*repos)(nil)
+
 type repos struct {
 	*gorm.DB
 }
 
+type ErrRepoAlreadyExist struct {
+	args errutil.Args
+}
+
+func IsErrRepoAlreadyExist(err error) bool {
+	_, ok := err.(ErrRepoAlreadyExist)
+	return ok
+}
+
+func (err ErrRepoAlreadyExist) Error() string {
+	return fmt.Sprintf("repository already exists: %v", err.args)
+}
+
+type createRepoOpts struct {
+	Name          string
+	Description   string
+	DefaultBranch string
+	Private       bool
+	Mirror        bool
+	EnableWiki    bool
+	EnableIssues  bool
+	EnablePulls   bool
+	Fork          bool
+	ForkID        int64
+}
+
+// create creates a new repository record in the database. Fields of "repo" will be updated
+// in place upon insertion. It returns ErrNameNotAllowed when the repository name is not allowed,
+// or returns ErrRepoAlreadyExist when a repository with same name already exists for the owner.
+func (db *repos) create(ownerID int64, opts createRepoOpts) (*Repository, error) {
+	err := isRepoNameAllowed(opts.Name)
+	if err != nil {
+		return nil, err
+	}
+
+	_, err = db.GetByName(ownerID, opts.Name)
+	if err == nil {
+		return nil, ErrRepoAlreadyExist{args: errutil.Args{"ownerID": ownerID, "name": opts.Name}}
+	} else if !IsErrRepoNotExist(err) {
+		return nil, err
+	}
+
+	repo := &Repository{
+		OwnerID:       ownerID,
+		LowerName:     strings.ToLower(opts.Name),
+		Name:          opts.Name,
+		Description:   opts.Description,
+		DefaultBranch: opts.DefaultBranch,
+		IsPrivate:     opts.Private,
+		IsMirror:      opts.Mirror,
+		EnableWiki:    opts.EnableWiki,
+		EnableIssues:  opts.EnableIssues,
+		EnablePulls:   opts.EnablePulls,
+		IsFork:        opts.Fork,
+		ForkID:        opts.ForkID,
+	}
+	return repo, db.DB.Create(repo).Error
+}
+
+var _ errutil.NotFound = (*ErrRepoNotExist)(nil)
+
+type ErrRepoNotExist struct {
+	args map[string]interface{}
+}
+
+func IsErrRepoNotExist(err error) bool {
+	_, ok := err.(ErrRepoNotExist)
+	return ok
+}
+
+func (err ErrRepoNotExist) Error() string {
+	return fmt.Sprintf("repository does not exist: %v", err.args)
+}
+
+func (ErrRepoNotExist) NotFound() bool {
+	return true
+}
+
 func (db *repos) GetByName(ownerID int64, name string) (*Repository, error) {
 	repo := new(Repository)
 	err := db.Where("owner_id = ? AND lower_name = ?", ownerID, strings.ToLower(name)).First(repo).Error

+ 102 - 0
internal/db/repos_test.go

@@ -0,0 +1,102 @@
+// Copyright 2020 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 db
+
+import (
+	"testing"
+	"time"
+
+	"github.com/jinzhu/gorm"
+	"github.com/stretchr/testify/assert"
+
+	"gogs.io/gogs/internal/errutil"
+)
+
+func Test_repos(t *testing.T) {
+	if testing.Short() {
+		t.Skip()
+	}
+
+	t.Parallel()
+
+	tables := []interface{}{new(Repository)}
+	db := &repos{
+		DB: initTestDB(t, "repos", tables...),
+	}
+
+	for _, tc := range []struct {
+		name string
+		test func(*testing.T, *repos)
+	}{
+		{"create", test_repos_create},
+		{"GetByName", test_repos_GetByName},
+	} {
+		t.Run(tc.name, func(t *testing.T) {
+			t.Cleanup(func() {
+				err := clearTables(db.DB, tables...)
+				if err != nil {
+					t.Fatal(err)
+				}
+			})
+			tc.test(t, db)
+		})
+	}
+}
+
+func test_repos_create(t *testing.T, db *repos) {
+	t.Run("name not allowed", func(t *testing.T) {
+		_, err := db.create(1, createRepoOpts{
+			Name: "my.git",
+		})
+		expErr := ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "pattern": "*.git"}}
+		assert.Equal(t, expErr, err)
+	})
+
+	t.Run("already exists", func(t *testing.T) {
+		_, err := db.create(1, createRepoOpts{
+			Name: "repo1",
+		})
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		_, err = db.create(1, createRepoOpts{
+			Name: "repo1",
+		})
+		expErr := ErrRepoAlreadyExist{args: errutil.Args{"ownerID": int64(1), "name": "repo1"}}
+		assert.Equal(t, expErr, err)
+	})
+
+	repo, err := db.create(1, createRepoOpts{
+		Name: "repo2",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	repo, err = db.GetByName(repo.OwnerID, repo.Name)
+	if err != nil {
+		t.Fatal(err)
+	}
+	assert.Equal(t, gorm.NowFunc().Format(time.RFC3339), repo.Created.Format(time.RFC3339))
+}
+
+func test_repos_GetByName(t *testing.T, db *repos) {
+	repo, err := db.create(1, createRepoOpts{
+		Name: "repo1",
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = db.GetByName(repo.OwnerID, repo.Name)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = db.GetByName(1, "bad_name")
+	expErr := ErrRepoNotExist{args: errutil.Args{"ownerID": int64(1), "name": "bad_name"}}
+	assert.Equal(t, expErr, err)
+}

+ 33 - 6
internal/db/user.go

@@ -503,25 +503,52 @@ var (
 	reservedUserPatterns = []string{"*.keys"}
 )
 
-// isUsableName checks if name is reserved or pattern of name is not allowed
+type ErrNameNotAllowed struct {
+	args errutil.Args
+}
+
+func IsErrNameNotAllowed(err error) bool {
+	_, ok := err.(ErrNameNotAllowed)
+	return ok
+}
+
+func (err ErrNameNotAllowed) Value() string {
+	val, ok := err.args["name"].(string)
+	if ok {
+		return val
+	}
+
+	val, ok = err.args["pattern"].(string)
+	if ok {
+		return val
+	}
+
+	return "<value not found>"
+}
+
+func (err ErrNameNotAllowed) Error() string {
+	return fmt.Sprintf("name is not allowed: %v", err.args)
+}
+
+// isNameAllowed checks if name is reserved or pattern of name is not allowed
 // based on given reserved names and patterns.
 // Names are exact match, patterns can be prefix or suffix match with placeholder '*'.
-func isUsableName(names, patterns []string, name string) error {
+func isNameAllowed(names, patterns []string, name string) error {
 	name = strings.TrimSpace(strings.ToLower(name))
 	if utf8.RuneCountInString(name) == 0 {
-		return errors.EmptyName{}
+		return ErrNameNotAllowed{args: errutil.Args{"reason": "empty name"}}
 	}
 
 	for i := range names {
 		if name == names[i] {
-			return ErrNameReserved{name}
+			return ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "name": name}}
 		}
 	}
 
 	for _, pat := range patterns {
 		if pat[0] == '*' && strings.HasSuffix(name, pat[1:]) ||
 			(pat[len(pat)-1] == '*' && strings.HasPrefix(name, pat[:len(pat)-1])) {
-			return ErrNamePatternNotAllowed{pat}
+			return ErrNameNotAllowed{args: errutil.Args{"reason": "reserved", "pattern": pat}}
 		}
 	}
 
@@ -529,7 +556,7 @@ func isUsableName(names, patterns []string, name string) error {
 }
 
 func IsUsableUsername(name string) error {
-	return isUsableName(reservedUsernames, reservedUserPatterns, name)
+	return isNameAllowed(reservedUsernames, reservedUserPatterns, name)
 }
 
 // CreateUser creates record of a new user.

+ 2 - 5
internal/route/admin/users.go

@@ -101,12 +101,9 @@ func NewUserPost(c *context.Context, f form.AdminCrateUser) {
 		case db.IsErrEmailAlreadyUsed(err):
 			c.Data["Err_Email"] = true
 			c.RenderWithErr(c.Tr("form.email_been_used"), USER_NEW, &f)
-		case db.IsErrNameReserved(err):
+		case db.IsErrNameNotAllowed(err):
 			c.Data["Err_UserName"] = true
-			c.RenderWithErr(c.Tr("user.form.name_reserved", err.(db.ErrNameReserved).Name), USER_NEW, &f)
-		case db.IsErrNamePatternNotAllowed(err):
-			c.Data["Err_UserName"] = true
-			c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), USER_NEW, &f)
+			c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), USER_NEW, &f)
 		default:
 			c.Error(err, "create user")
 		}

+ 1 - 2
internal/route/api/v1/admin/user.go

@@ -55,8 +55,7 @@ func CreateUser(c *context.APIContext, form api.CreateUserOption) {
 	if err := db.CreateUser(u); err != nil {
 		if db.IsErrUserAlreadyExist(err) ||
 			db.IsErrEmailAlreadyUsed(err) ||
-			db.IsErrNameReserved(err) ||
-			db.IsErrNamePatternNotAllowed(err) {
+			db.IsErrNameNotAllowed(err) {
 			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
 			c.Error(err, "create user")

+ 1 - 2
internal/route/api/v1/org/org.go

@@ -31,8 +31,7 @@ func CreateOrgForUser(c *context.APIContext, apiForm api.CreateOrgOption, user *
 	}
 	if err := db.CreateOrganization(org, user); err != nil {
 		if db.IsErrUserAlreadyExist(err) ||
-			db.IsErrNameReserved(err) ||
-			db.IsErrNamePatternNotAllowed(err) {
+			db.IsErrNameNotAllowed(err) {
 			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
 			c.Error(err, "create organization")

+ 1 - 2
internal/route/api/v1/repo/repo.go

@@ -165,8 +165,7 @@ func CreateUserRepo(c *context.APIContext, owner *db.User, opt api.CreateRepoOpt
 	})
 	if err != nil {
 		if db.IsErrRepoAlreadyExist(err) ||
-			db.IsErrNameReserved(err) ||
-			db.IsErrNamePatternNotAllowed(err) {
+			db.IsErrNameNotAllowed(err) {
 			c.ErrorStatus(http.StatusUnprocessableEntity, err)
 		} else {
 			if repo != nil {

+ 2 - 4
internal/route/org/org.go

@@ -40,10 +40,8 @@ func CreatePost(c *context.Context, f form.CreateOrg) {
 		switch {
 		case db.IsErrUserAlreadyExist(err):
 			c.RenderWithErr(c.Tr("form.org_name_been_taken"), CREATE, &f)
-		case db.IsErrNameReserved(err):
-			c.RenderWithErr(c.Tr("org.form.name_reserved", err.(db.ErrNameReserved).Name), CREATE, &f)
-		case db.IsErrNamePatternNotAllowed(err):
-			c.RenderWithErr(c.Tr("org.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), CREATE, &f)
+		case db.IsErrNameNotAllowed(err):
+			c.RenderWithErr(c.Tr("org.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), CREATE, &f)
 		default:
 			c.Error(err, "create organization")
 		}

+ 2 - 4
internal/route/org/setting.go

@@ -51,10 +51,8 @@ func SettingsPost(c *context.Context, f form.UpdateOrgSetting) {
 		} else if err = db.ChangeUserName(org, f.Name); err != nil {
 			c.Data["OrgName"] = true
 			switch {
-			case db.IsErrNameReserved(err):
-				c.RenderWithErr(c.Tr("user.form.name_reserved"), SETTINGS_OPTIONS, &f)
-			case db.IsErrNamePatternNotAllowed(err):
-				c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed"), SETTINGS_OPTIONS, &f)
+			case db.IsErrNameNotAllowed(err):
+				c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), SETTINGS_OPTIONS, &f)
 			default:
 				c.Error(err, "change user name")
 			}

+ 2 - 2
internal/route/org/teams.go

@@ -172,8 +172,8 @@ func NewTeamPost(c *context.Context, f form.CreateTeam) {
 		switch {
 		case db.IsErrTeamAlreadyExist(err):
 			c.RenderWithErr(c.Tr("form.team_name_been_taken"), TEAM_NEW, &f)
-		case db.IsErrNameReserved(err):
-			c.RenderWithErr(c.Tr("org.form.team_name_reserved", err.(db.ErrNameReserved).Name), TEAM_NEW, &f)
+		case db.IsErrNameNotAllowed(err):
+			c.RenderWithErr(c.Tr("org.form.team_name_not_allowed", err.(db.ErrNameNotAllowed).Value()), TEAM_NEW, &f)
 		default:
 			c.Error(err, "new team")
 		}

+ 2 - 4
internal/route/repo/pull.go

@@ -136,10 +136,8 @@ func ForkPost(c *context.Context, f form.CreateRepo) {
 			c.RenderWithErr(c.Tr("repo.form.reach_limit_of_creation", c.User.RepoCreationNum()), FORK, &f)
 		case db.IsErrRepoAlreadyExist(err):
 			c.RenderWithErr(c.Tr("repo.settings.new_owner_has_same_repo"), FORK, &f)
-		case db.IsErrNameReserved(err):
-			c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), FORK, &f)
-		case db.IsErrNamePatternNotAllowed(err):
-			c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), FORK, &f)
+		case db.IsErrNameNotAllowed(err):
+			c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), FORK, &f)
 		default:
 			c.Error(err, "fork repository")
 		}

+ 2 - 5
internal/route/repo/repo.go

@@ -93,12 +93,9 @@ func handleCreateError(c *context.Context, owner *db.User, err error, name, tpl
 	case db.IsErrRepoAlreadyExist(err):
 		c.Data["Err_RepoName"] = true
 		c.RenderWithErr(c.Tr("form.repo_name_been_taken"), tpl, form)
-	case db.IsErrNameReserved(err):
+	case db.IsErrNameNotAllowed(err):
 		c.Data["Err_RepoName"] = true
-		c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), tpl, form)
-	case db.IsErrNamePatternNotAllowed(err):
-		c.Data["Err_RepoName"] = true
-		c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), tpl, form)
+		c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), tpl, form)
 	default:
 		c.Error(err, name)
 	}

+ 4 - 6
internal/route/repo/setting.go

@@ -67,10 +67,8 @@ func SettingsPost(c *context.Context, f form.RepoSetting) {
 				switch {
 				case db.IsErrRepoAlreadyExist(err):
 					c.RenderWithErr(c.Tr("form.repo_name_been_taken"), SETTINGS_OPTIONS, &f)
-				case db.IsErrNameReserved(err):
-					c.RenderWithErr(c.Tr("repo.form.name_reserved", err.(db.ErrNameReserved).Name), SETTINGS_OPTIONS, &f)
-				case db.IsErrNamePatternNotAllowed(err):
-					c.RenderWithErr(c.Tr("repo.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SETTINGS_OPTIONS, &f)
+				case db.IsErrNameNotAllowed(err):
+					c.RenderWithErr(c.Tr("repo.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), SETTINGS_OPTIONS, &f)
 				default:
 					c.Error(err, "change repository name")
 				}
@@ -432,7 +430,7 @@ func DeleteCollaboration(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.remove_collaborator_success"))
 	}
 
-	c.JSONSuccess( map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/settings/collaboration",
 	})
 }
@@ -685,7 +683,7 @@ func DeleteDeployKey(c *context.Context) {
 		c.Flash.Success(c.Tr("repo.settings.deploy_key_deletion_success"))
 	}
 
-	c.JSONSuccess( map[string]interface{}{
+	c.JSONSuccess(map[string]interface{}{
 		"redirect": c.Repo.RepoLink + "/settings/keys",
 	})
 }

+ 2 - 5
internal/route/user/auth.go

@@ -344,12 +344,9 @@ func SignUpPost(c *context.Context, cpt *captcha.Captcha, f form.Register) {
 		case db.IsErrEmailAlreadyUsed(err):
 			c.FormErr("Email")
 			c.RenderWithErr(c.Tr("form.email_been_used"), SIGNUP, &f)
-		case db.IsErrNameReserved(err):
+		case db.IsErrNameNotAllowed(err):
 			c.FormErr("UserName")
-			c.RenderWithErr(c.Tr("user.form.name_reserved", err.(db.ErrNameReserved).Name), SIGNUP, &f)
-		case db.IsErrNamePatternNotAllowed(err):
-			c.FormErr("UserName")
-			c.RenderWithErr(c.Tr("user.form.name_pattern_not_allowed", err.(db.ErrNamePatternNotAllowed).Pattern), SIGNUP, &f)
+			c.RenderWithErr(c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value()), SIGNUP, &f)
 		default:
 			c.Error(err, "create user")
 		}

+ 2 - 4
internal/route/user/setting.go

@@ -76,10 +76,8 @@ func SettingsPost(c *context.Context, f form.UpdateProfile) {
 				switch {
 				case db.IsErrUserAlreadyExist(err):
 					msg = c.Tr("form.username_been_taken")
-				case db.IsErrNameReserved(err):
-					msg = c.Tr("form.name_reserved")
-				case db.IsErrNamePatternNotAllowed(err):
-					msg = c.Tr("form.name_pattern_not_allowed")
+				case db.IsErrNameNotAllowed(err):
+					msg = c.Tr("user.form.name_not_allowed", err.(db.ErrNameNotAllowed).Value())
 				default:
 					c.Error(err, "change user name")
 					return

Some files were not shown because too many files changed in this diff