mirror of https://github.com/gogs/gogs.git
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 testspull/6119/head
parent
e131a45646
commit
fa497b1633
|
@ -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
|
||||
|
|
2
go.mod
2
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
go.sum
2
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 one or more lines are too long
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue