#1511 Allow local import only for admin users
This commit is contained in:
		
							parent
							
								
									25ec20d525
								
							
						
					
					
						commit
						6f0a41b8b2
					
				
					 18 changed files with 152 additions and 79 deletions
				
			
		|  | @ -5,7 +5,7 @@ Gogs - Go Git Service [ |  | ||||||
| 
 | 
 | ||||||
| ##### Current version: 0.6.23 Beta | ##### Current version: 0.6.24 Beta | ||||||
| 
 | 
 | ||||||
| <table> | <table> | ||||||
|     <tr> |     <tr> | ||||||
|  |  | ||||||
|  | @ -360,6 +360,7 @@ migrate_type_helper=Diese Repository wird ein <span class="text blue">Spiegel</s | ||||||
| migrate_repo=Repository migrieren | migrate_repo=Repository migrieren | ||||||
| migrate.clone_address=Adresse kopieren | migrate.clone_address=Adresse kopieren | ||||||
| migrate.clone_address_desc=Dies kann eine HTTP/HTTPS/GIT URL oder ein lokaler Serverpfad sein. | migrate.clone_address_desc=Dies kann eine HTTP/HTTPS/GIT URL oder ein lokaler Serverpfad sein. | ||||||
|  | migrate.permission_denied=You are not allowed to import local repositories. | ||||||
| migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner. | migrate.invalid_local_path=Lokaler Pfad ist ungültig, er existiert nicht oder ist kein Ordner. | ||||||
| 
 | 
 | ||||||
| forked_from=Geforkt von | forked_from=Geforkt von | ||||||
|  | @ -651,7 +652,7 @@ release.tag_name_already_exist=Ein Release mit diesem Tag existiert bereits. | ||||||
| 
 | 
 | ||||||
| [org] | [org] | ||||||
| org_name_holder=Name der Organisation | org_name_holder=Name der Organisation | ||||||
| org_full_name_holder=Organization Full Name | org_full_name_holder=Vollständiger Name der Organisation | ||||||
| org_name_helper=Gute Namen von Organisationen sind kurz und einprägsam. | org_name_helper=Gute Namen von Organisationen sind kurz und einprägsam. | ||||||
| create_org=Organisation erstellen | create_org=Organisation erstellen | ||||||
| repo_updated=Aktualisiert | repo_updated=Aktualisiert | ||||||
|  | @ -808,6 +809,7 @@ users.edit_account=Konto bearbeiten | ||||||
| users.is_activated=Dieses Konto ist aktiviert | users.is_activated=Dieses Konto ist aktiviert | ||||||
| users.is_admin=Dieses Konto hat Administratorrechte | users.is_admin=Dieses Konto hat Administratorrechte | ||||||
| users.allow_git_hook=Dieses Konto ist berechtigt, Git-Hooks zu erstellen | users.allow_git_hook=Dieses Konto ist berechtigt, Git-Hooks zu erstellen | ||||||
|  | users.allow_import_local=This account has permissions to import local repositories | ||||||
| users.update_profile=Kontoprofil aktualisieren | users.update_profile=Kontoprofil aktualisieren | ||||||
| users.delete_account=Dieses Konto löschen | users.delete_account=Dieses Konto löschen | ||||||
| users.still_own_repo=Dieses Konto besitzt noch Repositories. Diese müssen zuerst gelöscht oder übertragen werden. | users.still_own_repo=Dieses Konto besitzt noch Repositories. Diese müssen zuerst gelöscht oder übertragen werden. | ||||||
|  |  | ||||||
|  | @ -360,6 +360,7 @@ migrate_type_helper = This repository will be a <span class="text blue">mirror</ | ||||||
| migrate_repo = Migrate Repository | migrate_repo = Migrate Repository | ||||||
| migrate.clone_address = Clone Address | migrate.clone_address = Clone Address | ||||||
| migrate.clone_address_desc = This can be a HTTP/HTTPS/GIT URL or local server path. | migrate.clone_address_desc = This can be a HTTP/HTTPS/GIT URL or local server path. | ||||||
|  | migrate.permission_denied = You are not allowed to import local repositories. | ||||||
| migrate.invalid_local_path = Invalid local path, it does not exist or not a directory. | migrate.invalid_local_path = Invalid local path, it does not exist or not a directory. | ||||||
| 
 | 
 | ||||||
| forked_from = forked from | forked_from = forked from | ||||||
|  | @ -808,6 +809,7 @@ users.edit_account = Edit Account | ||||||
| users.is_activated = This account is activated | users.is_activated = This account is activated | ||||||
| users.is_admin = This account has administrator permissions | users.is_admin = This account has administrator permissions | ||||||
| users.allow_git_hook = This account has permissions to create Git hooks | 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.update_profile = Update Account Profile | users.update_profile = Update Account Profile | ||||||
| users.delete_account = Delete This Account | 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. | users.still_own_repo = This account still has ownership over at least one repository, you have to delete or transfer them first. | ||||||
|  |  | ||||||
|  | @ -360,6 +360,7 @@ migrate_type_helper=该仓库将是一个 <span class="text blue">镜像</span> | ||||||
| migrate_repo=迁移仓库 | migrate_repo=迁移仓库 | ||||||
| migrate.clone_address=克隆地址 | migrate.clone_address=克隆地址 | ||||||
| migrate.clone_address_desc=该地址可以是 HTTP/HTTPS/GIT URL 或本地服务器路径。 | migrate.clone_address_desc=该地址可以是 HTTP/HTTPS/GIT URL 或本地服务器路径。 | ||||||
|  | migrate.permission_denied=您没有获得导入本地仓库的权限。 | ||||||
| migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录! | migrate.invalid_local_path=无效的本地路径,不存在或不是一个目录! | ||||||
| 
 | 
 | ||||||
| forked_from=派生自 | forked_from=派生自 | ||||||
|  | @ -807,7 +808,8 @@ users.update_profile_success=该用户信息更新成功! | ||||||
| users.edit_account=编辑用户信息 | users.edit_account=编辑用户信息 | ||||||
| users.is_activated=该用户已被激活 | users.is_activated=该用户已被激活 | ||||||
| users.is_admin=该用户具有管理员权限 | users.is_admin=该用户具有管理员权限 | ||||||
| users.allow_git_hook=该帐户具有创建 Git 钩子的权限 | users.allow_git_hook=该用户具有创建 Git 钩子的权限 | ||||||
|  | users.allow_import_local=该用户具有导入本地仓库的权限 | ||||||
| users.update_profile=更新用户信息 | users.update_profile=更新用户信息 | ||||||
| users.delete_account=删除该用户 | users.delete_account=删除该用户 | ||||||
| users.still_own_repo=该帐户仍然是某些仓库的拥有者,您必须先转移或删除它们才能执行删除帐户操作! | users.still_own_repo=该帐户仍然是某些仓库的拥有者,您必须先转移或删除它们才能执行删除帐户操作! | ||||||
|  |  | ||||||
|  | @ -360,6 +360,7 @@ migrate_type_helper=該倉庫將是一個 <span class="text blue">鏡像</span> | ||||||
| migrate_repo=遷移倉庫 | migrate_repo=遷移倉庫 | ||||||
| migrate.clone_address=複製地址 | migrate.clone_address=複製地址 | ||||||
| migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。 | migrate.clone_address_desc=該地址可以是 HTTP/HTTPS/GIT URL 或本地服務器路徑。 | ||||||
|  | migrate.permission_denied=You are not allowed to import local repositories. | ||||||
| migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄! | migrate.invalid_local_path=無效的本地路徑,該路徑不存在或不是一個目錄! | ||||||
| 
 | 
 | ||||||
| forked_from=派生自 | forked_from=派生自 | ||||||
|  | @ -808,6 +809,7 @@ users.edit_account=編輯用戶信息 | ||||||
| users.is_activated=該用戶已被激活 | users.is_activated=該用戶已被激活 | ||||||
| users.is_admin=該用戶具有管理員權限 | users.is_admin=該用戶具有管理員權限 | ||||||
| users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限 | users.allow_git_hook=該帳戶具有創建 Git 鉤子的權限 | ||||||
|  | users.allow_import_local=This account has permissions to import local repositories | ||||||
| users.update_profile=更新用戶信息 | users.update_profile=更新用戶信息 | ||||||
| users.delete_account=刪除該用戶 | users.delete_account=刪除該用戶 | ||||||
| users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作! | users.still_own_repo=該帳戶仍然是某些倉庫的擁有者,您必須先轉移或刪除它們才能執行刪除帳戶操作! | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							|  | @ -17,7 +17,7 @@ import ( | ||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const APP_VER = "0.6.23.1103 Beta" | const APP_VER = "0.6.24.1103 Beta" | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ func IsErrNameReserved(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrNameReserved) Error() string { | func (err ErrNameReserved) Error() string { | ||||||
| 	return fmt.Sprintf("name is reserved: [name: %s]", err.Name) | 	return fmt.Sprintf("name is reserved [name: %s]", err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrNamePatternNotAllowed struct { | type ErrNamePatternNotAllowed struct { | ||||||
|  | @ -31,7 +31,7 @@ func IsErrNamePatternNotAllowed(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrNamePatternNotAllowed) Error() string { | func (err ErrNamePatternNotAllowed) Error() string { | ||||||
| 	return fmt.Sprintf("name pattern is not allowed: [pattern: %s]", err.Pattern) | 	return fmt.Sprintf("name pattern is not allowed [pattern: %s]", err.Pattern) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //  ____ ___
 | //  ____ ___
 | ||||||
|  | @ -51,7 +51,7 @@ func IsErrUserAlreadyExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrUserAlreadyExist) Error() string { | func (err ErrUserAlreadyExist) Error() string { | ||||||
| 	return fmt.Sprintf("user already exists: [name: %s]", err.Name) | 	return fmt.Sprintf("user already exists [name: %s]", err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrUserNotExist struct { | type ErrUserNotExist struct { | ||||||
|  | @ -65,7 +65,7 @@ func IsErrUserNotExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrUserNotExist) Error() string { | func (err ErrUserNotExist) Error() string { | ||||||
| 	return fmt.Sprintf("user does not exist: [uid: %d, name: %s]", err.UID, err.Name) | 	return fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrEmailAlreadyUsed struct { | type ErrEmailAlreadyUsed struct { | ||||||
|  | @ -78,7 +78,7 @@ func IsErrEmailAlreadyUsed(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrEmailAlreadyUsed) Error() string { | func (err ErrEmailAlreadyUsed) Error() string { | ||||||
| 	return fmt.Sprintf("e-mail has been used: [email: %s]", err.Email) | 	return fmt.Sprintf("e-mail has been used [email: %s]", err.Email) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrUserOwnRepos struct { | type ErrUserOwnRepos struct { | ||||||
|  | @ -91,7 +91,7 @@ func IsErrUserOwnRepos(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrUserOwnRepos) Error() string { | func (err ErrUserOwnRepos) Error() string { | ||||||
| 	return fmt.Sprintf("user still has ownership of repositories: [uid: %d]", err.UID) | 	return fmt.Sprintf("user still has ownership of repositories [uid: %d]", err.UID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrUserHasOrgs struct { | type ErrUserHasOrgs struct { | ||||||
|  | @ -104,7 +104,7 @@ func IsErrUserHasOrgs(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrUserHasOrgs) Error() string { | func (err ErrUserHasOrgs) Error() string { | ||||||
| 	return fmt.Sprintf("user still has membership of organizations: [uid: %d]", err.UID) | 	return fmt.Sprintf("user still has membership of organizations [uid: %d]", err.UID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // __________     ___.   .__  .__          ____  __.
 | // __________     ___.   .__  .__          ____  __.
 | ||||||
|  | @ -124,7 +124,7 @@ func IsErrKeyNotExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrKeyNotExist) Error() string { | func (err ErrKeyNotExist) Error() string { | ||||||
| 	return fmt.Sprintf("public key does not exist: [id: %d]", err.ID) | 	return fmt.Sprintf("public key does not exist [id: %d]", err.ID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrKeyAlreadyExist struct { | type ErrKeyAlreadyExist struct { | ||||||
|  | @ -138,7 +138,7 @@ func IsErrKeyAlreadyExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrKeyAlreadyExist) Error() string { | func (err ErrKeyAlreadyExist) Error() string { | ||||||
| 	return fmt.Sprintf("public key already exists: [owner_id: %d, content: %s]", err.OwnerID, err.Content) | 	return fmt.Sprintf("public key already exists [owner_id: %d, content: %s]", err.OwnerID, err.Content) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrKeyNameAlreadyUsed struct { | type ErrKeyNameAlreadyUsed struct { | ||||||
|  | @ -152,7 +152,7 @@ func IsErrKeyNameAlreadyUsed(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrKeyNameAlreadyUsed) Error() string { | func (err ErrKeyNameAlreadyUsed) Error() string { | ||||||
| 	return fmt.Sprintf("public key already exists: [owner_id: %d, name: %s]", err.OwnerID, err.Name) | 	return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrDeployKeyAlreadyExist struct { | type ErrDeployKeyAlreadyExist struct { | ||||||
|  | @ -166,7 +166,7 @@ func IsErrDeployKeyAlreadyExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrDeployKeyAlreadyExist) Error() string { | func (err ErrDeployKeyAlreadyExist) Error() string { | ||||||
| 	return fmt.Sprintf("public key already exists: [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID) | 	return fmt.Sprintf("public key already exists [key_id: %d, repo_id: %d]", err.KeyID, err.RepoID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ErrDeployKeyNameAlreadyUsed struct { | type ErrDeployKeyNameAlreadyUsed struct { | ||||||
|  | @ -180,7 +180,7 @@ func IsErrDeployKeyNameAlreadyUsed(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrDeployKeyNameAlreadyUsed) Error() string { | func (err ErrDeployKeyNameAlreadyUsed) Error() string { | ||||||
| 	return fmt.Sprintf("public key already exists: [repo_id: %d, name: %s]", err.RepoID, err.Name) | 	return fmt.Sprintf("public key already exists [repo_id: %d, name: %s]", err.RepoID, err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //    _____                                   ___________     __
 | //    _____                                   ___________     __
 | ||||||
|  | @ -200,7 +200,7 @@ func IsErrAccessTokenNotExist(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrAccessTokenNotExist) Error() string { | func (err ErrAccessTokenNotExist) Error() string { | ||||||
| 	return fmt.Sprintf("access token does not exist: [sha: %s]", err.SHA) | 	return fmt.Sprintf("access token does not exist [sha: %s]", err.SHA) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ________                            .__                __  .__
 | // ________                            .__                __  .__
 | ||||||
|  | @ -220,7 +220,7 @@ func IsErrLastOrgOwner(err error) bool { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (err ErrLastOrgOwner) Error() string { | func (err ErrLastOrgOwner) Error() string { | ||||||
| 	return fmt.Sprintf("user is the last member of owner team: [uid: %d]", err.UID) | 	return fmt.Sprintf("user is the last member of owner team [uid: %d]", err.UID) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // __________                           .__  __
 | // __________                           .__  __
 | ||||||
|  | @ -259,6 +259,22 @@ func (err ErrRepoAlreadyExist) Error() string { | ||||||
| 	return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name) | 	return fmt.Sprintf("repository already exists [uname: %s, name: %s]", err.Uname, err.Name) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type ErrInvalidCloneAddr struct { | ||||||
|  | 	IsURLError         bool | ||||||
|  | 	IsInvalidPath      bool | ||||||
|  | 	IsPermissionDenied bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func IsErrInvalidCloneAddr(err error) bool { | ||||||
|  | 	_, ok := err.(ErrInvalidCloneAddr) | ||||||
|  | 	return ok | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (err ErrInvalidCloneAddr) Error() string { | ||||||
|  | 	return fmt.Sprintf("invalid clone address [is_url_error: %v, is_invalid_path: %v, is_permission_denied: %v]", | ||||||
|  | 		err.IsURLError, err.IsInvalidPath, err.IsPermissionDenied) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| //  __      __      ___.   .__                   __
 | //  __      __      ___.   .__                   __
 | ||||||
| // /  \    /  \ ____\_ |__ |  |__   ____   ____ |  | __
 | // /  \    /  \ ____\_ |__ |  |__   ____   ____ |  | __
 | ||||||
| // \   \/\/   // __ \| __ \|  |  \ /  _ \ /  _ \|  |/ /
 | // \   \/\/   // __ \| __ \|  |  \ /  _ \ /  _ \|  |/ /
 | ||||||
|  |  | ||||||
|  | @ -75,9 +75,10 @@ type User struct { | ||||||
| 	LastRepoVisibility bool | 	LastRepoVisibility bool | ||||||
| 
 | 
 | ||||||
| 	// Permissions.
 | 	// Permissions.
 | ||||||
| 	IsActive     bool | 	IsActive         bool | ||||||
| 	IsAdmin      bool | 	IsAdmin          bool | ||||||
| 	AllowGitHook bool | 	AllowGitHook     bool | ||||||
|  | 	AllowImportLocal bool // Allow migrate repository by local path
 | ||||||
| 
 | 
 | ||||||
| 	// Avatar.
 | 	// Avatar.
 | ||||||
| 	Avatar          string `xorm:"VARCHAR(2048) NOT NULL"` | 	Avatar          string `xorm:"VARCHAR(2048) NOT NULL"` | ||||||
|  | @ -107,6 +108,16 @@ func (u *User) AfterSet(colName string, _ xorm.Cell) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // CanEditGitHook returns true if user can edit Git hooks.
 | ||||||
|  | func (u *User) CanEditGitHook() bool { | ||||||
|  | 	return u.IsAdmin || u.AllowGitHook | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // CanImportLocal returns true if user can migrate repository by local path.
 | ||||||
|  | func (u *User) CanImportLocal() bool { | ||||||
|  | 	return u.IsAdmin || u.AllowImportLocal | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // EmailAdresses is the list of all email addresses of a user. Can contain the
 | // EmailAdresses is the list of all email addresses of a user. Can contain the
 | ||||||
| // primary email address, but is not obligatory
 | // primary email address, but is not obligatory
 | ||||||
| type EmailAddress struct { | type EmailAddress struct { | ||||||
|  |  | ||||||
|  | @ -24,16 +24,17 @@ func (f *AdminCrateUserForm) Validate(ctx *macaron.Context, errs binding.Errors) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type AdminEditUserForm struct { | type AdminEditUserForm struct { | ||||||
| 	LoginType    string `binding:"Required"` | 	LoginType        string `binding:"Required"` | ||||||
| 	LoginName    string | 	LoginName        string | ||||||
| 	FullName     string `binding:"MaxSize(100)"` | 	FullName         string `binding:"MaxSize(100)"` | ||||||
| 	Email        string `binding:"Required;Email;MaxSize(254)"` | 	Email            string `binding:"Required;Email;MaxSize(254)"` | ||||||
| 	Password     string `binding:"MaxSize(255)"` | 	Password         string `binding:"MaxSize(255)"` | ||||||
| 	Website      string `binding:"MaxSize(50)"` | 	Website          string `binding:"MaxSize(50)"` | ||||||
| 	Location     string `binding:"MaxSize(50)"` | 	Location         string `binding:"MaxSize(50)"` | ||||||
| 	Active       bool | 	Active           bool | ||||||
| 	Admin        bool | 	Admin            bool | ||||||
| 	AllowGitHook bool | 	AllowGitHook     bool | ||||||
|  | 	AllowImportLocal bool | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | func (f *AdminEditUserForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | ||||||
|  |  | ||||||
|  | @ -5,8 +5,14 @@ | ||||||
| package auth | package auth | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"net/url" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"github.com/Unknwon/com" | ||||||
| 	"github.com/go-macaron/binding" | 	"github.com/go-macaron/binding" | ||||||
| 	"gopkg.in/macaron.v1" | 	"gopkg.in/macaron.v1" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gogits/gogs/models" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // _______________________________________    _________.______________________ _______________.___.
 | // _______________________________________    _________.______________________ _______________.___.
 | ||||||
|  | @ -46,6 +52,34 @@ func (f *MigrateRepoForm) Validate(ctx *macaron.Context, errs binding.Errors) bi | ||||||
| 	return validate(errs, ctx.Data, f, ctx.Locale) | 	return validate(errs, ctx.Data, f, ctx.Locale) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // ParseRemoteAddr checks if given remote address is valid,
 | ||||||
|  | // and returns composed URL with needed username and passowrd.
 | ||||||
|  | // It also checks if given user has permission when remote address
 | ||||||
|  | // is actually a local path.
 | ||||||
|  | func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) { | ||||||
|  | 	remoteAddr := f.CloneAddr | ||||||
|  | 
 | ||||||
|  | 	// Remote address can be HTTP/HTTPS/Git URL or local path.
 | ||||||
|  | 	if strings.HasPrefix(remoteAddr, "http://") || | ||||||
|  | 		strings.HasPrefix(remoteAddr, "https://") || | ||||||
|  | 		strings.HasPrefix(remoteAddr, "git://") { | ||||||
|  | 		u, err := url.Parse(remoteAddr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return "", models.ErrInvalidCloneAddr{IsURLError: true} | ||||||
|  | 		} | ||||||
|  | 		if len(f.AuthUsername)+len(f.AuthPassword) > 0 { | ||||||
|  | 			u.User = url.UserPassword(f.AuthUsername, f.AuthPassword) | ||||||
|  | 		} | ||||||
|  | 		remoteAddr = u.String() | ||||||
|  | 	} else if !user.CanImportLocal() { | ||||||
|  | 		return "", models.ErrInvalidCloneAddr{IsPermissionDenied: true} | ||||||
|  | 	} else if !com.IsDir(remoteAddr) { | ||||||
|  | 		return "", models.ErrInvalidCloneAddr{IsInvalidPath: true} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return remoteAddr, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| type RepoSettingForm struct { | type RepoSettingForm struct { | ||||||
| 	RepoName    string `binding:"Required;AlphaDashDot;MaxSize(100)"` | 	RepoName    string `binding:"Required;AlphaDashDot;MaxSize(100)"` | ||||||
| 	Description string `binding:"MaxSize(255)"` | 	Description string `binding:"MaxSize(255)"` | ||||||
|  |  | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -420,7 +420,7 @@ func RequireRepoAdmin() macaron.Handler { | ||||||
| // GitHookService checks if repository Git hooks service has been enabled.
 | // GitHookService checks if repository Git hooks service has been enabled.
 | ||||||
| func GitHookService() macaron.Handler { | func GitHookService() macaron.Handler { | ||||||
| 	return func(ctx *Context) { | 	return func(ctx *Context) { | ||||||
| 		if !ctx.User.AllowGitHook && !ctx.User.IsAdmin { | 		if !ctx.User.CanEditGitHook() { | ||||||
| 			ctx.Handle(404, "GitHookService", nil) | 			ctx.Handle(404, "GitHookService", nil) | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -213,6 +213,7 @@ func EditUserPost(ctx *middleware.Context, form auth.AdminEditUserForm) { | ||||||
| 	u.IsActive = form.Active | 	u.IsActive = form.Active | ||||||
| 	u.IsAdmin = form.Admin | 	u.IsAdmin = form.Admin | ||||||
| 	u.AllowGitHook = form.AllowGitHook | 	u.AllowGitHook = form.AllowGitHook | ||||||
|  | 	u.AllowImportLocal = form.AllowImportLocal | ||||||
| 
 | 
 | ||||||
| 	if err := models.UpdateUser(u); err != nil { | 	if err := models.UpdateUser(u); err != nil { | ||||||
| 		if models.IsErrEmailAlreadyUsed(err) { | 		if models.IsErrEmailAlreadyUsed(err) { | ||||||
|  |  | ||||||
|  | @ -5,9 +5,7 @@ | ||||||
| package v1 | package v1 | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"net/url" |  | ||||||
| 	"path" | 	"path" | ||||||
| 	"strings" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/Unknwon/com" | 	"github.com/Unknwon/com" | ||||||
| 
 | 
 | ||||||
|  | @ -218,22 +216,23 @@ func MigrateRepo(ctx *middleware.Context, form auth.MigrateRepoForm) { | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Remote address can be HTTP/HTTPS/Git URL or local path.
 | 	remoteAddr, err := form.ParseRemoteAddr(ctx.User) | ||||||
| 	remoteAddr := form.CloneAddr | 	if err != nil { | ||||||
| 	if strings.HasPrefix(form.CloneAddr, "http://") || | 		if models.IsErrInvalidCloneAddr(err) { | ||||||
| 		strings.HasPrefix(form.CloneAddr, "https://") || | 			addrErr := err.(models.ErrInvalidCloneAddr) | ||||||
| 		strings.HasPrefix(form.CloneAddr, "git://") { | 			switch { | ||||||
| 		u, err := url.Parse(form.CloneAddr) | 			case addrErr.IsURLError: | ||||||
| 		if err != nil { | 				ctx.APIError(422, "", err) | ||||||
| 			ctx.APIError(422, "", err) | 			case addrErr.IsPermissionDenied: | ||||||
| 			return | 				ctx.APIError(422, "", "You are not allowed to import local repositories.") | ||||||
|  | 			case addrErr.IsInvalidPath: | ||||||
|  | 				ctx.APIError(422, "", "Invalid local path, it does not exist or not a directory.") | ||||||
|  | 			default: | ||||||
|  | 				ctx.APIError(500, "ParseRemoteAddr", "Unknown error type (ErrInvalidCloneAddr): "+err.Error()) | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			ctx.APIError(500, "ParseRemoteAddr", err) | ||||||
| 		} | 		} | ||||||
| 		if len(form.AuthUsername) > 0 || len(form.AuthPassword) > 0 { |  | ||||||
| 			u.User = url.UserPassword(form.AuthUsername, form.AuthPassword) |  | ||||||
| 		} |  | ||||||
| 		remoteAddr = u.String() |  | ||||||
| 	} else if !com.IsDir(remoteAddr) { |  | ||||||
| 		ctx.APIError(422, "", "Invalid local path, it does not exist or not a directory.") |  | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ package repo | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"path" | 	"path" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | @ -164,26 +163,24 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Remote address can be HTTP/HTTPS/Git URL or local path.
 | 	remoteAddr, err := form.ParseRemoteAddr(ctx.User) | ||||||
| 	// Note: remember to change api/v1/repo.go: MigrateRepo
 | 	if err != nil { | ||||||
| 	// FIXME: merge these two functions with better error handling
 | 		if models.IsErrInvalidCloneAddr(err) { | ||||||
| 	remoteAddr := form.CloneAddr |  | ||||||
| 	if strings.HasPrefix(form.CloneAddr, "http://") || |  | ||||||
| 		strings.HasPrefix(form.CloneAddr, "https://") || |  | ||||||
| 		strings.HasPrefix(form.CloneAddr, "git://") { |  | ||||||
| 		u, err := url.Parse(form.CloneAddr) |  | ||||||
| 		if err != nil { |  | ||||||
| 			ctx.Data["Err_CloneAddr"] = true | 			ctx.Data["Err_CloneAddr"] = true | ||||||
| 			ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form) | 			addrErr := err.(models.ErrInvalidCloneAddr) | ||||||
| 			return | 			switch { | ||||||
|  | 			case addrErr.IsURLError: | ||||||
|  | 				ctx.RenderWithErr(ctx.Tr("form.url_error"), MIGRATE, &form) | ||||||
|  | 			case addrErr.IsPermissionDenied: | ||||||
|  | 				ctx.RenderWithErr(ctx.Tr("repo.migrate.permission_denied"), MIGRATE, &form) | ||||||
|  | 			case addrErr.IsInvalidPath: | ||||||
|  | 				ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &form) | ||||||
|  | 			default: | ||||||
|  | 				ctx.Handle(500, "Unknown error", err) | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			ctx.Handle(500, "ParseRemoteAddr", err) | ||||||
| 		} | 		} | ||||||
| 		if len(form.AuthUsername) > 0 || len(form.AuthPassword) > 0 { |  | ||||||
| 			u.User = url.UserPassword(form.AuthUsername, form.AuthPassword) |  | ||||||
| 		} |  | ||||||
| 		remoteAddr = u.String() |  | ||||||
| 	} else if !com.IsDir(remoteAddr) { |  | ||||||
| 		ctx.Data["Err_CloneAddr"] = true |  | ||||||
| 		ctx.RenderWithErr(ctx.Tr("repo.migrate.invalid_local_path"), MIGRATE, &form) |  | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| 0.6.23.1103 Beta | 0.6.24.1103 Beta | ||||||
|  | @ -72,7 +72,13 @@ | ||||||
|             <div class="inline field"> |             <div class="inline field"> | ||||||
|               <div class="ui checkbox"> |               <div class="ui checkbox"> | ||||||
|                 <label><strong>{{.i18n.Tr "admin.users.allow_git_hook"}}</strong></label> |                 <label><strong>{{.i18n.Tr "admin.users.allow_git_hook"}}</strong></label> | ||||||
|                 <input name="allow_git_hook" type="checkbox" {{if or .User.IsAdmin .User.AllowGitHook}}checked{{end}}> |                 <input name="allow_git_hook" type="checkbox" {{if .User.CanEditGitHook}}checked{{end}}> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |             <div class="inline field"> | ||||||
|  |               <div class="ui checkbox"> | ||||||
|  |                 <label><strong>{{.i18n.Tr "admin.users.allow_import_local"}}</strong></label> | ||||||
|  |                 <input name="allow_import_local" type="checkbox" {{if .User.CanImportLocal}}checked{{end}}> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| 	  <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks"> | 	  <a class="{{if .PageIsSettingsHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks"> | ||||||
| 	    {{.i18n.Tr "repo.settings.hooks"}} | 	    {{.i18n.Tr "repo.settings.hooks"}} | ||||||
| 	  </a> | 	  </a> | ||||||
| 	  {{if or .SignedUser.AllowGitHook .SignedUser.IsAdmin}} | 	  {{if .SignedUser.CanEditGitHook}} | ||||||
| 	  <a class="{{if .PageIsSettingsGitHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks/git"> | 	  <a class="{{if .PageIsSettingsGitHooks}}active{{end}} item" href="{{.RepoLink}}/settings/hooks/git"> | ||||||
| 	    {{.i18n.Tr "repo.settings.githooks"}} | 	    {{.i18n.Tr "repo.settings.githooks"}} | ||||||
| 	  </a> | 	  </a> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue